iT邦幫忙

2025 iThome 鐵人賽

DAY 10
1

交易的生命週期

特務 K 回想一下目前經歷了些什麼。(有些前面沒提到的細節是小雨幫忙補上的)

  • 一個點對點網路組成的電腦提供服務
  • 使用者發動交易向網路提供服務
  • 驗證者監聽網路中廣播來的交易,再把使用者的交易打包到區塊裡
  • 系統根據區塊滿載程度調整系統費
  • 使用者要為其交易繳交手續費。一部分是系統費,一部分是給驗證者的小費。
  • 打包完成的區塊最後被廣播到網路上
  • 全節點會監聽網路上廣播來的區塊,照裡面的交易一筆一筆去執行,並更新全節點記載的全域狀態。

以太坊虛擬機

「我們看到了交易裡面的原始輸入、看到了合約裡面的位元組碼,到底這個交易執行是怎麼運作的呢?」特務 K 問。

「背後用的東西叫 EVM 以太坊虛擬機(Ethereum Virtual Machine) 」小雨說。

小雨的百寶袋裡,不乏奇奇怪怪的工具網站,現在又拿出了 https://www.evm.codes/

特務 K 在網站中看到各種 操作碼(Opcode) , STOP, ADD, MUL, SUB, DIV

「這些操作碼是什麼呢?」

「他們是最小的運算單元,所有更複雜的運算都是由一個個小小的操作碼組成的」

「以太坊的設計是讓全節點能夠重新驗算區塊裡面的交易,確保網路的節點能得到一致的狀態」小雨接著解釋。

「這些節點背後可能是我古老的 Windows 桌電、資料中心裡面的高速電腦、或是一台 ipad ,不同的硬體、不同的作業系統,難道他們都有辦法算出一樣的東西嗎?」特務 K 疑惑。

「這就是為什麼需要抽象出一個針對點對點網路所使用的 指令集架構(Instruction Set Architecture, ISA)」小雨說「當然最低的硬體性能還是得要求,但把運算抽象成軟體之後,就能避免硬體上的差異了」

「指令集架構我看維基百科上面都是在談 CPU ,針對點對點網路所使用的指令集架構有什麼樣的特色呢?」

「第一是同樣的輸入必須要得到一樣的運算結果,要有 確定性(Deterministic) 」小雨說「例如不能有個 隨機數指令 會讓輸出都不一樣」

「這樣就不能寫投骰子之類的程式嗎?」特務 K 問

「還是能寫出投骰子程式,但亂數來源需要從區塊之類的資料來」

「第二是要能對運算 跳表(Metering) ,像計程車對路程跳表一樣」小雨說「我才能說一個區塊的時間已經負擔了多少運算」

「了解,這樣能配合前面說的手續費做負載平衡」

「第三是因為現在這台電腦不只是個人使用,而是給全世界的人使用,所以假設壞人存在,且要避免壞人玩壞他」

特務 K 兩眼一亮,他最喜歡破壞了。

運算資源

特務 K 看了網站的操作碼,大概有百來個。

「我要怎麼看這百來個操作碼呢?」特務 K 問。

「也許可以照運算資源,以及從執行環境抽象出來的結構來看」小雨說。

從最底層硬體來看。為了去中心化,以太坊對節點最低的硬體需求是「消費者等級」的電腦。我們可以看到 Geth 文件 列出以下建議:

  • 四核心的 CPU
  • 16GB RAM
  • 2TB SSD
  • 至少 25Mbps 的網路下載速度

EVM 把 執行環境(Execution Environment) 抽象為:

  • 程式 Code
  • 程式計數器 Program Counter
  • 堆疊 Stack
  • 記憶區 Memory
  • 儲存區 Storage
  • 呼叫資料 calldata
  • 回傳資料 return data

「我們可以知道的是,在交易結束後,儲存區、程式的內容本身會需要儲存在節點的硬碟裡面,供未來使用。其他的部分都是交易執行時會短暫放在記憶體裡,在交易結束後,資源就能釋放掉了。」小雨說。

「最初的 calldata 會需要從交易上的輸入欄位 input 來,也就是說,要驗證輸入欄位,需要把他們下載下來,這吃的是網路下載的資源。」小雨說。

「最後,一些加減乘除、二進位運算、取餘數運算等等,就是 CPU 的苦勞」

執行 EVM

「我對運算資源有點印象了。 EVM 實際上是怎麼執行的呢?」特務 K 問

「通常是一筆交易從 外部帳戶(Externally Owned Account, EOA) 打到 合約帳戶(Contract Account)」小雨說

  • 在合約帳戶裡面,程式會一步一步執行。程式計數器會記得現在讀到哪個操作符了。
  • 程式可能會先從交易的輸入欄位,取得輸入值。他們在呼叫資料 calldata 區。
    • 像是之前的 ERC20 交易,程式會取得輸入值裡面的函式選擇器與參數。
  • 運算的過程中,盡可能會把算一半的值往堆疊裡丟。
  • 堆疊只有 1024 個位置。如果堆疊滿了,就往記憶區丟。
  • 需要永久儲存的資料,像餘額之類,放儲存區。
  • 偶爾程式需要呼叫其他的子合約,與其做互動。
    • 這時會在呼叫資料寫下要呼叫的函式選擇器與參數
    • 子合約處理完之後,把資料寫回回傳資料區,讓親合約使用

操作碼

「操作碼上會記載其運算負擔,節點的開發者很小心的對他們定價。」小雨說。

「如果定價錯誤會怎麼樣?」不待小雨回答,特務 K 已有想法「如果有個操作碼每單位燃氣的運算負擔特別吃重,我會想辦法把整個區塊包滿全是那個操作碼的交易,藉此癱瘓鏈」。

「古老的 Tangerine Whistle 升級就是在這樣的攻擊背景之下發生的」小雨說。

小雨照用途簡單分類了一下各種操作碼。其中 X 開頭的是多種類似名稱的操作碼合稱。

  • 一般運算
    • 數字運算、加減乘除等: ADD MUL SUB DIV, EXP
    • 取餘數運算 XMOD
    • 比較:LT GT ... EQ, ISZERO
    • 二進位運算: AND OR XOR NOT, ...
  • 流程控制: JUMP JUMPI
  • 雜湊運算 KECCAK256
  • 當下的區塊、交易、帳戶資訊: ADDRESS BALANCE ORIGIN CALLER TIMESTAMP ...
  • 執行環境
    • 程式 CODEX
      • 其他帳戶的程式 EXTCODEX
    • 程式計數器 PC
    • 堆疊 POP PUSHX DUPX SWAPX
    • 記憶區 MLOAD MSTORE MSTORE8 MCOPY
    • 儲存區 SLOAD SSTORE
      • 全域儲存區 TLOAD, TSTORE
    • 呼叫資料 CALLDATAX
    • 回傳資料 RETURNDATAX
    • 日誌(快消失的功能)LOGX
  • 合約帳戶互動
    • 創建 CREATE CREATE2
    • 消滅(坎昆升級後行為變更) SELFDESTRUCT
    • 進 XCALL (其中 CALLCODE 是設計壞掉的盲腸)
    • 出 RETURN REVERT

預編譯(Precompile)

理論上,EVM 應該有辦法讓人們設計出任何想要的運算。但是有些密碼學特別用的演算法,用 EVM 來表達實在太貴了。

因此有預編譯的這種設計。在 EVM 裡面,他其實是一個合約,人們可以使用 CALL 之類的操作碼與合約互動。合約會回傳最後算完的結果。但這個算的過程不是透過 EVM 操作符去算出來的,而是偷偷使用節點某種最佳化過的實作。

  • 過期
    • RIPEMD-160 與 blake2f 等當初想支援其他鏈所使用的雜湊函式,但後來使用量超低。
    • modexp 想支援 RSA 運算但沒什麼人用。有純 EVM 實作更有效率。
    • identity 被後來的 MCOPY 取代
  • 零知識證明相關: ecAdd ecMul ecPairing 支援 alt_bn128 橢圓曲線的相關運算,開啟零知識證明相關應用的大門
  • point evaluation :驗證多項式承諾的 KZG 證明,開啟資料可得性應用(小雨還沒找到比較好的語言描述這些事情,唸起來十分拗口)

附錄


上一篇
花式轉帳的電腦
下一篇
賞罰分明的電腦
系列文
那個有好多好多節點的電腦調查報告11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言