txpool 详解
交易池 txpool 作为区块链系统的重要组成部分, 对系统的安全性和稳定性具有重要作用. 功能可归纳为: 交易缓存, 交易验证和交易过滤.
基本介绍
交易分类和缓存
txpool 主要包含两个重要的缓冲区: pending 和 queue. 交易在进行打包验证和 p2p 广播前, 首先要通过 txpool 来进行层层验证, 验证过的交易会被换存在 pending 和 queue 中, 等待进一步处理.
图 1: peding 和 queue 缓冲区
其中, 换存在 pending 中的交易可被立即处理并打包, queue 中的交易是 nonce-gap 交易, 当 nonce-gap 消除后, 会被迁移到 pending 缓存中.
事件处理
交易池在符合条件下, 会处理以下事件:
report: 统计交易池中 pending 和 queue 中交易数量(default 8s)
evict: 交易失效检查事件(1min), 从 queue 中剔除 3 个小时前的交易,(类似挂单, 超时删除)
journal: 本地交易日志(缓存 pending 和 queue 队列中属于本地的交易, 白名单交易, 默认存储于 transactions.rlp)
chainHeadEvent: 收到新块后交易池的处理, 调用 reset
核心功能
交易池状态重置
启动
收到新块~
图 2: 缓冲区状态重置
启动时, 从本地获取当前区块状态, 设置 pending 和 queue 缓冲, 设置 txpool 状态 db; 收到合法块的时候, 重置交易池状态到新块 root, 调整 pending 和 queue 缓冲区以对应新的区块高度.
注: eth 按照 td 最大作为最长链, 在交易池重置状态时需要计算 old 链与 new 链中交易的差集, 并重新进行广播, 重新打包.
交易入池
p2p 网络
本地节点
图 3: 交易入池和检查
交易的来源包括 p2p 广播和本地节点 rpc 接收. 当 txpool 接收到交易后, 会对每笔交易进行一连串严格的检查, 包括:
余额
nonce
交易 Gas
签名
交易大小
交易 value, 等等
交易的升级和降级
- Queue -> Pending
- Pending -> Queue
图 4: 交易升级和降级
pending 和 queue 两个缓冲区的交易是动态调整的, 比如当由于删除了某笔交易造成较大 nonce 从可执行状态变为不可执行状态, 会导致 pending 中的交易迁移到 queue 中; 当由于新添加交易消除了 queue 中 nonce-gap 交易时, queue 中缓存的部分交易会迁移到 pending 中, 变为可执行状态.
缓冲区溢出及处理
在 txpool 中, 缓冲区不是无限的, 受限于硬件设备以及出于安全性考虑, pending 和 queue 所容纳的交易量通过一组参数 / 阈值进行限制: AccountSlots,GlobalSlots,AccountQueue 和 GlobalQueue. 其中, 前两个与 pending 缓冲区有关, 后两个用来限制 queue 缓冲区大小.
缓冲区溢出 (交易超过阈值) 的三种情况:
all 溢出, Count(all)> GlobalSlots + GlobalQueue
pending 溢出, Count(pending)> GlobalSlots
queue 溢出, Count(queue)> GlobalQueue
第一种情况起因一般是有新的交易入池, 后两种情况起因除了新交易入池外, 还有可能是删除交易或交易替换引起的两者之间的动态调整.
对应的处理策略:
all 溢出. 新交易如果是 Unpriced, 拒绝; 否则删除旧交易, 插入新交易
pending 溢出. 建立一个关于账户交易数的优先队列, 对超过交易数限额 AccountSlots 的账户进行惩罚, 按照图 5 所示策略剔除交易, 降低交易池负载
queue 溢出. 删除滞留在 queue 中最旧的交易.
图 5. pending 溢出交易剔除策略
说明: 首先, 建立一个超限额账户的优先队列; 取出交易最多的两个账户(蓝色和红色), 从交易最多的账户开始删除交易, 直到与红色相等, 如果 pending 仍溢出, 从优先队列中取出下一个账户(紫色), 重复前面的过程.
最后, 如果优先队列为空, pending 仍溢出, 那么按照账户的取出顺序, 每次删除一笔交易, 直到 pending 内交易量小于 GlobalSlots 阈值.
交易过滤
超时过滤
gas 最大过滤, GasLimit
gasPrice 过滤
Local 白名单
local 交易会被登记入 pool.locals, 类似一个白名单, 添加交易的时候不对 gasPrice 进行检查. 缓冲区执行交易剔除相关策略时, 不删除在 pools.locals 中登记账户的交易
来源: https://www.cnblogs.com/informatics/p/10417121.html