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中登記賬戶的交易