区块链 区块链技术 比特币公众号手机端

Agave 4.2:迁移清单

liumuhui 2小时前 阅读数 1 #区块链

我们在发布概览中介绍了 Agave 4.2 的功能集。本文介绍迁移:在功能开关激活之前,哪些地方会出问题,以及如何验证你的集成。

这些变更中的大多数会返回错误或缺失的数据,而不是报错,因此它们不会出现在你的异常日志中。

激活时间线

时间 内容 状态
2026 年 8 月 11 日 Anza 推荐在主网使用 4.2;验证者开始升级 进行中
随着节点升级 账户更新抑制和 Token-2022 jsonParsed 变更生效 已完成
升级后的第一个 epoch 边界 DeactivatedStake rewardType 值出现在奖励中 已完成
Epoch 1020 区块时间从 400ms 缩短到 350ms,这是迈向 200ms 的四步中的第一步 已完成
Epoch 1024 区块时间从 350ms 缩短到 300ms 已计划(预计 8 月 28 日)
功能开关,日期待定 Transaction v1(4,096 字节交易) 待定(尚未公布日期,因此请按下周激活做准备)
五个功能开关,日期待定 租金减免,从 6,960 lamports/字节 逐步降至 696 待定
Agave 4.3,目标 2026 年 10 月 Alpenglow 共识 未来版本

Agave 4.2 破坏性变更

Transaction v1 会导致整个调用失败

SIMD-0296 和 SIMD-0385 通过一种新的交易格式将 Solana 交易大小限制提高到 4,096 字节。

额外的空间让开发者可以运行更大的链上工作负载,例如 ZK 证明或具有更多路径的 DEX 路由。

问题在于:如果调用没有设置 maxSupportedTransactionVersion: 1,区块中的一笔 v1 交易会导致整个区块的 getBlock 失败。

其他交易也不会返回;整个调用都会报错。getTransactiongetTransactionsForAddress(使用 transactionDetails = full)在任何 v1 交易上都会以同样的方式失败。

如何修复:
  • 将你的 SDK 升级到能够解码 v1 的版本。各客户端正在陆续支持。如果你的 SDK 尚未发布 transaction v1 支持,请关注其发布说明中关于 transaction v1 或 SIMD-0385 的内容。
    • 常用的 JS 客户端:@solana/kit 8.0+、@solana/web3.js v3
    • 常用的 Rust crates:solana-rpc-client-api 4.2+、solana-client 4.2+、solana-transaction 4.2+、solana-compute-budget 4.2+、其他 Anza crates。
  • 在每次 getBlock、getTransaction 和 getTransactionsForAddress 调用(使用 transactionDetails = full)中设置 maxSupportedTransactionVersion: 1
  • 在 WebSocket transactionSubscribe 调用中设置 maxSupportedTransactionVersion: 1
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "getTransactionsForAddress",
  "params": [\
    "Vote111111111111111111111111111111111111111",\
    {\
      "transactionDetails": "full",\
      "sortOrder": "desc",\
      "filters": {\
        "status": "succeeded"\
      },\
      "maxSupportedTransactionVersion": 1\
    }\
  ]
}

该参数声明你的客户端能够处理的最高版本。现在设置它是安全的,并且不会改变 legacy 和 v0 交易的返回方式。

Transaction v1 计算预算失败

v1 交易将其计算上限和优先费用存储在 transactionConfig 对象中,而不是 ComputeBudget 指令中。通过匹配这些指令来检测费用的费用仪表盘和优先费用估算器,会将每笔 v1 交易读取为支付零费用,且不会报错。

如何修复:

改为从交易配置中的新 priorityFee 字段读取值。注意,新的 priorityFee 字段表示的是以 lamports 为单位的总费用(不是每个计算单元的价格)。

"message": {
  "instructions": ["… no ComputeBudget instruction here …"],
  "recentBlockhash": "...",
  "transactionConfig": {
    "computeUnitLimit": 200000,
    "heapSize": null,
    "loadedAccountsDataSizeLimit": 200000,
    "priorityFee": 50000
  }
}

未变化的账户停止发出更新

Agave 4.2 仅在账户实际被写入时才发出账户事件。对于 LaserStream gRPC 和 WSS 账户订阅,这意味着事件数量大约减少 80%。

如何修复:
  1. 如果你将交易与账户更新进行匹配,不要再等待每个可写账户的更新;将缺失的更新视为“账户没有变化”。只有付费方保证会更新,因为它总是支付费用。
  2. 如果你将更新频率作为健康信号,请对经常被锁定但很少变化的账户移除该检查。一个安静的账户是健康的;它停止发出事件是因为没有变化。

新的 rewardType 值

完成去激活的质押账户现在会在 getBlockblockSubscribe 奖励数组中,以新的 rewardTypeDeactivatedStake 收到最终付款。奖励对象的结构与 Agave 4.1 相同,因此只接受已知奖励类型的解析器会跳过 DeactivatedStake 付款,而不会报错。

getInflationReward 不受影响;风险仅适用于你自己解析原始奖励数组的情况。

如何修复:

DeactivatedStake 添加到你的解析器接受的 rewardType 值中,并记录任何你不认识的值,而不是丢弃该记录。

{
  "pubkey": "...",
  "lamports": 10000000,
  "postBalance": 50000000000,
  "rewardType": "DeactivatedStake",
  "commission": null,
  "commissionBps": 500
}

Token-2022:移除一个字段,解析范围扩大

jsonParsed 响应中,depositConfidentialTransferwithdrawConfidentialTransfer 不再使用 source 和 destination,而是使用单个 account 字段。旧的标签是不正确的;每条指令只涉及一个代币账户。

修复方法是更新 Token-2022 解析器以支持新字段。

{
  "parsed": {
    "type": "depositConfidentialTransfer",
    "info": {
      "account": "6XVfUq9jZQtBfqcm1Rz8fBhViyoyzWiEUAaWnQ9AmXeR",
      "mint": "8fJ7bCZo2vZ3vAnyCBQgZuLYuTX1qPnKvsMKotk92B2J",
      "amount": 42,
      "decimals": 9,
      "owner": "F7yLk3s2iZDPBBvSNbXAaKPBnQ9vXqSSSzYUCGeUFhXn"
    }
  }
}

Permissioned burn、unwrapLamportsconfidentialBurn 和批量操作现在以解析后的 JSON 返回,而不是原始字节。

{
  "parsed": {
    "type": "unwrapLamports",
    "info": {
      "source": "9rr9Xh6PXPKcVqbCB1qxGDWRUJJAdguqcUqVuUqEjqQK",
      "destination": "BhU2wDgmvvMNC1vTSU4aG7BvW26MoTMSDL63hcMqziGL",
      "amount": "1000000",
      "authority": "F7yLk3s2iZDPBBvSNbXAaKPBnQ9vXqSSSzYUCGeUFhXn"
    }
  }
}

带有以前无法识别的扩展的 Mint,过去会返回一个空的 extensions 数组;在 Agave 4.2 上,该数组会被填充。

如果你的代码将空数组视为“没有扩展”,那么预计那里会开始出现值。

"extensions": [\
  {\
    "extension": "transferFeeConfig",\
    "state": {\
      "transferFeeConfigAuthority": "...",\
      "withdrawWithheldAuthority": "...",\
      "withheldAmount": 0,\
      "olderTransferFee": {...},\
      "newerTransferFee": {...}\
    }\
  },\
  {\
    "extension": "permissionedBurnConfig",\
    "state": {\
      "authority": "3nGhQzXCzoDDvW9pkg8fVLGDrJc23uwFz7qzW26MoTMS"\
    }\
  }\
]

Slot 时间常量已过时

主网自 epoch 1020 起运行 350ms 的区块时间。下一次缩减到 300ms 的计划在 epoch 1024(预计 8 月 28 日),目标为 200ms。在 slot 到时间的计算中,硬编码的 400ms 常量目前偏差 12.5%,并且随着每一步会进一步偏离。

如何修复:

从区块时间戳推导时间,或使其可配置,并确保当区块开始更快到达时,你的索引器能够跟上。

验证你是否已完成

要验证你是否已完成,请运行 agent 审计并确认你的依赖项。

运行 agent 审计

将下面的技能复制到你的编码 agent 中。

对于 Claude Code,将其保存为 .claude/skills/agave-42-readiness/SKILL.md

对于其他 agent,将其作为任务提示粘贴。

提示

---
name: agave-42-readiness
description: 审计此仓库中 Solana Agave 4.2 的破坏性变更。当被要求检查 Agave 4.2 就绪状态、为 transaction v1 迁移或审计 Solana RPC/流式集成代码时使用。
---

## Agave 4.2 就绪审计

审计以下五个 Agave 4.2 破坏性变更。对于每一项,定位相关代码,判断其是否受影响,并报告 file:line 以及 PASS、FAIL 或 NEEDS REVIEW 的结论。除非被要求修复发现的问题,否则不要修改代码。

### 检查 1:Transaction v1 选择加入(最高优先级)
查找所有 `getBlock`、`getTransaction` 和 `getTransactionsForAddress`(使用 `transactionDetails = full`)调用。搜索所有语言、原始 JSON-RPC 请求体(`"method": "getBlock"`)以及 SDK 包装器(`connection.getBlock`、`connection.getParsedTransaction`、`rpc_client.get_block`、`client.GetTransaction` 等)。
- 如果 `maxSupportedTransactionVersion` 缺失或设置为 0,则 FAIL。一旦 v1 功能开关激活,这些调用将在 v1 交易上失败,并返回 JSON-RPC 错误代码 -32015:`"Transaction version (1) is not supported by the requesting client. Please use \"maxSupportedTransactionVersion\" in your request."` 同时,在日志和错误处理器中搜索 `-32015`;命中表示项目已经在版本化交易上失败。
- 如果项目反序列化原始交易字节(自定义索引器、签名者、中继器),且解码器不处理 v1 布局,则 FAIL:版本字节 0x81(十进制 129,而 v0 为 0x80),签名在交易末尾而不是开头,计算预算通过头部配置掩码而不是指令携带。
- 正确的修复顺序:将 Solana SDK 升级到支持 v1 的版本(JS:@solana/kit 8.0+ 或 @solana/web3.js v3),然后设置 `maxSupportedTransactionVersion: 1`。如果参数已设置但安装的 SDK 版本早于 v1 支持,请标记。
- 如果优先费用或计算预算提取扫描 ComputeBudget 程序指令(`ComputeBudget111111111111111111111111111111`、`setComputeUnitPrice`、`setComputeUnitLimit`),则 FAIL。v1 交易不包含此类指令;其值位于消息中的 `transactionConfig` 对象中。扫描代码会将每笔 v1 交易读取为支付零优先费用。
- 单位陷阱,即使代码读取了 `transactionConfig`,FAIL:legacy/v0 的 `setComputeUnitPrice` 是**每个计算单元的微 lamports**;v1 的 `priorityFee` 是**以 lamports 为单位的总费用**。将旧的 `price × computeUnitLimit ÷ 1e6` 数学移植到新字段的代码会误报费用。`priorityFee` 不需要乘法。Null 字段表示发送者未设置它们。

v1 消息示例:
```
"message": {
"instructions": ["… no ComputeBudget instruction here …"],
"recentBlockhash": "...",
"transactionConfig": {
    "computeUnitLimit": 200000,
    "heapSize": null,
    "loadedAccountsDataSizeLimit": 200000,
    "priorityFee": 50000
}
}
```
`"priorityFee": 50000` = 这笔交易总共支付 50,000 lamports。Legacy 和 v0 消息完全省略 `transactionConfig`,因此它的存在(或外层交易的 `"version": 1`)标识 v1。

### 检查 2:rewardType 被解析为封闭枚举
查找从 `getBlock`、`blockSubscribe` 或 Geyser/gRPC 奖励数组中读取 `rewardType` 的代码。同时搜索现有值(JSON 路径中的 `"Fee"`、`"Rent"`、`"Staking"`、`"Voting"`;Rust 中的 `RewardType::`;生成的 gRPC 代码中的 reward-type 枚举)。
- 4.2 添加了值 `DeactivatedStake`——与现有 JSON 值的大小写相同(`"Staking"`,而不是 `"staking"`)。奖励条目如下:
```
{
"pubkey": "...",
"lamports": 10000000,
"postBalance": 50000000000,
"rewardType": "DeactivatedStake",
"commission": null
}
```
- 如果未知值抛出异常,或落入 match/switch 分支或 if/else 链中丢弃记录而不记录日志,则 FAIL:没有记录日志的通配符分支的 Rust `match`、`default` 为静默的 TS `switch`、缺失键跳过条目的查找表。封闭解析器会丢失每个去激活质押账户的最终付款,且不会报错。
- 如果反序列化枚举(serde、protobuf 映射、Zod/io-ts schema)拒绝未知的 reward-type 字符串,则 FAIL;整个奖励数组或区块记录会出错,而不仅仅是一个条目。
- PASS 要求保留或记录未知值。如果项目通过过滤 `rewardType == "Staking"` 来聚合质押收益,请添加 NEEDS REVIEW,注明团队必须决定 `DeactivatedStake` 付款是否应计入总额;它们是最终付款,而不是周期性收益。

### 检查 3:交易到账户更新的匹配
查找将交易与账户更新通知相关联的逻辑。搜索 `accountSubscribe`、Yellowstone/LaserStream `SubscribeRequest` 账户过滤器,以及构建交易可写账户的待处理集合并等待更新到达时勾销的代码。
- 如果它假设交易中的每个可写账户都会产生更新,则 FAIL。在 4.2 上,被写锁定但未修改的账户不会发出任何事件;等待完整集合的逻辑会永远挂起。典型模式:对 `message.accountKeys` 可写条目的倒计时/完成闩锁、将缺失更新视为错误的超时、重新获取“迟到”账户的对账器。付费方是唯一保证更新的账户。
- 缺失更新的正确解释是“该账户没有变化”;其交易前状态仍然是最新的。
- 将更新频率视为信号的 liveness 或健康检查也会 FAIL,并标记根据 4.2 之前数量校准的警报阈值;账户订阅事件数量在 4.2 上大约下降 80%。

### 检查 4:Token-2022 jsonParsed 变更
查找读取 Token-2022 `jsonParsed` 输出的解析器:指令类型 `depositConfidentialTransfer` 和 `withdrawConfidentialTransfer`,以及 mint 账户的 `extensions` 数组。
- 如果机密转账解析器读取 `source` 或 `destination`,则 FAIL;4.2 将两者替换为单个 `account` 字段。新结构:
```
"info": {
"account": "...",   // 原为 source + destination
"mint": "...",
"amount": 42,
"decimals": 9,
"owner": "..."      // multisig:改为 "multisigOwner" + "signers" 数组
}
```
- 新的指令类型现在以解析后的形式返回,而不是原始形式:`unwrapLamports`、`confidentialBurn`、permissioned burn 和批量操作。如果代码假设这些以原始 base64/base58 数据到达,则 FAIL,并标记要求 `info.amount` 或将其视为数字的 `unwrapLamports` 解析器:它是一个**字符串**,并且当指令解包全部余额时**完全省略**。
- extensions 数组:在 4.1 上,mint 上有一个无法识别的扩展类型会导致节点返回 `"extensions": []`,隐藏所有扩展,包括已知的。在 4.2 上,完整数组返回,每个条目为 `{"extension": "<name>", "state": {...}}`,仍然无法解码的条目为 `{"extension": "unparseableExtension"}`。如果代码将空数组视为没有扩展的证明,或对其不认识的扩展名称(`scaledUiAmountConfig`、`pausableConfig`、`permissionedBurnConfig`、`unparseableExtension` 以及未来的值)抛出异常,则 FAIL。

### 检查 5:Slot 时间和流式依赖
- 硬编码 slot 持续时间常量则 FAIL:`400`、`0.4`、`400_000` 微秒、`MS_PER_SLOT`、`SLOT_DURATION`、`DEFAULT_MS_PER_SLOT`,或诸如 `slots * 400` 的 slot 到时间计算。主网为 350ms,将于 2026 年 8 月 28 日缩减到 300ms,并逐步迈向 200ms。从 SDK 继承的常量也算硬编码。PASS 要求时间从区块时间戳推导(例如,几千个 slot 的 `getBlockTime` 增量)或使用具有文档化更新路径的配置值。
- 同时标记与区块速率相关的容量假设:为 400ms 区块设计的批量大小、轮询间隔和队列深度会随着 slot 缩短而落后。
- 在 Cargo.toml/Cargo.lock 中:如果 `yellowstone-grpc-client` < 13.3.0 或 `yellowstone-grpc-proto` < 12.6.0(第一个携带 transaction v1 的 proto),则 FAIL。建议客户端 13.3.0,proto 12.6.0,两者都要声明。
- 对于 Go gRPC 客户端:如果生成的 protos 早于 transaction v1,则标记;从最新的 Yellowstone protos 和 solana-storage-proto 重新生成。
- 如果项目使用 Helius LaserStream SDK(依赖项中的包名 `helius-laserstream`、`laserstream`):如果低于 JS 0.8.4、Rust 0.6.3 或 Go 0.2.0(首批支持 v1 的 proto 的版本),则 FAIL。

### 报告格式
输出一个表格:检查项、结论、file:line 引用、一行修复建议。最后给出总体结论(就绪 / 未就绪)和有序的修复列表。完整迁移指南:https://www.helius.dev/blog/agave-4-2-migration-checklist

确认流式依赖

Rust:声明 yellowstone-grpc-client 13.3.0 和 yellowstone-grpc-proto 12.6.0,然后运行 cargo update

Go:从最新的 Yellowstone protos 和 solana-storage-proto 重新生成。

LaserStream SDK:JS 0.8.4、Rust 0.6.3 和 Go 0.2.0 或更高版本包含支持 v1 的 proto。你的订阅和过滤器在任何路径上都无需更改。

问题

如果你的集成在 4.2 上表现不同,而本文没有解释,请通过 Discord 或 支持 联系我们。有关功能级别的详细说明,请阅读 4.2 概览。

  • 原文链接: helius.dev/blog/agave-4-...
  • 鸿途知科网 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
版权声明

本文仅代表作者观点,不代表区块链技术网立场。
本文系作者授权本站发表,未经许可,不得转载。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门