1. 程式人生 > >以太坊交易池(txpool)的管理

以太坊交易池(txpool)的管理

txpool對應的啟動引數

我們先來了解一下,針對txpool有哪些引數項可以設定,然後著重分析。

  1. --txpool.nolocals 為本地提交交易禁用價格豁免
  2. --txpool.journal value 本地交易的磁碟日誌:用於節點重啟 (預設: "transactions.rlp")
  3. --txpool.rejournal value 重新生成本地交易日誌的時間間隔 (預設: 1小時)
  4. --txpool.pricelimit value 加入交易池的最小的gas價格限制(預設: 1)
  5. --txpool.pricebump value 價格波動百分比(相對之前已有交易) (預設: 10)
  6. --txpool.accountslots value 每個帳戶保證可執行的最少交易槽數量 (預設: 16)
  7. --txpool.globalslots value 所有帳戶可執行的最大交易槽數量 (預設: 4096)
  8. --txpool.accountqueue value 每個帳戶允許的最多非可執行交易槽數量 (預設: 64)
  9. --txpool.globalqueue value 所有帳戶非可執行交易最大槽數量 (預設: 1024)
  10. --txpool.lifetime value 非可執行交易最大入隊時間(預設: 3小時)

txpool內容的檢視

  1. > txpool.content
  2. {
  3. pending: {},
  4. queued: {}
  5. }

很顯然,txpool中由兩部分構成pending和queued組成。那麼他們兩者有什麼分別呢。最明顯的是一個為待打包狀態,一個為佇列中。這裡我們發起了兩筆不同的交易:

  1. > eth.sendTransaction({from:"0xdae19174969a7404e222c24b6726e4d089c12768",to:"0x5929a871f57a1C5F7E4eA304CAe92DACD1C1556b",value:web3.toWei(0.01,"ether"),gasPrice:21000000000,nonce:2});
  2. "0x7db7883bb23a31deb9f01b5e6fb28363b1aee1b9b6797ea8b5706be170a1187c"
  3. > eth.sendTransaction({from:"0xdae19174969a7404e222c24b6726e4d089c12768",to:"0x5929a871f57a1C5F7E4eA304CAe92DACD1C1556b",value:web3.toWei(0.01,"ether")});
  4. "0x2784a79a8c454c72700e7be3b31c1c98ceaea232ca4992a6830b0fc999ebb653"

很顯然,第一筆交易指定了nonce為2,第二筆交易未指定nonce值,因為此地址沒有發起過交易那麼nonce值預設為0。這時我們再看一下txpool中的內容:

  1. > txpool.content
  2. {
  3. pending: {
  4. 0xdAE19174969A7404e222c24B6726E4D089c12768: {
  5. 0: {
  6. blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  7. blockNumber: null,
  8. from: "0xdae19174969a7404e222c24b6726e4d089c12768",
  9. gas: "0x15f90",
  10. gasPrice: "0x1",
  11. hash: "0x2784a79a8c454c72700e7be3b31c1c98ceaea232ca4992a6830b0fc999ebb653",
  12. input: "0x",
  13. nonce: "0x0",
  14. r: "0xdabcd46d8d0b61e468d9f10119d544437f89cd094c35a89e5cbed298faf52c4a",
  15. s: "0x3670f23ecfb0a12e982a60438640fe042eefc50646a077de0244a8d67a84af9e",
  16. to: "0x5929a871f57a1c5f7e4ea304cae92dacd1c1556b",
  17. transactionIndex: "0x0",
  18. v: "0xa95",
  19. value: "0x2386f26fc10000"
  20. }
  21. }
  22. },
  23. queued: {
  24. 0xdAE19174969A7404e222c24B6726E4D089c12768: {
  25. 2: {
  26. blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  27. blockNumber: null,
  28. from: "0xdae19174969a7404e222c24b6726e4d089c12768",
  29. gas: "0x15f90",
  30. gasPrice: "0x4e3b29200",
  31. hash: "0x7db7883bb23a31deb9f01b5e6fb28363b1aee1b9b6797ea8b5706be170a1187c",
  32. input: "0x",
  33. nonce: "0x2",
  34. r: "0xa8953a87c326c02da9d7a712d6c7ac0cd415cbc71ea0c24423f9e01b1fec65bd",
  35. s: "0x3faefc3a0db585a67f02996a7167890e41ff5fd8fd4be6efff3bea7a797fad29",
  36. to: "0x5929a871f57a1c5f7e4ea304cae92dacd1c1556b",
  37. transactionIndex: "0x0",
  38. v: "0xa96",
  39. value: "0x2386f26fc10000"
  40. }
  41. }
  42. }
  43. }

現在txpool中有兩筆交易,其中nonce為0的在pending中,nonce為2的在queued中。為什麼只有nonce不同的兩筆交易,在txpool中的位置卻不同呢?

txpool的處理流程

首先,如果不傳入nonce值,那麼geth節點會預設計算當前地址已經發起了的交易中最大的nonce值為多少,然後將其+1,然後將此交易放置在pending中,等待節點打包。

其次,如果傳入的nonce值過大,在進入txpool中檢查到它之前的nonce並沒有使用過,那麼此筆交易不會發送到pending中,而且放置在queued中。只有當前面的nonce補齊之後,才會進入到pending中。那麼,我們再發一筆交易把nonce補齊看看:

  1. > eth.sendTransaction({from:"0xdae19174969a7404e222c24b6726e4d089c12768",to:"0x5929a871f57a1C5F7E4eA304CAe92DACD1C1556b",value:web3.toWei(0.01,"ether")});
  2. "0x7ee17d38405c01bab4eec4d9dc62a6bba98283e243a2d9132187706485878ef5"
  3. > txpool.content
  4. {
  5. pending: {
  6. 0xdAE19174969A7404e222c24B6726E4D089c12768: {
  7. 0: {
  8. blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  9. blockNumber: null,
  10. from: "0xdae19174969a7404e222c24b6726e4d089c12768",
  11. gas: "0x15f90",
  12. gasPrice: "0x1",
  13. hash: "0x2784a79a8c454c72700e7be3b31c1c98ceaea232ca4992a6830b0fc999ebb653",
  14. input: "0x",
  15. nonce: "0x0",
  16. r: "0xdabcd46d8d0b61e468d9f10119d544437f89cd094c35a89e5cbed298faf52c4a",
  17. s: "0x3670f23ecfb0a12e982a60438640fe042eefc50646a077de0244a8d67a84af9e",
  18. to: "0x5929a871f57a1c5f7e4ea304cae92dacd1c1556b",
  19. transactionIndex: "0x0",
  20. v: "0xa95",
  21. value: "0x2386f26fc10000"
  22. },
  23. 1: {
  24. blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  25. blockNumber: null,
  26. from: "0xdae19174969a7404e222c24b6726e4d089c12768",
  27. gas: "0x15f90",
  28. gasPrice: "0x1",
  29. hash: "0x7ee17d38405c01bab4eec4d9dc62a6bba98283e243a2d9132187706485878ef5",
  30. input: "0x",
  31. nonce: "0x1",
  32. r: "0xe03fb4d94b0ff04107c855bfd88a84ecdefb03f4c9b0cea5341591aa69d4751e",
  33. s: "0x4d2f60f4045e5492cd4818145cec73c78b00e0cff57026c4528d91a82dee76e1",
  34. to: "0x5929a871f57a1c5f7e4ea304cae92dacd1c1556b",
  35. transactionIndex: "0x0",
  36. v: "0xa96",
  37. value: "0x2386f26fc10000"
  38. },
  39. 2: {
  40. blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  41. blockNumber: null,
  42. from: "0xdae19174969a7404e222c24b6726e4d089c12768",
  43. gas: "0x15f90",
  44. gasPrice: "0x4e3b29200",
  45. hash: "0x7db7883bb23a31deb9f01b5e6fb28363b1aee1b9b6797ea8b5706be170a1187c",
  46. input: "0x",
  47. nonce: "0x2",
  48. r: "0xa8953a87c326c02da9d7a712d6c7ac0cd415cbc71ea0c24423f9e01b1fec65bd",
  49. s: "0x3faefc3a0db585a67f02996a7167890e41ff5fd8fd4be6efff3bea7a797fad29",
  50. to: "0x5929a871f57a1c5f7e4ea304cae92dacd1c1556b",
  51. transactionIndex: "0x0",
  52. v: "0xa96",
  53. value: "0x2386f26fc10000"
  54. }
  55. }
  56. },
  57. queued: {}
  58. }

很明顯,當中間的nonce被補齊之後,原來處於queued當中的交易被放置到了pending中。

經驗之談

前文提到的如何處理過期交易中提到了補齊nonce和設定—txpool.lifetime也是基於今天這批文章講述的基礎邏輯。除此之外,我們還要了解一下—txpool.accountqueue引數,它定義了每個賬戶在本節點queued中存放的最多的交易個數,預設是64個交易。

另外為了避免手續費過低導致交易一直存在於txpool當中佔用記憶體,可以通過console設定手續費的最低值:

  1. >miner.setGasPrice(51000000000)
  2. true

或者在啟動引數上新增:

  1. --gasprice "51000000000"