Mercurial > public > bitcaviar-plus
diff src/puppy/block.py @ 6:5f6d1a28051a
add python package config files
author | Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com> |
---|---|
date | Sun, 24 Oct 2021 15:18:54 +0200 |
parents | src/block.py@1a8d94b500d8 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/puppy/block.py Sun Oct 24 15:18:54 2021 +0200 @@ -0,0 +1,127 @@ +from puppy.helpers import __get_hash +from puppy.helpers import __get_variable_int +from puppy.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 + position_before_header = f.tell() + header_bytes = f.read(80) + block.block_hash = __get_hash(header_bytes) + f.seek(position_before_header) + 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 current transaction ID: https://learnmeabitcoin.com/technical/txid + 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__