Skip to content

Commit

Permalink
NVC/PPC protocol changes support
Browse files Browse the repository at this point in the history
  • Loading branch information
alex authored and alex committed Mar 7, 2013
1 parent 77e7e2a commit b683589
Show file tree
Hide file tree
Showing 13 changed files with 298 additions and 380 deletions.
55 changes: 22 additions & 33 deletions README
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Requirements:
Generic:
Bitcoin >=0.6.4
Novacoin >= 0.3.1
ltc_scrypt
Python
Twisted
python-argparse (for Python <=2.6)
Expand All @@ -15,27 +16,9 @@ Requirements:
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
Expand All @@ -50,14 +33,20 @@ Notes for Litecoin:

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
2 changes: 2 additions & 0 deletions p2pool/bitcoin/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ def write(self, file, item):

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)),
Expand Down Expand Up @@ -130,6 +131,7 @@ def write(self, file, item):
block_type = pack.ComposedType([
('header', block_header_type),
('txs', pack.ListType(tx_type)),
('signature', pack.VarStrType()),
])

# merged mining
Expand Down
7 changes: 5 additions & 2 deletions p2pool/bitcoin/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,23 +62,26 @@ def go():
@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
if (not success and success_expected and not ignore_failure) or (success and not success_expected):
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)
182 changes: 46 additions & 136 deletions p2pool/bitcoin/networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,156 +5,66 @@

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
7 changes: 4 additions & 3 deletions p2pool/bitcoin/p2p.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
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,
Expand Down Expand Up @@ -115,7 +116,7 @@ def handle_tx(self, tx):
('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'])

Expand All @@ -125,7 +126,7 @@ def handle_block(self, block):
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([])
Expand Down
Loading

0 comments on commit b683589

Please sign in to comment.