這篇文章是用來幫助人們理解以太坊網絡上的一些基本概念和體系,包括賬戶體系、gas、礦工在區塊大小設置機制裡的角色等。
什麼是賬戶?
外部擁有賬戶 vs 合約賬戶
以太坊中有兩種賬戶
外部擁有賬戶(EOA)
合約賬戶
這個區別在即將到來的大都會升級中將會被抽象化。
外部擁有賬戶
一個外部擁有賬戶具有一下特性:
有一個以太幣餘額
可以發送交易(以太幣轉賬或者激活合約代碼)
通過私鑰控制
沒有相關聯的代碼
合約賬戶
一個合約賬戶擁有一下特性:
有一個以太幣餘額
有相關聯的代碼
代碼執行是通過交易或者其他合約發送的call來激活
當被執行時 -- 運行在隨機複雜度 (圖靈完備性)-- 只能操作其擁有的特定儲存,例如可以擁有其永久state -- 可以call其他合約
所有以太坊區塊鏈上的行動都是由各賬戶發送的交易激活。每次一個合約賬戶收到一個交易,交易自帶的參數都會成為代碼的輸入值運行。合約代碼會被以太坊虛擬機(EVM)在每一個參與網絡的節點上運行,以作為它們新區塊的驗證。
什麼是交易和消息?
交易
"交易"這個術語在以太坊裡被用來指代一個用來存儲消息的被簽名數據包在區塊鏈上從一個外部擁有賬戶發送至另一個賬戶的過程。
交易包括:
這個消息的接收者
一個簽名,用來證明發送者有意向通過區塊鏈向接收者發送消息
價值域 - 從發送方轉移到接受方的wei (ether/10^18) 的數量
一個可選的數據域,用來儲存發送給合約的消息
一個GASLIMIT值,代表了這個交易的執行最多被允許使用的計算步驟
一個GASPRICE值,代表了交易發送者願意支付的gas費用。一個單位的gas表示了執行一個基本指令,例如一個計算步驟
消息
合約具有發送"消息"到其他合約的能力。消息是一個永不串行且只在以太坊執行環境中存在的虛擬對象。他們可以被理解為函數調用(function calls)。
一個消息包括:
明確的消息發送者
消息的接收者
一個可選的數據域,這是合約實際上的輸入數據
一個GASLIMIT值,用來限制這個消息出發的代碼執行可用的最大gas數量
總的來說,一個消息就像是一個交易,除了它不是由外部賬戶生成,而是合約賬戶生成。當合約正在執行的代碼中運行了
CALL
或者DELEGATECALL
這兩個命令時,就會生成一個消息。消息有的時候也被稱為"內部交易"。與一個交易類似,一個消息會引導接收的賬戶運行它的代碼。因此,合約賬戶可以與其他合約賬戶發生關係,這點和外部賬戶一樣。有許多人會誤用交易這個詞指代消息,所以可能消息這個詞已經由於社區的共識而慢慢退出大家的視野,不再被使用。什麼是 gas?
以太坊在區塊鏈上實現了一個運行環境,被稱為以太坊虛擬機(EVM)。每個參與到網絡的節點都會運行都會運行EVM作為區塊驗證協議的一部分。他們會驗證區塊中涵蓋的每個交易並在EVM中運行交易所觸發的代碼。每個網絡中的全節點都會進行相同的計算並儲存相同的值。合約執行會在所有節點中被多次重複,這個事實得使得合約執行的消耗變得昂貴,所以這也促使大家將能在鏈下進行的運算都不放到區塊鏈上進行。對於每個被執行的命令都會有一個特定的消耗,用單位gas計數。每個合約可以利用的命令都會有一個相應的gas值。這裡列了一些命令的gas消耗。
gas和交易消耗的gas
每筆交易都被要求包括一個gas limit(有的時候被稱為startGas
)和一個交易願為單位gas支付的費用。礦工可以有選擇的打包這些交易並收取這些費用。在現實中,今天所有的交易最終都是由礦工選擇的,但是用戶所選擇支付的交易費用多少會影響到該交易被打包所需等待的時長。如果該交易由於計算,包括原始消息和一些觸發的其他消息,需要使用的gas數量小於或等於所設置的gas limit,那麼這個交易會被處理。如果gas總消耗超過gas limit,那麼所有的操作都會被複原,但交易是成立的並且交易費任會被礦工收取。區塊鏈會顯示這筆交易完成嘗試,但因為沒有提供足夠的gas導致所有的合約命令都被複原。所以交易裡沒有被使用的超量gas都會以以太幣的形式打回給交易發起者。因為gas消耗一般只是一個大致估算,所以許多用戶會超額支付gas來保證他們的交易會被接受。這沒什麼問題,因為多餘的gas會被退回給你。
估算交易消耗
一個交易的交易費由兩個因素組成:
gasUsed
:該交易消耗的總gas數量gasPrice
:該交易中單位gas的價格(用以太幣計算)
交易費 = gasUsed * gasPrice
gasUsed
每個EVM中的命令都被設置了相應的gas消耗值。gasUsed是所有被執行的命令的gas消耗值總和。
如果希望估算gasUsed,可以使用這個estimateGas的API
gasPrice
一個用戶可以構建和簽名一筆交易,但每個用戶都可以各自設置自己希望使用的gasPrice
,甚至可以是0。然而,以太坊客戶端的Frontier版本有一個默認的gasPrice
,即0.05e12 wei。礦工為了最大化他們的收益,如果大量的交易都是使用默認
gasPrice
即0.05e12 wei,那麼基本上就很難又礦工去接受一個低gasPrice
交易,更別說0 gasPrice
交易了。交易費案例
在被允許後,我將使用這個MyEtherWallet團隊的例子並借用他們的分析。請參考他們與gas相關的介紹。他們還有一個小頁面方便大家把以太幣轉換成小單位的gas計數單位。
你可以將gasLimit理解為你汽車油箱的上限。同時將gasPrice理解為油價。
對於一輛車來說,油價可能是 $2.5(價格)每升(單位)。在以太坊中,就是20 GWei(價格)每gas(單位)。為了填滿你的"油箱",需要 10升$2.5的油 = $25。同樣的,21000個20 GWei的gas = 0.00042 ETH。
因此,總交易費將會是0.00042以太幣。
發送代幣通常需要消耗大約5萬至10萬的gas,所以總交易費會上升0.001至0.002個ETH。
什麼是"區塊gas limit"?
區塊gas limit是單個區塊允許的最多gas總量,以此可以用來決定單個區塊中能打包多少筆交易。例如,我們有5筆交易的gas limit分別是10、20、30、40和50.如果區塊gas limit是100,那麼前4筆交易就能被成功打包進入這個區塊。礦工有權決定將哪些交易打包入區塊。所以,另一個礦工可以選擇打包最後兩筆交易進入這個區塊(50+40),然後再將第一筆交易打包(10)。如果你嘗試將一個會使用超過當前區塊gas limit的交易打包,這個交易會被網絡拒絕,你的以太坊客戶端會反饋錯誤"交易超過區塊gas limit"。以下例子是來自於以太坊StackExhcange的帖子。
目前區塊的gas limit是 4,712,357 gas,數據來自於ethstats.net,這表示著大約224筆轉賬交易(gas limit為21000)可以被塞進一個區塊(區塊時間大約在15-20秒間波動)。這個協議允許每個區塊的礦工調整區塊gas limit,任意加減 1/2024(0.0976%)。
誰來決定
區塊的gas limit是由在網絡上的礦工決定的。與可調整的區塊gas limit協議不同的是一個默認的挖礦策略,即大多數客戶端默認最小區塊gas limit為4,712,388。
區塊gas limit是怎樣改變的
以太坊上的礦工需要用一個挖礦軟件,例如ethminer。它會連接到一個geth或者Parity以太坊客戶端。Geth和Pairty都有讓礦工可以更改配置的選項。這裡是geth挖礦命令行選項以及Parity的選項。
以太坊網絡上的"DoS"攻擊是什麼?
最近有些評論表示以太坊網絡正在慢慢減速,變得擁堵甚至無法使用。這些評論把這個減速的過程稱為對以太坊網絡的"DoS"攻擊。當以太坊網絡上持續地出現全滿區塊並且有大量交易在網絡上待處理時就會出現所謂的DoS情況。同時,礦工有權利根據交易費選擇打包哪些交易。如果當時隊列中(交易池中)有上千筆交易正在等待打包,那麼就有可能造成幾個小時的非正常交易延遲。DDoS可能是惡意的也有可能是非惡意的。
惡意的DoS
上個秋天,以太坊被某人或某個團體攻擊了,通過大量製造垃圾交易。這次攻擊在如下博客有介紹:
攻擊者通過在他們的智能合約中反覆的調用某些命令來讓客戶端難以處理這些計算,但是這些命令都只消耗少量的gas所以調用起來十分廉價。
在這次攻擊中,礦工被要求降低gas limit到150萬,在後來的另一次事件中更改到了200萬。也有幾次其他的事件要求礦工在網絡被攻擊時降低區塊gas limit。
非惡意的DoS
非惡意的DoS其實就是當網絡面臨海量交易時需要比平常更多的時間來處理一筆交易。最近由於ICO的流行,以太坊網絡多次被交易填滿。Infura的朋友們寫過一篇與此相關的技術分析文章。
為什麼區塊gas limit在區塊被填滿時不會自動調整?
主要原因:礦工們沒有使用gas limit動態調整的功能。
以太坊協議中存在著讓礦工可以通過投票來決定gas limit的機制,所以區塊容量不需要經過硬分叉就可以調整。最初,這個機制和另一個默認策略是綁定在一起的,即礦工默認投票使區塊gas limit至少有470萬,並且趨向於最近1024個區塊gas使用量的1.5倍。這使得區塊容量會根據需求來自動上升,同時也有一個可用來防禦垃圾交易的限制。
就像"惡意的DoS"部分說的,在歷史上有幾次礦工因為攻擊的原因不得不使用非默認設置來幫助降低攻擊造成的影響。但現在的問題是礦池在攻擊之後並沒有將設置改回默認設置。大約一個月前,礦工被要求改變gas limit和gas price設置來再次加入gas limit動態調整功能。因為最近的代幣銷售火爆導致很多區塊被填滿並且區塊鏈交易堵塞。
ETH Gas Station是一個人們可以查閱最新區塊gas limit設置的網站。
礦工需要做什麼才能修復這個問題?
礦工可以在Geth或者Parity客戶端中更改設置來重啟動態gas limit調整。注意:這些設置是在這個Reddit帖子找到的,其實可以被設置的更高(參考這個帖子)。
Geth
推薦設置
--gasprice 4000000000 --targetgaslimit 4712388
解釋
--targetgaslimit Target gas limit sets the artificial target gas floor for the blocks to mine (default: “4712388”) --gasprice Minimal gas price to accept for mining a transactions (default: “20000000000”). Note: gasprice is listed in wei.
Parity
推薦設置
--gas-floor-target 4712388 --gas-cap 9000000 --gasprice 4000000000
解釋
--gas-floor-target Amount of gas per block to target when sealing a new block (default: 4700000).
--gas-cap A cap on how large we will raise the gas limit per block due to transaction volume (default: 6283184).
--gasprice Minimum amount of Wei per GAS to be paid for a transaction to be accepted for mining. Note: gasprice is listed in wei. Note 2: --gasprice is a “Legacy Option”
其他挖礦設置選項
可以參考CLI選項頁面來看看礦工還能如何調整優化設置。
Resources and Further Reading
Eth Gas Station website with Ethereum gas and miner stats.
Ethereum StackExchange for technical questions of all kinds.
EthDocs Ethereum Documentation (Much of it is outdated, but still good).
“Ethereum Gas, Fuel and Fees” by Joseph Chow.
“What is Gas?” by MyEtherWallet.
MyEtherWallet Ether unit conversion tool.
“When there are too many pending transactions” by Infura.
原文鏈接: http://hudsonjameson.com/2017-06-27-accounts-transactions-gas-ethereum/
翻譯&校對: 許昕
閱讀更多 以太坊愛好者 的文章