Bitcoin-Core

python中的比特幣鏈狀態數據庫解析給出錯誤的值

  • May 5, 2018

我正在嘗試為 python 中的交易的特定輸出索引解碼chainstate db,以供學習。交易 ID:4d4a4c6ca4f3c91e69563199943336d3279fad71c9e8d9c1708ef9dc6ac16000 出索引 = 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)

我得到以下結果:高度 = 355833,coinbase = 0 數量 = 12353

當我在比特幣核心守護程序中執行 getrawtransaction 時,我得到的金額為 12200。

./bitcoin-cli getrawtransaction 4d4a4c6ca4f3c91e69563199943336d3279fad71c9e8d9c1708ef9dc6ac16000 true

對於索引 1822,我得到:

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

所以我無法弄清楚的程式碼肯定有問題。我認為問題出在

txout_decompress(x)

方法。但這很奇怪,因為我在比特幣核心中直接使用了方法

uint64_t 解壓量(uint64_t x)

src / 壓縮器.cpp

將其轉換為python後。請幫我解決這個問題。

經過調查,我發現*txout_decompress(x)*中的 x 不是導致答案不同的整數,因此在除法期間我將其類型轉換為 int 並且它起作用了。所以更正的程式碼:

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

引用自:https://bitcoin.stackexchange.com/questions/74759