removed PassthruType and moved hashing functions from util.pack to bitcoin.data
authorForrest Voight <forrest@forre.st>
Sun, 29 Jan 2012 03:21:19 +0000 (22:21 -0500)
committerForrest Voight <forrest@forre.st>
Sun, 29 Jan 2012 03:34:31 +0000 (22:34 -0500)
p2pool/bitcoin/data.py
p2pool/bitcoin/networks.py
p2pool/bitcoin/p2p.py
p2pool/data.py
p2pool/main.py
p2pool/test/bitcoin/test_data.py
p2pool/util/pack.py

index 921dd72..7d14079 100644 (file)
@@ -5,6 +5,12 @@ import hashlib
 from p2pool.util import bases, math, pack
 from . import base58
 
+def hash256(data):
+    return pack.IntType(256).unpack(hashlib.sha256(hashlib.sha256(data).digest()).digest())
+
+def hash160(data):
+    return pack.IntType(160).unpack(hashlib.new('ripemd160', hashlib.sha256(data).digest()).digest())
+
 class ChecksummedType(pack.Type):
     def __init__(self, inner):
         self.inner = inner
@@ -137,7 +143,7 @@ def merkle_hash(hashes):
         return 0
     hash_list = list(hashes)
     while len(hash_list) > 1:
-        hash_list = [merkle_record_type.hash256(dict(left=left, right=left if right is None else right))
+        hash_list = [hash256(merkle_record_type.pack(dict(left=left, right=left if right is None else right)))
             for left, right in zip(hash_list[::2], hash_list[1::2] + [None])]
     return hash_list[0]
 
@@ -149,7 +155,7 @@ def calculate_merkle_branch(hashes, index):
     while len(hash_list) > 1:
         hash_list = [
             (
-                merkle_record_type.hash256(dict(left=left, right=right)),
+                hash256(merkle_record_type.pack(dict(left=left, right=right))),
                 left_f or right_f,
                 (left_l if left_f else right_l) + [dict(side=1, hash=right) if left_f else dict(side=0, hash=left)],
             )
@@ -166,10 +172,10 @@ def calculate_merkle_branch(hashes, index):
     return res
 
 def check_merkle_branch(tip_hash, index, merkle_branch):
-    return reduce(lambda c, (i, h): merkle_record_type.hash256(
+    return reduce(lambda c, (i, h): hash256(merkle_record_type.pack(
         dict(left=h, right=c) if 2**i & index else
         dict(left=c, right=h)
-    ), enumerate(merkle_branch), tip_hash)
+    )), enumerate(merkle_branch), tip_hash)
 
 def target_to_average_attempts(target):
     return 2**256//(target + 1)
@@ -189,13 +195,11 @@ human_address_type = ChecksummedType(pack.ComposedType([
     ('pubkey_hash', pack.IntType(160)),
 ]))
 
-pubkey_type = pack.PassthruType()
-
 def pubkey_hash_to_address(pubkey_hash, net):
     return base58.encode(human_address_type.pack(dict(version=net.ADDRESS_VERSION, pubkey_hash=pubkey_hash)))
 
 def pubkey_to_address(pubkey, net):
-    return pubkey_hash_to_address(pubkey_type.hash160(pubkey), net)
+    return pubkey_hash_to_address(hash160(pubkey), net)
 
 def address_to_pubkey_hash(address, net):
     x = human_address_type.unpack(base58.decode(address))
@@ -206,7 +210,7 @@ def address_to_pubkey_hash(address, net):
 # transactions
 
 def pubkey_to_script2(pubkey):
-    return ('\x41' + pubkey_type.pack(pubkey)) + '\xac'
+    return ('\x41' + pubkey) + '\xac'
 
 def pubkey_hash_to_script2(pubkey_hash):
     return '\x76\xa9' + ('\x14' + pack.IntType(160).pack(pubkey_hash)) + '\x88\xac'
index 52b1a87..e059daa 100644 (file)
@@ -1,7 +1,7 @@
 from twisted.internet import defer
 
 from . import data
-from p2pool.util import math
+from p2pool.util import math, pack
 
 BitcoinMainnet = math.Object(
     P2P_PREFIX='f9beb4d9'.decode('hex'),
@@ -12,7 +12,7 @@ BitcoinMainnet = math.Object(
         'bitcoinaddress' in (yield bitcoind.rpc_help()) and
         not (yield bitcoind.rpc_getinfo())['testnet']
     )),
-    POW_FUNC=data.block_header_type.hash256,
+    POW_FUNC=data.hash256,
     SYMBOL='BTC',
 )
 BitcoinTestnet = math.Object(
@@ -24,7 +24,7 @@ BitcoinTestnet = math.Object(
         'bitcoinaddress' in (yield bitcoind.rpc_help()) and
         (yield bitcoind.rpc_getinfo())['testnet']
     )),
-    POW_FUNC=data.block_header_type.hash256,
+    POW_FUNC=data.hash256,
     SYMBOL='tBTC',
 )
 
@@ -37,7 +37,7 @@ NamecoinMainnet = math.Object(
         'namecoinaddress' in (yield bitcoind.rpc_help()) and
         not (yield bitcoind.rpc_getinfo())['testnet']
     )),
-    POW_FUNC=data.block_header_type.hash256,
+    POW_FUNC=data.hash256,
     SYMBOL='NMC',
 )
 NamecoinTestnet = math.Object(
@@ -49,7 +49,7 @@ NamecoinTestnet = math.Object(
         'namecoinaddress' in (yield bitcoind.rpc_help()) and
         (yield bitcoind.rpc_getinfo())['testnet']
     )),
-    POW_FUNC=data.block_header_type.hash256,
+    POW_FUNC=data.hash256,
     SYMBOL='tNMC',
 )
 
@@ -62,7 +62,7 @@ LitecoinMainnet = math.Object(
         'litecoinaddress' in (yield bitcoind.rpc_help()) and
         not (yield bitcoind.rpc_getinfo())['testnet']
     )),
-    POW_FUNC=data.block_header_type.scrypt,
+    POW_FUNC=lambda data: pack.IntType(256).unpack(__import__('ltc_scrypt').getPoWHash(data)),
     SYMBOL='LTC',
 )
 LitecoinTestnet = math.Object(
@@ -74,6 +74,6 @@ LitecoinTestnet = math.Object(
         'litecoinaddress' in (yield bitcoind.rpc_help()) and
         (yield bitcoind.rpc_getinfo())['testnet']
     )),
-    POW_FUNC=data.block_header_type.scrypt,
+    POW_FUNC=lambda data: pack.IntType(256).unpack(__import__('ltc_scrypt').getPoWHash(data)),
     SYMBOL='tLTC',
 )
index 36c15e9..09a80f1 100644 (file)
@@ -213,13 +213,13 @@ class Protocol(BaseProtocol):
         ('tx', bitcoin_data.tx_type),
     ])
     def handle_tx(self, tx):
-        self.get_tx.got_response(bitcoin_data.tx_type.hash256(tx), tx)
+        self.get_tx.got_response(bitcoin_data.hash256(bitcoin_data.tx_type.pack(tx)), tx)
     
     message_block = pack.ComposedType([
         ('block', bitcoin_data.block_type),
     ])
     def handle_block(self, block):
-        block_hash = bitcoin_data.block_header_type.hash256(block['header'])
+        block_hash = bitcoin_data.hash256(bitcoin_data.block_header_type.pack(block['header']))
         self.get_block.got_response(block_hash, block)
         self.get_block_header.got_response(block_hash, block['header'])
     
@@ -229,7 +229,7 @@ class Protocol(BaseProtocol):
     def handle_headers(self, headers):
         for header in headers:
             header = header['header']
-            self.get_block_header.got_response(bitcoin_data.block_header_type.hash256(header), header)
+            self.get_block_header.got_response(bitcoin_data.hash256(bitcoin_data.block_header_type.pack(header)), header)
         self.factory.new_headers.happened([header['header'] for header in headers])
     
     message_ping = pack.ComposedType([])
@@ -277,7 +277,7 @@ class HeaderWrapper(object):
     
     @classmethod
     def from_header(cls, header):
-        return cls(bitcoin_data.block_header_type.hash256(header), header['previous_block'])
+        return cls(bitcoin_data.hash256(bitcoin_data.block_header_type.pack(header)), header['previous_block'])
     
     def __init__(self, hash, previous_hash):
         self.hash, self.previous_hash = hash, previous_hash
index 1c41329..ca67ff5 100644 (file)
@@ -81,7 +81,7 @@ class Share(object):
         if merkle_branch is None and other_txs is None:
             raise ValueError('need either merkle_branch or other_txs')
         if other_txs is not None:
-            new_merkle_branch = bitcoin_data.calculate_merkle_branch([0] + map(bitcoin_data.tx_type.hash256, other_txs), 0)
+            new_merkle_branch = bitcoin_data.calculate_merkle_branch([0] + [bitcoin_data.hash256(bitcoin_data.tx_type.pack(x)) for x in other_txs], 0)
             if merkle_branch is not None:
                 if merke_branch != new_merkle_branch:
                     raise ValueError('invalid merkle_branch and other_txs')
@@ -115,10 +115,10 @@ class Share(object):
         if len(self.share_data['coinbase']) > 100:
             raise ValueError('''coinbase too large! %i bytes''' % (len(self.share_data['coinbase']),))
         
-        self.pow_hash = net.PARENT.POW_FUNC(header)
-        self.header_hash = bitcoin_data.block_header_type.hash256(header)
+        self.pow_hash = net.PARENT.POW_FUNC(bitcoin_data.block_header_type.pack(header))
+        self.header_hash = bitcoin_data.hash256(bitcoin_data.block_header_type.pack(header))
         
-        self.hash = share1a_type.hash256(self.as_share1a())
+        self.hash = bitcoin_data.hash256(share1a_type.pack(self.as_share1a()))
         
         if self.pow_hash > self.target:
             print 'hash %x' % self.pow_hash
@@ -142,7 +142,7 @@ class Share(object):
         if share_info != self.share_info:
             raise ValueError('share difficulty invalid')
         
-        if bitcoin_data.check_merkle_branch(bitcoin_data.tx_type.hash256(gentx), 0, self.merkle_branch) != self.header['merkle_root']:
+        if bitcoin_data.check_merkle_branch(bitcoin_data.hash256(bitcoin_data.tx_type.pack(gentx)), 0, self.merkle_branch) != self.header['merkle_root']:
             raise ValueError('''gentx doesn't match header via merkle_branch''')
     
     def as_share(self):
@@ -260,7 +260,7 @@ def generate_transaction(tracker, share_data, block_target, desired_timestamp, n
             sequence=None,
             script=share_data['coinbase'].ljust(2, '\x00'),
         )],
-        tx_outs=[dict(value=0, script='\x20' + pack.IntType(256).pack(share_info_type.hash256(share_info)))] + [dict(value=amounts[script], script=script) for script in dests if amounts[script]],
+        tx_outs=[dict(value=0, script='\x20' + pack.IntType(256).pack(bitcoin_data.hash256(share_info_type.pack(share_info))))] + [dict(value=amounts[script], script=script) for script in dests if amounts[script]],
         lock_time=0,
     )
 
index 2bddd4f..19d797f 100644 (file)
@@ -475,7 +475,7 @@ def main(args, net, datadir_path):
                     target = max(target, current_work.value['aux_work']['target'])
                 
                 transactions = [generate_tx] + list(current_work2.value['transactions'])
-                merkle_root = bitcoin_data.merkle_hash(map(bitcoin_data.tx_type.hash256, transactions))
+                merkle_root = bitcoin_data.merkle_hash([bitcoin_data.hash256(bitcoin_data.tx_type.pack(x)) for x in transactions])
                 self.merkle_root_to_transactions[merkle_root] = share_info, transactions, time.time(), current_work.value['aux_work'], target
                 
                 print 'New work for worker! Difficulty: %.06f Share difficulty: %.06f Payout if block: %.6f %s Total block value: %.6f %s including %i transactions' % (
@@ -502,7 +502,7 @@ def main(args, net, datadir_path):
                     return False
                 share_info, transactions, getwork_time, aux_work, target = self.merkle_root_to_transactions[header['merkle_root']]
                 
-                pow_hash = net.PARENT.POW_FUNC(header)
+                pow_hash = net.PARENT.POW_FUNC(bitcoin_data.block_header_type.pack(header))
                 on_time = current_work.value['best_share_hash'] == share_info['share_data']['previous_share_hash']
                 
                 try:
@@ -513,9 +513,9 @@ def main(args, net, datadir_path):
                             print >>sys.stderr, 'No bitcoind connection when block submittal attempted! Erp!'
                         if pow_hash <= header['bits'].target:
                             print
-                            print 'GOT BLOCK FROM MINER! Passing to bitcoind! bitcoin: %x' % (bitcoin_data.block_header_type.hash256(header),)
+                            print 'GOT BLOCK FROM MINER! Passing to bitcoind! bitcoin: %x' % (bitcoin_data.hash256(bitcoin_data.block_header_type.pack(header)),)
                             print
-                            recent_blocks.append({ 'ts': time.time(), 'hash': '%x' % (bitcoin_data.block_header_type.hash256(header),) })
+                            recent_blocks.append({ 'ts': time.time(), 'hash': '%x' % (bitcoin_data.hash256(bitcoin_data.block_header_type.pack(header)),) })
                 except:
                     log.err(None, 'Error while processing potential block:')
                 
@@ -527,8 +527,8 @@ def main(args, net, datadir_path):
                             bitcoin_data.aux_pow_type.pack(dict(
                                 merkle_tx=dict(
                                     tx=transactions[0],
-                                    block_hash=bitcoin_data.block_header_type.hash256(header),
-                                    merkle_branch=bitcoin_data.calculate_merkle_branch(map(bitcoin_data.tx_type.hash256, transactions), 0),
+                                    block_hash=bitcoin_data.hash256(bitcoin_data.block_header_type.pack(header)),
+                                    merkle_branch=bitcoin_data.calculate_merkle_branch([bitcoin_data.hash256(bitcoin_data.tx_type.pack(x)) for x in transactions], 0),
                                     index=0,
                                 ),
                                 merkle_branch=[],
index c98a7ca..756e0fe 100644 (file)
@@ -6,17 +6,17 @@ from p2pool.util import pack
 
 class Test(unittest.TestCase):
     def test_header_hash(self):
-        assert data.block_header_type.hash256(dict(
+        assert data.hash256(data.block_header_type.pack(dict(
             version=1,
             previous_block=0x000000000000038a2a86b72387f93c51298298a732079b3b686df3603d2f6282,
             merkle_root=0x37a43a3b812e4eb665975f46393b4360008824aab180f27d642de8c28073bc44,
             timestamp=1323752685,
             bits=data.FloatingInteger(437159528),
             nonce=3658685446,
-        )) == 0x000000000000003aaaf7638f9f9c0d0c60e8b0eb817dcdb55fd2b1964efc5175
+        ))) == 0x000000000000003aaaf7638f9f9c0d0c60e8b0eb817dcdb55fd2b1964efc5175
     
     def test_tx_hash(self):
-        assert data.tx_type.hash256(dict(
+        assert data.hash256(data.tx_type.pack(dict(
             version=1,
             tx_ins=[dict(
                 previous_output=None,
@@ -28,7 +28,7 @@ class Test(unittest.TestCase):
                 script=data.pubkey_hash_to_script2(pack.IntType(160).unpack('ca975b00a8c203b8692f5a18d92dc5c2d2ebc57b'.decode('hex'))),
             )],
             lock_time=0,
-        )) == 0xb53802b2333e828d6532059f46ecf6b313a42d79f97925e457fbbfda45367e5c
+        ))) == 0xb53802b2333e828d6532059f46ecf6b313a42d79f97925e457fbbfda45367e5c
     
     def test_address_to_pubkey_hash(self):
         assert data.address_to_pubkey_hash('1KUCp7YP5FP8ViRxhfszSUJCTAajK6viGy', networks.BitcoinMainnet) == pack.IntType(160).unpack('ca975b00a8c203b8692f5a18d92dc5c2d2ebc57b'.decode('hex'))
index bed3c3b..4380907 100644 (file)
@@ -1,5 +1,4 @@
 import binascii
-import hashlib
 import struct
 
 import p2pool
@@ -80,17 +79,6 @@ class Type(object):
                 raise AssertionError((self._unpack(data), obj))
         
         return data
-    
-    
-    def hash160(self, obj):
-        return IntType(160).unpack(hashlib.new('ripemd160', hashlib.sha256(self.pack(obj)).digest()).digest())
-    
-    def hash256(self, obj):
-        return IntType(256).unpack(hashlib.sha256(hashlib.sha256(self.pack(obj)).digest()).digest())
-    
-    def scrypt(self, obj):
-        import ltc_scrypt
-        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
@@ -133,13 +121,6 @@ class VarStrType(Type):
     def write(self, file, item):
         return self._inner_size.write(file, len(item)), item
 
-class PassthruType(Type):
-    def read(self, file):
-        return read(file, size(file))
-    
-    def write(self, file, item):
-        return file, item
-
 class EnumType(Type):
     def __init__(self, inner, values):
         self.inner = inner