以太坊是什麼? 以太坊是一個全新開放的區塊鏈平台,它允許任何人在平台中建立和使用通過區塊鏈技術運行的去中心化應用。就像比特幣一樣,以太坊不受任何人控制,也不歸任何人所有 —— 它是一個開放源碼項目,由全球範圍內的很多人共同創建。和比特幣協議有所不同的是,以太坊的設計十分靈活,極具適應性。在以太坊平台上創立新的應用十分簡便,隨著 Homestead 的發布,任何人都可以安全地使用該平台上的應用。
以太坊 DApp 實戰開發課程,以去中心化投票應用(Voting DApp)為課程項目,通過三次迭代開發過程的詳細講解不在線實踐,並且將區塊鏈的理念和去中心化思想貫穿於課程實踐過程中,為希望快速入門區塊鏈開發的開發者提供了一個高效的學習和價值提升途徑。《以太坊 DApp 開發實戰入門》後面會寫。
教程預置了開發環境。進入教程後,可以在每一個知識點立刻進行同步實踐,而不必在開發環境的搭建上浪費時間:
以太坊白皮書中文版當中本聰在 2009 年 1 月啟動比特幣區塊鏈時,他同時向世界引入了兩種未经測試的革命性的新概念。第一種就是比特幣(bitcoin),一種去中心化的點對點的網上貨幣,在沒有任何資產擔保、內在價值或者中心發行者的情況下維持著價值。到目前為止,比特幣已經吸引了大量的公眾注意力,就政治方面而言,它是一種沒有中央銀行的貨幣,並且有著劇烈的價格波動。然而,中本聰的偉大試驗還有與比特幣同等重要的一部分:基於工作量證明的區塊鏈概念使得人們可以就交易順序達成共識。作為應用的比特幣可以被描述為個先申請(first-to-file)系統:如果某人有 50BTC 並且同時向 A 和 B 發送這 50BTC,只有被首先確認的交易才會生效。沒有固有方法可以決定兩筆交易哪一筆先到,這個問題阻礙了去中心化數字貨幣的發展許多年。中本聰的區塊鏈是第一個可靠的去中心化解決辦法。現在,開發者們的注意力開始迅速地轉向比特幣技術的第二部分,區塊鏈怎樣應用於貨幣以外的領域。常被提及的應用,包括使用鏈上數字資產來代表定制貨幣和金融工具(彩色幣),某種基礎物理設備的所有權(智能資產),如域名一樣的沒有可替代性的資產(域名幣)以及如去中心化交易所,金融衍生品,點到點賭博和鏈上身份和信用系統等更高級的應用。另一個常被詢問的重要領域是 “智能合約”- 根據事先任意制訂的規則來自動轉移數字資產的系統。例如,一個人可能有一個存儲合約,形式為 “A 可以每天最多提現 X 個幣,B 每天最多 Y 個,A 和 B 一起可以隨意提取,A 可以停掉 B 的提現權”。這種合約的符合邏輯的擴展就是去中心化自治組織(DAOs)- 長期的包含一個組織的資產並把組織的規則編碼的智能合約。以太坊的目標就是提供一個帶有內置的成熟的圖靈完備語言的區塊鏈,用這種語言可以創建合約來編碼任意狀態轉換功能,用戶只要簡單地用幾行代碼來實現邏輯,就能夠創建以上提及的所有系統以及許多我們還想象不到的其它系統。
歷史沿革去中心化的數字貨幣概念,正如財產登記這樣的替代應用一樣,早在幾十年前就被提出了。
1980 和 1990 年代的匿名電子現金協議,大部分是以喬姆盲簽技術(Chaumian blinding)為基礎的。這些電子現金協議提供具有高度隱私性的貨幣,但是這些協議都沒有流行起來,因為它們都依賴於一個中心化的中介機構。1998 年,戴偉(Wei Dai)的 b-money 首次引入了通過解決計算難題和去中心化共識創造貨幣的思想,但是該建議並未給出如何實現去中心化共識的具體方法。
2005 年,芬尼(Hal Finney)引入了 “可重複使用的工作量證明機制”(reusable proofs of work)概念,它同時使用 b-money 的思想和亞當・巴克(Adam Back)提出的計算困難的哈希現金(Hashcash)難題來創造密碼學貨幣。但是,這種概念再次迷失於理想化,因為它依賴於可信任的計算作為後端。因為貨幣是一個先申請應用,交易的順序至關重要,所以去中心化的貨幣需要找到實現去中心化共識的方法。比特幣以前的所有電子貨幣協議所遇到的主要障礙是,儘管對如何創建安全的拜占庭問題容錯(Byzantine-fault-tolerant)多方共識系統的研究已經歷時多年,但是上述協議只解決了問題的一半。這些協議假設系統的所有參與者是已知的,並產生如 “如果有 N 方參與到系統中,那麼系統可以容忍 N/4 的惡意參與者” 這樣形式的安全邊界。然而這個假設的問題在於,在匿名的情況下,系統設置的安全邊界容易遭受女巫攻擊,因為一個攻擊者可以在一台伺服器或者殭屍網絡上創建數以千計的節點,從而單方面確保擁有多數份額。中本聰的創新是引入這樣一個理念:將一個非常簡單的基於節點的去中心化共識協議與工作量證明機制結合在一起。節點通過工作量證明機制獲得參與到系統的權利,每十分鐘將交易打包到 “區塊” 中,從而創建出不斷增長的區塊鏈。擁有大量算力的節點有更大的影響力,但獲得比整個網絡更多的算力比創建一百萬個節點困難得多。儘管比特幣區塊鏈模型非常簡陋,但是實踐證明它已經足夠好用了,在未來五年,它將成為全世界兩百個以上的貨幣和協議的基石。
作為狀態轉換系統的比特幣
從技術角度講,比特幣賬本可以被認為是一個狀態轉換系統,該系統包括所有現存的比特幣所有權狀態和 “狀態轉換函數”。狀態轉換函數以當前狀態和交易為輸入,輸出新的狀態。例如,在標準的銀行系統中,狀態就是一個資產負債表,一個從 A 賬戶向 B 賬戶轉賬 X 美元的請求是一筆交易,狀態轉換函數將從 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
比特幣系統的 “狀態” 是所有已經被挖出的、沒有花費的比特幣(技術上稱為 “未花費的交易輸出,unspent transaction outputs 或 UTXO”)的集合。每個 UTXO 都有一個面值和所有者(由 20 個字節的本質上是密碼學公鑰的地址所定義 [1])。一筆交易包括一個或多個輸入和一個或多個輸出。每個輸入包含一個對現有 UTXO 的引用和由與所有者地址相對應的私鑰創建的密碼學簽名。每個輸出包含一個新的加入到狀態中的 UTXO。在比特幣系統中,狀態轉換函數 APPLY (S,TX)->S‟大體上可以如下定義:
- 交易的每個輸入:
-
如果引用的 UTXO 不存在於現在的狀態中(S),返回錯誤提示
-
如果簽名與 UTXO 所有者的簽名不一致,返回錯誤提示
-
如果所有的 UTXO 輸入面值總額小於所有的 UTXO 輸出面值總額,返回錯誤提示
-
返回新狀態 S‟, 新狀態 S‟中移除了所有的輸入 UTXO,增加了所有的輸出 UTXO。第一步的第一部分防止交易的發送者花費不存在的比特幣,第二部分防止交易的發送者花費其他人的比特幣。第二步確保價值守恆。比特幣的支付協議如下。假設 Alice 想給 Bob 發送 11.7BTC。事實上,Alice 不可能正好有 11.7BTC。假設,她能得到的最小數額比特幣的方式是:6+4+2=12。所以,她可以創建一筆有 3 個輸入,2 個輸出的交易。第一個輸出的面值是 11.7BTC,所有者是 Bob(Bob 的比特幣地址),第二個輸出的面值是 0.3BTC,所有者是 Alice 自己,也就是找零。
挖礦#
如果我們擁有可信任的中心化服務機構,狀態轉換系統可以很容易地實現,可以簡單地將上述功能準確編碼。然而,我們想把比特幣系統建造成去中心化的貨幣系統,為了確保每個人都同意交易的順序,我們需要將狀態轉換系統與一個共識系統結合起來。比特幣的去中心化共識過程要求網絡中的節點不斷嘗試將交易打包成 “區塊”。網絡被設計為大約每十分鐘產生一個區塊,每個區塊包含一個時間戳、一個隨機數、一個對上個區塊的引用(即哈希)和上一区塊生成以來發生的所有交易列表。這樣隨著時間流逝就創建出了一个持續增長的區塊鏈,它不斷地更新,從而能夠代表比特幣賬本的最新狀態。依照這個範式,檢查一個區塊是否有效的算法如下:
-
檢查區塊引用的上個區塊是否存在且有效。
-
檢查區塊的時間戳是否晚於以前的區塊的時間戳,而且早於未來 2 小時 [2]。
-
檢查區塊的工作量證明是否有效。
-
將上個區塊的最終狀態賦於 S [0]。
-
假設 TX 是區塊的交易列表,包含 n 筆交易。對於屬於 0……n-1 的所有 i, 進行狀態轉換 S [i+1] = APPLY (S [i],TX [i])。如果任何一筆交易 i 在狀態轉換中出錯,退出程序,返回錯誤。
-
返回正確,狀態 S [n] 是這區塊的最終狀態。
本質上,區塊中的每筆交易必須提供一個正確的狀態轉換,要注意的是,“狀態” 並不是編碼到區塊的。它純粹只是被校驗節點記住的抽象概念,對於任意區塊都可以從創世狀態開始,按順序加上每一個區塊的每一筆交易,(妥妥地)計算出當前的狀態。另外,需要注意礦工將交易收錄進區塊的順序。如果一個區塊中有 A、B 兩筆交易,B 花費的是 A 創建的 UTXO,如果 A 在 B 以前,這個區塊是有效的,否則,這個區塊是無效的。區塊驗證算法的有趣部分是 “工作量證明” 概念:對每個區塊進行 SHA256 哈希處理,將得到的哈希視為長度為 256 比特的數值,該數值必須小於不斷動態調整的目標數值,本書寫作時目標數值大約是 2^190。工作量證明的目的是使區塊的創建變得困難,從而阻止女巫攻擊者惡意重新生成區塊鏈。因為 SHA256 是完全不可預測的伪隨機函數,創建有效區塊的唯一方法就是簡單地不斷試錯,不斷地增加隨機數的數值,查看新的哈希數值是否小於目標數值。如果當前的目標數值是 2^192,就意味著平均需要嘗試 2^64 次才能生成有效的區塊。一般而言,比特幣網絡每隔 2016 個區塊重新設定目標數值,保證平均每十分鐘生成一個區塊。為了對礦工的計算工作進行獎勵,每一個成功生成區塊的礦工有權在區塊中包含一筆憑空發給他們自己 25BTC 的交易。另外,如果交易的輸入大於輸出,差額部分就作為 “交易費用” 付給礦工。順便提一下,對礦工的獎勵是比特幣發行的唯一機制,創世狀態中並沒有比特幣。為了更好地理解挖礦的目的,讓我們分析比特幣網絡出現惡意攻擊者時會發生什麼。因為比特幣的密碼學基礎是非常安全的,所以攻擊者會選擇攻擊沒有被密碼學直接保護的部分:交易順序。攻擊者的策略非常簡單:
-
向賣家發送 100BTC 購買商品(尤其是無需郵寄的電子商品)。
-
等待直至商品發出。
-
創建另一筆交易,將相同的 100BTC 發送給自己的賬戶。
-
使比特幣網絡相信發送給自己賬戶的交易是最先發出的。一旦步驟(1)發生,幾分鐘後礦工將把這筆交易打包到區塊,假設是第 270000 個區塊。大約一個小時以後,在此區塊後面將會有五個區塊,每個區塊間接地指向這筆交易,從而確認這筆交易。這時賣家收到貨款,並向買家發貨。因為我們假設這是數字商品,攻擊者可以即時收到貨。現在,攻擊者創建另一筆交易,將相同的 100BTC 發送到自己的賬戶。如果攻擊者只是向全網廣播這一消息,這筆交易不會被處理。礦工會運行狀態轉換函數 APPLY (S,TX),發現這筆交易將花費已經不在狀態中的 UTXO。所以,攻擊者會對區塊鏈進行分叉,將第 269999 個區塊作為父區塊重新生成第 270000 個區塊,在此區塊中用新的交易取代舊的交易。因為區塊數據是不同的,這要求重新進行工作量證明。另外,因為攻擊者生成的新的第 270000 個區塊有不同的哈希,所以原來的第 270001 到第 270005 的區塊不指向它,因此原有的區塊鏈和攻擊者的新區塊是完全分離的。在發生區塊鏈分叉時,區塊鏈長的分支被認為是誠實的區塊鏈,合法的的礦工將會沿著原有的第 270005 區塊後挖礦,只有攻擊者一人在新的第 270000 區塊後挖礦。攻擊者為了使得他的區塊鏈最長,他需要擁有比除了他以外的全網更多的算力來追趕(即 51% 攻擊)。
默克爾樹
左:僅提供默克爾樹(Merkle tree)上的少量節點已經足夠給出分支的合法證明。右:任何對於默克爾樹的任何部分進行改變的嘗試都會最終導致鏈上某處的不一致。比特幣系統的一個重要的可擴展特性是:它的區塊存儲在多層次的數據結構中。一個區塊的哈希實際上只是區塊頭的哈希,區塊頭是包含時間戳、隨機數、上個區塊哈希和存儲了所有的區塊交易的默克爾樹的根哈希的長度大約為 200 字節的一段數據。
默克爾樹是一種二叉樹,由一組葉節點、一組中間節點和一個根節點構成。最下面的大量的葉節點包含基礎數據,每個中間節點是它的兩個子節點的哈希,根節點也是由它的兩個子節點的哈希,代表了默克爾樹的頂部。
默克爾樹的目的是允許區塊的數據可以零散地傳送:節點可以從一個源下載區塊頭,從另外的源下載與其有關的樹的其它部分,而依然能夠確認所有的數據都是正確的。之所以如此是因為哈希向上的擴散:如果一個惡意用戶嘗試在樹的下部加入一個偽造的交易,所引起的改動將導致樹的上層節點的改動,以及更上層節點的改動,最終導致根節點的改動以及區塊哈希的改動,這樣協議就會將其記錄為一個完全不同的區塊(幾乎可以肯定是帶著不正確的工作量證明的)。默克爾樹協議對比特幣的長期持續性可以說是至關重要的。
在 2014 年 4 月,比特幣網絡中的一個全節點 - 存儲和處理所有區塊的全部數據的節點 - 需要佔用 15GB 的內存空間,而且還以每個月超過 1GB 的速度增長。目前,這一存儲空間對台式計算機來說尚可接受,但是手機已經負載不了如此巨大的數據了。未來只有商業機構和愛好者才會充當完整節點。簡化支付確認(SPV) 協議允許另一種節點存在,這樣的節點被稱為 “輕節點”,它下載區塊頭,使用區塊頭確認工作量證明,然後只下載與其交易相關的默克爾樹 “分支”。這使得輕節點只要下載整個區塊鏈的一小部分,就可以安全地確定任何一筆比特幣交易的狀態和賬戶的當前餘額。其它的區塊鏈應用將區塊鏈的思想應用到其它領域的想法早就出現了。
在 2005 年,尼克・薩博提出了 “用所有權為財產冠名” 的概念,文中描述了複製數據庫技術的發展如何使基於區塊鏈的系統可以應用於登記土地所有權,創建包括例如房產權、違法侵占和喬治亞州土地稅等概念的詳細框架。然而,不幸的是在那時還沒有實用的複製數據庫系統,所以這個協議並沒有被付諸實踐。不過,自 2009 年比特幣系統的去中心化共識開發成功以來,許多區塊鏈的其它應用開始快速出現。
- 域名幣(namecoin)- 創建於 2010 年,被稱為去中心化的名稱註冊數據庫。
像 Tor、Bitcoin 和 BitMessage 這樣的去中心化協議,需要一些確認賬戶的方法,這樣其他人才能夠與用戶進行互動。但是,在所有的現存的解決方案中僅有的可用的身份標識是像 1LW79wp5ZBqaHW1jL5TciBCrhQYtHagUWy 這樣的伪隨機哈希。理想的情況下,人們希望擁有一個帶有像 “george” 這樣的名稱的賬戶。然而,問題是如果有人可以創建 “george” 賬戶,那麼其他人同樣也可以創建 “george” 賬戶來假扮。唯一的解決方法是先申請原則(first-to-file),只有第一個註冊者可以成功註冊,第二個不能再次註冊同一個賬戶。這一問題就可以利用比特幣的共識協議。
域名幣是利用區塊鏈實現名稱註冊系統的最早的、最成功的系統。- 彩色幣(Colored coins)- 彩色幣的目的是為人們在比特幣區塊鏈上創建自己的數字貨幣,或者,在更重要的一般意義上的貨幣 – 數字令牌提供服務。依照彩色幣協議,人們可以通過為某一特別的比特幣 UTXO 指定顏色,發行新的貨幣。該協議遞歸地將其它 UTXO 定義為與交易輸入 UTXO 相同的顏色。這就允許用戶保持只包含某一特定顏色的 UTXO,發送這些 UTXO 就像發送普通的比特幣一樣,通過回溯全部的區塊鏈判斷收到的 UTXO 顏色。
- 元幣(Metacoins)- 元幣的理念是在比特幣區塊鏈上創建新的協議,利用比特幣的交易保存元幣的交易,但是採用了不同的狀態轉換函數 APPLY‟。因為元幣協議不能阻止比特幣區塊鏈上的無效的元幣交易,所以增加一個規則如果 APPLY‟(S,TX) 返回錯誤,這一協議將默認 APPLY‟(S,TX) = S。這為創建任意的、先進的不能在比特幣系統中實現的密碼學貨幣協議提供了一個簡單的解決方法,而且開發成本非常低,因為挖礦和網絡的問題已經由比特幣協議處理好了。
因此,一般而言,建立共識協議有兩種方法:建立一個獨立的網絡和在比特幣網絡上建立協議。雖然像域名幣這樣的應用使用第一種方法已經獲得了成功,但是該方法的實施非常困難,因為每一個應用需要創建獨立的區塊鏈和建立、測試所有狀態轉換和網絡代碼。另外,我們預測去中心化共識技術的應用將會服從幂律分布,大多數的應用太小不足以保證自由區塊鏈的安全,我們還注意到大量的去中心化應用,尤其是去中心化自治組織,需要進行應用之間的交互。另一方面,基於比特幣的方法存在缺點,它沒有繼承比特幣可以進行簡化確認支付(SPV) 的特性。比特幣可以實現簡化確認支付,因為比特幣可以將區塊鏈深度作為有效性確認代理。在某一點上,一旦一筆交易的祖先們距離現在足夠遠時,就可以認為它們是合法狀態的一部分。與之相反,基於比特幣區塊鏈的元幣協議不能強迫區塊鏈不包括不符合元幣協議的交易。因此,安全的元幣協議的簡化支付確認需要後向掃描所有的區塊,直到區塊鏈的初始點,以確認某一交易是否有效。目前,所有基於比特幣的元幣協議的 “輕” 實施都依賴可信任的伺服器提供數據,這對主要目的之一是消除信任需要的密碼學貨幣而言,只是一個相當次優的結果。
腳本#
即使不對比特幣協議進行擴展,它也能在一定程度上實現” 智能合約”。比特幣的 UTXO 可以被不只一個公鑰擁有,也可以被用基於堆棧的編程語言所編寫的更加複雜的腳本所擁有。在這一模式下,花費這樣的 UTXO,必須提供滿足腳本的數據。事實上,基本的公鑰所有權機制也是通過腳本實現的:腳本將椭圓曲線簽名作為輸入,驗證交易和擁有這一 UTXO 的地址,如果驗證成功,返回 1,否則返回 0。更加複雜的腳本用於其它不同的應用情況。例如,人們可以創建要求集齊三把私鑰中的兩把才能進行交易確認的腳本(多重簽名),對公司賬戶、儲蓄賬戶和某些商業代理來說,這種腳本是非常有用的。腳本也能用來對解決計算問題的用戶發送獎勵。人們甚至可以創建這樣的腳本 “如果你能夠提供你已經發送一定數額的狗幣給我的簡化確認支付證明,這一比特幣 UTXO 就是你的了”,
本質上,比特幣系統允許不同的密碼學貨幣進行去中心化的兌換。然而,比特幣系統的腳本語言存在一些嚴重的限制:
- 缺少圖靈完備性 – 這就是說,儘管比特幣腳本語言可以支持多種計算,但是它不能支持所有的計算。最主要的缺失是循環語句。
不支持循環語句的目的是避免交易確認時出現無限循環。理論上,對於腳本程序員來說,這是可以克服的障礙,因為任何循環都可以用多次重複 if 語句的方式來模擬,但是這樣做會導致腳本空間利用上的低效率,例如,實施一個替代的椭圓曲線簽名算法可能將需要 256 次重複的乘法,而每次都需要單獨編碼。
- 價值盲(Value-blind)。
UTXO 腳本不能為賬戶的取款額度提供精細的控制。
例如,預言機合約(oracle contract)的強大應用是對沖合約,A 和 B 各自向對沖合約中發送價值 1000 美元的比特幣,30 天以後,腳本向 A 發送價值 1000 美元的比特幣,向 B 發送剩餘的比特幣。雖然實現對沖合約需要一個預言機(oracle)決定一比特幣值多少美元,但是與現在完全中心化的解決方案相比,這一機制已經在減少信任和基礎設施方面有了巨大的進步。然而,由於 UTXO 是不可分割的,為實現此合約,唯一的方法是非常低效地採用許多有不同面值的 UTXO(例如對應於最大為 30 的每個 k,有一個 2^k 的 UTXO)並使預言機挑出正確的 UTXO 發送給 A 和 B。- 缺少狀態 – UTXO 只能是已花費或者未花費狀態,這就沒有給需要任何其它內部狀態的多階段合約或者腳本留出生存空間。這使得實現多階段期權合約、去中心化的交換要約或者兩階段加密承諾協議(對確保計算獎勵非常必要)非常困難。這也意味著 UTXO 只能用於建立簡單的、一次性的合約,而不是例如去中心化組織這樣的有著更加複雜的狀態的合約,使得元協議難以實現。二元狀態與價值盲結合在一起意味著另一個重要的應用 - 取款限額 - 是不可能實現的。- 區塊鏈盲(Blockchain-blind)- UTXO 看不到區塊鏈的數據,例如隨機數和上個區塊的哈希。這一缺陷剝奪了腳本語言所擁有的基於隨機性的潛在價值,嚴重地限制了博彩等其它領域應用。我們已經考察了在密碼學貨幣上建立高級應用的三種方法:建立一個新的區塊鏈,在比特幣區塊鏈上使用腳本,在比特幣區塊鏈上建立元幣協議。建立新區塊鏈的方法可以自由地實現任意的特性,成本是開發時間和培育努力。使用腳本的方法非常容易實現和標準化,但是它的能力有限。元幣協議儘管非常容易實現,但是存在擴展性差的缺陷。在以太坊系統中,我們的目的是建立一個能夠同時具有這三種模式的所有優勢的通用框架。
以太坊#
以太坊的目的是基於腳本、競爭幣和鏈上元協議(on-chain meta-protocol)概念進行整合和提高,使得開發者能夠創建任意的基於共識的、可擴展的、標準化的、特性完備的、易於開發的和協同的應用。以太坊通過建立終極的抽象的基礎層 - 內置有圖靈完備編程語言的區塊鏈 - 使得任何人都能夠創建合約和去中心化應用,並在其中設立他們自由定義的所有權規則、交易方式和狀態轉換函數。
域名幣的主體框架只需要兩行代碼就可以實現,諸如貨幣和信用系統等其它協議只需要不到二十行代碼就可以實現。智能合約 - 包含價值而且只有滿足某些條件才能打開的加密箱子 - 也能在我們的平台上創建,並且因為圖靈完備性、價值知曉(value-awareness)、區塊鏈知曉(blockchain-awareness)和多狀態所增加的力量,而比比特幣腳本所能提供的智能合約強大得多。
以太坊賬戶#
在以太坊系統中,狀態是由被稱為 “賬戶”(每個賬戶由一個 20 字節的地址)的對象和在兩個賬戶之間轉移價值和信息的狀態轉換構成的。以太坊的賬戶包含四個部分:
- 隨機數,用於確定每筆交易只能被處理一次的計數器
- 賬戶目前的以太幣餘額
- 賬戶的合約代碼,如果有的話
- 賬戶的存儲(默認為空)
以太幣(Ether)是以太坊內部的主要加密燃料,用於支付交易費用。一般而言,以太坊有兩種類型的賬戶:
外部所有的賬戶(由私鑰控制的)和合約賬戶(由合約代碼控制)。外部所有的賬戶沒有代碼,人們可以通過創建和簽名一筆交易從一個外部賬戶發送消息。每當合約賬戶收到一條消息,合約內部的代碼就會被激活,允許它對內部存儲進行讀取和寫入,和發送其它消息或者創建合約。消息和交易以太坊的消息在某種程度上類似於比特幣的交易,但是兩者之間存在三點重要的不同。
第一,以太坊的消息可以由外部實體或者合約創建,然而比特幣的交易只能從外部創建。第二,以太坊消息可以選擇包含數據。
第三,如果以太坊消息的接受者是合約賬戶,可以選擇進行回應,這意味著以太坊消息也包含函數概念。
以太坊中 “交易” 是指存儲從外部賬戶發出的消息的簽名數據包。交易包含消息的接收者、用於確認發送者的簽名、以太幣賬戶餘額、要發送的數據和兩個被稱為 STARTGAS 和 GASPRICE 的數值。
為了防止代碼的指數型爆炸和無限循環,每筆交易需要對執行代碼所引發的計算步驟 - 包括初始消息和所有執行中引發的消息 - 做出限制。STARTGAS 就是限制,GASPRICE 是每一計算步驟需要支付礦工的費用。如果執行交易的過程中,“用完了燃料”,所有的狀態改變恢復原狀態,但是已經支付的交易費用不可收回了。如果執行交易中止時還剩余燃料,那麼這些燃料將退還給發送者。創建合約有單獨的交易類型和相應的消息類型;合約的地址是基於賬號隨機數和交易數據的哈希計算出來的。
消息機制的一個重要後果是以太坊的 “頭等公民” 財產 - 合約與外部賬戶擁有同樣權利,包括發送消息和創建其它合約的權利。這使得合約可以同時充當多個不同的角色,例如,用戶可以使去中心化組織(一個合約)的成員成為一個中介賬戶(另一個合約),為一個偏執的使用定制的基於量子證明的蘭波特簽名(第三個合約)的個人和一個自身使用由五個私鑰保證安全的賬戶(第四個合約)的共同簽名實體提供居間服務。以太坊平台的強大之處在於去中心化的組織和代理合約不需要關心合約的每一參與方是什麼類型的賬戶。以太坊狀態轉換函數
以太坊的狀態轉換函數: APPLY (S,TX) -> S’ ,可以定義如下:
-
檢查交易的格式是否正確(即有正確數值)、簽名是否有效和隨機數是否與發送者賬戶的隨機數匹配。如否,返回錯誤。
-
計算交易費用=STARTGAS * GASPRICE,並從簽名中確定發送者的地址。從發送者的賬戶中減去交易費用和增加發送者的隨機數。如果賬戶餘額不足,返回錯誤。
-
設定初值 GAS = STARTGAS,並根據交易中的字節數減去一定量的燃料值。
-
從發送者的賬戶轉移價值到接收者賬戶。如果接收賬戶還不存在,創建此賬戶。如果接收賬戶是一個合約,運行合約的代碼,直到代碼運行結束或者燃料用完。
-
如果因為發送者賬戶沒有足夠的錢或者代碼執行耗尽燃料導致價值轉移失敗,恢復原來的狀態,但是還需要支付交易費用,交易費用加至礦工賬戶。
-
否則,將所有剩余的燃料歸還給發送者,消耗掉的燃料作為交易費用發送給礦工。例如,假設合約的代碼如下:
需要注意的是,在現實中合約代碼是用底層以太坊虛擬機(EVM)代碼寫成的。上面的合約是用我們的高級語言 Serpent 語言寫成的,它可以被編譯成 EVM 代碼。假設合約存儲器開始時是空的,一個值為 10 以太,燃料為 2000,燃料價格為 0.001 以太並且兩個數據字段值為 [2, 'CHARLIE'][3] 的交易發送後,狀態轉換函數的處理過程如下:
-
檢查交易是否有效、格式是否正確。
-
檢查交易發送者至少有 2000*0.001=2 個以太幣。如果有,從發送者賬戶中減去 2 個以太幣。
-
初始設定 gas=2000, 假設交易長為 170 字節,每字節的費用是 5,減去 850,所以還剩 1150。
-
從發送者賬戶減去 10 個以太幣,為合約賬戶增加 10 個以太幣。
-
運行代碼。在這個合約中,運行代碼很簡單:它檢查合約存儲器索引為 2 處是否已使用,注意到它未被使用,然後將其值置為 CHARLIE。假設這消耗了 187 單位的燃料,於是剩余的燃料為 1150 – 187 = 963。 6. 向發送者的賬戶增加 963*0.001=0.963 個以太幣,返回最終狀態。如果沒有合約接收交易,那麼所有的交易費用就等於 GASPRICE 乘以交易的字節長度,交易的數據就與交易費用無關了。另外,需要注意的是,合約發起的消息可以對它們產生的計算分配燃料限額,如果子計算的燃料用完了,它只恢復到消息發出時的狀態。因此,就像交易一樣,合約也可以通過對它產生的子計算設置嚴格的限制,保護它們的計算資源。
代碼執行#
以太坊合約的代碼使用低級的基於堆棧的字節碼的語言寫成的,被稱為 “以太坊虛擬機代碼” 或者 “EVM 代碼”。
代碼由一系列字節構成,每一個字節代表一種操作。一般而言,代碼執行是無限循環,程序計數器每增加一(初始值為零)就執行一次操作,直到代碼執行完畢或者遇到錯誤,STOP 或者 RETURN 指令。操作可以訪問三種存儲數據的空間:
堆棧,一種後進先出的數據存儲,32 字節的數值可以入棧,出棧。
-
內存,可無限擴展的字節隊列。
-
合約的長期存儲,一個秘鑰 / 數值的存儲,其中秘鑰和數值都是 32 字節大小,與計算結束即重置的堆棧和內存不同,存儲內容將長期保持。代碼可以像訪問區塊頭數據一樣訪問數值,發送者和接受到的消息中的數據,代碼還可以返回數據的字節隊列作為輸出。 EVM 代碼的正式執行模型令人驚訝地簡單。
當以太坊虛擬機運行時,它的完整的計算狀態可以由元組 (block_state, transaction, message, code, memory, stack, pc, gas) 來定義,這裡 block_state 是包含所有賬戶餘額和存儲的全局狀態。每輪執行時,通過調出代碼的第 pc(程序計數器)個字節,當前指令被找到,每個指令都有定義自己如何影響元組。
例如,ADD 將兩個元素出棧並將它們的和入棧,將 gas(燃料)減一並將 pc 加一,SSTORE 將頂部的兩個元素出棧並將第二個元素插入到由第一個元素定義的合約存儲位置,同樣減少最多 200 的 gas 值並將 pc 加一,雖然有許多方法通過即時編譯去優化以太坊,但以太坊的基礎性的實施可以用幾百行代碼實現。
區塊鏈和挖礦#
雖然有一些不同,但以太坊的區塊鏈在很多方面類似於比特幣區塊鏈。它們的區塊鏈架構的不同在於,以太坊區塊不僅包含交易記錄和最近的狀態,還包含區塊序號和難度值。以太坊中的區塊確認算法如下:
-
檢查區塊引用的上個區塊是否存在和有效
-
檢查區塊的時間戳是否比引用的上個區塊大,而且小於 15 分鐘。
-
檢查區塊序號、難度值、交易根,叔根和燃料限額(許多以太坊特有的底層概念)是否有效。
-
檢查區塊的工作量證明是否有效。
-
將 S [0] 賦值為上個區塊的 STATE_ROOT。
-
將 TX 賦值為區塊的交易列表,一共有 n 筆交易。對於屬於 0……n-1 的 i,進行狀態轉換 S [i+1] = APPLY (S [i],TX [i])。如果任何一個轉換發生錯誤,或者程序執行到此處所花費的燃料(gas)超過了 GASLIMIT,返回錯誤。
-
用 S [n] 給 S_FINAL 賦值,向礦工支付區塊獎勵。
-
檢查 S-FINAL 是否與 STATE_ROOT 相同。如果相同,區塊是有效的。否則,區塊是無效的。這一確認方法乍看起來似乎效率很低,因為它需要存儲每個區塊的所有狀態,但是事實上以太坊的確認效率可以與比特幣相提並論。原因是狀態存儲在樹結構中(tree structure),每增加一個區塊只需要改變樹結構的一小部分。因此,一般而言,兩個相鄰的區塊的樹結構的大部分應該是相同的,因此存儲一次數據,可以利用指針(即子樹哈希)引用兩次。一種被稱為 “帕特里夏樹(Patricia Tree)” 的樹結構可以實現這一點,其中包括了對默克爾樹概念的修改,不僅允許改變節點,而且還可以插入和刪除節點。另外,因為所有的狀態信息是最後一個區塊的部分,所以沒有必要存儲全部的區塊歷史 - 這一方法如果能夠可以應用到比特幣系統中,經計算可以對存儲空間有 10-20 倍的節省。
應用一般來講,以太坊之上有三種應用。第一類是金融應用,為用戶提供更強大的用他們的錢管理和參與合約的方法。包括子貨幣,金融衍生品,對沖合約,儲蓄錢包,遺囑,甚至一些種類的全面的雇傭合約。第二類是半金融應用,這裡有錢的存在但也有很重的非金錢的方面,一個完美的例子是為解決計算問題而設的自我強制懸賞。最後,還有在線投票和去中心化治理這樣的完全的非金融應用。
令牌系統鏈上令牌系統有很多應用,從代表如美元或黃金等資產的子貨幣到公司股票,單獨的令牌代表智能資產,安全的不可偽造的優惠券,甚至與傳統價值完全沒有聯繫的用來進行積分獎勵的令牌系統。在以太坊中實施令牌系統容易得讓人吃驚。
關鍵的一點是理解,所有的貨幣或者令牌系統,從根本上來說是一個帶有如下操作的數據庫:從 A 中減去 X 單位並把 X 單位加到 B 上,前提條件是 (1) A 在交易之前有至少 X 單位以及 (2) 交易被 A 批准。
實施一個令牌系統就是把這樣一個邏輯實施到一個合約中去。用 Serpent 語言實施一個令牌系統的基本代碼如下:
這從本質上來說是本文將要進一步描述的 “銀行系統” 狀態轉變功能的一個最小化實施。需要增加一些額外的代碼以提供在初始和其它一些邊緣情況下分發貨幣的功能,理想情況下會增加一個函數讓其它合約來查詢一個地址的餘額。就足夠了。
理論上,基於以太坊的充當子貨幣的令牌系統可能包括一個基於比特幣的鏈上元幣所缺乏的重要功能:直接用這種貨幣支付交易費的能力。實現這種能力的方法是在合約裡維護一個以太幣賬戶以用來為發送者支付交易費,通過收集被用來充當交易費用的內部貨幣並把它們在一個不斷運行的拍賣中拍賣掉,合約不斷為該以太幣賬戶注資。這樣用戶需要用以太幣 “激活” 他們的賬戶,但一旦賬戶中有以太幣它將會被重複使用因為每次合約都會為其充值。金融衍生品和價值穩定的貨幣金融衍生品是 “智能合約” 的最普遍的應用,也是最易於用代碼實現的之一。實現金融合約的主要挑戰是它們中的大部分需要參照一個外部的價格發布器;例如,一個需求非常大的應用是一個用來對沖以太幣(或其它密碼學貨幣)相對美元價格波動的智能合約,但該合約需要知道以太幣相對美元的價格。最簡單的方法是通過由某特定機構(例如納斯達克)維護的 “數據提供 “合約進行,該合約的設計使得該機構能夠根據需要更新合約,並提供一個接口使得其它合約能夠通過發送一個消息給該合約以獲取包含價格信息的回覆。當這些關鍵要素都齊備,對沖合約看起來會是下面的樣子:等待 A 輸入 1000 以太幣。. 等待 B 輸入 1000 以太幣。
通過查詢數據提供合約,將 1000 以太幣的美元價值,例如,x 美元,記錄至存儲器。30 天後,允許 A 或 B“重新激活 “合約以發送價值 x 美元的以太幣(重新查詢數據提供合約,以獲取新價格並計算)給 A 並將剩余的以太幣發送給 B。這樣的合約在密碼學商務中有非同尋常的潛力。密碼學貨幣經常被詬病的一個問題就是其價格的波動性;雖然大量的用戶和商家可能需要密碼學資產所帶來的安全和便利,可他們不太會樂意面對一天中資產跌去 23% 價值的情形。直到現在,最為常見的推薦方案是發行者背書資產;思想是發行者創建一種子貨幣,對此種子貨幣他們有權發行和贖回,給予(線下)提供給他們一個單位特定相關資產(例如黃金,美元)的人一個單位子貨幣。
發行者承諾當任何人送還一個單位密碼學資產時。發還一個單位的相關資產。這種機制能夠使任何非密碼學資產被 “升級 “為密碼學資產,如果發行者值得信任的話。然而實踐中發行者並非總是值得信任的,並且一些情況下銀行體系太脆弱,或者不夠誠實守信從而使這樣的服務無法存在。
金融衍生品提供了一種替代方案。這裡將不再有提供儲備以支撐一種資產的單獨的發行者,取而代之的是一個由賭一種密碼學資產的價格會上升的投機者構成的去中心化市場。與發行者不同,投機者一方沒有討價還價的權利,因為對沖合約把他們的儲備凍結在了契約中。注意這種方法並非是完全去中心化的,因為依然需要一個可信任的提供價格信息的數據源,儘管依然有争议這依然是在降低基礎設施需求(與發行者不同,一個價格發布器不需要牌照並且似乎可歸為自由言論一類)和降低潛在欺詐風險方面的一個巨大的進步。
身份和信用系統#
最早的替代幣,域名幣,嘗試使用一個類比特幣區塊鏈來提供一個名稱註冊系統,在那裡用戶可以將他們的名稱和其它數據一起在一個公共數據庫註冊。最常用的應用案例把像 “bitcoin.org”(或者再域名幣中,”bitcoin.bit“)一樣的域名與一個 IP 地址對應的域名系統。其它的應用案例包括電子郵件驗證系統和潛在的更先進的信用系統。這裡是以太坊中提供與域名幣類似的的名稱註冊系統的基礎合約:
合約非常簡單;就是一個以太坊網絡中的可以被添加但不能被修改或移除的數據庫。任何人都可以把一個名稱註冊為一個值並永遠不變。一個更複雜的名稱註冊合約將包含允許其他合約查詢的 “功能條款”,以及一個讓一個名稱的” 擁有者(即 “第一個註冊者)修改數據或者轉讓所有權的機制。甚至可以在其上添加信用和信任網絡功能。
去中心化存儲在過去的幾年裡出現了一些大眾化的在線文件存儲初創公司,最突出的是 Dropbox,它尋求允許用戶上傳他們的硬盤備份,提供備份存儲服務並允許用戶訪問從而按月向用戶收取費用。
然而,在這一點上這個文件存儲市場有時相對低效;對現存服務的粗略觀察表明,特別地在 “神秘谷” 20-200GB 這一既沒有免費空間也沒有企業級用戶折扣的水平上,主流文件存儲成本每月的價格意味著支付在一個月裡支付整個硬盤的成本。以太坊合約允許去中心化存儲生態的開發,這樣用戶通過將他們自己的硬盤或未用的網絡空間租出去以獲得少量收益,從而降低了文件存儲的成本。這樣的設施的基礎性構件就是我們所謂的 “去中心化 Dropbox 合約”。
這個合約工作原理如下。
首先,某人將需要上傳的數據分成塊,對每一塊數據加密以保護隱私,並且以此構建一個默克爾樹。然後創建一個含以下規則的合約,每 N 個塊,合約將從默克爾樹中抽取一個隨機索引(使用能夠被合約代碼訪問的上個塊的哈希來提供隨機性),然後給第一個實體 X 以太以支撐一個帶有類似簡化驗證支付(SPV)的在樹中特定索引處的塊的所有權證明。當一個用戶想重新下載他的文件,他可以使用微支付通道協議(例如每 32k 字節支付 1 萨博)恢復文件;從費用上講最高效的方法是支付者不到最後不發布交易,而是用一個略微更合算的帶有同樣隨機數的交易在每 32k 字節之後來代替原交易。這個協議的一個重要特徵是,雖然看起來像是一個人信任許多不準備丟失文件的隨機節點,但是他可以通過秘密分享把文件分成許多小塊,然後通過監視合同得知每個小塊都還被某個節點的保存著。如果一個合約依然在付款,那麼就提供了某個人依然在保存文件的證據。
去中心化自治組織(DAO)#
通常意義上 “去中心化自治組織(DAO, decentralized autonomous organization)” 的概念指的是一個擁有一定數量成員或股東的虛擬實體,依靠比如 67% 多數來決定花錢以及修改代碼。成員會集體決定組織如何分配資金。分配資金的方法可能是懸賞,工資或者更有吸引力的機制比如用內部貨幣獎勵工作。這僅僅使用密碼學區塊鏈技術就從根本上複製了傳統公司或者非營利組織的法律意義以實現強制執行。至此許多圍繞 DAO 的討論都是圍繞一個帶有接受分紅的股東和可交易的股份的 “去中心化自治公司(DAC,decentralized autonomous corporation)” 的 “資本家” 模式;作為替代者,一個被描述為 “去中心化自治社區(decentralized autonomous community)” 的實體將使所有成員都在決策上擁有同等的權利並且在增減成員時要求 67% 多數同意。每個人都只能擁有一個成員資格這一規則需要被群體強制實施。
下面是一個如何用代碼實現 DAO 的綱要。最簡單的設計就是一段如果三分之二成員同意就可以自我修改的代碼。雖然理論上代碼是不可更改的,然而通過把代碼主幹放在一個單獨的合約內並且把合約調用的地址指向一個可更改的存儲依然可以容易地繞開障礙而使代碼變得可修改,在一個這樣的 DAO 合約的簡單實現中有三種交易類型,由交易提供的數據區分:
-
[0,i,K,V] 註冊索引為 i 的對存儲地址索引為 K 至 v 的內容的更改建議。
-
[0,i] 註冊對建議 i 的投票。
-
[2,i] 如有足夠投票則確認建議 i。然後合約對每一項都有具體的條款。它將維護一個所有開放存儲的更改記錄以及一個誰投票表決的表。還有一個所有成員的表。當任何存儲內容的更改獲得了三分之二多數同意,一個最終的交易將執行這項更改。更複雜的框架會增加內置的選舉功能以實現如發送交易,增減成員,甚至提供委任制民主一類的投票代表(即任何人都可以委託另外一個人來代表自己投票,而且這種委託關係是可以傳遞的,所以如果 A 委託了 B 然後 B 委託了 C 那麼 C 將決定 A 的投票)。
這種設計將使 DAO 作為一個去中心化社區有機地成長,使人們最終能夠把挑選合適人選的任務交給專家,與當前系統不同,隨著社區成員不斷改變他們的站隊假以時日專家會容易地出現和消失。一個替代的模式是去中心化公司,那裡任何賬戶可以擁有 0 到更多的股份,決策需要三分之二多數的股份同意。
一個完整的框架將包括資產管理功能 - 可以提交買賣股份的訂單以及接受這種訂單的功能(前提是合約裡有訂單匹配機制)。
代表依然以委任制民主的方式存在,產生了 “董事會” 的概念。更先進的組織治理機制可能會在未來實現;現在一個去中心化組織(DO)可以從去中心化自治組織(DAO)開始描述。DO 和 DAO 的區別是模糊的,一個大致的分割線是治理是否可以通過一個類似政治的過程或者一個 “自動” 過程實現,一個不錯的直覺測試是 “無通用語言” 標準:如果兩個成員不說同樣的語言組織還能正常運行嗎?
顯然,一個簡單的傳統的持股式公司會失敗,而像比特幣協議這樣的卻很可能成功,羅賓・漢森的 “futarchy”,一個通過預測市場實現組織化治理的機制是一個真正的說明 “自治” 式治理可能是什麼樣子的好例子。注意一個人無需假設所有 DAO 比所有 DO 優越;自治只是一個在一些特定場景下有很大優勢的,但在其它地方未必可行的範式,許多半 DAO 可能存在。進一步的應用
- 儲蓄錢包。假設 Alice 想確保她的資金安全,但她擔心丟失或者被黑客盜走私鑰。她把以太幣放到和 Bob 簽訂的一個合約裡,如下所示,這合同是一個銀行:
Alice 單獨每天最多可提取 1%的資金。 Bob 單獨每天最多可提取 1%的資金,但 Alice 可以用她的私鑰創建一個交易取消 Bob 的提現權限。 Alice 和 Bob 一起可以任意提取資金。 一般來講,每天 1%對 Alice 足夠了,如果 Alice 想提現更多她可以聯系 Bob 尋求幫助。如果 Alice 的私鑰被盜,她可以立即找到 Bob 把她的資金轉移到一個新合同裡。如果她弄丟了她的私鑰, Bob 可以慢慢地把錢提出。如果 Bob 表現出了惡意,她可以關掉他的提現權限。
-
作物保險。一個人可以很容易地以天氣情況而不是任何價格指數作為數據輸入來創建一個金融衍生品合約。如果一個愛荷華的農民購買了一個基於愛荷華的降雨情況進行反向賠付的金融衍生品,那麼如果遇到乾旱,該農民將自動地收到賠付資金而如果有足量的降雨他會很開心因為他的作物收成會很好。
-
一個去中心化的數據發布器。對於基於差異的金融合約,事實上通過 “謝林點” 協議將數據發布器去中心化是可能的。謝林點的工作原理如下:N 方為某個指定的數據提供輸入值到系統(例如 ETH/USD 價格),所有的值被排序,每個提供 25% 到 75% 之間的值的節點都會獲得獎勵,每個人都有激勵去提供他人將提供的答案,大量玩家可以真正同意的答案明顯默認就是正確答案,這構造了一個可以在理論上提供很多數值,包括 ETH/USD 價格,柏林的溫度甚至某個特別困難的計算的結果的去中心化協議。
-
多重簽名智能契約。比特幣允許基於多重簽名的交易合約,例如,5 把私鑰裡集齊 3 把就可以使用資金。以太坊可以做得更細化,例如,5 把私鑰裡集齊 4 把可以花全部資金,如果只 3 把則每天最多花 10% 的資金,只有 2 把就只能每天花 0.5% 的資金。另外,以太坊裡的多重簽名是異步的,意思是說,雙方可以在不同時間在區塊鏈上註冊簽名,最後一個簽名到位後就會自動發送交易。
-
雲計算。EVM 技術還可被用來創建一個可驗證的計算環境,允許用戶邀請他人進行計算然後選擇性地要求提供在一定的隨機選擇的檢查點上計算被正確完成的證據。這使得創建一個任何用戶都可以用他們的台式機,筆記本電腦或者專用伺服器參與的雲計算市場成為可能,現場檢查和安全保證金可以被用來確保系統是值得信任的(即沒有節點可以因欺騙獲利)。雖然這樣一個系統可能並不適用所有任務;例如,需要高級進程間通信的任務就不易在一個大的節點雲上完成。然而一些其它的任務就很容易實現並行; SETI@home, folding@home 和基因算法這樣的項目就很容易在這樣的平台上進行。
-
點對點賭博。任意數量的點對點賭博協議都可以搬到以太坊的區塊鏈上,例如 Frank Stajano 和 Richard Clayton 的 Cyberdice。最簡單的賭博協議事實上是這樣一個簡單的合約,它用來賭下個區塊的哈希值與猜測值之間的差額,據此可以創建更複雜的賭博協議,以實現近乎零費用和無欺騙的賭博服務。
-
預測市場。不管是有神諭還是有謝林幣,預測市場都會很容易實現,帶有謝林幣的預測市場可能會被證明是第一個主流的作為去中心化組織管理協議的 “futarchy” 應用。
-
鏈上去中心化市場,以身份和信用系統為基礎。
雜項和關注#
改進版幽靈協議的實施 “幽靈 “協議(”Greedy Heaviest Observed Subtree” (GHOST) protocol)是由 Yonatan Sompolinsky 和 Aviv Zohar 在 2013 年 12 月引入的創新。幽靈協議提出的動機是當前快速確認的區塊鏈因為區塊的高作廢率而受到低安全性困擾;因為區塊需要花一定