跳到主要内容

1.17.x 升级与迁移指南

概览

概览

在即将发布的 Blocklet Server v1.17.x 版本中,我们对 Blocklet Server 的一系列安全场景进行了优化,但同时也带来了一些 Breaking Change:

  • 删除了 Blocklet 的部分环境变量(BLOCKLET_APP_SKBLOCKLET_APP_PSK )。
  • @blocklet/sdk 的 getWallet() 返回对象删除wallet.secretKey / wallet.sk 属性;
  • @blocklet/sdk 和 @ocap/wallet 的签名/验证函数多数从同步改为异步
  • 多个包的导出方式从 CommonJS 默认导出变为 ES Module 的命名导出
  • 以下场景的签名/验证私钥由原来的 BLOCKLET_APP_SK 变更为 BLOCKLET_APP_ASK:跨 Component 调用 / 调用 Service API / Server API / Notification 或 WebSocket
  • 增加了部分环境变量:
    • BLOCKLET_APP_ASK: 新环境变量,用来以下场景签名:跨 Component 调用 / 调用 Service API / Server API / Notification 或 WebSocket
    • BLOCKLET_APP_PPK:为原来 BLOCKLET_APP_PSK 的公钥

本指南把这些改动拆解成明确的迁移步骤、替换示例、以及回归检查项,方便逐步修改与人工复核。

在修改之前,请确保所有相关依赖已升级至最新版本(版本为 1.17.1

此文档可复制给 AI,由 AI 进行迁移和修改。

主要 Breaking Changes 列表

1. 环境变量变动

变更:BLOCKLET_APP_SK、BLOCKLET_APP_PSK 已删除。任何依赖这些私钥的代码必须改为通过 @blocklet/sdk 的 wallet 接口签名或导出公钥用于校验。

迁移要点

  • 如果代码直接使用私钥进行签名 -> 改为 getWallet() 获取 wallet 并使用其异步签名方法(参见示例)。
  • 如果用私钥派生子钱包 -> 使用 await getWallet().deriveWallet()
  • 如果只用于 verify -> 使用公钥 getWallet().publicKey 或 process.env.BLOCKLET_APP_PK 来替换。

SK 签名

旧代码:

javascript
const wallet = fromSecretKey(process.env.BLOCKLET_APP_SK);
const signature = wallet.sign();

新代码:

javascript
const { getWallet } = require('@blocklet/sdk/lib/wallet');
const wallet = await getWallet();
const signature = await wallet.sign();

JWT 签名

旧:

javascript
const jwtToken = jwt.sign(payload, process.env.BLOCKLET_APP_SK);

新:

javascript
const { getWallet } = require('@blocklet/sdk/lib/wallet');
const wallet = await getWallet();
const jwtToken = await wallet.signJWT(payload);

SK 验证:

 旧:

javascript
const wallet = fromSecretKey(process.env.BLOCKLET_APP_SK);
const isValid = wallet.verify(data);

新:

javascript
const wallet = fromSecretKey(process.env.BLOCKLET_APP_PK);
const isValid = wallet.verify(data);

fromAppDid:

旧:

javascript
// BLOCKLET_APP_SK
const wallet = fromAppDid(address, process.env.BLOCKLET_APP_SK, { role: types.RoleType.ROLE_ACCOUNT }, x)

// BLOCKLET_APP_PSK
const wallet = fromAppDid(address, process.env.BLOCKLET_APP_PSK, { role: types.RoleType.ROLE_ACCOUNT }, x)

新:

javascript
  const { deriveWallet } = require('@blocklet/sdk/lib/wallet');

  // BLOCKLET_APP_SK
  const wallet = await deriveWallet(address, { role: types.RoleType.ROLE_ACCOUNT }, x);

  // BLOCKLET_APP_PSK
  const wallet = await deriveWallet(address, { role: types.RoleType.ROLE_ACCOUNT }, x, 'psk');

2. getWallet() 返回对象的改动

变更:删除 wallet.secretKey / wallet.sk 等属性;签名/验证方法均改为异步。

迁移要点

  • 所有 wallet.sign()、wallet.verify() 等调用必须 await。
  • 若代码依赖 wallet.secretKey 进行签名或派生,请参考 1. 环境变量变动 的改动。

示例

旧:

javascript
const { getWallet } = require('@blocklet/sdk/lib/wallet');

const wallet = getWallet();
const sig = wallet.sign(data);

console.log(wallet.secretKey) // sk....

新:

javascript
const { getWallet } = require('@blocklet/sdk/lib/wallet');

const wallet = await getWallet();
const sig = await wallet.sign(data);

console.log(wallet.secretKey) // undefined

3. 多个导出变为命名(ESM)导出

变更:一些包从默认导出或 CommonJS 风格改为命名导出。导入语法需调整。

常见替换模式

javascript
- import parse from '@blocklet/meta/lib/parse';
+ import { parse } from '@blocklet/meta/lib/parse';

- const env = require('@blocklet/sdk/lib/env');
+ const { env } = require('@blocklet/sdk/lib/env');

受影响的包与常见导出(请在代码库中全局搜索并替换):

  • @blocklet/sdkBlockletAuthenticator, createConnectHandlers, Database, authMiddleware, fallback, sessionMiddleware, sitemap, userMiddleware, WalletAuthenticator, WalletHandlers, getWallet, getPkWallet, createRemoteWallet, deriveWallet, getPermanentWallet, getEthereumWallet, getAccessWallet, env, BlockletService 等。
  • @blocklet/metatoBlockletDid, validateBlockletEntry, getComponentProcessId, hasReservedKey, getBlockletInfo, parseNavigation, parse, urlPathFriendly, verifyMultiSig, getApplicationWallet, checkBlockletEnvironment, env
  • @blocklet/env:以前直接默认导出 env,现在需要从 blockletEnv / env 命名导出中解构。

建议使用 IDE 的全仓 grep/replace 或逐文件修改,确保引入方式与导出的命名保持一致。

4. 同步 -> 异步:需要在调用处添加 await 与 async

变更:下列函数/方法现在为异步(仅列出高频用到的)。请将调用处添加 await,并将包含调用的函数标注为 async。

4.1 @blocklet/sdk

  • verify() / sign() / getSignData()(lib/util/verify-sign.ts)
  • signResponse() / verifyResponse()(lib/security)
  • getDelegation()(lib/connect/shared.ts)
  • verifyBlockletSig()(lib/middlewares/blocklet.ts)
  • subscribe() / unsubscribe()(lib/service/eventbus.ts)
  • ensureClient() / on()(lib/service/notification.ts)

4.2 @ocap/wallet

由库生成的 wallet 实例(或 getWallet() 返回)的方法均改为异步:

  • wallet.sign()
  • wallet.verify()
  • wallet.ethSign()
  • wallet.ethVerify()

4.3 其他库(常见)

  • @arcblock/jwt:jwt.sign(), jwt.verify(), jwt.signV2() -> await。
  • @blocklet/meta:signResponse(), verifyResponse() -> await。
  • @asset/vc:create(), verify(), verifyPresentation(), createCredentialList(), verifyCredentialList() -> await。
  • @blocklet/js-sdk:verifyResponse() -> await。
  • @blocklet/store / @blocklet/cli:sign() -> await。
  • @blocklet/server-js:_getAuthHeaders(), getAuthHeaders(), signWithAccessKey() -> await。

5. 签名与调用场景的特殊说明(关键)

以下场景(跨 Component 调用 / 调用 Service API / Notification 或 WebSocket),签名私钥用原来的 process.env.BLOCKLET_APP_SK,改成 access wallet 的 secretKey

迁移要点

  • 使用 @blocklet/sdk 的 getAccessWallet() 获取 access wallet(包含签名密钥),并将 secretKey 显式传入 sign() / verify() / getSignData() 的 options。示例:
javascript
import { sign, verify, getSignData } from '@blocklet/sdk/lib/util/verify-sign';
import { getAccessWallet } from '@blocklet/sdk/lib/wallet';

const accessWallet = await getAccessWallet();

// sign
const result = await axios({
  url: '/service/api',
  data: json,
  headers: {
    'x-app-id': accessWallet.address,
    'x-app-pk': accessWallet.publicKey,
    'x-component-sig': await sign(json, { appSk: accessWallet.secretKey }),
    'x-component-did': process.env.BLOCKLET_COMPONENT_DID
  },
});

// verify
const isValid = await verify(data, signature, { appSk: accessWallet.secretKey });

// getSignData
const signData = await getSignData(data, { appSk: accessWallet.secretKey });

代码迁移清单(按优先级)

  1. 在代码库根目录运行升级命令并安装依赖。创建单独分支。
  2. 全仓搜索并替换导入方式(CommonJS 默认导出 -> 命名导出)。
  3. 全仓搜索 getWallet() / fromSecretKey() / fromAppDid() 等用法:
    • 用到私钥属性(secretKey / sk)的位置需替换为 getWallet() 签名或 getAccessWallet() 并使用 appSk。
    • 将所有 sign() / verify() / getSignData() 等变更为 await。
  1. 针对跨组件/Service/Notification/WebSocket 的调用,确保使用 getAccessWallet() 并把 appSk 传给签名方法。
  2. 修改后运行 TypeScript/Node 构建及单元/集成测试,捕获遗漏的同步调用或导入错误。
  3. 逐文件人工复核:特别关注在中间件、service、eventbus、notification、connect 相关的代码路径。

常见问题与排错建议

  • Bad secret key size
    • 原因:未将依赖升级到最新版本
  • 各种 verify 失败
    • 确认签名使用的是 access wallet 的 secretKey
  • 其他组件启动失败
    • 请将你应用中的所有组件都升级到最新版,彻底停止后,再启动