Accounts

帳戶儲存中的 (key,value) 對和相應的修改後的 Merkle patricia 樹

  • February 25, 2018

黃皮書(第 4.1 節,storageRoot)中提到了它

storageRoot: Merkle Patricia 樹根節點的 256 位雜湊,用於編碼帳戶的儲存內容(256 位整數值之間的映射),作為來自 Keccak 256 位雜湊的映射編碼到樹中RLP 編碼的 256 位整數值的 256 位整數鍵。雜湊正式表示為 σ

$$ a $$_s。

從上面我可以理解的是,對於儲存映射的所有鍵值對**(k,v)(Kecak(k), RLP(v))**將用於儲存的修改後的 merkle trie,其中 Keccak(k)將作為值 RLP(v) 的鍵

我的問題是:

1.在賬戶的儲存內容中,這些(k,v)是什麼,即keys和values?

一個例子的解釋會非常有幫助。

2.為什麼使用Keccak(k)作為Merkle patricia樹的key,而不是直接使用k?

提前致謝。

在帳戶的儲存內容中,這些 (k,v) 是什麼,即鍵和值?

合約程式碼可以隨意使用。例如,在這個 Solidity 程式碼中,編譯器將索引 0var1和索引 1 var2

pragma solidity 0.4.20;

contract Test {

 uint public var1;
 address public var2;

 function test() public {
   var1 = 5;
   var2 = address(6);
 }
}

所以呼叫後的 (k,v) 對test()

(0,5)
(1,6)

您可以在本文中找到更多詳細資訊:https ://medium.com/@hayeah/diving-into-the-ethereum-vm-part-2-storage-layout-bc5349cb11b7

2.為什麼使用Keccak(k)作為Merkle patricia樹的key,而不是直接使用k?

乙太坊 wiki的Design Rationale文件中對此進行了解釋:

使用 sha3(k) 作為“安全樹”中的密鑰(在狀態和帳戶儲存嘗試中使用):這使得通過設置 64 層深度和重複呼叫的最大不利鏈的分歧節點來 DoS 嘗試變得更加困難對它們進行 SLOAD 和 SSTORE。請注意,這使得列舉樹變得更加困難;如果您想在客戶端中具有列舉功能,最簡單的方法是維護一個數據庫映射 sha3(k) -> k。


上一個答案

我不確定,但我的猜測是使用雜湊會導致更平衡的 trie。如果您想像一個 Patricia trie,其中條目按索引順序添加,則 trie 的一側通常會比另一側重。另一方面,當使用散列時,新元素被添加到隨機位置。插入/刪除/查找在平衡的 trie 中提供更一致的性能。

也有可能使用散列會產生更小的樹,因為可能會有更多的葉子和擴展節點,而在基於索引的樹中會有更多的分支節點。

為了展示使用連續索引作為鍵如何導致不平衡的 trie,讓我們假設在 trie 的某個級別有一個分支節點,其中只有第一個和第二個半字節指向其他一些節點:

<hash0> branch [<hash1>, <hash2>, NULL,..<13 NULLs>, value]

如果此分支位於 trie 的第 n 級(可以有 64 個級別,因為鍵是 32 個字節,root 位於第 0 級),那麼它將2 ^ ((64 - n) * 4 - 8)插入到 trie 中,直到第 3 個半字節變為非 NULL。

例如,如果此分支位於根目錄,您將需要2 ^ 248在第三個半字節變為非 NULL 之前插入鍵,這是不可能的(但是,這樣的分支首先不可能位於根級別,因為它需要2 ^ 247鍵達到這種狀態,但有可能達到更高級別的特里)。一般來說,左側半字節比右側半字節更有可能為非 NULL,這意味著左側的 trie 更重。

引用自:https://ethereum.stackexchange.com/questions/40069