1. 程式人生 > 其它 >ETH-以太坊的交易樹與收據樹

ETH-以太坊的交易樹與收據樹

交易樹和收據樹

每次釋出一個區塊時,區塊中的交易會形成一顆Merkle Tree,即交易樹,跟比特幣中的情況類似。

此外,以太坊還添加了一個收據樹,每個交易執行完之後形成一個收據,記錄交易相關資訊。也就是說,交易樹和收據樹上的節點是一一對應的。主要是考慮到以太坊智慧合約執行較為複雜,通過增加收據樹,便於快速查詢執行結果。

交易樹和收據樹都是M(Merkle)PT,而BTC中都採用普通的MT(Merkle Tree)。(可能就僅僅是為了三棵樹程式碼複用好所以這樣設計的)

MPT的好處是支援查詢操作,通過鍵值沿著樹進行查詢即可:

  • 對於狀態樹,查詢鍵值為賬戶地址;
  • 對於交易樹和收據樹,查詢鍵值為交易在釋出的區塊中的序號。

交易樹和收據樹只將當前區塊中的交易組織起來,而狀態樹將所有賬戶的狀態都包含進去,無論這些賬戶是否與當前區塊中交易有關係。多個區塊狀態樹共享節點,而交易樹和收據樹依照區塊獨立。

交易樹和收據樹的用途:

  1. 向輕節點提供Merkle Proof。
  2. 更加複雜的查詢操作(例如:查詢過去十天的交易;過去十天的眾籌事件等)

Bloom filter(布隆過濾器)

Bloom filter的作用

支援較為高效查詢某個元素是否在某個集合中

eg:查詢某個元素是否在某個集合中

最笨:元素遍歷,複雜度為O(n)——輕節點不能用

方法:給一個大的集合,計算出一個緊湊的“摘要”

如下圖,給定一個數據集,其中含義元素a、b、c,通過一個雜湊函式H()對其進行計算,將其對映到一個其初始全為0的128位的向量的某個位置,將該位置置為1。將所有元素處理完,就可以得到一個向量,則稱該向量為原集合的“摘要”。可見該“摘要”比原集合是要小很多的。

摘要的作用:假定想要查詢一個元素d是否在集合中,假設H(d)對映到向量中的位置處為0,說明d一定不在集合中;假設H(d)對映到向量中的位置處為1,有可能集合中確實有d,也有可能因為雜湊碰撞產生誤報。

如果集合中刪除元素該怎麼操作?

無法操作。也就是說,簡單的Bloom filter不支援刪除操作。如果想要支援刪除操作,需要將記錄數不能為0和1,需要修改為一個計數器(需要考慮計數器是否會溢位)。

Bloom filter特點:有可能出現誤報,但不會出現漏報。

Bloom filter變種:採用一組雜湊函式進行向量對映,有效避免雜湊碰撞

以太坊中Bloom filter的作用

每個交易完成後會產生一個收據,收據包含一個Bloom filter記錄交易型別、地址等資訊。在區塊block header中也包含一個Bloom filter,其為該區塊中所有交易的Bloom filter的一個並集。

所以,查詢時候先查詢塊頭中的Bloom filter,如果塊頭中包含。再檢視區塊中包含的交易的Bloom filter,如果存在,再檢視交易進行確認;如果不存在,則說明發生了“碰撞”。

好處:通過Bloom filter這樣一個結構,快速大量過濾掉大量無關區塊,從而提高了查詢效率。

交易驅動的狀態機

以太坊的執行過程,可以視為交易驅動的狀態機,通過執行當前區塊中包含的交易,驅動系統從當前狀態轉移到下一狀態。當然,BTC我們也可以視為交易驅動的狀態機,其狀態為UTXO。

狀態轉移都是確定性的:對於給定的當前狀態和給定一組交易,可以確定性的轉移到下一狀態(保證系統一致性)。

問題1:A轉賬到B,有沒有可能收款賬戶不包含再狀態樹中?

可能。因為以太坊中賬戶可以節點自己產生,不需要通知其他人,只有在產生交易時才會被其他節點知道,這個時候要在狀態樹中新插入一個節點。

問題2:可否將每個區塊中狀態樹更改為只包含和區塊中交易相關的賬戶狀態?(大幅削減狀態樹大小,且和交易樹、收據樹保持一致)

不能。首先,這樣設計要查詢賬戶狀態很不方便,因為不存在某個區塊包含所有狀態。其次,如果要向一個新建立賬戶轉賬,因為需要知道收款賬戶的狀態,才能給其新增金額,但由於其是新建立的賬戶,所有需要一直找到創世紀塊才能知道該賬戶為新建賬戶,系統中並未儲存,而區塊鏈是不斷延長的。

程式碼中具體的資料結構

交易樹和收據樹的建立過程

下圖的函式中建立了交易樹和收據樹並且創造了他們的根雜湊值