我究竟如何解碼 leveldb 中的塊文件資訊?
基於連結 <https://github.com/bitcoin/bitcoin/blob/fcbc8bfa6d10cac4f16699d6e6e68fb6eb98acd0/src/main.h#L392>和 區塊鏈 levelDB 中使用的鍵是什麼(即鍵:值對是什麼)? 我應該簡單地將結果作為變數讀取。所以我寫了一些如下所示的 Python 程式碼。但是我沒有得到我預期的結果。
下面是我用文件號解碼文件資訊的程式碼
0
。我通過我的解析blk00000.dat
發現第一個塊是創世塊,最後一個塊是177
帶有 blockhash的塊00000000480c9799dd2b35009ff1833f69690f76c26a9bea7e00cd0042f67db1
。
nBlocks``134
看起來塊是正確的,這是我在blk00000.dat
.nHeightFirst
看起來值是正確的0
,但我nHeightLast
不是177
。nSize
並且nUndoSize
看起來不正確,因為它與我在終端上找到的文件大小不匹配ls -l ~/.bitcoin/blocks/blk00000.dat
和
ls -l ~/.bitcoin/blocks/rev00000.dat
此外
nTimeFirst
,與創世塊的時間戳不匹配。並且nTimeLast
與 block 的時間戳不匹配177
,我發現它是blk00000.dat
. 做錯了什麼?import plyvel blockIndexDB = plyvel.DB('/home/chris/.bitcoin/blocks/index') result = blockIndexDB.get(b'f\x00\x00\x00\x00') # result value from leveldb # result = b'\x86\xa8%\xbe\xfe\xf4E\x88\xa5\xa7}\x00\x86\xa8r\x83\xc9\xfd\xd5)\x83\xec\xd3\xa1N' # hexString = b'86a825befef44588a5a77d0086a87283c9fdd52983ecd3a14e' nBlocks = int.from_bytes(result[0:1], byteorder='little') print('nBlocks', nBlocks) print(nBlocks == 134) s = int.from_bytes(result[1:2], byteorder='little') # print('s', s) nSize = int.from_bytes(result[2:6], byteorder='little') print('nSize', nSize) print(nSize == 134216389) # blk00000.dat file size s = int.from_bytes(result[6:7], byteorder='little') # print('s', s) nUndoSize = int.from_bytes(result[7:11], byteorder='little') print('nUndoSize', nUndoSize) print(nUndoSize == 19502205) # rev00000.dat file size nHeightFirst = int.from_bytes(result[11:12], byteorder='little') print('nHeightFirst', nHeightFirst) print(nHeightFirst == 0) nHeightLast = int.from_bytes(result[12:13], byteorder='little') print('nHeightLast', nHeightLast) print(nHeightLast == 177) s = int.from_bytes(result[15:16], byteorder='little') # print('s', s) nTimeFirst = int.from_bytes(result[16:20], byteorder='little') print('nTimeFirst', nTimeFirst) print(nTimeFirst == 1231006505) # block 0 timestamp s = int.from_bytes(result[20:21], byteorder='little') # print('s', s) nTimeLast = int.from_bytes(result[21:], byteorder='little') print('nTimeLast', nTimeLast) # block 177 is the last block in blk00000.dat file print(nTimeLast == 1231736557) # block 177 timestamp
您將每個值反序列化為整數,但這是不正確的。這些值被序列化為可變長度整數,其中高位表示整數的長度,這些整數被丟棄為實際整數值本身。因此,您需要修復程式碼以將字節反序列化為 varint,而不僅僅是具有固定長度的整數。
以下程式碼能夠正確反序列化條目。
#! /usr/bin/env python3 import binascii def get_max(long=False): if long: return 18446744073709551615 else: return 4294967295 def read_var_int(s, pos, long=False): n = 0 while True: chData = s[pos] pos += 1 if n > (get_max(long) >> 7): raise IOError("ReadVarInt(): size too large"); n = (n << 7) | (chData & 0x7F) if chData & 0x80: if n == get_max(long): raise IOError("ReadVarInt(): size too large"); n += 1 else: return n, pos entry = binascii.unhexlify(b'86a825befef44588a5a77d0086a87283c9fdd52983ecd3a14e') pos = 0 nBlocks, pos = read_var_int(entry, pos) print('nBlocks: {}'.format(nBlocks)) nSize, pos = read_var_int(entry, pos) print('nSize: {}'.format(nSize)) nUndoSize, pos = read_var_int(entry, pos) print('nUndoSize: {}'.format(nUndoSize)) nHeightFirst, pos = read_var_int(entry, pos) print('nHeightFirst: {}'.format(nHeightFirst)) nHeightLast, pos = read_var_int(entry, pos) print('nHeightLast: {}'.format(nHeightLast)) nTimeFirst, pos = read_var_int(entry, pos) print('nTimeFirst: {}'.format(nTimeFirst)) nTimeLast, pos = read_var_int(entry, pos) print('nTimeLast: {}'.format(nTimeLast))
結果是:
nBlocks: 119973 nSize: 134216389 nUndoSize: 19502205 nHeightFirst: 0 nHeightLast: 120050 nTimeFirst: 1231006505 nTimeLast: 1303712078
nBlocks
和是預期的nHeightLast
,因為早期的塊非常小,但塊文件相當大。我認為您對塊文件中 134 個塊的計算是錯誤的。對於 134 個塊,這些塊的大小必須超過 1 MB,這對於早期塊來說是不正確的。