Tornado.Cash 匿名协议及挖矿

Tornado.Cash是以太坊上完全去中心化的匿名交易协议,基于zk-SNARK实现,可以切断交易中发送者和接收者的关联,目前支持代币有:ETH, DAI, cDAI(Compound Dai),USDC,USDT,WBTC。

Tornado.Cash支持采用 relayer 进行取款,将资金发送到新生成的地址上。

Tornado.Cash于2019年在以太坊上线,2021年6月,在 BSC 和 Polygon上部署, 分别支持BNB 和 Matic 代币的匿名化。

Tornado.Cash支持一些代币进行匿名挖矿,可以获取TORN治理代币。

匿名交易原理

Tornado.Cash支持deposit 和 withdraw 两种操作, deposit 将用户将资金存入资金池中,经过混币后,再通过withdraw将资金取到一个新的地址中。因此越多人参与,匿名效果越好。

存款

用户要往合约存款,需要生成两个248bits的随机数k,r,k为nullifier,r为随机数,这两个数就是凭证。 计算

commitment = H1(k||r), H1是PedersenHash

commitment是触发TC合约存款函数deposit的唯一参数。

deposit函数主要完成以下工作

  • 检查commitment是否已存在(合约要求commitment不能重复)
  • 将commitment插入到merkle树中
  • 将commitment标记为已存在(mapping(bytes32 => bool) public commitments)
  • 如果是针对ERC20的代币,则执行转账,将用户账户的token转到合约账户里。如果是ETH,则不用执行显示转账,在触发合约deposit函数时必须附带指定金额的ETH.

合约deposit执行成功后会emit

event Deposit(bytes32 indexed commitment, uint32 leafIndex, uint256 timestamp);

用户可以确定自己的commitment处于叶子节点的位置。

提款

用户要想提款,必须向合约提供proof,证明用户知道某个commitment对应的隐私信息(k,r),同时不能让别人知道(k,r)的任何信息,确保别人不知道花费的是哪个commitment.

具体步骤:

  1. 用户选择一个收款地址A和fee,fee是根据具体的中继者的收费标准确定。

  2. 用户选择一个Root,构造证明commitment存在的Merkle path。在合约里,存储里最近100个历史Root,而非所以的历史Root。

  3. 计算nullifier(即k)的hash, h=H1(k).

  4. 计算零知识证明的proof,具体算法用的是Groth16。约束条件为:

    1. h = H1(k)
    2. commitment = H1(k||r)
    3. commitment的Merkle证明

    公开输入:Root, h,

    隐私输入:k, r, l(commitment在叶子节点的位置), path

  5. 触发合约withdraw函数

    withdraw(bytes calldata _proof, bytes32 _root, bytes32 _nullifierHash, address payable _recipient, address payable _relayer, uint256 _fee, uint256 _refund)

withdraw函数完成以下过程:

  1. 检查_nullifierHash是否被花掉
  2. 检查_root是否是历史root
  3. 验证_proof
  4. _nullifierHash标记为已花掉
  5. 处理转账:分别转给收款人和中继者(若有)。
  6. refund:这个字段是针对ERC20 token设置的,用户可以用自己的token跟中继者兑换一些ETH,可以用来支付以后的交易gas费用。

Setup

  1. TC合约部署时绑定验证proof的合约,存/提款金额,Merkle树高度(20),特权账户(operator).
    等trusted setup完成之后,特权账户更新proof的验证密钥VK,然后将特权账户地址更新为0,之后便没有任何人可以更改VK,保证合约的安全性。
  2. 针对ERC20 token,部署合约时还要绑定对应的ERC20合约。

凭证示例:

tornado-eth-1-5-0xc594a62c82e8772b1731601a90d30f0d5b705fdcdd3147b46c3a1dbe546f58173f2a8ad7b19dce041e46a4626a48ff555b00eaa33ea47a5f6bf812d7c2c1

在deposit时,需要更新20层的Merkle树, 需要消耗较多的gas; withdraw 生成证明的过程相对复杂,但消耗的gas较少。

匿名挖矿

匿名挖矿主要激励用户将资金在资金池存留更长时间,增加匿名池资金, 以提升交易匿名性。激励从2020.12开始, 到2021.12月截止。

支持匿名挖矿的代币有:ETH, WBTC, DAI, cDAI. 资金存款每过一个块会获取固定AP(Anonymity Points) 奖励,AP 可以兑换 TORN代币,汇率是浮动的。

(1) 首先用户发起deposit操作

   此时需要构建deposit Mekle 树,叶子节点为hash( address(torando) || commitment || blockNumber):       
 bytes32 leafHash = keccak256(abi.encode(deposit.instance, deposit.hash, deposit.block));
   但是更新Merkle树需要消耗大量的gas费用,因此合约首先记录deposit 的 LeafHash, 更新操作由第(3)步完成。  
   (2)   等过段时间后,用户发起withdraw 操作.
    此时需要构建 withdraw Merkle 树, 叶子节点为: hash(address(tornado) || nullifierHash || blockNumber)      
 bytes32 leafHash = keccak256(abi.encode(withdrawal.instance, withdrawal.hash, withdrawal.block));
    同上,更新Merkle 树由第(3) 步完成,合约记录withdraw 的 LeafHash. 

(3) 需要有人调用 updateRoots, 更新deposit Merkle树和 withdraw Merkle 树,需要消耗大量的gas.

(4) 用户需要利用凭证根据deposit和withdraw时间差获取奖励AP,为了不泄露凭证的信息,需要生成零知识证明,主要包括reward 和withdraw两种操作。

\- reward: 主要为了领取奖励AP:rate * (withdrawalBlock - depositBlock) , 奖励AP以commint 的形式存在于合约Account Merkle树中。 

    此时需要利用deposit和withdraw 树 生成的零知识证明 构建Accout Merkle 树,叶子点节为: hash( amount || secret || nullifier )

    此时可以用匿名挖矿密钥加密 Accout 信息, 在链上存储。 加密密钥又由以太坊密钥加密存储在链上,即使丢失也可以恢复。

    为了避免用户重复领取奖励,需要生成:rewardNullifer = noteNullifier

    对于累加的奖励,需要生成:accountNullifier.   

\- withdraw: 可以取出部分或全部AP,将其转化为TORN代币。

    需要根据Account Merkle树生成零知识证明。        

    为了避免用户重复withdraw, 需要生成 accountNullifer: 

用户将AP兑换成TORN代币,采用AMM流动模型,TORN代币线性增加流动池中,AP换成TORN代币的公式为:

BalanceAfter = BalanceBefore * e^(-rewardAmount/poolWeight)
tokens = BalanceBefore - BalanceAfter

链上备份

先前用户需要本地备份凭证,并不方便。目前添加可以在链上存储加密凭证的功能。用户需要设置凭证账户(Note Account), 在deposit时,可以选择利用公钥加密凭证保存链上,可以用对应的私钥解密。

去中心化的Relayer

任何人可以申请成为Realyer, 帮助用户触发withdraw操作,赚取手续费用。采用零知识证明,保证Relayer 无法对withdraw 接收者,手续费,relayer 进行更改。

来源证明

通过提供凭证,可以重新链接发送者和接收者地址,证明资金来源。

合约部署

(1) tornado-core

合约代码:https://github.com/tornadocash/tornado-core.git

部署步骤:

  1. 部署Verifier.sol

    运行:npm run build:circuit 生成 Verifier.sol 合约;

    运行:./solc --bin --abi --optimize Verifier.sol 编译合约;

    在wallet-cli 利用 deploycontract 部署Verifier.sol 合约

    Verifier.sol 合约地址:

    https://nile.tronscan.org/#/contract/TYfR63UZJy9XqPwUhZKewnnwgPHEZeX5Wp

  2. 运行: node compileHasher.js 生成 Hasher的abi 和 字节码;

    在wallet-cli利用deploycontract 部署 Hasher 合约。

    Hasher 合约地址:https://nile.tronscan.org/#/contract/TZ7GYKy3BwU4fBrK3KQKoXKa8XXHtwMCoi/code

  3. 编译ETHTornado 合约:./solc --bin --abi --optimize --libraries Hasher:0xFDD12CCE9EF36ABC2C4BD1500FE3322FBECCF3D1 ETHTornado.sol

    在wallet-cli 利用 deploycontract 部署ETHTornado合约。

    合约地址为:https://nile.tronscan.org/#/contract/TXb7LSgx3BbwqVSzMr9FhMuA3GvgGi1ACA

  4. 合约调用:https://nile.tronscan.org/#/transaction/f6cbccf0552ba3a6dce8c0a8f3dc343d74fe67714ac078bfb0484d1ee3e930a2

参考

https://tornado.cash/

https://docs.tornado.cash/

https://github.com/tornadocash

https://torn.community/t/anonymity-mining-spreadsheet/720

https://github.com/tornadocash/relayer

https://torn.community/t/anonymity-mining-technical-overview/15

https://github.com/tornadocash/tornado-root-updater

https://tornado-cash.medium.com/tornado-cash-governance-proposal-a55c5c7d0703#2084

https://github.com/tornadocash/tornado-relayer

https://tornado.cash/Tornado.cash_whitepaper_v1.4.pdf

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容