(clave, valor) par en el almacenamiento de la cuenta y el árbol patricia de Merkle modificado correspondiente

En el documento amarillo (sección 4.1, storageRoot) se menciona

storageRoot: un hash de 256 bits del nodo raíz de un árbol Merkle Patricia que codifica el contenido de almacenamiento de la cuenta (un mapeo entre valores enteros de 256 bits), codificado en el trie como un mapeo del hash Keccak de 256 bits de las claves enteras de 256 bits a los valores enteros de 256 bits codificados en RLP. El hash se denota formalmente como σ[a]_s.

Lo que puedo entender de lo anterior es que para todos los pares de valores clave de mapeo de almacenamiento (k, v) , (Kecak (k), RLP (v)) se usará en el merkle trie modificado del almacenamiento donde Keccak (k) actuará como clave para el valor RLP(v)

Mis preguntas son:

1.En el contenido de almacenamiento de la cuenta, ¿cuáles son estos (k, v), es decir, claves y valores?

Una explicación con un ejemplo sería muy útil.

2. ¿Por qué se utiliza Keccak(k) como clave del árbol patricia de Merkle en lugar de utilizar directamente la k?

Gracias por adelantado.

Respuestas (1)

En el contenido de almacenamiento de la cuenta, ¿cuáles son estos (k, v), es decir, claves y valores?

El código del contrato es libre de utilizarlos como desee. Por ejemplo, en este código de Solidity, el compilador tomará el índice 0 var1y el índice 1 para var2:

pragma solidity 0.4.20;

contract Test {

  uint public var1;
  address public var2;

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

Entonces los pares (k,v) después de llamar test():

(0,5)
(1,6)

Puede encontrar más detalles en este artículo: https://medium.com/@hayeah/diving-into-the-ethereum-vm-part-2-storage-layout-bc5349cb11b7

2. ¿Por qué se utiliza Keccak(k) como clave del árbol patricia de Merkle en lugar de utilizar directamente la k?

Se explica en el documento Design Rationale en el wiki de Ethereum:

Usar sha3(k) como clave en el "árbol seguro" (usado en los intentos de estado y almacenamiento de cuenta): esto hace que sea mucho más difícil DoS el intento al establecer cadenas desfavorables máximas de nodos divergentes de 64 niveles de profundidad y llamando repetidamente SLOAD y SSTORE en ellos. Tenga en cuenta que esto hace que sea más difícil enumerar el árbol; si desea tener la capacidad de enumeración en su cliente, el enfoque más simple es mantener un mapeo de base de datos sha3(k) -> k.


Respuesta anterior

No estoy seguro, pero supongo que el uso de hash da como resultado un intento más equilibrado. Si imagina un Trie de Patricia donde las entradas se agregan secuencialmente mediante el índice, un lado del Trie a menudo será más pesado que el otro. Cuando se usan hashes, por otro lado, los nuevos elementos se agregan en una posición aleatoria. Las inserciones/eliminaciones/búsquedas brindan un rendimiento más consistente en una prueba equilibrada.

También es posible que el uso de hashes produzca un trie de menor tamaño porque presumiblemente habrá más nodos de hoja y de extensión, mientras que en el trie basado en índices habrá más nodos de rama.

Para demostrar cómo el uso de índices contiguos como claves da como resultado un trie desequilibrado, imaginemos una situación en la que en algún nivel del trie hay un nodo de rama donde solo el primer y el segundo nibble apuntan a otros nodos:

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

Si esta rama está en el nivel n del trie (puede haber 64 niveles porque las claves son 32 bytes, la raíz está en el nivel 0), entonces tomará 2 ^ ((64 - n) * 4 - 8)inserciones en el trie hasta que el tercer nibble se vuelva no NULL.

Por ejemplo, si esta rama está en la raíz, deberá insertar 2 ^ 248claves antes de que el tercer nibble se vuelva no NULL, lo cual es simplemente imposible (sin embargo, es imposible que dicha rama esté en el nivel raíz en primer lugar, porque tomará 2 ^ 247claves para llegar a este estado, pero es posible para niveles más altos del trie). En general, es mucho más probable que los nibbles del lado izquierdo no sean NULOS que los del lado derecho, lo que significa que el trie es más pesado en el lado izquierdo.

Gracias por responder. Para la primera parte, ¿hay alguna fuente donde pueda leer con más detalle? Para la 2da parte, seguro que los nodos de la rama serán de mayor tamaño, pero lo que obtengo es que si usamos índices contiguos para almacenar el valor, obtendremos un trie más equilibrado en caso de usar directamente los valores k como claves para el árbol Merkle.
@sourav Actualicé la respuesta con un enlace sobre el diseño de almacenamiento en Solidity. Para la segunda parte, agregué mis pensamientos en la sección Actualizar a continuación. Sin embargo, no estoy seguro de que mi lógica sea correcta, puede señalar si encuentra fallas en ella.
@sourav encontró la respuesta por qué se usan claves hash github.com/ethereum/wiki/wiki/Design-Rationale . Es para protección DoS. Actualicé mi respuesta.