Gas是以太坊用於衡量程式執行一個或一組動作所需計算量的單位。交易或合約執行的每項操作都需要一定數量的gas; 所需的gas數量與正在執行的計算步驟的類型和數量有關。與僅以千字節(kB)計算交易規模的比特幣交易費相比,以太坊交易費必須考慮智能合約程式碼可以執行的任意數量的計算步驟。程式執行的操作數越多,運行完成的成本就越高。
每次操作都需要固定量的gas。以太坊黃皮書的的一些例子:
-
添加兩個數字需要3個gas
-
計算Keccak256雜湊值,需要30個gas+ 每256位數據被雜湊6個gas
-
發送交易成本為21000 gas
gas是以太坊的重要組成部分,具有雙重作用。一,作為以太坊價格(具有波動性)和礦工對其工作的獎勵之間的抽象層。另一種是抵禦拒絕服務攻擊。為了防止網路中的意外或惡意無限迴圈或其他計算浪費,每個交易的發起者需要設置他們願意花費在gas上的金額的限制。因此,gas系統阻止攻擊者發送垃圾郵件交易,因為他們必須按比例支付他們消耗的計算,帶寬和儲存資源。
雖然gas有價格,但它不能“擁有”也不能“花”。gas僅存在於以太坊虛擬機(EVM)內部,作為計算工作量的計數。發起方被收取ether交易費,然後轉換為gas,然後轉回到ether,作為礦工的塊獎勵。這些轉換步驟用於將計算的價格(與“工作量”相關)與ether的價格(與市場波動相關)分開。
雖然gas成本是EVM中執行的操作步驟的度量,但gas本身也具有以ether測量的gas價格。在執行交易時,發起方指定他們願意為每個gas單位支付的gas價格(以ether為單位),允許市場決定ether的價格與計算操作的成本之間的關係(以gas衡量) 。
total gas used * gas price paid = transaction fee
,以ether為單位
此金額將在交易執行開始時從發起方的帳戶中扣除。發起方不是設置“total gas used”,而是設置gas limit,該限制應足以覆蓋執行交易所需的gas量。
在發送交易之前,發起方必須指定gas limit - 他們願意購買的最大gas數量。他們還必須指定gas price - 他們願意為每單位gas支付的以太價格。
以ether計算的`gas limit * gas price`在交易執行開始時從發起方的帳戶中扣除作為存款。這是為了防止發送者在執行中期“破產”並且無法支付gas費用。由於這個原因,用戶也無法設置超出其帳戶餘額的gas限制。
理想情況下,發起方將設置一個高於或等於實際使用的gas的gas限制。如果gas限制設置高於消耗的gas量,發貨人將收到超額金額的退款,因為礦工只獲得他們實際工作的補償。
在這種情況下:
`(gas限制 - 多餘gas)*gas價格以太以礦塊作為塊獎勵
(gas limit - excess gas) * gas price
ether作為礦工的區塊獎勵
excess gas * gas price
ether退回發起方
但是,如果使用的gas超過規定的gas限制,即如果在執行期間交易“runs out of gas”,則操作終止。雖然交易不成功,但由於礦工已經完成了計算工作,不會退回發送人的交易費用,礦工因此得到補償。
如果交易是從外部擁有帳戶(EOA)發送的,則從EOA的餘額中扣除gas費。換句話說,交易的發起人正在支付gas費。發起人為交易消耗的總gas以及隨後的任何子執行提供資金。這意味著如果發起者X附加1000個gas來調用合約A,其在計算上花費500個gas然後向合約B發送另一個消息,則A用於將消息發送到B的gas也會再已開始從X的gas限制中扣除。
EOA帳戶X啟動交易並調用合約帳戶A上的功能,附帶1000個gas
合約A在計算上花費500gas,並向合約B發送消耗100gas的消息
合約B在計算上花費300個gas並完成交易。
100個gas退還給X.
因此,如果該交易的發起人在開始時沒有附加足夠高的gas費,那麼在交易中執行一部分操作的中間合約(例如,在我們的範例中為合約A)理論上可以耗盡gas。如果合約在執行中期用完,除了gas費支付外,所有狀態變更都會被撤銷。
通過假裝交易已經被包含在區塊鏈中來估算gas,然後返回如果操作是真實的那麼可以收取的確切gas量。換句話說,它使用與礦工用來計算實際費用但從未開採過區塊鏈的完全相同的程式。
請注意,由於各種原因(包括EVM機制和節點性能),估計值可能遠遠超過交易實際使用的gas量。
var result = web3.eth.estimateGas({
to: "0xc4abd0339eb8d57087278718986382264244252f",
data: "0xc6888fa10000000000000000000000000000000000000000000000000000000000000003"
});
console.log(result); // "0x0000000000000000000000000000000000000000000000000000000000000015"
gas價格是交易發起方願意為每個gas單位支付的ether量。開採下一個區塊的礦工決定要包括哪些交易。由於gas價格被計入他們將作為獎勵的交易費中,他們更可能首先包括具有最高gas價格的交易。如果發起方將gas價格設置得太低,他們可能需要等待很長時間才能將其交易進入一個區塊。
礦工還可以決定塊中包含交易的順序。由於多個礦工競爭將其區塊附加到區塊鏈,因此區塊內的交易順序由“獲勝”礦工任意決定,然後其他礦工用該訂單核實。雖然可以任意排列來自不同帳戶的交易,但是來自個人帳戶的交易是按照自動遞增的隨機數的順序執行的。
區塊gas限制是區塊中允許的最大gas量,用於確定區塊中可以容納的交易數量。例如,假設我們有5個交易,其中每個交易的gas限制為10,20,30,40和50.如果區塊gas限制為100,那麼前四個交易可以適合該區塊,而交易5必須等待未來的區塊。如前所述,礦工決定在一個區塊中包含哪些交易。不同的礦工可以嘗試包括塊中的最後2個交易(50 + 40),並且它們僅具有包括第一個交易(10)的空間。如果你嘗試包含的交易需要的gas量超過當前的gas限制,則網路將拒絕該交易,你的以太坊客戶將向你發送消息“交易超過區塊gas限制。根據https://etherscan.io的數據,目前區塊的gas限制在500萬左右。即一個區塊可以容納約238個交易,每個交易消耗21000個gas。
網路上的礦工決定區塊gas限制是什麼。想要在以太坊網路上挖礦的個人使用挖礦程式,例如ethminer,它連接到Geth或Parity Ethereum客戶端。以太坊協議有一個內建機制,礦工可以對gas限制進行投票,因此無需在硬分叉上進行協調就可以增加容量。塊的礦工能夠在任一方向上將塊氣限制調整1/1024(0.0976%)。其結果是根據當時網路的需要調整塊大小。這一機制與預設的開採策略結合在一起,礦工預設將投票決定至少470萬的gas限制,但如果這一數字更高的話,將把目標對準最近的(1024區塊指數移動)平均gas的150%,從而使數量有機地增加。礦工們可以選擇改變這一點,但是他們中的許多人不這樣做,並保留預設值。
以太坊通過退還高達一半的gas費用來鼓勵刪除儲存的變數。 EVM中有2個負的gas操作:
清理合約是-24,000(SELFDESTRUCT) 清理儲存為-15,000(SSTORE [x] = 0)
GasToken是一種符合ERC20標準的token,允許任何人在gas價格低時“儲存”gas,並在gas價格高時使用gas。通過使其成為可交易的資產,它基本上創造了一個gas市場。 它的工作原理是利用前面描述的gas退款機制。
目前,以太坊社區提出了一項關於向智能合約收取“租金”以保持活力的建議。
在沒有支付租金的情況下,智能合約將被“睡眠”,即使是簡單的讀取操作也無法獲得數據。需要通過支付租金和提交Merkle證據來喚醒進入睡眠狀態的合約。