Estoy tratando de decodificar chainstate db para un índice de salida específico para una transacción en python solo para aprender. ID de transacción: 4d4a4c6ca4f3c91e69563199943336d3279fad71c9e8d9c1708ef9dc6ac16000 índice de salida = 1822
chainstate_db = plyvel.DB(os.path.join(os.getenv('HOME'),".bitcoin/chainstate"), compression=None)
def getObfuscationKey():
value = chainstate_db.get(b'\x0e\x00' + b'obfuscate_key')
print('obfuscation key = %s' % value)
obfuscation_key = value[1:]
return obfuscation_key
def applyObfuscationKey(data: bytes):
obfuscation_key = getObfuscationKey()
new_val = bytes(data[index] ^ obfuscation_key[index % len(obfuscation_key)] for index in range(len(data)))
return new_val
def b128_varint_decode(value: bytes, pos = 0):
n = 0
while True:
data = value[pos]
pos += 1
n = (n << 7) | (data & 0x7f) # 1111111
if data & 0x80 == 0:
return (n, pos)
n += 1
def txout_decompress(x):
# x = 0 OR x = 1+10*(9*n + d - 1) + e OR x = 1+10*(n - 1) + 9
if x == 0:
return 0
x -=1
# x = 10*(9*n + d - 1) + e
e = x % 10
x /= 10
n = 0
if e < 9:
# x = 9*n + d - 1
d = (x % 9) + 1
x /= 9
# x = n
n = x*10 + d
else:
n = x+1
while e:
n *= 10
e -= 1
return n
...
def getChainstateData(txn_hash_big_endian: bytes, out_index: int):
key = b'C' + txn_hash_big_endian + b128_varint_encode(out_index)
value = chainstate_db.get(key)
value = applyObfuscationKey(value)
code, pos = b128_varint_decode(value)
height = code >> 1
coinbase = code & 0x01
print('height = %d, coinbase = %r' % (height, coinbase))
decoded_varint_amount, pos = b128_varint_decode(value, pos)
amount = txout_decompress(decoded_varint_amount)
print('amount = %d' % amount)
if __name__ == '__main__':
getChainstateData(binascii.unhexlify('0060c16adcf98e70c1d9e8c971ad9f27d3363394993156691ec9f3a46c4c4a4d'), 1822)
Obtengo el siguiente resultado: altura = 355833, base de monedas = 0 cantidad = 12353
Cuando hago getrawtransaction en el demonio central de bitcoin, obtengo una cantidad de 12200.
./bitcoin-cli getrawtransaction 4d4a4c6ca4f3c91e69563199943336d3279fad71c9e8d9c1708ef9dc6ac16000 true
Para nuestro índice 1822 obtengo:
{
"value": 0.00012200,
"n": 1822,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 c40c4870c3874cafb3385dca3731d637ac51110d OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a914c40c4870c3874cafb3385dca3731d637ac51110d88ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"1JscA3193KByPvFv4X6nNEV2SGjdXVcVq6"
]
}
},
Entonces debe haber un problema con el código que no puedo resolver. creo que el problema esta en
txout_descomprimir(x)
método. Pero esto es extraño porque he usado directamente el método en el núcleo de bitcoin
uint64_t DescomprimirCantidad(uint64_t x)
en
src/compresor.cpp
después de convertir esto a python. Por favor ayudame a resolver este problema.
Después de investigar, encontré que la x en txout_decompress(x) no era un número entero que causaba la diferencia en la respuesta, así que durante la división lo encasillé a int y funcionó. Así que el código corregido:
def amount_decompress(x: int):
# x = 0 OR x = 1+10*(9*n + d - 1) + e OR x = 1+10*(n - 1) + 9
if x == 0:
return 0
x -=1
# x = 10*(9*n + d - 1) + e
e = x % 10
x = int(x / 10)
n = 0
if e < 9:
# x = 9*n + d - 1
d = (x % 9) + 1
x = int(x / 9)
# x = n
n = x*10 + d
else:
n = x+1
while e:
n *= 10
e -= 1
return n