El análisis de la base de datos de bitcoin chainstate en python da un valor incorrecto

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.

Respuestas (1)

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