Requirements:
Generic:
- Bitcoin >=0.6.4
+ Novacoin >= 0.3.1
+ ltc_scrypt
Python
Twisted
python-argparse (for Python <=2.6)
Install Zope.Interface: http://pypi.python.org/pypi/zope.interface/3.8.0
Unzip the files into C:\Python27\Lib\site-packages
-Running P2Pool:
- To use P2Pool, you must be running your own local bitcoind. For standard
- configurations, using P2Pool should be as simple as:
-
- python run_p2pool.py
-
- Then run your miner program, connecting to 127.0.0.1 on port 9332 with any
- username and password.
-
- If you are behind a NAT, you should enable TCP port forwarding on your
- router. Forward port 9333 to the host running P2Pool.
-
- Run "python run_p2pool.py --help" for additional options.
-
-Donations towards further development:
- 1HNeqi3pJRNvXybNX4FKzZgYJsdTSqJTbk
-
-Notes for Litecoin:
- Requirements:
- In order to run P2Pool with the Litecoin network, you would need to build and install the
- ltc_scrypt module that includes the scrypt proof of work code that Litecoin uses for hashes.
+Additional info about scrypt module:
+ In order to run P2Pool with the NovaCoin network, you would need to build and install the
+ ltc_scrypt module that includes the scrypt proof of work code that NovaCoin uses for block hashes.
Linux:
cd litecoin_scrypt
If you run into an error with unrecognized command line option '-mno-cygwin', see this:
http://stackoverflow.com/questions/6034390/compiling-with-cython-and-mingw-produces-gcc-error-unrecognized-command-line-o
-
- Running P2Pool:
- Run P2Pool with the "--net litecoin" option.
- Run your miner program, connecting to 127.0.0.1 on port 9327.
- Forward port 9338 to the host running P2Pool.
-
- Litecoin's use of ports 9332 and 9332 conflicts with P2Pool running on
- the Bitcoin network. To avoid problems, add these lines to litecoin.conf
- and restart litecoind:
- rpcport=10332
- port=10333
+
+Running P2Pool:
+ To use P2Pool, you must be running your own local bitcoind. For standard
+ configurations, using P2Pool should be as simple as:
+
+ python run_p2pool.py --net novacoin
+
+ Then run your miner program, connecting to 127.0.0.1 on port 8336 with any
+ username and password.
+
+ If you are behind a NAT, you should enable TCP port forwarding on your
+ router. Forward port 9777 to the host running P2Pool.
+
+ Run "python run_p2pool.py --help" for additional options.
+
+Donations towards further development:
+ 1HNeqi3pJRNvXybNX4FKzZgYJsdTSqJTbk
tx_type = pack.ComposedType([
('version', pack.IntType(32)),
+ ('timestamp', pack.IntType(32)),
('tx_ins', pack.ListType(pack.ComposedType([
('previous_output', pack.PossiblyNoneType(dict(hash=0, index=2**32 - 1), pack.ComposedType([
('hash', pack.IntType(256)),
block_type = pack.ComposedType([
('header', block_header_type),
('txs', pack.ListType(tx_type)),
+ ('signature', pack.VarStrType()),
])
# merged mining
@deferral.retry('Error submitting primary block: (will retry)', 10, 10)
def submit_block_p2p(block, factory, net):
if factory.conn.value is None:
- print >>sys.stderr, 'No bitcoind connection when block submittal attempted! %s%064x' % (net.PARENT.BLOCK_EXPLORER_URL_PREFIX, bitcoin_data.hash256(bitcoin_data.block_header_type.pack(block['header'])))
+ print >>sys.stderr, 'No bitcoind connection when block submittal attempted! %s%064x' % (net.PARENT.BLOCK_EXPLORER_URL_PREFIX, self.node.net.PARENT.BLOCKHASH_FUNC(bitcoin_data.block_header_type.pack(block['header'])))
raise deferral.RetrySilentlyException()
factory.conn.value.send_block(block=block)
@deferral.retry('Error submitting block: (will retry)', 10, 10)
@defer.inlineCallbacks
def submit_block_rpc(block, ignore_failure, bitcoind, bitcoind_work, net):
+
if bitcoind_work.value['use_getblocktemplate']:
result = yield bitcoind.rpc_submitblock(bitcoin_data.block_type.pack(block).encode('hex'))
success = result is None
else:
+ print bitcoin_data.block_type.pack(block).encode('hex')
+
result = yield bitcoind.rpc_getmemorypool(bitcoin_data.block_type.pack(block).encode('hex'))
success = result
success_expected = net.PARENT.POW_FUNC(bitcoin_data.block_header_type.pack(block['header'])) <= block['header']['bits'].target
print >>sys.stderr, 'Block submittal result: %s (%r) Expected: %s' % (success, result, success_expected)
def submit_block(block, ignore_failure, factory, bitcoind, bitcoind_work, net):
- submit_block_p2p(block, factory, net)
+ #submit_block_p2p(block, factory, net)
submit_block_rpc(block, ignore_failure, bitcoind, bitcoind_work, net)
from . import data
from p2pool.util import math, pack
+from operator import *
+
+def get_subsidy(nCap, nMaxSubsidy, bnTarget):
+ bnLowerBound = 0.01
+ bnUpperBound = bnSubsidyLimit = nMaxSubsidy
+ bnTargetLimit = 0x00000fffff000000000000000000000000000000000000000000000000000000
+
+ while bnLowerBound + 0.01 <= bnUpperBound:
+ bnMidValue = (bnLowerBound + bnUpperBound) / 2
+ if pow(bnMidValue, nCap) * bnTargetLimit > pow(bnSubsidyLimit, nCap) * bnTarget:
+ bnUpperBound = bnMidValue
+ else:
+ bnLowerBound = bnMidValue
+
+ nSubsidy = round(bnMidValue, 2)
+
+ if nSubsidy > bnMidValue:
+ nSubsidy = nSubsidy - 0.01
+
+ return int(nSubsidy * 1000000)
nets = dict(
- bitcoin=math.Object(
- P2P_PREFIX='f9beb4d9'.decode('hex'),
- P2P_PORT=8333,
- ADDRESS_VERSION=0,
- RPC_PORT=8332,
+ novacoin=math.Object(
+ P2P_PREFIX='e4e8e9e5'.decode('hex'),
+ P2P_PORT=7777,
+ ADDRESS_VERSION=8,
+ RPC_PORT=8344,
RPC_CHECK=defer.inlineCallbacks(lambda bitcoind: defer.returnValue(
- 'bitcoinaddress' in (yield bitcoind.rpc_help()) and
+ 'novacoinaddress' in (yield bitcoind.rpc_help()) and
not (yield bitcoind.rpc_getinfo())['testnet']
)),
- SUBSIDY_FUNC=lambda height: 50*100000000 >> (height + 1)//210000,
- POW_FUNC=data.hash256,
- BLOCK_PERIOD=600, # s
- SYMBOL='BTC',
- CONF_FILE_FUNC=lambda: os.path.join(os.path.join(os.environ['APPDATA'], 'Bitcoin') if platform.system() == 'Windows' else os.path.expanduser('~/Library/Application Support/Bitcoin/') if platform.system() == 'Darwin' else os.path.expanduser('~/.bitcoin'), 'bitcoin.conf'),
- BLOCK_EXPLORER_URL_PREFIX='http://blockexplorer.com/block/',
- ADDRESS_EXPLORER_URL_PREFIX='http://blockexplorer.com/address/',
- SANE_TARGET_RANGE=(2**256//2**32//1000 - 1, 2**256//2**32 - 1),
- ),
- bitcoin_testnet=math.Object(
- P2P_PREFIX='0b110907'.decode('hex'),
- P2P_PORT=18333,
- ADDRESS_VERSION=111,
- RPC_PORT=18332,
- RPC_CHECK=defer.inlineCallbacks(lambda bitcoind: defer.returnValue(
- 'bitcoinaddress' in (yield bitcoind.rpc_help()) and
- (yield bitcoind.rpc_getinfo())['testnet']
- )),
- SUBSIDY_FUNC=lambda height: 50*100000000 >> (height + 1)//210000,
- POW_FUNC=data.hash256,
- BLOCK_PERIOD=600, # s
- SYMBOL='tBTC',
- CONF_FILE_FUNC=lambda: os.path.join(os.path.join(os.environ['APPDATA'], 'Bitcoin') if platform.system() == 'Windows' else os.path.expanduser('~/Library/Application Support/Bitcoin/') if platform.system() == 'Darwin' else os.path.expanduser('~/.bitcoin'), 'bitcoin.conf'),
- BLOCK_EXPLORER_URL_PREFIX='http://blockexplorer.com/testnet/block/',
- ADDRESS_EXPLORER_URL_PREFIX='http://blockexplorer.com/testnet/address/',
- SANE_TARGET_RANGE=(2**256//2**32//1000 - 1, 2**256//2**32 - 1),
- ),
-
- namecoin=math.Object(
- P2P_PREFIX='f9beb4fe'.decode('hex'),
- P2P_PORT=8334,
- ADDRESS_VERSION=52,
- RPC_PORT=8332,
- RPC_CHECK=defer.inlineCallbacks(lambda bitcoind: defer.returnValue(
- 'namecoinaddress' in (yield bitcoind.rpc_help()) and
- not (yield bitcoind.rpc_getinfo())['testnet']
- )),
- SUBSIDY_FUNC=lambda height: 50*100000000 >> (height + 1)//210000,
- POW_FUNC=data.hash256,
- BLOCK_PERIOD=600, # s
- SYMBOL='NMC',
- CONF_FILE_FUNC=lambda: os.path.join(os.path.join(os.environ['APPDATA'], 'Namecoin') if platform.system() == 'Windows' else os.path.expanduser('~/Library/Application Support/Namecoin/') if platform.system() == 'Darwin' else os.path.expanduser('~/.namecoin'), 'bitcoin.conf'),
- BLOCK_EXPLORER_URL_PREFIX='http://explorer.dot-bit.org/b/',
- ADDRESS_EXPLORER_URL_PREFIX='http://explorer.dot-bit.org/a/',
- SANE_TARGET_RANGE=(2**256//2**32 - 1, 2**256//2**32 - 1),
- ),
- namecoin_testnet=math.Object(
- P2P_PREFIX='fabfb5fe'.decode('hex'),
- P2P_PORT=18334,
- ADDRESS_VERSION=111,
- RPC_PORT=8332,
- RPC_CHECK=defer.inlineCallbacks(lambda bitcoind: defer.returnValue(
- 'namecoinaddress' in (yield bitcoind.rpc_help()) and
- (yield bitcoind.rpc_getinfo())['testnet']
- )),
- SUBSIDY_FUNC=lambda height: 50*100000000 >> (height + 1)//210000,
- POW_FUNC=data.hash256,
- BLOCK_PERIOD=600, # s
- SYMBOL='tNMC',
- CONF_FILE_FUNC=lambda: os.path.join(os.path.join(os.environ['APPDATA'], 'Namecoin') if platform.system() == 'Windows' else os.path.expanduser('~/Library/Application Support/Namecoin/') if platform.system() == 'Darwin' else os.path.expanduser('~/.namecoin'), 'bitcoin.conf'),
- BLOCK_EXPLORER_URL_PREFIX='http://testnet.explorer.dot-bit.org/b/',
- ADDRESS_EXPLORER_URL_PREFIX='http://testnet.explorer.dot-bit.org/a/',
- SANE_TARGET_RANGE=(2**256//2**32 - 1, 2**256//2**32 - 1),
- ),
-
- litecoin=math.Object(
- P2P_PREFIX='fbc0b6db'.decode('hex'),
- P2P_PORT=9333,
- ADDRESS_VERSION=48,
- RPC_PORT=9332,
- RPC_CHECK=defer.inlineCallbacks(lambda bitcoind: defer.returnValue(
- 'litecoinaddress' in (yield bitcoind.rpc_help()) and
- not (yield bitcoind.rpc_getinfo())['testnet']
- )),
- SUBSIDY_FUNC=lambda height: 50*100000000 >> (height + 1)//840000,
+ SUBSIDY_FUNC=lambda target: get_subsidy(6, 100, target),
+ BLOCKHASH_FUNC=lambda data: pack.IntType(256).unpack(__import__('ltc_scrypt').getPoWHash(data)),
POW_FUNC=lambda data: pack.IntType(256).unpack(__import__('ltc_scrypt').getPoWHash(data)),
- BLOCK_PERIOD=150, # s
- SYMBOL='LTC',
- CONF_FILE_FUNC=lambda: os.path.join(os.path.join(os.environ['APPDATA'], 'Litecoin') if platform.system() == 'Windows' else os.path.expanduser('~/Library/Application Support/Litecoin/') if platform.system() == 'Darwin' else os.path.expanduser('~/.litecoin'), 'litecoin.conf'),
- BLOCK_EXPLORER_URL_PREFIX='http://explorer.litecoin.net/block/',
- ADDRESS_EXPLORER_URL_PREFIX='http://explorer.litecoin.net/address/',
+ BLOCK_PERIOD=600, # s
+ SYMBOL='NVC',
+ CONF_FILE_FUNC=lambda: os.path.join(os.path.join(os.environ['APPDATA'], 'NovaCoin') if platform.system() == 'Windows' else os.path.expanduser('~/Library/Application Support/NovaCoin/') if platform.system() == 'Darwin' else os.path.expanduser('~/.novacoin'), 'novacoin.conf'),
+ BLOCK_EXPLORER_URL_PREFIX='http://novacoin.ru/block/',
+ ADDRESS_EXPLORER_URL_PREFIX='http://novacoin.ru/address/',
SANE_TARGET_RANGE=(2**256//1000000000 - 1, 2**256//1000 - 1),
),
- litecoin_testnet=math.Object(
- P2P_PREFIX='fcc1b7dc'.decode('hex'),
- P2P_PORT=19333,
+ novacoin_testnet=math.Object(
+ P2P_PREFIX='cdf2c0ef'.decode('hex'),
+ P2P_PORT=17777,
ADDRESS_VERSION=111,
- RPC_PORT=19332,
+ RPC_PORT=8344,
RPC_CHECK=defer.inlineCallbacks(lambda bitcoind: defer.returnValue(
- 'litecoinaddress' in (yield bitcoind.rpc_help()) and
+ 'novacoinaddress' in (yield bitcoind.rpc_help()) and
(yield bitcoind.rpc_getinfo())['testnet']
)),
- SUBSIDY_FUNC=lambda height: 50*100000000 >> (height + 1)//840000,
+ SUBSIDY_FUNC=lambda target: get_subsidy(6, 100, target),
+ BLOCKHASH_FUNC=lambda data: pack.IntType(256).unpack(__import__('ltc_scrypt').getPoWHash(data)),
POW_FUNC=lambda data: pack.IntType(256).unpack(__import__('ltc_scrypt').getPoWHash(data)),
- BLOCK_PERIOD=150, # s
- SYMBOL='tLTC',
- CONF_FILE_FUNC=lambda: os.path.join(os.path.join(os.environ['APPDATA'], 'Litecoin') if platform.system() == 'Windows' else os.path.expanduser('~/Library/Application Support/Litecoin/') if platform.system() == 'Darwin' else os.path.expanduser('~/.litecoin'), 'litecoin.conf'),
- BLOCK_EXPLORER_URL_PREFIX='http://nonexistent-litecoin-testnet-explorer/block/',
- ADDRESS_EXPLORER_URL_PREFIX='http://nonexistent-litecoin-testnet-explorer/address/',
- SANE_TARGET_RANGE=(2**256//1000000000 - 1, 2**256 - 1),
- ),
-
- terracoin=math.Object(
- P2P_PREFIX='42babe56'.decode('hex'),
- P2P_PORT=13333,
- ADDRESS_VERSION=0,
- RPC_PORT=13332,
- RPC_CHECK=defer.inlineCallbacks(lambda bitcoind: defer.returnValue(
- 'terracoinaddress' in (yield bitcoind.rpc_help()) and
- not (yield bitcoind.rpc_getinfo())['testnet']
- )),
- SUBSIDY_FUNC=lambda height: 20*100000000 >> (height + 1)//1050000,
- POW_FUNC=data.hash256,
- BLOCK_PERIOD=120, # s
- SYMBOL='TRC',
- CONF_FILE_FUNC=lambda: os.path.join(os.path.join(os.environ['APPDATA'], 'Terracoin') if platform.system() == 'Windows' else os.path.expanduser('~/Library/Application Support/Terracoin/') if platform.system() == 'Darwin' else os.path.expanduser('~/.terracoin'), 'terracoin.conf'),
- BLOCK_EXPLORER_URL_PREFIX='http://cryptocoinexplorer.com:3750/block/',
- ADDRESS_EXPLORER_URL_PREFIX='http://cryptocoinexplorer.com:3750/address/',
- SANE_TARGET_RANGE=(2**256//2**32//1000 - 1, 2**256//2**32 - 1),
- ),
- terracoin_testnet=math.Object(
- P2P_PREFIX='41babe56'.decode('hex'),
- P2P_PORT=23333,
- ADDRESS_VERSION=111,
- RPC_PORT=23332,
- RPC_CHECK=defer.inlineCallbacks(lambda bitcoind: defer.returnValue(
- 'terracoinaddress' in (yield bitcoind.rpc_help()) and
- (yield bitcoind.rpc_getinfo())['testnet']
- )),
- SUBSIDY_FUNC=lambda height: 20*100000000 >> (height + 1)//1050000,
- POW_FUNC=data.hash256,
- BLOCK_PERIOD=120, # s
- SYMBOL='tTRC',
- CONF_FILE_FUNC=lambda: os.path.join(os.path.join(os.environ['APPDATA'], 'Terracoin') if platform.system() == 'Windows' else os.path.expanduser('~/Library/Application Support/Terracoin/') if platform.system() == 'Darwin' else os.path.expanduser('~/.terracoin'), 'terracoin.conf'),
- BLOCK_EXPLORER_URL_PREFIX='http://cryptocoinexplorer.com:3750/testnet/block/',
- ADDRESS_EXPLORER_URL_PREFIX='http://cryptocoinexplorer.com:3750/testnet/address/',
- SANE_TARGET_RANGE=(2**256//2**32//1000 - 1, 2**256//2**32 - 1),
+ BLOCK_PERIOD=600, # s
+ SYMBOL='tNVC',
+ CONF_FILE_FUNC=lambda: os.path.join(os.path.join(os.environ['APPDATA'], 'NovaCoin') if platform.system() == 'Windows' else os.path.expanduser('~/Library/Application Support/NovaCoin/') if platform.system() == 'Darwin' else os.path.expanduser('~/.novacoin'), 'novacoin.conf'),
+ BLOCK_EXPLORER_URL_PREFIX='http://nonexistent-novacoin-testnet-explorer/block/',
+ ADDRESS_EXPLORER_URL_PREFIX='http://nonexistent-novacoin-testnet-explorer/address/',
+ SANE_TARGET_RANGE=(2**256//1000000000 - 1, 2**256//1000 - 1),
),
-
)
for net_name, net in nets.iteritems():
net.NAME = net_name
class Protocol(p2protocol.Protocol):
def __init__(self, net):
p2protocol.Protocol.__init__(self, net.P2P_PREFIX, 1000000)
-
+ self.net = net
+
def connectionMade(self):
self.send_version(
version=32200,
('block', bitcoin_data.block_type),
])
def handle_block(self, block):
- block_hash = bitcoin_data.hash256(bitcoin_data.block_header_type.pack(block['header']))
+ block_hash = self.net.BLOCKHASH_FUNC(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'])
def handle_headers(self, headers):
for header in headers:
header = header['header']
- self.get_block_header.got_response(bitcoin_data.hash256(bitcoin_data.block_header_type.pack(header)), header)
+ self.get_block_header.got_response(self.net.BLOCKHASH_FUNC(bitcoin_data.block_header_type.pack(header)), header)
self.factory.new_headers.happened([header['header'] for header in headers])
message_ping = pack.ComposedType([])
import random
import sys
import time
+import math
from twisted.python import log
from p2pool.bitcoin import data as bitcoin_data, script, sha256
from p2pool.util import math, forest, pack
+minout = pow(10, 6) / 100;
+
# hashlink
hash_link_type = pack.ComposedType([
SUCCESSOR = None
other_txs = None
-
+
small_block_header_type = pack.ComposedType([
('version', pack.VarIntType()),
('previous_block', pack.PossiblyNoneType(0, pack.IntType(256))),
('previous_share_hash', pack.PossiblyNoneType(0, pack.IntType(256))),
('coinbase', pack.VarStrType()),
('nonce', pack.IntType(32)),
- ('pubkey_hash', pack.IntType(160)),
+ ('pubkey', pack.FixedStrType(33)),
('subsidy', pack.IntType(64)),
('donation', pack.IntType(16)),
('stale_info', pack.EnumType(pack.IntType(8), dict((k, {0: None, 253: 'orphan', 254: 'doa'}.get(k, 'unk%i' % (k,))) for k in xrange(256)))),
('identifier', pack.FixedStrType(64//8)),
('share_info', share_info_type),
])
-
- gentx_before_refhash = pack.VarStrType().pack(DONATION_SCRIPT) + pack.IntType(64).pack(0) + pack.VarStrType().pack('\x24' + pack.IntType(256).pack(0) + pack.IntType(32).pack(0))[:2]
-
+
+
+ gentx_before_refhash = pack.VarStrType().pack(DONATION_SCRIPT) + pack.IntType(64).pack(minout) + pack.VarStrType().pack('\x24' + pack.IntType(256).pack(0) + pack.IntType(32).pack(0))[:2]
+
@classmethod
def generate_transaction(cls, tracker, share_data, block_target, desired_timestamp, desired_target, ref_merkle_link, desired_other_transaction_hashes_and_fees, net, known_txs=None, last_txout_nonce=0, base_subsidy=None):
previous_share = tracker.items[share_data['previous_share_hash']] if share_data['previous_share_hash'] is not None else None
-
+
+ def get_coinbase_fee(outpointsnum):
+ # calculate neccessary coinbase fee
+ coinbase_size = 59 + outpointsnum * 44 + 50
+
+ # if coinbase size is greater than 1000 bytes, it should pay fee (0.01 per 1000 bytes)
+ if coinbase_size > 1000:
+ return floor(coinbase_size / 1000.0) * minout
+
+ return 0
+
+ if base_subsidy is None:
+ base_subsidy = net.PARENT.SUBSIDY_FUNC(block_target)
+
+ # current user payout script
+ this_script = bitcoin_data.pubkey_to_script2(share_data['pubkey'])
+
height, last = tracker.get_height_and_last(share_data['previous_share_hash'])
assert height >= net.REAL_CHAIN_LENGTH or last is None
if height < net.TARGET_LOOKBEHIND:
pre_target3 = math.clip(pre_target2, (net.MIN_TARGET, net.MAX_TARGET))
max_bits = bitcoin_data.FloatingInteger.from_target_upper_bound(pre_target3)
bits = bitcoin_data.FloatingInteger.from_target_upper_bound(math.clip(desired_target, (pre_target3//10, pre_target3)))
-
+
new_transaction_hashes = []
new_transaction_size = 0
transaction_hash_refs = []
other_transaction_hashes = []
-
+
past_shares = list(tracker.get_chain(share_data['previous_share_hash'], min(height, 100)))
tx_hash_to_this = {}
for i, share in enumerate(past_shares):
this = [0, len(new_transaction_hashes)-1]
transaction_hash_refs.extend(this)
other_transaction_hashes.append(tx_hash)
-
+
included_transactions = set(other_transaction_hashes)
- removed_fees = [fee for tx_hash, fee in desired_other_transaction_hashes_and_fees if tx_hash not in included_transactions]
- definite_fees = sum(0 if fee is None else fee for tx_hash, fee in desired_other_transaction_hashes_and_fees if tx_hash in included_transactions)
- if None not in removed_fees:
- share_data = dict(share_data, subsidy=share_data['subsidy'] - sum(removed_fees))
- else:
- assert base_subsidy is not None
- share_data = dict(share_data, subsidy=base_subsidy + definite_fees)
-
+
+ share_data = dict(share_data, subsidy=base_subsidy)
+
weights, total_weight, donation_weight = tracker.get_cumulative_weights(share_data['previous_share_hash'],
min(height, net.REAL_CHAIN_LENGTH),
65535*net.SPREAD*bitcoin_data.target_to_average_attempts(block_target),
)
+
+ # calculate "raw" subsidy
+ raw_subsidy = share_data['subsidy'] - 3 * minout - get_coinbase_fee(len(weights))
+
+ # calculate "raw" amounts
+ raw_amounts = dict((script, raw_subsidy*weight//total_weight) for script, weight in weights.iteritems())
+
+ total_remowed_weight = 0
+
+ # iterate list and collect all weights, which produces less than 0.01 payout
+ # it's neccessary due to NVC/PPC protocol-level limitations for coinbase outpoint size
+ for x in raw_amounts.keys():
+ if raw_amounts[x] < minout and x not in [this_script, DONATION_SCRIPT]:
+ total_remowed_weight = total_remowed_weight + weights[x]
+ del weights[x]
+
+ total_weight = total_weight - total_remowed_weight
assert total_weight == sum(weights.itervalues()) + donation_weight, (total_weight, sum(weights.itervalues()) + donation_weight)
-
- amounts = dict((script, share_data['subsidy']*(199*weight)//(200*total_weight)) for script, weight in weights.iteritems()) # 99.5% goes according to weights prior to this share
- this_script = bitcoin_data.pubkey_hash_to_script2(share_data['pubkey_hash'])
- amounts[this_script] = amounts.get(this_script, 0) + share_data['subsidy']//200 # 0.5% goes to block finder
- amounts[DONATION_SCRIPT] = amounts.get(DONATION_SCRIPT, 0) + share_data['subsidy'] - sum(amounts.itervalues()) # all that's left over is the donation weight and some extra satoshis due to rounding
-
- if sum(amounts.itervalues()) != share_data['subsidy'] or any(x < 0 for x in amounts.itervalues()):
+
+
+ # base subsidy value calculated as:
+ # [subsidy - (0.01 for donation + 0.01 for current user + 0.01 for p2pool outpoint) - netfee]
+ my_subsidy = share_data['subsidy'] - 3 * minout - get_coinbase_fee(len(weights) + 1)
+
+ # subsidy goes according to weights prior to this share
+ amounts = dict((script, my_subsidy*weight//total_weight) for script, weight in weights.iteritems())
+
+ # all that's left over is the donation weight and some extra satoshis due to rounding
+ amounts[DONATION_SCRIPT] = amounts.get(DONATION_SCRIPT, 0) + my_subsidy - sum(amounts.itervalues())
+
+ if sum(amounts.itervalues()) != my_subsidy or any(x < 0 for x in amounts.itervalues()):
raise ValueError()
-
+
+ # add 0.01 coin to donation, to satisfy the protocol
+ amounts[DONATION_SCRIPT] = amounts[DONATION_SCRIPT] + minout
+
+ # add 0.01 to current user output, to satisfy the protocol
+ amounts[this_script] = amounts.get(this_script, 0) + minout
+
+# print amounts
+
dests = sorted(amounts.iterkeys(), key=lambda script: (script == DONATION_SCRIPT, amounts[script], script))[-4000:] # block length limit, unlikely to ever be hit
-
+
+# print dests
+
share_info = dict(
share_data=share_data,
far_share_hash=None if last is None and height < 99 else tracker.get_nth_parent_hash(share_data['previous_share_hash'], 99),
new_transaction_hashes=new_transaction_hashes,
transaction_hash_refs=transaction_hash_refs,
)
-
+
gentx = dict(
version=1,
+ # coinbase timestamp must be older than share/block timestamp
+ # maybe there are more elegant solution, but this hack works quite well for now
+ timestamp=share_info['timestamp'],
tx_ins=[dict(
previous_output=None,
sequence=None,
script=share_data['coinbase'],
)],
tx_outs=[dict(value=amounts[script], script=script) for script in dests if amounts[script] or script == DONATION_SCRIPT] + [dict(
- value=0,
+ # add 0.01 coin to service output, to satisfy the protocol
+ value=minout,
script='\x24' + cls.get_ref_hash(net, share_info, ref_merkle_link) + pack.IntType(32).pack(last_txout_nonce),
)],
lock_time=0,
)
-
+
+ #print gentx
+
def get_share(header, last_txout_nonce=last_txout_nonce):
min_header = dict(header); del min_header['merkle_root']
share = cls(net, None, dict(
self.target = self.share_info['bits'].target
self.timestamp = self.share_info['timestamp']
self.previous_hash = self.share_data['previous_share_hash']
- self.new_script = bitcoin_data.pubkey_hash_to_script2(self.share_data['pubkey_hash'])
+ self.new_script = bitcoin_data.pubkey_to_script2(self.share_data['pubkey'])
self.desired_version = self.share_data['desired_version']
n = set()
merkle_root = bitcoin_data.check_merkle_link(self.gentx_hash, self.merkle_link)
self.header = dict(self.min_header, merkle_root=merkle_root)
self.pow_hash = net.PARENT.POW_FUNC(bitcoin_data.block_header_type.pack(self.header))
- self.hash = self.header_hash = bitcoin_data.hash256(bitcoin_data.block_header_type.pack(self.header))
+ self.hash = self.header_hash = net.PARENT.BLOCKHASH_FUNC(bitcoin_data.block_header_type.pack(self.header))
if self.target > net.MAX_TARGET:
from p2pool import p2p
if self.pow_hash > self.target:
from p2pool import p2p
raise p2p.PeerMisbehavingError('share PoW invalid')
-
+
self.new_transaction_hashes = self.share_info['new_transaction_hashes']
# XXX eww
raise p2p.PeerMisbehavingError('''%s can't follow %s''' % (type(self).__name__, type(previous_share).__name__))
other_tx_hashes = [tracker.items[tracker.get_nth_parent_hash(self.hash, share_count)].share_info['new_transaction_hashes'][tx_count] for share_count, tx_count in self.iter_transaction_hash_refs()]
-
- share_info, gentx, other_tx_hashes2, get_share = self.generate_transaction(tracker, self.share_info['share_data'], self.header['bits'].target, self.share_info['timestamp'], self.share_info['bits'].target, self.contents['ref_merkle_link'], [(h, None) for h in other_tx_hashes], self.net, last_txout_nonce=self.contents['last_txout_nonce'])
+# print self
+
+ share_info, gentx, other_tx_hashes2, get_share = self.generate_transaction(
+ tracker,
+ self.share_info['share_data'],
+ self.header['bits'].target,
+ self.share_info['timestamp'],
+ self.share_info['bits'].target,
+ self.contents['ref_merkle_link'],
+ [(h, None) for h in other_tx_hashes],
+ self.net,
+ last_txout_nonce=self.contents['last_txout_nonce'],
+ base_subsidy=None
+ )
+
assert other_tx_hashes2 == other_tx_hashes
if share_info != self.share_info:
+ print share_info, self.share_info
raise ValueError('share_info invalid')
if bitcoin_data.hash256(bitcoin_data.tx_type.pack(gentx)) != self.gentx_hash:
raise ValueError('''gentx doesn't match hash_link''')
other_txs = self._get_other_txs(tracker, known_txs)
if other_txs is None:
return None # not all txs present
- return dict(header=self.header, txs=[self.check(tracker)] + other_txs)
+ return dict(header=self.header, txs=[self.check(tracker)] + other_txs, signature='')
class WeightsSkipList(forest.TrackerSkipList):
def get_user_stale_props(tracker, share_hash, lookbehind):
res = {}
for share in tracker.get_chain(share_hash, lookbehind - 1):
- stale, total = res.get(share.share_data['pubkey_hash'], (0, 0))
+ stale, total = res.get(share.share_data['pubkey'], (0, 0))
total += 1
if share.share_data['stale_info'] is not None:
stale += 1
total += 1
- res[share.share_data['pubkey_hash']] = stale, total
- return dict((pubkey_hash, stale/total) for pubkey_hash, (stale, total) in res.iteritems())
+ res[share.share_data['pubkey']] = stale, total
+ return dict((pubkey, stale/total) for pubkey, (stale, total) in res.iteritems())
+
+def calculate_payout(weight, total_weight, subsidy):
+ global minout
+
+ payout = (subsidy - 3*minout) * weight//total_weight
+
+ if payout < minout:
+ payout = 0
+
+ return payout
def get_expected_payouts(tracker, best_share_hash, block_target, subsidy, net):
+
weights, total_weight, donation_weight = tracker.get_cumulative_weights(best_share_hash, min(tracker.get_height(best_share_hash), net.REAL_CHAIN_LENGTH), 65535*net.SPREAD*bitcoin_data.target_to_average_attempts(block_target))
- res = dict((script, subsidy*weight//total_weight) for script, weight in weights.iteritems())
+
+ #res = dict((script, subsidy*weight//total_weight) for script, weight in weights.iteritems())
+
+ res = dict((script, calculate_payout(weight, total_weight, subsidy)) for script, weight in weights.iteritems())
res[DONATION_SCRIPT] = res.get(DONATION_SCRIPT, 0) + subsidy - sum(res.itervalues())
+
return res
def get_desired_version_counts(tracker, best_share_hash, dist):
if '--iocp' in sys.argv:
from twisted.internet import iocpreactor
iocpreactor.install()
-from twisted.internet import defer, reactor, protocol, task, tcp
+from twisted.internet import defer, reactor, protocol, task
from twisted.web import server
from twisted.python import log
from nattraverso import portmapper, ipdiscover
factory = yield connect_p2p()
print 'Determining payout address...'
- if args.pubkey_hash is None:
- address_path = os.path.join(datadir_path, 'cached_payout_address')
-
- if os.path.exists(address_path):
- with open(address_path, 'rb') as f:
- address = f.read().strip('\r\n')
- print ' Loaded cached address: %s...' % (address,)
- else:
- address = None
-
- if address is not None:
- res = yield deferral.retry('Error validating cached address:', 5)(lambda: bitcoind.rpc_validateaddress(address))()
+ pubkey_path = os.path.join(datadir_path, 'cached_payout_pubkey')
+
+ if os.path.exists(pubkey_path):
+ with open(pubkey_path, 'rb') as f:
+ pubkey = f.read().strip('\r\n')
+ print ' Loaded cached pubkey, payout address: %s...' % (bitcoin_data.pubkey_to_address(pubkey.decode('hex'), net.PARENT),)
+ else:
+ pubkey = None
+
+ if pubkey is not None:
+ res = yield deferral.retry('Error validating cached pubkey:', 5)(lambda: bitcoind.rpc_validatepubkey(pubkey))()
if not res['isvalid'] or not res['ismine']:
- print ' Cached address is either invalid or not controlled by local bitcoind!'
+ print ' Cached pubkey is either invalid or not controlled by local bitcoind!'
address = None
+
+ if pubkey is None:
+ print ' Getting payout pubkey from bitcoind...'
+ pubkey = yield deferral.retry('Error getting payout pubkey from bitcoind:', 5)(lambda: bitcoind.rpc_getnewpubkey('p2pool'))()
- if address is None:
- print ' Getting payout address from bitcoind...'
- address = yield deferral.retry('Error getting payout address from bitcoind:', 5)(lambda: bitcoind.rpc_getaccountaddress('p2pool'))()
-
- with open(address_path, 'wb') as f:
- f.write(address)
-
- my_pubkey_hash = bitcoin_data.address_to_pubkey_hash(address, net.PARENT)
- else:
- my_pubkey_hash = args.pubkey_hash
+ with open(pubkey_path, 'wb') as f:
+ f.write(pubkey)
+
+ my_pubkey = pubkey.decode('hex')
+
+ address = bitcoin_data.pubkey_to_address(my_pubkey, net.PARENT)
+
+ my_pubkey_hash = bitcoin_data.address_to_pubkey_hash(address, net.PARENT)
print ' ...success! Payout address:', bitcoin_data.pubkey_hash_to_address(my_pubkey_hash, net.PARENT)
print
print 'Listening for workers on %r port %i...' % (worker_endpoint[0], worker_endpoint[1])
- wb = work.WorkerBridge(node, my_pubkey_hash, args.donation_percentage, merged_urls, args.worker_fee)
+ wb = work.WorkerBridge(node, my_pubkey, args.donation_percentage, merged_urls, args.worker_fee)
web_root = web.get_web_root(wb, datadir_path, bitcoind_warning_var)
caching_wb = worker_interface.CachingWorkerBridge(wb)
worker_interface.WorkerInterface(caching_wb).attach_to(web_root, get_handler=lambda request: request.redirect('/static/'))
shares, stale_orphan_shares, stale_doa_shares,
math.format_binomial_conf(stale_orphan_shares + stale_doa_shares, shares, 0.95),
math.format_binomial_conf(stale_orphan_shares + stale_doa_shares, shares, 0.95, lambda x: (1 - x)/(1 - stale_prop)),
- node.get_current_txouts().get(bitcoin_data.pubkey_hash_to_script2(my_pubkey_hash), 0)*1e-8, net.PARENT.SYMBOL,
+ node.get_current_txouts().get(bitcoin_data.pubkey_to_script2(my_pubkey), 0) * 1e-6, net.PARENT.SYMBOL,
)
this_str += '\n Pool: %sH/s Stale rate: %.1f%% Expected time to block: %s' % (
math.format(int(real_att_s)),
log.err(None, 'Fatal error:')
def run():
- if not hasattr(tcp.Client, 'abortConnection'):
- print "Twisted doesn't have abortConnection! Upgrade to a newer version of Twisted to avoid memory leaks!"
- print 'Pausing for 3 seconds...'
- time.sleep(3)
-
realnets = dict((name, net) for name, net in networks.nets.iteritems() if '_testnet' not in name)
parser = fixargparse.FixedArgumentParser(description='p2pool (version %s)' % (p2pool.__version__,), fromfile_prefix_chars='@')
else:
addr, port = args.worker_endpoint.rsplit(':', 1)
worker_endpoint = addr, int(port)
-
- if args.address is not None:
- try:
- args.pubkey_hash = bitcoin_data.address_to_pubkey_hash(args.address, net.PARENT)
- except Exception, e:
- parser.error('error parsing address: ' + repr(e))
- else:
- args.pubkey_hash = None
-
+
def separate_url(url):
s = urlparse.urlsplit(url)
if '@' not in s.netloc:
# changes can be done by changing one, then the other
nets = dict(
- bitcoin=math.Object(
- PARENT=networks.nets['bitcoin'],
+ novacoin=math.Object(
+ PARENT=networks.nets['novacoin'],
SHARE_PERIOD=10, # seconds
CHAIN_LENGTH=24*60*60//10, # shares
REAL_CHAIN_LENGTH=24*60*60//10, # shares
TARGET_LOOKBEHIND=200, # shares
SPREAD=3, # blocks
- IDENTIFIER='fc70035c7a81bc6f'.decode('hex'),
- PREFIX='2472ef181efcd37b'.decode('hex'),
- P2P_PORT=9333,
- MIN_TARGET=0,
- MAX_TARGET=2**256//2**32 - 1,
- PERSIST=True,
- WORKER_PORT=9332,
- BOOTSTRAP_ADDRS='forre.st vps.forre.st 74.220.242.6:9334 93.97.192.93 66.90.73.83 67.83.108.0 219.84.64.174 24.167.17.248 109.74.195.142 83.211.86.49 94.23.34.145 168.7.116.243 94.174.40.189:9344 89.79.79.195 portals94.ns01.us'.split(' '),
- ANNOUNCE_CHANNEL='#p2pool',
- VERSION_CHECK=lambda v: 50700 <= v < 60000 or 60010 <= v < 60100 or 60400 <= v,
- ),
- bitcoin_testnet=math.Object(
- PARENT=networks.nets['bitcoin_testnet'],
- SHARE_PERIOD=10, # seconds
- CHAIN_LENGTH=60*60//10, # shares
- REAL_CHAIN_LENGTH=60*60//10, # shares
- TARGET_LOOKBEHIND=200, # shares
- SPREAD=3, # blocks
- IDENTIFIER='5fc2be2d4f0d6bfb'.decode('hex'),
- PREFIX='3f6057a15036f441'.decode('hex'),
- P2P_PORT=19333,
- MIN_TARGET=0,
- MAX_TARGET=2**256//2**32 - 1,
- PERSIST=False,
- WORKER_PORT=19332,
- BOOTSTRAP_ADDRS='forre.st vps.forre.st liteco.in'.split(' '),
- ANNOUNCE_CHANNEL='#p2pool-alt',
- VERSION_CHECK=lambda v: 50700 <= v < 60000 or 60010 <= v < 60100 or 60400 <= v,
- ),
-
- litecoin=math.Object(
- PARENT=networks.nets['litecoin'],
- SHARE_PERIOD=10, # seconds
- CHAIN_LENGTH=24*60*60//10, # shares
- REAL_CHAIN_LENGTH=24*60*60//10, # shares
- TARGET_LOOKBEHIND=200, # shares
- SPREAD=12, # blocks
- IDENTIFIER='e037d5b8c6923410'.decode('hex'),
- PREFIX='7208c1a53ef629b0'.decode('hex'),
- P2P_PORT=9338,
+ IDENTIFIER='e037d5b8c6923510'.decode('hex'),
+ PREFIX='7208c1a53ef649b0'.decode('hex'),
+ P2P_PORT=9777,
MIN_TARGET=0,
MAX_TARGET=2**256//2**20 - 1,
PERSIST=True,
- WORKER_PORT=9327,
- BOOTSTRAP_ADDRS='forre.st vps.forre.st 199.255.95.94 75.12.89.18 181.28.244.151 83.142.189.132 66.90.82.155:11332 201.57.241.77 80.222.255.91 142.68.214.29 24.52.247.82 72.230.179.177 94.127.200.29 200.204.161.215 91.121.9.7 91.235.254.37 198.154.98.195 178.79.136.10'.split(' '),
+ WORKER_PORT=8336,
+ BOOTSTRAP_ADDRS='188.120.239.144'.split(' '),
ANNOUNCE_CHANNEL='#p2pool-alt',
VERSION_CHECK=lambda v: True,
),
- litecoin_testnet=math.Object(
- PARENT=networks.nets['litecoin_testnet'],
+ novacoin_testnet=math.Object(
+ PARENT=networks.nets['novacoin_testnet'],
SHARE_PERIOD=3, # seconds
CHAIN_LENGTH=20*60//3, # shares
REAL_CHAIN_LENGTH=20*60//3, # shares
TARGET_LOOKBEHIND=200, # shares
SPREAD=12, # blocks
- IDENTIFIER='cca5e24ec6408b1e'.decode('hex'),
- PREFIX='ad9614f6466a39cf'.decode('hex'),
- P2P_PORT=19338,
+ IDENTIFIER='e037d5b8c7923510'.decode('hex'),
+ PREFIX='7208c1a54ef649b0'.decode('hex'),
+ P2P_PORT=19777,
MIN_TARGET=0,
- MAX_TARGET=2**256//2000 - 1,
- PERSIST=False,
- WORKER_PORT=19327,
- BOOTSTRAP_ADDRS='forre.st vps.forre.st'.split(' '),
- ANNOUNCE_CHANNEL='#p2pool-alt',
- VERSION_CHECK=lambda v: True,
- ),
-
- terracoin=math.Object(
- PARENT=networks.nets['terracoin'],
- SHARE_PERIOD=30, # seconds
- CHAIN_LENGTH=24*60*60//30, # shares
- REAL_CHAIN_LENGTH=24*60*60//30, # shares
- TARGET_LOOKBEHIND=200, # shares
- SPREAD=15, # blocks
- IDENTIFIER='a41b2356a1b7d35e'.decode('hex'),
- PREFIX='5623b62178d2b8a3'.decode('hex'),
- P2P_PORT=9323,
- MIN_TARGET=0,
- MAX_TARGET=2**256//2**32 - 1,
- PERSIST=True,
- WORKER_PORT=9322,
- BOOTSTRAP_ADDRS='seed1.p2pool.terracoin.org seed2.p2pool.terracoin.org forre.st vps.forre.st 93.97.192.93 66.90.73.83 67.83.108.0 219.84.64.174 24.167.17.248 109.74.195.142 83.211.86.49 94.23.34.145 168.7.116.243 94.174.40.189:9344 89.79.79.195 portals94.ns01.us'.split(' '),
- ANNOUNCE_CHANNEL='#p2pool-alt',
- VERSION_CHECK=lambda v: True,
- ),
- terracoin_testnet=math.Object(
- PARENT=networks.nets['terracoin_testnet'],
- SHARE_PERIOD=30, # seconds
- CHAIN_LENGTH=60*60//30, # shares
- REAL_CHAIN_LENGTH=60*60//30, # shares
- TARGET_LOOKBEHIND=200, # shares
- SPREAD=15, # blocks
- IDENTIFIER='b41b2356a5b7d35d'.decode('hex'),
- PREFIX='1623b92172d2b8a2'.decode('hex'),
- P2P_PORT=19323,
- MIN_TARGET=0,
- MAX_TARGET=2**256//2**32 - 1,
+ MAX_TARGET=2**256//2**20 - 1,
PERSIST=False,
- WORKER_PORT=19322,
- BOOTSTRAP_ADDRS='seed1.p2pool.terracoin.org seed2.p2pool.terracoin.org forre.st vps.forre.st'.split(' '),
+ WORKER_PORT=18336,
+ BOOTSTRAP_ADDRS='188.120.239.144'.split(' '),
ANNOUNCE_CHANNEL='#p2pool-alt',
VERSION_CHECK=lambda v: True,
),
-
)
for net_name, net in nets.iteritems():
net.NAME = net_name
if (self.best_block_header.value is None
or (
new_header['previous_block'] == bitcoind_best_block and
- bitcoin_data.hash256(bitcoin_data.block_header_type.pack(self.best_block_header.value)) == bitcoind_best_block
+ self.net.PARENT.BLOCKHASH_FUNC(bitcoin_data.block_header_type.pack(self.best_block_header.value)) == bitcoind_best_block
) # new is child of current and previous is current
or (
- bitcoin_data.hash256(bitcoin_data.block_header_type.pack(new_header)) == bitcoind_best_block and
+ self.net.PARENT.BLOCKHASH_FUNC(bitcoin_data.block_header_type.pack(new_header)) == bitcoind_best_block and
self.best_block_header.value['previous_block'] != bitcoind_best_block
)): # new is current and previous is not a child of current
self.best_block_header.set(new_header)
@self.tracker.verified.added.watch
def _(share):
+ if share.timestamp < share.min_header['timestamp']:
+ return
if not (share.pow_hash <= share.header['bits'].target):
return
-
+
block = share.as_block(self.tracker, self.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), self.net.PARENT.BLOCK_EXPLORER_URL_PREFIX, share.header_hash)
self.n.p2p_node = node.P2PNode(self.n, port=0, max_incoming_conns=1000000, addr_store={}, connect_addrs=[('127.0.0.1', peer_port) for peer_port in peer_ports])
self.n.p2p_node.start()
- wb = work.WorkerBridge(node=self.n, my_pubkey_hash=random.randrange(2**160), donation_percentage=random.uniform(0, 10), merged_urls=merged_urls, worker_fee=3)
+ wb = work.WorkerBridge(node=self.n, my_pubkey=random.randrange(2**520), donation_percentage=random.uniform(0, 10), merged_urls=merged_urls, worker_fee=3)
self.wb = wb
web_root = resource.Resource()
worker_interface.WorkerInterface(wb).attach_to(web_root)
n = node.Node(bitd, bitd, [], [], mynet)
yield n.start()
- wb = work.WorkerBridge(node=n, my_pubkey_hash=42, donation_percentage=2, merged_urls=[('http://127.0.0.1:%i' % (mm_port.getHost().port,), '')], worker_fee=3)
+ wb = work.WorkerBridge(node=n, my_pubkey=42, donation_percentage=2, merged_urls=[('http://127.0.0.1:%i' % (mm_port.getHost().port,), '')], worker_fee=3)
web_root = resource.Resource()
worker_interface.WorkerInterface(wb).attach_to(web_root)
port = reactor.listenTCP(0, server.Site(web_root))
if resp['id'] != id_:
raise ValueError('invalid id')
- if 'error' in resp and resp['error'] is not None:
+ if 'error' in resp and resp['error'] is not None and resp['error']['code'] != -100:
raise Error_for_code(resp['error']['code'])(resp['error']['message'], resp['error'].get('data', None))
defer.returnValue(resp['result'])
HTTPProxy = lambda url, headers={}, timeout=5: Proxy(lambda method, params: _http_do(url, headers, timeout, method, params))
uptime=time.time() - start_time,
attempts_to_share=bitcoin_data.target_to_average_attempts(node.tracker.items[node.best_share_var.value].max_target),
attempts_to_block=bitcoin_data.target_to_average_attempts(node.bitcoind_work.value['bits'].target),
- block_value=node.bitcoind_work.value['subsidy']*1e-8,
+ block_value=node.bitcoind_work.value['subsidy']*1e-6,
warnings=p2pool_data.get_warnings(node.tracker, node.best_share_var.value, node.net, bitcoind_warning_var.value, node.bitcoind_work.value),
donation_proportion=wb.donation_percentage/100,
)
request.setHeader('Access-Control-Allow-Origin', '*')
res = yield self.func(*self.args)
defer.returnValue(json.dumps(res) if self.mime_type == 'application/json' else res)
-
+
def decent_height():
return min(node.tracker.get_height(node.best_share_var.value), 720)
web_root.putChild('rate', WebInterface(lambda: p2pool_data.get_pool_attempts_per_second(node.tracker, node.best_share_var.value, decent_height())/(1-p2pool_data.get_average_stale_prop(node.tracker, node.best_share_var.value, decent_height()))))
web_root.putChild('difficulty', WebInterface(lambda: bitcoin_data.target_to_difficulty(node.tracker.items[node.best_share_var.value].max_target)))
web_root.putChild('users', WebInterface(get_users))
- web_root.putChild('user_stales', WebInterface(lambda: dict((bitcoin_data.pubkey_hash_to_address(ph, node.net.PARENT), prop) for ph, prop in
+ web_root.putChild('user_stales', WebInterface(lambda: dict((bitcoin_data.pubkey_to_address(ph, node.net.PARENT), prop) for ph, prop in
p2pool_data.get_user_stale_props(node.tracker, node.best_share_var.value, node.tracker.get_height(node.best_share_var.value)).iteritems())))
web_root.putChild('fee', WebInterface(lambda: wb.worker_fee))
web_root.putChild('current_payouts', WebInterface(lambda: dict((bitcoin_data.script2_to_address(script, node.net.PARENT), value/1e8) for script, value in node.get_current_txouts().iteritems())))
])
))))
web_root.putChild('peer_versions', WebInterface(lambda: dict(('%s:%i' % peer.addr, peer.other_sub_version) for peer in node.p2p_node.peers.itervalues())))
- web_root.putChild('payout_addr', WebInterface(lambda: bitcoin_data.pubkey_hash_to_address(wb.my_pubkey_hash, node.net.PARENT)))
+ web_root.putChild('payout_addr', WebInterface(lambda: bitcoin_data.pubkey_to_address(wb.my_pubkey, node.net.PARENT)))
web_root.putChild('recent_blocks', WebInterface(lambda: [dict(
ts=s.timestamp,
hash='%064x' % s.header_hash,
shares=shares,
stale_shares=stale_orphan_shares + stale_doa_shares,
stale_shares_breakdown=dict(orphan=stale_orphan_shares, doa=stale_doa_shares),
- current_payout=node.get_current_txouts().get(bitcoin_data.pubkey_hash_to_script2(wb.my_pubkey_hash), 0)*1e-8,
+ current_payout=node.get_current_txouts().get(bitcoin_data.pubkey_to_script2(wb.my_pubkey), 0)*1e-6,
peers=dict(
incoming=sum(1 for peer in node.p2p_node.peers.itervalues() if peer.incoming),
outgoing=sum(1 for peer in node.p2p_node.peers.itervalues() if not peer.incoming),
),
attempts_to_share=bitcoin_data.target_to_average_attempts(node.tracker.items[node.best_share_var.value].max_target),
attempts_to_block=bitcoin_data.target_to_average_attempts(node.bitcoind_work.value['bits'].target),
- block_value=node.bitcoind_work.value['subsidy']*1e-8,
+ block_value=node.bitcoind_work.value['subsidy']*1e-6,
))
with open(os.path.join(datadir_path, 'stats'), 'wb') as f:
gentx=dict(
hash='%064x' % share.gentx_hash,
coinbase=share.share_data['coinbase'].ljust(2, '\x00').encode('hex'),
- value=share.share_data['subsidy']*1e-8,
+ value=share.share_data['subsidy']*1e-6,
),
txn_count_range=[len(share.other_txs), len(share.other_txs)] if share.other_txs is not None else 1 if len(share.merkle_link['branch']) == 0 else [2**len(share.merkle_link['branch'])//2+1, 2**len(share.merkle_link['branch'])],
),
hd.datastreams['pool_rates'].add_datum(t, pool_rates)
current_txouts = node.get_current_txouts()
- hd.datastreams['current_payout'].add_datum(t, current_txouts.get(bitcoin_data.pubkey_hash_to_script2(wb.my_pubkey_hash), 0)*1e-8)
+ hd.datastreams['current_payout'].add_datum(t, current_txouts.get(bitcoin_data.pubkey_to_script2(wb.my_pubkey), 0)*1e-6)
miner_hash_rates, miner_dead_hash_rates = get_local_rates()
current_txouts_by_address = dict((bitcoin_data.script2_to_address(script, node.net.PARENT), amount) for script, amount in current_txouts.iteritems())
- hd.datastreams['current_payouts'].add_datum(t, dict((user, current_txouts_by_address[user]*1e-8) for user in miner_hash_rates if user in current_txouts_by_address))
+ hd.datastreams['current_payouts'].add_datum(t, dict((user, current_txouts_by_address[user]*1e-6) for user in miner_hash_rates if user in current_txouts_by_address))
hd.datastreams['incoming_peers'].add_datum(t, sum(1 for peer in node.p2p_node.peers.itervalues() if peer.incoming))
hd.datastreams['outgoing_peers'].add_datum(t, sum(1 for peer in node.p2p_node.peers.itervalues() if not peer.incoming))
class WorkerBridge(worker_interface.WorkerBridge):
COINBASE_NONCE_LENGTH = 4
- def __init__(self, node, my_pubkey_hash, donation_percentage, merged_urls, worker_fee):
+ def __init__(self, node, my_pubkey, donation_percentage, merged_urls, worker_fee):
worker_interface.WorkerBridge.__init__(self)
self.recent_shares_ts_work = []
self.node = node
- self.my_pubkey_hash = my_pubkey_hash
+ self.my_pubkey = my_pubkey
self.donation_percentage = donation_percentage
self.worker_fee = worker_fee
# COMBINE WORK
+
self.current_work = variable.Variable(None)
def compute_work():
t = self.node.bitcoind_work.value
bb = self.node.best_block_header.value
+
+ subsidy = self.node.net.PARENT.SUBSIDY_FUNC(bb['bits'].target)
+
if bb is not None and bb['previous_block'] == t['previous_block'] and self.node.net.PARENT.POW_FUNC(bitcoin_data.block_header_type.pack(bb)) <= t['bits'].target:
print 'Skipping from block %x to block %x!' % (bb['previous_block'],
- bitcoin_data.hash256(bitcoin_data.block_header_type.pack(bb)))
+ self.node.net.PARENT.BLOCKHASH_FUNC(bitcoin_data.block_header_type.pack(bb)))
t = dict(
version=bb['version'],
- previous_block=bitcoin_data.hash256(bitcoin_data.block_header_type.pack(bb)),
+ previous_block=self.node.net.PARENT.BLOCKHASH_FUNC(bitcoin_data.block_header_type.pack(bb)),
bits=bb['bits'], # not always true
coinbaseflags='',
height=t['height'] + 1,
transactions=[],
transaction_fees=[],
merkle_link=bitcoin_data.calculate_merkle_link([None], 0),
- subsidy=self.node.net.PARENT.SUBSIDY_FUNC(self.node.bitcoind_work.value['height']),
+ subsidy=subsidy,
last_update=self.node.bitcoind_work.value['last_update'],
)
except:
pass
- if random.uniform(0, 100) < self.worker_fee:
- pubkey_hash = self.my_pubkey_hash
- else:
- try:
- pubkey_hash = bitcoin_data.address_to_pubkey_hash(user, self.node.net.PARENT)
- except: # XXX blah
- pubkey_hash = self.my_pubkey_hash
+ pubkey = self.my_pubkey
- return user, pubkey_hash, desired_share_target, desired_pseudoshare_target
+ return user, pubkey, desired_share_target, desired_pseudoshare_target
def preprocess_request(self, user):
- user, pubkey_hash, desired_share_target, desired_pseudoshare_target = self.get_user_details(user)
- return pubkey_hash, desired_share_target, desired_pseudoshare_target
+ user, pubkey, desired_share_target, desired_pseudoshare_target = self.get_user_details(user)
+ return pubkey, desired_share_target, desired_pseudoshare_target
- def get_work(self, pubkey_hash, desired_share_target, desired_pseudoshare_target):
+ def get_work(self, pubkey, desired_share_target, desired_pseudoshare_target):
if (self.node.p2p_node is None or len(self.node.p2p_node.peers) == 0) and self.node.net.PERSIST:
raise jsonrpc.Error_for_code(-12345)(u'p2pool is not connected to any peers')
if self.node.best_share_var.value is None and self.node.net.PERSIST:
share_type = previous_share_type
if True:
+ subsidy = self.node.net.PARENT.SUBSIDY_FUNC(self.current_work.value['bits'].target)
+
share_info, gentx, other_transaction_hashes, get_share = share_type.generate_transaction(
tracker=self.node.tracker,
share_data=dict(
] + ([mm_data] if mm_data else []) + [
]) + self.current_work.value['coinbaseflags'])[:100],
nonce=random.randrange(2**32),
- pubkey_hash=pubkey_hash,
+ pubkey=pubkey,
subsidy=self.current_work.value['subsidy'],
donation=math.perfect_round(65535*self.donation_percentage/100),
stale_info=(lambda (orphans, doas), total, (orphans_recorded_in_chain, doas_recorded_in_chain):
desired_other_transaction_hashes_and_fees=zip(tx_hashes, self.current_work.value['transaction_fees']),
net=self.node.net,
known_txs=tx_map,
- base_subsidy=self.node.net.PARENT.SUBSIDY_FUNC(self.current_work.value['height']),
+ base_subsidy=subsidy
)
packed_gentx = bitcoin_data.tx_type.pack(gentx)
print 'New work for worker! Difficulty: %.06f Share difficulty: %.06f Total block value: %.6f %s including %i transactions' % (
bitcoin_data.target_to_difficulty(target),
bitcoin_data.target_to_difficulty(share_info['bits'].target),
- self.current_work.value['subsidy']*1e-8, self.node.net.PARENT.SYMBOL,
+ self.current_work.value['subsidy']*1e-6, self.node.net.PARENT.SYMBOL,
len(self.current_work.value['transactions']),
)
merkle_link=merkle_link,
coinb1=packed_gentx[:-4-4],
coinb2=packed_gentx[-4:],
- timestamp=self.current_work.value['time'],
+ timestamp=gentx['timestamp'],
bits=self.current_work.value['bits'],
share_target=target,
)
new_packed_gentx = packed_gentx[:-4-4] + coinbase_nonce + packed_gentx[-4:] if coinbase_nonce != '\0'*self.COINBASE_NONCE_LENGTH else packed_gentx
new_gentx = bitcoin_data.tx_type.unpack(new_packed_gentx) if coinbase_nonce != '\0'*self.COINBASE_NONCE_LENGTH else gentx
- header_hash = bitcoin_data.hash256(bitcoin_data.block_header_type.pack(header))
+ header_hash = self.node.net.PARENT.BLOCKHASH_FUNC(bitcoin_data.block_header_type.pack(header))
pow_hash = self.node.net.PARENT.POW_FUNC(bitcoin_data.block_header_type.pack(header))
try:
+ if header['timestamp'] > new_gentx['timestamp'] + 3600:
+ print
+ print header['timestamp'], '>', new_gentx['timestamp'] + 3600
+ print 'Coinbase timestamp is too early!'
+ print
+
+ return
+
+ if header['timestamp'] < new_gentx['timestamp']:
+ print
+ print header['timestamp'], '<', new_gentx['timestamp']
+ print 'Block header timestamp is before coinbase timestamp!'
+ print
+ return
+
if pow_hash <= header['bits'].target or p2pool.DEBUG:
- helper.submit_block(dict(header=header, txs=[new_gentx] + other_transactions), False, self.node.factory, self.node.bitcoind, self.node.bitcoind_work, self.node.net)
+ helper.submit_block(dict(header=header, txs=[new_gentx] + other_transactions, signature=''), False, self.node.factory, self.node.bitcoind, self.node.bitcoind_work, self.node.net)
if pow_hash <= header['bits'].target:
print
print 'GOT BLOCK FROM MINER! Passing to bitcoind! %s%064x' % (self.node.net.PARENT.BLOCK_EXPLORER_URL_PREFIX, header_hash)