moved bitcoin.data.Tracker to util.forest.Tracker
[p2pool.git] / p2pool / bitcoin / data.py
1 from __future__ import division
2
3 import hashlib
4 import struct
5
6 from twisted.internet import defer
7
8 from . import base58, skiplists
9 from p2pool.util import bases, math, expiring_dict, memoize, dicts
10 import p2pool
11
12 class EarlyEnd(Exception):
13     pass
14
15 class LateEnd(Exception):
16     pass
17
18 def read((data, pos), length):
19     data2 = data[pos:pos + length]
20     if len(data2) != length:
21         raise EarlyEnd()
22     return data2, (data, pos + length)
23
24 def size((data, pos)):
25     return len(data) - pos
26
27 class Type(object):
28     # the same data can have only one unpacked representation, but multiple packed binary representations
29     
30     def __hash__(self):
31         rval = getattr(self, '_hash', None)
32         if rval is None:
33             try:
34                 rval = self._hash = hash((type(self), frozenset(self.__dict__.items())))
35             except:
36                 print self.__dict__
37                 raise
38         return rval
39     
40     def __eq__(self, other):
41         return type(other) is type(self) and other.__dict__ == self.__dict__
42     
43     def __ne__(self, other):
44         return not (self == other)
45     
46     def _unpack(self, data):
47         obj, (data2, pos) = self.read((data, 0))
48         
49         assert data2 is data
50         
51         if pos != len(data):
52             raise LateEnd()
53         
54         return obj
55     
56     def _pack(self, obj):
57         f = self.write(None, obj)
58         
59         res = []
60         while f is not None:
61             res.append(f[1])
62             f = f[0]
63         res.reverse()
64         return ''.join(res)
65     
66     
67     def unpack(self, data):
68         obj = self._unpack(data)
69         
70         if p2pool.DEBUG:
71             data2 = self._pack(obj)
72             if data2 != data:
73                 if self._unpack(data2) != obj:
74                     raise AssertionError()
75         
76         return obj
77     
78     def pack2(self, obj):
79         data = self._pack(obj)
80         
81         if p2pool.DEBUG:
82             if self._unpack(data) != obj:
83                 raise AssertionError((self._unpack(data), obj))
84         
85         return data
86     
87     _backing = expiring_dict.ExpiringDict(100)
88     pack2 = memoize.memoize_with_backing(_backing, [unpack])(pack2)
89     unpack = memoize.memoize_with_backing(_backing)(unpack) # doesn't have an inverse
90     
91     def pack(self, obj):
92         return self.pack2(dicts.immutify(obj))
93     
94     
95     def pack_base58(self, obj):
96         return base58.base58_encode(self.pack(obj))
97     
98     def unpack_base58(self, base58_data):
99         return self.unpack(base58.base58_decode(base58_data))
100     
101     
102     def hash160(self, obj):
103         return ShortHashType().unpack(hashlib.new('ripemd160', hashlib.sha256(self.pack(obj)).digest()).digest())
104     
105     def hash256(self, obj):
106         return HashType().unpack(hashlib.sha256(hashlib.sha256(self.pack(obj)).digest()).digest())
107     
108     def scrypt(self, obj):
109         import ltc_scrypt
110         return HashType().unpack(ltc_scrypt.getPoWHash(self.pack(obj)))
111
112 class VarIntType(Type):
113     # redundancy doesn't matter here because bitcoin and p2pool both reencode before hashing
114     def read(self, file):
115         data, file = read(file, 1)
116         first = ord(data)
117         if first < 0xfd:
118             return first, file
119         elif first == 0xfd:
120             desc, length = '<H', 2
121         elif first == 0xfe:
122             desc, length = '<I', 4
123         elif first == 0xff:
124             desc, length = '<Q', 8
125         else:
126             raise AssertionError()
127         data, file = read(file, length)
128         return struct.unpack(desc, data)[0], file
129     
130     def write(self, file, item):
131         if item < 0xfd:
132             file = file, struct.pack('<B', item)
133         elif item <= 0xffff:
134             file = file, struct.pack('<BH', 0xfd, item)
135         elif item <= 0xffffffff:
136             file = file, struct.pack('<BI', 0xfe, item)
137         elif item <= 0xffffffffffffffff:
138             file = file, struct.pack('<BQ', 0xff, item)
139         else:
140             raise ValueError('int too large for varint')
141         return file
142
143 class VarStrType(Type):
144     _inner_size = VarIntType()
145     
146     def read(self, file):
147         length, file = self._inner_size.read(file)
148         return read(file, length)
149     
150     def write(self, file, item):
151         return self._inner_size.write(file, len(item)), item
152
153 class FixedStrType(Type):
154     def __init__(self, length):
155         self.length = length
156     
157     def read(self, file):
158         return read(file, self.length)
159     
160     def write(self, file, item):
161         if len(item) != self.length:
162             raise ValueError('incorrect length item!')
163         return file, item
164
165 class EnumType(Type):
166     def __init__(self, inner, values):
167         self.inner = inner
168         self.values = dicts.frozendict(values)
169         
170         keys = {}
171         for k, v in values.iteritems():
172             if v in keys:
173                 raise ValueError('duplicate value in values')
174             keys[v] = k
175         self.keys = dicts.frozendict(keys)
176     
177     def read(self, file):
178         data, file = self.inner.read(file)
179         if data not in self.keys:
180             raise ValueError('enum data (%r) not in values (%r)' % (data, self.values))
181         return self.keys[data], file
182     
183     def write(self, file, item):
184         if item not in self.values:
185             raise ValueError('enum item (%r) not in values (%r)' % (item, self.values))
186         return self.inner.write(file, self.values[item])
187
188 class HashType(Type):
189     def read(self, file):
190         data, file = read(file, 256//8)
191         return int(data[::-1].encode('hex'), 16), file
192     
193     def write(self, file, item):
194         if not 0 <= item < 2**256:
195             raise ValueError('invalid hash value - %r' % (item,))
196         if item != 0 and item < 2**160:
197             print 'Very low hash value - maybe you meant to use ShortHashType? %x' % (item,)
198         return file, ('%064x' % (item,)).decode('hex')[::-1]
199
200 class ShortHashType(Type):
201     def read(self, file):
202         data, file = read(file, 160//8)
203         return int(data[::-1].encode('hex'), 16), file
204     
205     def write(self, file, item):
206         if not 0 <= item < 2**160:
207             raise ValueError('invalid hash value - %r' % (item,))
208         return file, ('%040x' % (item,)).decode('hex')[::-1]
209
210 class ListType(Type):
211     _inner_size = VarIntType()
212     
213     def __init__(self, type):
214         self.type = type
215     
216     def read(self, file):
217         length, file = self._inner_size.read(file)
218         res = []
219         for i in xrange(length):
220             item, file = self.type.read(file)
221             res.append(item)
222         return res, file
223     
224     def write(self, file, item):
225         file = self._inner_size.write(file, len(item))
226         for subitem in item:
227             file = self.type.write(file, subitem)
228         return file
229
230 class StructType(Type):
231     def __init__(self, desc):
232         self.desc = desc
233         self.length = struct.calcsize(self.desc)
234     
235     def read(self, file):
236         data, file = read(file, self.length)
237         res, = struct.unpack(self.desc, data)
238         return res, file
239     
240     def write(self, file, item):
241         data = struct.pack(self.desc, item)
242         if struct.unpack(self.desc, data)[0] != item:
243             # special test because struct doesn't error on some overflows
244             raise ValueError('''item didn't survive pack cycle (%r)''' % (item,))
245         return file, data
246
247 class IPV6AddressType(Type):
248     def read(self, file):
249         data, file = read(file, 16)
250         if data[:12] != '00000000000000000000ffff'.decode('hex'):
251             raise ValueError('ipv6 addresses not supported yet')
252         return '.'.join(str(ord(x)) for x in data[12:]), file
253     
254     def write(self, file, item):
255         bits = map(int, item.split('.'))
256         if len(bits) != 4:
257             raise ValueError('invalid address: %r' % (bits,))
258         data = '00000000000000000000ffff'.decode('hex') + ''.join(chr(x) for x in bits)
259         assert len(data) == 16, len(data)
260         return file, data
261
262 _record_types = {}
263
264 def get_record(fields):
265     fields = tuple(sorted(fields))
266     if 'keys' in fields:
267         raise ValueError()
268     if fields not in _record_types:
269         class _Record(object):
270             __slots__ = fields
271             def __repr__(self):
272                 return repr(dict(self))
273             def __getitem__(self, key):
274                 return getattr(self, key)
275             def __setitem__(self, key, value):
276                 setattr(self, key, value)
277             #def __iter__(self):
278             #    for field in self.__slots__:
279             #        yield field, getattr(self, field)
280             def keys(self):
281                 return self.__slots__
282             def __eq__(self, other):
283                 if isinstance(other, dict):
284                     return dict(self) == other
285                 elif isinstance(other, _Record):
286                     return all(self[k] == other[k] for k in self.keys())
287                 raise TypeError()
288             def __ne__(self, other):
289                 return not (self == other)
290         _record_types[fields] = _Record
291     return _record_types[fields]()
292
293 class ComposedType(Type):
294     def __init__(self, fields):
295         self.fields = tuple(fields)
296     
297     def read(self, file):
298         item = get_record(k for k, v in self.fields)
299         for key, type_ in self.fields:
300             item[key], file = type_.read(file)
301         return item, file
302     
303     def write(self, file, item):
304         for key, type_ in self.fields:
305             file = type_.write(file, item[key])
306         return file
307
308 class ChecksummedType(Type):
309     def __init__(self, inner):
310         self.inner = inner
311     
312     def read(self, file):
313         obj, file = self.inner.read(file)
314         data = self.inner.pack(obj)
315         
316         checksum, file = read(file, 4)
317         if checksum != hashlib.sha256(hashlib.sha256(data).digest()).digest()[:4]:
318             raise ValueError('invalid checksum')
319         
320         return obj, file
321     
322     def write(self, file, item):
323         data = self.inner.pack(item)
324         return (file, data), hashlib.sha256(hashlib.sha256(data).digest()).digest()[:4]
325
326 class FloatingInteger(object):
327     __slots__ = ['_bits']
328     
329     @classmethod
330     def from_target_upper_bound(cls, target):
331         n = bases.natural_to_string(target)
332         if n and ord(n[0]) >= 128:
333             n = '\x00' + n
334         bits2 = (chr(len(n)) + (n + 3*chr(0))[:3])[::-1]
335         bits = struct.unpack('<I', bits2)[0]
336         return cls(bits)
337     
338     def __init__(self, bits):
339         self._bits = bits
340     
341     @property
342     def _value(self):
343         return math.shift_left(self._bits & 0x00ffffff, 8 * ((self._bits >> 24) - 3))
344     
345     def __hash__(self):
346         return hash(self._value)
347     
348     def __cmp__(self, other):
349         if isinstance(other, FloatingInteger):
350             return cmp(self._value, other._value)
351         elif isinstance(other, (int, long)):
352             return cmp(self._value, other)
353         else:
354             raise NotImplementedError(other)
355     
356     def __int__(self):
357         return self._value
358     
359     def __repr__(self):
360         return 'FloatingInteger(bits=%s (%x))' % (hex(self._bits), self)
361     
362     def __add__(self, other):
363         if isinstance(other, (int, long)):
364             return self._value + other
365         raise NotImplementedError()
366     __radd__ = __add__
367     def __mul__(self, other):
368         if isinstance(other, (int, long)):
369             return self._value * other
370         raise NotImplementedError()
371     __rmul__ = __mul__
372     def __truediv__(self, other):
373         if isinstance(other, (int, long)):
374             return self._value / other
375         raise NotImplementedError()
376     def __floordiv__(self, other):
377         if isinstance(other, (int, long)):
378             return self._value // other
379         raise NotImplementedError()
380     __div__ = __truediv__
381     def __rtruediv__(self, other):
382         if isinstance(other, (int, long)):
383             return other / self._value
384         raise NotImplementedError()
385     def __rfloordiv__(self, other):
386         if isinstance(other, (int, long)):
387             return other // self._value
388         raise NotImplementedError()
389     __rdiv__ = __rtruediv__
390
391 class FloatingIntegerType(Type):
392     _inner = StructType('<I')
393     
394     def read(self, file):
395         bits, file = self._inner.read(file)
396         return FloatingInteger(bits), file
397     
398     def write(self, file, item):
399         return self._inner.write(file, item._bits)
400
401 class PossiblyNoneType(Type):
402     def __init__(self, none_value, inner):
403         self.none_value = none_value
404         self.inner = inner
405     
406     def read(self, file):
407         value, file = self.inner.read(file)
408         return None if value == self.none_value else value, file
409     
410     def write(self, file, item):
411         if item == self.none_value:
412             raise ValueError('none_value used')
413         return self.inner.write(file, self.none_value if item is None else item)
414
415 address_type = ComposedType([
416     ('services', StructType('<Q')),
417     ('address', IPV6AddressType()),
418     ('port', StructType('>H')),
419 ])
420
421 tx_type = ComposedType([
422     ('version', StructType('<I')),
423     ('tx_ins', ListType(ComposedType([
424         ('previous_output', PossiblyNoneType(dicts.frozendict(hash=0, index=2**32 - 1), ComposedType([
425             ('hash', HashType()),
426             ('index', StructType('<I')),
427         ]))),
428         ('script', VarStrType()),
429         ('sequence', PossiblyNoneType(2**32 - 1, StructType('<I'))),
430     ]))),
431     ('tx_outs', ListType(ComposedType([
432         ('value', StructType('<Q')),
433         ('script', VarStrType()),
434     ]))),
435     ('lock_time', StructType('<I')),
436 ])
437
438 merkle_branch_type = ListType(HashType())
439
440 merkle_tx_type = ComposedType([
441     ('tx', tx_type),
442     ('block_hash', HashType()),
443     ('merkle_branch', merkle_branch_type),
444     ('index', StructType('<i')),
445 ])
446
447 block_header_type = ComposedType([
448     ('version', StructType('<I')),
449     ('previous_block', PossiblyNoneType(0, HashType())),
450     ('merkle_root', HashType()),
451     ('timestamp', StructType('<I')),
452     ('target', FloatingIntegerType()),
453     ('nonce', StructType('<I')),
454 ])
455
456 block_type = ComposedType([
457     ('header', block_header_type),
458     ('txs', ListType(tx_type)),
459 ])
460
461 aux_pow_type = ComposedType([
462     ('merkle_tx', merkle_tx_type),
463     ('merkle_branch', merkle_branch_type),
464     ('index', StructType('<i')),
465     ('parent_block_header', block_header_type),
466 ])
467
468
469 merkle_record_type = ComposedType([
470     ('left', HashType()),
471     ('right', HashType()),
472 ])
473
474 def merkle_hash(tx_list):
475     if not tx_list:
476         return 0
477     hash_list = map(tx_type.hash256, tx_list)
478     while len(hash_list) > 1:
479         hash_list = [merkle_record_type.hash256(dict(left=left, right=left if right is None else right))
480             for left, right in zip(hash_list[::2], hash_list[1::2] + [None])]
481     return hash_list[0]
482
483 def calculate_merkle_branch(txs, index):
484     # XXX optimize this
485     
486     hash_list = [(tx_type.hash256(tx), i == index, []) for i, tx in enumerate(txs)]
487     
488     while len(hash_list) > 1:
489         hash_list = [
490             (
491                 merkle_record_type.hash256(dict(left=left, right=right)),
492                 left_f or right_f,
493                 (left_l if left_f else right_l) + [dict(side=1, hash=right) if left_f else dict(side=0, hash=left)],
494             )
495             for (left, left_f, left_l), (right, right_f, right_l) in
496                 zip(hash_list[::2], hash_list[1::2] + [hash_list[::2][-1]])
497         ]
498     
499     res = [x['hash'] for x in hash_list[0][2]]
500     
501     assert hash_list[0][1]
502     assert check_merkle_branch(txs[index], index, res) == hash_list[0][0]
503     assert index == sum(k*2**i for i, k in enumerate([1-x['side'] for x in hash_list[0][2]]))
504     
505     return res
506
507 def check_merkle_branch(tx, index, merkle_branch):
508     return reduce(lambda c, (i, h): merkle_record_type.hash256(
509         dict(left=h, right=c) if 2**i & index else
510         dict(left=c, right=h)
511     ), enumerate(merkle_branch), tx_type.hash256(tx))
512
513 def target_to_average_attempts(target):
514     return 2**256//(target + 1)
515
516 def target_to_difficulty(target):
517     return (0xffff0000 * 2**(256-64) + 1)/(target + 1)
518
519 # tx
520
521 def tx_get_sigop_count(tx):
522     return sum(script.get_sigop_count(txin['script']) for txin in tx['tx_ins']) + sum(script.get_sigop_count(txout['script']) for txout in tx['tx_outs'])
523
524 # human addresses
525
526 human_address_type = ChecksummedType(ComposedType([
527     ('version', StructType('<B')),
528     ('pubkey_hash', ShortHashType()),
529 ]))
530
531 pubkey_type = FixedStrType(65)
532
533 def pubkey_hash_to_address(pubkey_hash, net):
534     return human_address_type.pack_base58(dict(version=net.BITCOIN_ADDRESS_VERSION, pubkey_hash=pubkey_hash))
535
536 def pubkey_to_address(pubkey, net):
537     return pubkey_hash_to_address(pubkey_type.hash160(pubkey), net)
538
539 def address_to_pubkey_hash(address, net):
540     x = human_address_type.unpack_base58(address)
541     if x['version'] != net.BITCOIN_ADDRESS_VERSION:
542         raise ValueError('address not for this net!')
543     return x['pubkey_hash']
544
545 # transactions
546
547 def pubkey_to_script2(pubkey):
548     return ('\x41' + pubkey_type.pack(pubkey)) + '\xac'
549
550 def pubkey_hash_to_script2(pubkey_hash):
551     return '\x76\xa9' + ('\x14' + ShortHashType().pack(pubkey_hash)) + '\x88\xac'
552
553 def script2_to_human(script2, net):
554     try:
555         pubkey = script2[1:-1]
556         script2_test = pubkey_to_script2(pubkey)
557     except:
558         pass
559     else:
560         if script2_test == script2:
561             return 'Pubkey. Address: %s' % (pubkey_to_address(pubkey, net),)
562     
563     try:
564         pubkey_hash = ShortHashType().unpack(script2[3:-2])
565         script2_test2 = pubkey_hash_to_script2(pubkey_hash)
566     except:
567         pass
568     else:
569         if script2_test2 == script2:
570             return 'Address. Address: %s' % (pubkey_hash_to_address(pubkey_hash, net),)
571     
572     return 'Unknown. Script: %s'  % (script2.encode('hex'),)