当前位置: > 热评

70 亿美金流转地,Tornado Cash 的前世今生(一)

时间:2022-08-11 12:56:56 热评 我要投稿

免责声明:本文旨在传递更多市场信息,不构成任何投资建议。文章仅代表作者观点,不代表MarsBit官方立场。

小编:记得关注哦

来源:BlockSec

原文标题:70亿美金流转地,Tornado Cash的前世今生(一)

2022年8月8日,Tornado.Cash受到OFAC(美国财政部海外资产控制办公室)制裁,部分与Tornado Cash协议相关的以太坊地址被列入SDN List(美国特别制定国民名单)。自 2019 年创建以来,Tornado Cash 已经洗钱了价值超过 70 亿美元的虚拟货币。那么它是如何实现的呢?受制裁后社区和用户作何反应?BlockSec的AML团队将通过两篇文章分别阐述其实现原理及现状分析。

区块链上的隐私保护问题

在区块链上,所有的历史交易都是公开的,这意味着如果有人知道了你的地址(账户),他能轻而易举的掌握你的资金流动:新的地址可以随意创建,但是资产的转移却使得新旧地址之间的关系一目了然。

想想看,如果有这样一个可靠的且守口如瓶的中间人:每个人都可以放心的地将固定数额的钱存放到中间人处,并且每个人都以新的身份将存放的钱取回。那么对于外部观测者来说,只能确定取钱的人一定属于所有存钱的人中的一个,但无法确定具体是哪一个。这使得你和其他存钱者不可区分。而且这种隐私保护会随着存钱者数目的增加而变得更强。

在以太坊链上,智能合约一经部署就不可改变,合约会忠实的执行事先设定的逻辑,无需信任,作为中间人再合适不过了。唯一的问题是,与合约交互的过程在链上是公开的。如果能通过一定的方式,使得交互过程不会暴露存取款的关联,是不是就得到了一个优秀的隐私保护方案呢?幸运的是,密码学可以实现这样的效果。我们来看看这个方案是怎么实现的。

一个基础的隐私保护方案

我们将上述的设想分成两个部分,存款和取款。首先我们来看存款阶段是怎么做的。

存款时,我们需要创建两个随机数k和r,并根据这两个随机数计算commitment = Pedersen hash(k||r)。密码学hash函数能够实现这样的效果:任何只知道commitment但不知道k和r的人,都不能反向构造出满足等式k和r;但是已知k和r可以立刻求出commitment。

我们把commitment和固定数额的钱(为了创造匿名集,所有存款应该是一样数额的)发送给合约,合约会储存commitment并检查确实收到了规定数额的存款。

现在假设我们已经往合约里存入一笔存款。我们手上有存款凭证k和r,只要向合约出示它们,合约立刻可以验证这笔存款。并且其他任何人都不能从合约接受的commitment反向推出凭证,这确保只有我们自己可以取走自己的存款。

但是,我们不能通过简单地出示凭证来取款。这是因为和合约交互的信息是公开的,其他人如果知道了k和r,立刻能够计算出commitment,也就能从历史交易找到我们的存款交易,这就暴露存款和取款的联系。

运用零知识证明来取款

这时候,我们可以运用零知识证明来帮助我们在取款的过程中保护隐私。零知识证明能够实现这样的效果:证明者能够在不暴露相关知识的情况下,向证明者证明一个陈述的正确性。于是现在,我们能够在不透露k和r的同时向合约证明这样的事情:我知道一对k和r,由它们生成的commitment在合约的存储空间里。这等同于证明了我曾向合约存入一笔存款。于是合约在检查正确性后,就允许我们从合约里取款。

这样一来,外部观察者虽然拥有和合约一样多的信息,也只能做到验证证明是正确的,证明者确实曾经往合约里存过款。于是匿名集就产生效力了,每一笔发生在取款前的存款,都有可能是取款对应的存款,面对这样的情况,外部观察者也只能望洋兴叹。

到此为止,我们已经能够实现存取款间的不可链接性。但是还存在一个小小的问题:要是我们在取款之后,再次出示证明,是不是可以从合约再次取钱?好像真的可以!因为零知识证明没有向合约透露任何信息,即使是合约也不知道我的取款应该对应的是哪笔存款,对应的存款是不是被取走过,只知道我曾经存过款。

为了解决这个问题,我们要求取款时提供nullifier hash h = Pedersen hash(k),合约会将这个值储存起来。因为即便是我们也没办法从同一个commitment反向构造出另一对不同的k’和r’。于是在一次取款之后,我们就没办法再次使用相同的凭证k和r重复取款了。因为合约会发现,这个h值我是见过的,然后拒绝我们的重复取款要求。为了防止提供的h和k无关,提款时不仅需要提供h,并且要在零知识证明的陈述中指出关系:我知道一对k和r,由它们生成的commitment在合约的存储空间里,并且h由k生成。

到这里,我们已经基本构建了一个可用的方案,可以实现存款和取款的不可链接性。并且我们发现:可以通过增加取款的条件和零知识证明所需的参数,来增强合约对用户的约束能力。

Tornado Cash隐私保护方案

这其实就是 Tornado Cash 方案的基本原理。正如我们先前介绍的那样,作为方案的具体实例,Tornado Cash智能合约可以接受一个地址的 ETH 存款,并且能在不需要知道原始交易的情况下从合约中取款,也即允许用户从不同的地址提取资金。这些智能合约充当混合所有存款的匿名池。用户将固定面额的 ETH 存入对应的智能合约。并且可以选择直接取走资金或者是通过 relayer 来间接取款。

奇怪,我们之前从未听说过relayer,似乎无需这样的角色的存在,方案就已经可以正常运作了。那么 relayer 是做什么的?事实上,刚刚的讨论是相当简化的,并没有将运算和存储的成本考虑在内。在以太坊上,与智能合约的交互需要通过交易进行,交互过程中发生的运算和存储都将消耗一定的资源,为此我们需要为交易支付一定的交易费用。

现在,让我们再次向合约发起一次存款和一次取款,这回我们会把交易费用考虑在内,看看交易费用对存取款会产生什么样的影响。

在存款的过程中,我们需要使用一个地址向合约发起一笔交易,调用合约的deposit存款功能。合约会将我们提供的commitment存储起来,为此需要支付一定的交易费用。因而为了能够成功存款,我们的存款地址至少需要持有的余额等于固定数额的钱+交易费用。

在取款的过程中,由于隐私保护方案的前提要求我们使用新的身份进行取款,我们需要使用一个与存款地址不同的地址向合约发起一笔交易,调用合约的withdraw取款功能。合约将通过运算检验零知识证明和参数是否匹配,并且存储nullifier hash h,为此需要支付一定的交易费用。

在取款的过程中,由于隐私保护方案的前提要求我们使用新的身份进行取款,我们需要使用一个与存款地址不同的地址向合约发起一笔交易,调用合约的withdraw取款功能。合约将通过运算检验零知识证明和参数是否匹配,并且存储nullifier hash h,为此需要支付一定的交易费用。

很显然,为取款交易支付费用的人只能是取款人自己。一个很自然的想法是,我们使用一个已有余额的地址来发起交易,将存款取到一个新地址。这引入了一个新的问题:新地址与发起交易的地址的关系一目了然。此外,因为地址的交易历史在链上是公开的,通过追溯发起交易的地址拥有的余额的来源,区块链的观察者或许能够发现我们拥有的地址之间的关系。

那么能不能创建一个全新的地址来发起交易?这样做确实可以完全避免和已存在的地址发生联系,只是不切实际,因为新地址没有足够的余额支付取款交易的交易费——只有在拿到存款以后,新地址才拥有支付交易费的能力。

当然,使用已有余额的地址其实也并没有那么糟糕。如果能很好的管理和规划自己拥有的地址,将不同用途的地址隔离使用,地址之间的关系是很难暴露的。但话说回来,这样的取款方式确实引入了一些隐私泄露的风险。我们希望能找到一种方法,能够在不涉及自己的地址的情况下支付交易费用,并使用新地址来取款以根本上排除这一风险。

为此,Tornado Cash方案中引入了relayer的角色。我们可以请relayer来帮助我们垫付交易费,由relayer来发起取款交易,并且将垫付的费用扣除后,把剩余的钱交给新地址。还记得在上一节的末尾的发现吗?事实上,在真正的Tornado Cash方案中,收款者的地址、relayer地址以及指定给relayer的费用也是生成零知识证明的一部分参数,属于取款条件的一部分。这样一来,我们只需要事先将这些参数确定并生成证明,就可以保证这个交易不能被relayer所篡改。因为relayer无法在不知道k和r的情况下重新生成有效的证明。而通过relayer进行取款,我们就能保证取款过程的隐私。

谁在担任Relayer?

敏锐的读者或许已经注意到了:虽然relayer这一角色能够帮助我们解决取款到新账户的问题,在理论上实现了链上的隐私保护。但这个过程基于非常强的条件:我们在取款时,能够找到合适的relayer,并能够在链外完成协商和参数传递过程。

假设我们在过去的某个时刻往 Tornado Cash 智能合约存了一小笔ETH,现在我们打算将ETH提取到一个新地址上,于是我们需要借助relayer替我们向合约发起取款交易。但是问题来了,我们该去哪找relayer?relayer或许不愿意免费劳动,不过要是我们愿意在支付垫付的交易费之余,支付一定的感谢费,relayer就很乐意效劳了,那么我们该怎么和relayer协商?要知道,找到relayer绝非易事,想找到合适的relayer的更是难上加难。

别担心,Tornado Cash 的开发者们注意到了这个问题。开发团队为了方便大众的使用,将繁琐的存款和取款的计算集成到了UI里,并且提供了relayer的选项。在 Tornado Cash 发展的早期阶段,前端开发团队会选择一些可靠的relayer加入到relayer列表中,这些relayer将时刻保持可用状态。在这个relayer列表里可以看到每一个relayer所要求的报酬。

于是借助UI,我们可以很轻松的完成存款和取款的操作:存款时,我们可以直接在UI上连接钱包,借助UI进行存款并获得存款凭证。取款时我们要做的仅仅是提供存款凭证,再加上指定收款地址和挑选一个报价可以接受的relayer。

UI会在本地完成所有的计算,生成零知识证明从链外发送给relayer。relayer在收到所有需要的参数后将使用这些参数发起取款交易并支付交易费,最终从合约转出总和为存款金额的两笔资金,一笔资金将发送到我们指定的收款地址,另一笔按约定的数额发送给relayer的地址。

Tornado Cash社区和治理

到此为止,Tornado Cash 方案的问题已经全部得到了解决。这要感谢relayer列表的存在。有了relayer列表,我们可以很轻松地使用relayer进行提款。

不过relayer列表仍有美中不足之处,在于其是由开发团队提供的,要是relayer列表不那么中心化就更好了。毕竟,我们既不清楚开发者选择relayer的标准,也不知道relayer的实际身份。只能寄希望于开发团队的眼光——开发团队声称他们选择的relayer是可靠的。

幸运的是,Tornado Cash 社区注意到了这一点,治理提案 #10: Relayer registry 正是为了解决这一问题而诞生的。从此以后,relayer列表的中心化得到了彻底解决,任何人只要质押300TORN,就可以成为relayer。

哇哦,这里出现了好多之前从未见过的概念,事实上,这些概念并不属于 Tornado Cash 隐私解决方案,而是和 Tornado Cash 社区与治理密切相关。简单来说,Tornado Cash 社区是围绕着 Tornado Cash 合约,以开发者和活跃用户为中心建立的治理体系。

我们知道 Tornado Cash 智能合约已在以太坊区块链中实施,即便是开发者也不可能改变已经被部署到链上的 Tornado Cash 智能合约。那么, Tornado Cash 社区究竟在治理些什么呢?还记得上一小节我们是怎样找到relayer的吗?如果没有relayer列表的支持,寻找relayer将成为难题,迫使用户使用已有余额的地址进行取款,这无疑会导致隐私保护方案的弱化。像维护relayer列表这样的增强合约可用性的任务就需要由社区来治理。

另外,社区治理能够通过创造新的合约。新合约充当代理的作用,覆盖在 Tornado Cash 智能合约之上。代理合约会在内部将我们提供的参数传递给 Tornado Cash 智能合约,能够在不影响隐私保护方案的前提下,实现社区需要的功能。‍Tornado Cash 的治理并不是一开始就由社区来实施的。在 Tornado Cash 的治理史上,有一个重要的里程碑,那就是发布于2020.12.18的提案 Tornado.Cash Governance Proposal 。这个提案将 Tornado Cash 的治理权从开发者移交给用户社区。随后社区沿用了这一形式,通过提案-投票的方式来实施对于 Tornado Cash 的治理。

提案设计了 Tornado Cash 的治理系统,将治理权具象化为代币TORN。开发者和投资人获得30%的代币,早期用户获得5%的代币,DAO获得55%的代币。然后剩余的10%的代币,将作为匿名挖矿的奖励,持续一年;并且为了实现匿名挖矿,治理创建了新的合约。

匿名挖矿是一种激励措施:用户的存款保存在匿名池中的时间越长,金额越高,会获得更多的奖励。意在吸引到用户,使合约度过初期的难关。

这是由于匿名集越大,保护隐私的能力就会越强,使用者的意愿也会更强。因此合约一旦进入正轨就能够自然的运转。最大的难点就在于启动:一开始没有匿名集,就没有人愿意使用,那匿名集永远不会增长。

在2021年12月,匿名挖矿在引导了智能合约顺利运转后功成身退。

Tornado Cash的现状

总而言之,Tornado Cash 是以太坊上的隐私解决方案,使用简洁非交互式零知识证明 (zk-SNARK) 来实现属于同一用户地址之间的不可链接性,并以无需信任的方式保护隐私。而Tornado Cash 智能合约作为方案的实例,完全去中心化,无需监督,并且无法被更改。另外,我们还知道 Tornado Cash 社区的存在,他们在为 Tornado Cash 变得更好而努力。

现在我们可以自信的说,我们相当了解 Tornado Cash。不过,为了能说出那句”没有人比我更懂 Tornado Cash“,我们还有更多的东西要学。

在先前的讨论中,我们介绍了 Tornado Cash 的原理、 Tornado Cash 的社区和 Tornado Cash 的治理。我们知道在这三者的协同作用下,Tornado Cash 能够符合预期地工作,但我们对于 Tornado Cash 实际的情况知之甚少:有多少人在使用 Tornado Cash ?什么人在使用 Tornado Cash ?事实上,Tornado Cash 现在正面临的一些挑战。

自2019年成立以来,Tornado Cash一直在以太坊区块链上运营,作为隐私解决方案为多种代币提供固定金额池。并且自2021年6月以来,在其他侧链和区块链上也部署了合约。(这部分可在官方文档https://docs.tornado.cash/general/readme中找到)作为其中最有代表性的实例,Tornado Cash 为 ETH 部署了四个不同面额的智能合约,分别是0.1、1、10 和 100 ETH,来实现固定面额的混合服务。

不幸的是, Tornado Cash 受到不法分子的滥用。虽然 Tornado Cash 的诞生是为了保护人们的隐私权,但是却常常在各种事件中沦为黑灰地址的帮凶:这是因为 Tornado Cash 能够打破资金来源地址和资金到达地址之间的链上关联,也因此对反洗钱工作的开展造成很大的困难。在很多攻击事件中,狡猾的不法分子会选择通过 Tornado Cash 获得启动资金,然后在实施攻击之后使用 Tornado Cash 掩盖获利的去向,使得溯源和追踪扑朔迷离。

在今年3月Ronin Network被盗超6亿美元的事件中,黑客通过Tornado Cash转移了价值数千万美元ETH,8月初发生的Nomad Bridge被盗2亿美元的事件中,黑客同样用Tornado Cash进行混币。2022年上半年安全事件中74.6%洗钱资金流向Tornado Cash。

正因如此,2022年8月8日,Tornado.Cash受到OFAC(美国财政部海外资产控制办公室)制裁,部分与Tornado Cash协议或与之相关的以太坊地址进行交互的地址被列入SDN List(美国特别制定国民名单)。