diff --git a/docs/architecture.md b/docs/architecture.md index a0f1544f0..8ac7701b1 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -7,7 +7,7 @@ OneKey Hardware SDK 采用三层架构设计: ``` 应用层 (DApps) ↓ -SDK接口层 (@onekeyfe/core) +SDK接口层 (@onekeyfe/hd-core) ↓ 传输抽象层 (@onekeyfe/hd-transport) ↓ @@ -23,7 +23,7 @@ SDK接口层 (@onekeyfe/core) - **`@onekeyfe/hd-transport`** - 传输层抽象 ### 传输层 -- **`@onekeyfe/hd-transport-webusb`** - WebUSB传输(浏览器) +- **`@onekeyfe/hd-transport-web-device`** - WebUSB传输(浏览器) - **`@onekeyfe/hd-transport-usb`** - Node.js USB传输(CLI/服务端,基于 libusb) - **`@onekeyfe/hd-transport-http`** - HTTP Bridge传输 - **`@onekeyfe/hd-transport-lowlevel`** - 低层传输(BLE 插件模式) @@ -106,12 +106,89 @@ switch(env) { │ └── @onekeyfe/hd-transport │ └── 传输层实现 - ├── @onekeyfe/hd-transport-webusb (浏览器) + ├── @onekeyfe/hd-transport-web-device (浏览器) ├── @onekeyfe/hd-transport-usb (Node.js CLI) ├── @onekeyfe/hd-transport-lowlevel (BLE 插件) └── @onekeyfe/hd-transport-http (Bridge) ``` +## ⚡ 预初始化(preInitialize)快路径 + +`@onekeyfe/hd-core` 暴露了一个单独的预热入口,用来提前完成一次 `acquire + Initialize`,让后续符合条件的签名调用跳过重复初始化。 + +### 公开接口 + +```typescript +await HardwareSDK.preInitialize(connectId, { + passphraseState, + initSession: false, +}); +``` + +- `preInitialize(connectId, params?)` 的公开类型定义位于 `packages/core/src/types/api/preInitialize.ts` +- 公开返回类型是 `Response`;成功响应里的 `payload` 为 `true` 表示预热成功,`payload` 为 `false` 表示预热内部失败后已清理预热标记 +- 预热结束后 SDK 会主动 `release()` 当前设备连接;它缓存的是后续跳过 `Initialize` 所需的设备状态,而不是长期占用会话 +- 重复的 `preInitialize` 会按 `connectId + passphraseState + method name` 去重;同一 key 在 60 秒窗口内不会重复做预热 + +### 什么时候会命中快路径 + +后续业务调用只有在以下条件同时满足时,才会真正跳过 `Initialize`: + +- 方法本身显式允许:`BaseMethod.allowUsePreInitialize === true` +- 本次调用显式传入 `usePreInitialize: true` +- 调用里带有稳定的 `connectId` +- 当前 `passphraseState` 与预热时记录的元数据一致 +- 设备已有 `features` +- 预热记录仍在 60 秒 TTL 内 + +命中时,核心层会输出: + +```text +[PRE-INIT][HIT] method= skip Initialize (...) +``` + +未命中时,核心层会输出: + +```text +[PRE-INIT][MISS] method= method.disallow,... +``` + +常见 miss 原因和源码字段一一对应: + +| 日志原因 | 含义 | +| --- | --- | +| `method.disallow` | 当前方法没有开启 `allowUsePreInitialize` | +| `payload.usePreInitialize=false` | 调用参数里没有打开 `usePreInitialize` | +| `connectId.missing` | 没有固定目标设备,SDK 不会跳过初始化 | +| `meta.mismatch` | `passphraseState` 与预热时记录的不一致 | +| `features.missing` | 设备还没有可复用的 `features` | +| `ttl.expired` | 预热窗口已超过 60 秒 | + +### 当前 Cardano 边界 + +最近的 Cardano 调整明确关闭了签名类方法的预初始化快路径: + +- `cardanoSignTransaction` +- `cardanoSignMessage` + +这两个方法在源码里都将 `allowUsePreInitialize` 设为 `false`,因此即使宿主继续传入 `usePreInitialize: true`,日志也会以 `method.disallow` 记为 miss,并执行完整的 `Initialize` 流程。集成方不应把 `preInitialize` 当作 Cardano 签名延迟优化手段。 + +### 使用示例 + +```typescript +await HardwareSDK.preInitialize(connectId, { + passphraseState, +}); + +await HardwareSDK.solSignTransaction(connectId, deviceId, { + ...params, + passphraseState, + usePreInitialize: true, +}); +``` + +如果第二次调用复用了相同的 `connectId` 和 `passphraseState`,并且落在 60 秒窗口内,`solSignTransaction` 这类已开启 `allowUsePreInitialize` 的签名方法才会真正复用这次预热。 + ## 🔧 开发工具 - **Lerna** - Monorepo管理