Mercurial > public > bitcaviar-plus
view src/block.py @ 5:1a8d94b500d8
finish basic parser
author | Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com> |
---|---|
date | Thu, 21 Oct 2021 18:52:54 +0200 |
parents | e7a84094bf07 |
children |
line wrap: on
line source
from src.helpers import __get_hash from src.helpers import __get_variable_int from src.block_structure import * def read_block(f): """ Deserialize block More info about block structure: https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch09.asciidoc More info about bytes order: https://en.wikipedia.org/wiki/Endianness :param f: buffer, required :return: """ block = Block() _ = f.read(4) # Magic number _ = f.read(4)[::-1] # Block size header_bytes = f.read(80) block.block_hash = __get_hash(header_bytes) f.seek(8) block.header = __get_header(f) number_of_transactions = __get_variable_int(f) transactions = [] for transaction_number in range(number_of_transactions): transactions.append(__get_transaction(f)) block_dict = block.__dict__ block_dict['transactions'] = transactions return block_dict def __get_header(f): """ Get block header :param f: buffer, required :return: dict """ header = Header() header.version = int.from_bytes(f.read(4), 'little') header.previous_block_hash = f.read(32)[::-1].hex() header.merkle_root = f.read(32)[::-1].hex() header.timestamp = int.from_bytes(f.read(4), 'little') header.bits = int.from_bytes(f.read(4), 'little') header.nonce = int.from_bytes(f.read(4), 'little') return header.__dict__ def __get_transaction(f): """ Get transaction :param f: buffer, required :return: dict """ transaction_data_start = f.tell() transaction = Transaction() transaction.version = int.from_bytes(f.read(4)[::-1], 'big') number_of_inputs = __get_variable_int(f) inputs = [] for input_number in range(number_of_inputs): inputs.append(__get_input(f)) number_of_outputs = __get_variable_int(f) outputs = [] for output_number in range(number_of_outputs): outputs.append(__get_outputs(f)) transaction.lock_time = int.from_bytes(f.read(4)[::-1], 'little') transaction_dict = transaction.__dict__ transaction_dict['inputs'] = inputs transaction_dict['outputs'] = outputs transaction_data_end = f.tell() # Get transaction id transaction_data_size = transaction_data_end - transaction_data_start f.seek(transaction_data_start) transaction_data = f.read(transaction_data_size) transaction.id = __get_hash(transaction_data) return transaction_dict def __get_input(buffer): """ Get input from transaction data :param buffer: bytes, required :return: dict """ transaction_input = TransactionInput() transaction_input.id = buffer.read(32)[::-1].hex() if transaction_input.id == '0000000000000000000000000000000000000000000000000000000000000000': transaction_input.is_coinbase = True transaction_input.vout = int.from_bytes(buffer.read(4)[::-1], 'little') script_sig_size = __get_variable_int(buffer) transaction_input.script_sig = buffer.read(script_sig_size).hex() transaction_input.sequence = int.from_bytes(buffer.read(4)[::-1], 'little') return transaction_input.__dict__ def __get_outputs(buffer): """ Get output from transaction data :param buffer: bytes, required :return: dict """ transaction_output = TransactionOutput() transaction_output.value = float.fromhex(buffer.read(8)[::-1].hex()) transaction_output.value /= 100000000 # Satoshis to BTC script_pub_key_size = __get_variable_int(buffer) transaction_output.script_pub_key = buffer.read(script_pub_key_size).hex() return transaction_output.__dict__