¿Formato de archivos LevelDB en el directorio de nodos? Problemas para extraer contenido con la API de python leveldb

Estoy interesado en explorar los datos en ~/.ethereum/nodes, que creo que contiene intentos de conexión anteriores e información sobre los nodos. (¿Es eso correcto?) Pero estoy atascado tratando de extraer los datos de esa base de datos.

Aquí está mi intento hasta ahora:

import leveldb

db = leveldb.LevelDB("./nodes")
# I don't know the format so I will iterate a few keys
keys = list()
for k in db.RangeIter():
    if len(keys) > 10:
        break
    keys.append(k)

print(keys[0][0])

Lo que me da una matriz de bytes con la que no sé qué hacer:

>>> bytearray(b'n:\x00\x00\x07\xf2\x91\xff\xcd\xba%\x8f%\xf8b\xfe\x1b3\xda\x10\xfa,\xb7>\x93\x82_X\r5\xdfG\xae\x8b\xd6-\x9d6\rB\x84$\xb8+\x07\x18<\x8d\xed\xca\x93\xa4\x0bt\x84\xa7\x14\xaf\xc8B\x1a\xb3\xb7(K\x00:discover:lastping')

Lo siento si esto es más una pregunta de Python que de Ethereum, pero sospecho que conocer la estructura de los datos ayudaría y parece que no puedo encontrarla en ninguna parte.

ACTUALIZACIÓN: Debo aclarar con qué estoy trabajando:

keys[0]es una entrada en la base de nodesdatos y es una tupla:

( bytearray(b'n:\x00\x00\x07\xf2\x91\xff\xcd\xba%\x8f%\xf8b\xfe\x1b3\xda\x10\xfa,\xb7>\x93\x82_X\r5\xdfG\xae\x8b\xd6-\x9d6\rB\x84$\xb8+\x07\x18<\x8d\xed\xca\x93\xa4\x0bt\x84\xa7\x14\xaf\xc8B\x1a\xb3\xb7(K\x00:discover:lastping'), bytearray(b'\x90\xa7\xae\xef\n') )

Siendo el primer elemento la clave. La ejecución rlp.decodeen cualquiera de los elementos devuelve un error:

import rlp

rlp.decode(bytes(keys[0][0]))
>>> DecodingError: RLP string ends with 83 superfluous bytes

rlp.decode(bytes(keys[0][1]))
>>> DecodingError: RLP string ends with -12 superfluous bytes

Estoy muy confundido porque parece que está siendo codificado en RLP por geth, así que no entiendo por qué no se decodifica.

Respuestas (1)

El contenido de la base de datos está blobificado, por lo que tendrá que eliminarlo para obtener algo legible por humanos.

El diseño se puede encontrar en database.go:

// Schema layout for the node database
var (
    nodeDBVersionKey = []byte("version") // Version of the database to flush if changes
    nodeDBItemPrefix = []byte("n:")      // Identifier to prefix node entries with

    nodeDBDiscoverRoot      = ":discover"
    nodeDBDiscoverPing      = nodeDBDiscoverRoot + ":lastping"
    nodeDBDiscoverPong      = nodeDBDiscoverRoot + ":lastpong"
    nodeDBDiscoverFindFails = nodeDBDiscoverRoot + ":findfail"
)

Si revisa ese archivo, verá que se usa el paquete RLP (prefijo de longitud recursiva) para la codificación/descodificación, cuya versión de Python se puede encontrar aquí .

Gracias por señalar esto. Todavía tengo problemas para "desbloquear" el índice: rlp.decode(b'\x90\xa7\xae\xef\n')-->DecodingError: RLP string ends with -12 superfluous bytes.
Hmm, es posible que tengas que pasar como segundo argumento de (des) serialización a la función de decodificación para que sepa de qué tipo se trata. (Así es como parece hacerlo el código Go). Eche un vistazo a los "objetos Sedes" en la documentación de Python: github.com/ethereum/pyrlp/blob/develop/docs/tutorial.rst
Esta verificación en realidad viene antes de la verificación de sedes: github.com/ethereum/pyrlp/blob/develop/rlp/codec.py#L211