comparison 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
comparison
equal deleted inserted replaced
5:1a8d94b500d8 6:5f6d1a28051a
1 from puppy.helpers import __get_hash
2 from puppy.helpers import __get_variable_int
3 from puppy.block_structure import *
4
5
6 def read_block(f):
7 """
8 Deserialize block
9 More info about block structure: https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch09.asciidoc
10 More info about bytes order: https://en.wikipedia.org/wiki/Endianness
11 :param f: buffer, required
12 :return:
13 """
14
15 block = Block()
16 _ = f.read(4) # Magic number
17 _ = f.read(4)[::-1] # Block size
18 position_before_header = f.tell()
19 header_bytes = f.read(80)
20 block.block_hash = __get_hash(header_bytes)
21 f.seek(position_before_header)
22 block.header = __get_header(f)
23 number_of_transactions = __get_variable_int(f)
24
25 transactions = []
26 for transaction_number in range(number_of_transactions):
27 transactions.append(__get_transaction(f))
28
29 block_dict = block.__dict__
30 block_dict['transactions'] = transactions
31
32 return block_dict
33
34
35 def __get_header(f):
36 """
37 Get block header
38 :param f: buffer, required
39 :return: dict
40 """
41
42 header = Header()
43 header.version = int.from_bytes(f.read(4), 'little')
44 header.previous_block_hash = f.read(32)[::-1].hex()
45 header.merkle_root = f.read(32)[::-1].hex()
46 header.timestamp = int.from_bytes(f.read(4), 'little')
47 header.bits = int.from_bytes(f.read(4), 'little')
48 header.nonce = int.from_bytes(f.read(4), 'little')
49
50 return header.__dict__
51
52
53 def __get_transaction(f):
54 """
55 Get transaction
56 :param f: buffer, required
57 :return: dict
58 """
59
60 transaction_data_start = f.tell()
61
62 transaction = Transaction()
63 transaction.version = int.from_bytes(f.read(4)[::-1], 'big')
64 number_of_inputs = __get_variable_int(f)
65
66 inputs = []
67 for input_number in range(number_of_inputs):
68 inputs.append(__get_input(f))
69
70 number_of_outputs = __get_variable_int(f)
71
72 outputs = []
73 for output_number in range(number_of_outputs):
74 outputs.append(__get_outputs(f))
75
76 transaction.lock_time = int.from_bytes(f.read(4)[::-1], 'little')
77
78 transaction_dict = transaction.__dict__
79 transaction_dict['inputs'] = inputs
80 transaction_dict['outputs'] = outputs
81
82 transaction_data_end = f.tell()
83
84 # Get current transaction ID: https://learnmeabitcoin.com/technical/txid
85 transaction_data_size = transaction_data_end - transaction_data_start
86 f.seek(transaction_data_start)
87 transaction_data = f.read(transaction_data_size)
88 transaction.id = __get_hash(transaction_data)
89
90 return transaction_dict
91
92
93 def __get_input(buffer):
94 """
95 Get input from transaction data
96 :param buffer: bytes, required
97 :return: dict
98 """
99
100 transaction_input = TransactionInput()
101 transaction_input.id = buffer.read(32)[::-1].hex()
102
103 if transaction_input.id == '0000000000000000000000000000000000000000000000000000000000000000':
104 transaction_input.is_coinbase = True
105
106 transaction_input.vout = int.from_bytes(buffer.read(4)[::-1], 'little')
107 script_sig_size = __get_variable_int(buffer)
108 transaction_input.script_sig = buffer.read(script_sig_size).hex()
109 transaction_input.sequence = int.from_bytes(buffer.read(4)[::-1], 'little')
110
111 return transaction_input.__dict__
112
113
114 def __get_outputs(buffer):
115 """
116 Get output from transaction data
117 :param buffer: bytes, required
118 :return: dict
119 """
120
121 transaction_output = TransactionOutput()
122 transaction_output.value = float.fromhex(buffer.read(8)[::-1].hex())
123 transaction_output.value /= 100000000 # Satoshis to BTC
124 script_pub_key_size = __get_variable_int(buffer)
125 transaction_output.script_pub_key = buffer.read(script_pub_key_size).hex()
126
127 return transaction_output.__dict__