特務 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 文件 列出以下建議:
EVM 把 執行環境(Execution Environment) 抽象為:
「我們可以知道的是,在交易結束後,儲存區、程式的內容本身會需要儲存在節點的硬碟裡面,供未來使用。其他的部分都是交易執行時會短暫放在記憶體裡,在交易結束後,資源就能釋放掉了。」小雨說。
「最初的 calldata 會需要從交易上的輸入欄位 input 來,也就是說,要驗證輸入欄位,需要把他們下載下來,這吃的是網路下載的資源。」小雨說。
「最後,一些加減乘除、二進位運算、取餘數運算等等,就是 CPU 的苦勞」
「我對運算資源有點印象了。 EVM 實際上是怎麼執行的呢?」特務 K 問
「通常是一筆交易從 外部帳戶(Externally Owned Account, EOA) 打到 合約帳戶(Contract Account)」小雨說
「操作碼上會記載其運算負擔,節點的開發者很小心的對他們定價。」小雨說。
「如果定價錯誤會怎麼樣?」不待小雨回答,特務 K 已有想法「如果有個操作碼每單位燃氣的運算負擔特別吃重,我會想辦法把整個區塊包滿全是那個操作碼的交易,藉此癱瘓鏈」。
「古老的 Tangerine Whistle 升級就是在這樣的攻擊背景之下發生的」小雨說。
小雨照用途簡單分類了一下各種操作碼。其中 X 開頭的是多種類似名稱的操作碼合稱。
理論上,EVM 應該有辦法讓人們設計出任何想要的運算。但是有些密碼學特別用的演算法,用 EVM 來表達實在太貴了。
因此有預編譯的這種設計。在 EVM 裡面,他其實是一個合約,人們可以使用 CALL 之類的操作碼與合約互動。合約會回傳最後算完的結果。但這個算的過程不是透過 EVM 操作符去算出來的,而是偷偷使用節點某種最佳化過的實作。