separated p2pool and bitcoin network definitions
[p2pool.git] / p2pool / main.py
index 95f6f09..491926e 100644 (file)
@@ -6,7 +6,6 @@ from __future__ import division
 import argparse
 import codecs
 import datetime
-import itertools
 import os
 import random
 import struct
@@ -37,17 +36,17 @@ def getwork(bitcoind):
         transactions=[bitcoin_data.tx_type.unpack(x.decode('hex')) for x in work['transactions']],
         subsidy=work['coinbasevalue'],
         time=work['time'],
-        target=bitcoin_data.FloatingIntegerType().unpack(work['bits'].decode('hex')[::-1]) if isinstance(work['bits'], (str, unicode)) else bitcoin_data.FloatingInteger(work['bits']),
+        bits=bitcoin_data.FloatingIntegerType().unpack(work['bits'].decode('hex')[::-1]) if isinstance(work['bits'], (str, unicode)) else bitcoin_data.FloatingInteger(work['bits']),
     ))
 
 @deferral.retry('Error creating payout script:', 10)
 @defer.inlineCallbacks
-def get_payout_script2(bitcoind, net):
+def get_payout_script2(bitcoind, net2):
     address = yield bitcoind.rpc_getaccountaddress('p2pool')
     validate_response = yield bitcoind.rpc_validateaddress(address)
     if 'pubkey' not in validate_response:
         print '    Pubkey request failed. Falling back to payout to address.'
-        defer.returnValue(bitcoin_data.pubkey_hash_to_script2(bitcoin_data.address_to_pubkey_hash(address, net)))
+        defer.returnValue(bitcoin_data.pubkey_hash_to_script2(bitcoin_data.address_to_pubkey_hash(address, net2)))
     pubkey = validate_response['pubkey'].decode('hex')
     defer.returnValue(bitcoin_data.pubkey_to_script2(pubkey))
 
@@ -67,7 +66,7 @@ def main(args, net, datadir_path):
         url = 'http://%s:%i/' % (args.bitcoind_address, args.bitcoind_rpc_port)
         print '''Testing bitcoind RPC connection to '%s' with username '%s'...''' % (url, args.bitcoind_rpc_username)
         bitcoind = jsonrpc.Proxy(url, (args.bitcoind_rpc_username, args.bitcoind_rpc_password))
-        good = yield deferral.retry('Error while checking bitcoind identity:', 1)(net.BITCOIN_RPC_CHECK)(bitcoind)
+        good = yield deferral.retry('Error while checking bitcoind identity:', 1)(net.PARENT.RPC_CHECK)(bitcoind)
         if not good:
             print "    Check failed! Make sure that you're connected to the right bitcoind with --bitcoind-rpc-port!"
             return
@@ -78,7 +77,7 @@ def main(args, net, datadir_path):
         
         # connect to bitcoind over bitcoin-p2p
         print '''Testing bitcoind P2P connection to '%s:%s'...''' % (args.bitcoind_address, args.bitcoind_p2p_port)
-        factory = bitcoin_p2p.ClientFactory(net)
+        factory = bitcoin_p2p.ClientFactory(net.PARENT)
         reactor.connectTCP(args.bitcoind_address, args.bitcoind_p2p_port, factory)
         yield factory.getProtocol() # waits until handshake is successful
         print '    ...success!'
@@ -86,12 +85,12 @@ def main(args, net, datadir_path):
         
         if args.pubkey_hash is None:
             print 'Getting payout address from bitcoind...'
-            my_script = yield get_payout_script2(bitcoind, net)
+            my_script = yield get_payout_script2(bitcoind, net.PARENT)
         else:
             print 'Computing payout script from provided address....'
             my_script = bitcoin_data.pubkey_hash_to_script2(args.pubkey_hash)
         print '    ...success!'
-        print '    Payout script:', bitcoin_data.script2_to_human(my_script, net)
+        print '    Payout script:', bitcoin_data.script2_to_human(my_script, net.PARENT)
         print
         
         ht = bitcoin_p2p.HeightTracker(bitcoind, factory)
@@ -153,7 +152,7 @@ def main(args, net, datadir_path):
             pre_current_work.set(dict(
                 version=work['version'],
                 previous_block=work['previous_block_hash'],
-                target=work['target'],
+                bits=work['bits'],
             ))
         
         def set_real_work2():
@@ -248,7 +247,7 @@ def main(args, net, datadir_path):
         
         @tracker.verified.added.watch
         def _(share):
-            if share.pow_hash <= share.header['target']:
+            if share.pow_hash <= share.header['bits'].target:
                 if factory.conn.value is not None:
                     factory.conn.value.send_block(block=share.as_block(tracker))
                 else:
@@ -405,8 +404,7 @@ def main(args, net, datadir_path):
                 removed_unstales.add(share.hash)
         
         
-        def get_payout_script_from_username(request):
-            user = worker_interface.get_username(request)
+        def get_payout_script_from_username(user):
             if user is None:
                 return None
             try:
@@ -418,7 +416,7 @@ def main(args, net, datadir_path):
             state = current_work.value
             user = worker_interface.get_username(request)
             
-            payout_script = get_payout_script_from_username(request)
+            payout_script = get_payout_script_from_username(user)
             if payout_script is None or random.uniform(0, 100) < args.worker_fee:
                 payout_script = my_script
             
@@ -444,24 +442,24 @@ def main(args, net, datadir_path):
                         255 if shares == 0 else math.perfect_round(254*stales/shares)
                     )(*get_share_counts()),
                 ),
-                block_target=state['target'],
+                block_target=state['bits'].target,
                 desired_timestamp=int(time.time() - current_work2.value['clock_offset']),
                 net=net,
             )
             
             print 'New work for worker %s! Difficulty: %.06f Payout if block: %.6f %s Total block value: %.6f %s including %i transactions' % (
                 user,
-                bitcoin_data.target_to_difficulty(share_info['target']),
-                (sum(t['value'] for t in generate_tx['tx_outs'] if t['script'] == payout_script) - subsidy//200)*1e-8, net.BITCOIN_SYMBOL,
-                subsidy*1e-8, net.BITCOIN_SYMBOL,
+                bitcoin_data.target_to_difficulty(share_info['bits'].target),
+                (sum(t['value'] for t in generate_tx['tx_outs'] if t['script'] == payout_script) - subsidy//200)*1e-8, net.PARENT.SYMBOL,
+                subsidy*1e-8, net.PARENT.SYMBOL,
                 len(current_work2.value['transactions']),
             )
             
             transactions = [generate_tx] + list(current_work2.value['transactions'])
-            merkle_root = bitcoin_data.merkle_hash(transactions)
+            merkle_root = bitcoin_data.merkle_hash(map(bitcoin_data.tx_type.hash256, transactions))
             merkle_root_to_transactions[merkle_root] = share_info, transactions, time.time()
             
-            return bitcoin_getwork.BlockAttempt(state['version'], state['previous_block'], merkle_root, current_work2.value['time'], state['target'], share_info['target']), state['best_share_hash']
+            return bitcoin_getwork.BlockAttempt(state['version'], state['previous_block'], merkle_root, current_work2.value['time'], state['bits'], share_info['bits'].target), state['best_share_hash']
         
         my_shares = set()
         doa_shares = set()
@@ -478,14 +476,14 @@ def main(args, net, datadir_path):
                 
                 hash_ = bitcoin_data.block_header_type.hash256(header)
                 
-                pow_hash = net.BITCOIN_POW_FUNC(header)
+                pow_hash = net.PARENT.POW_FUNC(header)
                 
-                if pow_hash <= header['target'] or p2pool.DEBUG:
+                if pow_hash <= header['bits'].target or p2pool.DEBUG:
                     if factory.conn.value is not None:
                         factory.conn.value.send_block(block=dict(header=header, txs=transactions))
                     else:
                         print 'No bitcoind connection! Erp!'
-                    if pow_hash <= header['target']:
+                    if pow_hash <= header['bits'].target:
                         print
                         print 'GOT BLOCK! Passing to bitcoind! bitcoin: %x' % (hash_,)
                         print
@@ -496,7 +494,7 @@ def main(args, net, datadir_path):
                             merkle_tx=dict(
                                 tx=transactions[0],
                                 block_hash=hash_,
-                                merkle_branch=[x['hash'] for x in p2pool_data.calculate_merkle_branch(transactions, 0)],
+                                merkle_branch=[x['hash'] for x in p2pool_data.calculate_merkle_branch(map(bitcoin_data.tx_type.hash256, transactions), 0)],
                                 index=0,
                             ),
                             merkle_branch=[],
@@ -513,9 +511,8 @@ def main(args, net, datadir_path):
                     except:
                         log.err(None, 'Error while processing merged mining POW:')
                 
-                target = share_info['target']
-                if pow_hash > target:
-                    print 'Worker submitted share with hash > target:\nhash  : %x\ntarget: %x' % (pow_hash, target)
+                if pow_hash > share_info['bits'].target:
+                    print 'Worker submitted share with hash > target:\nhash  : %x\ntarget: %x' % (pow_hash, share_info['bits'].target)
                     return False
                 share = p2pool_data.Share(net, header, share_info, other_txs=transactions[1:])
                 my_shares.add(share.hash)
@@ -742,10 +739,10 @@ def run():
         help='connect to this address (default: 127.0.0.1)',
         type=str, action='store', default='127.0.0.1', dest='bitcoind_address')
     bitcoind_group.add_argument('--bitcoind-rpc-port', metavar='BITCOIND_RPC_PORT',
-        help='''connect to JSON-RPC interface at this port (default: %s)''' % ', '.join('%s:%i' % (n.NAME, n.BITCOIN_RPC_PORT) for _, n in sorted(networks.realnets.items())),
+        help='''connect to JSON-RPC interface at this port (default: %s)''' % ', '.join('%s:%i' % (n.NAME, n.PARENT.RPC_PORT) for _, n in sorted(networks.realnets.items())),
         type=int, action='store', default=None, dest='bitcoind_rpc_port')
     bitcoind_group.add_argument('--bitcoind-p2p-port', metavar='BITCOIND_P2P_PORT',
-        help='''connect to P2P interface at this port (default: %s)''' % ', '.join('%s:%i' % (n.NAME, n.BITCOIN_P2P_PORT) for _, n in sorted(networks.realnets.items())),
+        help='''connect to P2P interface at this port (default: %s)''' % ', '.join('%s:%i' % (n.NAME, n.PARENT.P2P_PORT) for _, n in sorted(networks.realnets.items())),
         type=int, action='store', default=None, dest='bitcoind_p2p_port')
     
     bitcoind_group.add_argument(metavar='BITCOIND_RPCUSER',
@@ -775,7 +772,10 @@ def run():
             self.softspace = 0
         def write(self, data):
             if isinstance(data, unicode):
-                data = data.encode(self.inner_file.encoding, 'replace')
+                try:
+                    data = data.encode(self.inner_file.encoding, 'replace')
+                except:
+                    data = data.encode('ascii', 'replace')
             self.inner_file.write(data)
         def flush(self):
             self.inner_file.flush()
@@ -853,10 +853,10 @@ def run():
     task.LoopingCall(logfile.reopen).start(5)
     
     if args.bitcoind_rpc_port is None:
-        args.bitcoind_rpc_port = net.BITCOIN_RPC_PORT
+        args.bitcoind_rpc_port = net.PARENT.RPC_PORT
     
     if args.bitcoind_p2p_port is None:
-        args.bitcoind_p2p_port = net.BITCOIN_P2P_PORT
+        args.bitcoind_p2p_port = net.PARENT.P2P_PORT
     
     if args.p2pool_port is None:
         args.p2pool_port = net.P2P_PORT
@@ -866,7 +866,7 @@ def run():
     
     if args.address is not None:
         try:
-            args.pubkey_hash = bitcoin_data.address_to_pubkey_hash(args.address, net)
+            args.pubkey_hash = bitcoin_data.address_to_pubkey_hash(args.address, net.PARENT)
         except Exception, e:
             parser.error('error parsing address: ' + repr(e))
     else: