Cómo se almacenan los bloqueos y los intentos

Novato aquí!

Todavía no estoy seguro de haber entendido cómo se almacenan físicamente algunas estructuras de Ethereum (asumiendo la implementación de Geth)

  • State Trie: solo una Merkle Patricia Tries fuera de la cadena almacenada usando LevelDB;

  • Storage Trie: una Merkle Patricia Trie por cuenta; almacenado fuera de la cadena junto con State Trie usando LevelDB;

  • Intentos de transacción: en realidad no se almacenan físicamente; una Merkle Patricia Trie se crea sobre la marcha cuando es necesario utilizando la lista de transacciones en bloque;

  • Recibos Trie: ni idea;

  • Bloques: los intentos de estado y almacenamiento se almacenan en archivos .ldb (LevelDB), pero ¿dónde puedo encontrar los archivos de bloque y en qué formato están almacenados?

Respuestas (1)

El formato de la base de datos geth de bajo nivel es:

var databaseVerisionKey = new Buffer("DatabaseVersion"); // databaseVerisionKey tracks the current database version.
var headHeaderKey = new Buffer("LastHeader"); // headHeaderKey tracks the latest know header's hash.
var headBlockKey = new Buffer("LastBlock"); // headBlockKey tracks the latest know full block's hash.
var headFastBlockKey = new Buffer("LastFast"); // headFastBlockKey tracks the latest known incomplete block's hash duirng fast sync.
var fastTrieProgressKey = new Buffer("TrieSync"); // fastTrieProgressKey tracks the number of trie entries imported during fast sync.

// Data item prefixes (use single byte to avoid mixing data types, avoid `i`, used for indexes).
var headerPrefix = new Buffer("h"); // headerPrefix + num (uint64 big endian) + hash -> header
var headerTDSuffix = new Buffer("t"); // headerPrefix + num (uint64 big endian) + hash + headerTDSuffix -> td
var headerHashSuffix = new Buffer("n"); // headerPrefix + num (uint64 big endian) + headerHashSuffix -> hash
var headerNumberPrefix = new Buffer("H"); // headerNumberPrefix + hash -> num (uint64 big endian)
var blockBodyPrefix = new Buffer("b"); // blockBodyPrefix + num (uint64 big endian) + hash -> block body
var blockReceiptsPrefix = new Buffer("r"); // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts
var txLookupPrefix = new Buffer("l"); // txLookupPrefix + hash -> transaction/receipt lookup metadata
var bloomBitsPrefix = new Buffer("B"); // bloomBitsPrefix + bit (uint16 big endian) + section (uint64 big endian) + hash -> bloom bits
var preimagePrefix = new Buffer("secure-key-");      // preimagePrefix + hash -> preimage
var configPrefix = new Buffer("ethereum-config-"); // config prefix for the db
var BloomBitsIndexPrefix = new Buffer("iB"); // BloomBitsIndexPrefix is the data table of a chain indexer to track its progress // Chain index prefixes (use `i` + single byte to avoid mixing data types).

Para obtener datos, debe construir recursivamente árboles a partir de estos datos. Al conocer el hash de la raíz del estado, puede encontrar la raíz del estado, y luego conoce los hashes de los hijos de la raíz del estado, por lo que conoce a los hijos para que pueda llegar a las hojas.

Dependiendo de la opción de geth --gcmode archive|fast|light(también puede especificar cuántos bloques desea recordar), geth almacena o no algunos intentos.

Los diferentes intentos son el árbol de estado mundial (enlaces a cuentas), los intentos de almacenamiento (datos de cuenta) y los intentos de recibo (para recibos de transacciones).

Para obtener el valor "valor de muestra" del árbol (por ejemplo, la dirección del contrato). Debe recorrer 32 longitudes hacia abajo en el árbol dependiendo de la longitud de 32 caracteres sha3 ("valor de muestra").

Para comprender mejor qué datos se almacenan en db y cómo se realizan los intentos, mire estas imágenes:

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

Interesante, pero aún no me queda claro si los intentos de transacción persisten o si se crean sobre la marcha cuando es necesario. ¿También dónde se almacenan los datos de los intentos de recibos? ¿Están almacenados en LevelDB? ¿Se almacenan dentro de los bloques? ¿Los bloques también se almacenan en LevelDB? Si no, ¿dónde puedo encontrar los archivos?
Los intentos se almacenan en db en formato de nodos trie. Cuando Geth necesita usar un trie, lo construye de forma recursiva y lo almacena en la memoria RAM hasta que apaga geth. Por ejemplo, al solicitar datos de geth usando web3 api. Las transacciones también se almacenan en formato de matriz en el cuerpo del bloque. Entonces, en el caso de la transacción, no necesita construir un árbol para obtener tx del bloque especificado. Todo lo que se muestra en la imagen está en LevelDB. Si el modo de archivo está habilitado. Entonces, la respuesta resumida es: creada sobre la marcha cuando es necesario y almacenada en caché en ram, sí, sí, sí (lo señala por hash), sí.
Bien, ¿y qué pasa cuando se actualiza State Trie... se anulan los valores de los nodos o se almacenan nuevos nodos con los nuevos valores?
Dos datos diferentes que dan los mismos hashes tienen una probabilidad tan pequeña que geth asume que esto nunca sucede. Entonces, diferentes estados del mundo pueden coexistir en el mismo formato en una base de datos, porque los nodos son referenciados por su hash. Los nodos comunes se almacenan, por supuesto, de forma única.
@EtherswornCanonist, LevelDB es una base de datos de pares clave->valor. Todo se almacena como hashsiendo el keyy la estructura de datos correspondiente siendo el value. Eso es todo. ¿Por qué necesitaría profundizar en la estructura de la base de datos, simplemente use las funciones que ethereum tiene para obtener los datos que necesita?