Filecoin 攻击之二:预挖攻击
已经发表了好几篇关于Filecoin攻击的文章,那为什么这篇文章还是之二呢?这是因为这个题目早就写下来了,只是一直没有把它完成。原因之一,在Filecoin团队把这个问题修复之前,不便于发表;而修复之后呢?又懒于发表。都到了2020年了,想一想,既然是技术分析文章,那还是把它完成,希望对大家有所帮助,那也就够了。
目前大家跟踪的较多的是 Lotus 实现,在目前的Lotus 版本中,这个问题,已经不存在了,至少不是以原来的方式存在了。使用相同的方法攻击网络已不可行,但考虑到测试网期间,重要的是安全,那么通过对这个问题的分析,希望给大家带来一些思考,能够设计出更多有价值的测试方法,对 Filecoin 的完善有所帮助。
Filecoin 挖矿的参与,门槛颇高。一方面本身就是这条链比较复杂,另一方面也因为复杂,完善需要一个过程,没有一定的技术实力,参与起来就困难一些。在加上有些有技术实力的团队,能够利用实现中存在的漏洞不不足,那么哪些仅仅跑跑官方代码的矿工基本上就只能看着别人在前面飞奔。
其中最为明显的例子就是在 go-filecoin 0.4.x 系列版本中,有少数矿工一上来算力就非常靠前。其中最主要的原因,就是实施了预挖攻击。
预挖攻击,大家都明白,就是在网络还没有启动的时候就准备了大量的算力,等网络上线,直接加载算力,跑在前面。等你上线初始化时,他人已经准备了好几天了。
这其实是一个公开的秘密,Steven 公开的一个秘密,下面这个 bug 进行了比较详细的描述。这个 Bug 有可能是在攻击发生之后,也有可能是在其之前。现在记不太清了。但这个 Bug 提交之后,后来又发生了几次预挖攻击,这是肯定的。
能够预挖的前提就是,你实现知道或者能够构造复制证明所需要的所有参数或者变量。如果你未卜先知的话,还有什么事情不能做呢?
go-filecoin 的预挖也是如此,当时的复制证明引入的变量包括:
矿工 actor 地址
数据本身
sectorID
就这么简单,如果上面几个都事先知道的话,就好了。三个变量中的后两个比较容易,数据可以事先准备,sectorID是一个递增的量,或者自己可以设定;关键是矿工地址,而矿工地址恰恰与矿工钱包地址和其什么时候创建此矿工有关。钱包地址当然可以事先创建,这是因为区块链的私钥本身就是随机数,是离线创建的,而地址是由私钥运算而来的,那么地址可以事先搞定。而创建矿工的时机也是可以把握的,掌握好与链通信的步骤就好了。
至此,一切就绪,做好算力,等新的网络开启即可。更有甚者,你可用 0.3.x 的算力用到 0.4.x 中,网络重置不重置无所谓。
针对这一问题,团队在slack里和github都又讨论,解决办法也很简单,引入可验证的随机数,加入新的变量。这样一来,如果你事先不能知道这个新的变量的话,也就不能事先证明了。
这个新的变量,就是 Filecoin 网络区块中的 ticket。这个 ticket 是 Filecoin 协议安全的基础。几乎所有需要随机数的地方基本上都是用某一个高度的 ticket,而这个ticket只有在这个高度显现之后,矿工才可能查到。
当然,这一改变,涉及到协议的改变,所有这个改变最终由负责 Spec 的Stern 首先完成,而后直接在 Lotus 的事先中被采用。在当前的复制证明中,步骤已经更加复杂,随机变量引入也更多了,包括 precommit 和 provecommit两个阶段,每一个阶段都引入了ticket参与运算。因此,像在 go-filecoin0.4 版本上出现的预挖已不可能。
那么问题来了,Lotus测试网上线的时候,不是出现了t0222, t0333, t0444 这几个节点一上来就自带高光,算力 1.25T 吗?怎么来的?答案:预挖来的。
那不是还是能预挖吗?是的,他能预挖,你不能。为什么?这里不全部揭晓,但是可以提一个思路,大家想想。要预挖,就要知道所有变量,他在网络启动之前就预挖了,他所需要的变量就是能够确定的。没错,就是能确定的。要是让你来启动网络,你也可以预挖。
不知道,但看起来是的。网络总是需要算力维持的,不要太高就好。
相关文章