跨分片合約拖拽
Cross-shard contract yanking
特別感謝Piper Merriam幫忙一起想出這個點子。
跨分片合約拖拽(Cross-shard Contract Yanking)屬於跨分片鎖定【1】及類似技術的通用化方案,以實現跨分片活動解決火車和酒店問題。其實,「鎖定」分片A上的合約意思是把分片上的合約狀態凍結,將狀態保存到收據中,將合約導入分片B,在該合約與分片B上的其他對象間執行些操作,然後使用另個收據將合約發送回分片A,讓其繼續存在。
想要簡化並通用化這個機制,把「鎖定」改為「拖拽(yanking)」即可。在EVM中添加個YANK(單個堆棧參數:target_shard
)操作碼,YANK從狀態中刪除合約並簽發包含合約狀態及target_shard
的收據;隨後在target_shard
中對收據進行處理,在該分片中實例化相同合約。合約可以自由指定自己被拖拽的條件。
舉個例子,酒店預訂合約可以通過reserve()
函數實現,這個函數可以預訂酒店房間,實例化代表酒店房間的合約,且該合約包含move_to_shard(uint256 shard_id)
函數,允許任何人將合約拖到另個分片上。那麼,人們也可以通過預訂酒店房間,拖合約到車票預訂合約分片,然後在該分片上以原子方式預訂酒店和車票,從而解決車票酒店問題。必要時,酒店房間合約中的book()
函數可以自毀酒店房間合約並簽發收據,這個收據可用來保存預訂記錄在酒店預訂主合約中。用戶在拖拽後原子預訂前消失時,任何想要預訂酒店房間的人都可以使用這個(相同的)酒店房間合約來執行此操作,甚至是將酒店房間合約拖回到原始分片。
為保證拖拽效率,被拖者的內部狀態必須很小,以便可以編碼進收據中,且拖拽的gas成本要與被拖者的總大小成正比。一般從可用性層面來說,令對許多用戶有意義的合約為可拖拽(yankable)並不是個好主意,原因是拖拽後的合約在target_shard
中重新實例化之前,是不可用的。出於這兩個原因,最可能的工作流是使合約具有與上述酒店房間(合約)類似的行為,意思是合約將與個別交互相關的狀態分離出來,以便可以分別在分片間移動。
注意,跨分片消息和拖拽之間存在很好的並行,現有的CALLs和CREATEs:CALL = 同步分片內消息傳遞,CREATE = 同步分片內合約創建,CROSS_SHARD_CALL = 非同步跨分片消息傳遞,YANK = 非同步跨分片合同創建。YANK操作碼不一定必須刪除現有合約並創建收據才能在新分片上生成副本。非要這麼做時(刪除現有合約並創建收據)可能需要調用CROSS_SHARD_CREATE和self-destruct;這麼做雖體現出對稱性,卻也需要個支持在另個分片中創建一個與原始合約地址相同合約的功能。
Q&A
問:如何預防用戶相同的拖拽收據用兩次,比如在沒有任何新YANK調用的情況下在分片之間來回拖拽(狀態相同的)合約?
分片是否需要記住每個領取過(claimed)的收據,防止領取兩次的情形?(若需要,不就產生了須由分片存儲不斷增長且不可修剪的狀態嗎?)
或者還有別的機智法子?
答:有三種比較極端的選項:
1. 分片需要記住領取過的所有拖拽收據
2. 拖拽要求提供該分片中所有先前塊的Merkle證明,證明相同合約未在先前塊中被拖拽進(該分片)
3. 收據指定一個特定的區塊高度,在此期間可以領取,若合約未包含在該特定高度,則永遠消失。
但這三個選項都顯然有點荒謬,下面是正常點的:
1. 收據須在一年內領取。分片須記住收據一年。
2. 分片記住收據一周。若一周內收據未領取,那麼請求人必須每周提供一份Merkle證明,證明該收據不在上一周狀態中領取收據列表中。
【1】
Cross Shard Locking Scheme - (1)跨分片鎖定方案
基本思想是使用讀寫鎖定確保引用多個分片上數據的交易能以原子方式執行。
假設交易T所需的狀態/存儲集S,規定:
1. 一團數據的地址;
2. 是否需要讀或寫鎖定
3. 保存數據團分片的ID
準備階段
執行T之前,要求將一組存儲S的鎖定L添加至區塊鏈。存儲s∈S的鎖定l∈L類似一筆交易,但是需要由保存s的分片以及T的父分片共同finalize。
提交階段
執行T之前,需要:
(1)提供L已被添加到S中引用的所有分片狀態的Merkle證明
(2)存儲S的Merkle分支
T被執行並提交前,需要在T所在分片中提交(1)和(2),否則T所在分片中沒有人能夠檢查T是否已正確執行。
如何避免系統中出現死鎖?
1. 簡單的解決方案是鎖定時間超時,可以是某個塊高度,並防止區塊在一段時間內獲得鎖定。但是這麼做可能太慢。
2. 更好的解決方案是讓區塊鏈用T的首個預留塊高度給交易T加個時間戳。有了該時間戳,就可以使用受傷等待機制(wound-wait mechanism)【2】來預防死鎖。
【2】Cross Shard Locking - Resolving Deadlock
受傷-等待機制屬於主動預防死鎖的技術。交易Ti請求正由Tj持有的數據項時,僅在Ti時間戳大於Tj時間戳時,允許Ti等待,反之Tj被回滾(受傷)。
本方案中,交易請求鎖定資源(數據項)時,若該資源已被其他交易衝突鎖定,可能出現以下兩種情形(之一):
1. 時間戳(Ti)<時間戳(Tj)時,則Ti強制回滾Tj,即Ti使Tj受傷。稍後Tj隨機延遲重啟,但有相同時間戳。
2. 時間戳(Ti)>時間戳(Tj)時,則強制Ti等待至資源可用。
區塊鏈實現
假設將任何交易鎖定添加至區塊鏈之前,必須添加交易初始化程序指定交易可引用的所有存儲及鎖定。
交易T的時間戳是其初始化程序的塊高。
那麼,如何保證條件(1)和(2)是成立的?
例(1)
分片上的驗證人發現某些Ti的時間戳小於自己分片上交易Tj的時間戳且Tj阻止Ti訪問資源時,分片引用Tj已獲取鎖定,聯繫其他分片,證明Tj的其他鎖定必須回滾。有數據可用性證明時,Tj所在分片客戶端可訪問全部信息,因此客戶端(出於故障保護的目的)可將信息轉發給其他分片。
例(2)
我對例2有些疑慮。交易Ti必須等待另個有較早時間戳的交易Tj執行完畢,若Tj一直不釋放自己的鎖定,會怎樣?交易Tj能否「擁有」數據?這個問題或許能通過鎖定的時間限制緩解,鎖定可由分片甚至數據團本身指定。
鎖定方案的優點:交易以原子方式執行,必要時有可能以原子方式回滾。
不足:帶來些開銷。
推薦閱讀:
※ETH拿穩別動,有V神代碼拉盤!老狼5月5行情分析
※比特幣以太坊萊特幣7月2日分析
※三觀盡毀,李笑來自爆瘋狂割韭菜的內部錄音流出(速看,恐被刪)
※以太坊是不是完蛋了?
※以太坊第三課:私有鏈創建賬戶並且挖礦
TAG:以太坊 |