from __future__ import division
-import ConfigParser
-import StringIO
import base64
import json
import os
version=work['version'],
previous_block=int(work['previousblockhash'], 16),
transactions=map(bitcoin_data.tx_type.unpack, packed_transactions),
- merkle_link=bitcoin_data.calculate_merkle_link([None] + map(bitcoin_data.hash256, packed_transactions), 0),
subsidy=work['coinbasevalue'],
time=work['time'] if 'time' in work else work['curtime'],
bits=bitcoin_data.FloatingIntegerType().unpack(work['bits'].decode('hex')[::-1]) if isinstance(work['bits'], (str, unicode)) else bitcoin_data.FloatingInteger(work['bits']),
traffic_happened = variable.Event()
+ @defer.inlineCallbacks
+ def connect_p2p():
+ # 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.PARENT)
+ reactor.connectTCP(args.bitcoind_address, args.bitcoind_p2p_port, factory)
+ yield factory.getProtocol() # waits until handshake is successful
+ print ' ...success!'
+ print
+ defer.returnValue(factory)
+
+ if args.testnet: # establish p2p connection first if testnet so bitcoind can work without connections
+ factory = yield connect_p2p()
+
# connect to bitcoind over JSON-RPC and do initial getmemorypool
url = '%s://%s:%i/' % ('https' if args.bitcoind_rpc_ssl else 'http', args.bitcoind_address, args.bitcoind_rpc_port)
print '''Testing bitcoind RPC connection to '%s' with username '%s'...''' % (url, args.bitcoind_rpc_username)
yield check()
temp_work = yield getwork(bitcoind)
+ if not args.testnet:
+ factory = yield connect_p2p()
+
block_height_var = variable.Variable(None)
@defer.inlineCallbacks
def poll_height():
print ' Current block height: %i' % (block_height_var.value,)
print
- # 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.PARENT)
- reactor.connectTCP(args.bitcoind_address, args.bitcoind_p2p_port, factory)
- yield factory.getProtocol() # waits until handshake is successful
- print ' ...success!'
- print
-
print 'Determining payout address...'
if args.pubkey_hash is None:
address_path = os.path.join(datadir_path, 'cached_payout_address')
# BEST SHARE
+ known_txs_var = variable.Variable({}) # hash -> tx
+ mining_txs_var = variable.Variable({}) # hash -> tx
get_height_rel_highest = yield height_tracker.get_height_rel_highest_func(bitcoind, factory, lambda: bitcoind_work.value['previous_block'], net)
best_share_var = variable.Variable(None)
desired_var = variable.Variable(None)
def set_best_share():
- best, desired = tracker.think(get_height_rel_highest, bitcoind_work.value['previous_block'], bitcoind_work.value['bits'])
+ best, desired = tracker.think(get_height_rel_highest, bitcoind_work.value['previous_block'], bitcoind_work.value['bits'], known_txs_var.value)
best_share_var.set(best)
desired_var.set(desired)
# setup p2p logic and join p2pool network
+ # update mining_txs according to getwork results
+ @bitcoind_work.changed.run_and_watch
+ def _(_=None):
+ new_mining_txs = {}
+ new_known_txs = dict(known_txs_var.value)
+ for tx in bitcoind_work.value['transactions']:
+ tx_hash = bitcoin_data.hash256(bitcoin_data.tx_type.pack(tx))
+ new_mining_txs[tx_hash] = tx
+ new_known_txs[tx_hash] = tx
+ mining_txs_var.set(new_mining_txs)
+ known_txs_var.set(new_known_txs)
+ # forward transactions seen to bitcoind
+ @known_txs_var.transitioned.watch
+ def _(before, after):
+ for tx_hash in set(after) - set(before):
+ factory.conn.value.send_tx(tx=after[tx_hash])
+
class Node(p2p.Node):
def handle_shares(self, shares, peer):
if len(shares) > 5:
@tracker.verified.added.watch
def _(share):
if share.pow_hash <= share.header['bits'].target:
- submit_block(share.as_block(tracker), ignore_failure=True)
+ block = share.as_block(tracker, known_txs_var.value)
+ if block is None:
+ print >>sys.stderr, 'GOT INCOMPLETE BLOCK FROM PEER! %s bitcoin: %s%064x' % (p2pool_data.format_hash(share.hash), net.PARENT.BLOCK_EXPLORER_URL_PREFIX, share.header_hash)
+ return
+ submit_block(block, ignore_failure=True)
print
print 'GOT BLOCK FROM PEER! Passing to bitcoind! %s bitcoin: %s%064x' % (p2pool_data.format_hash(share.hash), net.PARENT.BLOCK_EXPLORER_URL_PREFIX, share.header_hash)
print
connect_addrs=connect_addrs,
max_incoming_conns=args.p2pool_conns,
traffic_happened=traffic_happened,
+ known_txs_var=known_txs_var,
+ mining_txs_var=mining_txs_var,
)
p2p_node.start()
shares.append(share)
for peer in list(p2p_node.peers.itervalues()):
- yield peer.sendShares([share for share in shares if share.peer is not peer])
+ yield peer.sendShares([share for share in shares if share.peer is not peer], tracker, known_txs_var.value, include_txs_with=[share_hash])
# send share when the chain changes to their chain
best_share_var.changed.watch(broadcast_share)
'''rpcpassword=%x\r\n'''
'''\r\n'''
'''Keep that password secret! After creating the file, restart Bitcoin.''' % (conf_path, random.randrange(2**128)))
- with open(conf_path, 'rb') as f:
- cp = ConfigParser.RawConfigParser()
- cp.readfp(StringIO.StringIO('[x]\r\n' + f.read()))
- for conf_name, var_name, var_type in [
- ('rpcuser', 'bitcoind_rpc_username', str),
- ('rpcpassword', 'bitcoind_rpc_password', str),
- ('rpcport', 'bitcoind_rpc_port', int),
- ('port', 'bitcoind_p2p_port', int),
- ]:
- if getattr(args, var_name) is None and cp.has_option('x', conf_name):
- setattr(args, var_name, var_type(cp.get('x', conf_name)))
+ conf = open(conf_path, 'rb').read()
+ contents = {}
+ for line in conf.splitlines(True):
+ if '#' in line:
+ line = line[:line.index('#')]
+ if '=' not in line:
+ continue
+ k, v = line.split('=', 1)
+ contents[k.strip()] = v.strip()
+ for conf_name, var_name, var_type in [
+ ('rpcuser', 'bitcoind_rpc_username', str),
+ ('rpcpassword', 'bitcoind_rpc_password', str),
+ ('rpcport', 'bitcoind_rpc_port', int),
+ ('port', 'bitcoind_p2p_port', int),
+ ]:
+ if getattr(args, var_name) is None and conf_name in contents:
+ setattr(args, var_name, var_type(contents[conf_name]))
if args.bitcoind_rpc_password is None:
parser.error('''Bitcoin configuration file didn't contain an rpcpassword= line! Add one!''')