编者按:本文来自以太坊爱好者,作者:Blocknative,翻译:阿剑,Odaily星球日报经授权转载。Blocknative已经找出了MakerDAO在3月12日和13日时的清算活动乃是有人刻意为之的证据。这些证据是从“Mempool”,即矿工打包区块时候的备选交易池,中发现的。交易内存池是一个以太坊生态中经常被人忽略——也不受大家重视——的部分。作为交易内存池分析专家,Blocknative运营着一个由遍布全球且配置各不相同的Geth节点和Parity节点组成的网络。这一基础设施使我们能部署实时的交易监控服务,我们可以捕捉、规范化和归档内存交易池的状态变化。Blocknative在“黑色星期四”时捕捉到了3000万行数据,使我们能做一项开放式的研究;迄今为止,我们已经发现了数个似乎已被利用过的“漏洞”。虽然很多人都已写过“黑色星期四”的结果,但在本文中我们会首次披露Blocknative内存池存档中的数据,用新的数据和理论说话。我们也把分析要用的底层内存池交易数据集合开放出来了,供大家审阅。如果你是一位安全研究员,想了解更多我们的发现,或想发现其它潜在的交易池异常,请联系我们。总结
Blocknative的内存池事后检验报告显示,内存池中有三大因素影响到了3月12日和13日的事态:被阻塞的交易——内存池的拥堵极大地提高了交易卡壳率,让同一地址连续发出的多笔交易都被卡住、不能得到处理;交易池“压缩”——交易池中可上链部分比重的大幅减少,可能影响到了Gas价格的估计;“Hammerbot”——自动化的交易系统加剧了交易池堵塞,因此与交易池压缩效应相叠加;我们出版这份分析以及相关的数据,是为了引起大家对动态交易风险的关注,这种风险在区块链网络拥堵期间可能会迅速出现。背景:“黑色星期四”概况
在2020年3月12日,密码学货币市场上出现了有史以来最大的抛售潮,几个小时里面,ETH价格暴跌43%,BTC的价格跌掉了39%。随着价格下跌,一个负反馈循环出现,多种DeFi合约内都开始出现流动性降低和强制清算活动。在此期间,这种下行的压力使得每一个尝试在网络上发送交易的个体都遇到了严酷的挑战。
-UTC时间2020年3月12日到13日期间按小时加权的ETH平均价格。数据来源:cointelegraph.com-迅速的价格变化导致了以太坊交易池的持续拥堵,因为自动化的交易系统总是按照程序对波动性机械地作出反应。如此堵塞情形的一个负面后果是MakerDAO债仓清算活动中出现了“0价格拍卖”现象。在“黑色星期四”期间的3994个清算拍卖中,有1462个债仓的担保品是被0价格拍走的。在大概12小时的时间里,锁在债仓中、总计832万美元的担保品被0价格拍走,没有让系统回收到一分钱。更多细节请看MakerDAO自己发布的《2020年3月12-13日的价格暴跌及其对MakerDAO的影响》一文。1.由交易池堵塞导致的交易卡壳
3月12日时ETH价格的迅速变化导致用户大量发送交易,产生了交易池内部的拥堵。对价格波动自动作出反应的机器人的活动加剧了这一情形。
-进入交易池的待打包交易计数vs.打包上链的交易计数-结果就是大量的交易通过网络传播,迫使使用默认交易池设置的节点通过下列手段来保护自己的系统资源:删除,或者说丢弃掉许多有效的交易;拒绝,或者说无视掉许多有效的交易。交易池通常会用最低手续费门槛来选择放弃哪些交易。虽说这些被丢掉的交易并没在整个网络中“完全丢失”,但被丢掉的交易可能会遭遇显著的时延,直至网络条件回归正常。
-2020年3月11日至3月14日期间,到达交易池的被丢弃掉的交易和卡壳交易计数-更重要的是,丢弃交易还会带来一个副作用:增加交易卡壳的可能性。删掉一笔交易之后,该节点不会留下关于该笔交易的任何信息,比如发送地址和交易nonce。因此,当同一个地址的一笔新的交易到达交易池,该节点会发现该地址已处理交易和这笔新交易之间有nonce空缺,因此也不能处理这笔新交易。受此效果影响的交易就只能放到该节点的交易池中无法处理的队列中。这些交易,无论所支付的交易手续费有多高,都一概会被卡住、无法处理。想了解更多细节,请看我们此前讲解交易排序的文章:《节点是你通往内存池的网关》。与此同时,网络的堵塞导致进入内存池的GasPrice门槛随之迅速提高,因此最初的一些交易现在会因为GasPrice太低而被拒绝。而且,因为之前被删除的交易不能回到交易池中来,交易的nonce空缺问题又变得更严重了。事实上,一些节点实现会在一段时间内主动无视掉这些被拒绝的交易,以保护自己不受点对点网络中的泛滥攻击影响。所以,nonce空缺实际上会锁住这些受影响的地址,使得他们无法完成新的交易。卡壳交易更有可能影响会发出许多新交易的地址,包括自动化交易系统、支付网络,甚至交易所。这些系统想回到正轨,但通常会加剧拥堵,因为越来越多交易被推迟处理。有没有解决办法?你得主动发现自己何时开始遭遇卡壳。这可能有点难,因为你的交易可能仅在某些节点处是卡壳的,但并不是在所有节点处都面临卡壳。因此,你必须确定第一笔被丢弃、导致nonce空缺的交易,然后立即用可以得到打包的GasPrice加速让这笔交易上链。最后,你还得继续监控一开始发现卡壳的交易,确保它从不能处理的队列中移回到了交易池的待打包部分中,并成功上链。如果你的交易还是卡壳,重复上述加速步骤,直到你可以确认所有导致nonce空缺的交易都已成功上链。当然,这也是我们开发并运营我们的NotifyAPI的理由之一。2.压缩内存池中可上链的部分
网络阻塞的出现——及其导致的交易卡壳——使得交易池中可上链交易的比重迅速缩减。我们管这叫“交易池压缩”。矿工的激励分两部分:区块奖励和交易的GasPrice;所以收益最大化需要打包GasPrice最高的那部分交易,挖矿时要根据交易池——即候选交易——的情况来决定打包哪些交易。在交易池拥堵时,多种行为会导致交易池压缩,对矿工来说值得考虑的交易比重越来越小:资源耗尽:在某些节点实现中,卡壳交易数量的迅速上升会消耗掉可观的交易内存池资源。这又反过来导致节点处理有效pending交易的可用资源进一步减少。不断升高的GasPrice:ETH价格的下跌导致许多交易变得“高度紧急”,因为这些交易在构造时是希望能够赶在ETH进一步下跌时上链确认的。这使得个体用户也好、自动化机器人也好,都赶紧提高GasPrice。因为不是所有参与者都这样密切关注着堵塞情形,待打包交易总体包含了反常比例的低价——因此不可能被打包的——交易。反应慢半拍的定价算法:交易池中待打包交易的GasPrice分布,以及近期被打包交易的GasPrice,使得一些预测合适GasPrice的服务的测算出现扭曲。但这就导致更多GasPrice过低的新交易出现,又进一步加剧了测算值与实际值的不一致。交易池堵塞出现时,让交易打包上链所需付出的GasPrice会升高是意料中的事情。但是,因为并不是所有人都跟踪到了GasPrice这种迅速的提高——包括,尤其是那些有GasPrice报告功能的服务——上链所需的平均Gas价格开始偏离进入交易池的交易平均Gas价格。而一般的出价上涨跟不上当时的价格上涨速率。在3月12日,我们的数据平台发现了交易手续费定价的明显偏离。在3月13日,交易池中部分交易的GasPrice与上链交易的GasPrice差额在可预料范围内,但在3月12日,已挖出交易和未挖出交易的Gas出价简直是天壤之别。不能上链的交易要成为可以上链的交易,一般来说标准的操作就是提高GasPrice。但是,在3月12日,这样做根本就没用。因为,大量交易池资源被以几乎同样的GasPrice重发的交易消耗掉了。
-2020年3月12日至13日每小时的GasPrice箱型图。每个小时的箱型都划分了1分位值和3分位值,两者中间的线表示中值,而箱顶和箱底的线表示最大值和最小值。已忽略掉了异常值-这张图反映了真实情形吗?还是说这些出价过低的交易本身就是为了堵塞掉交易池呢?如果真是有意为之,为什么呢?3.Hammerbot交易导致内存池失真
我们的内存池存档数据暗示,机器人成功地提高了堵塞情形,并扭曲了交易池中交易的Gas价格分布,而且还没有导致交易手续费的相应提高。这样做的净效果就是交易卡壳率的提高和GasPrice报告服务扭曲,结果是交易池一场,使天平偏向了某些特定的交易——即,提高了清算CDP仓位的交易以0价格成功竞拍的几率。机器人用本来就无意提交上链的交易捶打交易池。这些Hammerbot通过发送置换率极高的交易消耗掉了交易池的资源。但是,交易池还有一种设计,是要求重发交易至少要提高10%的Gas价格,本身就是用来防止此类行为的。那这些交易是如何实现置换的呢?答案很简单:异常高的交易丢弃率导致节点“失忆”。Hammerbot等待着——或者仅仅是预估——自己发出的交易从交易内存池中丢弃,然后立即用相同的Gas价格重发交易。因为节点“忘记掉了”之前被丢弃的交易,自然就尽职地把这些置换后的交易当成有效交易接了过来。当然,结果就是进一步的拥堵。Hammerbot用显然是“自动化”的方式让自己的交易变得畸形,每一次置换都包括了稍微更改过的合约输出。因此,每一笔Hammerbot交易都有一个独特的哈希值,可以绕过所有节点的点对点网络协议中的泛滥攻击过滤保护。如下图中重点标出的粉色线所示,从UTC时间3月12日9点开始,我们的交易池数据平台发现根本不可能被打包的待打包交易数量急剧上升。35分钟后,此类不可能上链的交易产生的速度翻了一倍,在10点之后才降为线性增长的模式。
-从UTC时间8点到10点期间达到交易池的交易计数,以分钟计。蓝线表示最终上链了的交易计数;而橙线表示根本没有上链的交易计数。-即使这些交易似乎没有上链的意图,这些从未被打包的Hammerbot交易的GasPrice还是显得太低了:在市场要求给出30Gwei乃至更高价格时,这些交易几乎总是只给5Gwei。Hammerbot交易既没有像套利机器人经常做的那样加速交易,又高效地消耗掉了节点的交易池资源。从整体上来看,虽然进入交易池的交易数量急剧增加,交易池中还是有很大一个比例的交易GasPrice被人为压低了。
-从UTC时间8点到10点间的交易GasPrice箱型图。蓝线表示最终上链的交易的情形。橙线表示从未上链过的交易的情形。-拿出一笔Hammerbot交易作为例子,可能有说明价值。这里是最终的交易哈希值:0x5b00c13020b82c9e8a098393564feca976dbbd2e8da6c54263f6e492be56fbfb。仅仅用你惯用的区块浏览器检视这笔交易并不能给出除了其区块确认信息以外的洞见。表面上来看,这笔交易平平无奇。但Blocknative的交易池数据平台检测到了这笔交易上链之前使用这个nonce值的418笔独特交易。这些交易都是在一个小时内出现的,也就是这些置换交易平均每6.86秒重发一次,而某些置换交易之间的时间差不超过0.1秒。
-地址0x5cf2fa4e0c84e71fd2e4fa86d2fa64b7a50a6fc0从UTC时间9点开始在相连的4个nonce上发起的置换交易次数-大多数置换交易都使用同样高的GasPrice,都是因为节点的交易丢弃机制才作为“新”交易成功进入到节点的交易池内。只有最后一笔想要上链的置换交易才需要给出更高的GasPrice,然后被打包到区块内。
-地址0x5cf2fa4e0c84e71fd2e4fa86d2fa64b7a50a6fc0从UTC时间9点开始在相连的4个nonce上的平均GasPrice-这种模式使我们很难说这些Hammerbot交易到底是有心还是无意的。实际上,我们的系统在一分钟之内记录下了超过20个从UTC时间9:05开始活跃的可能的Hammerbot地址:
-如果你是上述任一地址的运营者,我们很希望跟您聊聊。请联系我们-注意:这些特征明显的、使用同样的GasPrice重发被丢弃交易的Hammerbot行为,也可能跟最近大家讨论的“backrunning”行为有关。见此处和此处。交易池漏洞对MakerDAO的影响
MakerDAO的担保债仓是用户生成稳定币DAI时托管被锁定的担保品ETH的智能合约。因为ETH的价格有波动,而DAI希望能保持1美元的价格,所以维持一个开放的CDP所需的担保品数量是不断变动的。当3月12日ETH价格暴跌时,大量的CDP立即变成了担保不足的状态,需要被强制清算。系统为保证担保品清算时可以获得竞争性的市场价格,安排了折价机制:参与清算者可以以折价买到担保品ETH;这就使得许多人都愿意运营多种多样的Keeper机器人。清算活动的表现形式为拍卖。任何Keeper都可以用链上出价参与拍卖,而一个看护者出价之后,另一个看护者想要与之竞争必须在10分钟之内发送竞拍价更高的交易。每当有新的竞拍交易到达,都会刷新10分钟的竞拍窗口期。如果10分钟之内系统没有收到更高的出价,则拍卖结束,最高出价者胜出。但是,当矿工节点因为网络拥堵和交易池压缩而以异常高的比例丢弃交易时,许多看护者的交易都被卡住了,因此根本没能及时让清算CDP的竞拍交易成功上链。结果就是看护者们无法在由0价格竞拍交易开启的窗口中可靠地开展竞争,即使看护机器人正确地发现了0价格拍卖并发送出了更高出价的交易也没用。最终,因为拥堵和实际手续费的混淆,看护者无法恰当地解读出GasPrice的实际上涨幅度,看护者的交易也因此被节点丢弃。接下来是产生nonce空缺、交易在使用默认交易池设置的节点处卡壳。遭遇此种情形的看护者机器人为其他拍卖发出的所有后续竞拍交易会全部被卡住,让该看护者根本无法在10分钟的竞拍窗口内参与交易,最终让0价格竞拍交易得逞。下面我们用1866号拍卖作为例子来说明上述过程:一个“0价格竞拍机器人”在UTC时间15:59:50时以200Gwei的价格发送一笔0价格竞拍交易。该交易在26秒后成功上链,10分钟倒计时就此开始。一个“诚信看护者机器人”在16:08:01时以450Gwei的GasPrice发送一笔竞价交易。这笔交易是在10分钟内发出的——之隔了8分11秒——而且Gas价格还是最初那笔0价格竞拍交易的2.5倍。如果能在接下来的1分49秒内被打包到区块中,1866号拍卖就会像大家预期的那样进行。但是,这笔竞拍交易因为这个好机器人之前发送的一笔交易被丢弃而被卡住了。这个好机器人在16:15:31又发出一笔4500Gwei的竞价交易。但是哪怕GasPrice提高了10倍也无济于事,因为这个地址被nonce空缺锁死了。再然后,等到竞价交易不再被卡的时候,已经过了10分钟的窗口期,交易自然就失败了。上述模式可能重复了一整天,最终导致总计832万美元的担保品被0价格拍走。值得指出的是,大多数Hammerbot的活动似乎都在当天较早的时候发生,这样就造成了后来影响到Keeper机器人交易的拥堵情况。GasPrice的迅速上升、导致Gas价格估计失灵的交易池压缩,同样对其它价格信息传输机制造成了负面影响。这导致了定价方面的混乱,也有可能使得面临清算风险的CDP持有者推迟了添加担保品的决定。总结我们的发现
总结一下,我们对“黑色星期四”交易池状况的事后检验暗示了下述情况:多种Hammerbot的活动导致挖矿节点的交易池饱和。这推高了以太坊网络的拥堵程度并使之不断上升。发送许多以同样的GasPrice发出的置换交易在点对点gossip层和节点本身产生了巨大的开销。正常交易的传播受到阻碍,大量的交易被挖矿节点丢弃或者拒绝。这又反过来提高了出现nonce空缺和卡壳交易的几率,还扭曲了对GasPrice的估计。虽然自动化的交易系统通常被设计成会自动提高交易的GasPrice,许多交易系统并不能很好地处理nonce空缺问题——甚至是完全束手无策。以上就是我们在研究过程中的发现。我们的数据集可能还能揭示出更多的证据以及/或者新的发现来支持或证否我们的结论。为加速这个发现过程,我们现在把那两天的交易池存档数据开放给社区,我们希望这能促进对交易池在“黑色星期四”及以太坊网络其它类似事件中所扮演的角色的研究。建议:保护好你自己,以及你的用户
交易池是区块链生态系统非常关键的一环,虽然它瞬息万变,常常被忽略。因此,交易池中藏着很多开发者和用户“完全无知的未知之物”。现在,我们并不知道有多少人在开发这样的利用交易池弱点的技术——只是显然有人在利用交易池的特点。我们也不知道有多少这样的弱点存在——只是那些复杂的利用方法似乎已经在现实中证明了其有效性。因此,我们建议所有交易、所有协议、所有钱包供应商和交易员:持续监控交易池的情况,注意发现交易池开始变得拥堵的时机;交易丢弃率和拒绝率的变化。理解交易nonce排序的细微差别。即使合理构造的交易也可能被卡在网络的某个角落。主动观察被卡壳的交易,并且要知道加速先前的哪一笔交易能使发送交易的地址脱困。基于交易池中对矿工有吸引力的部分来计算GasPrice。还需要知道你所依赖的GasPrice报告服务所用的算法。在高度拥堵期间,不要假设交易待打包的情形是可以预测的。先防范,你要监控每一笔交易,了解每一个细节,包括Gas是否充分,交易是不是被丢弃、被卡壳,会不会被人抢跑,等等。这些问题,如果你自己动手解决,是非常有挑战性的、很耗时而且很昂贵的。Blocknative的全球数据平台一直在往捕捉和规范化去中心化交易池的方向优化——也就是一直在实现上述的五个建议。我们的基础设施和API提供了实时的交易池监控服务,保证你的交易能可靠、灵活、可预测地流动。……非常感谢评议本文初稿的各位,包括:SarahBaker-Mills、DmitriyBerenzon、SpencerBogart、NicCarter、Hsin-JuChuang、TomaszDrwi?ga,AndyGray、HudsonJameson、JonKol、CalvinLiu、JustinMart、GavinMcDermott、TaylorMonahan、AndraNicolau、CharlieNoyes、SimonaPop、AlexPruden、AustinRoberts、CuySheffield、LarrySukernik、ChrisWhinfrey,等等。我们非常感谢你们的反馈、洞见和指导。
郑重声明: 本文版权归原作者所有, 转载文章仅为传播更多信息之目的, 如作者信息标记有误, 请第一时间联系我们修改或删除, 多谢。