comparison src/block.py @ 2:5b16e6df6a59

get txid hashing transaction data
author Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com>
date Sun, 17 Oct 2021 11:14:46 +0200
parents 2327b9eda10f
children 3d83609e12a1
comparison
equal deleted inserted replaced
1:8522a23c82f0 2:5b16e6df6a59
1 import hashlib 1 import hashlib
2 from src.helpers import read_bytes 2 from src.helpers import read_bytes
3 from src.helpers import get_variable_int
3 4
4 5
5 class Block: 6 class Block:
6 """ 7 """
7 Block structure 8 Block structure
8 """ 9 """
9 10
10 block_hash = None 11 block_hash = str()
11 magic_number = None 12 magic_number = int()
12 size = None 13 size = int()
13 14 number_of_transactions = int()
14 def __init__(self): 15 transactions = []
15 # Init BlockHeader class
16 self.header = self.Header()
17 16
18 class Header: 17 class Header:
19 version = None 18 version = int()
20 previous_block_hash = None 19 previous_block_hash = str()
21 merkle_root = None 20 merkle_root = str()
22 timestamp = None 21 timestamp = int() # Epoch Unix time
23 difficult_target = None 22 difficult_target = int() # Bits
24 nonce = None 23 nonce = int()
24
25
26 class Transaction:
27 id = str()
28 version = int()
29 number_of_inputs = int()
30 inputs = []
31
32 class Inputs:
33 pass
25 34
26 35
27 def read_block(file): 36 def read_block(file):
28 """ 37 """
29 Deserialize block 38 Deserialize block
39 More info about block structure: https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch09.asciidoc
30 :param file: <class '_io.BufferedReader'>, required 40 :param file: <class '_io.BufferedReader'>, required
31 :return: 41 :return:
32 """ 42 """
33 43
34 block = Block() 44 block = Block()
35 block.magic_number = int(read_bytes(file, 4), 16) 45 block.magic_number = int.from_bytes(read_bytes(file, 4), 'big')
36 block.size = int(read_bytes(file, 4), 16) 46 block.size = int.from_bytes(read_bytes(file, 4), 'big')
37 47
38 # Compute block hash 48 # Compute block hash
39 header_bytes = file.read(80) 49 header_bytes = read_bytes(file, 80, 'forward')
40 block_hash = hashlib.sha256(header_bytes).digest() 50 block_hash = hashlib.sha256(header_bytes).digest()
41 block_hash = hashlib.sha256(block_hash).digest() 51 block_hash = hashlib.sha256(block_hash).digest()
42 52
43 # Read block header 53 # Read block header
44 header = block.Header() 54 header = block.Header()
45 header.block_hash = block_hash[::-1].hex() 55 header.block_hash = block_hash[::-1].hex()
46 header.version = int.from_bytes(header_bytes[:4], 'little') 56 header.version = int.from_bytes(header_bytes[:4], 'little')
47 header.previous_block_hash = header_bytes[4:32].hex() 57 header.previous_block_hash = header_bytes[4:36][::-1].hex()
58 header.merkle_root = header_bytes[36:68][::-1].hex()
59 header.timestamp = int.from_bytes(header_bytes[68:72], 'little')
60 header.difficult_target = int.from_bytes(header_bytes[72:76], 'little')
61 header.nonce = int.from_bytes(header_bytes[76:80], 'little')
48 62
63 # Number of transactions (varInt)
64 block.number_of_transactions = get_variable_int(file)
65
66 # Compute transaction ID
67 # Get remaining bytes until the end of the block
68 transaction = Transaction()
69 bytes_read = file.tell()
70 whole_block_size = block.size + 8 # Plus magic number and block size
71 transaction_data_size = whole_block_size - bytes_read
72 transaction_data = file.read(transaction_data_size)
73 file.seek(bytes_read) # Set position to where 'transaction data' starts
74 transaction_id = hashlib.sha256(transaction_data).digest()
75 transaction_id = hashlib.sha256(transaction_id).digest()
76 transaction.id = transaction_id[::-1].hex()
77
78 transaction.version = int.from_bytes(read_bytes(file, 4), 'little')
79 transaction.number_of_inputs = get_variable_int(file)
80
81
82