Estoy frente a un problema estúpido. Estoy tratando de leer bitcoin/blocks/index leveldb usando plyvel. Configuré una prueba de registro y sé que hay un bloque con el hash:
27ce8199dee22f96e4f392dec29ef207fcd8a3c9e43b7d58cb40a5ba01af674b
Estoy tratando de consultarlo usando plyvel.
Tenga en cuenta que ya leí los temas:
¿Cómo lee/escribe Bitcoin en LevelDB?
https://en.bitcoin.it/wiki/Protocol_documentation
Entonces, sé que tengo que cambiar el endianness para que se convierta en:
MYVAR = "4b67af01baa540cb587d3be4c9a3d8fc07f29ec2de92f3e4962fe2de9981ce27"
Por lo tanto, debería consultar algo como:
b + (byte) MYVAR
Sin embargo no entiendo cómo. Supongo que no entiendo algo en la codificación. Lo intenté :
db.get(b'b4b67af01baa540cb587d3be4c9a3d8fc07f29ec2de92f3e4962fe2de9981ce27')
db.get(b'b'+b'4b67af01baa540cb587d3be4c9a3d8fc07f29ec2de92f3e4962fe2de9981ce27')
..
Luego, abrí bitcoin/blocks/index leveldb usando un explorador de interfaz gráfica de usuario y noté que la clave para este bloque es:
\x62\x4b\x67\xaf\x01\xba\xa5\x40\xcb\x58\x7d\x3b\xe4\xc9\xa3\xd8\xfc\x07\xf2\x9e\xc2\xde\x92\xf3\xe4\x96\x2f\xe2\xde\x99\x81\xce\x27
que es \x62 correspondiente a la "b" + el hash con \x (caracter de escape? Sé que aquí está mi malentendido sobre la codificación hexadecimal)
y obviamente
db.get(b'\x62\x4b\x67\xaf\x01\xba\xa5\x40\xcb\x58\x7d\x3b\xe4\xc9\xa3\xd8\xfc\x07\xf2\x9e\xc2\xde\x92\xf3\xe4\x96\x2f\xe2\xde\x99\x81\xce\x27')
funciona perfectamente
También probé estos métodos:
https://stackoverflow.com/questions/5649407/hexadecimal-string-to-byte-array-in-python
Ninguno de ellos funciona y realmente no entiendo por qué:
bytes.fromhex(hash)
bytearray.fromhex(hash)
gracias de antemano
Esta respuesta es un poco obsoleta. Pero aquí está de todos modos.
Debe observar la endianidad de los bytes. La forma en que miramos la identificación del bloque (hash del encabezado del bloque) es bigendian, el bit más significativo primero, y la forma en que bitcoin-core administra todo detrás de escena es littleendian, el bit menos significativo primero.
Aquí hay una secuencia de comandos simple para acceder a todo el índice de bloques de leveldb.
import re
from plyvel import DB
# Note for POSIX users, typically we have to escape spaces,
# e.g. "Application\ Support". However this is not needed here so you
# can write "Application Support" instead.
BITCOIN_DATADIR: str ="/absolute/path/to/your/bitcoin/datadir/"
db = DB(BITCOIN_DATADIR + "blocks/index")
keys = list(db.iterator(include_value=False))
regtest = re.compile(br"^b")
block_id_keys = list(filter(regtest.search, keys))
Podemos acceder a la estructura de datos y ver esto:
>>> bytes.hex(block_id_keys[-1][::-1][:-1])
'0000000000429f3501d60512df277b97f539becd18a7541b433e5110b2feffff'
https://blockstream.info/block/0000000000429f3501d60512df277b97f539becd18a7541b433e5110b2feffff
Pasando por el [-1][::-1][:-1]
, el [-1]
es el último elemento de la lista, cambia [::-1]
el orden de los bytes de littleendian a bigendian, y [:-1]
suelta el b"b"
.
Para ver la clave sin procesar, podemos ver la estructura completa:
>>> block_id_keys[-1]
b"b\xff\xff\xfe\xb2\x10Q>C\x1bT\xa7\x18\xcd\xbe9\xf5\x97{'\xdf\x12\x05\xd6\x015\x9fB\x00\x00\x00\x00\x00"
Tenga en cuenta que la clave comienza con b"b"
.
Para obtener la clave leveldb de un blockid hexadecimal bigendiano, puede hacer lo siguiente:
>>> hex_data = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
>>> test_key = b"b" + bytes.fromhex(hex_data)[::-1]
>>> db.get(test_key)
b'\x8b\x99@\x00\x0b\x01\x00\x08\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\xa3\xed\xfdz{\x12\xb2z\xc7,>gv\x8fa\x7f\xc8\x1b\xc3\x88\x8aQ2:\x9f\xb8\xaaK\x1e^J)\xab_I\xff\xff\x00\x1d\x1d\xac+|'
Consulte también https://bitcoin.stackexchange.com/a/29418/124452
Las bases de datos leveldb se serializan para la optimización y no funcionan bien al intentar analizar manualmente los datos. Puede obtener más fácilmente detalles sobre un blockhash específico utilizando la API JSON-RPC integrada y utilizar la getblock
llamada.
Elerir
Elerir