Blockchain and Smart Contract
- Published time
前言#
因為實習專案需要寫智能合約,所以花了一點時間做了研究。這篇會先介紹什麼是區塊鏈、上面的資料是怎麼被記錄的,以及智能合約是如何部署在區塊鏈上。
需要先說明的是,我的身分是智能合約開發者,而不是區塊鏈本身的開發者,所以這篇只會處理到「讓我在寫 Dapp 的時候,不會覺得背後的 network 像一個黑盒子」的程度。實際的技術細節不會是這篇的重點,對我來說難度也有點高哈哈。
什麼是區塊鏈#
區塊鏈是一個去中心化的資料庫兼網路。整條鏈由一個個「區塊」串接而成,每一個區塊上面包含資料(等等會介紹有哪些資料),而整條區塊鏈會透過 P2P(Peer to Peer)網路分發到所有節點上。這些節點都是一台一台的伺服器,而所有節點上的區塊鏈內容都是相同的。
「每個節點都存一份完整副本」聽起來非常沒有效率,而它確實很沒有效率——但這正是它的價值所在。想要竄改資料,你必須同時說服網路上過半數的節點接受你的版本,而不是攻破一台伺服器就好。
資料是如何被記錄的#
要說明區塊鏈上的資料,會需要底下幾個觀念。
Hash#
在給定的 data 下,SHA-256 會產生一個固定長度的 fingerprint。相同的資料一定得到相同的 hash,而只要改動一個字元,產生的 hash 就會完全不同。
這個性質是整條鏈的黏著劑:因為每個區塊都包含前一個區塊的 hash,只要有人動了中間任何一個區塊,後面所有區塊的 hash 就全部對不上,竄改馬上就會被發現。
Block#
底下舉一個最簡單的 block 為例,以 PoW 為背景(也就是比特幣所使用的機制):
一個區塊包含 Block number、Nonce、Tx(交易資料)、Prev(前一個區塊的 hash)以及本身的 Hash。這個 Hash 是由前面幾項透過剛剛說的 SHA-256 產生的。
以 PoW 而言,一個「合格」的區塊,它的 hash 必須以 0000… 開頭。因為其他欄位都是固定的,唯一能調整的只有 Nonce,所以礦工要做的就是不斷嘗試不同的 Nonce,直到湊出符合條件的 hash——這就是挖礦。由於 hash 無法反推,除了暴力嘗試沒有捷徑,這也是為什麼挖礦需要消耗那麼多算力。當然實務上的難度調整會比這個複雜。
Consensus Algorithm#
共識算法定義了如何驗證區塊,以及決定哪一個節點可以出塊。
最一開始的 PoW 是透過 mining 找出符合條件的 Nonce,所以需要礦工投入算力來競爭;而 PoS 則是透過質押代幣來決定下一個出塊者,用「押上去的資產」取代「燒掉的電力」當作作惡的成本。兩者所存儲的資料結構也不太相同。比特幣系統使用的是 PoW,以太坊則在 2022 年之後轉為 PoS。
Digital Signatures#
每個帳號都會有一對 public key 跟 private key,public key 經過轉換後就是你的地址。
任何人想要從某個地址轉走資產,都需要附上 signature,它是由 private key 和 message(也就是這筆交易的內容)共同產生的。節點收到交易後,用發送方的 public key 驗證 signature 是否合法,就能確認「這筆交易確實是私鑰持有者本人授權的」,而且過程中完全不需要知道私鑰是什麼。
EVM#
在提到智能合約之前,首先要提到 EVM(Ethereum Virtual Machine)。
EVM 是一個專門用來執行智能合約 bytecode 的虛擬機器。它存在於每一個以太坊節點中,負責執行存放在 block 裡的 bytecode。
EVM 具有圖靈完備(Turing Completeness)的特性。圖靈完備描述的是一台機器可以計算一切可計算問題(computational problem),不論花費時間長短皆可以計算出結果。可計算問題指的是像「給定一個正整數 n,判斷它是否為質數」這類的數學問題。這樣的機器需要具有無限的儲存空間、可增減的運算能力、條件判斷(if-else)以及重複(loop)的能力,而 EVM 具備上述所有能力,所以 EVM 是圖靈完備的機器。
可以把以太坊想像成一台超級電腦:理論上它擁有無限大的儲存空間與運算能力,我們可以編寫任何自己要的程式並放到這台電腦上運行。這台超級電腦由區塊鏈技術建構,放在上面的資料都難以被竄改;而因為去中心化的結構,沒有任何一方可以單方面掌控它。以太坊就是這樣一個易於運行任何 Dapp 的去中心化開發平台。
不過現實中「無限的運算能力」當然不存在,取而代之的是 gas:每一個運算步驟都要付費,而每個區塊有 gas 上限。這既是收費機制,也是防止有人送出一個無窮迴圈把整個網路卡死的保護。
EVM 背後的邏輯相當複雜,它其實就像是一個作業系統。對於當初寫出來的人,我真的很懷疑他們的腦袋到底是怎麼構成的——我們光是 trace code 就要花上一個禮拜以上的東西,他們竟然在十年前就寫得出來,真的令人感到不可思議。
Smart Contract#
智能合約其實就是運作在區塊鏈上的合約,它會自動化地幫你完成代幣的轉移,這裡的代幣就包含了虛擬貨幣、NFT 等等。
它和一般程式最大的差異是:部署之後就改不掉。這也是為什麼智能合約的稽核那麼重要,一個 bug 不是修一修重新部署就好,而是直接對應到真實資產的損失。
合約是如何部署的#
寫好 smart contract 程式碼、經過編譯後會得到兩樣東西:一個是編譯所得的 bytecode,另一個是 JSON 格式的 ABI 檔案。
ABI(Application Binary Interface)描述的是這份合約有哪些函式、參數型別是什麼,等於是合約對外的說明書;bytecode 才是真正要被 EVM 執行的內容。
當開始要部署合約到以太坊區塊鏈時,就把 bytecode 放在交易的 data 欄位中,丟到網路上等待節點幫我們把 contract 寫進 block。當 contract 部署好之後會自動生成一個帳戶,並回傳這個帳戶的 address,這就是俗稱的合約帳戶(contract account)。之後我們就透過這個 address,搭配 ABI,來跟 smart contract 做互動。
如何和合約互動#
直接以流程說明:
- 使用者或應用程式發出交易,送到節點(進入節點的 mempool)。
- 節點驗證交易的格式、簽名、nonce、餘額是否足夠等等。
- 共識機制決定哪個節點(validator / miner)有權產生下一個區塊。
- 出塊者從 mempool 裡挑選若干交易打包成區塊,並使用 EVM 執行裡面每一筆交易,得到狀態變更、logs 與 gas 消耗等結果。
- 出塊者產生區塊頭與區塊體(包含交易與 receipts / logs 等),並把這個完整的區塊廣播給其他節點。
- 其他節點收到區塊後,用自己的 EVM 再次執行所有交易,驗證結果是否與出塊者一致(例如算出來的 state root hash 是否與區塊頭裡的相符)。若合法,就把它加進自己的區塊鏈並更新狀態。
第 6 步是整個設計最關鍵也最違反直覺的地方:每一筆交易都會被網路上所有節點各執行一遍。這正是為什麼鏈上運算如此昂貴——你付的 gas 不是買一次計算,而是買全網數千個節點各算一次。
結語#
仔細研究過後會發現,這背後是一個很複雜很複雜的結構。這也是為什麼還是有那麼多人支持去中心化的發展,因為它的確有強大的技術底層,只是炒幣和交易的聲量蓋過了這件事情。
研究區塊鏈的時候,感覺很像之前在研究作業系統,好像懂了又好像沒有懂。其實有一些開源專案可以讓我寫測試去驗證理解,但目前在工作上畢竟做的是 Dapp 開發,只需要知道大概的邏輯就夠了——就像開發 App 也不需要完全掌握作業系統背後的運作。
不過了解之後確實有幫助:之後開發時可以更清楚區塊鏈適合的使用場景,未來構思新專案的時候,也能提出更符合底層技術特性的設計。
