以太坊网络中,我们发送一笔交易时,可能发送成功,也可能发送失败,那么交易是如何判断能否发送成功的呢。当我们发送交易后,交易会被广播到矿工,矿工会监听交易的广播,然后把交易放到本地的交易池中等待处理,但是交易能否放到交易池中,以及在交易池中的交易如何处理的,具体如下:
当交易进入交易池(tx_pool)时,矿工节点会做以下验证:
通过交易 Hash 判断交易在交易池中是否存在,如果存在就使用新的交易替换以前的交易
验证交易的合法性,如长度、value、是否溢出当前区块的 GasLimit、Nonce 值等、Gas 是否足够,如果验证不通过就会返回对应的错误代码
验证是否孤儿交易,如果是就本地保存,不转发,防止 DDOS 攻击
如果交易池满了,就会验证交易 Gas 是否比当前交易池中的最低 Gas 低,如果低于交易池的最低 Gas 会返回 ErrUnderpriced,如果高于最低值,就剔除最低 Gas 的交易。发生这种情况后,在 etherscan 中会发现在这笔交易 pending 中消失了(也有很大机率依然能够查到这笔交易在 pending 列表中,因为 etherscan 连接了很多节点,每个节点的交易池的状态都是不一样的,那条被踢出的交易可能在别的节点中仍然处于 pending 状态)
如果交易已经在交易池中,会判断 Gas 是否高于上一条相同 Nonce 的交易 Gas 某一个阈值(默认 10%),如果 Gas 高于,就剔除前一笔交易,就使用新的交易替换前一笔交易,如果没有高于当前的交易就会返回失败
按顺序放入到交易池中,等待打包
等待新的交易加入到交易池,会重复上述步骤。
在明白上述逻辑之前我们需要了解几个细节
矿工不能在一个区块中打包任意多的 tx(只能尽可能多的打包),因为一个区块有 GasLimit 限制和区块大小限制。
矿工运行以太坊实例时,是可以根据需要修改最低的 GasPrice 值,这样可以过滤很多低 Gas 的交易。
交易池容纳的交易数默认是有上限的。以太坊的 txpool 中的 pending 集合(miner 是从 pending 中拿交易组装 block 的)中容纳的交易数量默认设置为最大 4096。但是在 Geth v1.6.2 中支持外部重置交易池默认配置。具体是–txpool.globalslots value。在 Parity v1.6.8 中也支持外部设置,具体是 –tx-queue-size LIMIT。Parity 默认是 1024。一个账户默认只能放 16 条交易到 pending 中,满了以后,第 17 条乃至以后更多的交易会有一套规则来替换先前位于 pending 中的 16 条交易。
欢迎订阅「K 叔区块链」– 专注于区块链技术学习 博客地址:http://www.jouypub.com 简书主页:https://www.jianshu.com/u/756c9c8ae984segmentfault 主页:https://segmentfault.com/blog/jouypub 腾讯云主页:https://cloud.tencent.com/developer/column/72548