实战指南)
fhevm Gateway 协议暂停机制Pausing Mechanism实战指南【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm导读本指南系统讲解 fhevm Gateway 协议的暂停Pause与恢复Unpause机制当协议出现紧急状况如安全事件、密钥泄露、升级过渡期时如何通过预授权的 pauser 账户快速冻结新的输入证明input proof与解密decryption请求同时保证已提交请求的响应链路与链上 view 查询不受影响。阅读本文后你将掌握PauserSet/Pausable合约的权限模型、被暂停的精确函数清单、GatewayConfig聚合暂停的实现原理以及如何用仓库内置的 Hardhat 任务与PAUSER_PRIVATE_KEY/DEPLOYER_PRIVATE_KEY环境变量完成一轮完整的暂停—恢复操作。1. 暂停机制概览为什么需要紧急刹车fhevm Gateway 协议对外承担两类关键职责验证用户的输入证明Input Verification与处理链上的解密请求Decryption。这两条链路一旦被恶意请求冲击可能影响整个 Gateway 服务的可用性甚至资金安全。因此协议设计了一套只允许人工触发的紧急暂停开关The Gateway can only be paused and unpaused manually暂停是单向门只有预注册的 pauser 账户可以暂停且暂停后所有新的request类交易都会立即 revert暂停不阻断存量请求已经发送并上链的请求其响应仍然会被接受进行中的共识on-going consensus可以继续达成view 函数不受影响只读查询依旧可调用便于暂停期间排查问题恢复权限更高只有GatewayConfig合约的 owner或GatewayConfig合约自身能够解除暂停避免 pauser 误操作导致协议无法恢复。该机制由两个合约配合实现详见 PauserSet 合约文档合约类型职责PauserSet不可升级immutable合约管理谁可以暂停的账户白名单Pausable抽象合约abstract提供pause()/unpause()核心逻辑被各 Gateway 合约继承2. 可暂停的合约与暂停后的行为语义2.1 哪些合约可被暂停pauser 账户可以暂停以下两个 Gateway 合约Decryption解密请求入口InputVerification输入证明验证入口其他 Gateway 合约如CiphertextCommits、GatewayConfig、KMSGeneration在技术上也继承了Pausable但当前版本没有对外暴露任何whenNotPaused修饰的请求函数因此pauseAllGatewayContracts不会也无需暂停它们——这一设计取舍在 pauseContracts.ts 的注释中有明确说明。2.2 暂停后的行为语义一个合约被暂停意味着任何触发其请求request类函数的交易都会 revert。同时保证对已发送请求的响应交易仍被接受网关后台仍可提交解密结果/证明响应进行中的共识流程可以正常收敛所有 view 函数读取类继续可调用。该语义直接来自 OpenZeppelin 的PausableUpgradeable状态机paused true时带whenNotPaused修饰符的函数全部回滚。3. 被暂停的确切函数清单源码级验证3.1 Decryption 合约当Decryption被暂停时以下函数会 revert在 Decryption.sol 中均带whenNotPaused修饰符函数源码位置功能publicDecryptionRequestDecryption.sol#L332公钥公开解密请求userDecryptionRequestDecryption.sol#L466用户私钥解密请求delegatedUserDecryptionRequestDecryption.sol#L560委托式用户解密请求如 委托解密指南 场景3.2 InputVerification 合约当InputVerification被暂停时以下函数会 revert见 InputVerification.sol#L190函数源码位置功能verifyProofRequestInputVerification.sol#L190提交输入证明的验证请求也就是说暂停后任何新的加密输入ciphertext input都无法进入协议同时任何新的解密请求都无法发起——这正是冻结新请求这一设计目标的精确落点。4. 权限模型源码剖析谁可以暂停、谁可以恢复4.1Pausable抽象合约双通道鉴权Pausable.sol 基于 OpenZeppelinPausableUpgradeable实现并通过硬编码的GATEWAY_CONFIG地址来自 GatewayAddresses.sol进行跨合约鉴权function pause() external virtual { if (!GATEWAY_CONFIG.isPauser(msg.sender) msg.sender ! gatewayConfigAddress) { revert NotPauserOrGatewayConfig(msg.sender); } _pause(); } function unpause() external virtual { // GatewayConfig ownerdeployer 或多签或 GatewayConfig 合约本身 if (msg.sender ! Ownable2StepUpgradeable(gatewayConfigAddress).owner() msg.sender ! gatewayConfigAddress) { revert NotOwnerOrGatewayConfig(msg.sender); } _unpause(); }关键点暂停通道pausemsg.sender必须是GatewayConfig.isPauser(addr) true的已注册 pauser或者是GatewayConfig合约地址本身用于聚合暂停恢复通道unpausemsg.sender必须是GatewayConfig的 owner由Ownable2StepUpgradeable管理见 GatewayConfig或者是GatewayConfig合约地址本身源码中通过将GatewayConfig强转为Ownable2StepUpgradeable读取 owner避免循环依赖注释中对此有专门说明。由此可得出结论有源码依据pauser 永远无法自行解除暂停恢复权始终握在 owner 手中形成暂停快、恢复受控的安全设计。4.2PauserSet不可升级合约pauser 名单管理PauserSet.sol 是一个部署后不可升级的合约其地址存储在GatewayConfig合约中提供四个管理函数接口定义见 IPauserSet.sol函数说明权限与校验源码实现addPauser(address)添加 pauser仅GatewayConfigowner 可调用拒绝零地址、拒绝重复添加AccountAlreadyPauser发出AddPauser事件removePauser(address)移除 pauser仅 owner 可调用目标必须是现有 pauserAccountNotPauser发出RemovePauser事件swapPauser(old, new)原子替换 pauser仅 owner 可调用校验旧地址是 pauser、新地址不是发出SwapPauser事件isPauser(address)查询是否 pauserview 函数GatewayConfig内部pause()鉴权时调用pauser 账户被设计为由 fhevm Gateway 协议 operators 控制的热钱包见 gateway_config.md 中的 operators 说明便于在紧急时刻快速响应。owner 添加/移除 pauser 的操作可通过仓库 tasks 目录下的 addPausers.ts、removePauser.ts、swapPauser.ts 执行相关行为由测试 PauserSet.ts 覆盖验证。5.GatewayConfig的聚合暂停一次暂停全部为了让 pauser 不需要逐个合约调用GatewayConfig合约提供了聚合入口源码见 GatewayConfig.sol#L535-L580接口定义见 IGatewayConfig.solfunction pauseAllGatewayContracts() external virtual onlyPauser { bool isDecryptionPaused DECRYPTION.paused(); bool isInputVerificationPaused INPUT_VERIFICATION.paused(); if (isDecryptionPaused isInputVerificationPaused) { revert AllGatewayContractsAlreadyPaused(); } if (!isDecryptionPaused) DECRYPTION.pause(); if (!isInputVerificationPaused) INPUT_VERIFICATION.pause(); emit PauseAllGatewayContracts(); } function unpauseAllGatewayContracts() external virtual onlyOwner { bool isDecryptionPaused DECRYPTION.paused(); bool isInputVerificationPaused INPUT_VERIFICATION.paused(); if (!isDecryptionPaused !isInputVerificationPaused) { revert AllGatewayContractsAlreadyUnpaused(); } if (isDecryptionPaused) DECRYPTION.unpause(); if (isInputVerificationPaused) INPUT_VERIFICATION.unpause(); emit UnpauseAllGatewayContracts(); }实现要点pauseAllGatewayContracts带onlyPauser修饰符——pauser 即可一键暂停Decryption与InputVerificationunpauseAllGatewayContracts带onlyOwner修饰符——只有 owner 才能一键恢复两个聚合函数都是幂等且带全量状态检查的全部已暂停时再暂停会 revertAllGatewayContractsAlreadyPaused全部未暂停时再恢复会 revertAllGatewayContractsAlreadyUnpaused避免了重复交易与 Gas 浪费由于CiphertextCommits、GatewayConfig自身暂无whenNotPaused的请求函数KMSGeneration尚未启用聚合暂停只作用于上述两个合约见 pauseContracts.ts#L104-L110 注释。6. Hardhat 任务一键暂停与恢复仓库在 tasks/pauseContracts.ts 中定义了完整的 Hardhat 任务。注意源码中注册的任务名带task:前缀文档中的简写名去掉前缀即为实际命令名。6.1 暂停任务需要PAUSER_PRIVATE_KEY文档中的任务名实际命令npx hardhat ...作用pauseAllGatewayContractstask:pauseAllGatewayContracts暂停全部可暂停的 Gateway 合约pauseInputVerificationtask:pauseInputVerification仅暂停InputVerificationpauseDecryptiontask:pauseDecryption仅暂停Decryption这些任务读取环境变量PAUSER_PRIVATE_KEY用对应 pauser 钱包调用合约见 pauseContracts.ts 中pauseSingleContract对contract.pause()的调用。# 仅暂停 Decryption 合约 PAUSER_PRIVATE_KEY0x... npx hardhat task:pauseDecryption --network network6.2 恢复任务需要DEPLOYER_PRIVATE_KEY文档中的任务名实际命令npx hardhat ...作用unpauseAllGatewayContractstask:unpauseAllGatewayContracts恢复全部已暂停的 Gateway 合约unpauseInputVerificationtask:unpauseInputVerification仅恢复InputVerificationunpauseDecryptiontask:unpauseDecryption仅恢复Decryption恢复任务读取DEPLOYER_PRIVATE_KEY因为只有GatewayConfigowner 才能调用unpause()见 pauseContracts.ts#L43-L52 中unpauseSingleContract。所有任务还支持--use-internal-proxy-address可选参数为true时使用/addresses目录中记录的内部代理地址否则读取对应的地址环境变量见 getGatewayContract。6.3 重要限制多签接管后恢复任务的失效在GatewayConfig的所有权由部署者deployer转移给多签multi-sig之后基于DEPLOYER_PRIVATE_KEY的恢复任务将无法再解除暂停。此时必须通过多签钱包调用GatewayConfig的unpauseAllGatewayContracts或对具体合约unpause来完成恢复。部署与所有权转移的完整流程可参考 本地部署指南 与 ownership.ts。7. 环境变量配置详解暂停/恢复任务依赖两个环境变量完整说明见 env_variables.md示例值来自.env.example用于本地测试环境变量描述Solidity 类型默认值PAUSER_PRIVATE_KEY任一已注册 pauser 的私钥bytes32-DEPLOYER_PRIVATE_KEY部署者账户私钥bytes32-# pauser 私钥用于执行暂停任务含 pauseAllGatewayContracts PAUSER_PRIVATE_KEY0x3588ffb4f4d9bea785a012b895543fe68f2d580a9d449decc91a25878064079a # (bytes32) # 部署者私钥用于部署合约以及在所有权未转移时执行恢复任务 DEPLOYER_PRIVATE_KEY0x7136d8dc72f873124f4eded25f3525a20f6cee4296564c76b44f1d582c57640f # (bytes32)说明每个 operator 都应将PAUSER_PRIVATE_KEY设为其热钱包pauser对应的私钥以便在紧急时快速暂停文档中给出的示例账户是通过make get-accounts生成的、已注资的 Hardhat 测试账户部署相关环境变量的完整集合见 部署环境变量文档。8. 端到端操作流程示例结合上述机制一次完整的紧急暂停 → 排查 → 恢复流程如下确认 pauser 已注册owner 通过addPauser或 addPausers.ts 任务确保紧急响应账户在PauserSet白名单内设置环境变量将 pauser 私钥填入PAUSER_PRIVATE_KEY触发暂停PAUSER_PRIVATE_KEY0x... npx hardhat task:pauseAllGatewayContracts --network network此时Decryption.publicDecryptionRequest/userDecryptionRequest/delegatedUserDecryptionRequest与InputVerification.verifyProofRequest全部开始 revert新输入与新解密请求被冻结存量请求继续消化后台对已提交请求的响应交易仍可正常上链共识正常收敛排查并恢复确认风险解除后由 owner 侧执行恢复DEPLOYER_PRIVATE_KEY0x... npx hardhat task:unpauseAllGatewayContracts --network network若所有权已转移至多签则改为通过多签发起GatewayConfig.unpauseAllGatewayContracts交易验证状态可调用各合约的paused()视图函数确认状态已恢复正常。9. 常见问题与边界情况暂停后还能提交请求吗不能带whenNotPaused的请求函数全部 revert但响应类交易与 view 调用不受影响。重复暂停/恢复会怎样聚合函数会因AllGatewayContractsAlreadyPaused/AllGatewayContractsAlreadyUnpausedrevert天然防重复。pauser 能恢复吗不能。Pausable.unpause()仅允许GatewayConfigowner 或GatewayConfig合约本身调用。GatewayConfig本身会被暂停吗当前版本它虽继承Pausable但未暴露任何whenNotPaused请求函数聚合暂停不涉及它。多签接管后如何恢复放弃 Hardhat 任务改由多签钱包直接调用GatewayConfig的unpauseAllGatewayContracts函数。10. 延伸阅读PauserSet 合约文档pauser 名单管理接口与事件Pausable 抽象合约源码暂停/恢复鉴权实现GatewayConfig 聚合暂停源码pauseAllGatewayContracts/unpauseAllGatewayContractsPauserSet 合约源码 与 IPauserSet 接口暂停任务实现 与 环境变量文档GatewayConfig 合约文档operators 与所有权模型【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考