# HG changeset patch # User Dennis Concepcion Martin # Date 1634462086 -7200 # Node ID 5b16e6df6a59c8cf1463523da31a93a828c3fc82 # Parent 8522a23c82f02e4b654b8ae62830296d5f8756c0 get txid hashing transaction data diff -r 8522a23c82f0 -r 5b16e6df6a59 src/block.py --- a/src/block.py Sat Oct 16 18:59:23 2021 +0200 +++ b/src/block.py Sun Oct 17 11:14:46 2021 +0200 @@ -1,5 +1,6 @@ import hashlib from src.helpers import read_bytes +from src.helpers import get_variable_int class Block: @@ -7,36 +8,45 @@ Block structure """ - block_hash = None - magic_number = None - size = None - - def __init__(self): - # Init BlockHeader class - self.header = self.Header() + block_hash = str() + magic_number = int() + size = int() + number_of_transactions = int() + transactions = [] class Header: - version = None - previous_block_hash = None - merkle_root = None - timestamp = None - difficult_target = None - nonce = None + version = int() + previous_block_hash = str() + merkle_root = str() + timestamp = int() # Epoch Unix time + difficult_target = int() # Bits + nonce = int() + + +class Transaction: + id = str() + version = int() + number_of_inputs = int() + inputs = [] + + class Inputs: + pass def read_block(file): """ Deserialize block + More info about block structure: https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch09.asciidoc :param file: , required :return: """ block = Block() - block.magic_number = int(read_bytes(file, 4), 16) - block.size = int(read_bytes(file, 4), 16) + block.magic_number = int.from_bytes(read_bytes(file, 4), 'big') + block.size = int.from_bytes(read_bytes(file, 4), 'big') # Compute block hash - header_bytes = file.read(80) + header_bytes = read_bytes(file, 80, 'forward') block_hash = hashlib.sha256(header_bytes).digest() block_hash = hashlib.sha256(block_hash).digest() @@ -44,5 +54,29 @@ header = block.Header() header.block_hash = block_hash[::-1].hex() header.version = int.from_bytes(header_bytes[:4], 'little') - header.previous_block_hash = header_bytes[4:32].hex() + header.previous_block_hash = header_bytes[4:36][::-1].hex() + header.merkle_root = header_bytes[36:68][::-1].hex() + header.timestamp = int.from_bytes(header_bytes[68:72], 'little') + header.difficult_target = int.from_bytes(header_bytes[72:76], 'little') + header.nonce = int.from_bytes(header_bytes[76:80], 'little') + + # Number of transactions (varInt) + block.number_of_transactions = get_variable_int(file) + # Compute transaction ID + # Get remaining bytes until the end of the block + transaction = Transaction() + bytes_read = file.tell() + whole_block_size = block.size + 8 # Plus magic number and block size + transaction_data_size = whole_block_size - bytes_read + transaction_data = file.read(transaction_data_size) + file.seek(bytes_read) # Set position to where 'transaction data' starts + transaction_id = hashlib.sha256(transaction_data).digest() + transaction_id = hashlib.sha256(transaction_id).digest() + transaction.id = transaction_id[::-1].hex() + + transaction.version = int.from_bytes(read_bytes(file, 4), 'little') + transaction.number_of_inputs = get_variable_int(file) + + + diff -r 8522a23c82f0 -r 5b16e6df6a59 src/helpers.py --- a/src/helpers.py Sat Oct 16 18:59:23 2021 +0200 +++ b/src/helpers.py Sun Oct 17 11:14:46 2021 +0200 @@ -13,6 +13,26 @@ if bytes_order == 'backward': b = b[::-1] - b = b.hex().upper() + return b + + +def get_variable_int(file): + """ + Get variable int from transaction data + More info: https://learnmeabitcoin.com/technical/varint + :param file: , required + :return: int + """ - return b + first_byte = read_bytes(file, 1) + + if first_byte == b'\xfd': + variable_int_bytes = read_bytes(file, 2) + elif first_byte == b'\xfe': + variable_int_bytes = read_bytes(file, 4) + elif first_byte == b'\xff': + variable_int_bytes = read_bytes(file, 8) + else: + variable_int_bytes = first_byte + + return int.from_bytes(variable_int_bytes, 'little')