
fhEVM Coprocessor 链上升级实操借助 Aragon DAO 完成proposeCoprocessorUpgrade提案的全流程指南【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm本篇指南完整讲解 fhEVM 仓库中 coprocessor协处理器需要链上升级提案时的标准操作流程如何通过 GitHub Actions 工作流或 Hardhat 任务为 Aragon DAO 生成调用ProtocolConfig.proposeCoprocessorUpgrade(...)的 calldata并在 DAO 投票通过后打开覆盖所有 host 链与 gateway 的升级窗口。读完本文你将掌握从环境参数确认、跨链区块窗口计算、calldata 获取到 DAO 提案提交与本地演练的完整实战能力并能理解底层源码的窗口投影与 buffer 校验逻辑。原始操作手册位于 host-contracts/COPROCESSOR_UPGRADE_RUNBOOK.md本文以其为骨架结合 host-contracts/tasks 下的实现源码与测试进行纵深展开。一、升级提案的背景与产出fhEVM 的 coprocessor 是链下负责同态加密计算TFHE 运算、解密等的分布式服务。当 coprocessor 需要发布新版本例如v0.14.0时出于安全与可审计性要求升级必须经过链上治理由 Aragon DAO 对ProtocolConfig.proposeCoprocessorUpgrade(...)进行投票投票通过后升级窗口才会在所有 host 链与 gateway 上打开GCSGateway Coprocessor Service等相关组件才能在该窗口内完成蓝绿切换与回放dry-run。本流程产出物是一个十六进制字符串calldata它对应 Aragon DAO 提案中调用的ProtocolConfig.proposeCoprocessorUpgrade(...)动作。DAO 投票通过并执行提案后链上会发出CoprocessorUpgradeProposed事件升级窗口随即开启。从合约源码看host-contracts/contracts/ProtocolConfig.sol 中的proposeCoprocessorUpgrade方法签名如下function proposeCoprocessorUpgrade( uint256 proposalId, string calldata softwareVersion, ChainUpgradeWindow[] calldata chainUpgradeWindows, uint64 gwStartBlock ) external virtual onlyACLOwner其中每个链的升级窗口使用 host-contracts/contracts/shared/Structs.sol 中定义的ChainUpgradeWindow结构struct ChainUpgradeWindow { uint64 chainId; // 该窗口适用的 host 链 ID uint64 startBlock; // GCS 在 dry-run 中回放的首个区块含 uint64 endBlock; // GCS 在 dry-run 中回放的最后一个区块含 }该结构体注释明确说明其用途是coprocessor blue-green upgrade期间每个 host 链的回放窗口这解释了为什么提案需要为每一条链精确计算起止区块号。二、前置条件在运行任何工具之前请确认以下条件已满足新版本已构建完成新的 coprocessor 版本已经构建好并已知其发布标签release tag例如v0.14.0。dry-run 评估窗口的起始墙钟时间已确定评估窗口的 wall-clock 开始时间已经最终确认并以 ISO 8601 UTC 格式记录。起始时间足够靠后开始时间必须给 DAO 投票留出足够的前置时间这个前置时间即--buffer参数主网通常取2h。如果起始区块距离当前链头太近任务会因 buffer 校验失败而拒绝输出见下文buffer 门禁。三、Step 1 — 运行 GitHub Actions 工作流仓库提供了名为host-contracts-prepare-coprocessor-upgrade的手动触发工作流.github/workflows/host-contracts-prepare-coprocessor-upgrade.yml它针对所选环境的真实 RPC 执行task:prepareCoprocessorUpgrade任务并把计算报告与 ABI 编码后的 calldata 输出到工作流日志。在仓库页面进入Actions → host-contracts-prepare-coprocessor-upgrade → Run workflow填写以下输入输入项取值说明Environmentdevnet、testnet或mainnet目标环境下拉选择Start timeISO 8601 UTC例如2026-07-01T12:00:00Z评估窗口的墙钟开始时间Duration窗口长度例如30m支持30s、30m、2h、1d或裸整数秒BufferDAO 前置时间例如2h从现在到startBlock之间必须保留的秒数Proposal id任意正整数运营方自选合约会拒绝0Software versioncoprocessor 发布标签例如v0.14.0随提案上链的版本字符串点击Run workflow并等待任务完成。工作流的内部实现值得注意两点来源.github/workflows/host-contracts-prepare-coprocessor-upgrade.yml所有 RPC 密钥通过env:注入而不是在run:中插值以防止workflow_dispatch输入造成 shell 注入工作流把所有环境的 RPC secrets 无条件注入RPC_URL_ETHEREUM、RPC_URL_POLYGON、RPC_URL_SEPOLIA、RPC_URL_AMOY、RPC_URL_GATEWAY_DEVNET、RPC_URL_GATEWAY_TESTNET、RPC_URL_GATEWAY_MAINNET脚本只读取所选环境需要的那些因此某个环境缺失 secret 会以env var RPC_URL_X is not set报错见下文失败模式。四、Step 2 — 复制 calldata工作流完成后打开Prepare upgrade proposal步骤的日志滚动到末尾。在## Calldata标题下的最后一块内容即是以0xccbf8199…开头的十六进制字符串。0xccbf8199是proposeCoprocessorUpgrade函数的函数选择器前 4 字节其 ABI 定义内联在 host-contracts/tasks/utils/coprocessorUpgradeProposal.ts 中function proposeCoprocessorUpgrade(uint256 proposalId, string softwareVersion, tuple(uint64 chainId, uint64 startBlock, uint64 endBlock)[] chainUpgradeWindows, uint64 gwStartBlock)请复制整个十六进制字符串不要只复制选择器它将在 Step 3 中作为 DAO 提案的 calldata 使用。五、Step 3 — 提交 DAO 提案打开目标环境对应的 Aragon DAOMainnet— Ethereum 上的 Aragon DAO0xB6D69D5F334d8B97B194617B53c6aB62f8681Ef3Testnet— Sepolia 上的 Aragon DAO0x08e8a84c3c8c7cba165B1adcf67Ae4639eF84f52在 DAO 中创建新提案填写Target contracthost 链上的ProtocolConfig合约mainnet 为 Ethereum 上的部署testnet 为 Sepolia 上的部署CalldataStep 2 中复制的十六进制字符串。DAO 投票通过且提案执行后链上proposeCoprocessorUpgrade事件触发升级窗口在所有 host 链与 gateway 上打开。注意该方法是onlyACLOwner限定的host-contracts/contracts/ProtocolConfig.sol即只有 ACL 所有者即 DAO 地址能够成功调用这正是必须经由 DAO 提案的原因。六、升级窗口的生成原理从墙钟时间到区块号工作流和 Hardhat 任务的核心逻辑都在 host-contracts/tasks/utils/blockWindow.ts 中理解它能帮助你正确设置--start-time与--duration。6.1 区块时间采样sampleBlockTime读取链头区块号与时间戳再向前回溯采样BLOCK_TIME_SAMPLE_SIZE 1000个区块host-contracts/tasks/utils/blockWindow.ts用采样起止时间差 ÷ 区块数估算平均出块时间。如果链太年轻不足 1000 个区块或采样失败则回退到该环境配置的fallbackBlockTimeSeconds并在报告中标记usedFallback/WARN: block-time sampling failed。6.2 区块号投影projectBlockNumber以链头为基准把目标墙钟时刻投影为区块号deltaSeconds targetTimestamp - tipTimestamp projectedBlock tipBlock round(deltaSeconds / blockTimeSeconds)由于按最近的区块取整投影产生的 skew 被限定在半块出块时间以内——报告中会以startSkewSeconds明确展示这一误差host-contracts/tasks/utils/blockWindow.ts。6.3 buffer 门禁DAO 投票缓冲bufferSatisfied校验startBlock与链头之间按有效出块时间换算出的墙钟间隔是否 ≥--bufferhost-contracts/tasks/utils/blockWindow.ts。若任一 host 链或 gateway 不满足任务会硬性失败DAO 路径打印 calldata 供检查但明确提示不得提交直连路径直接拒绝广播。报告中还会输出跨链对齐信息所有 host 链与 gateway 的startBlock估计时间戳的最大跨度start skew range以及各自相对最早起点的延迟便于运营方判断窗口是否足够对齐。6.4 出块时间漂移告警如果采样得到的真实出块时间与配置的 fallback 相差超过 20%BLOCK_TIME_DRIFT_WARN_FRACTION 0.2报告会给出WARN: observed block time drifted 20% from fallback提示警示当前网络可能处于拥堵状态窗口估算应谨慎对待host-contracts/tasks/utils/blockWindow.ts。七、环境与链集合参考每个环境的链 ID、出块时间与 RPC 环境变量名统一登记在 host-contracts/tasks/utils/environments.ts 的ENVIRONMENTS注册表中环境链chainIdfallback 出块时间RPC 环境变量公共默认 RPCdevnetsepolia1115511112sRPC_URL_SEPOLIAhttps://ethereum-sepolia-rpc.publicnode.comdevnetamoy800021.5sRPC_URL_AMOYhttps://rpc-amoy.polygon.technologydevnetgateway-devnet2sRPC_URL_GATEWAY_DEVNET无内部端点必须设置testnetsepolia1115511112sRPC_URL_SEPOLIA同上公共端点testnetamoy800021.5sRPC_URL_AMOY同上公共端点testnetgateway-testnet2sRPC_URL_GATEWAY_TESTNEThttps://rpc.testnet.zama.orgmainnetethereum112sRPC_URL_ETHEREUM无生产 RPC 私有必须设置mainnetpolygon1372sRPC_URL_POLYGON无生产 RPC 私有必须设置mainnetgateway-mainnet2sRPC_URL_GATEWAY_MAINNET无生产 RPC 私有必须设置从源码注释可以确认设计原则defaultRpcUrl仅保留给公开、众所周知的端点如测试网公共 RPC主网端点和任何私有/内部 URL 必须省略defaultRpcUrl强制运营方通过 repo secrets 配置防止密钥泄露或误连公共限流端点。新增链的方式向目标环境的chains数组追加条目新增环境则添加顶层键并给出chainsgateway。注册表在模块加载时校验同一环境内chainId唯一重复会直接抛错。八、合约层的输入校验即使 calldata 已生成并提交ProtocolConfig.proposeCoprocessorUpgrade在执行时还会做一套完整的链上校验host-contracts/contracts/ProtocolConfig.solproposalId 0→ 拒绝InvalidProposalIdsoftwareVersion为空 → 拒绝EmptySoftwareVersionchainUpgradeWindows为空数组 → 拒绝EmptyChainUpgradeWindowsgwStartBlock 0→ 拒绝ZeroGwStartBlock任一chainId 0→ 拒绝ZeroChainId任一startBlock endBlock→ 拒绝InvalidBlockWindow出现重复chainId→ 拒绝DuplicateChainId。全部校验通过后才发出CoprocessorUpgradeProposed(proposalId, softwareVersion, chainUpgradeWindows, gwStartBlock)事件。这也解释了为什么运营方选择的--proposal-id必须是正整数、且--duration不能过短——校验在链下任务与链上合约两个层面同时生效。九、失败模式与排障运行工作流或任务时可能遇到以下日志错误对应的处理方法如下日志中的错误处理方法DAO buffer violated for: chain X — short by 22m将--start-time至少再向后推迟所缺的时长后重跑。env var RPC_URL_X is not set在 repo settings 中补齐缺失的 secret工作流文件头部按环境列出了所需 secrets。--environment must be one of: devnet, testnet, mainnet从下拉框中选择一个合法环境。duration too short for chain block time至少使用1m作为--duration该错误由 host-contracts/tasks/utils/blockWindow.ts 在投影出的endBlock startBlock时抛出。此外还有两类非致命告警需要留意block-time sampling failed; used configured fallback采样失败回退到配置值与block-time drifted 20% from fallback网络拥堵出块时间与配置偏差过大。十、本地演练DAO 路径在本地做 dry-run 或开发调试时可以直接运行task:prepareCoprocessorUpgradeHardhat 任务定义在 host-contracts/tasks/prepareCoprocessorUpgrade.ts它只计算并打印 calldata绝不广播交易cd host-contracts npx hardhat task:prepareCoprocessorUpgrade \ --environment testnet \ --start-time $(date -u -v2H %Y-%m-%dT%H:%M:%SZ) \ --duration 30m \ --buffer 1h \ --proposal-id 1 \ --software-version v0.14.0输出与 calldata 和工作流运行完全一致。如果任何链的startBlock距离链头小于--buffer任务会以非零退出码失败并打印 calldata 供检查但明确提示不得提交。可用以下命令查看完整参数说明npx hardhat help task:prepareCoprocessorUpgrade任务底层调用链为parseCoprocessorUpgradeInputs校验并解析输入、解析 RPC URL→buildCoprocessorUpgradeProposal调用computeBlockWindow逐链/逐 gateway 计算窗口→encodeProposeCoprocessorUpgrade纯 ABI 编码→printCoprocessorUpgradeProposal打印报告与 calldata→bufferViolationsbuffer 门禁判定全部实现在 host-contracts/tasks/utils/coprocessorUpgradeProposal.ts。时间与时长参数的解析规则host-contracts/tasks/utils/blockWindow.ts时间戳ISO 8601 UTC如2026-07-01T12:00:00Z时长30s/30m/2h/1d或裸整数按秒解释--proposal-id支持十进制或0x十六进制且必须 0。十一、直连no-DAO路径 — devnet / test-suite在 devnet 或 test-suite 环境中deployer 密钥拥有 host 链上的ProtocolConfig即onlyACLOwner的 owner 是 deployer因此可以跳过 DAO直接把 calldata 广播上链。task:proposeCoprocessorUpgrade执行相同的构建步骤然后用DEPLOYER_PRIVATE_KEY发送字节完全一致的 calldata——它是 KMS 上下文切换任务task:defineNewKmsContextAndEpoch广播路径的姊妹实现。它发送到--network指定网络上的 hostProtocolConfig合约地址可通过环境变量PROTOCOL_CONFIG_CONTRACT_ADDRESS指定或加--use-internal-proxy-address从addresses/目录读取cd host-contracts DEPLOYER_PRIVATE_KEY0x... npx hardhat --network sepolia task:proposeCoprocessorUpgrade \ --environment devnet \ --start-time $(date -u -v2H %Y-%m-%dT%H:%M:%SZ) \ --duration 30m --buffer 1h --proposal-id 1 --software-version v0.14.0 \ --use-internal-proxy-address广播前同样会执行 buffer 门禁若任一链不满足 buffer任务直接拒绝广播Refusing to broadcast。广播实现位于executeCoprocessorUpgradeProposalhost-contracts/tasks/utils/coprocessorUpgradeProposal.ts它用 deployer 钱包向目标地址发送{ to: target, data: calldata }并等待交易确认后返回交易哈希。十二、测试与验证仓库为这套逻辑提供了针对非 RPC 面的单元测试host-contracts/test/tasks/prepareCoprocessorUpgrade.ts覆盖编码往返encodeProposeCoprocessorUpgrade生成的 calldata 能被PROPOSE_UPGRADE_ABI解码还原出完全一致的proposalId、softwareVersion与各链窗口含 sepolia、amoy 两条链与 gateway输入校验parseCoprocessorUpgradeInputs对非法--proposal-id非整数、≤ 0与空--software-version的拒绝行为buffer 门禁bufferViolations正确列出不满足 buffer 的链与 gateway。窗口计算本身依赖真实 RPC由工作流覆盖因此测试刻意避开 RPC只验证与网络无关的纯逻辑面。合约层的CoprocessorUpgradeProposed事件与各类 revert 分支的完整行为可在 host-contracts/test/protocolConfig/protocolConfig.t.sol 中找到对应用例可作为理解链上校验的补充阅读材料。结语coprocessor 升级是 fhEVM 多链体系中的关键治理动作它把新版本发布与多链gateway 同步切换通过 Aragon DAO 提案串成一条可审计、可回放的闭环。掌握本 runbook 的四个要点——正确设置时间参数start-time/duration/buffer、理解区块窗口的投影与 buffer 门禁、区分 DAO 路径与 no-DAO 路径、善用本地演练与排障表——即可安全、可重复地完成每一次 coprocessor 链上升级。【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考