Serenity - 第一部分: 深度抽象是什么?Serenity是什么?
我們已經公開繼續改進以太坊協議的計劃和長期開發路線圖相當長一段時間了,這個做法也是來自于從1.0版本發布之前或者事后沒有能及時處理的錯誤中學到的經驗 。不管怎樣,以太坊核心協議的周期性開發已經重新啟動,Homestead階段很快就要到來,我們也已經悄悄開始開發一個概念原型(PoC),目標是開發路線圖中最大的里程碑: Serenity.下面小編給大家介紹一下!

Serenity會有兩大主要特性:深度抽象,一個我最早在這里展開討論過的特性,和Casper,基于保證金的權益證明(PoS)算法 。此外,我們也在探索平滑的部署可伸縮性(scalability)改進的方法,至少是一個腳手架 , 同時完全解決這里對并行性的擔憂 - 運行在私有鏈環境下,多核CPU專有服務器之上的以太坊節點性能將會有立竿見影的巨大提升,甚至公有鏈的可伸縮性也能看到2到5倍的提升 。在過去的幾個月中,Casper的研究和對可伸縮性與抽象改進的形式化工作(eg. EIP101)都在快速推進,參與者有我, Vlad Zamfir, Lucius Greg Meredith和其他一些人 。現在我很高興的宣布,Serenity階段的第一個概念原型, 盡管能做的事情還非常有限僅僅可以用于測試,已經完成 。
在ethereum目錄下運行python test.py就可以把概念原型跑起來(別忘了先從https://github.com/ethereum/serpentSerpent下載和安裝最新的 develop分支),如果看到這樣的輸出就對了:
vub@vub-ThinkPad-X250 15:01:03 serenity/ethereum: python test.py
REVERTING 940534 gas from account 0x0000000000000000000000000000000000000000 to account 0x98c78be58d729dcdc3de9efb3428820990e4e3bf with data 0x
Warning (file casper.se.py, line 74, char 0): Warning: function return type inconsistent!
Running with 13 maximum nodes
Warning (file casper.se.py, line 74, char 0): Warning: function return type inconsistent!
Warning (file casper.se.py, line 74, char 0): Warning: function return type inconsistent!
Length of validation code: 57
Length of account code: 0
Joined with index 0
Length of validation code: 57
Length of account code: 0
Joined with index 1
Length of validation code: 57
在每5秒一個塊,使用Casper Serenity協議的條件下,這個程序模擬了的13個節點的運行;這個模擬已經很接近當前客戶端能處理的上限了,不過要注意:(i) 這是python寫的 , C和Go的實現很可能會有更好的表現,以及(ii) 所有這些節點都同時運行在一臺電腦上,所以你有理由相信在一個更“正常”的環境中python版本的Casper可以處理大約169個節點(不過,從另一方面來說 , 我們希望共識的開銷遠低于100%的CPU占用,因此這兩點注意并不表示你可以期待Casper和上千個節點一起工作!) 。如果你的電腦太慢處理不了13個節點,試試用python test.py 10來模擬10個節點(或者python test.py 7來模擬7個節點,你懂的) 。當然,改進Casper效率的研究仍在繼續 , 雖然這改進可能會以減慢終局性(finality)的收斂為代價 , 這些問題都會逐漸解決 。network.py文件模擬了一個基本的P2P網絡接口,接下來的工作會把它替換成運行在真實網絡上的真實計算機 。
程序代碼被分割到幾個主要文件中:
serenity_blocks.py - 描述block類,state類,以及block和transaction級別狀態轉移函數的代碼(比以前的版本簡單一倍) 。
serenity_transactions.py - 描述transaction的代碼(比之前簡單一倍) 。
casper.se.py - Casper合約的serpent實現 , 激勵正確的下注行為 。
bet.py - Casper的下注邏輯和完整的客戶端實現 。
ECDSA_accounts.py - 賬戶相關代碼,讓你可以在Serenity上模擬當前的賬戶驗證邏輯 。
【Serenity - 第一部分: 深度抽象是什么?Serenity是什么?】test.py - 測試腳本
config.py - 參數配置
vm.py - 虛擬機(fastvm.py提供了一個更快的實現)
network.py - 網絡模擬
在這篇文章中,我們只討論深度抽象的特性,因此關鍵文件是serenity_blocks.py, ecdsa_accounts.py和serenity_transactions.py;在下一篇討論Casper的文章中,casper.se.py和bet.py將會是焦點 。
賬戶的抽象
目前以太坊中有兩種類型的賬戶:外部擁有的賬戶 , 由私鑰控制 , 和合約賬戶 , 由代碼控制 。對于外部擁有的賬戶,我們指定了一種特別的數字簽名算法(secp256k1橢圓曲線簽名)和一個序號體系(nonce),要求每一個交易都必須包含一個比前一個交易序號大1的數字,目的是防止重放攻擊(replay attacks) 。我們為提高抽象程度而做的主要改動是:不再有兩種不同類型的賬戶,而是統一為一種 - 合約賬戶 。將會存在一個特殊的“入口”賬戶,0x0000000000000000000000000000000000000000,任何人都可以從這個賬戶發起交易 。因此,協議中將不再包含簽名 nonce的賬戶驗證邏輯,用戶必須用合約來保護他們自己的賬戶 。
最簡單有效的此類合約可能要屬橢圓曲線數字簽名驗證合約了,它可以提供和現在完全一樣的功能:只有擁有有效簽名和序號的交易才能通過驗證,而且序號在交易成功后增加1 。這個合約的代碼如下:
# We assume that data takes the following schema:
# bytes 0-31: v (ECDSA sig)
# bytes 32-63: r (ECDSA sig)
# bytes 64-95: s (ECDSA sig)
# bytes 96-127: sequence number (formerly called nonce)
# bytes 128-159: gasprice
# bytes 172-191: to
# bytes 192-223: value
# bytes 224 : data
# Get the hash for transaction signing
~mstore(0, ~txexecgas())
~calldatacopy(32, 96, ~calldatasize() - 96)
~mstore(0, ~sha3(0, ~calldatasize() - 64))
~calldatacopy(32, 0, 96)
# Call ECRECOVER contract to get the sender
~call(5000, 1, 0, 0, 128, 0, 32)
# Check sender correctness; exception if not
if ~mload(0) != 0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1:
~invalid()
# Sequence number operations
with minusone = ~sub(0, 1):
with curseq = self.storage[minusone]:
# Check sequence number correctness, exception if not
if ~calldataload(96) != curseq:
~invalid()
# Increment sequence number
self.storage[minusone] = curseq1
# Make the sub-call and discard output
with x = ~msize():
~call(msg.gas - 50000, ~calldataload(160), ~calldataload(192), 160, ~calldatasize() - 224, x, 1000)
# Pay for gas
~mstore(0, ~calldataload(128))
~mstore(32, (~txexecgas() - msg.gas50000))
~call(12000, ETHER, 0, 0, 64, 0, 0)
~return(x, ~msize() - x)
這段代碼就是用戶賬戶的合約代碼;如果用戶要從自己的賬戶發送一個交易,他們會先從地址0發送一個交易到這個賬戶 , 交易數據會像上述代碼所示那樣包括ECDSA簽名 , 序號,gas價格,目標地址,數額和真正的交易數據 。合約代碼會檢查對交易gas限制和數據的簽名,然后檢查交易序號,如果兩者都沒有問題就把保存的序號加一 , 發送所需的消息 , 然后發送另一條消息支付gas費用作為結束(注意,礦工可以靜態分析賬戶的合約代碼,如果交易的賬戶合約最后沒有支付gas可以拒絕處理) 。
Serenity的這個改動有一個很重要的后果,系統中的所有交易(只要滿足基本的格式)都是有效的 。現階段無效的交易在Serenity中將僅僅是沒有作用(上例中的invalid是一個尚未使用的操作碼,它會使程序執行立即退出) 。這意味著交易被打包進區塊不再是交易會被真正執行的保證,作為彌補,每一筆交易都會有一條收據記錄(receipt entry) , 通過返回碼指明它是否成功執行:0表示由于gas限制交易沒有執行,1表示交易執行了但是出錯,2表示交易成功執行 。收據記錄還可以提供更多的信息,例如交易的返回值(現在有自動日志記錄)或者自己創建的日志,
這個改動最主要的好處是用戶可以在賬戶策略這個領域自由的創新了 。可能的方向包括:
比特幣風格的多重簽名 , 賬戶要求交易同時具有多個私鑰的簽名 , 而不是一次接收一個簽名,然后把中間結果臨時存放在區塊鏈里 。
其他的橢圓曲線, 包括ed25519 。
更好的集成先進的加密算法,例如環狀簽名(ring signature),門限簽名(threshold signature), 零知識證明等等 。
更先進的序號方案, 支持更高程度的并行化,讓用戶可以同時從一個賬戶發出多個交易,并且更快的把這些交易打包 。想想傳統的序號和位掩碼(bitmask)如果結合會怎樣 。我們也可以通過各種機智的方法在有效性檢查中利用時間戳或是區塊的hash值 。
基于UTXO的代幣管理, 有些用戶處于隱私的元應,不喜歡以太坊使用賬戶而不是比特幣的“未使用的交易輸出”(unspent transaction output, UTXO)模型來管理代幣的所有權 。現在你可以在以太坊中建立一個事實上基于UTXO的系統了,并且Serenity不再顯式的特殊對待其中某一個 。
支付方案的創新,對于某些dapp, “由合約支付費用”可能比“由使用者支付”更有用,使用者可能沒有以太幣 。現在dapp就可以實現這個支付模型了 。如果礦工能對它的代碼做靜態分析并確信他們可以得到報酬 , 礦工就會接受這種交易(本質上,我們實現了Rookstock想要通過可選的作者支付(author-pay)想做的事情,但是是通過一種更抽象和靈活的方法) 。
與“以太坊鬧鐘”之類的應用更好的集成,賬戶的檢驗代碼不一定要檢查簽名 , 也可以檢查收據的Merkle proof,或是其他賬戶的狀態,等等 。
提出這些場景是為了說明最主要的論點 , 通過抽象所有這些另外的機制都可以更加容易的實現,不再需要創造一個“傳遞層”來把信息喂給以太坊默認的簽名體系 。當沒有應用是特殊的時候,每個應用都特殊 。
一個特別有意思的結果是:在Serenity的設計下,以太坊將具有可選的量子安全性 。如果你害怕NSA秘密擁有一臺量子計算機 , 想要把自己的賬戶變得更安全,你隨時可以個人切換使用Lamport簽名 。轉換到PoS機制進一步鞏固了安全性,即使世界上只有NSA有量子計算機他們也不能利用這一點來實施51%攻擊 。在以太坊的協議層唯一剩下的密碼學安全假設只有SHA3的抵御碰撞(collision-resistance)的性質了 。
這些改變的另一個結果是 , 交易數據會變得更加簡單 。交易將會用四個字段取代現在的九個:目標地址,數據,初始gas和初始化代碼 。目標地址 , 數據和初始gas和現在一樣,“初始化代碼”是一個可選用于保存目標地址賬戶合約創建代碼的字段 。
需要這個機制的原因如下 。目前以太坊有一個重要的性質,是允許往一個還不存在的賬戶轉賬 。為了在區塊鏈上創建一個合約接受以太幣,你并不需要事先持有任何以太幣 。為了在Serenity中實現這個性質,我們讓賬戶地址能事先從它的初始化代碼中推導出來,通過公式sha3(creatorinitcode) % 2**160 。這里creator是創建這個合約的賬戶(默認是地址為0的賬戶) , 而initcode就是合約的初始化代碼(這段代碼的運行結果會成為賬戶合約的代碼,正如現在的CREATE一樣) 。因此你可以在本地先生成這段初始化代碼,計算它的地址,然后讓其他人往這個地址轉賬 。然后一旦你想要從這個地址發出第一筆交易,你可以在交易里面包含這段初始化代碼 , 它就會在真正的交易執行之前,被自動執行并創建賬戶(這段邏輯的實現代碼在這里) 。
區塊的抽象
Serenity中將實現的另一個干凈的分離是將區塊(僅僅是一堆交易),狀態(例如合約的存儲區 , 代碼和賬戶余額)和共識層完全分開 。共識激勵在合約內部實現,而如果你希望激勵的話,共識級別的對象(例如PoW, 賭注)應該被包含在發往“共識激勵管理合約”的交易中 。
這應該會讓你更容易用其它的共識算法 - Tendermint, HoneyBadgeBFT, subjective consensus甚至是普通的PoW - 替換掉Serenity代碼中的Casper 。我們非常歡迎這個方向的研究,并且希望能做到最大的靈活 。
存儲的抽象
目前,以太坊系統的“狀態”數據實際上相當復雜 , 包括這些部分:
余額,代碼,nonce,和賬戶存儲區
Gas上限,難度 , 塊高度,時間戳
最后256個塊的hash值
在執行區塊內代碼時 , 需要保存交易索引,收據樹(receipt tree, receipt是EVM中的一個概念)和當前消耗的gas 。
這些數據結構存在于許多地方,包括塊狀態轉移函數,狀態樹,區塊頭和前一個區塊頭中 。在Serenity里面這些將被大幅簡化:雖然許多數據仍然會存在 , 但他們會被轉移到特殊的合約中去;因此,唯一的”“狀態”將以一棵樹的形式繼續存在,數學上可以看作是形如{address: {key: value}}的映射 。賬戶將是一些樹 , 賬戶合約代碼會被存放在主鍵(key)為的地方(SSTORE不可以修改),余額會存在特別的“以太幣合約”中,而序號將由每一個帳號自己決定如何保存 。收據也將被轉移到合約存儲區,他們會被保存在一個內容在每個區塊都會被覆蓋的“日志合約”中 。
這樣代碼實現中的狀態對象可以極大的簡化 。現在只剩下一個兩級的trie了 。可伸縮性方面的升級可能要求增加為三級trie(分片ID, 地址,主鍵) , 這還沒有確定,但即使是這樣復雜性也遠低于現在 。
需要注意 , 把以太幣轉移進一個合約管理并不是以太幣抽象的全部 。事實上,一個有爭議的看法是相對于現狀這并不是一個很大的進步 , 因為為了向前兼容那些和以太幣相關的操作碼(帶value參數的CALL,BALANCE等等)依然保留著 。某種程度上說,這只是數據存放的一次重組 。
未來的計劃
在第二個概念原型中,我們計劃讓抽象更進一步 。目前區塊和交易級別的狀態轉移函數依然有相當的復雜性(例如更新收據,gas限制,交易索引,區塊高度 , 狀態根節點),我們的目標是為交易創建一個“入口”對象來處理所有這些每一個交易都需要的額外的“樣板邏輯”,以及“塊開始”和“塊結束”的入口 。理論上的終極目標,是找到一個只有一個入口點的協議 , 這樣狀態轉移函數只需要從零地址發送一條包含區塊內容數據的消息給入口點即可 。這樣做的目的是盡可能的減少客戶端實現的共識關鍵部分(consensus-critical client implementation)的大?。?把盡可能多的邏輯推到以太坊自身上去 。這樣即使為了達到我們對交易速度和可伸縮性的目標,我們需要采用一個接受硬分叉和一定的新復雜度的激進開發制度 , 也能夠個確保以太坊的多重客戶端形態可以持續而無需大量額外開發工作和安全審計 。
長期來看 , 我打算繼續在python上開發概念原型,Casper團隊則共同改進協議的效率,并證明它的安全性和正確性 。在某個時刻,這個協議將成熟到足以處理一個公開的某種形式的測試網絡,其上可能會有真實的價值 , 為人們找出Casper的漏洞提供激勵,就像一條真正的鏈不可避免的遭受的那樣 。這只是第一步,不過是非常重要的一步 , 它標志著我們對于權益證明和深度抽象的研究終于從談話,白板上的數學公式和博客文章變成了能工作的代碼 。
這個系列的下一篇文章將會討論Serenity的另一個旗艦特性,Casper共識算法 。
以上就是關于Serenity - 第一部分: 深度抽象的相關介紹 , 希望小編的內容能幫到大家!
