打印
分类:极客论道
点击数:3907

比特币mempool机制与相关风险、对策

用途:

  mempool存放未确认的tx

基本流程:

节点接收到tx-》收录入mempool-》转发-》矿工/矿池将tx收录入block,节点收到block后,从mempool中删除tx。

mempool收录考虑因素:

主要是防止DDOS攻击。无效或垃圾tx过多会导致整个比特币网络崩溃。

mempool收录处理机制:

1 验证tx是否有效。无效直接拒掉

2 验证tx是否已存在。已存在就不用重复劳动了。

3 验证是否为orphan tx。

orphan tx是指有vin找不到prevout的tx。节点存储上限1万个。以每个最大100k计算,是1G内存。

不转发orphan tx。这样ddos只能针对单个节点,无法针对整个网络。

4 验证手续费是否足够

4.1 标准手续费是1000字节10000satoshi。如果符合手续费标准,则直接收录。

标准mempool没有存储上限。1G内存可以存储相当于1000个block(每个block1M)的数据量,这相当于队列长度7天(10分钟1个block)。但是问题是tx覆水难收,一旦新增tx数量开始大于block确认数量,队列就会一直变长下去,最终就不是7天,可能是70天700天,击溃所有的节点。

发tx的成本是每1K 10000satoshi,换算为每1M 0.1BTC,每G 100BTC。如果有人愿意付出1000BTC的成本(外加一些币用于中转,对应的成本是攻击后的这些币的贬值),就可以制造10G的mempool,这将会使多数节点崩溃:(1)多数电脑根本没有10G内存,(2)由于网络转发量大概是数据量的10倍,这会给每个节点制造100G的流量,彻底干扰正常接收tx和block。

4.2 判断是否符合free relay标准。如果符合且freerelay空间足够,则收录。

free relay的空间采用指数衰减算法,相当于每分钟1k字节。对应10分钟10k,即平均每个block 10k。

每个block最多收录50k的no fee tx。因而最大支持50k的tx。(当然,发过50k之后,后面好几个block就收不到no fee tx了)

free relay的判断标准:

以下标准有排列组合。

(1)自己生成的tx,最大1k免费。

(2)收到来自别的节点的tx,最大50k免费。

(3)每个vout的value都大于0.01BTC。(如果找零值很小,也要付费。对策是加一个vin,增大找零值)

(4)如果block快满了,就增长手续费下限,直至达到标准手续费标准,即free relay作废。

mempool清理机制:

只有2种清理机制。

1正常清理。进入block后删除

2 失效清理。如果有vin-prevout被block里的tx花掉了,则删除tx。(即发生double spending)

 

讨论:

1 安全起见当然是1个最好2个block收录之后再承认tx。但是由于比特币1个block最长可达1小时,所以很多人等不起。那么就必须为了效率而承认具有高风险mempool tx。这就需要研究mempool tx的风险机制,以及对应的分辨和降低风险的策略。

1 mempool tx有2个风险:

(1)double spending。即同一个cheque同时发2个不同的tx,每个tx有半数的节点收到。最终由矿工决定收录哪个tx进block,另外一个tx就报废。因而钱包收到的未确认交易,是有报废风险的。这便是block(必须配合pow)的原初意义。当然,如果block发生回撤,则很可能收录入block的tx也被撤销,另外一个tx生效(不是51%攻击,是正常的矿工竞争行为),所以安全起见至少2个block之后才可以确认一笔收入有效。

需要说明的是,如果发生block回撤,一个tx 退回了mempool,而没有被立即收录入新的block,这个tx会存在于所有节点的mempool中,此时如果补发double spending的tx,只能排在这个老tx的后面,会被所有的节点拒掉,所以仍然都是安全的。换言之,double spending的tx必须同时广播,才有攻击的意义。

对于这个风险的对策很清晰:连接全部矿池,从全部矿池中找tx,如果发现double spending,则标记高危;如果没有发现,则这个tx是安全的。

(2) prevout chain double spending。当然是基于上一个,但是“原罪”不同。double spending,是付款给你的人在干坏事。而prevout chain double spending,付款给你的人是好人,他也是受害者。一个tx的prevout和prevout的prevout和之前N个prevout,只要有一个因为double spending而报废,后面所有相关的tx都报废。而由于一个tx有多个vin和vout,这个chain实际上是一个cascade,如果是机器人自动生成tx的话,可能会波及上千个tx。

因而,如果一个mempool tx 的prevout中有mempool tx,则新的这个tx(child tx)具有更高级别的风险。mempool prevout chain越长,风险级别就越高。而且,只有1个确认的prevout,也是具有一定风险的。

所以,只有全部prevout 都具有2个确认的tx,才可以认为是安全的。

2 基于对1风险的防范,会出现新的风险:

因为必须要1个block才承认,所以一个tx如果长时间挂在mempool里,就等同于无效。当block填满之后,矿池按照手续费收录tx,有些tx会因为手续费低一直不被收录,导致无法被承认。而基于这个tx prevout的新的更高手续费的tx,会被视为double spending拒绝。这可能导致一个tx“永久性”地飘在mempool里不得“投胎”block。

理论上这个问题可以根本就不发生,因为现在的比特币节点程序机制是凡是进mempool的tx就按顺序进block,如果想提高收入,就抬高后面的fee标准。但是问题是矿工/矿池是生意,而且“中奖”矿工具有“独断专行大权”,他先收录哪个tx别人根本管不着。

解决方案可能是需要“公益矿池”,专门收录被“拒载”的低手续费tx。但是由于tx满天飞,公益矿池也很难解决问题。这是个大麻烦,容我想想有别的招没。