annotate 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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
1 from src.helpers import __get_hash
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
2 from src.helpers import __get_variable_int
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
3 from src.block_structure import *
0
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
4
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
5
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
6 def read_block(f):
0
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
7 """
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
8 Deserialize block
2
5b16e6df6a59 get txid hashing transaction data
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 0
diff changeset
9 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
10 More info about bytes order: https://en.wikipedia.org/wiki/Endianness
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
11 :param f: buffer, required
0
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
12 :return:
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
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
15 block = Block()
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
16 _ = f.read(4) # Magic number
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
17 _ = f.read(4)[::-1] # Block size
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
18 header_bytes = f.read(80)
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
19 block.block_hash = __get_hash(header_bytes)
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
20 f.seek(8)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
21 block.header = __get_header(f)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
22 number_of_transactions = __get_variable_int(f)
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
23
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
24 transactions = []
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
25 for transaction_number in range(number_of_transactions):
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
26 transactions.append(__get_transaction(f))
0
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
27
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
28 block_dict = block.__dict__
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
29 block_dict['transactions'] = transactions
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
30
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
31 return block_dict
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
32
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
33
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
34 def __get_header(f):
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
35 """
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
36 Get block header
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
37 :param f: buffer, required
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
38 :return: dict
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
39 """
0
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
40
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
41 header = Header()
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
42 header.version = int.from_bytes(f.read(4), 'little')
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
43 header.previous_block_hash = f.read(32)[::-1].hex()
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
44 header.merkle_root = f.read(32)[::-1].hex()
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
45 header.timestamp = int.from_bytes(f.read(4), 'little')
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
46 header.bits = int.from_bytes(f.read(4), 'little')
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
47 header.nonce = int.from_bytes(f.read(4), 'little')
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
48
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
49 return header.__dict__
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
50
2
5b16e6df6a59 get txid hashing transaction data
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 0
diff changeset
51
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
52 def __get_transaction(f):
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
53 """
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
54 Get transaction
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
55 :param f: buffer, required
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
56 :return: dict
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
57 """
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
58
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
59 transaction_data_start = f.tell()
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
60
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
61 transaction = Transaction()
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
62 transaction.version = int.from_bytes(f.read(4)[::-1], 'big')
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
63 number_of_inputs = __get_variable_int(f)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
64
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
65 inputs = []
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
66 for input_number in range(number_of_inputs):
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
67 inputs.append(__get_input(f))
0
2327b9eda10f first commit
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents:
diff changeset
68
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
69 number_of_outputs = __get_variable_int(f)
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
70
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
71 outputs = []
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
72 for output_number in range(number_of_outputs):
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
73 outputs.append(__get_outputs(f))
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
74
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
75 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
76
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
77 transaction_dict = transaction.__dict__
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
78 transaction_dict['inputs'] = inputs
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
79 transaction_dict['outputs'] = outputs
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
80
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
81 transaction_data_end = f.tell()
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
82
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
83 # Get transaction id
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
84 transaction_data_size = transaction_data_end - transaction_data_start
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
85 f.seek(transaction_data_start)
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
86 transaction_data = f.read(transaction_data_size)
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
87 transaction.id = __get_hash(transaction_data)
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
88
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
89 return transaction_dict
4
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
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
92 def __get_input(buffer):
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
93 """
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
94 Get input from transaction data
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
95 :param buffer: bytes, required
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
96 :return: dict
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
97 """
2
5b16e6df6a59 get txid hashing transaction data
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 0
diff changeset
98
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
99 transaction_input = TransactionInput()
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
100 transaction_input.id = buffer.read(32)[::-1].hex()
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
101
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
102 if transaction_input.id == '0000000000000000000000000000000000000000000000000000000000000000':
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
103 transaction_input.is_coinbase = True
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
104
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
105 transaction_input.vout = int.from_bytes(buffer.read(4)[::-1], 'little')
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
106 script_sig_size = __get_variable_int(buffer)
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
107 transaction_input.script_sig = buffer.read(script_sig_size).hex()
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
108 transaction_input.sequence = int.from_bytes(buffer.read(4)[::-1], 'little')
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
109
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
110 return transaction_input.__dict__
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
111
2
5b16e6df6a59 get txid hashing transaction data
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 0
diff changeset
112
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
113 def __get_outputs(buffer):
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
114 """
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
115 Get output from transaction data
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
116 :param buffer: bytes, required
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
117 :return: dict
4
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
118 """
e7a84094bf07 refactor code
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 3
diff changeset
119
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
120 transaction_output = TransactionOutput()
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
121 transaction_output.value = float.fromhex(buffer.read(8)[::-1].hex())
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
122 transaction_output.value /= 100000000 # Satoshis to BTC
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
123 script_pub_key_size = __get_variable_int(buffer)
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
124 transaction_output.script_pub_key = buffer.read(script_pub_key_size).hex()
2
5b16e6df6a59 get txid hashing transaction data
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 0
diff changeset
125
5
1a8d94b500d8 finish basic parser
Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
parents: 4
diff changeset
126 return transaction_output.__dict__