def main(): global LOGGER global CONFIG CONFIG = lib.get_config() LOGGER = lib.get_logger(PROCESS) LOGGER.warn("=== Starting {}".format(PROCESS)) # Get Config settings pool_fee = float(CONFIG[PROCESS]["pool_fee"]) # Number of blocks of share data used to calculate rewards PPLNG_WINDOW_SIZE = 60 try: PPLNG_WINDOW_SIZE = int(os.environ["PPLNG_WINDOW_SIZE"]) except Exception as e: LOGGER.error( "Failed to get PPLNG_WINDOW_SIZE from the environment: {} Using default size of {}" .format(e, PPLNG_WINDOW_SIZE)) # Connect to DB database = lib.get_db() # Get current blockchain height chain_height = grin.blocking_get_current_height() # Get unlocked blocks from the db unlocked_blocks = Pool_blocks.get_all_unlocked() unlocked_blocks = [blk.height for blk in unlocked_blocks] LOGGER.warn("Paying for {} pool blocks: {}".format(len(unlocked_blocks), unlocked_blocks)) for height in unlocked_blocks: try: LOGGER.warn("Processing unlocked block: {}".format(height)) # Call the library routine to get this blocks payout map payout_map = pool.calculate_block_payout_map( height, PPLNG_WINDOW_SIZE, pool_fee, LOGGER, False) #print("payout_map = {}".format(payout_map)) # Store the payment map for this block credits_record = Pool_credits(chain_height, height, payout_map) database.db.getSession().add(credits_record) # Make payments based on the workers total share_value Pool_blocks.setState(height, "paid") for user_id, payment_amount in payout_map.items(): # Add worker rewards to pool account balance LOGGER.warn("Credit to user: {} = {}".format( user_id, payment_amount)) worker_utxo = Pool_utxo.credit_worker(user_id, payment_amount) # Worker_stats accounting and running totals #latest_worker_stats = Worker_stats.get_latest_by_id(user_id) #latest_worker_stats.dirty = True database.db.getSession().commit() except Exception as e: database.db.getSession().rollback() LOGGER.exception("Something went wrong: {}".format(repr(e))) LOGGER.warn("=== Completed {}".format(PROCESS)) sys.stdout.flush()
def main(): global LOGGER LOGGER = lib.get_logger(PROCESS) LOGGER.warn("=== Starting {}".format(PROCESS)) # Connect to DB database = lib.get_db() latest_block = 0 # XXX All in one db transaction.... # Get unlocked blocks from the db unlocked_blocks = Pool_blocks.get_all_unlocked() database.db.getSession().commit() for pb in unlocked_blocks: try: LOGGER.warn("Processing unlocked block: {}".format(pb)) if pb.height > latest_block: latest_block = pb.height # Get valid pool_shares for that block from the db pool_shares = Pool_shares.get_valid_by_height(pb.height) # Calculate Payment info: worker_shares = {} for ps in pool_shares: LOGGER.warn("Processing pool_shares: {}".format(ps)) # Need to get actual_difficulty gs = Grin_shares.get_by_nonce(ps.nonce) if gs == None: # XXX NOTE: no payout for shares not accepted by grin node continue if ps.found_by in worker_shares: worker_shares[ps.found_by] += gs.actual_difficulty else: worker_shares[ps.found_by] = gs.actual_difficulty if len(worker_shares) > 0: # Calcualte reward/difficulty: XXX TODO: Enhance # What algorithm to use? Maybe: https://slushpool.com/help/manual/rewards r_per_d = REWARD / sum(worker_shares.values()) for worker in worker_shares.keys(): # Calculate reward per share worker_rewards = worker_shares[worker] * r_per_d # Add or create worker rewards worker_utxo = Pool_utxo.credit_worker( worker, worker_rewards) LOGGER.warn("Credit to user: {} = {}".format( worker, worker_rewards)) # Mark the pool_block state="paid" (maybe "processed" would be more accurate?) pb.state = "paid" database.db.getSession().commit() except Exception as e: database.db.getSession().rollback() LOGGER.error("Something went wrong: {}".format(e)) #database.db.getSession().commit() # db.set_last_run(PROCESS, str(time.time())) LOGGER.warn("=== Completed {}".format(PROCESS)) sys.stdout.flush()
def main(): global LOGGER LOGGER = lib.get_logger(PROCESS) LOGGER.warn("=== Starting {}".format(PROCESS)) # Connect to DB database = lib.get_db() latest_block = 0 # XXX All in one db transaction.... # Get unlocked blocks from the db unlocked_blocks = Pool_blocks.get_all_unlocked() database.db.getSession().commit() for pb in unlocked_blocks: try: LOGGER.warn("Processing unlocked block: {}".format(pb)) if pb.height > latest_block: latest_block = pb.height # Get Worker_stats of this block to calculate reward for each worker worker_stats = Worker_stats.get_by_height(pb.height) # Calculate Payment info: if len(worker_stats) > 0: # Calcualte reward/share: # XXX TODO: Enhance # What algorithm to use? Maybe: https://slushpool.com/help/manual/rewards r_per_g = REWARD / sum([st.gps for st in worker_stats]) for stat in worker_stats: # Calculate reward worker_rewards = stat.gps * r_per_g # Add or create worker rewards worker_utxo = Pool_utxo.credit_worker( stat.worker, worker_rewards) LOGGER.warn("Credit to user: {} = {}".format( stat.worker, worker_rewards)) # Mark the pool_block state="paid" (maybe "processed" would be more accurate?) pb.state = "paid" database.db.getSession().commit() except Exception as e: database.db.getSession().rollback() LOGGER.error("Something went wrong: {}".format(e)) #database.db.getSession().commit() LOGGER.warn("=== Completed {}".format(PROCESS)) sys.stdout.flush()
def main(): global LOGGER LOGGER = lib.get_logger(PROCESS) LOGGER.warn("=== Starting {}".format(PROCESS)) # Connect to DB database = lib.get_db() # XXX All in one db transaction.... # Get unlocked blocks from the db unlocked_blocks = Pool_blocks.get_all_unlocked() unlocked_blocks = [blk.height for blk in unlocked_blocks] for height in unlocked_blocks: try: LOGGER.warn("Processing unlocked block: {}".format(height)) # Call the library routine to get this blocks payout map payout_map = pool.calculate_block_payout_map( height, PPLNS_WINDOW, LOGGER, False) #print("payout_map = {}".format(payout_map)) # Make payments based on the workers total share_value Pool_blocks.setState(height, "paid") database.db.getSession().commit() for user_id, payment_amount in payout_map.items(): # Add worker rewards to pool account balance LOGGER.warn("Credit to user: {} = {}".format( user_id, payment_amount)) worker_utxo = Pool_utxo.credit_worker(user_id, payment_amount) # Worker_stats accounting and running totals #latest_worker_stats = Worker_stats.get_latest_by_id(user_id) #latest_worker_stats.dirty = True database.db.getSession().commit() except Exception as e: database.db.getSession().rollback() LOGGER.error("Something went wrong: {} - {}".format( e, traceback.print_exc())) LOGGER.warn("=== Completed {}".format(PROCESS)) sys.stdout.flush()
def main(): global LOGGER LOGGER = lib.get_logger(PROCESS) LOGGER.warn("=== Starting {}".format(PROCESS)) # Connect to DB database = lib.get_db() latest_block = 0 # XXX All in one db transaction.... # Get unlocked blocks from the db unlocked_blocks = Pool_blocks.get_all_unlocked() database.db.getSession().commit() for pb in unlocked_blocks: try: LOGGER.warn("Processing unlocked block: {}".format(pb)) if pb.height > latest_block: latest_block = pb.height # Get Worker_stats of this block + range to calculate reward for each worker worker_shares_window = Worker_shares.get_by_height(pb.height, PPLNS_WINDOW) print("worker_shares_window = {}".format(worker_shares_window)) # Calculate Payment info: if len(worker_shares_window) > 0: # Calcualte reward/share: # XXX TODO: Enhance # What algorithm to use? Maybe: https://slushpool.com/help/manual/rewards # For now, some variation on pplns # Sum up the number of each size share submitted by each user shares_count_map = {} for worker_shares_rec in worker_shares_window: if not worker_shares_rec.worker in shares_count_map: shares_count_map[worker_shares_rec.worker] = {} for pow_size in worker_shares_rec.sizes(): print("pow_size = {}".format(pow_size)) if not pow_size in shares_count_map[worker_shares_rec.worker]: shares_count_map[worker_shares_rec.worker][pow_size] = 0 shares_count_map[worker_shares_rec.worker][pow_size] += worker_shares_rec.num_valid(pow_size) print("Shares Count Map:") pp.pprint(shares_count_map) # Normalize and sum each workers shares to create a "share value" total_value = 0 for worker, worker_shares_count in shares_count_map.items(): print("worker: {}, worker_shares_count: {}".format(worker, worker_shares_count)) sizes = list(worker_shares_count.keys()) print("sizes: {}".format(sizes)) shares_count_map[worker]["value"] = 0 value = 0 for size, count in worker_shares_count.items(): if size == 29: value += float(count) * .33 else: value += float(count) total_value += value shares_count_map[worker]["value"] = value print("Worker {} value: {}".format(worker, value)) # Make payments based on the workers total share_value for worker, worker_shares_count in shares_count_map.items(): worker_rewards = REWARD * worker_shares_count["value"] / total_value # Add or create worker rewards worker_utxo = Pool_utxo.credit_worker(worker, worker_rewards) LOGGER.warn("Credit to user: {} = {}".format(worker, worker_rewards)) # Mark the pool_block state="paid" (maybe "processed" would be more accurate?) pb.state = "paid" database.db.getSession().commit() except Exception as e: database.db.getSession().rollback() LOGGER.error("Something went wrong: {} - {}".format(e, traceback.print_exc())) #database.db.getSession().commit() LOGGER.warn("=== Completed {}".format(PROCESS)) sys.stdout.flush()