This repository has been archived by the owner on Dec 22, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
/
parser.py
96 lines (81 loc) · 2.51 KB
/
parser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import struct
import socket
class BParser:
def __init__(self):
pass
def unpack(self, fmt, data):
size = struct.calcsize(fmt)
data, rem = data[:size], data[size:]
return struct.unpack(fmt, data), rem
def pack_variable_int(self, n):
if n < 0xfd:
return struct.pack("<B", n)
if n <= 0xffff:
return struct.pack("<BH", 0xfd, n)
if n <= 0xffffffff:
return struct.pack("<BL", 0xfe, n)
return struct.pack("<Q", 0xff, n)
def unpack_variable_int(self, data):
(m,), data = self.unpack("<B", data)
f = None
if m == 0xff:
f = "Q"
elif m == 0xfe:
f = "L"
elif m == 0xfd:
f = "H"
else:
return m, data
(n,), data = self.unpack("<"+f, data)
return n, data
def pack_variable_string(self, data):
return self.pack_variable_int(len(data)) + data
def unpack_variable_string(self, data):
size, data = self.unpack_variable_int(data)
return data[:size], data[size:]
def pack_address(self, services, addr, port):
addr = "::ffff:"+addr
addr = socket.inet_pton(socket.AF_INET6, addr)
return struct.pack("<Q", services) + addr + struct.pack("!H", port)
def unpack_address(self, data):
(services, addr), data = self.unpack("<Q16s", data)
(port,), data = self.unpack("!H", data)
return (services, addr, port), data
def get_checksum_size(self):
return struct.calcsize("<L")
def pack_checksum(self, checksum):
return struct.pack("<L", checksum)
def unpack_checksum(self, data):
(checksum,), data = self.unpack("<L", data)
return checksum, data
def unpack_block(self, data):
original = data
result, data = self.unpack("<L32B32BLLL", data)
version, pblock, merkle, timestamp, bits, nonce = result
size, data = self.unpack_variable_int(data)
transactions = []
for i in range(size):
tx, data = self.unpack_transaction(data)
transactions.append(tx)
block = (version, pblock, merkle, timestamp, bits, nonce, transactions)
return block, data
def unpack_transaction(self, data):
o = data
(version,), data = self.unpack("<L", data)
tx_in_count, data = self.unpack_variable_int(data)
tx_in = []
for i in range(tx_in_count):
tx_in.append(data[:41])
data = data[41:]
tx_out_count, data = self.unpack_variable_int(data)
tx_out = []
for i in range(tx_out_count):
tx_in.append(data[:8])
data = data[8:]
(lock_time,), data = self.unpack("<L", data)
tx = (version, tx_in, tx_out, lock_time)
return tx, data
def unpack_inv(self, data):
(hash_type,), data = self.unpack("<L", data)
hash_val = data[:32]
return (hash_type, hash_val[::-1]), data[32:]