annotate src/block.py @ 4:e7a84094bf07

refactor code
author Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
date Wed, 20 Oct 2021 19:36:39 +0200
parents 3d83609e12a1
children 1a8d94b500d8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
1 import hashlib
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
2 from src.block_structure import *
0
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
3
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
4
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
5 def read_block(f):
0
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
6 """
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
7 Deserialize block
2
5b16e6df6a59 get txid hashing transaction data
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 0
diff changeset
8 More info about block structure: https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch09.asciidoc
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
9 More info about bytes order: https://en.wikipedia.org/wiki/Endianness
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
10 :param f: buffer, required
0
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
11 :return:
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
12 """
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
13
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
14 block = Block()
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
15 _ = f.read(4) # Magic number
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
16 _ = f.read(4)[::-1] # Block size
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
17 header_bytes = f.read(80)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
18 block.h = __get_hash(header_bytes)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
19 f.seek(8)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
20 block.header = __get_header(f)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
21 number_of_transactions = __get_variable_int(f)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
22 for transaction_number in range(number_of_transactions):
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
23 block.transactions.append(__get_transaction(f))
0
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
24
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
25 return block.__dict__
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
26
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
27
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
28 def __get_header(f):
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
29 """
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
30 Get block header
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
31 :param f: buffer, required
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
32 :return: dict
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
33 """
0
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
34
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
35 header = Header()
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
36 header.version = int.from_bytes(f.read(4), 'little')
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
37 header.previous_block_hash = f.read(32)[::-1].hex()
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
38 header.merkle_root = f.read(32)[::-1].hex()
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
39 header.timestamp = int.from_bytes(f.read(4), 'little')
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
40 header.bits = int.from_bytes(f.read(4), 'little')
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
41 header.nonce = int.from_bytes(f.read(4), 'little')
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
42
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
43 return header.__dict__
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
44
2
5b16e6df6a59 get txid hashing transaction data
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 0
diff changeset
45
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
46 def __get_transaction(f):
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
47 """
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
48 Get transaction
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
49 :param f: buffer, required
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
50 :return: dict
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
51 """
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
52
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
53 transaction = Transaction()
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
54 transaction.version = int.from_bytes(f.read(4)[::-1], 'big')
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
55 number_of_inputs = __get_variable_int(f)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
56
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
57 for input_number in range(number_of_inputs):
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
58 transaction_input = TransactionInput()
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
59 transaction_input.id = f.read(32)[::-1].hex()
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
60
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
61 if transaction_input.id == '0000000000000000000000000000000000000000000000000000000000000000':
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
62 transaction_input.is_coinbase = True
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
63
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
64 transaction_input.vout = int.from_bytes(f.read(4)[::-1], 'little')
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
65 script_sig_size = __get_variable_int(f)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
66 transaction_input.script_sig = f.read(script_sig_size).hex()
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
67 transaction_input.sequence = int.from_bytes(f.read(4)[::-1], 'little')
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
68 transaction.inputs.append(transaction_input.__dict__)
0
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
69
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
70 number_of_outputs = __get_variable_int(f)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
71
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
72 for output_number in range(number_of_outputs):
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
73 transaction_output = TransactionOutput()
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
74 transaction_output.value = float.fromhex(f.read(8)[::-1].hex())
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
75 transaction_output.value /= 100000000 # Satoshis to BTC
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
76 script_pub_key_size = __get_variable_int(f)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
77 transaction_output.script_pub_key = f.read(script_pub_key_size)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
78 transaction.outputs.append(transaction_output.__dict__)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
79
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
80 transaction.lock_time = int.from_bytes(f.read(4)[::-1], 'little')
3
3d83609e12a1 get value in output
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 2
diff changeset
81
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
82 print(transaction.outputs)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
83 print(transaction.inputs)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
84 print(transaction.__dict__)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
85
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
86 return transaction.__dict__
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
87
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
88
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
89 def __get_hash(buffer, bytes_order='backward'):
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
90 """
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
91 Compute hash from bytes
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
92 More info about bytes order: https://en.wikipedia.org/wiki/Endianness
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
93 :param buffer: bytes, required
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
94 :param bytes_order: string, 'backward' or 'forward', optional
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
95 :return: string
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
96 """
2
5b16e6df6a59 get txid hashing transaction data
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 0
diff changeset
97
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
98 h = hashlib.sha256(buffer).digest()
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
99 h = hashlib.sha256(h).digest()
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
100
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
101 if bytes_order == 'backward':
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
102 h = h[::-1]
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
103
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
104 return h.hex()
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
105
2
5b16e6df6a59 get txid hashing transaction data
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 0
diff changeset
106
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
107 def __get_variable_int(f):
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
108 """
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
109 Get variable int from transaction data
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
110 More info: https://learnmeabitcoin.com/technical/varint
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
111 :param f: buffer, required
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
112 :return: int
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
113 """
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
114
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
115 first_byte = f.read(1)
2
5b16e6df6a59 get txid hashing transaction data
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 0
diff changeset
116
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
117 if first_byte == b'\xfd':
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
118 variable_int_bytes = f.read(2)[::-1]
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
119 elif first_byte == b'\xfe':
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
120 variable_int_bytes = f.read(4)[::-1]
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
121 elif first_byte == b'\xff':
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
122 variable_int_bytes = f.read(8)[::-1]
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
123 else:
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
124 variable_int_bytes = first_byte
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
125
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
126 return int.from_bytes(variable_int_bytes, 'little')