def get(self, id, height=0): LOGGER = lib.get_logger(PROCESS) if id != g.user.id: response = jsonify({ 'message': 'Not authorized to access data for other users' }) response.status_code = 403 return response debug and LOGGER.warn("EstimateApi_payment get id:{} height:{}".format(id, height)) if height != 0: # Request is for a single block reward payout_map = pool.get_block_payout_map_estimate(height, LOGGER) if payout_map is None: return 0 #print("payout map: {}".format(payout_map)) #sys.stdout.flush() if id in payout_map: return payout_map[id] else: return 0 # Get a list of all new and unlocked blocks unlocked_blocks = Pool_blocks.get_all_unlocked() unlocked_blocks_h = [blk.height for blk in unlocked_blocks] #LOGGER.warn("EstimateApi_payment unlocked blocks: {}".format(unlocked_blocks)) new_blocks = Pool_blocks.get_all_new() new_blocks_h = [blk.height for blk in new_blocks] #LOGGER.warn("EstimateApi_payment new blocks: {}".format(new_blocks)) total = 0 for height in unlocked_blocks_h + new_blocks_h: debug and print("Estimate block at height: {}".format(height)) payout_map = pool.get_block_payout_map_estimate(height, LOGGER) if payout_map is not None and id in payout_map: total = total + payout_map[id] return total
def main(): global CONFIG global LOGGER CONFIG = lib.get_config() LOGGER = lib.get_logger(PROCESS) LOGGER.warn("=== Starting {}".format(PROCESS)) # 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() esitmated = [ ] # Blocks we know have already been estimated - XXX TODO: Clean paid blocks out of this list # Get Config settings pool_fee = float(CONFIG[PROCESS]["pool_fee"]) while True: # Generate pool block reward estimates for all new and unlocked blocks try: database.db.initializeSession() unlocked_blocks = Pool_blocks.get_all_unlocked() new_blocks = Pool_blocks.get_all_new() unlocked_blocks_h = [blk.height for blk in unlocked_blocks] new_blocks_h = [blk.height for blk in new_blocks] need_estimates = [] for height in unlocked_blocks_h + new_blocks_h: if height not in esitmated: need_estimates.append(height) if need_estimates: LOGGER.warn("Will ensure estimate for blocks: {}".format( need_estimates)) # Generate Estimate for height in need_estimates: LOGGER.warn("Ensure estimate for block: {}".format(height)) payout_map = pool.calculate_block_payout_map( height, PPLNG_WINDOW_SIZE, pool_fee, LOGGER, True) # Double check the total paid is correct esitmated.append(height) LOGGER.warn( "Completed estimate for block: {}".format(height)) LOGGER.warn("Completed estimates") database.db.destroySession() sleep(check_interval) except Exception as e: # AssertionError as e: LOGGER.error("Something went wrong: {} - {}".format( e, traceback.print_stack())) LOGGER.warn("=== Completed {}".format(PROCESS)) sleep(check_interval)
def main(): CONFIG = lib.get_config() LOGGER = lib.get_logger(PROCESS) LOGGER.warn("=== Starting {}".format(PROCESS)) # Connect to DB database = lib.get_db() database.db.initializeSession() while True: # Generate pool block reward estimates for all new and unlocked blocks try: unlocked_blocks = Pool_blocks.get_all_unlocked() unlocked_blocks_h = [blk.height for blk in unlocked_blocks] new_blocks = Pool_blocks.get_all_new() new_blocks_h = [blk.height for blk in new_blocks] LOGGER.warn("Will ensure estimate for blocks: {}".format( unlocked_blocks_h + new_blocks_h)) # Generate Estimate for height in unlocked_blocks_h + new_blocks_h: LOGGER.warn("Ensure estimate for block: {}".format(height)) payout_map = pool.calculate_block_payout_map( height, 60, LOGGER, True) LOGGER.warn("Completed estimate for block: {}".format(height)) #database.db.getSession().commit() LOGGER.warn("Completed estimates") sleep(check_interval) except Exception as e: # AssertionError as e: LOGGER.error("Something went wrong: {} - {}".format( e, traceback.print_stack())) LOGGER.warn("=== Completed {}".format(PROCESS)) sleep(check_interval)
def main(): CONFIG = lib.get_config() LOGGER = lib.get_logger(PROCESS) LOGGER.warn("=== Starting {}".format(PROCESS)) # Connect to DB database = lib.get_db() # Get the list of pool_blocks that are # old enough to unlock and # are not orphan blocks # XXX TODO: The node may not be synced, may need to wait? block_locktime = int(CONFIG[PROCESS]["block_locktime"]) block_expiretime = int(CONFIG[PROCESS]["block_expiretime"]) LOGGER.warn("using locktime: {}, expiretime: {}".format( block_locktime, block_expiretime)) latest = grin.blocking_get_current_height() LOGGER.warn("Latest: {}".format(latest)) new_poolblocks = Pool_blocks.get_all_new() for pb in new_poolblocks: if pb.height < (latest - block_expiretime): # Dont re-process very old blocks - protection against duplicate payouts. LOGGER.error("Processed expired pool block at height: {}".format( pb.height)) pb.state = "expired" continue response = grin.get_block_by_height(pb.height) if response == None: # Unknown. Leave as "new" for now and attempt to validate next run LOGGER.error("Failed to get block {}".format(pb.height)) continue if int(response["header"]["nonce"]) != int(pb.nonce): LOGGER.warn("Processed orphan pool block at height: {}".format( pb.height)) pb.state = "orphan" continue if pb.height < (latest - block_locktime): # This block seems valid, and old enough to unlock LOGGER.warn("Unlocking pool block at height: {}".format(pb.height)) pb.state = "unlocked" sys.stdout.flush() # db.set_last_run(PROCESS, str(time.time())) database.db.getSession().commit() LOGGER.warn("=== Completed {}".format(PROCESS)) sys.stdout.flush()
def main(): CONFIG = lib.get_config() LOGGER = lib.get_logger(PROCESS) LOGGER.warn("=== Starting {}".format(PROCESS)) # Connect to DB database = lib.get_db() # Get the list of pool_blocks that are # old enough to unlock and # are not orphan blocks # XXX TODO: The node may not be synced, may need to wait? block_locktime = int(CONFIG[PROCESS]["block_locktime"]) block_expiretime = int(CONFIG[PROCESS]["block_expiretime"]) LOGGER.warn("using locktime: {}, expiretime: {}".format(block_locktime, block_expiretime)) latest = grin.blocking_get_current_height() LOGGER.warn("Latest: {}".format(latest)) # Get outputs form the wallet wallet_outputs = wallet.retrieve_outputs(refresh=True) wallet_outputs_map = wallet.outputs_to_map_by_height(wallet_outputs) wallet_output_heights = list(wallet_outputs_map.keys()) wallet_output_heights.sort() #print("wallet_output_heights = {}".format(wallet_output_heights)) new_poolblocks = Pool_blocks.get_all_new() for pb in new_poolblocks: if pb.height < (latest - block_expiretime): # Dont re-process very old blocks - protection against duplicate payouts. LOGGER.error("Processed expired pool block at height: {}".format(pb.height)) pb.state = "expired" continue response = grin.get_block_by_height(pb.height) # Check for unknown block if response == None: # Unknown. Leave as "new" for now and attempt to validate next run LOGGER.error("Failed to get block {}".format(pb.height)) continue # Check for orphans if int(response["header"]["nonce"]) != int(pb.nonce): LOGGER.warn("Processed orphan pool block at height: {}".format(pb.height)) pb.state = "orphan" continue # # Check that we have a coinbase output in the wallet for this block # if pb.height not in wallet_output_heights: # LOGGER.warn("Wallet has no output for pool block at height: {}".format(pb.height)) # pb.state = "no_wallet_output" # continue # Check if its old enough to be mature if pb.height < (latest - block_locktime): # This block seems valid, and old enough to unlock LOGGER.warn("Unlocking pool block at height: {}".format(pb.height)) pb.state = "unlocked" sys.stdout.flush() # db.set_last_run(PROCESS, str(time.time())) database.db.getSession().commit() LOGGER.warn("=== Completed {}".format(PROCESS)) sys.stdout.flush()
def get(self, id, height=None, range=None): LOGGER = lib.get_logger(PROCESS) if id != g.user.id: response = jsonify( {'message': 'Not authorized to access data for other users'}) response.status_code = 403 return response debug and LOGGER.warn("EstimateApi_payment get id:{} height:{}".format( id, height)) id_str = str(id) if height is None: # Immature Balance Estimate LOGGER.warn("Immature Balance Estimate") # Get a list of all new and unlocked blocks unlocked_blocks = Pool_blocks.get_all_unlocked() unlocked_blocks_h = [blk.height for blk in unlocked_blocks] #LOGGER.warn("EstimateApi_payment unlocked blocks: {}".format(unlocked_blocks)) new_blocks = Pool_blocks.get_all_new() new_blocks_h = [blk.height for blk in new_blocks] #LOGGER.warn("EstimateApi_payment new blocks: {}".format(new_blocks)) total = 0 for height in unlocked_blocks_h + new_blocks_h: debug and print("Estimate block at height: {}".format(height)) payout_map = pool.get_block_payout_map_estimate(height, LOGGER) if payout_map is not None and id_str in payout_map: total = total + payout_map[id_str] return {"immature": total} if type(height) == str: if height == "next": # Next block estimate debug and LOGGER.warn("Next block estimate") estimate = 0 payout_map = pool.get_block_payout_map_estimate(height, LOGGER) if payout_map is None: estimate = "TBD" elif id_str in payout_map: estimate = payout_map[id_str] else: estimate = 0 return {"next": estimate} else: response = jsonify({'message': 'Invalid Request'}) response.status_code = 400 return response # Block Reward estimate if range is None: # One specific block estimate debug and LOGGER.warn("One specific block estimate") estimate = 0 payout_map = pool.get_block_payout_map_estimate(height, LOGGER) if payout_map is not None: if id_str in payout_map.keys(): estimate = payout_map[id_str] else: estimate = 0 else: # Maybe this is a pool block but we didnt estimate it yet pb = Pool_blocks.get_by_height(height) if pb is not None: estimate = "TBD" str_height = str(height) return {str_height: estimate} # Range of pool block reward estimates debug and LOGGER.warn("Range of blocks estimate") # Enforce range limit range = min(range, pool_blocks_range_limit) # Get the list of pool block(s) heights if height == 0: blocks = Pool_blocks.get_latest(range) else: blocks = Pool_blocks.get_by_height(height, range) block_heights = [pb.height for pb in blocks] # Get estimates for each of the blocks estimates = {} for height in block_heights: estimate = 0 payout_map = pool.get_block_payout_map_estimate(height, LOGGER) if payout_map is None: estimate = "TBD" elif id_str in payout_map: estimate = payout_map[id_str] else: estimate = 0 str_height = str(height) estimates[str_height] = estimate return estimates
def main(): global CONFIG global LOGGER CONFIG = lib.get_config() LOGGER = lib.get_logger(PROCESS) LOGGER.warn("=== Starting {}".format(PROCESS)) # 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)) POOL_FEE = 0.0075 try: POOL_FEE = float(CONFIG[PROCESS]["pool_fee"]) except Exception as e: LOGGER.error( "Failed to get POOL_FEE from the config: {}. Using default fee of {}" .format(e, POOL_FEE)) # Keep track of "next" block estimated next_height_estimated = 0 # Connect to DB database = lib.get_db() while True: # Generate pool block reward estimates for all new and unlocked blocks try: database.db.initializeSession() next_height = Blocks.get_latest( ).height - 5 # A recent height which all worker shares are available unlocked_blocks = Pool_blocks.get_all_unlocked() new_blocks = Pool_blocks.get_all_new() unlocked_blocks_h = [blk.height for blk in unlocked_blocks] new_blocks_h = [blk.height for blk in new_blocks] need_estimates = unlocked_blocks_h + new_blocks_h LOGGER.warn( "Will ensure estimate for blocks: {}".format(need_estimates)) redisdb = lib.get_redis_db() # Generate Estimate for height in need_estimates: if height > next_height: LOGGER.warn( "Delay estimate until we have recent shares availalbe for block: {}" .format(height)) else: LOGGER.warn("Ensure estimate for block: {}".format(height)) # Check if we already have an estimate cached payout_estimate_map_key = key_prefix + str(height) cached_map = redisdb.get(payout_estimate_map_key) if cached_map is None: # We dont have it cached, we need to calcualte it and cache it now payout_map = pool.calculate_block_payout_map( height, PPLNG_WINDOW_SIZE, POOL_FEE, LOGGER, True) payout_map_json = json.dumps(payout_map) redisdb.set(payout_estimate_map_key, payout_map_json, ex=cache_expire) LOGGER.warn( "Created estimate for block {} with key {}".format( height, payout_estimate_map_key)) else: LOGGER.warn( "There is an exiting estimate for block: {}". format(height)) # Generate estimate for "next" block LOGGER.warn( "Ensure estimate for next block: {}".format(next_height)) if next_height_estimated != next_height: payout_map = pool.calculate_block_payout_map( next_height, PPLNG_WINDOW_SIZE, POOL_FEE, LOGGER, True) payout_map_json = json.dumps(payout_map) payout_estimate_map_key = key_prefix + "next" redisdb.set(payout_estimate_map_key, payout_map_json, ex=cache_expire) next_height_estimated = next_height LOGGER.warn("Created estimate for block {} with key {}".format( next_height, payout_estimate_map_key)) else: LOGGER.warn( "There is an exiting next block estimate for : {}".format( next_height)) LOGGER.warn("Completed estimates") database.db.destroySession() # Flush debug print statements sys.stdout.flush() except Exception as e: # AssertionError as e: LOGGER.error("Something went wrong: {} - {}".format( e, traceback.format_exc())) database.db.destroySession() LOGGER.warn("=== Completed {}".format(PROCESS)) sleep(check_interval)