Tuesday, November 5, 2024

What are the keys used within the blockchain levelDB (ie what are the important thing:worth pairs)?

import binascii

BLOCK_HAVE_DATA          =    8 #!< full block out there in blk*.dat
BLOCK_HAVE_UNDO          =   16 #!< undo information out there in rev*.dat

def encode_varint(quantity):

    # * Variable-length integers: bytes are a MSB base-128 encoding of the quantity.
    # * The excessive bit in every byte signifies whether or not one other digit follows. To make
    # * positive the encoding is one-to-one, one is subtracted from all however the final digit.
    # * Thus, the byte sequence a[] with size len, the place all however the final byte
    # * has bit 128 set, encodes the quantity:
    # *
    # *  (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1))
    # *
    # * Properties:
    # * * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes)
    # * * Each integer has precisely one encoding
    # * * Encoding doesn't rely on measurement of unique integer sort
    # * * No redundancy: each (infinite) byte sequence corresponds to an inventory
    # *   of encoded integers.
    # *
    # * 0:         [0x00]  256:        [0x81 0x00]
    # * 1:         [0x01]  16383:      [0xFE 0x7F]
    # * 127:       [0x7F]  16384:      [0xFF 0x00]
    # * 128:  [0x80 0x00]  16511: [0x80 0xFF 0x7F]
    # * 255:  [0x80 0x7F]  65535: [0x82 0xFD 0x7F]
    # * 2^32:           [0x8E 0xFE 0xFE 0xFF 0x00]

    """Encodes a non-negative integer utilizing the MSB base-128 scheme."""
    if quantity < 0:
        increase ValueError("Solely non-negative integers might be encoded.")

    consequence = []
    whereas True:
        byte = quantity & 0x7F  # Extract decrease 7 bits
        quantity >>= 7  # Shift proper by 7
        if quantity:
            byte |= 0x80  # Set excessive bit for continuation
        consequence.append(byte)
        if quantity == 0:
            break
    return bytes(consequence)

def decode_varint(stream):
    """Decodes a variable-length integer from the MSB base-128 format."""
    n = 0
    whereas True:
        chData = ord(stream.get(1))
        n = (n << 7) | (chData & 0x7F)

        if chData & 0x80:
            n += 1
        else:
            return n
        
def read_int(stream, bits):
    information = stream.get(bits//8)
    information.reverse()
    return binascii.b2a_hex(information) if bits > 64 else int(binascii.b2a_hex(information), 16)


class Stream:
    '''Class to deal with byte stream'''
    def __init__(self, hexdata):
        self.information = bytearray(bytes.fromhex(hexdata))
        self.information.reverse()

    def get(self, n):
        consequence = self.information[:n]
        self.information = self.information[n:]
        return consequence
class BlockHeader:
    def __init__(self, stream):
        self.nVersion = read_int(stream, 32)
        self.hashPrev = read_int(stream, 256)
        self.hashMerkleRoot = read_int(stream, 256)
        self.nTime = read_int(stream, 32)
        self.nBits = read_int(stream, 32)
        self.nNonce = read_int(stream, 32)

class VarintCBlockIndex:
    def __init__(self, stream):
        self.nVer = decode_varint(stream)
        self.nHeight = decode_varint(stream)
        self.nStatus = decode_varint(stream)
        self.nTx = decode_varint(stream)
        self.nFile = decode_varint(stream) if self.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO) else -1
        self.nDataPos = decode_varint(stream) if self.nStatus & BLOCK_HAVE_DATA else -1
        self.nUndoPos = decode_varint(stream) if self.nStatus & BLOCK_HAVE_UNDO else -1


if __name__ == '__main__':

    data_hex = '572fe3011b5bede64c91a5338fb300e3fdb6f30a4c67233b997f99fdd518b968b9a3fd65857bfe78b260071900000000001937917bd2caba204bb1aa530ec1de9d0f6736e5d85d96da9c8bba0000000129ffd98136b19a8e00021d00f0833ced8e'

    # Utilization
    stream = Stream(data_hex)
    varint_cblockindex = VarintCBlockIndex(stream)
    block_header = BlockHeader(stream)

    # print all information from courses:
    print('varint_cblockindex:')
    print('tnVer=", varint_cblockindex.nVer)
    print("tnHeight=", varint_cblockindex.nHeight)
    print("tnStatus=", varint_cblockindex.nStatus)
    print("tnTx = ', varint_cblockindex.nTx)
    print('tnFile=", varint_cblockindex.nFile)
    print("tnDataPos=", varint_cblockindex.nDataPos)
    print("tnUndoPos=", varint_cblockindex.nUndoPos)

    print("block_header:')
    print('tnVersion = ', block_header.nVersion)
    print('thashPrev = ', block_header.hashPrev)
    print('thashMerkleRoot=", block_header.hashMerkleRoot)
    print("tnTime=", block_header.nTime)
    print("tnBits=", block_header.nBits)
    print("tnNonce=", block_header.nNonce)

I hope it will assist…

Key Construction (b + 32-byte block hash):

The important thing for every block index document begins with the letter “b’ to tell apart it from different sorts of entries within the database (e.g., transaction index entries may begin with ‘t’).

Following the ‘b’ is the 32-byte (256-bit) hash of the block. This hash serves as a novel identifier for the block.

The block hash is usually represented in little-endian byte order within the database.

Worth Construction (Block Index Document):

Every block index document related to a selected block hash accommodates a mixture of knowledge:

Block Header:

80 bytes in complete
Accommodates the next fields:
Model (4 bytes)
Earlier Block Hash (32 bytes)
Merkle Root (32 bytes)
Timestamp (4 bytes)
Bits (problem goal, 4 bytes)
Nonce (4 bytes)

Peak:

A variable-length integer (varint) representing the block’s peak within the blockchain.
Signifies what number of blocks precede this block within the chain.

Variety of Transactions:

A varint indicating the overall variety of transactions included within the block.

Validation Standing:

A varint representing flags that point out:

File Location and Place:

If the block’s information is obtainable:

  • A varint indicating the file quantity (e.g., blkXXXXX.dat) the place the block information is saved.

  • A varint indicating the byte offset inside the file the place the block information begins.

If the block’s undo information is obtainable:

  • A varint indicating the file quantity (e.g., revXXXXX.dat) the place the undo information is saved.

  • A varint indicating the byte offset inside the file the place the undo information begins.

Vital Notes:

Varints: Bitcoin makes use of varints for area effectivity. Smaller numbers are encoded with fewer bytes than bigger ones. This makes the scale of the block index document variable relying on the block peak, transaction depend, and so forth.

Information Availability: Not all block information and undo information is perhaps out there within the LevelDB index. The validation standing flags point out whether or not the info is current and the place to seek out it within the precise block information on disk.

Endianness: The block hash and different fields inside the block header are saved in little-endian byte order in LevelDB. This implies the least vital byte comes first.

Instance (Simplified):

For example a block index document seems like this:

Key: b<block_hash>
Worth: <block_header_bytes><varint_height><varint_tx_count><varint_status><varint_file_num><varint_data_pos><varint_undo_file_num><varint_undo_pos>

This document tells you:

The block hash (block_hash)
The block header information (block_header_bytes)
The block peak (varint_height)
The variety of transactions (varint_tx_count)
The block’s validation standing (varint_status)
The place to seek out the block information and undo information on disk (if out there)

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles