5 class EarlyEnd(Exception):
8 class LateEnd(Exception):
12 # the same data can have only one unpacked representation, but multiple packed binary representations
14 def _unpack(self, data):
15 f = StringIO.StringIO(data)
19 if f.tell() != len(data):
20 raise LateEnd('underread ' + repr((self, data)))
24 def unpack(self, data):
25 obj = self._unpack(data)
26 assert self._unpack(self._pack(obj)) == obj
30 f = StringIO.StringIO()
39 data = self._pack(obj)
40 assert self._unpack(data) == obj
43 class VarIntType(Type):
48 first, = struct.unpack('<B', data)
49 if first == 0xff: desc = '<Q'
50 elif first == 0xfe: desc = '<I'
51 elif first == 0xfd: desc = '<H'
53 length = struct.calcsize(desc)
54 data = file.read(length)
55 if len(data) != length:
57 return struct.unpack(desc, data)[0]
59 def write(self, file, item):
61 file.write(struct.pack('<B', item))
63 file.write(struct.pack('<BH', 0xfd, item))
64 elif item <= 0xffffffff:
65 file.write(struct.pack('<BI', 0xfe, item))
66 elif item <= 0xffffffffffffffff:
67 file.write(struct.pack('<BQ', 0xff, item))
69 raise ValueError('int too large for varint')
71 class VarStrType(Type):
73 length = VarIntType().read(file)
74 res = file.read(length)
75 if len(res) != length:
76 raise EarlyEnd('var str not long enough %r' % ((length, len(res), res),))
79 def write(self, file, item):
80 VarIntType().write(file, len(item))
83 class FixedStrType(Type):
84 def __init__(self, length):
88 res = file.read(self.length)
89 if len(res) != self.length:
90 raise EarlyEnd('early EOF!')
93 def write(self, file, item):
94 if len(item) != self.length:
95 raise ValueError('incorrect length!')
99 def __init__(self, inner, values):
104 for k, v in values.iteritems():
106 raise ValueError('duplicate value in values')
109 def read(self, file):
110 return self.keys[self.inner.read(file)]
112 def write(self, file, item):
113 self.inner.write(file, self.values[item])
115 class HashType(Type):
116 def read(self, file):
117 data = file.read(256//8)
118 if len(data) != 256//8:
119 raise EarlyEnd('incorrect length!')
120 return int(data[::-1].encode('hex'), 16)
122 def write(self, file, item):
123 file.write(('%064x' % (item,)).decode('hex')[::-1])
125 class ShortHashType(Type):
126 def read(self, file):
127 data = file.read(160//8)
128 if len(data) != 160//8:
129 raise EarlyEnd('incorrect length!')
130 return int(data[::-1].encode('hex'), 16)
132 def write(self, file, item):
133 file.write(('%020x' % (item,)).decode('hex')[::-1])
135 class ListType(Type):
136 def __init__(self, type):
139 def read(self, file):
140 length = VarIntType().read(file)
141 return [self.type.read(file) for i in xrange(length)]
143 def write(self, file, item):
144 VarIntType().write(file, len(item))
146 self.type.write(file, subitem)
148 class StructType(Type):
149 def __init__(self, desc):
151 self.length = struct.calcsize(self.desc)
153 def read(self, file):
154 data = file.read(self.length)
155 if len(data) != self.length:
157 res, = struct.unpack(self.desc, data)
160 def write(self, file, item):
161 data = struct.pack(self.desc, item)
162 if struct.unpack(self.desc, data)[0] != item:
163 # special test because struct doesn't error on some overflows
164 raise ValueError("item didn't survive pack cycle (%r)" % (item,))
167 class IPV6AddressType(Type):
168 def read(self, file):
172 if data[:12] != '00000000000000000000ffff'.decode('hex'):
173 raise ValueError("ipv6 addresses not supported yet")
174 return '::ffff:' + '.'.join(str(ord(x)) for x in data[12:])
176 def write(self, file, item):
178 if not item.startswith(prefix):
179 raise ValueError("ipv6 addresses not supported yet")
180 item = item[len(prefix):]
181 bits = map(int, item.split('.'))
183 raise ValueError("invalid address: %r" % (bits,))
184 data = '00000000000000000000ffff'.decode('hex') + ''.join(chr(x) for x in bits)
185 assert len(data) == 16, len(data)
188 class ComposedType(Type):
189 def __init__(self, fields):
192 def read(self, file):
194 for key, type_ in self.fields:
195 item[key] = type_.read(file)
198 def write(self, file, item):
199 for key, type_ in self.fields:
200 type_.write(file, item[key])
202 address_type = ComposedType([
203 ('services', StructType('<Q')),
204 ('address', IPV6AddressType()),
205 ('port', StructType('>H')),
208 tx_type = ComposedType([
209 ('version', StructType('<I')),
210 ('tx_ins', ListType(ComposedType([
211 ('previous_output', ComposedType([
212 ('hash', HashType()),
213 ('index', StructType('<I')),
215 ('script', VarStrType()),
216 ('sequence', StructType('<I')),
218 ('tx_outs', ListType(ComposedType([
219 ('value', StructType('<Q')),
220 ('script', VarStrType()),
222 ('lock_time', StructType('<I')),
225 block_header_type = ComposedType([
226 ('version', StructType('<I')),
227 ('previous_block', HashType()),
228 ('merkle_root', HashType()),
229 ('timestamp', StructType('<I')),
230 ('bits', StructType('<I')),
231 ('nonce', StructType('<I')),
234 block_type = ComposedType([
235 ('header', block_header_type),
236 ('txs', ListType(tx_type)),
240 return HashType().unpack(hashlib.sha256(hashlib.sha256(data).digest()).digest())
243 return ShortHashType().unpack(hashlib.new('ripemd160', hashlib.sha256(data).digest()).digest())
245 merkle_record_type = ComposedType([
246 ('left', HashType()),
247 ('right', HashType()),
250 def merkle_hash(tx_list):
251 hash_list = [doublesha(tx_type.pack(tx)) for tx in tx_list]
252 while len(hash_list) > 1:
253 hash_list = [doublesha(merkle_record_type.pack(dict(left=left, right=left if right is None else right)))
254 for left, right in zip(hash_list[::2], hash_list[1::2] + [None])]
258 return doublesha(tx_type.pack(tx))
260 def block_hash(header):
261 return doublesha(block_header_type.pack(header))
263 class EarlyEnd(Exception):
266 class LateEnd(Exception):
270 # the same data can have only one unpacked representation, but multiple packed binary representations
272 def _unpack(self, data):
273 f = StringIO.StringIO(data)
277 if f.tell() != len(data):
278 raise LateEnd('underread ' + repr((self, data)))
282 def unpack(self, data):
283 obj = self._unpack(data)
284 assert self._unpack(self._pack(obj)) == obj
287 def _pack(self, obj):
288 f = StringIO.StringIO()
297 data = self._pack(obj)
298 assert self._unpack(data) == obj
301 class VarIntType(Type):
302 def read(self, file):
306 first, = struct.unpack('<B', data)
307 if first == 0xff: desc = '<Q'
308 elif first == 0xfe: desc = '<I'
309 elif first == 0xfd: desc = '<H'
311 length = struct.calcsize(desc)
312 data = file.read(length)
313 if len(data) != length:
315 return struct.unpack(desc, data)[0]
317 def write(self, file, item):
319 file.write(struct.pack('<B', item))
321 file.write(struct.pack('<BH', 0xfd, item))
322 elif item <= 0xffffffff:
323 file.write(struct.pack('<BI', 0xfe, item))
324 elif item <= 0xffffffffffffffff:
325 file.write(struct.pack('<BQ', 0xff, item))
327 raise ValueError('int too large for varint')
329 class VarStrType(Type):
330 def read(self, file):
331 length = VarIntType().read(file)
332 res = file.read(length)
333 if len(res) != length:
334 raise EarlyEnd('var str not long enough %r' % ((length, len(res), res),))
337 def write(self, file, item):
338 VarIntType().write(file, len(item))
341 class FixedStrType(Type):
342 def __init__(self, length):
345 def read(self, file):
346 res = file.read(self.length)
347 if len(res) != self.length:
348 raise EarlyEnd('early EOF!')
351 def write(self, file, item):
352 if len(item) != self.length:
353 raise ValueError('incorrect length!')
356 class EnumType(Type):
357 def __init__(self, inner, values):
362 for k, v in values.iteritems():
364 raise ValueError('duplicate value in values')
367 def read(self, file):
368 return self.keys[self.inner.read(file)]
370 def write(self, file, item):
371 self.inner.write(file, self.values[item])
373 class HashType(Type):
374 def read(self, file):
375 data = file.read(256//8)
376 if len(data) != 256//8:
377 raise EarlyEnd('incorrect length!')
378 return int(data[::-1].encode('hex'), 16)
380 def write(self, file, item):
381 file.write(('%064x' % (item,)).decode('hex')[::-1])
383 class ShortHashType(Type):
384 def read(self, file):
385 data = file.read(160//8)
386 if len(data) != 160//8:
387 raise EarlyEnd('incorrect length!')
388 return int(data[::-1].encode('hex'), 16)
390 def write(self, file, item):
391 file.write(('%020x' % (item,)).decode('hex')[::-1])
393 class ListType(Type):
394 def __init__(self, type):
397 def read(self, file):
398 length = VarIntType().read(file)
399 return [self.type.read(file) for i in xrange(length)]
401 def write(self, file, item):
402 VarIntType().write(file, len(item))
404 self.type.write(file, subitem)
406 class StructType(Type):
407 def __init__(self, desc):
409 self.length = struct.calcsize(self.desc)
411 def read(self, file):
412 data = file.read(self.length)
413 if len(data) != self.length:
415 res, = struct.unpack(self.desc, data)
418 def write(self, file, item):
419 data = struct.pack(self.desc, item)
420 if struct.unpack(self.desc, data)[0] != item:
421 # special test because struct doesn't error on some overflows
422 raise ValueError("item didn't survive pack cycle (%r)" % (item,))
425 class IPV6AddressType(Type):
426 def read(self, file):
430 if data[:12] != '00000000000000000000ffff'.decode('hex'):
431 raise ValueError("ipv6 addresses not supported yet")
432 return '::ffff:' + '.'.join(str(ord(x)) for x in data[12:])
434 def write(self, file, item):
436 if not item.startswith(prefix):
437 raise ValueError("ipv6 addresses not supported yet")
438 item = item[len(prefix):]
439 bits = map(int, item.split('.'))
441 raise ValueError("invalid address: %r" % (bits,))
442 data = '00000000000000000000ffff'.decode('hex') + ''.join(chr(x) for x in bits)
443 assert len(data) == 16, len(data)
446 class ComposedType(Type):
447 def __init__(self, fields):
450 def read(self, file):
452 for key, type_ in self.fields:
453 item[key] = type_.read(file)
456 def write(self, file, item):
457 for key, type_ in self.fields:
458 type_.write(file, item[key])
460 address_type = ComposedType([
461 ('services', StructType('<Q')),
462 ('address', IPV6AddressType()),
463 ('port', StructType('>H')),
466 tx_type = ComposedType([
467 ('version', StructType('<I')),
468 ('tx_ins', ListType(ComposedType([
469 ('previous_output', ComposedType([
470 ('hash', HashType()),
471 ('index', StructType('<I')),
473 ('script', VarStrType()),
474 ('sequence', StructType('<I')),
476 ('tx_outs', ListType(ComposedType([
477 ('value', StructType('<Q')),
478 ('script', VarStrType()),
480 ('lock_time', StructType('<I')),
483 block_header_type = ComposedType([
484 ('version', StructType('<I')),
485 ('previous_block', HashType()),
486 ('merkle_root', HashType()),
487 ('timestamp', StructType('<I')),
488 ('bits', StructType('<I')),
489 ('nonce', StructType('<I')),
492 block_type = ComposedType([
493 ('header', block_header_type),
494 ('txs', ListType(tx_type)),
498 return HashType().unpack(hashlib.sha256(hashlib.sha256(data).digest()).digest())
501 return ShortHashType().unpack(hashlib.new('ripemd160', hashlib.sha256(data).digest()).digest())
503 merkle_record_type = ComposedType([
504 ('left', HashType()),
505 ('right', HashType()),
508 def merkle_hash(tx_list):
509 hash_list = [doublesha(tx_type.pack(tx)) for tx in tx_list]
510 while len(hash_list) > 1:
511 hash_list = [doublesha(merkle_record_type.pack(dict(left=left, right=left if right is None else right)))
512 for left, right in zip(hash_list[::2], hash_list[1::2] + [None])]
516 return doublesha(tx_type.pack(tx))
518 def block_hash(header):
519 return doublesha(block_header_type.pack(header))
521 def bits_to_target(bits):
522 return (bits & 0x00ffffff) * 2 ** (8 * ((bits >> 24) - 3))
524 def target_to_average_attempts(target):
525 return 2**256//(target + 1)