remove dangling whitespace
[stratum-mining.git] / lib / util.py
1 '''Various helper methods. It probably needs some cleanup.'''
2
3 import struct
4 import StringIO
5 import binascii
6 from hashlib import sha256
7
8 def deser_string(f):
9     nit = struct.unpack("<B", f.read(1))[0]
10     if nit == 253:
11         nit = struct.unpack("<H", f.read(2))[0]
12     elif nit == 254:
13         nit = struct.unpack("<I", f.read(4))[0]
14     elif nit == 255:
15         nit = struct.unpack("<Q", f.read(8))[0]
16     return f.read(nit)
17
18 def ser_string(s):
19     if len(s) < 253:
20         return chr(len(s)) + s
21     elif len(s) < 0x10000:
22         return chr(253) + struct.pack("<H", len(s)) + s
23     elif len(s) < 0x100000000L:
24         return chr(254) + struct.pack("<I", len(s)) + s
25     return chr(255) + struct.pack("<Q", len(s)) + s
26
27 def deser_uint256(f):
28     r = 0L
29     for i in xrange(8):
30         t = struct.unpack("<I", f.read(4))[0]
31         r += t << (i * 32)
32     return r
33
34 def ser_uint256(u):
35     rs = ""
36     for i in xrange(8):
37         rs += struct.pack("<I", u & 0xFFFFFFFFL)
38         u >>= 32
39     return rs
40
41 def uint256_from_str(s):
42     r = 0L
43     t = struct.unpack("<IIIIIIII", s[:32])
44     for i in xrange(8):
45         r += t[i] << (i * 32)
46     return r
47
48 def uint256_from_str_be(s):
49     r = 0L
50     t = struct.unpack(">IIIIIIII", s[:32])
51     for i in xrange(8):
52         r += t[i] << (i * 32)
53     return r
54
55 def uint256_from_compact(c):
56     nbytes = (c >> 24) & 0xFF
57     v = (c & 0xFFFFFFL) << (8 * (nbytes - 3))
58     return v
59
60 def deser_vector(f, c):
61     nit = struct.unpack("<B", f.read(1))[0]
62     if nit == 253:
63         nit = struct.unpack("<H", f.read(2))[0]
64     elif nit == 254:
65         nit = struct.unpack("<I", f.read(4))[0]
66     elif nit == 255:
67         nit = struct.unpack("<Q", f.read(8))[0]
68     r = []
69     for i in xrange(nit):
70         t = c()
71         t.deserialize(f)
72         r.append(t)
73     return r
74
75 def ser_vector(l):
76     r = ""
77     if len(l) < 253:
78         r = chr(len(l))
79     elif len(l) < 0x10000:
80         r = chr(253) + struct.pack("<H", len(l))
81     elif len(l) < 0x100000000L:
82         r = chr(254) + struct.pack("<I", len(l))
83     else:
84         r = chr(255) + struct.pack("<Q", len(l))
85     for i in l:
86         r += i.serialize()
87     return r
88
89 def deser_uint256_vector(f):
90     nit = struct.unpack("<B", f.read(1))[0]
91     if nit == 253:
92         nit = struct.unpack("<H", f.read(2))[0]
93     elif nit == 254:
94         nit = struct.unpack("<I", f.read(4))[0]
95     elif nit == 255:
96         nit = struct.unpack("<Q", f.read(8))[0]
97     r = []
98     for i in xrange(nit):
99         t = deser_uint256(f)
100         r.append(t)
101     return r
102
103 def ser_uint256_vector(l):
104     r = ""
105     if len(l) < 253:
106         r = chr(len(l))
107     elif len(l) < 0x10000:
108         r = chr(253) + struct.pack("<H", len(l))
109     elif len(l) < 0x100000000L:
110         r = chr(254) + struct.pack("<I", len(l))
111     else:
112         r = chr(255) + struct.pack("<Q", len(l))
113     for i in l:
114         r += ser_uint256(i)
115     return r
116
117 __b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
118 __b58base = len(__b58chars)
119
120 def b58decode(v, length):
121     """ decode v into a string of len bytes
122     """
123     long_value = 0L
124     for (i, c) in enumerate(v[::-1]):
125         long_value += __b58chars.find(c) * (__b58base**i)
126
127     result = ''
128     while long_value >= 256:
129         div, mod = divmod(long_value, 256)
130         result = chr(mod) + result
131         long_value = div
132     result = chr(long_value) + result
133
134     nPad = 0
135     for c in v:
136         if c == __b58chars[0]: nPad += 1
137         else: break
138
139     result = chr(0)*nPad + result
140     if length is not None and len(result) != length:
141         return None
142
143     return result
144
145 def reverse_hash(h):
146     # This only revert byte order, nothing more
147     if len(h) != 64:
148         raise Exception('hash must have 64 hexa chars')
149
150     return ''.join([ h[56-i:64-i] for i in range(0, 64, 8) ])
151
152 def doublesha(b):
153     return sha256(sha256(b).digest()).digest()
154
155 def bits_to_target(bits):
156     return struct.unpack('<L', bits[:3] + b'\0')[0] * 2**(8*(int(bits[3], 16) - 3))
157
158 def address_to_pubkeyhash(addr):
159     try:
160         addr = b58decode(addr, 25)
161     except:
162         return None
163
164     if addr is None:
165         return None
166
167     ver = addr[0]
168     cksumA = addr[-4:]
169     cksumB = doublesha(addr[:-4])[:4]
170
171     if cksumA != cksumB:
172         return None
173
174     return (ver, addr[1:-4])
175
176 def ser_uint256_be(u):
177     '''ser_uint256 to big endian'''
178     rs = ""
179     for i in xrange(8):
180         rs += struct.pack(">I", u & 0xFFFFFFFFL)
181         u >>= 32
182     return rs
183
184 def deser_uint256_be(f):
185     r = 0L
186     for i in xrange(8):
187         t = struct.unpack(">I", f.read(4))[0]
188         r += t << (i * 32)
189     return r
190
191 def ser_number(n):
192     # For encoding nHeight into coinbase
193     s = bytearray(b'\1')
194     while n > 127:
195         s[0] += 1
196         s.append(n % 256)
197         n //= 256
198     s.append(n)
199     return bytes(s)
200
201 def script_to_address(addr):
202     d = address_to_pubkeyhash(addr)
203     if not d:
204         raise ValueError('invalid address')
205     (ver, pubkeyhash) = d
206     return b'\x76\xa9\x14' + pubkeyhash + b'\x88\xac'