Skip to content

Commit

Permalink
Implement per address and per miner vardiff
Browse files Browse the repository at this point in the history
  • Loading branch information
metalicjames committed Nov 4, 2017
1 parent d7ddaa4 commit d85ac04
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 14 deletions.
10 changes: 10 additions & 0 deletions p2pool/bitcoin/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,16 @@ def difficulty_to_target(difficulty):
assert difficulty >= 0
if difficulty == 0: return 2**256-1
return min(int((0xffff0000 * 2**(256-64) + 1)/difficulty - 1 + 0.5), 2**256-1)

def target_to_difficulty_alt(target, modifier):
assert 0 <= target and isinstance(target, (int, long)), target
if target >= 2**256: warnings.warn('target >= 2**256!')
return ((0xffff0000 * 2**(256-64) + 1)/(target + 1)) * modifier

def difficulty_to_target_alt(difficulty, modifier):
assert difficulty >= 0
if difficulty == 0: return 2**256-1
return min(int((0xffff0000 * 2**(256-64) + 1)/(difficulty / modifier) - 1 + 0.5), 2**256-1)

# human addresses

Expand Down
2 changes: 1 addition & 1 deletion p2pool/bitcoin/networks/vertcoin.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@
ADDRESS_EXPLORER_URL_PREFIX='http://explorer.vtconline.org/address/'
TX_EXPLORER_URL_PREFIX='http://explorer.vtconline.org/tx/'
SANE_TARGET_RANGE=(2**256//1000000000000000000 - 1, 2**256//100000 - 1)
DUMB_SCRYPT_DIFF=256
DUMB_SCRYPT_DIFF=16
DUST_THRESHOLD=0.03e8
2 changes: 1 addition & 1 deletion p2pool/bitcoin/stratum.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def _send_work(self):
self.transport.loseConnection()
return
jobid = str(random.randrange(2**128))
self.other.svc_mining.rpc_set_difficulty(bitcoin_data.target_to_difficulty(x['share_target']) * self.wb.net.DUMB_SCRYPT_DIFF).addErrback(lambda err: None)
self.other.svc_mining.rpc_set_difficulty(bitcoin_data.target_to_difficulty_alt(x['share_target'], self.wb.net.DUMB_SCRYPT_DIFF) * self.wb.net.DUMB_SCRYPT_DIFF).addErrback(lambda err: None)
self.other.svc_mining.rpc_notify(
jobid, # jobid
getwork._swap4(pack.IntType(256).pack(x['previous_block'])).encode('hex'), # prevhash
Expand Down
21 changes: 20 additions & 1 deletion p2pool/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,14 @@ def upnp_thread():

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, args, pubkeys, bitcoind)
#wb = work.WorkerBridge(node, my_pubkey_hash, args.donation_percentage, merged_urls, args.worker_fee, args, pubkeys, bitcoind)
if args.address_share_rate is not None:
share_rate_type = 'address'
share_rate = args.address_share_rate
else:
share_rate_type = 'miner'
share_rate = args.miner_share_rate
wb = work.WorkerBridge(node, my_pubkey_hash, args.donation_percentage, merged_urls, args.worker_fee, args, pubkeys, bitcoind, args.min_difficulty, share_rate, share_rate_type)
web_root = web.get_web_root(wb, datadir_path, bitcoind_getinfo_var, static_dir=args.web_static)
caching_wb = worker_interface.CachingWorkerBridge(wb)
worker_interface.WorkerInterface(caching_wb).attach_to(web_root, get_handler=lambda request: request.redirect('/static/'))
Expand Down Expand Up @@ -517,6 +524,16 @@ def run():
worker_group.add_argument('-f', '--fee', metavar='FEE_PERCENTAGE',
help='''charge workers mining to their own bitcoin address (by setting their miner's username to a bitcoin address) this percentage fee to mine on your p2pool instance. Amount displayed at http://127.0.0.1:WORKER_PORT/fee (default: 0)''',
type=float, action='store', default=0, dest='worker_fee')

worker_group.add_argument('--miner-share-rate', metavar='SHARES_PER_MINUTE',
help='number of psuedoshares per minute for each miner',
type=float, action='store', default=None, dest='miner_share_rate')
worker_group.add_argument('--address-share-rate', metavar='SHARES_PER_MINUTE',
help='number of psuedoshares per minute for each address',
type=float, action='store', default=None, dest='address_share_rate')
worker_group.add_argument('--min-difficulty', metavar='DIFFICULTY',
help='minium difficulty for miners',
type=float, action='store', default=1.0, dest='min_difficulty')

bitcoind_group = parser.add_argument_group('bitcoind interface')
bitcoind_group.add_argument('--bitcoind-config-path', metavar='BITCOIND_CONFIG_PATH',
Expand Down Expand Up @@ -549,6 +566,8 @@ def run():
net_name = args.net_name + ('_testnet' if args.testnet else '')
net = networks.nets[net_name]

args.min_difficulty /= net.PARENT.DUMB_SCRYPT_DIFF

datadir_path = os.path.join((os.path.join(os.path.dirname(sys.argv[0]), 'data') if args.datadir is None else args.datadir), net_name)
if not os.path.exists(datadir_path):
os.makedirs(datadir_path)
Expand Down
66 changes: 55 additions & 11 deletions p2pool/work.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
class WorkerBridge(worker_interface.WorkerBridge):
COINBASE_NONCE_LENGTH = 8

def __init__(self, node, my_pubkey_hash, donation_percentage, merged_urls, worker_fee, args, pubkeys, bitcoind):
def __init__(self, node, my_pubkey_hash, donation_percentage, merged_urls, worker_fee, args, pubkeys, bitcoind, min_difficulty, share_rate, share_rate_type):
worker_interface.WorkerBridge.__init__(self)
self.recent_shares_ts_work = []

Expand All @@ -34,6 +34,10 @@ def __init__(self, node, my_pubkey_hash, donation_percentage, merged_urls, worke
self.donation_percentage = args.donation_percentage
self.worker_fee = args.worker_fee

self.min_difficulty = min_difficulty
self.share_rate = share_rate
self.share_rate_type = share_rate_type

self.net = self.node.net.PARENT
self.running = True
self.pseudoshare_received = variable.Event()
Expand Down Expand Up @@ -175,13 +179,13 @@ def get_user_details(self, username):
for symbol, parameter in zip(contents2[::2], contents2[1::2]):
if symbol == '+':
try:
desired_pseudoshare_target = bitcoin_data.difficulty_to_target(float(parameter))
desired_pseudoshare_target = bitcoin_data.difficulty_to_target_alt(float(parameter), self.node.net.PARENT.DUMB_SCRYPT_DIFF)
except:
if p2pool.DEBUG:
log.err()
elif symbol == '/':
try:
desired_share_target = bitcoin_data.difficulty_to_target(float(parameter))
desired_share_target = bitcoin_data.difficulty_to_target_alt(float(parameter), self.node.net.PARENT.DUMB_SCRYPT_DIFF)
except:
if p2pool.DEBUG:
log.err()
Expand Down Expand Up @@ -211,7 +215,7 @@ def preprocess_request(self, user):
if time.time() > self.current_work.value['last_update'] + 60:
raise jsonrpc.Error_for_code(-12345)(u'lost contact with bitcoind')
user, pubkey_hash, desired_share_target, desired_pseudoshare_target = self.get_user_details(user)
return pubkey_hash, desired_share_target, desired_pseudoshare_target
return user, pubkey_hash, desired_share_target, desired_pseudoshare_target

def _estimate_local_hash_rate(self):
if len(self.recent_shares_ts_work) == 50:
Expand All @@ -236,8 +240,23 @@ def get_local_addr_rates(self):
for datum in datums:
addr_hash_rates[datum['pubkey_hash']] = addr_hash_rates.get(datum['pubkey_hash'], 0) + datum['work']/dt
return addr_hash_rates

def get_local_addr_rate(self, pubkey_hash):
addr_hash_rate = 0
datums, dt = self.local_addr_rate_monitor.get_datums_in_last()
for datum in datums:
addr_hash_rate = addr_hash_rate + datum['work']/dt
return addr_hash_rate

def get_miner_rate(self, miner):
miner_hash_rate = 0
datums, dt = self.local_rate_monitor.get_datums_in_last()
for datum in datums:
if datum['user'] == miner:
miner_hash_rate = miner_hash_rate + datum['work']/dt
return miner_hash_rate

def get_work(self, pubkey_hash, desired_share_target, desired_pseudoshare_target):
def get_work(self, user, pubkey_hash, desired_share_target, desired_pseudoshare_target):
global print_throttle
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')
Expand Down Expand Up @@ -340,11 +359,36 @@ def get_work(self, pubkey_hash, desired_share_target, desired_pseudoshare_target
if desired_pseudoshare_target is None:
#target = 2**256-1
#DUMB_SCR
target = bitcoin_data.difficulty_to_target(float(1.0 / self.node.net.PARENT.DUMB_SCRYPT_DIFF))
local_hash_rate = self._estimate_local_hash_rate()
if local_hash_rate is not None:
#target = bitcoin_data.difficulty_to_target(float(1.0 / self.node.net.PARENT.DUMB_SCRYPT_DIFF))
#local_hash_rate = self._estimate_local_hash_rate()
#if local_hash_rate is not None:
#target = min(target, bitcoin_data.average_attempts_to_target(local_hash_rate * 1)) # limit to 1 share response every second by modulating pseudoshare difficulty
target = bitcoin_data.average_attempts_to_target(local_hash_rate * 1) # limit to 1 share response every second by modulating pseudoshare difficulty
#target = bitcoin_data.average_attempts_to_target(local_hash_rate * 1) # limit to 1 share response every second by modulating pseudoshare difficulty
target = bitcoin_data.difficulty_to_target_alt(self.min_difficulty, self.node.net.PARENT.DUMB_SCRYPT_DIFF)
if self.share_rate is not None:
if self.share_rate_type == 'address': # per-address
if local_addr_rates is not None:
local_rate = local_addr_rates.get(pubkey_hash, 0)
else:
local_rate = self.get_local_addr_rate(pubkey_hash)
else: # per-miner
local_rate = self.get_miner_rate(user)
if local_rate > 0:
target = min(target, bitcoin_data.average_attempts_to_target(local_rate * 60 / self.share_rate))
else: # per-node
local_hash_rate = self._estimate_local_hash_rate()
if local_hash_rate is not None:
target = min(target,
bitcoin_data.average_attempts_to_target(local_hash_rate * 1)) # limit to 1 share response every second by modulating pseudoshare difficulty
difficulty = bitcoin_data.target_to_difficulty_alt(target, self.node.net.PARENT.DUMB_SCRYPT_DIFF)
rounded_difficulty = 1
if difficulty >= 1:
while (rounded_difficulty + rounded_difficulty * 2) / 2 < difficulty:
rounded_difficulty = rounded_difficulty * 2
else:
while (rounded_difficulty + rounded_difficulty / 2) / 2 >= difficulty:
rounded_difficulty = rounded_difficulty / 2
target = bitcoin_data.difficulty_to_target_alt(rounded_difficulty, self.node.net.PARENT.DUMB_SCRYPT_DIFF)
else:
target = desired_pseudoshare_target
target = max(target, share_info['bits'].target)
Expand All @@ -362,8 +406,8 @@ def get_work(self, pubkey_hash, desired_share_target, desired_pseudoshare_target
current_time = time.time()
if (current_time - print_throttle) > 5.0:
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),
bitcoin_data.target_to_difficulty_alt(target, self.node.net.PARENT.DUMB_SCRYPT_DIFF),
bitcoin_data.target_to_difficulty_alt(share_info['bits'].target, self.node.net.PARENT.DUMB_SCRYPT_DIFF),
self.current_work.value['subsidy']*1e-8, self.node.net.PARENT.SYMBOL,
len(self.current_work.value['transactions']),
)
Expand Down

0 comments on commit d85ac04

Please sign in to comment.