From 52cacb4b663c0e744b0f709b90fcea7d6bda0076 Mon Sep 17 00:00:00 2001 From: Forrest Voight Date: Mon, 23 Jan 2012 12:59:48 -0500 Subject: [PATCH] unified HashType, ShortHashType, and StructType into IntType --- p2pool/bitcoin/data.py | 111 ++++++++++++++++++------------------- p2pool/bitcoin/getwork.py | 4 +- p2pool/bitcoin/p2p.py | 36 ++++++------ p2pool/data.py | 12 ++-- p2pool/main.py | 8 ++-- p2pool/p2p.py | 20 ++++---- p2pool/test/bitcoin/test_data.py | 4 +- 7 files changed, 96 insertions(+), 99 deletions(-) diff --git a/p2pool/bitcoin/data.py b/p2pool/bitcoin/data.py index 6bf8a63..8cf730f 100644 --- a/p2pool/bitcoin/data.py +++ b/p2pool/bitcoin/data.py @@ -91,14 +91,14 @@ class Type(object): def hash160(self, obj): - return ShortHashType().unpack(hashlib.new('ripemd160', hashlib.sha256(self.pack(obj)).digest()).digest()) + return IntType(160).unpack(hashlib.new('ripemd160', hashlib.sha256(self.pack(obj)).digest()).digest()) def hash256(self, obj): - return HashType().unpack(hashlib.sha256(hashlib.sha256(self.pack(obj)).digest()).digest()) + return IntType(256).unpack(hashlib.sha256(hashlib.sha256(self.pack(obj)).digest()).digest()) def scrypt(self, obj): import ltc_scrypt - return HashType().unpack(ltc_scrypt.getPoWHash(self.pack(obj))) + return IntType(256).unpack(ltc_scrypt.getPoWHash(self.pack(obj))) class VarIntType(Type): # redundancy doesn't matter here because bitcoin and p2pool both reencode before hashing @@ -171,28 +171,6 @@ class EnumType(Type): raise ValueError('enum item (%r) not in values (%r)' % (item, self.values)) return self.inner.write(file, self.values[item]) -class HashType(Type): - def read(self, file): - data, file = read(file, 256//8) - return int(data[::-1].encode('hex'), 16), file - - def write(self, file, item): - if not 0 <= item < 2**256: - raise ValueError('invalid hash value - %r' % (item,)) - if item != 0 and item < 2**160: - print 'Very low hash value - maybe you meant to use ShortHashType? %x' % (item,) - return file, ('%064x' % (item,)).decode('hex')[::-1] - -class ShortHashType(Type): - def read(self, file): - data, file = read(file, 160//8) - return int(data[::-1].encode('hex'), 16), file - - def write(self, file, item): - if not 0 <= item < 2**160: - raise ValueError('invalid hash value - %r' % (item,)) - return file, ('%040x' % (item,)).decode('hex')[::-1] - class ListType(Type): _inner_size = VarIntType() @@ -220,15 +198,34 @@ class StructType(Type): def read(self, file): data, file = read(file, self.length) - res, = struct.unpack(self.desc, data) - return res, file + return struct.unpack(self.desc, data)[0], file def write(self, file, item): - data = struct.pack(self.desc, item) - if struct.unpack(self.desc, data)[0] != item: - # special test because struct doesn't error on some overflows - raise ValueError('''item didn't survive pack cycle (%r)''' % (item,)) - return file, data + return file, struct.pack(self.desc, item) + +class IntType(Type): + def __new__(cls, bits, endianness='little'): + assert bits % 8 == 0 + assert endianness in ['little', 'big'] + if bits in [8, 16, 32, 64]: + return StructType(('<' if endianness == 'little' else '>') + {8: 'B', 16: 'H', 32: 'I', 64: 'Q'}[bits]) + else: + return object.__new__(cls, bits, endianness) + + def __init__(self, bits, endianness='little'): + assert bits % 8 == 0 + assert endianness in ['little', 'big'] + self.bytes = bits//8 + self.step = -1 if endianness == 'little' else 1 + + def read(self, file): + data, file = read(file, self.bytes) + return int(data[::self.step].encode('hex'), 16), file + + def write(self, file, item): + if not 0 <= item < 2**(8*self.bytes): + raise ValueError('invalid int value - %r' % (item,)) + return file, ('%x' % (item,)).zfill(2*self.bytes).decode('hex')[::self.step] class IPV6AddressType(Type): def read(self, file): @@ -350,7 +347,7 @@ class FloatingInteger(object): return 'FloatingInteger(bits=%s, target=%s)' % (hex(self.bits), hex(self.target)) class FloatingIntegerType(Type): - _inner = StructType('H')), + ('port', IntType(16, 'big')), ]) tx_type = ComposedType([ - ('version', StructType(' 100: @@ -187,9 +187,9 @@ class Protocol(bitcoin_p2p.BaseProtocol): ]) message_getshares = bitcoin_data.ComposedType([ - ('hashes', bitcoin_data.ListType(bitcoin_data.HashType())), + ('hashes', bitcoin_data.ListType(bitcoin_data.IntType(256))), ('parents', bitcoin_data.VarIntType()), - ('stops', bitcoin_data.ListType(bitcoin_data.HashType())), + ('stops', bitcoin_data.ListType(bitcoin_data.IntType(256))), ]) def handle_getshares(self, hashes, parents, stops): self.node.handle_get_shares(hashes, parents, stops, self) diff --git a/p2pool/test/bitcoin/test_data.py b/p2pool/test/bitcoin/test_data.py index a29c965..4f503a0 100644 --- a/p2pool/test/bitcoin/test_data.py +++ b/p2pool/test/bitcoin/test_data.py @@ -24,13 +24,13 @@ class Test(unittest.TestCase): )], tx_outs=[dict( value=5003880250, - script=data.pubkey_hash_to_script2(data.ShortHashType().unpack('ca975b00a8c203b8692f5a18d92dc5c2d2ebc57b'.decode('hex'))), + script=data.pubkey_hash_to_script2(data.IntType(160).unpack('ca975b00a8c203b8692f5a18d92dc5c2d2ebc57b'.decode('hex'))), )], lock_time=0, )) == 0xb53802b2333e828d6532059f46ecf6b313a42d79f97925e457fbbfda45367e5c def test_address_to_pubkey_hash(self): - assert data.address_to_pubkey_hash('1KUCp7YP5FP8ViRxhfszSUJCTAajK6viGy', networks.BitcoinMainnet) == data.ShortHashType().unpack('ca975b00a8c203b8692f5a18d92dc5c2d2ebc57b'.decode('hex')) + assert data.address_to_pubkey_hash('1KUCp7YP5FP8ViRxhfszSUJCTAajK6viGy', networks.BitcoinMainnet) == data.IntType(160).unpack('ca975b00a8c203b8692f5a18d92dc5c2d2ebc57b'.decode('hex')) def test_merkle_hash(self): assert data.merkle_hash([ -- 1.7.1