ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

FHEVM 全同态加密下的循环与分支处理:为什么不能 break,以及如何用 FHE.select 重写控制流

FHEVM 全同态加密下的循环与分支处理:为什么不能 break,以及如何用 FHE.select 重写控制流 FHEVM 全同态加密下的循环与分支处理为什么不能 break以及如何用 FHE.select 重写控制流【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm本文是 fhEVM Solidity 开发指南中「逻辑Logics」系列的核心篇章讲解在条件或索引本身是密文encrypted时如何处理分支、循环与条件逻辑。你将理解为何基于加密条件的while循环在 FHE 下不可行、如何用「固定步数循环 FHE.select」安全等价改写、如何通过混淆交易方向来隐藏分支走向以及为什么应尽量避免使用加密索引访问数组。读完即可将普通 Solidity 的面向流程控制逻辑改写成可正确运行、且不泄露明文路径的全同态版本。背景加密条件无法驱动传统控制流在普通 Solidity 中if、while、for的跳转条件都是链上公开可读的明文布尔值EVM 可以据此决定执行路径。但在 FHEVM 中比较运算如FHE.lt、FHE.eq返回的是加密布尔类型ebool——它的真值被同态加密保护EVM 无法直接读取因此不能用作原生if/while的跳转条件。处理加密分支的标准手段是FHE.select它相当于加密版三元运算符根据一个ebool条件在两个密文值之间选择其一整个过程不揭示条件本身。关于FHE.select的基础用法含竞拍出价示例可先阅读同目录下的 分支基础文档本文在其之上进一步讨论循环、索引与分支混淆场景。为什么不能基于加密条件 break 循环❌ 在 FHE 中不可能基于加密条件来中断break一个循环。下面这类写法无法工作euint8 maxValue FHE.asEuint8(6); // Could be a value between 0 and 10 euint8 x FHE.asEuint8(0); // some code while(FHE.lt(x, maxValue)){ x FHE.add(x, 2); }原因在于FHE.lt(x, maxValue)返回的是ebool密文循环何时退出完全取决于一个链上不可见的秘密值。EVM 的执行模型要求执行路径与 Gas 消耗在交易前即可确定而加密条件下的动态控制流既无法被链上节点评估也会让 Gas 上界不可预测因此这种写法在 FHEVM 中不被支持。如果你的业务逻辑确实需要基于加密布尔条件循环官方建议优先尝试将其改写为固定步数的有限循环并在循环体内使用FHE.select。推荐方案有限步循环 FHE.select✅ 上一节的while示例可以改写为下面这样euint8 maxValue FHE.asEuint8(6); // Could be a value between 0 and 10 euint8 x FHE.asEuint8(0); // some code for (uint32 i 0; i 10; i) { euint8 toAdd FHE.select(FHE.lt(x, maxValue), FHE.asEuint8(2), FHE.asEuint8(0)); x FHE.add(x, toAdd); }这个片段执行固定 10 次迭代每次迭代只要x仍小于maxValue就给x加上 2一旦x达到maxValue由于无法 break剩余迭代改为加 0。对这段代码做逐步拆解明文循环边界for (uint32 i 0; i 10; i)的循环变量i与上界10都是公开常量EVM 可以正常驱动循环这正是「有限步数」的含义——迭代次数与任何秘密值无关。加密条件计算FHE.lt(x, maxValue)每轮都产生一个表示「x 是否仍小于 maxValue」的新ebool密文。同态选择FHE.select(条件, 加2, 加0)在条件为真时取出FHE.asEuint8(2)为假时取出FHE.asEuint8(0)两者都是密文因此选择过程不暴露 x 与 maxValue 的大小关系。同态累加FHE.add(x, toAdd)将选择结果累加进x继续下一轮。从源码看FHE.select在 library-solidity/lib/FHE.sol 中为所有加密类型提供了重载ebool、euint8、euint16、euint32、euint64、euint128、euint256和eaddress且对未初始化的操作数会先安全地补零。其底层实现在 library-solidity/lib/Impl.sol最终调用 coprocessor 的IFHEVMExecutor.fheIfThenElse(control, ifTrue, ifFalse)由链下 FHE 计算节点完成同态多路选择。需要特别留意的是每一次FHE.select与FHE.add都会产生一个全新的密文句柄即使明文数值不变句柄也会改变。这是 FHE 保证机密性的固有特性开发者在设计状态更新逻辑时必须考虑到这一点并在操作后为句柄配置 ACL 权限详见下文。最佳实践一混淆分支Obfuscate branching前一节强调分支逻辑应尽量依赖FHE.select而不是解密操作这样才能真正隐藏「哪条分支被执行」。但仅做到这一点有时仍不够——提升智能合约的隐私性往往要求重新审视应用逻辑本身。例如基于线性恒定函数、针对两个加密 ERC20 代币实现一个简单 AMM 时不仅应隐藏被交换的数量还应隐藏被交换的是哪个代币。假设 tokenA 与 tokenB 之间的汇率恒为 1下面是一个非常简化的实现示例// typically either encryptedAmountAIn or encryptedAmountBIn is an encrypted null value // ideally, the user already owns some amounts of both tokens and has pre-approved the AMM on both tokens function swapTokensForTokens( externalEuint32 encryptedAmountAIn, externalEuint32 encryptedAmountBIn, bytes calldata inputProof ) external { euint32 encryptedAmountA FHE.fromExternal(encryptedAmountAIn, inputProof); // even if amount is null, do a transfer to obfuscate trade direction euint32 encryptedAmountB FHE.fromExternal(encryptedAmountBIn, inputProof); // even if amount is null, do a transfer to obfuscate trade direction // send tokens from user to AMM contract FHE.allowTransient(encryptedAmountA, tokenA); IConfidentialERC20(tokenA).transferFrom(msg.sender, address(this), encryptedAmountA); FHE.allowTransient(encryptedAmountB, tokenB); IConfidentialERC20(tokenB).transferFrom(msg.sender, address(this), encryptedAmountB); // send tokens from AMM contract to user // Price of tokenA in tokenB is constant and equal to 1, so we just swap the encrypted amounts here FHE.allowTransient(encryptedAmountB, tokenA); IConfidentialERC20(tokenA).transfer(msg.sender, encryptedAmountB); FHE.allowTransient(encryptedAmountA, tokenB); IConfidentialERC20(tokenB).transferFrom(msg.sender, address(this), encryptedAmountA); }注意为了保密这个实现要求对两个代币都执行一次「用户 → AMM」的入金转账以及对两个代币各执行一次「AMM → 用户」的出金转账——即使绝大多数情况下encryptedAmountAIn与encryptedAmountBIn中有一个实际是加密的零值。这与经典的非保密 AMM 完全不同普通 ERC20 场景下用户只需对被卖出的代币做一次入金转账、对被买入的代币收一次出金转账。但在 FHE 场景下如果只转账被卖出的代币旁观者就能从交易流向推断出用户的方向意图买入哪个、卖出哪个从而泄露交易方向这一敏感信息。「用加密零值走完整条路径」正是为了把分支走向抹平让链上观察者无法区分哪一侧是真实交易、哪一侧是空操作。从源码佐证来看这种「转账 ACL 授权」的组合正是 FHEVM 加密代币的标准实现模式。仓库中的 library-solidity/examples/EncryptedERC20.sol 展示了生产级写法_updateAllowance用FHE.select(isTransferable, FHE.sub(currentAllowance, amount), currentAllowance)选择是否扣减授权额度_transfer用FHE.select(isTransferable, amount, FHE.asEuint64(0))决定实际转移量并对新余额调用FHE.allowThis与FHE.allow设置权限。其底层 ACL 实现可追溯至 library-solidity/lib/Impl.solallowTransient只在当前交易内授权句柄使用allow则授予长期权限。在你的合约中使用FHE.select产生新句柄后务必记得同步调用这些 ACL 函数否则后续交易将因「SenderNotAllowedToUseHandle」而无法使用该句柄。最佳实践二避免使用加密索引用加密索引从数组中挑出一个元素而不暴露索引本身这种做法效率很低因为要保证机密性你仍然必须遍历所有索引、对每个索引做同态相等比较。不过文档与仓库都提到未来计划通过增加针对数组的专用运算符来大幅提升这类操作的效率。举个例子假设有一个加密数组encArray你想把加密值x更新为列表中的某一项encArray[i]同时不透露选择的是哪一项。❌ 你必须遍历所有索引并同态检查相等性但这种模式 Gas 消耗非常高昂应尽量避免euint32 x; euint32[] encArray; function setXwithEncryptedIndex(externalEuint32 encryptedIndex, bytes calldata inputProof) public { euint32 index FHE.fromExternal(encryptedIndex, inputProof); for (uint32 i 0; i encArray.length; i) { ebool isEqual FHE.eq(index, i); x FHE.select(isEqual, encArray[i], x); } FHE.allowThis(x); }这段代码的代价结构非常清晰对长度为N的数组每轮迭代都要执行一次同态相等比较FHE.eq和一次同态选择FHE.select共N次且x每轮都会产生新密文句柄最终还要FHE.allowThis(x)授权合约自身使用最终句柄。整体开销随数组长度线性增长而每个同态算子在链下 FHE 计算中都对应真实算力与 Gas 成本因此这种「用遍历换隐私」的模式应当只在小数组、低频场景下使用或者等待未来专用数组运算符落地后再迁移。小结在 FHEVM 中处理循环与条件的核心准则不要基于加密条件break或动态跳转循环EVM 无法评估密文条件Gas 上界也无法预测。要做的是把循环改写为固定步数的有限循环把「是否继续」的决策交给每轮中的FHE.select条件为真时累加真实增量条件为假时累加加密零值。FHE.select是加密三元运算符支持ebool、euint8/16/32/64/128/256、eaddress全类型底层对应 coprocessor 的fheIfThenElse同态多路选择。分支走向也需要混淆不仅是条件本身应用层的可见副作用如只转账一侧代币同样可能泄露分支信息必要时对两条路径都执行等价操作如用加密零值走完整条 AMM 路径。避免使用加密索引遍历数组同态eqselect的组合随数组长度线性膨胀、Gas 昂贵未来仓库计划引入专用数组运算符改善该场景。每次FHE.select/FHE.add都会产生新密文句柄产生后需用FHE.allowThis、FHE.allow或FHE.allowTransient正确配置 ACL否则后续交易无法使用该句柄。相关文档可按 docs/solidity-guides/SUMMARY.md 的「Logics」目录继续阅读分支基础conditions.md 与 错误处理error_handling.md底层算子实现可对照 library-solidity/lib/FHE.sol 与 library-solidity/lib/Impl.sol。【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表