fhEVM隐私区块链协议

基于fhEVM构建支持隐私交易的加密货币钱包

Chuck Chen
 · 
分类: [密码学]

TLDR

本文的项目代码开源在这里

全同态加密在区块链的应用

Zama的fhEVM近来正式在以太坊主网发布,并完成了第一笔机密USDT转账。这是一个标志性的事件,从此全同态加密在区块链有了新的应用。与EVM的整合意味着隐私保护是可编程控制,这可能会开启新的应用。

Zama官方提供了Relayer SDK,允许第三方dApp集成fhEVM的功能。所以有了这篇文章,尝试在以太坊Sepolia测试网络使用fhEVM构建一个转账金额和收款人保密的钱包。

创建项目

项目分为两部分:链上智能合约和前端。几乎所有的操作都在链上完成,所以目前没有后端服务。各部分代码以monorepo方式管理。其中:

  • frontend,dApp前端,与用户钱包和链上部署的智能合约交互,使用Relayer SDK;
  • contracts,智能合约,使用fhEVM的Solidity库完成全同态密码操作,如金额加密、解密、扣减、增加等。

前端

前端页面部署在免费层级的Cloudflare Workers平台上。为保持简单,只使用了React和Vite框架,使用官方提供的模版创建项目:

$ pnpm create cloudflare@latest frontend --framework=react
.../19b9c386a6b-abd0                     |   +1 +
.../19b9c386a6b-abd0                     | Progress: resolved 1, reused 0, downloaded 1, added 1, done
 
──────────────────────────────────────────────────────────────────────────────────────────────────────────
👋 Welcome to create-cloudflare v2.62.0!
🧡 Let's get started.
📊 Cloudflare collects telemetry about your usage of Create-Cloudflare.
 
Learn more at: https://github.com/cloudflare/workers-sdk/blob/main/packages/create-cloudflare/telemetry.md
──────────────────────────────────────────────────────────────────────────────────────────────────────────
 
╭ Create an application with Cloudflare Step 1 of 3

├ In which directory do you want to create your application?
│ dir ./frontend

├ What would you like to start with?
│ category Framework Starter

├ Which development framework do you want to use?
│ framework React

├ Select your deployment platform
│ platform Workers with Assets

├ Select a variant:
│ variant TypeScript + SWC
...
 

引入RainbowKit预构建的UI组件,通过Wagmi链接用户钱包,Sepolia链上操作通过Viem完成。

$ pnpm add @rainbow-me/rainbowkit wagmi viem

引入Zama的Relayer SDK,并初始化。

$ pnpm add @zama-fhe/relayer-sdk

智能合约

智能合约与fhEVM已经部署在Sepolia的合约交互,核心功能有:

  • 符合ERC-7984标准的机密同质化代币,封装Sepolia上的USDC代币成机密代币;
  • 支付网关合约,调用fhEVM的同态加密功能完成账户余额扣减、增加等操作。

fhEVM提供了Hardhat的项目模版(zama-ai/fhevm-hardhat-template)),可以直接点击“Use this template”创建新的项目。但在这里,我直接拉取项目模版的代码到本地,并放在contracts目录下。

如果使用了国内的npm镜像如npmmirrors,可能遇到报错“No matching version found for @nomicfoundation/slang@1.3.1 while fetching it from https://registry.npmmirror.com/”。此时需要临时切换成npm官方站:

$ pnpm i --registry https://registry.npmjs.org/

编译合约代码:

$ pnpm compile
 
> fhevm-hardhat-template@0.3.0-3 compile /Users/chuck/Projects/astra-hetu/contracts
> cross-env TS_NODE_TRANSPILE_ONLY=true hardhat compile
 
Generating typings for: 30 artifacts in dir: types for target: ethers-v6
Successfully generated 106 typings!
Compiled 28 Solidity files successfully (evm target: cancun).
 
> fhevm-hardhat-template@0.3.0-3 postcompile /Users/chuck/Projects/astra-hetu/contracts
> npm run typechain
 
 
> fhevm-hardhat-template@0.3.0-3 typechain
> cross-env TS_NODE_TRANSPILE_ONLY=true hardhat typechain

运行测试:

$ pnpm test
 
> fhevm-hardhat-template@0.3.0-3 test /Users/chuck/Projects/astra-hetu/contracts
> hardhat test
 
Compiled 1 Solidity file successfully (evm target: cancun).
 
 
  Hetu Protocol
    ConfidentialUSDCWrapper
      Deployment
 should have correct name
 should have correct symbol
 should have correct underlying token
 should have 6 decimals matching USDC
 should have 1:1 conversion rate
      Wrapping USDC cUSDC
 should wrap USDC into cUSDC
 should create encrypted balance after wrap
 should decrypt to correct wrapped amount
 should allow wrapping to different recipient
 should revert on insufficient allowance
      Confidential Transfers
 should transfer encrypted tokens between users (51ms)
    HetuPaymentGateway
      Deployment
 should set correct owner
...

Hardhat默认的测试网络在内存中保存状态。也可以启动本地网络,更接近测试网络的运行情况。启动本地网络:

$ pnpm chain
 
> fhevm-hardhat-template@0.3.0-3 chain /Users/chuck/Projects/astra-hetu/contracts
> hardhat node --network hardhat --no-deploy
 
Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/
 
Accounts
========
Account #0: 0xD8C83D1C163aF2A69d77deeba0FD97FDA1C3b041 (10000 ETH)
 
Account #1: 0x92bE91002Eb44086CCee18cAD8e112c5c0dE6baA (10000 ETH)
 
Account #2: 0x47749FC0E32D821451f433b4E1Bff951eE371473 (10000 ETH)
 
Account #3: 0x479BE9b5Db5eBc457C6C01bC42a74c1DfBEebf0F (10000 ETH)
 
Account #4: 0x74EcD30B4a054800c029449110Cf9aA389753E7F (10000 ETH)
 
Account #5: 0x3d896DFea5Bf023111e0d3469C3BF608a57668E6 (10000 ETH)
...

本地网络启动后,打开另一个终端,并部署合约到本地网络:

$ pnpm deploy:localhost
 
> fhevm-hardhat-template@0.3.0-3 deploy:localhost /Users/chuck/Projects/astra-hetu/contracts
> hardhat deploy --network localhost
 
Nothing to compile
No need to generate any newer typings.
 
🌊 Hetu Deployment
Network: localhost
Deployer: 0xD8C83D1C163aF2A69d77deeba0FD97FDA1C3b041
 
📦 Deploying ConfidentialUSDCWrapper...
deploying "ConfidentialUSDCWrapper" (tx: 0x5de517bb16e55b2ff9e5a275ff5b9a799661f8536326f9b9785fa1bcafb3f238)...: deployed at 0x32103E46a0edb5F5F3509A532308755D0F6F3149 with 2102227 gas
 ConfidentialUSDCWrapper deployed at: 0x32103E46a0edb5F5F3509A532308755D0F6F3149
 
🚀 Deploying HetuPaymentGateway...
deploying "HetuPaymentGateway" (tx: 0x8d29e2542165bbac56bec708cfff15e37edf361ef364a0ef7d98faf62aa2ece9)...: deployed at 0xa3509686e6104DDf899CD06814109BbA573Bd2c3 with 2159134 gas
 
 Deployment Complete!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ConfidentialUSDCWrapper: 0x32103E46a0edb5F5F3509A532308755D0F6F3149
HetuPaymentGateway:     0xa3509686e6104DDf899CD06814109BbA573Bd2c3
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
🔑 Update frontend/src/lib/contracts.ts with these addresses

在本地网络上运行测试:

$ pnpm hardhat test --network localhost
 
 
  Hetu Protocol
    ConfidentialUSDCWrapper
      Deployment
 should have correct name
 should have correct symbol
 should have correct underlying token
 should have 6 decimals matching USDC
 should have 1:1 conversion rate
      Wrapping USDC cUSDC
 should wrap USDC into cUSDC
 should create encrypted balance after wrap
 should decrypt to correct wrapped amount (47ms)
 should allow wrapping to different recipient
 should revert on insufficient allowance
      Confidential Transfers
 should transfer encrypted tokens between users (59ms)
    HetuPaymentGateway
      Deployment
 should set correct owner
 should set correct default token
      Send Payment
 should send encrypted payment
 should update payment count
 should revert when sending to self
 should revert when sending to zero address
...

部署

部署分为两部分,其中智能合约需要实现部署,并记录部署的合约地址。在合约地址更新到前端代码后,在Cloudflare平台部署前端dApp。

智能合约

部署到Sepolia测试网络:

$ pnpm deploy:sepolia
 
> fhevm-hardhat-template@0.3.0-3 deploy:sepolia /Users/chuck/Projects/astra-hetu/contracts
> hardhat deploy --network sepolia
 
Generating typings for: 4 artifacts in dir: types for target: ethers-v6
Successfully generated 62 typings!
Compiled 3 Solidity files successfully (evm target: cancun).
 
🌊 Hetu Deployment
Network: sepolia
Deployer: 0xD8C83D1C163aF2A69d77deeba0FD97FDA1C3b041
 
📦 Deploying ConfidentialUSDCWrapper...
deploying "ConfidentialUSDCWrapper" (tx: 0x7a7432eab37a3b4afc255ec3bc2d8ca7706221dafa8e8be37d3f6675dd6738b3)...: deployed at 0xe6832A06dE93088Cd637ea35602075aEcD0f9998 with 2111934 gas
 ConfidentialUSDCWrapper deployed at: 0xe6832A06dE93088Cd637ea35602075aEcD0f9998
 
🚀 Deploying HetuPaymentGateway...
deploying "HetuPaymentGateway" (tx: 0x8837fe56694953a400a0a88684867f6561d56f06cd4363c18e49663da37c860a)...: deployed at 0xb49712B3BA9042168b2C35E84c9F5B2b561426CC with 2159112 gas
 
 Deployment Complete!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ConfidentialUSDCWrapper: 0xe6832A06dE93088Cd637ea35602075aEcD0f9998
HetuPaymentGateway:     0xb49712B3BA9042168b2C35E84c9F5B2b561426CC
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
fhEVM的Hardhat插件不支持在Sepolia测试网络测试

直接运行pnpm test:sepolia会报错:“Cannot find a value for the configuration variable ‘ZAMA_FHEVM_API_KEY’”。这是因为fhEVM的Hardhat插件提供了Mock实现,并没有与Sepolia测试网络相关的代码。

验证合约代码:

$ pnpm verify:sepolia 0xe6832A06dE93088Cd637ea35602075aEcD0f9998 0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238 "Confidential USDC" "cUSDC" ""
 
> contracts@0.1.0 verify:sepolia /Users/chuck/Projects/astra-hetu/contracts
> hardhat verify --network sepolia 0xe6832A06dE93088Cd637ea35602075aEcD0f9998 0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238 'Confidential USDC' cUSDC ''
 
Successfully submitted source code for contract
contracts/ConfidentialUSDCWrapper.sol:ConfidentialUSDCWrapper at 0xe6832A06dE93088Cd637ea35602075aEcD0f9998
for verification on the block explorer. Waiting for verification result...
 
Successfully verified contract ConfidentialUSDCWrapper on the block explorer.
https://sepolia.etherscan.io/address/0xe6832A06dE93088Cd637ea35602075aEcD0f9998#code
 
The contract 0xe6832A06dE93088Cd637ea35602075aEcD0f9998 has already been verified on Sourcify.
https://repo.sourcify.dev/contracts/partial_match/11155111/0xe6832A06dE93088Cd637ea35602075aEcD0f9998/
 
$ pnpm verify:sepolia 0xb49712B3BA9042168b2C35E84c9F5B2b561426CC 0xe6832A06dE93088Cd637ea35602075aEcD0f9998
 
> contracts@0.1.0 verify:sepolia /Users/chuck/Projects/astra-hetu/contracts
> hardhat verify --network sepolia 0xb49712B3BA9042168b2C35E84c9F5B2b561426CC 0xe6832A06dE93088Cd637ea35602075aEcD0f9998
 
Successfully submitted source code for contract
contracts/HetuPaymentGateway.sol:HetuPaymentGateway at 0xb49712B3BA9042168b2C35E84c9F5B2b561426CC
for verification on the block explorer. Waiting for verification result...
 
Successfully verified contract HetuPaymentGateway on the block explorer.
https://sepolia.etherscan.io/address/0xb49712B3BA9042168b2C35E84c9F5B2b561426CC#code
 
The contract 0xb49712B3BA9042168b2C35E84c9F5B2b561426CC has already been verified on Sourcify.
https://repo.sourcify.dev/contracts/partial_match/11155111/0xb49712B3BA9042168b2C35E84c9F5B2b561426CC/

dApp

记录下上面的两个地址:cUSDC代币合约地址0xe6832A06dE93088Cd637ea35602075aEcD0f9998和支付网关合约地址0xb49712B3BA9042168b2C35E84c9F5B2b561426CC。更新到frontend目录下的src/lib/contracts.ts中。

如果还没有Cloudflare账户,注册一个免费账户。创建新的Worker,并选择从GitHub代码库部署。相关的部署配置:

  • 构建命令:pnpm build
  • 部署命令:pnpm dlx wrangler deploy
  • 目录:/改成/frontend

如果遇到问题,寻找React+Vite在Cloudflare Workers上部署的方法。

测试项目

连接钱包

如果上面部署成功,登录Cloudflare Worker的页面,点击“login”后,选择Metamask等钱包后会弹出登录的签名页。

Login Metamask

主要的流程如下:

  1. 把账户里的USDC封装成cUSDC代币,封装后的金额不再公开可见(如果没有USDC,需要找Sepolia水龙头获取测试USDC);
  2. 将cUSDC转账给任意地址,转账交易数据在区块上不公开;
  3. 接收到cUSDC后,可以选择解密,或继续持有待后续使用。