【译】From Smart Contracts to Courts with not so Smart Judges
以太坊通常被描述為自我實施智能合約的平臺。 雖然這確實是正確的,但本文認為,特別是當涉及更復雜的系統時,它更像是一個擁有聰明的律師的法院和一個不那么聰明的法官,或者更正式的法官,他是一個計算資源有限的法官。 稍后我們將看到如何利用這種視圖來編寫非常有效的智能合約系統,以便能夠以幾乎免費的方式實現交叉鏈代幣轉移或計算工作證明等計算。
法庭類比
首先,您可能知道以太坊上的智能合約本身無法從外部世界檢索信息。 它只能要求外部參與者代表其提供信息。 即便如此,它要么必須信任外部參與者,要么驗證信息本身的完整性。 在法庭上,法官通常會向專家詢問他們的意見(他們通常信任的人)或證人的證詞,這些證詞通常經過交叉核對驗證。
我猜很明顯,由于氣體限制,以太坊中的判斷者的計算資源受到限制,與來自外部世界的律師的計算能力相比,這種限制相當低。 然而,以這種方式受到限制的法官仍然可以決定非常復雜的法律案件:她的權力來自于她可以扮演辯護人對抗檢察官這一事實。
復雜性理論
這個確切的類比在Feige,Shamir和Tennenholtz, Noisy Oracle Problem的一篇文章中正式化。 他們主要結果的一個非常簡化的版本如下:假設我們有一個合同(判斷)誰可以使用N個步驟來執行計算(可能分布在多個事務中)。 有幾個外部演員(律師)可以幫助法官,其中至少有一個是誠實的(即至少有一個演員遵循既定的協議,其他人可能是惡意的并發送任意信息),但法官不知道誰誠實的演員是。 這樣的合同可以在沒有外界幫助的情況下執行可以使用N個存儲器單元和任意數量的步驟執行的任何計算。 (正式版本聲明多項式時間驗證器可以接受此模型中的所有PSPACE)
這可能聽起來有點笨拙,但他們的證明實際上非常有啟發性,并且使用PSPACE的類比是可以通過“游戲”解決的一類問題。 舉個例子,讓我告訴你一個以太坊合約如何下棋幾乎沒有汽油費用(專家可以原諒我使用NEXPTIME完成的國際象棋,但我們將在這里使用經典的8x8變體,所以它實際上是在PSPACE ... ):在這種情況下下棋意味著一些外部演員提出國際象棋位置,合同必須確定該位置是否是白色的獲勝位置,即白色總是獲勝,假設白色和黑色是無限聰明的。 這假設誠實的脫鏈演員有足夠的計算能力來完美地下棋,但是......所以任務不是與外部演員下棋,而是確定給定位置是否是白棋的獲勝位置并且詢問外部演員(除了其中一個可能誤導,給出錯誤的答案)以尋求幫助。 我希望你同意在沒有外界幫助的情況下這樣做非常復雜。 為簡單起見,我們只看一下我們有兩個外部演員A和B的情況。這是合同的作用:
合同并不需要對國際象棋戰略有任何線索。 它只需要能夠驗證單個移動是否有效。 因此合同的成本大致為N*(V+U) ,其中N是移動的數量(實際上是ply),V是驗證移動的成本,U是更新電路板的成本。
這個結果實際上可以改進為N*U + V ,因為我們不需要驗證每一個動作。 我們可以更新電路板(假設移動是通過坐標給出的),當我們要求下一步時,我們也會詢問前一步是否無效。 如果回答為“是”,我們檢查移動。 根據移動是否有效,其中一名球員被騙,我們知道誰獲勝。
家庭作業:改進合同,以便我們只需存儲移動序列并僅為移動的一小部分更新電路板,并僅針對單個移動執行移動驗證,即將成本帶到N*M + tiny(N)*U + V ,其中M是存儲移動的成本,而tiny是一個適當的函數,它返回N的“微小部分”。
在旁注中, Babai,Fortnow和Lund表明,律師正在合作但不能相互溝通的模型和法官被允許擲骰子(兩個變化都很重要)捕獲了一個據稱更大的類NEXPTIME,非確定性指數時間。
將加密經濟學添加到游戲中
從前一節要記住的一點是,假設交易沒有受到審查,合同將始終找出誠實的人和不誠實的演員是誰。 這導致了一個有趣的觀察,我們現在有一個相當便宜的交互協議來解決難題,但我們可以添加一個加密經濟機制,確保幾乎不必執行該協議:該機制允許任何人提交結果與保證金一起計算。 任何人都可以挑戰結果,但也必須提供押金。 如果存在至少一個挑戰者,則執行交互協議(或其多證明者變體)。 假設在提議者和挑戰者中至少有一個誠實的行為者,那些不誠實的行為者將被揭露,而誠實的行為者將獲得存款(減去一定百分比,這將阻止一個不誠實的提議者自我挑戰)作為獎勵。 因此,最終的結果是,只要至少有一個誠實的人正在觀察誰沒有受到審查,惡意行為者就沒有辦法成功,甚至嘗試對惡意行為者來說也是代價高昂的。
想要使用計算結果的應用程序可以將存款作為計算可信度的指標:如果解決方案提議者存在大量存款而且在一定時間內沒有質詢,則結果可能是正確的。 一旦出現挑戰,應用程序應該等待協議得到解決。 我們甚至可以創建計算結果保險,承諾檢查離線計算并退還用戶,以防無效結果未及早提出質疑。
二元搜索的力量
在接下來的兩節中,我將給出兩個具體的例子。 一個是交互式地驗證外部區塊鏈中數據的存在,第二個是關于驗證一般(確定性)計算。 在它們兩者中,我們經常會遇到這樣的情況:提議者有一個很長的值列表(由于它的長度而不能直接用于合同),它以正確的值開頭但以不正確的值結束(因為提議者想欺騙)。 合同可以很容易地計算第i個(i + 1)st值,但檢查完整列表會太昂貴。 挑戰者知道正確的列表,并可以要求提議者從該列表中提供多個值。 由于第一個值是正確的而且最后一個是不正確的,所以在這個列表中必須至少有一個點i,其中第i個值是正確的并且(i + 1)st值是不正確的,并且挑戰者的任務是找到這個位置(讓我們稱這一點為“轉換點”),因為那時合同可以檢查它。
讓我們假設列表的長度為1.000.000,因此我們的搜索范圍為1到1.000.000。 挑戰者詢問位置500.000的價值。 如果正確,則至少有一個轉換點在500.000和1.000.000之間。 如果不正確,則存在介于1和500.000之間的轉換點。 在這兩種情況下,搜索范圍的長度減少了一半。 我們現在重復這個過程,直到我們達到大小為2的搜索范圍,這必須是轉換點。 基數2的對數可用于計算“迭代二分”所采用的步數。 在1.000.000的情況下,這些是log1.000.000≈20步。
廉價的跨鏈轉移
作為第一個真實世界的例子,我想展示如何設計一個極其便宜的交叉鏈狀態或支付驗證。 由于區塊鏈不是確定性的,但可以分叉,這有點復雜,但總體思路是一樣的。
提議者提交她想要在目標合同中可用的數據(例如比特幣或狗狗幣交易,另一個以太坊鏈中的狀態值,或者Merkle-DAG中的任何東西,其根哈希包含在區塊鏈的塊頭中并且是公知的(這是非常重要的))以及塊號,該塊頭的散列和存款。
請注意,我們只提交一個塊號和哈希值。 在BTCRelay的第一個版本中,目前需要提交所有比特幣塊頭,并驗證所有比特幣的工作證明。 該協議僅在發生攻擊時才需要該信息。
如果一切正常,即外部驗證器檢查塊編號的散列是否與規范鏈匹配(并且可選地具有一些確認)并查看該塊中包含的事務/數據,則提議者可以請求返回存款和交叉 - 鏈轉移完成。 這就是非攻擊案件中的全部內容。 這應該每次轉移耗費約20萬個氣體。
如果出現問題,即我們要么有惡意提議者/提交者或惡意挑戰者,那么挑戰者現在有兩種可能:
注意,區塊鏈是由兩個“臂”組成的Merkle-DAG:一個形成塊頭鏈,一個形成狀態或事務的Merkle-DAG。 一旦我們接受根(當前塊頭哈希)有效,雙臂中的驗證就是簡單的Merkle-DAG證明。
(2)因此,讓我們先考慮第二種情況,因為它更簡單:因為我們希望盡可能高效,所以我們不要求提議者提供完整的Merkle-DAG證明。 相反,我們只是請求從根到數據的DAG路徑(即一系列子索引)。
如果路徑太長或索引無效,則挑戰者會詢問提議者超出范圍的點的父值和子值,并且提議者無法提供散列到父級的有效數據。 否則,我們的情況是根哈希是正確的,但某些點的哈希是不同的。 使用二進制搜索,我們在路徑中找到一個點,我們在一個不正確的哈希上方有一個正確的哈希值。 提議者將無法提供散列到正確散列的子值,因此合同可以檢測到欺詐。
(1)現在讓我們考慮提議者使用無效塊或作為廢棄叉子一部分的塊的情況。 讓我們假設我們有一種機制將其他區塊鏈的區塊編號與以太坊區塊鏈上的時間相關聯,因此合同有一種方法可以告訴區塊編號無效,因為它必須在將來存在。 提議者現在必須提供所有塊頭(比特幣只有80個字節,如果它們太大,僅從哈希開始)直到合同已經知道的某個檢查點(或者挑戰者以塊的形式請求它們)。 挑戰者必須做同樣的事情,并希望提供一個具有更高的區塊數/總難度的區塊。 現在兩人都可以交叉檢查他們的積木。 如果有人發現錯誤,他們可以將塊號提交給合同,該合同可以檢查或讓其由另一個交互階段驗證。
一般計算的特定交互式證明
假設我們有一個尊重局部性的計算模型,即它只能在一個步驟中對內存進行局部修改。 圖靈機尊重局部性,但隨機訪問機器(通常的計算機)如果只在每一步中修改內存中的恒定點數,也可以。 此外,假設我們有一個H位輸出的安全散列函數。 如果在這樣的機器上進行計算需要t步并且使用最多s個字節的內存/狀態,那么我們可以在以太網中執行關于log(t)+ 2 * log的此計算的交互式驗證(在提議器/挑戰者模型中) (log(s))+ 2輪,其中每輪中的消息不長于max(log(t),H + k + log(s)),其中k是“程序計數器”的大小,寄存器,磁頭位置或類似的內部狀態。 除了將消息存儲在存儲器中之外,合同還需要執行機器的最多一步或散列函數的一次評估。
證明:
該想法是計算(至少在請求時)每個步驟中計算所使用的所有存儲器的Merkle樹。 合同很容易驗證單步對存儲器的影響,并且由于只能訪問存儲器中的恒定點數,因此可以使用Merkle-proofs驗證存儲器的一致性。
在不失一般性的情況下,我們假設每一步都只訪問內存中的一個點。 協議從提交者提交輸入和輸出開始。 挑戰者現在可以針對各種時間步驟i請求存儲器的Merkle樹根,內部狀態/程序計數器以及訪問存儲器的位置。 挑戰者使用它來執行二進制搜索,該步驟導致步驟i,其中返回的信息是正確的但在步驟i + 1中是不正確的。這需要最多log(t)輪和大小log(t)的消息。 H + k + log(s)。
挑戰者現在請求訪問(在步驟之前和之后)的內存中的值以及沿著根路徑的所有兄弟(即Merkle證明)。 請注意,兄弟姐妹在步驟之前和之后是相同的,只有數據本身發生了變化。 使用此信息,合同可以檢查步驟是否正確執行并且根哈希是否正確更新。 如果合同驗證Merkle證明有效,則輸入內存數據必須正確(因為散列函數是安全的,并且提議者和挑戰者都具有相同的預根哈希)。 如果步驟執行被驗證正確,則它們的輸出存儲器數據相等。 由于Merkle樹的兄弟姐妹是相同的,找到不同的后根哈希的唯一方法是計算或Merkle證明有錯誤。
注意,前一段中描述的步驟進行了一輪并且消息大小為(H + 1)log(s)。 所以我們總共有log(t)+ 1輪和消息大小max(log(t),k +(H + 2)log(s))。 此外,合同需要計算散列函數2 * log(s)次。 如果s很大或散列函數很復雜,我們可以稍微減小消息的大小,并且只需要以更多交互為代價來達到散列函數的單個應用程序。 我們的想法是在Merkle證明上執行二進制搜索,如下所示:
我們不要求提議者發送完整的Merkle證明,而只發送內存中的pre-post值和post值。 合同可以檢查停止的執行,所以讓我們假設轉換是正確的(包括步驟i + 1中的內部post狀態和內存訪問索引)。 剩下的案例是:
在第一種情況下,挑戰者在從包含存儲器數據的Merkle樹葉到根的路徑上執行交互式二進制搜索,并找到具有正確父但錯誤子的位置。 這最多需要log(log(s))輪次和大小log(log(s))的消息。 H位。 最后,由于散列函數是安全的,因此提議者不能為散列到父節點的錯誤子節點提供兄弟節點。 這可以通過合同檢查哈希函數的單個評估。
在第二種情況下,我們處于倒置狀態:根是錯誤的,但葉子是正確的。 挑戰者再次在最多log(log(s(n))輪中執行交互式二進制搜索,其中消息大小為log(log(s))resp。 H位并在樹中找到父P錯誤但子C正確的位置。 挑戰者向提議者詢問兄弟S,使得(C,S)散列到P,合同可以檢查。 由于我們知道只有存儲器中的給定位置可以隨著步驟的執行而改變,所以S也必須出現在步驟之前的存儲器的Merkle樹中的相同位置。 此外,提議者為S提供的值不能正確,因為那時,(C,S)不會哈希到P(我們知道P是錯誤的,但C和S是正確的)。 因此,我們將其減少到提議者在pre-Merkle-tree中提供了錯誤節點但是正確的根哈希的情況。 如第一種情況所示,這最多需要log(log(s))輪次和大小log(log(s))的消息。 H位驗證。
總的來說,我們最多有log(t)+ 1 + 2 * log(log(s))+ 1輪,消息大小最多為max(log(t),H + k + log(s))。
家庭作業:將此證明轉換為可用于EVM或TinyRAM(以及C)程序的工作合同,并將其集成到Piper Merriam的以太坊計算市場中 。
感謝Vitalik建議使用Merkle-hash內存以允許任意的步進內存大小! 順便說一句,這很可能不是一個新結果。
在實踐中
這些對數很好,但這在實踐中意味著什么? 讓我們假設我們在使用5 GB RAM的4 GHz計算機上進行5秒的計算。 簡化實際時鐘速率與人工架構上的步驟之間的關系,我們大致有t =20000000000≈243和s =5000000000≈232。 交互式驗證這樣的計算應該采用43 + 2 + 2 * 5 = 55輪,即2 * 55 = 110塊并使用大約128字節的消息(主要取決于k,即架構)。 如果我們不以交互方式驗證Merkle證明,我們得到44輪(88塊)和大小為1200字節的消息(只有最后一條消息那么大)。
如果你說110塊(在以太坊上大約30分鐘,3比特幣上的確認)聽起來很多,不要忘記我們在這里談論的內容:4 GHz機器上實際使用5 GB RAM的5秒鐘。 如果您經常運行具有如此強大功能的程序,它們會搜索滿足特定條件的特定輸入值(優化例程,密碼破解程序,工作解算器證明......)。 由于我們只想驗證計算,因此不需要以這種方式執行搜索,我們可以從頭開始提供解決方案,只檢查條件。
好吧,對于每個計算步驟計算和更新Merkle樹應該是非常昂貴的,但是這個例子應該只顯示這個協議在鏈上的擴展程度。 此外,大多數計算,特別是在函數式語言中,可以細分為我們稱之為昂貴函數的級別,這些函數使用大量內存但輸出的數量很少。 我們可以將此功能視為主協議中的一個步驟,并在該功能中檢測到錯誤時啟動新的交互協議。 最后,正如已經說過的那樣:在大多數情況下,我們只是驗證輸出并且從不挑戰它(只有那時我們才需要計算Merkle樹),因為提議者幾乎肯定會失去他們的存款。
打開問題
在本文的幾個地方,我們假設我們只有兩個外部參與者,其中至少有一個是誠實的。 我們可以通過要求提議者和挑戰者的存款來接近這個假設。 一個問題是其中一個可能只是拒絕繼續協議,所以我們需要超時。 另一方面,如果我們增加超時,惡意行為者可能會使區塊鏈與不相關的交易飽和,希望答案不會及時成為一個塊。 合同是否有可能檢測到這種情況并延長超時? 此外,誠實的提議者可能會被阻止離開網絡。 正因為如此(并且因為比惡意演員更誠實),我們可能允許任何人在存款后進入(雙方)。 同樣,如果我們允許這樣做,惡意行為者可以介入“誠實”的一方,只是假裝誠實。 這聽起來有點復雜,但我相信它最終會成功。
https://blog.ethereum.org/2016/02/17/smart-contracts-courts-not-smart-judges/
總結
以上是生活随笔為你收集整理的【译】From Smart Contracts to Courts with not so Smart Judges的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ethermint部署及框架解析
- 下一篇: Guide To Using The G