跳至主要内容

以太坊白皮書

2015 年專案啟動之前,以太坊創辦人 Vitalik Buterin 於 2014 年首次發表了這篇介紹性白皮書。 值得一提的是,與許多社群驅動的開源軟體專案一樣,以太坊自最初誕生以來一直在不斷發展。

雖然已經過去多年,我們仍在維護此白皮書,因為此白皮書仍然可以作為有用的參考資料,並準確地表達以太坊及其願景。 要了解以太坊的最新發展以及協定如何更改,我們推薦你參閱本指南

研究人員和學者如需本白皮書歷史或標準版本 [自2014年12月起],應使用此 PDF。

新一代智慧型合約及去中心化應用程式平台

中本聰於 2009 年發明的比特幣常被譽為金錢與貨幣領域的革命性發展,作為第一種數位資產的範例,它沒有擔保或「內在價值(opens in a new tab)」,也沒有中心化發行人及掌控者。 然而,比特幣實驗的另一個可以說更重要的部分是作為分佈式共識工具的底層區塊鏈技術,人們的注意力正迅速開始轉移到比特幣的這個面向。 通常提及的區塊鏈技術的其他應用包括使用區塊鏈上的數位資產來代表自訂貨幣和金融工具(「彩色幣(opens in a new tab)」)、底層實體裝置的所有權(「智慧財產(opens in a new tab)」)、網域名稱(「域名幣(opens in a new tab)」)等非同質化資產,以及一些更複雜的應用,其中涉及由一段實作任意規則的程式碼(「智慧型合約(opens in a new tab)」)甚至基於區塊鏈的「去中心化自治組織(opens in a new tab)」(DAO) 直接控制的數位資產。 以太坊打算提供一條內建完全成熟、圖靈完備的程式設計語言的區塊鏈,該語言可用於建立可用來編碼任意狀態轉換函式的「合約」,從而讓使用者能夠建立上述任何系統,以及許多其他我們尚未想像到的事務,只需用幾行程式碼編寫邏輯即可。

比特幣及現有概念簡介

歷史

去中心化數位貨幣的概念以及財產登記等其他應用已經存在了幾十年。 1980 年代和 1990 年代的匿名電子現金協定主要依賴於稱為喬姆盲簽 (Chaumian blinding) 的密碼原語,提供了一種具有高度隱私性的貨幣,但這些協定基本上未能獲得關注,因為它們依賴於中心化仲介。 1998 年,戴偉 (Wei Dai) 的 B-money(opens in a new tab) 成為第一個提出透過解决計算難題及去中心化共識來創造貨幣之概念的提案,但該提案未提供關於如何實際實作去中心化共識的細節。 2005 年,哈爾·芬尼 (Hal Finney) 提出了「可重複使用的工作量證明(opens in a new tab)」的概念,這個體系使用 B-money 的概念以及亞當·貝克 (Adam Back) 計算難度大的 Hashcash 難題來創造加密貨幣的概念,但由於依賴可信計算作為後端,再次未能達到理想的效果。 2009 年,中本聰將透過公鑰密碼學管理所有權的成熟原語與用於跟踪貨幣所有者的共識演算法相結合,首次真正意義上實作了去中心化貨幣,被稱為「工作量證明」。

工作量證明機制是該領域的一項突破,因為它同時解决了兩個問題。 首先,這項機制提供了一種簡單且比較有效的共識演算法,讓網路中的節點能够全體對比特幣帳本狀態的一組規範更新達成一致。 接著,其提供了一種允許自由進入共識過程的機制,解决了决定誰來影響共識的政治問題,同時防止了女巫攻擊。 該機制透過用經濟參與障礙取代正式參與障礙(例如要求作為唯一實體在特定清單上登記)來實現這一點 - 共識投票過程中單一節點的權重與該節點的算力成正比。 從那時起,又提出了一種稱為權益證明的替代方法,節點的權重與其持有的貨幣量成正比,不再與計算資源成正比;這兩種方法相對優點的討論不在本文的討論範圍內,但應該指出的是,這兩種方法都可以用作加密貨幣的支柱。

比特幣作為狀態轉換系統

以太坊狀態轉換

從技術角度來看,比特幣等加密貨幣的帳本可以被認為是狀態轉換系統,其中存在一個由所有現有比特幣的所有權狀態組成的「狀態」和一個接受狀態和交易並輸出新狀態(即結果)的「狀態轉換函式」。 例如,在標準銀行系統中,狀態是資產負債表,交易是將 $X 從 A 轉移到 B 的請求,狀態轉換函式將 A 帳戶中的價值減少 $X 美元,並將 B 帳戶中的價值增加 $X 美元。 如果 A 的帳戶最初價值少於 $X 美元,則狀態轉換函式將傳回錯誤。 因此,可以正式定義:

APPLY(S,TX) -> S' or ERROR

在上面定義的銀行系統中:

APPLY({ Alice: $50, Bob: $50 },"send $20 from Alice to Bob") = { Alice: $30, Bob: $70 }

但是:

APPLY({ Alice: $50, Bob: $50 },"send $70 from Alice to Bob") = ERROR

比特幣中的「狀態」是所有已鑄造但尚未花費的貨幣(從技術上講,「未花費的交易輸出 (UTXO)」)的集合,每個未花費的交易輸出都有一個面額和一個所有者(由 20 位元組地址定義,該地址本質上是一個加密公鑰fn1)。 一筆交易包含一個或多個輸入以及一個或多個輸出,每個輸入包含對現有未花費的交易輸出的引用以及由與所有者地址關聯的私鑰生成的加密簽章,而每個輸出包含要新增到狀態的新未花費的交易輸出。

狀態轉換函式 APPLY(S,TX) -> S' 可以大致定義如下:

  1. 對於 TX 中的每個輸入:
    • 如果引用的未花費的交易輸出不在 S 中,則傳回錯誤。
    • 如果提供的簽章與未花費的交易輸出的所有者不匹配,則傳回錯誤
  2. 如果所有輸入未花費的交易輸出的面值總和小於所有輸出未花費的交易輸出的面值總和,則傳回錯誤。
  3. 傳回 S,並刪除所有輸入未花費的交易輸出以及新增所有輸出未花費的交易輸出。

第一步的前半部分防止交易傳送者花費不存在的貨幣,第一步的後半部分防止交易傳送者花費其他人的貨幣,而第二步確保價值守恆。 為了將此用於支付,協定如下。 假設 Alice 想傳送 11.7 BTC 給 Bob。 首先,Alice 將尋找她擁有的一組可用的未花費的交易輸出,總計至少為 11.7 BTC。 實際上,Alice 無法剛剛好獲得 11.7 BTC;假設她能得到的最小數是 6+4+2=12。 然後,她使用這三個輸入和兩個輸出來建立一個交易。 第一個輸出將為 11.7 BTC 且以 Bod 的地址作為其所有者,而第二個輸出為餘下的 0.3 BTC「零頭」且所有者為 Alice。

挖礦

以太坊區塊

如果我們能夠存取值得信賴的中心化服務,那麼該系統的實作將很簡單;它可以簡單地按照描述進行編碼,使用中心化伺服器的硬碟來追蹤狀態。 然而,透過比特幣,我們試圖構建一個去中心化貨幣系統,因此我們需要將狀態交易系統與共識系統結合起來,以確保每個人都同意交易順序。 比特幣的去中心化共識過程要求網路中的節點不斷嘗試產生稱為「區塊」的交易包。 該網路嘗試大約每十分鐘生成一個區塊,每個區塊包含一個時間戳記、一個隨機數、對前一個區塊的引用(即雜湊值)以及自前一個區塊以來發生的所有交易的清單。 隨著時間的推移,這會建立一個持久的、不斷增長的「區塊鏈」,區塊鏈會不斷更新以代表比特幣帳本的最新狀態。

在這個範例中,檢查區塊是否有效的演算法如下:

  1. 確認區塊引用之前一區塊是否存在並有效。
  2. 確認區塊的時間戳記是否大於前一個區塊的時間戳記 fn2 並且在未來的 2 小時內。
  3. 確認區塊上的工作量證明是否有效。
  4. 使 S[0] 為前一個區塊末端的狀態。
  5. 假設 TX 是區塊的交易清單,其中有 n 個交易。 對於 0...n-1 中的所有 i,設定 S[i+1] = APPLY(S[i],TX[i])。如果任何應用程式傳回錯誤,則結束並傳回 false。
  6. 傳回 true,並將 <0>S[n]</0> 註冊為該區塊末端的狀態。

本質上,區塊中的每個交易都必須提供一個有效的狀態轉換,即從交易執行之前的規範狀態轉換到某個新狀態。 請注意,狀態不會以任何方式編碼在區塊中;它純粹是驗證節點要記住的抽象,並且只能透過從創世狀態開始並順序應用每個區塊中的每個交易來(安全地)計算任何區塊。 此外,請注意,礦工將交易放入區塊的順序很重要;如果一個區塊中有兩個交易 A 和 B,並且 B 花費了 A 創造的未花費的交易輸出,那麼如果 A 出現在 B 之前,則該區塊將有效,否則無效。

上述清單中存在的而在其他系統中沒有的一個有效性條件是對「工作量證明」的要求。 具體的條件是,每個區塊的雙 SHA256 雜湊值(為 256 位元數字)必須小於動態調整的目標,截至撰寫本文時約為 2187。 這樣做的目的是使區塊建立在計算上變得「困難」,從而防止女巫攻擊者為取得利益而重建整個區塊鏈。 由於 SHA256 被設計為完全不可預測的偽隨機函式,因此建立有效區塊的唯一方法只不過是 試錯法,即重複增加隨機數並查看新的雜湊值是否匹配。

在目前目標大約為 2187 下,網路必須平均嘗試大致 269 次才能找到有效區塊;一般來說,網路每 2016 個區塊就會重新校準一次目標,因此網路中的某個節點平均每十分鐘就會產生一個新區塊。 為了就此項計算工作補償礦工,每個區塊的礦工都有權包含一筆交易,獎勵曠工 25 BTC。 此外,如果任何交易的輸入總面額高於其輸出,則差額也會作為「交易費」轉給礦工。 順便說一句,這也是比特幣的唯一發行機制;創世狀態根本不包含比特幣。

為了更加瞭解挖礦的意義,讓我們先分析當比特幣網路遭惡意攻擊時會發生甚麼情況。 由於比特幣的底層加密技術是安全的,因此攻擊者將攻擊比特幣系統中不受加密技術直接保護的部分:交易順序。 攻擊者之策略十分簡單:

  1. 向商家傳送 100 BTC 以換取某些產品(最好是快速交付的數位商品)
  2. 等待產品交付
  3. 產生另一筆交易,將同一 100 BTC 傳送給他自己
  4. 試著讓網路相信他對自己的交易是先發生的。

一旦步驟 (1) 發生,幾分鐘後,一些礦工會將交易包含在一個區塊中,例如區塊編號 270000。 大約一小時後,在該區塊之後,鏈上將新增另外五個區塊,其中每個區塊都間接指向該交易,從而「確認」該交易。 此時,商家將接受最終確定的付款並交付產品;由於我們假設這是一種數位商品,因此交付即時完成。 現在,攻擊者建立另一筆交易,將這 100 BTC 傳送給自己。 如果攻擊者只是向全網廣播這一資訊,則交易將不會被處理;礦工將嘗試執行 APPLY(S,TX) 並將注意到 TX 消耗了不再處於該狀態的未花費的交易輸出。 因此,攻擊者會建立區塊鏈的「分叉」,首先挖掘另一版本的區塊 270000,讓其指向同一父塊 269999,並用新交易取代舊交易。 因為區塊資料不同,這就需要重新進行工作量證明。 此外,攻擊者的新版本區塊 270000 具有不同的雜湊值,因此原始區塊 270001 至 270005 不會「指向」該區塊;因此,原始鏈和攻擊者的新鏈是完全分開的。 規則是,在分叉時,最長的區塊鏈被視為正確的鏈,因此合法礦工將處理 270005 鏈,而攻擊者獨自處理 270000 鏈。 攻擊者為了使其區塊鏈最長,需要擁有比網路其他部分加起來還要多的算力才能偽裝成正確的鏈(因此,被稱為「51% 攻擊」)。

默克爾樹

比特幣簡單支付驗證

左:只需在默克爾樹中呈現少量節點即可證明分支的有效性。

右:改變默克爾樹的任何部分的任何嘗試最終都會導致鏈上某個地方的不一致。

比特幣的一個重要的可擴展性特徵是區塊儲存在多層資料結構中。 區塊的「雜湊值」實際上只是區塊頭的雜湊值,區塊頭是一段大約 200 位元組的資料,其中包含時間戳記、隨機數、前一個區塊的雜湊值以及儲存區塊中所有交易的資料結構(稱為默克爾樹)的根雜湊值。 默克爾樹是一種二元樹,包括一組擁有大量葉節點的節點(這些葉節點位於樹底部儲存著底層資料),一組中間節點(其中每個節點都是其兩個子節點的雜湊值),以及一個代表樹的「頂部」的根節點(根節點亦由其兩個子節點的雜湊值組成)。 默克爾樹的用途是允許區塊中的資料分段傳送:節點可以只從一個來源下載區塊頭,從另一個來源下載與它們相關的樹的一小部分,並且仍然可以確認所有資料都正確。 這樣做的原因是雜湊值向上傳播:如果惡意使用者嘗試將虛假交易交換到默克爾樹的底部,則此變更將導致上面的節點發生變化,然後導致該節點上面的節點發生變化,最終改變樹的根,從而改變區塊的雜湊值,導致協定將其註冊為完全不同的區塊(幾乎確定包含無效的工作量證明)。

默克爾樹協定可以說對於長期永續性至關重要。 截至 2014 年 4 月,比特幣網路中的「全節點」(儲存和處理每個區塊的全部資料)佔用比特幣網路中約 15 GB 的磁碟空間,並且每月增長超過 1 GB。 目前,這對於某些桌上型電腦是可行的但不適用行動電話,將來只有企業和業餘愛好者才能參與。 一種稱為「簡單支付驗證」(SPV) 的協定允許存在另一類稱為「輕節點」的節點,這種節點下載區塊頭,驗證區塊頭上的工作量證明,並僅下載與其相關的交易的相關「分支」。 這使得輕節點能夠在強力的安全保證下確定任何比特幣交易的狀態及其目前餘額,同時僅下載整個區塊鏈的極一小部分。

其他區塊鏈應用

將區塊鏈底層理念應用於其他概念的想法也有著很長的歷史。 2005 年,尼克·薩博 (Nick Szabo) 提出了「利用所有者權限確保財產權」的概念,該文件描述了「複製資料庫技術的新進展」將如何允許基於區塊鏈的系統來儲存誰擁有哪些土地的登記表,建立一個包括宅基地、逆權管有和喬治亞土地稅等概念的複雜架構。 然而,不幸的是,當時沒有有效的複製資料庫系統可用,因此該協定從未在實踐中實作。 然而,2009 年之後,在比特幣的去中心化共識開發出來後,許多其他應用迅速開始出現。

因此,一般來說,建立共識協議有兩種方法:建立獨立網路以及在比特幣之上建立協議。 前一種方法雖然在域名幣等應用中相當成功,但很難實作;每個單獨的實作都需要啟動一個獨立的區塊鏈,以及建立和測試所有必要的狀態轉換和網路程式碼。 此外,我們預測去中心化共識技術的應用程式集將遵循冪律分布,其中絕大多數應用程式太小而無法保證自己的區塊鏈,並且我們注意到存在大量需要相互互動的去中心化應用程式,特別是去中心化自治組織。

另一方面,基於比特幣的方法有缺陷,即它沒有繼承比特幣的簡單支付驗證功能。 簡單支付驗證適用於比特幣,因為它可以使用區塊鏈深度作為有效性的代理;在某種程度上,只要交易的祖先可以追溯到足夠久遠的時間,就可以安全地認為它們是合法狀態的一部分。 另一方面,基於區塊鏈的元幣協議不能迫使區塊鏈排除在其自己的協議中無效的交易。 因此,完全安全的簡單支付驗證元幣協議實作需要向後一致掃描到比特幣區塊鏈的開頭,以確定某些交易是否有效。 目前,基於比特幣的元幣協議的所有「輕型」實作都依賴受信任的伺服器來提供資料,這可以說是一個非常次優的結果,特別是當加密貨幣的主要目的之一是消除信任需求。

腳本

即使沒有任何擴充功能,比特幣協議實際上也構成了弱化版本的「智慧型合約」。 比特幣中的未花費的交易輸出不僅可以由公鑰擁有,還可以由用簡單的基於堆疊的程式語言編寫的更複雜的腳本擁有。 在這個範式中,一筆花費該未花費的交易輸出的交易必須提供滿足腳本的資料。 事實上,即使是基本的公鑰所有權機制也是透過指令碼實作的:腳本將橢圓曲線簽章作為輸入,根據交易和擁有未花費的交易輸出的位址對其進行驗證,並且如果驗證成功則傳回 1,否則傳回 0。 對於各種附加使用案例,還有其他更複雜的腳本。 例如,可以建構一個腳本,要求要驗證的給定三個私鑰中的兩個私鑰的簽章(「多簽」),這是一種對公司帳戶、安全儲蓄帳戶和某些商家託管情況有用的設定。 腳本還可以用於支付計算問題解決方案的賞金,人們甚至可以建構一個腳本,上面寫著「如果你能提供簡單支付驗證證明,證明你向我傳送了該面額的狗狗幣交易,那麼這個比特幣未花費的交易輸出就是你的」,本質上允許去中心化的加密貨幣間的兌換。

然而,比特幣中實作的腳本語言有幾個重要限制:

  • 缺乏圖零完整性 - 也就是說,雖然比特幣腳本語言支援很大一部分計算,但它幾乎不支援其他東西。 最主要的問題是缺乏迴圈。 這樣做是為了避免在交易驗證過程中出現無限迴圈;從理論上講,這對腳本程式設計師來說是一個可以克服的障礙,因為任何迴圈都可以透過簡單地使用 if 語句多次重複底層程式碼來模擬,但它確實會導致腳本空間效率非常低。 例如,實作替代的橢圓曲線簽章演算法可能需要 256 次重複乘法輪次,所有輪次都單獨包含在程式碼中。
  • 價值盲 - 未花費的交易輸出腳本無法對可提取金額作精細控制。 例如,預言機合約的一個強大用例是對沖合約,其中 A 和 B 存入了價值 $1000 的比特幣,30 天後,腳本將價值 $1000 的比特幣傳送給 A,其餘的傳送給 B。這需要預言機來確定 1 個比特幣的美元價值,但即便如此,與現有的完全中心化解決方案相比,它在信任和基礎設施要求方面還是一個巨大改進。 然而,由於未花費的交易輸出是全有或全無的,實現這一點的唯一方法是透過非常低效的破解手段,即擁有許多不同面額的未花費的交易輸出(例如,對於每個最多可達 30 的 k,有一個 2k 的未花費的交易輸出)並讓預言機選擇將哪個未花費的交易輸出傳送給 A,將哪個未花費的交易輸出傳送給 B。
  • 缺少狀態 - 未花費的交易輸出要麼是已使用,要麼是未使用;用於保存任何其他內部狀態的多階段合約或腳本是沒有機會出現的。 這會使得難以創建多階段期權合約、去中心化交易報價或兩階段加密承諾協定(為安全計算賞金必需)。 這也意味著未花費的交易輸出只能用於建構簡單的一次性合約,而不是去中心化組織等更複雜的「有狀態」合約,並且讓元協定難以實作。 二元狀態加上價值盲也意味著另一個重要應用(提款限制)是不可能實現的。
  • 區塊鏈盲 - 未花費的交易輸出看不到區塊鏈的資料,例如隨機數、時間戳記和上一個區塊的雜湊值。 由於該腳本語言無法透過隨機性來創造可能的價值,因此它在博彩和其他幾個類別的應用受到嚴重限制。

這樣,我們瞭解了在加密貨幣之上建立進階應用程式的三種方法:構建新的區塊鏈、在比特幣之上使用腳本以及在比特幣之上構建元協定。 構建新的區塊鏈可以在建立功能集方面提供無限的自由,但需要犧牲開發時間、啟動工作和安全性。 使用腳本這一方法很容易實作和標準化,但其功能非常有限,而且元協定雖然簡單,但在可擴展性方面存在缺陷。 透過以太坊,我們打算建立一個替代架構,使得開發更簡單、輕量用戶端性能更強大,同時允許應用程式共享經濟的環境和區塊鏈安全性。

Ethereum

以太坊的目的是創造一個用於構建去中心化應用程式的替代協定,提供一套我們認為對於一大類去中心化應用程式非常有用的不同折衷方案,特別是快速開發時間、小型和不常用應用程式的安全性以及應用程式間高效互動能力很重要的情形。 以太坊透過建立本質上的終極抽象基礎層來實現這一點:具有內建圖靈完整程式語言的區塊鏈,允許任何人編寫智慧型合約和去中心化應用程式,他們可以在其中建立自己的所有權、交易格式和狀態轉換函式的任意規則。 域名幣的基本版本可以用兩行程式碼編寫,而貨幣和信譽系統等其他協定的構建需要不超過二十行程式碼。 智慧型合約是包含價值的加密「盒子」,只有在滿足某些條件時才解鎖,也可以構建在平台之上,由於圖零完整性、價值意識、區塊鏈意識和狀態的附加功能,其功能比比特幣腳本提供的功能要強大得多。

以太坊帳戶

在以太坊中,狀態由稱為「帳戶」的物件組成,每個帳戶都有一個 20 位元組地址,並且狀態轉換是帳戶之間價值和資訊的直接轉移。 以太坊帳戶包含四個欄位:

  • 隨機數,用來確定每個交易只能被處理一次的計數器
  • 帳戶目前的以太幣餘額
  • 帳戶的合約程式碼(如存在)
  • 帳戶的存儲(預設值為空白)

「以太幣」是以太坊的主要內部加密燃料,用於支付交易費。 一般來說,有兩種類型的帳戶:由私鑰控制的外部帳戶,以及由合約程式碼控制的合約帳戶。 外部帳戶沒有程式碼,可以藉由建立和簽署交易,從外部帳戶送出訊息;在合約帳戶中,合約帳戶每次收到訊息後,其程式碼啟動,允許其讀取和寫入內部存儲,以及送出其他訊息或依次建立合約。

請注意,以太坊中的「合約」不應被視為應該「履行」或「遵守」的東西;相反,「合約」更像是生活在以太坊執行環境中的「自治代理」,當被訊息或交易「觸發」時總是執行特定的程式碼片段,並直接控制自己的以太幣餘額和自己的鍵/值存儲來追蹤持久變數。

訊息及交易

以太坊中使用的術語「交易」是指已簽署資料包,其中儲存將從外部帳戶發送的訊息。 交易包含:

  • 訊息接收者
  • 識別發送者的簽章
  • 從發送者轉移到接收者的以太幣數量
  • 一可選數據段量
  • STARTGAS 值,表示交易執行允許使用的計算步驟之最大數量
  • GASPRICE 值,表示發送者為每個計算步驟支付的費用

前三個欄位是任何加密貨幣應有的標準欄位。 預設情況下資料欄位沒有函式,但虛擬機有操作碼,合約可以用操作碼來存取資料。例如,如果一個合約作為區塊鏈上的網域註冊服務,該合約可能希望將傳遞給它的資料解釋為含有兩個「欄位」,第一個欄位是要註冊的網域,第二個欄位是要註冊到的網際網路通訊協定地址。 合約將從訊息資料中讀取這些數值並且適當存儲。

STARTGASGASPRICE 欄位對以太坊的反拒絕服務模型很重要。 為了防止程式碼中出現意外或惡意的無限迴圈或其他計算浪費,每個交易都需要設定其可以使用的程式碼執行計算步驟數的限制。 計算的基本單位是「燃料」;通常,一個計算步驟花費 1 份燃料,但某些操作會花費更多的燃料,因為它們的計算成本更高,或者增加了必須作為狀態一部分儲存的資料量。 交易資料中每個位元組還需支付 5 份燃料。 收費系統的目的是要求攻擊者按比例為其消耗的每種資源付費,包括計算、頻寬和存儲;因此,任何導致網路消耗更多資源的交易都必須有與增量大致成正比的燃料費。

訊息

合約能夠傳送「訊息」至其他合約。 訊息是虛擬物件,永遠不會被序列化且只存在以太坊的執行環境中。 訊息包含:

  • 訊息的發送者(隱含)
  • 訊息接收者
  • 與訊息一起傳輸的以太幣數量
  • 一個可選擇的資料欄位
  • <0>STARTGAS</0> 值

訊息與交易基本相似,但是訊息是由合約產生的,而不是由外部執行者產生。 當目前執行程式碼的合約執行 CALL 操作碼時,就會產生一則訊息,該操作碼會產生並執行一則訊息。 與交易一樣,訊息會使得接收者帳戶執行其程式碼。 因此,如同外部參與者與其他合約建立的關係一樣,合約可以與其他合約建立完全相同的關係。

請注意,交易或合約指定的燃料限額適用於該交易和所有子執行消耗的燃料總量。 例如:假如外部參與者 A 以 1000 份燃料發送交易給 B,在發送訊息給 C 之前 B 消費 600 份燃料,在返回前 C 的內部執行消耗 300 份燃料,然後,在用完燃料之前 B 還可以再花掉另外 100 份燃料。

以太坊狀態轉換函式

以太幣狀態轉換

以太坊狀態轉換函式 APPLY(S,TX) -> S' 可以定義如下:

  1. 檢查交易格式是否正確(即擁有正確數量的值)、簽章是否有效、以及隨機數是否匹配發送者帳戶中的隨機數。 如果為否,則傳回錯誤。
  2. 透過 STARTGAS * GASPRICE 計算出交易費,並從簽章中確定發送地址。 從發送者的帳戶餘額中減去費用並增加發送者的隨機數。 如果沒有足夠餘額可供使用,則傳回錯誤。
  3. 初始化 GAS = STARTGAS,並根據交易中的位元組數量為每個位元組扣除相應數量的燃料。
  4. 將交易數值從發送者帳戶轉移至接收帳戶。 如果接收帳戶尚不存在,則建立此帳戶。 如果接收帳戶是合約,執行該合約的程式碼直到運行結束或耗盡燃料。
  5. 如果因發送者資金不足或程式碼運行耗盡了燃料而導致轉帳失敗,則還原除支付費用之外的所有狀態變化,並將費用支付給礦工帳戶。
  6. 否則,將所有剩餘燃料的費用退還給發送者,並把為所消耗燃料而支付的費用發送給礦工。

例如,假設合約程式碼如下:

if !self.storage[calldataload(0)]:
  self.storage[calldataload(0)] = calldataload(32)

請注意,合約程式碼實際上是用低階以太坊虛擬機程式碼編寫的;為清晰起見,此範例是用我們其中一種高階語言 Serpent 編寫的,它可以編譯為以太坊虛擬機程式碼。 假設合約的儲存一開始是空的,並發送了一個價值為 10 個以太幣的交易,消耗 2000 份燃料,燃料價格為 0.001 個以太幣,並且包含 64 位元組的資料,其中位元組 0-31 代表數字 2,位元組 32-63 代表字串 CHARLIE。 這種情況下,狀態轉移函式之流程如下:

  1. 檢查交易是否有效且格式正確。
  2. 檢查交易發送者是否至少有 2000 * 0.001 = 2 以太幣。 如是,則從發送者的帳戶中減去 2 以太幣。
  3. 初始化燃料 = 2000,假設交易長度為 170 個位元組,每個位元組費用為 5 份燃料,減去 850 份燃料,因此剩下 1150 份燃料。
  4. 從發送者的帳戶中再減去 10 個以太幣,並將其新增至合約帳戶。
  5. 執行程式碼。 在本例中,執行過程比較簡單:函式檢查是否使用合約位於索引 2 的儲存,若未使用,則通知未使用;若使用,函式將位於索引 2 的存儲設定為值 CHARLIE。 假設執行過程花費 187 份燃料,那麼剩餘的燃料數量為 1150 - 187 = 963
  6. 將 963 * 0.001 = 0.963 以太幣新增回發送者的帳戶,並傳回產生的狀態。

如果交易的接收一端沒有合約,那麼總交易費就等於提供的 GASPRICE 乘以交易的位元組長度,且和隨交易發送的資料無關。

請注意,訊息在還原方面與交易相同:如果訊息執行耗盡燃料,那麼該訊息的執行以及該執行觸發的所有其他執行都會還原,但父執行不需還原。 這意味著合約呼叫另一份合約是「安全的」,就好像 A 使用 G 份燃料呼叫 B,那麼可以保證 A 的執行最多損耗 G 份燃料。 最後,請注意有一個建立合約的操作碼 CREATE;它的執行機制通常類似於 CALL,不同之處在於執行的輸出決定了新建立合約的程式碼。

程式碼執行

以太坊合約中的程式碼是用一種基於堆疊的低階位元組碼語言編寫,被稱為「以太坊虛擬機器程式碼」或「EVM 程式碼」。 該程式碼由一系列位元組組成,每個位元組代表一種操作。 通常,程式碼執行是一個無限迴圈,即重複執行當前程式計數器(由零開始)的操作,然後將程式計數器增加一,直到程式碼執行完畢或出現錯誤,或偵測到 STOPRETURN 指令。 這些操作可以存取三種資料儲存空間:

  • 堆疊,一種後進先出的資料容器,允許對資料做推入與彈出
  • 記憶體,一個可無限擴充的位元組陣列
  • 合約的長期存儲,一個鍵/值儲存。 跟堆疊和記憶體會在計算結束後重置不同,存儲將長期持續存在。

程式碼也能存取傳入訊息的值、發送者與資料,以及區塊頭資料,並且程式碼也可以傳回資料位元組陣列作為輸出。

以太坊虛擬機程式碼的正式執行模型非常簡單。 當以太坊虛擬機運作時,其完整計算狀態可以由元組 (block_state, transaction, message, code, memory, stack, pc, gas) 來定義,其中 block_state 是包含所有帳戶的全域狀態並包含餘額和存儲。 在每一輪執行開始時,可以透過使用 code 的第 pc 個位元組(或 0,如果 pc >= len(code))來找到當前指令,並且每條指令在元組影響方式方面都有自己的定義。 例如,ADD 將兩個項目彈出並將它們的和推入堆疊,將 gas 減少 1 並將 pc 增加1,SSTORE 將頂部的兩個項目彈出並將第二個項目插入合約存儲中第一個項目指定的索引處。 雖然有很多透過即時編譯來最佳化以太坊虛擬機執行的方法,但只需幾百行程式碼就可以完成以太坊的基本實作。

區塊鏈及挖礦

以太坊應用框圖

以太坊區塊鏈在許多方面與比特幣區塊鏈相似,雖然確實存在一些差異。 以太坊和比特幣在區塊鏈架構方面的主要區別在於,與比特幣不同,以太坊區塊包含交易清單和最新狀態的副本。 除此之外,另外兩個數值,即區塊編號和難度,也儲存在區塊中。 以太坊中基本的區塊驗證演算法如下:

  1. 檢查引用的前一個區塊是否存在並且有效。
  2. 檢查區塊的時間戳記是否大於引用的前一個區塊的時間戳記,並且在未來的 15 分鐘內。
  3. 檢查區塊編號、難度、交易根、叔根和燃料限制(各種以太坊特定的低階概念)是否有效。
  4. 確認區塊上的工作量證明是否有效。
  5. 使S[0]為前任區塊之最終狀態.
  6. TX 為區塊的交易清單,並且包含 n 筆交易。 對於 0...n-1 中的所有 i,設定 S[i+1] = APPLY(S[i],TX[i])。 如果任何應用程式傳回錯誤,或直到此時區塊中消耗的總燃料量超過 GASLIMIT,則傳回錯誤。
  7. S_FINALS[n],但加上支付給礦工的區塊獎勵。
  8. 檢查狀態 S_FINAL 的默克爾樹根是否等於區塊頭中提供的最終狀態根。 如果為是,則該區塊有效;否則該區塊無效。

這種方法乍看似乎效率很低,因為它需要儲存每個區塊的完整狀態,但實際上效率應該與比特幣相當。 原因是狀態儲存在樹狀結構中,而且在新增每個區塊後只需要更改樹的一小部分。 因此,一般來說在兩個相鄰區塊之間,樹的絕大部分應該是相同的,因此資料可以儲存一次並使用指標引用兩次(即子樹的雜湊值)。 一種稱為「帕特里夏樹」的特殊類型的樹用於實現此目的,它包括對默克爾樹概念的修改,允許高效地插入和刪除節點,而非僅僅更改。 此外,由於所有狀態資訊都存在於最後一個區塊內,因此無需儲存整個區塊鏈歷史 - 如果此策略可以應用於比特幣,可以節省 5-20 倍空間。

一個常見的問題是合約程式碼在實體硬體的「哪裡」執行。 這有一個簡單答案:合約程式碼的執行過程是狀態轉換函式定義的一部分,而該函式是區塊驗證演算法的一部分,因此若將交易新增到區塊 B 中,由該交易產生的程式碼執行將在現在和未來由所有節點執行,由此下載並驗證區塊 B

應用

基本上,以太坊上擁有三類應用。 第一類是金融應用,為使用者提供更強大的方式使用他們的資金來管理和簽訂合約。 這包括子貨幣、金融衍生品、對沖合約、儲蓄錢包、遺囑,甚至某些類別的完整僱傭合約。 第二類是涉及金錢的半金融應用,但很大部分功能也與資金無關;一個恰當的例子是針對解決計算難題的自動執行的懸賞。 最後,還有一些非金融性質的應用,例如線上投票和去中心化治理。

代幣系統

區塊鏈上的代幣系統有許多應用,從代表美元或黃金等資產的子貨幣到公司股票等等,單一代幣可以代表智慧資產、安全且不可偽造的優惠券,甚至可代表作為激勵積分系統並與傳統價值完全沒有關聯的代幣系統。 代幣系統在以太坊的實作非常容易。 要理解的重點是所有貨幣或代幣系統,從根本上都是具有以下操作的資料庫:從 A 中減去 X 個單位並將 X 個單位新增給 B,附帶條件是 (1) A 在交易前至少有 X 個單位且 (2) 交易由 A 批准。實作代幣系統所需要做的就是將此邏輯實作到合約中。

使用 Serpent 實作代幣系統的基本程式碼如下:

def send(to, value):
  if self.storage[msg.sender] >= value:
    self.storage[msg.sender] = self.storage[msg.sender] - value
    self.storage[to] = self.storage[to] + value

此程式碼本質上是本文檔前面部分詳細描述的「銀行系統」狀態轉換函式的字面實作。 需要額外添加幾行程式碼來規定,在最初以及其他一些邊緣案例下分配貨幣單位的初始步驟。理想情況下,應該新增一個函式讓其他合約查詢某個地址的餘額。 但這就是全部了。 理論上,基於以太坊的代幣系統在作為子貨幣時可能具有另一個重要特徵,該特徵是基於比特幣的鏈上元貨幣所缺乏的:就是直接以該貨幣支付交易費的能力。 實作這點的方式是合約會保持一定數量的以太幣餘額,用來向發送者退還用於支付費用的以太幣,合約也會透過收取費用的形式收集內部貨幣單位,並在持續不斷的拍賣中轉售貨幣,以此補充以太幣餘額。 因此,使用者需要用以太幣「啟動」他們的帳戶,但一旦帳戶中有以太幣,就可以重複使用,因為合約每次都會向帳戶退還資金。

金融衍生物及穩定價值貨幣

金融衍生物是「智慧型合約」最常見的應用,也是最容易以程式碼實作的應用之一。 實作金融合約的主要挑戰在於,其中大多數合約都需要引用外部價格行情指示器;例如,一個非常理想的應用程式是對沖以太幣(或其他加密貨幣)相對於美元波動的智慧型合約,而這需要合約知道以太幣/美元的價值。 實現這一點的最簡單方法是藉助由特定方(例如納斯達克)維護的「資料饋送」合約,這種合約的設計讓特定方能夠根據需要更新合約並提供一個介面,允許其他合約向該合約發送訊息並傳回包含價格的回覆。

考慮到這一關鍵因素,對沖合約將如下所示:

  1. 等待 A 方輸入 1000 個以太幣。
  2. 等待 B 方輸入 1000 個以太幣。
  3. 將透過查詢資料饋送合約計算出的 1000 個以太幣的美元價值記錄在存儲中,假設為 $x。
  4. 30 天後,允許 A 或 B 「重新啟動」合約,以便將價值 $x 美元的以太幣(通過再次查詢資料饋送合約以獲得新價格來計算得出)發送給 A,並將其餘的發送給 B。

這種合約在加密貨幣商業上具有巨大潛力。 加密貨幣的主要問題之一是它的波動性。雖然許多使用者和商家可能希望獲得處理加密資產的安全性和便利性,但他們中許多人不希望面臨在一天內資金價值損失 23% 的景象。 目前為止,最常見的解決方案是發行者支持的資產;其想法是發行者創建一種子貨幣,他們有權發行和撤銷這種子貨幣單位,並且對於向發行者(離線)提供一個單位指定基礎資產(例如黃金、美元)的任何人,發行者可以向其(離線)提供一個單位的貨幣。 發行者然後承諾向返還一個單位加密資產的任何人提供一個單位基礎資產。 這種機制讓任何非加密資產「升級」為加密資產,前提為發行者是可信的。

然而實際上,發行者並不總是值得信賴,在某些情況下銀行基礎設施過於薄弱或過於不友好,以至無法提供此類服務。 金融衍生物提供了另一種選擇。 這種方案中,不是由單一發行者提供資金來支持資產,而是由一個去中心化的投機者市場承擔了這個角色,他們押注加密參考資產(例如以太幣)的價格會上漲。 與發行者不同,投機者無法在交易中違約,因為對沖合約託管他們的資金。 注意這種方法不是完全去中心化的,因為仍然需要一個可信來源提供價格行情指示器,但可以說在降低基礎設施要求(與發行者不同,發布價格饋送不需要許可證並且可能被歸類為言論自由)以及減少詐欺的可能性方面,這仍是一個巨大改進。

身分及信譽系統

最早的替代加密貨幣域名幣(opens in a new tab),嘗試使用類似比特幣的區塊鏈提供一種名稱註冊系統,讓使用者可以在公共資料庫中註冊他們的姓名和其他資料。 主要用例是網域名稱系統(opens in a new tab),它將諸如「bitcoin.org」等域名(在域名幣的情況下,「bitcoin.bit」)映射到一個網際網路通訊協定地址。 其他用例包括電子郵件身份驗證系統和可能更高階的信譽系統。 以下是在以太坊上提供類似域名幣的名稱註冊系統的基本合約:

def register(name, value):
  if !self.storage[name]:
    self.storage[name] = value

合約非常簡單;它就是以太坊網路中的一個資料庫,可以向其中新增但不能修改或移除。 任何人都可以把名稱註冊為一個值,並且該註冊將永遠保留。 更複雜的名稱註冊合約還將具有允許其他合約查詢的「函式子句」,以及允許名稱「所有者」(即首個註冊者)更改資料或轉讓所有權的機制。 甚至可以在該合約上添加信譽和信任網路功能。

去中心化檔案存儲

過去幾年,大批受歡迎的線上檔案存儲新創公司不斷湧現,其中最著名的是 Dropbox。這家公司想讓使用者能夠上傳硬碟備份、提供備份儲存服務並允許使用者存取備份來收取月費。 然而,目前檔案存儲市場其實效率相對較低。在粗略了解各種現有解決方案後會發現,主流檔案存儲的月費比整個硬碟的成本還要高,特別是在被稱為「恐怖谷」的 20-200 GB 級別,既沒有免費額度也沒有企業級折扣。 以太坊合約讓去中心化檔案存儲生態系統得以發展,個人使用者可以將自己的硬碟租出去以獲得少量收益,而未使用的空間可用於進一步降低檔案存儲成本。

這個系統的關鍵組成部分就是我們所謂的「去中心化 Dropbox 合約」。 該合約的運作方式如下。 首先,使用者將需要將存儲的資料拆分成幾個區塊並對每個區塊加密以保護隱私,然後以此構建一個梅克爾樹。 然後建立一個包含以下規則的合約,對於每 N 個區塊,合約將從默克爾樹中選擇一個隨機索引(使用能夠被合約程式碼存取的上一個區塊的雜湊值作為隨機性來源),然後給予第一個實體 X 個以太幣,以提供包含簡單支付驗證(例如位於樹中特定索引處區塊的所有權證明)的交易。 當使用者想重新下載他們的檔案時,他們可以使用微支付通道協定(例如每 32 KB 支付 1 個szabo)恢復檔案;最節省費用的方法是支付者不到最後不發布交易,而是每 32 KB 後用一個更划算的、具有相同隨機數的交易取代原來的交易。

該協定的一個重要特點是,雖然似乎使用者相信許多隨機節點不會丟失檔案,但可以透過以下方法將這種風險降低到接近零:透過私鑰共享將檔案拆分成許多部分,並透過監控合約確定每一部分仍在某個節點中。 如果合約依然在支付款項,那就提供了一個加密證明,某人仍在利用此合約來保存檔案。

去中心化自治組織 (DAO)

「去中心化自治組織」的一般概念是指擁有一定數量成員或股東的虛擬實體,它們大概擁有 67% 的大多數股權,有權使用實體的資金並修改其程式碼。 成員會集體決定該組織如何分配其資金。 去中心化自治組織的資金分配方式可以是賞金、薪資或更奇特的機制,例如用內部貨幣來獎勵工作。 這本質上複製了傳統公司或非營利組織的法律特徵,但僅使用加密區塊鏈技術來執行。 目前為止,許多關於去中心化自治組織的討論都圍繞著「去中心化自治公司」(DAC) 的「資本家」模式,其中有可獲得紅利的股東和可交易的股份;作為替代方案,有一種可能被稱為「去中心化自治社群」的實體會使所有成員在決策時擁有同等權利,並在增減成員時要求 67% 的現有成員多數同意。 由於每人只能擁有一個成員資格,所以需要群體來集體執行。

以下概括如何用程式碼實現去中心化自治組織。 最簡單的設計就是一段能夠在三分之二的成員同意變更時進行變更的自動修改程式碼。 雖然程式碼理論上是不可更改的,然而透過把程式碼片段放入不同的合約,並將要呼叫的合約的位址儲存在可修改的儲存中,使用者可以輕易解決這一問題及使程式碼事實上變得可修改。 在這種去中心化自治組織合約的簡單實作中,有三種交易類型可透過交易提供的資料區分:

  • [0,i,K,V] 在索引 i 處註冊提案,以便將儲存索引 K 的位址變更為值 V
  • [1,i] 註冊一張贊成提案 i 的投票
  • [2,i] 如果已獲得足夠的投票,則最終確定提案 i

合約為每一種交易提供了子句。 它將維護所有開放儲存變更的記錄,以及投票支持者的清單。 它還會有全部成員的清單。 當三分之二之成員投票贊成儲存變更,一個最終化交易將執行此變更。 更複雜的框架可能還有針對發送交易、增減成員等功能的內建投票功能,甚至可以提供流動式民主(opens in a new tab)投票委託(即任何人都可以委託另外一個人代表自己投票,而這種委託關係是可以傳遞的,如果 A 委託了 B,然後 B 委託了 C,那麼 C 將決定 A 的投票)。 這種設計將使去中心化自治組織作為一個去中心化社群有機地成長,允許人們最終將篩選成員的任務委派給專家,但與「現有系統」不同,隨著時間推移,當個別社群成員改變他們的陣營時,專家可以輕鬆地加入或退出。

另一替代模型是去中心化公司,其中任何帳戶可以擁有零份或多份股份,需要有三分之二的股份才能做出決策。 完整框架將包括資產管理功能,即能夠出價購買或出售股份並且能夠接受報價(最好是合約裡有訂單匹配機制)。 委託也提供流動式民主形式,普及了「董事會」的概念。

更多應用

1. 儲蓄錢包。 假設 Alice 想安全地保管她的資金,但她擔心自己的私鑰遺失或被破解。 她把以太幣放到和銀行 Bob 簽訂的一個合約裡,如下:

  • Alice 每天最多可以單獨提取 1% 的資金。
  • Bob 每天最多可以單獨提取 1% 的資金,但 Alice 可以用她的金鑰建立一個交易取消 Bob 的提款權限。
  • Alice 和 Bob 一起可以任意提取資金。

通常,每天 1% 的額度對於 Alice 來說已足夠,若 Alice 想提取更多資金,她可以聯繫 Bob 尋求幫助。 如果 Alice 的金鑰被破解,她可以立即聯絡 Bob 幫她將資金轉移到新合約。 如果她遺失了金鑰,Bob 最終會取出資金。 如果發現 Bob 是惡意的,她可以取消 Bob 的提款權限。

2. 農作物保險。 使用者可以輕鬆地建立金融衍生合約,但使用的是天氣而非任何價格指數的資料饋送。 如果愛荷華州的農民購買了一項金融衍生物,該產品基於愛荷華的降雨情況進行反向賠付,那麼如果遇到乾旱,該農民將自動收到賠付資金,而且如果降雨充足他會很開心,因為他的作物會有好收成。 這可以擴展到一般的自然災害保險。

3. 去中心化資料餽送。 對於金融差價合約,實際上有可能透過一種名為「SchellingCoin(opens in a new tab)」的協定將資料餽送服務去中心化。 SchellingCoin 的基本工作原理如下:N 個相關方都向系統輸入給定資料的值(例如以太幣/美元價格),對這些值進行排序,在第 25 和第 75 個百分位之間的每個人都會得到一個代幣作為獎勵。 每個人都有動力提供其他人都會提供的答案,而唯一能讓眾多參與者實際達成一致的值是顯而易見的:真相。 這樣就建立了一種去中心化協定,它理論上可以提供任何數量的數值,包括以太幣/美元價格、柏林的溫度甚至某個困難計算的結果。

4. 智慧型合約多重簽章託管。 比特幣允許多重簽章交易合約,例如,提供給定五個金鑰中的三個便可以使用資金。 以太坊允許更精細的控制;例如,提供五個金鑰中的四個可以使用任意數量的資金,提供五個金鑰中的三個可以每天最多使用 10% 的資金,提供五個金鑰中的兩個可以每天最多使用 0.5% 的資金。 此外,以太坊的多重簽章是非同步的 — 雙方可以在不同時間在區塊鏈上註冊他們的簽章,最後一個簽章將自動傳送交易。

5. 雲端運算。 以太坊虛擬機技術也可以用來建立一個可驗證的運算環境,讓使用者可以要求他人執行計算,並要求提供證據,證明某些隨機選擇檢查點處的計算被正確執行。 這允許創建一個雲端運算市場,任何使用者都可以使用他們的桌上型電腦、筆記型電腦或專用伺服器參與其中,並且可以使用抽查和保證金來確保系統是值得信賴的(即節點不能透過欺騙來獲利)。 雖然這種系統可能不適合所有任務;例如,需要高階的進程間通訊的任務無法在大型節點雲端上輕鬆完成。 然而,其他任務則更容易實現並行;例如 SETI@home、folding@home 和遺傳演算法等專案可以輕鬆地在這類平台上實作。

6. 點對點賭博。 任意數量的點對點賭博協議都可以在以太坊區塊鏈上實作,例如 Frank Stajano 和 Richard Clayton 的 Cyber​​dice(opens in a new tab)。 最簡單的賭博協定實際上只是關於下一個區塊雜湊值的差價合約,並且可以在其基礎上構建更進階的協定,建立接近零費用且無法作弊的賭博服務。

7. 預測市場。 如果有預言機或 SchellingCoin,預測市場也很容易實作,預測市場與 SchellingCoin 一起有可能被證明是 futarchy(opens in a new tab) 的第一個主流應用,作為去中心化組織的治理協定。

8. 鏈上去中心化市場,以身分和信譽系統為基礎。

雜項與憂慮

經修改之 GHOST 實作

「貪婪最重可觀察子樹」(GHOST) 協定是由 Yonatan Sompolinsky 和 Aviv Zohar 在 2013 年12 月(opens in a new tab)首次提出的創新。 提出 GHOST 的動機是,具有快速確認時間的區塊鏈目前由於過時率高而安全性降低— 因為區塊需要一定的時間才能透過網路傳播,如果礦工 A 開採了一個區塊,然後礦工 B 碰巧在礦工 A 的區塊傳播到 B 之前開採了另一個區塊,那麼礦工 B 的區塊最終會被作廢,無法用於增加網路安全性。 此外,還有一個中心化問題:如果礦工 A 是一個擁有 30% 哈希算力的礦池,而 B 擁有 10% 哈希算力,那麼 A 將面臨 70% 的時間生產陳腐區塊的風險(因為在其他 30 % 的時間 A 產生了最後一個區塊,所以會立即獲得挖礦數據),而 B 將面臨 90% 的時間生產陳腐區塊的風險。 因此,如果區塊間隔短到足以使過時率較高,則 A 將僅憑藉其算力大小而顯著提高效率。 結合這兩種影響,快速產生區塊的區塊鏈很可能造就一個擁有足夠高比例網路哈希算力的礦池,從而對挖礦過程擁有事實上的控制。

正如 Sompolinsky 和 Zohar 所描述,GHOST 透過在計算哪條鏈「最長」時包含陳腐區塊來解決網路安全性降低的第一個問題;也就是說,在計算哪個區塊受到最大的總工作量證明支援時,不僅區塊的父塊和更遠的祖先,而且該區塊祖塊(在以太坊行話中稱為「叔塊」)的陳腐子代也都被添加到計算中。 為了解決第二個問題,即中心化偏差,我們跳出了 Sompolinsky 和 Zohar 描述的協定範疇,並且還為陳腐區塊提供區塊獎勵:陳腐區塊獲得其基礎獎勵的 87.5%,而包含陳腐區塊的侄塊獲得剩餘的 12.5%。 然而,交易費並不獎勵給叔塊。

以太坊實作了一個簡化版的 GHOST 協定,它僅僅深入七個層級。 具體來說,定義如下:

  • 一個區塊必須指定一個父塊,並且必須指定零個或多個叔塊
  • 包含在區塊 B 中的叔塊必須具有以下屬性:
    • 它必須是區塊 B 的第 k 代祖先的直系子代,其中 2 <= k <= 7
    • 它不能是 B 的祖先
    • 叔塊必須是有效的區塊頭,但不需要是先前驗證過的甚至是有效的區塊
    • 叔塊必須不同於前面區塊中包含的所有叔塊,並且不同於同一區塊中包含的所有其他叔塊(非雙重包含)
  • 對於區塊 B 中的每個叔塊 U,區塊 B 的礦工獲得額外 3.125% 的鑄幣獎勵,而叔塊 U 的礦工獲得 93.75% 的標準鑄幣獎勵。

這種限製版的 GHOST 協議,最多只能包含 7 代叔塊,採用它有兩個原因。 首先,在計算給定區塊中哪些叔塊有效時,無限制 GHOST 會使得計算過於複雜。 第二,無限制 GHOST 協議採用了以太坊中使用的補償,取消了促使礦工在主鏈而不是公共攻擊者的鏈上挖礦的激勵措施。

手續費

由於發佈到區塊鏈中的每筆交易都會為網路帶來下載和驗證的成本,因此需要一些通常涉及交易費用的監管機制來防止濫用。 比特幣使用的預設方法是純粹自願的手續費,依靠礦工充當看門人並設定動態最低限額。 這種方法特別在比特幣社群中受歡迎,是因為它「基於市場」,允許礦工和交易發送者之間的供需決定價格。 然而,這種想法的問題在於交易處理並不符合市場法則。雖然將交易處理解釋為礦工向發送者提供的服務直觀上很有吸引力,但實際上礦工收錄的每筆交易都需要由網絡中的每個節點處理,因此絕大部分交易處理成本由第三方而非由決定是否收錄交易的礦工承擔。 因此,公地悲劇的問題很可能發生。

然而,結果卻是,基於市場機制中的這個缺陷,在給出一個不準確的特定簡化假設時,會神奇地自我抵銷。 論證如下。 假設:

  1. 交易導致 k 個操作,將提供獎勵 kR 給添加它的任何礦工,其中 R 由發送者設定,kR 事先(大體上)對礦工可見。
  2. 在任何節點,操作的處理成本為 C(即所有節點效率相同)
  3. N 個挖礦節點,每個節點的處理能力完全相同(即總處理能力的 1/N
  4. 沒有不挖礦的全節點。

如果預期獎勵大於成本,礦工將願意處理交易。 因此,預期獎勵為 kR/N,因為礦工有 1/N 機會處理下一個區塊,而礦工的處理成本僅為 kC。 因此,當 kR/N > kCR > NC 時,礦工將會添加交易。 請注意 R 是發送者提供的每個操作的費用,因此是發送者從交易中獲得的收益的下限,NC 是整個網路共同處理一個操作的成本。 因此,礦工有動機只添加那些總實際收益超過成本的交易。

然而,這些假設在現實中會出現有些許重要偏離:

  1. 與其他驗證節點相比,礦工處理交易的成本確實更高,因為額外的驗證時間會延遲區塊傳播,從而增加區塊陳腐的機率。
  2. 確實存在不挖礦的全節點。
  3. 實際上挖礦能力的分配最終可能極度不平等。
  4. 想破壞網路的投機者、政敵和瘋子確實存在,他們可以巧妙地設定合約,讓他們的成本遠低於其他驗證節點支付的成本。

(1) 讓礦工傾向於添加較少的交易,並且 (2) 增加 NC;因此這兩種作用會互相 抵銷一部分。 如何抵銷?(opens in a new tab) (3) 和 (4) 是主要問題,為了解決它們,我們簡單地制訂了一個浮動上限: 沒有區塊能夠包含比 BLK_LIMIT_FACTOR 乘以長期指數移動平均值更多的操作數。 具體來說:

blk.oplimit = floor((blk.parent.oplimit \* (EMAFACTOR - 1) +
floor(parent.opcount \* BLK\_LIMIT\_FACTOR)) / EMA\_FACTOR)

BLK_LIMIT_FACTOREMA_FACTOR 是常數,暫時設定為 65536 和 1.5,但可能在進一步分析後會變更。

還有一個因素會抑制比特幣中的大區塊:大區塊將需要更長時間來傳播,因此有更大機率變成陳腐區塊。 在以太坊中,燃料消耗量高的區塊也可能需要更長時間來傳播,因為它們的物理大小更大,而且因為它們需要更長時間來處理交易狀態轉換以進行驗證。 這種延遲抑制因素在比特幣中是一個重要的考慮因素,但在以太坊中由於 GHOST 協定而較少考慮;因此,依靠受監管的區塊限制可提供更穩定的基準。

計算及圖零完整性

重點是以太坊虛擬機是圖靈完整的;這意味著以太坊虛擬機程式碼可以對任何設想可執行的計算進行編碼,包括無限迴圈。 以太坊虛擬機程式碼以兩種方式實作迴圈。 首先,使用一個 JUMP 指令,允許程式跳回至程式碼中的前一個位置,也使用一個 JUMPI 指令進行條件跳轉,允許諸如 while x < 27: x = x * 2 之類的語句。 第二,合約可以呼叫其他合約,有可能透過遞迴進行迴圈。 這很自然地導致一個問題:本質上,惡意使用者能夠透過迫使礦工和全節點進入無限迴圈而關閉它們嗎? 這個問題​源於電腦科學中的一個難題,稱為停機問題:在一般情況下,沒有辦法知道一個特定的程式是否會停止運作。

如狀態轉換部分所述,我們的解決方案要求交易設定一個允許執行的最大計算步驟數,如果超過執行時間,計算就會被還原但仍要支付費用。 訊息以同樣的方式運作。 為顯示我們解決方案背後的動機,請看下面的範例:

  • 攻擊者建立一個運行無限迴圈的合約,然後向礦工發送啟動該迴圈的交易。 礦工將處理該交易,運行無限迴圈直到燃料耗盡。 即使執行耗盡了燃料並中途停止,交易仍然有效而礦工仍然向攻擊者索取每個計算步驟的費用。
  • 攻擊者建立一個非常長的無限迴圈,目的是迫使礦工持續長時間計算,以至於計算結束時將有更多區塊產生出來,這樣礦工就不可能透過添加該交易來索取費用。 然而,攻擊者需要為 STARTGAS 提交一個值,限制執行可以進行的計算步驟數,因此礦工將提前知道該計算將進行相當多的步驟數。
  • 攻擊者看到一個合約,其中的程式碼形式為 send(A,contract.storage[A]); contract.storage[A] = 0,然後發送一個交易,但燃料只夠運行第一步而不足以運行第二步(即進行提款但不讓餘額減少)。 合約創建者無需擔心防備此類攻擊,因為若執行中途停止,變更會被還原。
  • 金融合約取九個專有資料餽送的中位數,以最大限度地降低風險。 攻擊者接管其中一個資料饋送,該資料饋送設計為可透過去中心化自治組織部分描述的變數-地址-呼叫機制修改,並將其轉換為運行無限迴圈,從而強制任何從金融合約索取資金的嘗試都因燃料耗盡中止。 然而,金融合約可以對訊息設定燃料限制來預防這個問題。

圖靈完整的替代方案是圖靈不完整,其中 JUMPJUMPI 不存在,並且在任何給定時間每個合約只允許有一個副本存在於呼叫堆疊內。 在這個系統中,上述收費系統和關於我們解決方案效果的不確定性可能都是不必要的,因為執行一個合約的成本將由合約大小決定。 此外,圖靈不完整甚至不是一大限制;在我們內部構想的所有合約範例中,到目前為止只有一個需要迴圈,甚至那個迴圈也可以透過將一行程式碼重複 26 次來消除。 考慮到圖靈完整性帶來的嚴重影響和有限益處,為什麼不簡單地使用圖靈不完整的語言呢? 然而在現實中,圖靈不完整仍遠遠不能有效解決問題。 要了解原因,考慮以下合約:

C0: call(C1); call(C1);
C1: call(C2); call(C2);
C2: call(C3); call(C3);
...
C49: call(C50); call(C50);
C50: (run one step of a program and record the change in storage)

現在,向 A 發送一筆交易。這樣,在 51 筆交易中,我們有一個合約需要 250 個計算步驟。 礦工可以嘗試提前偵測這種邏輯炸彈,方法是為每個合約維護一個值,指定合約可以進行的最大計算步驟數,然後對遞迴呼叫其他合約的合約進行計算,但是這需要礦工禁止建立其他合約的合約(因為上面 26 個合約的建立和執行可以很容易地匯集到一個單獨合約內)。 另一個問題是訊息地址欄位是一個變數,所以在一般情況下,甚至不可能提前知道某個合約將呼叫哪些合約。 因此,最終我們有了一個驚人結論:圖靈完整性十分容易管理,而在缺乏同樣的控制時,圖靈不完整的管理異常地困難,那為什麼不直接讓協定圖靈完整呢?

貨幣與發行

以太坊網路包括自己的內建貨幣以太幣,其扮演雙重角色:提供一個主要流動資金層,實現各種數位資產之間的高效交易,更重要的是,提供一種支付交易費的機制。 為方便起見並避免未來爭議(參考當前比特幣中的 mBTC/uBTC/satoshi 爭論),面額預先設定如下:

  • 1:wei
  • 1012:szabo
  • 1015:finney
  • 1018:ether

這應該被視為「美元」和「美分」或「BTC」和「satoshi」概念的擴展版本。 在不久將來,我們期望「ether」用於普通交易,「finney」用於微型交易,「szabo」和「wei」可以在圍繞費用和協定實作的技術討論中使用;其餘的面額可能會在以後變得有用,但目前不應包含在用戶端中。

發行模式如下:

  • 以太幣將以貨幣銷售的形式發行,價格為一個比特幣可購買 1000-2000 個以太幣,這種機制旨在為以太坊組織籌資和支付開發費用,且已被其他平台(如 Mastercoin 和 NXT)成功應用。 早期買家將從較大的折扣中獲益。 發售所得的比特幣將全部用來支付開發者的薪資和獎金,並用來投資以太坊和加密貨幣生態系統中的各種營利和非營利專案。
  • 0.099 倍的發售總量(60102216 個以太幣)將分配給以太坊組織,以補償早期貢獻者,並用以太幣計價的方式支付創世區塊誕生前的開銷。
  • 0.099 倍的發售總量將保留為長期準備金。
  • 發售後,將永久地每年為礦工分配 0.26 倍的發售總量。
群組啟動時一年後五年後
貨幣數量1.198X1.458X2.498X
購買者83.5%68.6%40.0%
發售前花費的準備金8.26%6.79%3.96%
發售後使用的準備金8.26%6.79%3.96%
礦工0%17.8%52.0%

長期供應成長率(百分比)

以太坊通貨膨脹

除了線性的貨幣發行方式外,與比特幣相似,以太幣的長期供應成長率也趨於零。

上述模型提供了兩個主要選項:(1) 捐贈池的存在和規模,以及 (2) 永久增長的線性供應的存在,而比特幣採用了限制供應的方法。 捐贈池存在的理由如下。 如果捐贈池不存在,且線性發行量減少到​​總發售量的 0.217 倍以實現相同的通貨膨脹率,那麼以太幣總量將減少 16.5%,而每個單位將增值 19.8%。 因此,為了達成均衡,將會多發售 19.8% 的以太幣並購買,所以每個單位的價值將再次與以前完全一樣。 組織還將擁有 1.198 倍的比特幣,可以考慮將其分為兩部分:原有比特幣和額外的 0.198 倍比特幣。 因此,這種情況完全等同於捐贈,但有一個重要區別:該組織僅持有比特幣,因而沒有動機支持以太幣單位的價值。

永久性線性供應成長模型降低了有些人認為比特幣財富過度集中的風險,並為生活在當前和未來的人提供了獲取貨幣單位的公平機會,同時又保留了讓人獲取並持有以太幣的強效激勵措施,因為長期來看,用百分比表示的「供應成長率」仍將趨於零。 我們還推測由於加密貨幣總是會因為不小心、死亡等原因而丟失,而加密貨幣的損失可以被模擬為每年總供應量的百分比,因此流通中的貨幣總供應量實際上最終會穩定在一個等於每年發行量除以損失率的數值上(例如,在損失率為 1% 時,一旦供應量達到 26 倍,那麼每年將挖掘出 0.26 倍,0.26 倍丟失,形成一個平衡點)。

請注意,未來以太坊很可能會過渡到權益證明模型以確保安全,將每年的發行量減少到 0 至 0.05 倍之間。 如果以太坊組織失去資金或因任何其他原因消失,我們將開啟一個「社區合約」:任何人都有權創建以太坊的未來候選版本,唯一的條件是以太幣的數量必須最多等於 60102216 * (1.198 + 0.26 * n),其中 n 是創世區塊之後的年數。 創作者可以自由地眾售,或以其他方式分配權益證明驅動的供應擴張和最大允許供應擴張之間的部分或全部差額,來支付開發費用。 不符合社區合約的候選升級可能會合理地被分叉為相容版本。

挖礦中心化

比特幣挖礦演算法的原理是,讓礦工一次又一次地對區塊頭稍作修改的版本進行數百萬次 SHA256 計算,直到最終某個節點所產生版本的雜湊值小於目標值(目前大約為 2 192)。 然而,這種挖礦演算法容易出現兩種形式的中心化。 第一種,挖礦生態系統已經被 ASIC(特殊應用積體電路)所支配,這些電腦晶片專門為特定的比特幣挖礦任務而設計,因此效率提高了數千倍。 這意味著比特幣挖礦不再是一種高度去中心化和平等的追求,而是需要巨額資本才能有效參與。 第二,大部分比特幣礦工事實上不在本地完成區塊驗證;而是依賴中心化礦池提供區塊頭。 這個問題可以說很嚴重:截至撰寫本文時,最大的三個礦池間接地控制了大約比特幣網路 50% 的算力,雖然當一個礦池嘗試聯合發動 51% 攻擊時,礦工還是可以轉換到其他礦池來減輕此問題的嚴重性。

以太坊現在目的是使用一種挖礦演算法,要求礦工從狀態中獲取隨機資料,從區塊鏈的最後 N 個區塊中計算一些隨機選擇的交易,並傳回結果的雜湊值。 這有兩個重要好處。 首先,以太坊合約可以包含任何類型的計算,因此以太坊特殊應用積體電路本質上是用於一般計算的特殊應用積體電路,即更好的中央處理器。 其次,挖礦需要存取整條區塊鏈,這迫使礦工儲存整條區塊鏈並至少能夠驗證每筆交易。 這樣就消除了對中心化礦池的需求;雖然礦池仍然可以起到平衡獎勵分配隨機性的合法作用,但沒有中心化控制的點對點礦池同樣也可以很好地發揮此功能。

該模型未經測試,而在使用合約執行挖礦演算法時,避免某些巧妙最佳化過程中可能會遇到困難。 然而,這種演算法有一個值得注意的特點,任何人都可以透過將專用於抑制某些特殊應用積體電路的大量合約引入區塊鏈中,在「井裡投毒」。 由於存在經濟激勵,特殊應用積體電路製造商會使用這種方法互相攻擊。 因此,我們正在開發的解決方案最終是一種適應性人為經濟解決方案,而不是純粹的技術解決方案。

可擴展性

以太坊的一個常見問題是可擴展性問題。 與比特幣一樣,以太坊也存在缺陷,即每筆交易都需要由網路中的每個節點處理。 以比特幣來說,目前區塊鏈的大小約為 15 GB,每小時增長約 1 MB。 如果比特幣網路要像 Visa 那樣每秒處理 2000 筆交易,則每三秒鐘就會增加 1 MB(每小時 1 GB,每年 8 TB)。 以太坊可能也會經歷相似甚至更糟的增長模式,因為以太坊區塊鏈上還有很多應用程式,不像比特幣區塊鏈上只有貨幣,但以太坊全節點只需儲存狀態而不是完整的區塊鏈歷史,這一事實讓情況得到改善。

如此龐大的區塊鏈出現的問題是中心化風險。 如果區塊鏈大小增加到 100 TB,可能的情況是只有極少數大型企業能運行全節點,而所有普通使用者將使用簡單支付驗證輕量節點。 在這種情況下,可能會出現全節點合夥詐欺牟利(例如變更區塊獎勵,給他們自己比特幣等)這樣的問題。 輕節點無法立即偵測到這一點。 當然,可能至少存在一個誠實的全節點,而幾小時後有關詐騙的資訊會透過 Reddit 這種頻道洩露,但那時會為時已晚:由普通使用者互相組織協作將指定區塊列入黑名單,這種大型、很可能不切實際的協作在規模上無異於發動一次成功的 51% 攻擊。 就比特幣而言,目前這是一個問題,但 Peter Todd 建議(opens in a new tab)對區塊鏈進行修改,以緩解這個問題。

在短期內,以太坊將使用兩種附加策略來應對這個問題。 首先,因為基於區塊鏈的挖礦演算法,至少每個礦工都會被強制成為一個全節點,為全節點的數量創建了下限。 接著更重要的是,處理完每筆交易後,我們會把一個中間狀態樹根收錄到區塊鏈中。 即使區塊驗證是中心化的,只要存在一個誠實的驗證節點,就可以透過驗證協議來規避中心化問題。 如果礦工發布了無效區塊,該區塊必定是格式錯誤,或是狀態 S[n] 不正確。 由於已知 S[0] 是正確的,因此必然存在第一個不正確的狀態 S[i],但狀態 S[i-1] 是正確的。 驗證節點將提供索引 i 以及「無效證明」,該證明包括處理 APPLY(S[i-1],TX[i]) -> S[i] 所需的帕特里夏樹節點的子集。 節點將能夠使用那些節點來運行該部分計算,並查看生成的 S[i] 與提供的 S[i] 是否不匹配。

另一種更複雜的攻擊涉及惡意礦工發布不完整的區塊,因此甚至不存在完整訊息,致使無法確定區塊是否有效。 解決方案是查問-應答協議:驗證節點對目標交易索引發起「查問」,接受到質疑信息的輕型節點會對相應的區塊取消信任,直到另外無論是礦工還是另一個驗證者的節點,提供一個帕特里夏節點子集作為有效性證明。

結論

以太坊協議最初被設想為加密貨幣的升級版本,透過高度通用的程式語言提供進階功能,如區塊鏈託管、提款限制、金融合約、博彩市場等。 以太坊協議不會直接「支援」任何應用程式,但圖靈完備程式語言的存在意味著,理論上可以為任何交易類型或應用程式建立任意合約。 然而關於以太坊更有趣的地方是,以太坊協議遠遠超出了貨幣的範疇。 圍繞去中心化檔案儲存、去中心化計算和去中心化預測市場的協議以及許多其他這類概念,有可能大大提高計算行業的效率,並首次透過添加經濟層來大力促進其他點對點協議的發展。 最後,還有大量與金錢完全無關的應用程式。

以太坊協議實作的任意狀態轉換函式的概念,提供了一個具有獨特潛力的平台,而不是一種專門針對資料儲存、賭博或金融領域內一系列特定應用程式的封閉式單用途協議。以太坊在設計上是開放式的,我們相信在今後幾年裡它非常適合作為大量金融和非金融協議的基礎層。

註釋與延伸閱讀

注釋

  1. 有經驗的讀者可能會注意到,事實上比特幣地址是橢圓曲線公鑰的雜湊值,而不是公鑰本身。 然而,事實上從密碼學術語角度把公鑰雜湊值稱為公鑰是完全合理的。 這是因為比特幣密碼學可以視為一種客製化的數位簽章演算法。在數位簽章演算法中,公鑰由橢圓曲線密碼學公鑰的雜湊值組成,簽章由連接了橢圓曲線密碼學簽章的橢圓曲線密碼學公鑰組成。而驗證演算法涉及用橢圓曲線密碼學公鑰雜湊值(作為公鑰提供)來檢查簽章中的橢圓曲線密碼學公鑰,然後用橢圓曲線密碼學公鑰來驗證橢圓曲線密碼學簽章。
  2. 技術上來說,前 11 個區塊的中位數。
  3. 在內部,2 和「CHARLIE」都是數字 fn3,後者以高位元組在前基數 256 表示。 數字至少可以為 0,最多可以為 2256-1。

衍生閱讀

  1. 內在價值(opens in a new tab)
  2. 智慧型資產(opens in a new tab)
  3. 智慧型合約(opens in a new tab)
  4. B-money(opens in a new tab)
  5. 可重複使用之工作量證明(opens in a new tab)
  6. 利用所有者權限確保財產權(opens in a new tab)
  7. 比特幣白皮書(opens in a new tab)
  8. 域名幣(opens in a new tab)
  9. Zooko 三角(opens in a new tab)
  10. 彩色幣白皮書(opens in a new tab)
  11. 萬事達幣白皮書(opens in a new tab)
  12. 去中心化自治組織,Bitcoin Magazine(opens in a new tab)
  13. 簡單支付驗證(opens in a new tab)
  14. 默克爾樹(opens in a new tab)
  15. 帕特里夏樹(opens in a new tab)
  16. GHOST(opens in a new tab)
  17. StorJ 及自治代理,Jeff Garzik(opens in a new tab)
  18. Mike Hearn 在圖靈節談論智慧型資產(opens in a new tab)
  19. 以太坊遞迴長度前綴(opens in a new tab)
  20. 以太坊默克爾帕特里夏樹(opens in a new tab)
  21. Peter Todd 談論默克爾求和樹(opens in a new tab)

有關白皮書的歷史記錄,請參閱此維基(opens in a new tab)

與許多社群驅動的開源軟體專案一樣,以太坊自最初誕生以來一直在不斷發展。 來學習更多最新以太坊發展及多年來之網路協議變動, 我們推薦你詳閱此指南簡介.

這篇文章對你有幫助嗎?