ARTICLE DETAIL

资讯详情

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

FHEVM Relayer SDK 实战指南:通过 Zama Relayer 与全同态加密智能合约交互

FHEVM Relayer SDK 实战指南:通过 Zama Relayer 与全同态加密智能合约交互 FHEVM Relayer SDK 实战指南通过 Zama Relayer 与全同态加密智能合约交互【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevmFHEVMFully Homomorphic Encryption Virtual Machine将全同态加密引入区块链而 Relayer SDKzama-fhe/relayer-sdk是连接 dApp 与 FHEVM 的关键客户端库它让合约与用户无需直接操作 Gateway Chain仅凭 FHEVM 宿主链Host Chain上的一个钱包即可完成密文输入注册、用户解密与公开解密等全部核心流程。本文以 sdk-overview.md 为主线完整讲解 SDK 的初始化、加密输入、两类解密、CLI 工具与 Web 集成并结合当前仓库源码给出实现层面的佐证帮助你在自己的项目中快速落地端到端的隐私计算流程。1. Relayer SDK 在 FHEVM 架构中的定位FHEVM 采用多链架构FHEVM 宿主链Host Chain承载 ACL、KMSVerifier、InputVerifier 等合约与业务逻辑而 Gateway Chain 负责执行解密、输入校验等昂贵操作。如果每个 dApp 开发者都直接与 Gateway Chain 交互成本与复杂度都难以承受。Relayer SDK 正是为解决这一问题而设计。根据 sdk-overview.md 的描述SDK 让你无需直接接触 Gateway Chain即可与 FHEVM 智能合约交互FHEVM 客户端只需要一个 FHEVM 宿主链上的钱包所有与 Gateway Chain 的交互都由 SDK 通过HTTP 调用 Zama 的 Relayer完成并由 Relayer 在 Gateway Chain 上代为支付 Gas。换言之Relayer 是一个介于 dApp 与 Gateway Chain 之间的代理/预言机角色。从当前仓库源码结构看这一角色的服务端实现正是 Rust 编写的 relayer 组件其对外 HTTP 解密接口集中在 relayer/src/http 模块接口设计文档见 relayer/docs/http-api-design.md而 KMS密钥管理系统则由 kms-connector/crates/kms-worker 实现。客户端侧的加密、签名与重加密逻辑则全部封装在 SDK 内例如 sdk/js-sdk/src/core/modules/relayer/cleartext/fetchPublicDecrypt.ts 与 sdk/js-sdk/src/core/modules/relayer/cleartext/fetchUserDecryptV1.ts。说明本文介绍的是文档所描述的zama-fhe/relayer-sdk。仓库中 sdk/js-sdk 目录还维护着新一代fhevm/sdk二者接口不同迁移关系见 sdk/js-sdk/docs/migration.md下文以relayer-sdk的既有 API 为准。2. 安装与初始化创建 FhevmInstance2.1 安装在 Node.js 环境中安装 SDKnpm install zama-fhe/relayer-sdk若在 Web 项目中使用还可使用yarn add zama-fhe/relayer-sdk或pnpm add zama-fhe/relayer-sdk详见下文 Web 集成一节。2.2 完整初始化配置SDK 的使用需要一个 setup 阶段实例化FhevmInstance。该对象持有与 FHEVM经 Relayer交互所需的全部配置与方法通过createInstance创建import { createInstance } from zama-fhe/relayer-sdk; const instance await createInstance({ // ACL_CONTRACT_ADDRESS (FHEVM Host chain) aclContractAddress: 0x687820221192C5B662b25367F70076A37bc79b6c, // KMS_VERIFIER_CONTRACT_ADDRESS (FHEVM Host chain) kmsContractAddress: 0x1364cBBf2cDF5032C47d8226a6f6FBD2AFCDacAC, // INPUT_VERIFIER_CONTRACT_ADDRESS (FHEVM Host chain) inputVerifierContractAddress: 0xbc91f3daD1A5F19F8390c400196e58073B6a0BC4, // DECRYPTION_ADDRESS (Gateway chain) verifyingContractAddressDecryption: 0xb6E160B1ff80D67Bfe90A85eE06Ce0A2613607D1, // INPUT_VERIFICATION_ADDRESS (Gateway chain) verifyingContractAddressInputVerification: 0x7048C39f048125eDa9d678AEbaDfB22F7900a29F, // FHEVM Host chain id chainId: 11155111, // Gateway chain id gatewayChainId: 55815, // Optional RPC provider to host chain network: https://eth-sepolia.public.blastapi.io, // Relayer URL relayerUrl: https://relayer.testnet.zama.cloud, });各配置项的含义与作用如下表所示配置项所属链作用aclContractAddressHost ChainACL访问控制列表合约地址用户解密前需确认密文的 ACL 授权对应 host-contracts/contracts/ACL.solkmsContractAddressHost ChainKMSVerifier 合约地址用于校验 KMS 相关签名对应 host-contracts/contracts/KMSVerifier.solinputVerifierContractAddressHost ChainInputVerifier 合约地址校验输入密文及其零知识证明对应 host-contracts/contracts/InputVerifier.solverifyingContractAddressDecryptionGateway ChainDecryption 合约地址公开解密验证合约对应 gateway-contracts/contracts/Decryption.solverifyingContractAddressInputVerificationGateway ChainInputVerification 合约地址对应 gateway-contracts/contracts/InputVerification.solchainIdHost ChainFHEVM 宿主链的链 IDSepolia 为11155111gatewayChainIdGateway ChainGateway 链的链 ID固定为55815networkHost Chain可选宿主链 RPC Provider如window.ethereum或 RPC URLrelayerUrl—Relayer 的 HTTP 服务地址2.3 使用内置 Sepolia 配置如果目标环境是 Zama 维护的 Sepolia FHEVM 与 Relayer可以直接使用内置的SepoliaConfig预设一行完成初始化import { createInstance, SepoliaConfig } from zama-fhe/relayer-sdk; const instance await createInstance(SepoliaConfig);关于 Sepolia FHEVM 与关联 Relayer 的完整配置信息可查看仓库内的 SepoliaConfig 合约SDK 生成配置的合约侧来源以及文档页面 contract_addresses.md。其中gatewayChainId为55815chainId为 FHEVM 链的链 IDSepolia 为11155111。2.4 关于 initSDK在 Web 环境中使用 SDK 前需要先通过initSDK()加载 TFHE 的 WASM 模块详见 webapp.mdimport { initSDK } from zama-fhe/relayer-sdk/bundle; const init async () { await initSDK(); // 加载所需 WASM };initSDK负责在运行时加载 TFHE 加密库的 WASM 二进制是创建实例前必须完成的一步。3. 输入注册向 FHEVM 注册加密数据3.1 核心流程输入注册Input registration用于将明文在客户端加密为密文并注册到 FHEVM之后合约便可通过FHE.fromExternalSolidity 函数在链上使用这些密文。所有用于 FHEVM 的值都使用协议公钥加密。// 创建用于加密和注册到 fhevm 的 buffer const buffer instance.createEncryptedInput( // 允许与该 fresh 密文交互的合约地址 contractAddress, // 允许向 contractAddress 合约导入密文的实体地址 userAddress, ); // 使用对应的数据类型方法添加数值 buffer.add64(BigInt(23393893233)); buffer.add64(BigInt(1)); // buffer.addBool(false); // buffer.add8(BigInt(43)); // buffer.add16(BigInt(87)); // buffer.add32(BigInt(2339389323)); // buffer.add128(BigInt(233938932390)); // buffer.addAddress(0xa5e1defb98EFe38EBb2D958CEe052410247F4c80); // buffer.add256(BigInt(2339389323922393930)); // 加密数值、生成对应的知识证明并通过 relayer 上传密文。 // 该操作将返回密文句柄ciphertext handles列表。 const ciphertexts await buffer.encrypt();add*系列方法覆盖了 FHEVM 支持的常见类型包括布尔addBool、8/16/32/64/128/256 位整数add8add256以及地址addAddress。encrypt()是一个网络往返操作客户端本地完成加密并生成知识证明proof of knowledge后经 Relayer 上传密文最终返回ciphertexts.handles密文句柄列表顺序与add*的调用顺序一致ciphertexts.inputProof输入证明用于合约端验证密文确实由合法协议公钥加密生成。3.2 合约端配合FHE.fromExternal以合约MyContract为例它实现了接收两个 fresh 密文并做加法contract MyContract { ... function add( externalEuint64 a, externalEuint64 b, bytes calldata proof ) public virtual returns (euint64) { return FHE.add(FHE.fromExternal(a, proof), FHE.fromExternal(b, proof)) } }externalEuint64是外部密文类型FHE.fromExternal(a, proof)会先验证proof再把外部密文转换为链上可计算的euint64。3.3 链上调用使用ethers调用上述合约my_contract为合约实例my_contract.add(ciphertexts.handles[0], ciphertexts.handles[1], ciphertexts.inputProof);可以看到handles[0]、handles[1]依次对应合约参数a、b而inputProof对应最后一个bytes calldata proof参数。从底层看输入注册的合法性校验链路贯穿三条链客户端生成证明 → Relayer 上传并交由 Gateway 链的 InputVerification 验证对应 gateway-contracts/contracts/InputVerification.sol→ 合约调用时由宿主链 InputVerifier 复核对应 host-contracts/contracts/InputVerifier.sol。4. 用户解密User Decryption4.1 适用场景用户解密适用于让单个用户安全地访问并解密自己的私有数据如余额、计数器同时保持数据机密性的场景。其核心诉求是用户要读取自己的数据但明文不应暴露在区块链上。FHEVM 的用户解密机制允许在不暴露明文的前提下把加密数据在新公钥下安全地共享或复用。在需要把密文在合约、dApp 或用户之间转移且保持机密性的场景下这一特性不可或缺。4.2 工作原理用户解密的过程是先从区块链上取回密文句柄再在客户端执行用户解密。本质上是把 KMS 加密的数据解密后再用用户的公钥重新加密因此只有该用户能访问信息。数据始终保持在区块链 FHE 密钥加密状态但可以安全地以用户 NaCl 公钥重加密后共享给用户。该流程由Relayer与KMS密钥管理系统协同完成分为两步通过合约的 view 函数从链上取回密文在客户端用用户公钥重加密密文确保只有用户本人能解密。4.3 Step 1从链上取回密文在智能合约中实现一个 view 函数返回密文句柄import fhevm/solidity/lib/FHE.sol; contract ConfidentialERC20 { ... function balanceOf(account address) public view returns (euint64) { return balances[msg.sender]; } ... }这里balanceOf返回存储在链上的用户加密余额句柄——句柄是底层密文的标识符。⚠️ 注意用户要能够对某个密文执行用户解密也称重加密该密文所在合约必须先通过 Solidity 的FHE.allow(ciphertext, address)函数正确设置 ACL访问控制。详见仓库文档 ACL 指南。4.4 Step 2客户端解密拿到密文句柄后使用zama-fhe/relayer-sdk在客户端完成用户解密前提是已按第 2 节创建FhevmInstance// instance: [FhevmInstance] from zama-fhe/relayer-sdk // signer: [Signer] from ethers (could a [Wallet]) // ciphertextHandle: [string] // contractAddress: [string] const keypair instance.generateKeypair(); const handleContractPairs [ { handle: ciphertextHandle, contractAddress: contractAddress, }, ]; const startTimeStamp Math.floor(Date.now() / 1000).toString(); const durationDays 10; // String for consistency const contractAddresses [contractAddress]; const eip712 instance.createEIP712(keypair.publicKey, contractAddresses, startTimeStamp, durationDays); const signature await signer.signTypedData( eip712.domain, { UserDecryptRequestVerification: eip712.types.UserDecryptRequestVerification, }, eip712.message, ); const result await instance.userDecrypt( handleContractPairs, keypair.privateKey, keypair.publicKey, signature.replace(0x, ), contractAddresses, signer.address, startTimeStamp, durationDays, ); const decryptedValue result[ciphertextHandle];这段代码的关键要素generateKeypair()生成一次性传输密钥对transport keypair公钥用于重加密私钥只留在客户端绝不离开用户设备createEIP712signTypedData构造并签署一份 EIP-712 类型的解密许可permit声明允许对哪些合约的密文、在什么时间窗口startTimeStamp起durationDays天内执行解密并由数据的拥有者签名userDecrypt(...)携带密文句柄、密钥对与签名调用 RelayerRelayer 协同 KMS 完成解密后用用户公钥重加密客户端用私钥还原明文。返回结果是一个以密文句柄为键的对象result[ciphertextHandle]即解密后的值。从源码层面看该流程的客户端实现在 sdk/js-sdk/src/core/modules/relayer/cleartext/fetchUserDecryptV1.tsRelayer 端对应的解密请求处理位于 relayer/src/http 模块。KMS 侧的密钥管理与重加密实现见 kms-connector/crates/kms-worker。5. 公开解密Public Decryption5.1 适用场景公开解密用于让所有人看到某个密文中的值例如私有拍卖的结果。公开解密同样通过 Relayer SDK 完成SDK 通过 HTTP 端点请求解密Relayer 返回明文值以及一份可在链上验证的加密学证明。5.2 HTTP 公开解密// 需要解密的密文句柄列表 const handles [ 0x830a61b343d2f3de67ec59cb18961fd086085c1c73ff0000000000aa36a70000, 0x98ee526413903d4613feedb9c8fa44fe3f4ed0dd00ff0000000000aa36a70400, 0xb837a645c9672e7588d49c5c43f4759a63447ea581ff0000000000aa36a70700, ]; // 解密后的值列表 // { // 0x830a61b343d2f3de67ec59cb18961fd086085c1c73ff0000000000aa36a70000: true, // 0x98ee526413903d4613feedb9c8fa44fe3f4ed0dd00ff0000000000aa36a70400: 242n, // 0xb837a645c9672e7588d49c5c43f4759a63447ea581ff0000000000aa36a70700: 0xfC4382C084fCA3f4fB07c3BCDA906C01797595a8 // } const values instance.publicDecrypt(handles);从返回示例可以看到同一个方法可以批量解密多种类型true布尔、242nbigint 整数、地址字符串等返回对象以密文句柄为键。其客户端实现在 sdk/js-sdk/src/core/actions/base/decryptPublicValues.ts 与 sdk/js-sdk/src/core/modules/relayer/cleartext/fetchPublicDecrypt.ts。5.3 链上验证通过 Relayer SDK 取得解密值后可以在链上使用FHE.checkSignatures()验证解密证明。完整的链上工作流包含合约通过FHE.makePubliclyDecryptable()将某个密文标记为公开可解密任何人均可调用 SDK 的publicDecrypt获取明文与证明使用FHE.checkSignatures()在链上验证证明确保明文确实由合法阈值签名集生成。仓库中提供了开箱即用的可公开解密示例合约见 library-solidity/examples/MakePubliclyDecryptable.sol 与 library-solidity/examples/OnchainPublicDecrypt.sol其测试用例位于 library-solidity/test/onchainPublicDecrypt。6. 使用 CLI 加密数据fhevm命令行工具提供了一种简单高效的加密方式可直接为机密智能合约加密整数与布尔值。6.1 安装确保系统已安装 Node.js然后全局安装zama-fhe/relayer-sdknpm install -g zama-fhe/relayer-sdk安装完成后通过relayer命令访问 CLI可用以下命令验证安装并查看可用命令relayer help6.2 语法relayer encrypt --node NODE_URL CONTRACT_ADDRESS USER_ADDRESS DATA:TYPE...参数说明--node区块链节点的 RPC URL例如http://localhost:8545CONTRACT_ADDRESS与加密数据交互的合约地址USER_ADDRESS与加密数据关联的用户地址DATA:TYPE待加密数据及其类型后缀:64表示 64 位整数:1表示布尔值6.3 示例为合约0x8Fdb26641d14a80FCCBE87BF455338Dd9C539a50、用户0xa5e1defb98EFe38EBb2D958CEe052410247F4c80加密 64 位整数71721075和布尔值1relayer encrypt 0x8Fdb26641d14a80FCCBE87BF455338Dd9C539a50 0xa5e1defb98EFe38EBb2D958CEe052410247F4c80 71721075:64 1:1CLI 的encrypt/user-decrypt/public-decrypt等子命令在仓库中的实现位于 sdk/cli-js-sdk/packages/cli/src/cli/commands其中 public-decrypt.ts 与 user-decrypt.ts 可供进一步阅读。7. 在 Web 应用中集成 SDKzama-fhe/relayer-sdk由多个文件组成包含 WASM 文件与 WebWorker自行打包这些组件比较繁琐。官方推荐使用 CDN尤其适合带服务端渲染SSR的 dApp。7.1 使用 UMD CDN在项目顶部引入script srchttps://cdn.zama.ai/relayer-sdk-js/0.2.0/relayer-sdk-js.umd.cjs typetext/javascript/script如果已通过 npm 安装zama-fhe/relayer-sdk也可以使用 bundle 导入import { initSDK, createInstance, SepoliaConfig } from zama-fhe/relayer-sdk/bundle;7.2 使用 ESM CDNscript typemodule import { initSDK, createInstance, SepoliaConfig } from https://cdn.zama.ai/relayer-sdk-js/0.2.0/relayer-sdk-js.js; await initSDK(); const config { ...SepoliaConfig, network: window.ethereum }; config.network window.ethereum; const instance await createInstance(config); /script7.3 使用 npm 包# Using npm npm install zama-fhe/relayer-sdk # Using Yarn yarn add zama-fhe/relayer-sdk # Using pnpm pnpm add zama-fhe/relayer-sdkzama-fhe/relayer-sdk采用 ESM 格式需要在package.json中设置type: module。如果你的 Node 项目使用type: commonjs或未设置 type可以通过import { createInstance } from zama-fhe/relayer-sdk/web;强制加载 web 版本。import { initSDK, createInstance, SepoliaConfig } from zama-fhe/relayer-sdk;7.4 三步完成集成Step 1初始化 WASM。使用库前需要先通过initSDK加载 TFHE 的 WASMimport { initSDK } from zama-fhe/relayer-sdk/bundle; const init async () { await initSDK(); // Load needed WASM };Step 2创建实例。WASM 加载完成后创建实例import { initSDK, createInstance, SepoliaConfig } from zama-fhe/relayer-sdk/bundle; const init async () { await initSDK(); // Load FHE const config { ...SepoliaConfig, network: window.ethereum }; return createInstance(config); }; init().then((instance) { console.log(instance); });Step 3使用实例。之后即可用该实例 注册加密输入、执行 用户解密 或 公开解密。8. Webpack 常见错误排查在 Webpack 环境中集成时可能遇到以下四类典型问题均可在 webpack.md 中找到对应解法。8.1 Cant resolve tfhe_bg.wasm报错信息Module not found: Error: Cant resolve tfhe_bg.wasm原因代码库中存在new URL(tfhe_bg.wasm)Webpack 会尝试解析该文件。解决方案在webpack.config.js中为该文件添加 fallbackresolve: { fallback: { tfhe_bg.wasm: require.resolve(tfhe/tfhe_bg.wasm), }, },8.2 Buffer not defined报错信息ReferenceError: Buffer is not defined原因浏览器环境中原生不存在 Node.js 的Buffer对象。解决方案安装对应的浏览器化 npm 包并为 Node 核心模块配置 fallbackresolve: { fallback: { buffer: require.resolve(buffer/), crypto: require.resolve(crypto-browserify), stream: require.resolve(stream-browserify), path: require.resolve(path-browserify), }, },8.3 ESM 版本导入问题原因使用 Webpack 或 Rollup 等打包器时导入会按package.json的browser字段替换为对应版本可能引发类型typing问题。解决方案若遇到类型问题可参考使用 TypeScript 5 的tsconfig.json配置若遇到其他问题可强制导入浏览器包。8.4 使用预打包版本bundle原因某些框架尤其是 SSR 框架无法正确打包该库导致构建或运行时错误。解决方案改用 预打包版本zama-fhe/relayer-sdk/bundle通过script标签嵌入并按如下方式初始化const start async () { await window.fhevm.initSDK(); // load wasm needed const config { ...SepoliaConfig, network: window.ethereum }; config.network window.ethereum; const instance window.fhevm.createInstance(config).then((instance) { console.log(instance); }); };9. 正确性与安全性要点综合以上流程使用 Relayer SDK 时有几个关键点需要把握输入证明与地址强绑定createEncryptedInput同时接收contractAddress与userAddressencrypt()生成的inputProof只对该用户 → 该合约的调用有效任何一方不同都会导致链上验证失败。因此加密时必须使用将要发起交易的合约与发送方地址。ACL 是用户解密的前提用户要对密文执行重加密解密必须先由密文所在合约通过FHE.allow(ciphertext, address)授权。相关接口与示例见 ACL 文档。私钥永不离端用户解密的传输密钥对私钥keypair.privateKey只在客户端生成与使用KMS/Relayer 只拿到公钥与签名后的解密许可这也是数据始终加密、仅用户可读的保障。解密许可需设置有效期EIP-712 消息中的startTimeStamp与durationDays限定了许可的生效时间窗口从安全角度应尽量收紧。10. 进一步阅读SDK 初始化配置createInstance与SepoliaConfig的完整说明输入注册 / 用户解密 / 公开解密三大核心操作的完整指南CLI 工具 与 Web 应用集成、Webpack 排错工具链与前端集成细节ACL 指南访问控制的 Solidity 级详解合约地址参考Sepolia 等环境的地址清单服务端实现Relayerrelayer 及其 HTTP API 设计文档、KMSkms-connector/crates/kms-worker新一代 SDKfhevm/sdk与迁移说明见 sdk/js-sdk/docs/migration.md【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表