Bitcoin-Chainstate-Datenbank-Parsing in Python mit falschem Wert

Ich versuche, chainstate db für einen bestimmten Ausgangsindex für eine Transaktion in Python zu decodieren, nur um zu lernen. Transaktions-ID: 4d4a4c6ca4f3c91e69563199943336d3279fad71c9e8d9c1708ef9dc6ac16000 Ausgangsindex = 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)

Ich bekomme folgendes Ergebnis: Höhe = 355833, Münzbasis = 0 Betrag = 12353

Wenn ich getrawtransaction im Bitcoin Core Daemon mache, bekomme ich einen Betrag von 12200.

./bitcoin-cli getrawtransaction 4d4a4c6ca4f3c91e69563199943336d3279fad71c9e8d9c1708ef9dc6ac16000 true

Für den Index 1822 bekomme ich:

{
      "value": 0.00012200,
      "n": 1822,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 c40c4870c3874cafb3385dca3731d637ac51110d OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a914c40c4870c3874cafb3385dca3731d637ac51110d88ac",
        "reqSigs": 1,
        "type": "pubkeyhash",
        "addresses": [
          "1JscA3193KByPvFv4X6nNEV2SGjdXVcVq6"
        ]
      }
    },

Es muss also ein Problem mit dem Code geben, den ich nicht herausfinden kann. Ich denke das Problem ist drin

txout_decompress(x)

Methode. Aber das ist seltsam, weil ich die Methode direkt im Bitcoin-Kern verwendet habe

uint64_t Dekomprimierungsbetrag (uint64_t x)

In

src/compressor.cpp

nach der Konvertierung in Python. Bitte helfen Sie mir, dieses Problem zu lösen.

Antworten (1)

Nachdem ich nachgeforscht hatte, stellte ich fest, dass das x in txout_decompress(x) keine ganze Zahl war, was den Unterschied in der Antwort verursachte, also habe ich es während der Division in int umgewandelt und es funktionierte. Also der korrigierte Code:

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