以太坊nonce

       以太坊系列(ETH&ETC)在發送交易有三個對應的RPC接口,分別是ethsendTransaction、ethsendRawTransaction和personal_sendTransaction。這三個接口發送(或構造發送內容時)都須要一個參數nonce。官方文檔對此參數的解釋是:整數類型,容許使用相同隨機數覆蓋本身發送的處於pending狀態的交易。僅從官網的解釋,咱們沒法獲取到更多的有效的信息。但在真實生成中咱們會發現若是傳錯nonce字段值,經過RPC接口調用發送的交易很大可能將不會被確認。若是經過console命令來操做通常不會出現此問題,由於節點已經幫咱們處理了。api

問題追蹤安全

       若是繼續追蹤問題,會發現nonce傳遞錯誤的交易能夠經過eth_getTransaction查詢獲得相關信息,可是它的blocknumber始終未null,也就說這邊交易始終未被確認。若是是在dev模式下,應該是很快就會被確認的。更進一步,經過txpool.content命令,會發現那筆交易一直處於queued隊列中,而未被消費。網絡

緣由解析排序

       爲了防止交易重播,ETH(ETC)節點要求每筆交易必須有一個nonce數值。每個帳戶從同一個節點發起交易時,這個nonce值從0開始計數,發送一筆nonce對應加1。當前面的nonce處理完成以後纔會處理後面的nonce。注意這裏的前提條件是相同的地址在相同的節點發送交易。接口

       如下是nonce使用的幾條規則:隊列

● 當nonce過小(小於以前已經有交易使用的nonce值),交易會被直接拒絕。                              文檔

● 當nonce太大,交易會一直處於隊列之中,這也就是致使咱們上面描述的問題的緣由;get

● 當發送一個比較大的nonce值,而後補齊開始nonce到那個值之間的nonce,那麼交易依舊能夠被執行。it

 ● 當交易處於queue中時中止geth客戶端,那麼交易queue中的交易會被清除掉。io

獲取nonce值

       通過上面的解釋追蹤,咱們已經瞭解到了nonce的基本使用規則。那麼,在實際應該用中咱們如何保障nonce值的可靠性呢?這裏有兩個思路,第一個思路就是由業務系統維護nonce值的遞增。若是交易發送就出現問題,那麼該地址下一筆交易繼續使用這個nonce進行發送交易。第二個思路就是使用現有的api查詢當前地址已經發送交易的nonce值,而後對其加1,再發送交易。對應的API接口爲:eth_getTransactionCount,此方法由兩個參數,第一個參數爲須要查詢nonce的地址,第二個參數爲block的狀態:latest、earliest和pending。通常狀況使用pending就能夠查詢得到最新已使用的nonce。其餘狀態你們能夠自行驗證。

nonce使用陷阱

熱點帳戶:

       所謂的熱點帳戶就是頻繁被使用的帳戶,在以太坊中好比交易所的統一出幣帳戶,在短期內頻繁發起交易的帳戶,都可被稱做熱點帳戶。

replacement transaction underpriced異常:

       若是系統中的熱點帳戶或普通帳戶發起交易時出現error: replacement transaction underpriced異常,那麼就須要考慮nonce使用是否正確。

引發此異常緣由主要是當一個帳戶發起一筆交易,假設使用nonce爲1,交易已經發送至節點中,但因爲手續費不高或網絡擁堵或nonce值太高,此交易處於queued中遲遲未被打包。

同時此地址再發起一筆交易,若是經過eth_getTransactionCount獲取的nonce值與上一個nonce值相同,用一樣的nonce值再發出交易時,若是手續費高於原來的交易,那麼第一筆交易將會被覆蓋,若是手續費低於原來的交易就會發生上面的異常。

一般發生此異常意味着: 
- 你的Ethereum客戶端中已經有一幣處於pending狀態的交易。 
- 新的一筆交易擁有pending狀態交易相同的nonce值。 
- 新的交易的gas price過小,沒法覆蓋pending狀態的交易。

一般狀況下,覆蓋掉一筆處於pending狀態的交易gas price須要高於原交易的110%。

解決方案:

        針對此問題在不一樣的使用場景下有不一樣的解決方案。

依賴錢包:

        若是該熱點帳戶的私鑰信息等都存放在Ethereum客戶端中,那麼在發送交易的時候不傳遞nonce值,Ethereum客戶端會幫你處理好此nonce值的排序。

固然,此方案有兩個弊端。第一個是安全性沒法保障(未進行冷熱帳戶分離),第二,在熱點帳戶下若是想覆蓋掉一筆交易,須要先查詢一下該交易的信息,從中獲取nonce值。

自行管理nonce:

       自行管理nonce適用於冷熱帳戶模式,也就是適用sendRawTransaction發送已經簽名好的交易時,此時nonce值已經存在於交易中,而且已經被簽名。

這種模式下,須要在業務系統中維護nonce的自增序列,適用一個nonce以後,在業務系統中對nonce進行加一處理。

此種方案也有限制條件。第一,因爲nonce統一進行維護,那麼這個地址必須是內部地址,並且發起交易必須經過統一維護的nonce做爲出口,不然在其餘地方發起交易,原有維護的nonce將會出現混亂。第二,一旦已經發出的交易發生異常,異常交易的nonce未被使用,那麼異常交易的nonce須要從新被使用以後它後面的nonce纔會生效。

總結:

       nonce的使用有不少坑須要踩,你們在具體實踐過程當中一旦發現問題須要及時查找緣由,防止大面積的問題發生,致使整個系統的帳務或資金的錯亂。

相關文章
相關標籤/搜索