1 from __future__ import division
8 from p2pool.util import bases
10 class EarlyEnd(Exception):
13 class LateEnd(Exception):
17 # the same data can have only one unpacked representation, but multiple packed binary representations
19 def _unpack(self, data):
20 f = StringIO.StringIO(data)
24 if f.tell() != len(data):
25 raise LateEnd('underread ' + repr((self, data)))
29 def unpack(self, data):
30 obj = self._unpack(data)
31 assert self._unpack(self._pack(obj)) == obj
35 f = StringIO.StringIO()
44 data = self._pack(obj)
45 assert self._unpack(data) == obj
49 def pack_base58(self, obj):
50 return base58.base58_encode(self.pack(obj))
52 def unpack_base58(self, base58_data):
53 return self.unpack(base58.base58_decode(base58_data))
56 def hash160(self, obj):
57 return ripemdsha(self.pack(obj))
59 def hash256(self, obj):
60 return doublesha(self.pack(obj))
62 class VarIntType(Type):
67 first, = struct.unpack('<B', data)
68 if first == 0xff: desc = '<Q'
69 elif first == 0xfe: desc = '<I'
70 elif first == 0xfd: desc = '<H'
72 length = struct.calcsize(desc)
73 data = file.read(length)
74 if len(data) != length:
76 return struct.unpack(desc, data)[0]
78 def write(self, file, item):
80 file.write(struct.pack('<B', item))
82 file.write(struct.pack('<BH', 0xfd, item))
83 elif item <= 0xffffffff:
84 file.write(struct.pack('<BI', 0xfe, item))
85 elif item <= 0xffffffffffffffff:
86 file.write(struct.pack('<BQ', 0xff, item))
88 raise ValueError('int too large for varint')
90 class VarStrType(Type):
92 length = VarIntType().read(file)
93 res = file.read(length)
94 if len(res) != length:
95 raise EarlyEnd('var str not long enough %r' % ((length, len(res), res),))
98 def write(self, file, item):
99 VarIntType().write(file, len(item))
102 class FixedStrType(Type):
103 def __init__(self, length):
106 def read(self, file):
107 res = file.read(self.length)
108 if len(res) != self.length:
109 raise EarlyEnd('early EOF!')
112 def write(self, file, item):
113 if len(item) != self.length:
114 raise ValueError('incorrect length!')
117 class EnumType(Type):
118 def __init__(self, inner, values):
123 for k, v in values.iteritems():
125 raise ValueError('duplicate value in values')
128 def read(self, file):
129 return self.keys[self.inner.read(file)]
131 def write(self, file, item):
132 self.inner.write(file, self.values[item])
134 class HashType(Type):
135 def read(self, file):
136 data = file.read(256//8)
137 if len(data) != 256//8:
138 raise EarlyEnd('incorrect length!')
139 return int(data[::-1].encode('hex'), 16)
141 def write(self, file, item):
143 raise ValueError("invalid hash value")
144 file.write(('%064x' % (item,)).decode('hex')[::-1])
146 class ShortHashType(Type):
147 def read(self, file):
148 data = file.read(160//8)
149 if len(data) != 160//8:
150 raise EarlyEnd('incorrect length!')
151 return int(data[::-1].encode('hex'), 16)
153 def write(self, file, item):
155 raise ValueError("invalid hash value")
156 file.write(('%040x' % (item,)).decode('hex')[::-1])
158 class ListType(Type):
159 def __init__(self, type):
162 def read(self, file):
163 length = VarIntType().read(file)
164 return [self.type.read(file) for i in xrange(length)]
166 def write(self, file, item):
167 VarIntType().write(file, len(item))
169 self.type.write(file, subitem)
171 class StructType(Type):
172 def __init__(self, desc):
174 self.length = struct.calcsize(self.desc)
176 def read(self, file):
177 data = file.read(self.length)
178 if len(data) != self.length:
180 res, = struct.unpack(self.desc, data)
183 def write(self, file, item):
184 data = struct.pack(self.desc, item)
185 if struct.unpack(self.desc, data)[0] != item:
186 # special test because struct doesn't error on some overflows
187 raise ValueError("item didn't survive pack cycle (%r)" % (item,))
190 class IPV6AddressType(Type):
191 def read(self, file):
195 if data[:12] != '00000000000000000000ffff'.decode('hex'):
196 raise ValueError("ipv6 addresses not supported yet")
197 return '::ffff:' + '.'.join(str(ord(x)) for x in data[12:])
199 def write(self, file, item):
201 if not item.startswith(prefix):
202 raise ValueError("ipv6 addresses not supported yet")
203 item = item[len(prefix):]
204 bits = map(int, item.split('.'))
206 raise ValueError("invalid address: %r" % (bits,))
207 data = '00000000000000000000ffff'.decode('hex') + ''.join(chr(x) for x in bits)
208 assert len(data) == 16, len(data)
211 class ComposedType(Type):
212 def __init__(self, fields):
215 def read(self, file):
217 for key, type_ in self.fields:
218 item[key] = type_.read(file)
221 def write(self, file, item):
222 for key, type_ in self.fields:
223 type_.write(file, item[key])
225 class ChecksummedType(Type):
226 def __init__(self, inner):
229 def read(self, file):
230 obj = self.inner.read(file)
231 data = self.inner.pack(obj)
233 if file.read(4) != hashlib.sha256(hashlib.sha256(data).digest()).digest()[:4]:
234 raise ValueError("invalid checksum")
238 def write(self, file, item):
239 data = self.inner.pack(item)
241 file.write(hashlib.sha256(hashlib.sha256(data).digest()).digest()[:4])
243 address_type = ComposedType([
244 ('services', StructType('<Q')),
245 ('address', IPV6AddressType()),
246 ('port', StructType('>H')),
249 tx_type = ComposedType([
250 ('version', StructType('<I')),
251 ('tx_ins', ListType(ComposedType([
252 ('previous_output', ComposedType([
253 ('hash', HashType()),
254 ('index', StructType('<I')),
256 ('script', VarStrType()),
257 ('sequence', StructType('<I')),
259 ('tx_outs', ListType(ComposedType([
260 ('value', StructType('<Q')),
261 ('script', VarStrType()),
263 ('lock_time', StructType('<I')),
266 block_header_type = ComposedType([
267 ('version', StructType('<I')),
268 ('previous_block', HashType()),
269 ('merkle_root', HashType()),
270 ('timestamp', StructType('<I')),
271 ('bits', FixedStrType(4)),
272 ('nonce', StructType('<I')),
275 block_type = ComposedType([
276 ('header', block_header_type),
277 ('txs', ListType(tx_type)),
281 return HashType().unpack(hashlib.sha256(hashlib.sha256(data).digest()).digest())
284 return ShortHashType().unpack(hashlib.new('ripemd160', hashlib.sha256(data).digest()).digest())
286 merkle_record_type = ComposedType([
287 ('left', HashType()),
288 ('right', HashType()),
291 def merkle_hash(tx_list):
292 hash_list = map(tx_hash, tx_list)
293 while len(hash_list) > 1:
294 hash_list = [doublesha(merkle_record_type.pack(dict(left=left, right=left if right is None else right)))
295 for left, right in zip(hash_list[::2], hash_list[1::2] + [None])]
299 return doublesha(tx_type.pack(tx))
301 def block_hash(header):
302 return doublesha(block_header_type.pack(header))
304 def shift_left(n, m):
310 def bits_to_target(bits):
312 length = ord(bits[0])
313 return bases.string_to_natural((bits[1:] + "\0"*length)[:length])
315 def old_bits_to_target(bits):
316 return shift_left(bits & 0x00ffffff, 8 * ((bits >> 24) - 3))
318 def about_equal(a, b):
319 if a == b: return True
320 return abs(a-b)/((abs(a)+abs(b))/2) < .01
322 def compress_target_to_bits(target): # loses precision
325 n = bases.natural_to_string(target)
326 print "n", n.encode('hex')
327 bits = chr(len(n)) + n[:3].ljust(3, '\0')
329 print "bits", bits.encode('hex')
330 print "new", bits_to_target(bits)
331 print "old", old_bits_to_target(struct.unpack("<I", bits)[0])
332 assert about_equal(bits_to_target(bits), target), (bits_to_target(bits), target)
333 assert about_equal(old_bits_to_target(struct.unpack("<I", bits)[0]), target), (old_bits_to_target(struct.unpack("<I", bits)[0]), target)
336 def target_to_average_attempts(target):
337 return 2**256//(target + 1)
339 human_address_type = ChecksummedType(ComposedType([
340 ('version', StructType("<B")),
341 ('pubkey_hash', ShortHashType()),
344 pubkey_type = FixedStrType(65)
346 def pubkey_hash_to_address(pubkey_hash, net):
347 return human_address_type.pack_base58(dict(version=net.BITCOIN_ADDRESS_VERSION, pubkey_hash=pubkey_hash))
349 def pubkey_to_address(pubkey, net):
350 return pubkey_hash_to_address(pubkey_type.hash160(pubkey), net)
352 def address_to_pubkey_hash(address, net):
353 x = human_address_type.unpack_base58(address)
354 if x['version'] != net.BITCOIN_ADDRESS_VERSION:
355 raise ValueError('address not for this net!')
356 return x['pubkey_hash']
358 class Mainnet(object):
359 BITCOIN_P2P_PREFIX = 'f9beb4d9'.decode('hex')
360 BITCOIN_P2P_PORT = 8333
361 BITCOIN_ADDRESS_VERSION = 0
363 class Testnet(object):
364 BITCOIN_P2P_PREFIX = 'fabfb5da'.decode('hex')
365 BITCOIN_P2P_PORT = 18333
366 BITCOIN_ADDRESS_VERSION = 111