Zcash 2.0.5-rc1 版本解析:Sprout 到 Sapling 自动迁移、ZIP 209 与区块浏览器索引
【免费下载链接】zcashZcash - Internet Money项目地址: https://gitcode.com/GitHub_Trending/zc/zcash
导读
本文基于 Zcash 全节点实现(zcashd)的doc/release-notes/release-notes-2.0.5-rc1.md版本变更日志,深入解析 2.0.5-rc1 版本带来的核心功能变化。该版本是 Zcash 发展历程中的关键节点:它首次将Sprout 到 Sapling 资金自动迁移作为完整的 RPC 功能落地,在主网启用了ZIP 209(turnstile 检查)与对应的 Sprout 池余额 fallback 机制,并为 Bitcore Insight 风格区块浏览器引入了-addressindex、-spentindex、-timestampindex三个索引选项。读完本文,你将掌握迁移功能的配置与查询命令、开发者实验开关的用法,以及这些特性在源码中的实现位置与调用关系。
版本背景与变更总览
2.0.5-rc1 是 Zcash 2.0.x 系列的一个候选发布版本,其变更日志按贡献者罗列了共 40 余个提交。按技术主题归类,主要变更集中在以下四个方面:
| 主题 | 主要贡献者 | 变更要点 |
|---|---|---|
| Sprout 到 Sapling 自动迁移 | Eirik0 | 新增z_setmigration、z_getmigrationstatusRPC,迁移逻辑移至 ChainTip,新增-migrationdestaddress配置项 |
| ZIP 209 与开发者实验开关 | Simon Liu | 主网启用 ZIP 209 并设置 fallback Sprout 池余额,新增-developersetpoolsizezero实验功能 |
| 区块浏览器索引 | Larry Ruane | 新增-addressindex、-spentindex、-timestampindex,修复 enable-debug 构建问题 |
| 基础设施与构建 | Jack Grigg 等 | TransactionBuilder 增加 Sprout 支持、Blossom 升级、HD seed 修复、Boost 1.69 → 1.70 |
下文将围绕这四个主题逐一展开,并结合仓库源码给出实现层面的佐证。
Sprout 到 Sapling 自动迁移:完整的 RPC 功能落地
Sprout 是 Zcash 第一代屏蔽交易协议,其密码学原语(基于 SHA-256 压缩函数的零知识证明)相对脆弱;Sapling 则引入了更高效的证明系统。为了让仍持有 Sprout 资金的用户平滑过渡,Zcash 设计了自动迁移机制:当区块链高度满足特定条件时,节点会自动构造将 Sprout 资金转入 Sapling 地址的交易。2.0.5-rc1 通过多个提交完善了这一机制。
迁移开关:z_setmigration
变更日志中的 "Add rpc to enable and disable Sprout to Sapling migration" 对应了钱包 RPCz_setmigration。其实现位于 src/wallet/rpcwallet.cpp:
UniValue z_setmigration(const UniValue& params, bool fHelp) { ... "z_setmigration enabled\n" "When enabled the Sprout to Sapling migration will attempt to migrate all funds from this wallet's\n" "Sprout addresses to either the address for Sapling account 0 or the address specified by the parameter\n" "'-migrationdestaddress'.\n" ... LOCK(pwalletMain->cs_wallet); pwalletMain->fSaplingMigrationEnabled = params[0].get_bool(); return NullUniValue; }该 RPC 只接受一个布尔参数enabled,设置为true时启用迁移,false时关闭。调用后会写入钱包对象的fSaplingMigrationEnabled字段(声明于 src/wallet/wallet.h)。值得注意的是,该开关也可以通过配置文件中的-migration布尔参数在启动时直接设定(见 src/wallet/wallet.cpp)。
对参数类型的校验在测试中有明确覆盖:src/wallet/test/rpc_wallet_tests.cpp 验证了z_setmigration true/false正常返回、缺少参数抛runtime_error、非布尔字符串(如nonboolean、1)也会被拒绝。
迁移状态查询:z_getmigrationstatus
变更日志中的 "Add rpc to get Sprout to Sapling migration status" 对应z_getmigrationstatus,实现同样位于 src/wallet/rpcwallet.cpp。其返回结构完整定义在帮助文本中:
{ "enabled": true|false, (boolean) 迁移是否启用 "destination_address": "zaddr", (string) 接收 Sprout 资金的 Sapling 地址 "unmigrated_amount": nnn.n, (numeric) 未迁移的总金额(ZEC) "unfinalized_migrated_amount": nnn.n, (numeric) 未最终确认的已迁移金额 "finalized_migrated_amount": nnn.n, (numeric) 已最终确认的已迁移金额 "finalized_migration_transactions": nnn, (numeric) 涉及本钱包的已最终确认迁移交易数 "time_started": ttt, (numeric, 可选) 首笔迁移交易的区块时间(Unix 时间戳) "migration_txids": [txids] (json 数组) 所有涉及本钱包的迁移交易 ID }实现细节可以印证变更日志中的多项提交:
- "Do not look at vin/vout when determining migration txs and other cleanup":判定一笔交易是否为迁移交易,只看其是否满足三个条件——包含一个或多个
vpub_new非零的 Sprout JoinSplit、不含 Sapling Spends、含一个或多个 Sapling Outputs(src/wallet/rpcwallet.cpp)。 - "Calculate the number of confimations in the canonical way":交易"最终确认"的标准是主链深度达到 10 个确认(
tx.GetDepthInMainChain(asOfHeight) >= 10)。 - "use -valueBalance rather than vpub_new to calculate migrated amount":已迁移金额通过
GetValueBalanceSapling()计算而非直接累加vpub_new。 - "Refactor wait_and_assert_operationid_status to allow returning the result"与"Check for full failure message in test case"则服务于测试框架对迁移流程的断言。
此外,unmigrated_amount的计算会包含锁定中或仅存在于 mempool 的 Sprout 笔记(GetFilteredNotes调用传入0, INT_MAX深度范围,见 src/wallet/rpcwallet.cpp),确保查询结果反映真实可迁移余额。
迁移调度与金额选择算法
迁移并不是立即一次性完成的,而是遵循一个节流策略,这在z_setmigration的帮助文本中有明确描述(src/wallet/rpcwallet.cpp):
- 每次区块链高度达到
99 modulo 100时触发一轮迁移; - 每轮最多构造 5 笔交易;
- 交易金额按照 ZIP 308 规定的随机分布选取;
- 迁移在钱包 Sprout 余额低于 0.01 ZEC(
CENT)时结束。
金额选择算法实现在 src/wallet/asyncrpcoperation_saplingmigration.cpp:指数在 6~8(慢档)或 8~10(快档,当可用资金超过 1 ZEC 时)之间均匀选取,尾数在 1~99 之间均匀选取,最终金额为mantissa * 10^exponentzatoshi,若超过剩余可迁移金额则重新取样。
迁移目标地址与 HD Seed
迁移目标地址的确定逻辑(src/wallet/asyncrpcoperation_saplingmigration.cpp)为:
- 若启动参数
-migrationdestaddress=<zaddr>已设置,则使用该 Sapling 地址(该参数的合法性在 src/wallet/wallet.cpp 启动时校验,非法地址会直接报错退出); - 否则使用钱包为 Sapling 账户 0 派生的默认地址(派生路径为
m/32'/coin_type'/0x7FFFFFFF'/0')。
变更日志中的 "Create method for getting HD seed in RPCs" 与 "Do not throw an exception if HD Seed is not found when exporting wallet" 两项提交,为上述地址派生(GetHDSeedForRPC)与钱包导出流程提供了基础设施。
ZIP 209 与开发者实验功能 -developersetpoolsizezero
ZIP 209 定义了屏蔽池的 turnstile 检查规则,防止资金在屏蔽池间流转时出现守恒违规。2.0.5-rc1 中的 "Enable ZIP209 on mainnet and set fallback Sprout pool balance" 提交标志着该共识规则正式在主网生效。
主网 fallback 池余额
由于部分节点未在监控功能引入时执行 reindex,无法自行计算历史 Sprout 池余额,因此代码中硬编码了一个 fallback 值,见 src/chainparams.cpp:
// Hardcoded fallback value for the Sprout shielded value pool balance // for nodes that have not reindexed since the introduction of monitoring // in #2795. nSproutValuePoolCheckpointHeight = 520633; nSproutValuePoolCheckpointBalance = 22145062442933; fZIP209Enabled = true; hashSproutValuePoolCheckpointBlock = uint256S("0000000000c7b46b6bc04b4cbf87d8bb08722aebd51232619b214f7273f8460e");即:以 520633 高度的区块作为 Sprout 池余额检查点,fallback 余额为 22145062442933 zatoshi,同时将fZIP209Enabled置为true(testnet 的对应配置见同文件 src/chainparams.cpp)。
开发者实验开关 -developersetpoolsizezero
对于 regtest/testnet 测试而言,严格启用 turnstile 检查会阻碍构造违反守恒规则的测试链。为此 2.0.5-rc1 引入了实验功能-developersetpoolsizezero(变更日志 "Add testnet and regtest experimental feature")。
该开关在 src/experimental_features.cpp 中解析:
fExperimentalDeveloperSetPoolSizeZero = GetBoolArg("-developersetpoolsizezero", false);在 src/chainparams.cpp 中,当网络为 regtest 且设置了该参数时,会调用SetRegTestZIP209Enabled()启用 ZIP 209,从而允许开发者/测试用例验证 turnstile 违规场景。chainparams.h的注释(src/chainparams.h)明确指出:主网和 testnet 上 ZIP 209 是始终强制执行的共识规则,而 regtest 默认关闭,只有设置了-developersetpoolsizezero才启用。
从源码结构看,-developersetpoolsizezero的实验性还体现在 src/main.cpp 与 src/main.cpp 中:启用该选项时,共识校验不再依赖 fallback 余额,相关分支用于构造并验证 turnstile 违例场景。需要特别说明的是,该参数当前仍需配合-experimentalfeatures使用(experimentalfeatures列表注册见 src/experimental_features.cpp),且仅面向开发与测试用途。
面向区块浏览器的索引选项:-addressindex / -spentindex / -timestampindex
变更日志中 Larry Ruane 的三条提交("add -addressindex changes"、"add -spentindex changes"、"add -timestampindex for bitcore insight block explorer")为 zcashd 引入了三个与 Bitcore Insight 区块浏览器兼容的索引开关。这些索引允许节点额外维护:
- 地址索引(-addressindex):记录每个地址相关的交易,支撑
getaddresstxids等查询; - 花费索引(-spentindex):记录 UTXO 花费关系,支撑
getspentinfo查询; - 时间戳索引(-timestampindex):按时间范围检索交易,支撑按时间过滤的交易查询。
对应的索引接口声明可以在 src/addressindex.h、src/spentindex.h、src/timestampindex.h 中找到。从代码结构可以推断,这些索引在启动时通过布尔参数启用,启用后会在交易写入区块数据库时同步维护索引表,供 RPC 层读取。同样属于该版本相关工作的还有 "Adding addressindex.h to Makefile.am" 提交(src/Makefile.am),确保头文件被正确纳入构建。
其余关键变更与修复
除上述三大主题外,2.0.5-rc1 还包含一批值得关注的改动:
- TransactionBuilder 增加 Sprout 支持(Jack Grigg):扩展 src/transaction_builder.cpp,使统一的交易构造器可以同时处理 Sprout 与 Sapling 屏蔽输入输出,为迁移等跨池交易提供基础。
- Blossom 升级注册:"Add Blossom to upgrade list" 将 Blossom 网络升级加入共识升级列表(对应
consensus/upgrades相关配置),为后续区块时间缩短与目标出块间隔调整铺路。 - HD seed 生成修复(Jack Grigg):"init: Fix new HD seed generation for previously-encrypted wallets" 修复了已加密钱包首次解锁时可能无法正确生成新 HD seed 的问题。
- 依赖与构建更新:Boost 从 v1.69.0 升级到 v1.70.0(对应 GitHub issue #3947);修复
-enable-debug构建下DB_COINS未定义的问题;depends 系统为 aarch64 Linux 添加 rust-std 哈希、bdb 以--disable-atomics编译;libsnark 的 OPTFLAGS 改为根据目标架构自动推断-march而非硬编码。 - 测试与文档:为
IsPayToPublicKeyHash方法新增单元测试;迁移测试拆分为多个部分并支持通过参数与默认 Sapling 地址两种方式运行;文档清理与拼写修正。
测试覆盖与 QA 实践
变更日志体现出该版本对测试的重视。除IsPayToPublicKeyHash单元测试外:
- 迁移 RPC 的参数校验测试(src/wallet/test/rpc_wallet_tests.cpp)覆盖了合法布尔值、缺失参数与非布尔输入;
- 变更日志 "Test migration using both the parameter and the default Sapling address" 表明迁移功能在测试中同时验证了
-migrationdestaddress参数路径与默认地址路径; - "Split test in to multiple parts" 将原先过大的迁移测试拆分为多个独立用例,降低单用例失败时的定位成本;
- "Add qa test for experimental feature: -developersetpoolsizezero" 为开发者实验开关补充了 Python 层 QA 测试。
这些测试文件(如 src/wallet/test/rpc_wallet_tests.cpp 与 qa/rpc-tests 目录)是理解迁移与索引功能行为边界的最佳入口。
如何验证本文所述功能
若要实际体验 2.0.5-rc1 及后续版本中的这些功能,可以在 regtest 模式下按以下方式操作:
启用迁移:
zcash-cli z_setmigration true zcash-cli z_getmigrationstatus如需指定目标地址,启动节点时添加
-migrationdestaddress=<sapling_zaddr>,或在配置文件中设置migrationdestaddress=<sapling_zaddr>、migration=1。启用开发者实验开关(仅 regtest/testnet,需同时开启实验功能):
zcashd -regtest -experimentalfeatures=1 -developersetpoolsizezero=1启用区块浏览器索引:
zcashd -addressindex=1 -spentindex=1 -timestampindex=1注意:开启索引后,首次同步会额外消耗磁盘空间并可能延长启动/同步时间。
需要说明的是,当前仓库(更高版本)中相关 RPC 与参数仍然保留,但部分默认值与共识参数会随网络升级演进,实操时请以当前版本zcashd --help与文档为准。
总结
Zcash 2.0.5-rc1 是一个承上启下的版本:它把 Sprout 到 Sapling 自动迁移从构想变成了一套完整可用的 RPC 体系(z_setmigration/z_getmigrationstatus+-migrationdestaddress),在主网落地下沉了 ZIP 209 共识检查,并为开发者提供了-developersetpoolsizezero这一测试利器,同时通过地址/花费/时间戳三类索引增强了节点对区块浏览器的支撑能力。围绕这些变更,本文给出的源码路径——src/wallet/rpcwallet.cpp、src/wallet/asyncrpcoperation_saplingmigration.cpp、src/chainparams.cpp、src/experimental_features.cpp——可以继续作为深入研读该版本实现细节的入口。
【免费下载链接】zcashZcash - Internet Money项目地址: https://gitcode.com/GitHub_Trending/zc/zcash
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考