ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

fhevm FHE 库(Solidity 加密智能合约库)架构全解析:加密数据类型、FHE 运算与 ACL 访问控制

fhevm FHE 库(Solidity 加密智能合约库)架构全解析:加密数据类型、FHE 运算与 ACL 访问控制 fhevm FHE 库Solidity 加密智能合约库架构全解析加密数据类型、FHE 运算与 ACL 访问控制【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevmFHEVM 的 FHE 库library-solidity是开发者编写可处理加密数据的 Solidity 智能合约的入口它把全同态加密FHE抽象为一组与原生 Solidity 类型平行的加密类型与运算符让开发者无需任何密码学知识即可构建隐私合约。本文基于 docs/protocol/architecture/library.md 展开逐层讲解加密数据类型、FHE 运算的符号执行机制、select分支、外部加密输入验证、ACL 访问控制与伪随机数生成并结合仓库源码FHE.sol、Impl.sol 等剖析其底层实现。读完你将掌握如何在合约中声明加密状态变量、如何把明文合约改造成加密合约以及这些操作背后链上发指令、链下 Coprocessor 算的完整调用链。什么是 FHEVM 库FHEVM 库即仓库中的library-solidity目录核心为 library-solidity/lib/FHE.sol是 Zama Protocol 面向合约开发者提供的抽象层它把底层基于 TFHE 的全同态加密计算封装成与标准 Solidity 开发流程兼容的接口。开发者可以在合约中直接使用加密数据类型、算术/逻辑/条件运算、细粒度访问控制以及带认证的安全输入处理而无需关心密码学细节。它在架构上充当桥梁角色合约通过 FHE 库把加密运算指令发往链上的FHEVMExecutor 宿主合约Coprocessor真正的 FHE 密文计算在链下由Coprocessors完成ACL 状态则由Gateway等链下组件同步维护。这一点在 Impl.sol 中体现得最直观——CoprocessorConfig结构体只需三个地址即可完成接线struct CoprocessorConfig { address ACLAddress; address CoprocessorAddress; address KMSVerifierAddress; }对应到 docs/protocol/architecture/overview.md 描述的整体架构FHE 库是智能合约与 Host ContractsACL、FHEVMExecutor、KMSVerifier等之间的唯一交互入口。生产环境中开发者通常不需要手工填写这些地址仓库提供了 library-solidity/config/ZamaConfig.sol按block.chainid自动路由到 Ethereum 主网1、Polygon137、Sepolia11155111、Polygon Amoy80002以及本地 Hardhat/Anvil31337未知链上会抛出ZamaProtocolUnsupported错误继承ZamaEthereumConfig的合约会在构造函数中自动调用FHE.setCoprocessor。加密数据类型Encrypted Data TypesFHE 库为常见 Solidity 类型引入了加密变体实现为 Solidity 的用户自定义值类型user-defined value types。这些类型在链上只是一个 32 字节的bytes32handle——它不存储密文本身而是指向存储在链下 Coprocessor 处的密文值详见 docs/solidity-guides/handles.md 中关于 handle 与 plaintext/ciphertext 的区分。类别类型布尔ebool无符号整数euint8,euint16, ...,euint256有符号整数eint8,eint16, ...,eint256地址eaddress仓库中 library-solidity/lib/FheType.sol 的FheType枚举完整记录了底层支持的类型矩阵包括Uint4~Uint2048、Int2~Int2048、AsciiString等内部类型。面向合约开发者的公开类型及其支持的运算符见 docs/solidity-guides/types.md 中的表格要点如下ebool2 位支持and、or、xor、eq、ne、not、select、randeuint8~euint128支持全套运算符add、sub、mul、div、rem、and、or、xor、shl、shr、rotl、rotr、eq、ne、ge、gt、le、lt、min、max、neg、not、select、rand、randBoundedeuint160是eaddress的底层表示仅支持eq、ne、selecteuint256支持位运算、比较、neg、not、select与随机数但不支持add/sub/mul256 位密文做算术代价过高。两个重要的类型语义源码与文档均可印证算术是 unchecked回绕的加密整数上的算术运算不做溢出检查溢出时静默回绕。这是刻意的设计——避免通过错误检测泄露操作数信息见 docs/solidity-guides/types.md。div/rem的右操作数必须是明文标量Impl.sol中div与rem的实现把scalarByte硬编码为0x01Impl.sol对加密 rhs 的调用会在执行时 panic。此外FHE 库为每个类型提供了isInitialized纯函数FHE.sol通过检查 handle 是否为0判断加密变量是否已初始化可在require中使用防止使用未初始化的值。FHE 运算链上符号执行与链下真实计算每种加密类型都支持与其明文对应物类似的运算算术add、sub、mul、div、rem、neg、逻辑and、or、xor、not、比较lt、gt、le、ge、eq、ne、min、max以及位操作shl、shr、rotl、rotr。运算的底层执行方式这些运算在链上是符号执行的FHE 库生成新的 handle 并发出事件链下 Coprocessor 侦听事件后执行真正的 FHE 计算。以 Impl.sol 中add的实现为例function add(bytes32 lhs, bytes32 rhs, bool scalar) internal returns (bytes32 result) { bytes1 scalarByte; if (scalar) { scalarByte 0x01; } else { scalarByte 0x00; } CoprocessorConfig storage $ getCoprocessorConfig(); result IFHEVMExecutor($.CoprocessorAddress).fheAdd(lhs, rhs, scalarByte); }可以看到所有二元运算都遵循同一个模式先从固定的 storage 槽位COPROCESSOR_CONFIG_LOCATION读取CoprocessorConfig然后调用宿主合约IFHEVMExecutor上对应的fheXxx方法完整接口清单见 Impl.sol包含fheAdd~fheMax、fheNeg、fheNot、fheIfThenElse、fheRand、fheRandBounded、fheSum、fheIsIn、fheMulDiv、cast、trivialEncrypt、verifyInput等。scalarByte参数区分加密操作数0x00与明文标量操作数0x01也就是说FHE.add(x, 42)这类密文 明文混合运算是被支持的——FHE 库为每种二元运算都生成了加密×加密、加密×标量、标量×加密等多重重载。运算符与底层fheXxx方法的映射关系由代码生成器统一维护见 library-solidity/codegen/src/operators.ts其中每个算子声明了hasScalar是否支持标量、hasEncrypted是否支持密文操作数、arguments一元/二元、returnType、fheLibName以及移位/旋转等特殊标记。FHE 库本体library-solidity/lib/FHE.sol正是由 library-solidity/codegen/src/templateFHEDotSol.ts 基于这些算子与类型元数据生成通过generateFHEOperators与generateSolidityACLMethods填充模板占位符因此各类型间的行为保持严格一致。示例来自原文档可直接编译运行function compute(euint64 x, euint64 y, euint64 z) public returns (euint64) { euint64 result FHE.mul(FHE.add(x, y), z); return result; }由符号执行衍生的事实约束由于 handle 是计算指令的产物而非密文本体docs/solidity-guides/handles.md 明确告诫开发者协议只保证handle 相等 ⇒ 明文相等与明文不同 ⇒ handle 不同不保证相同运算、相同输入 ⇒ 相同 handle协议会在 handle 的生成中混入上一区块哈希因此跨区块相同计算会得到不同 handle。需要比较两个加密值是否相等时应当使用FHE.eq(a, b)得到可解密的ebool而不是比较 handle 本身。这一handle 是不透明名签的语义是理解 FHEVM 合约编程的关键前提。用 select 实现加密条件下的分支加密布尔值无法直接用于if或require语句——一旦把ebool解引用为明文做分支就会泄露条件本身。FHE 库提供的解决方案是select算子底层为fheIfThenElse见 Impl.sol它把ifTrue与ifFalse两个密文按条件密文选择其一从结果上模拟了条件分支但不暴露实际走了哪条分支ebool condition FHE.lte(x, y); euint64 result FHE.select(condition, valueIfTrue, valueIfFalse);这里condition、valueIfTrue、valueIfFalse全部保持加密状态select返回的result在两条路径上都是合法密文外部观察者无法从 gas 消耗或事件中推断条件真值。加密 ERC20 示例 library-solidity/examples/EncryptedERC20.sol 大量运用了这一模式例如_transfer内部ebool canTransfer FHE.le(amount, balances[msg.sender]); // 加密比较 euint64 transferValue FHE.select(isTransferable, amount, FHE.asEuint64(0)); euint64 newBalanceTo FHE.add(balances[to], transferValue); euint64 newBalanceFrom FHE.sub(balances[from], transferValue);值得注意的是示例中还演示了FHE.select(isTransferable, FHE.sub(currentAllowance, amount), currentAllowance)的用法——用 select 在扣减成功与保持不变两个加密候选值之间选择从而在密文域内完成余额/额度的条件更新。更复杂的多路分支可以通过嵌套 select 组合实现此外 FHE 库还提供FHE.ifThenElse语义等价物底层均映射到fheIfThenElse。处理外部加密输入external 类型与 fromExternal用户链下加密或从其他链桥接的输入不能直接当作 handle 使用。合约函数应把它们声明为externalEbool、externalEaddress、externalEuintXX类型本质是输入在证明中的索引并额外携带一个bytes参数承载密文与零知识证明ZKPoK。ZKPoK 用于证明用户确实知道密文背后的明文防止重放与滥用详见 docs/solidity-guides/inputs.md。FHE.fromExternal负责校验证明并从外部输入中提取出可用的加密 handlefunction handleInput(externalEuint64 param1, externalEbool param2, bytes calldata attestation) public { euint64 val FHE.fromExternal(param1, attestation); ebool flag FHE.fromExternal(param2, attestation); }原文档称第二个参数为coprocessor signatures (attestation)结合源码看它就是包含密文与认证证明的bytes输入。从实现层面看Impl.verifyImpl.sol做了两件事function verify(bytes32 inputHandle, bytes memory inputProof, FheType toType) internal returns (bytes32 result) { CoprocessorConfig storage $ getCoprocessorConfig(); result IFHEVMExecutor($.CoprocessorAddress).verifyInput(inputHandle, msg.sender, inputProof, toType); IACL($.ACLAddress).allowTransient(result, msg.sender); }即先在FHEVMExecutor.verifyInput中完成密文与证明的链上验证随后由 ACL 合约为该 handle 授予transient仅当前交易有效访问权给msg.sender这样输入者立刻就能在本次交易中使用这个外部输入。这保证只有经过授权、格式正确的密文才会被合约接受。在 Hardhat 环境中加密输入由fhevm.createEncryptedInput(contract.address, user.address)构造、addBool/add8/add64...按索引添加、encrypt()后取handles[i]与inputProof传入合约完整流程见 docs/solidity-guides/inputs.md注意输入在 TypeScript 中的构造顺序与 Solidity 函数参数顺序不必一致。ACL 访问控制FHE 库通过宿主合约维护的ACLAccess Control List管理每个 handle 的访问权限。库暴露的核心方法如下对应 Impl.sol 中的IACL接口方法语义allow(handle, address)授予持久访问权allowTransient(handle, address)仅授予当前交易内的访问权基于 EIP-1153 瞬态存储省 gasallowForDecryption(handle)使 handle 可被公开解密相当于makePubliclyDecryptableisAllowed(handle, address)查询某地址是否被允许使用该 handleisSenderAllowed(handle)检查msg.sender权限的快捷方式这些allow*方法发出的事件会被链下 Coprocessor 消费用于在 Gateway 中复制 ACL 状态从而支撑链下的解密与计算协调。仓库还在 ACL 中提供了更多管理能力见 docs/solidity-guides/acl/README.mdallowThis等价于allow(handle, address(this))授权当前合约在后续交易中复用 handle、isPubliclyDecryptable、isAccountDenied黑名单检查、delegateForUserDecryption/revokeDelegationForUserDecryption用户解密权委托可设定过期时间等。ACL 的典型使用来自 EncryptedERC20.sol 的mint与_approvebalances[owner()] FHE.add(balances[owner()], mintedAmount); FHE.allowThis(balances[owner()]); FHE.allow(balances[owner()], owner());require(FHE.isSenderAllowed(amount))则在transfer/transferFrom等入口先校验调用者对该密文 handle 的权限防止任何人用他人的加密余额做运算。在 Impl.verify 中我们已看到 transient 授权的自动授予模式——每次把外部输入转成 handle 时FHE 库都会自动allowTransient(result, msg.sender)这是隐私与可用性之间的关键平衡点。伪随机加密数值randEuintXXFHE 库支持在链上生成伪随机加密整数适用于游戏、抽奖或随机化逻辑。两类接口randEbool()/randEuint8()/randEuint16()/randEuint32()/randEuint64()/randEuint128()/randEuint256()randEuintXX(uint bound)有上界的随机数取值区间为[0, bound - 1]底层实现直接调用宿主合约的fheRand与fheRandBoundedImpl.sol。原文档强调两点安全属性各 Coprocessor 之间确定性一致所有链下节点对同一随机请求必须得到相同结果否则无法达成一致同时对外部观察者不可区分结果是加密的无人能预测。docs/solidity-guides/operations/random.md 补充了三条实操要点必须发生在交易内随机数生成需要更新链上 PRNG 状态不能用eth_call完成上界必须是 2 的幂例如FHE.randEuint8(32)产生[0, 31]、FHE.randEuint32(65536)产生[0, 65535]每次调用都会消耗 gas在 gas 敏感合约中应优化使用。仓库示例 library-solidity/examples/Rand.sol 展示了完整的实战用法——声明各类随机加密状态变量构造函数中FHE.setCoprocessor(CoprocessorSetup.defaultConfig())生成后调用FHE.allowThis(value)让合约自己保留权限function generate64UpperBound(uint64 upperBound) public { value64 FHE.randEuint64(upperBound); FHE.allowThis(value64); }在代码生成器一侧随机数相关的确定性由 library-solidity/codegen/src/pseudoRand.ts 体现它维护一组固定的 128 位随机种子表并配合计数器产生确定性比特流用于在开发/测试环境的模拟执行中复现与链下一致的随机行为。进阶能力与完整示例除原文档列出的六类特性外仓库还提供了一批值得关注的扩展能力均有源码与示例佐证类型转换与平凡加密FHE.asEuintXX/asEbool/asEaddress即cast如从euint8升到euint64见 Impl.sol以及FHE.asEuintXX(plaintext)的平凡加密trivialEncryptImpl.sol用于把已知明文常量带入密文域参与运算批量运算FHE.sum(uint[])fheSum、FHE.isIn(value, values)fheIsIn密文成员判定返回ebool、FHE.mulDiv(f1, f2, d)fheMulDiv中间位宽放大的乘法除法组合见 Impl.sol链上公开解密验证FHE 库通过FHE.checkPublicDecryption等函数配合PublicDecryptionVerified事件FHE.sol与 KMS 签名KMSVerifierEIP-712 阈值签名验证在链上确认公开解密结果的真实性跨链桥接ConfidentialBridge支持把加密 handle 连同密文桥接到其他链MessagingFeeLZ/MessagingReceiptLZ是 LayerZero 消息结构的 ABI 兼容拷贝见 Impl.sol对应示例见 library-solidity/examples/bridge/ConfidentialMultiChainToken.sol 与 ConfidentialMultiChainRandomGenerator.sol完整可运行示例仓库 library-solidity/examples 目录提供了 Counter.sol加密计数器、EncryptedERC20.sol加密 ERC20、HeadsOrTails.sol、Rand.sol、OnchainPublicDecrypt.sol 等对应测试位于 library-solidity/test如 test/encryptedERC20可参考其调用方式验证合约行为。小结FHEVM 的 FHE 库把全同态加密包装成了 Solidity 开发者熟悉的心智模型用euintXX/ebool/eaddress声明加密状态用FHE.add/sub/mul/...做密文运算用FHE.select处理条件逻辑用FHE.fromExternal安全接收用户加密输入用 ACL 家族方法控制每个 handle 的访问边界用randEuintXX生成不可预测的加密随机数。其核心机制是链上符号执行 链下真实计算合约只生成 handle 并发出指令真正的 FHE 计算由 Coprocessor 完成安全性与一致性则由 KMS 签名、输入 ZKPoK 与 ACL 事件复制共同保障。如需深入实践建议按顺序阅读 docs/solidity-guides/types.md类型与运算符矩阵、docs/solidity-guides/handles.mdhandle 语义、docs/solidity-guides/inputs.md外部输入、docs/solidity-guides/acl/README.mdACL与 docs/solidity-guides/configure.md配置并结合 library-solidity/examples 下的完整合约逐步改造你自己的隐私应用。【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表