예제 #1
0
파일: api.py 프로젝트: bitgrin/grin-pool
 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
예제 #2
0
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)
예제 #3
0
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)
예제 #4
0
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()
예제 #5
0
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()
예제 #6
0
파일: api.py 프로젝트: waosman/grin-pool
 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
예제 #7
0
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)