在以太坊的世界中,不知道大家是否有想過以下的問題
以上這些問題,其實都與 Nonce 息息相關,接下來讓我們帶領大家認識什麼是 Nonce 以及他在以太坊中的作用吧!
💡注意: nonce 一般代表著一次性的數字,在 web3 中(可以改成在“區塊鏈世界中”,區塊鏈的搜尋量比 web3 高)常常會在很多地方看到這個詞,但是放在不同地方的意義可能都不盡相同。而本篇所要討論的是發送交易時帶上的 nonce,也就是 Ethereum 協定中原生定義的 nonce,也就是 Transaction nonce。
在 Metamask 上查看 Transaction Nonce
在 Etherscan 上查看 Transaction Nonce
Nonce 值由 0 起算,也就是説對於一個 EOA 地址來說,Nonce 值為 0 的交易代表為該地址發起的第一筆交易。在 Metamask 中,Nonce 值會被自動帶上下一個可用的 Nonce 值,也就是説如果一個 EOA 地址已經發起並確認過的交易數為 3 筆時(即分別為 nonce 0, 1, 2 三筆交易),Metamask 會自動為用戶在交易中帶入下一個可用的 Nonce 值,也就是 3。
TL;DR
在以太坊的世界中,節點可能以無序的方式接收交易,但為了確保所有節點對於每個地址的狀態都要計算出相同的結果,因此引入 Nonce 的機制來強制每個地址發出的交易必須依照順序來執行。舉例來說,Alice 有一個擁有 10 顆 ETH 的 EOA 地址,這時他發起兩筆交易轉帳給 Bob 與 Carol 各 6 顆 ETH,兩個交易的 Nonce 值分別為 0 與 1。無論哪個節點先收到由 Alice 轉帳給 Carol 的交易(也就是 Nonce 值為 1 的交易),該節點都必須等到 Alice 轉帳給 Bob 的交易成功紀錄上鏈(也就是 Nonce 值為 0 的交易),才會執行由 Alice 轉帳給 Carol 的交易。如此一來不管是哪個節點都會得到以下結果
此外,由於鏈上數據是公開的,也就是說對於 Alice 轉帳給 Bob 這個行為是可以被任何人看到的。那麼以太坊要如何知道這筆交易已經被處理過,並且無法讓有心人士複製該交易並且進行重放攻擊呢?
這裡的 Nonce 機制就對執行過的交易起到的保護作用。對於在鏈上看到交易的第三者來說,除了轉帳對象以及轉帳金額一樣以外,最重要的 Nonce 值也是相同,所以就算第三者透過鏈上觀察到這筆交易的所有資訊,想對其進行重送這筆交易,也會因為該 Nonce 值已經被使用過而無法對其進行重送攻擊。
首先 Metamask 右上角的設定中選擇 ”進階“,把客製化 transaction nonce 的功能打開
將來發送交易時,就能自動設定 Nonce 值
一般來說 Nonce 值會由 Metamask 動態計算而得,所以一般情況下不需要特別設定即可正常運作。
但假設今天有一筆交易已經發出去但遲遲未執行,這時有可能是你發送的 gas fee 過低,導致沒有人願意為其打包執行上鏈。而根據 Nonce 的機制,如果你繼續發送新的交易也會因為前一筆交易遲遲未打包而無法被執行。為了解決這樣的情況,我們就會需要找出 “被卡住“ 的那筆交易的 Nonce 值,並且發送一筆新交易且帶上與 "被卡住“ 的交易相同的 Nonce 值,拉高 gas fee,才能解決交易被卡住的問題。
要取消交易,我們首先必須知道什麼樣的交易可以被取消。在我們將交易送出去到上鏈打包的過程中,交易會短暫在一個地方(這裡我們稱之為交易池)等待被執行,而我們有機會取消的就是這些在交易池中等待被執行的交易,因為交易一旦執行上鏈後就無法取消。
那我們該如何取消交易池中的交易,其實與前面解決被卡住的交易是相同的道理。假設今天想取消我們發送出去的交易,那我們就必須搶在交易要上鏈執行之前,找出要取消交易的 Nonce 值,這時候我們只需要重新發送一筆交易帶上該筆交易的 Nonce 值,並提高 gas fee 來爭取優先被執行的可能。透過這種方式,我們就能夠取消在交易池中的交易。
前面有提到 Nonce 值會透過動態計算而得,屬於地址本身的屬性,並不會記錄在鏈上!
如果發送一筆交易的 Nonce 值設定過高,則會需要等待中間所有 Nonce 值的交易被打包上鏈後才會執行。
如果發送一筆交易的 Nonce 值設定過低,則會因為使用無效的 Nonce 值而終止交易。