示例#1
0
def initialize():
    database = lib.get_db()
    # Special case for new pool startup - Need 3 stats records to bootstrap
    block_zero = Blocks.get_by_height(0)
    seed_stat0 = Grin_stats(height=0,
                            timestamp=block_zero.timestamp,
                            gps=0,
                            difficulty=block_zero.total_difficulty,
                            total_utxoset_size=block_zero.num_inputs)
    database.db.createDataObj(seed_stat0)
    block_one = Blocks.get_by_height(1)
    seed_stat1 = Grin_stats(height=1,
                            timestamp=block_one.timestamp,
                            gps=0,
                            difficulty=block_one.total_difficulty -
                            block_zero.total_difficulty,
                            total_utxoset_size=seed_stat0.total_utxoset_size +
                            block_one.num_outputs - block_one.num_inputs)
    database.db.createDataObj(seed_stat1)
    block_two = Blocks.get_by_height(2)
    seed_stat2 = Grin_stats(height=2,
                            timestamp=block_two.timestamp,
                            gps=0,
                            difficulty=block_two.total_difficulty -
                            block_one.total_difficulty,
                            total_utxoset_size=seed_stat1.total_utxoset_size +
                            block_two.num_outputs - block_two.num_inputs)
    database.db.createDataObj(seed_stat2)
示例#2
0
def calculate(height, avg_range=DIFFICULTY_ADJUST_WINDOW):
    # Get the most recent blocks from which to generate the stats
    recent_blocks = []
    previous_stats_record = Grin_stats.get_by_height(height-1)
    print("XXX: {}".format(previous_stats_record))
    assert previous_stats_record is not None, "No provious stats record found" 
    recent_blocks = Blocks.get_by_height(height, avg_range)
    if len(recent_blocks) < min(avg_range, height):
        # We dont have all of these blocks in the DB
        raise AssertionError("Missing blocks in range: {}:{}".format(height-avg_range, height))
    assert recent_blocks[-1].height == height, "Invalid height in recent_blocks[-1]" 
    assert recent_blocks[-2].height == height - 1, "Invalid height in recent_blocks[-2]: {} vs {}".format(recent_blocks[-2].height, height - 1) 
    # Calculate the stats data
    first_block = recent_blocks[0]
    last_block = recent_blocks[-1]
    timestamp = last_block.timestamp
    difficulty = recent_blocks[-1].total_difficulty - recent_blocks[-2].total_difficulty
    new_stats = Grin_stats(
        height = height,
        timestamp = timestamp,
        difficulty = difficulty,
    )
    # Caclulate estimated GPS for recent edge_bits sizes
    all_gps = estimate_all_gps(recent_blocks)
    for gps in all_gps:
        gps_rec = Gps(
            edge_bits = gps[0],
            gps = gps[1],
        )
        new_stats.gps.append(gps_rec)
    return new_stats
示例#3
0
def initialize(avg_over_range, logger):
    database = lib.get_db()
    # Special case for new pool startup - Need 3 stats records to bootstrap
    block_zero = None
    while block_zero is None:
        logger.warn("Waiting for the first block record in the database")
        time.sleep(1)
        block_zero = Blocks.get_earliest()
    print("block_zero={}".format(block_zero))
    height = block_zero.height
    # Create avg_over_range dummy block records prior to block_zero
    print("Create block filtters: {} - {}".format(height-avg_over_range, height))
    for h in range(height-avg_over_range, height):
        print("Creating fillter at height {}".format(h))
        new_block = Blocks(hash = "x",
            version = 0,
            height = h,
            previous = "x",
            timestamp = datetime.utcnow(),
            output_root = "x",
            range_proof_root = "x",
            kernel_root = "x",
            nonce = 0,
            edge_bits = 29,
            total_difficulty = block_zero.total_difficulty,
            secondary_scaling = 0,
            num_inputs = 0,
            num_outputs = 0,
            num_kernels = 0,
            fee = 0,
            lock_height = 0,
            total_kernel_offset = "x",
            state = "filler")
        database.db.getSession().add(new_block)
    database.db.getSession().commit()
    seed_stat0 = Grin_stats(
        height=height-2,
        timestamp=block_zero.timestamp,
        difficulty=block_zero.total_difficulty)
    database.db.createDataObj(seed_stat0)
    seed_stat1 = Grin_stats(
        height=height-1,
        timestamp=block_zero.timestamp,
        difficulty=block_zero.total_difficulty)
    database.db.createDataObj(seed_stat1)
    seed_stat2 = Grin_stats(
        height=height,
        timestamp=block_zero.timestamp,
        difficulty=block_zero.total_difficulty)
    database.db.createDataObj(seed_stat2)
    return height
示例#4
0
 def get(self, height=0, range=None, fields=None):
     database = lib.get_db()
     fields = lib.fields_to_list(fields)
     if height == 0:
         height = grin.get_current_height()
     if range == None:
         stat = Grin_stats.get_by_height(height)
         if stat is None:
             return None
         return stat.to_json(fields)
     else:
         stats = []
         for stat in Grin_stats.get_by_height(height, range):
             stats.append(stat.to_json(fields))
         return stats
示例#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()
    atexit.register(lib.teardown_db)

    check_interval = float(CONFIG[PROCESS]["check_interval"])
    avg_over_range = int(CONFIG[PROCESS]["avg_over_range"])

    # Find the height of the latest stats record
    last_height = 0
    latest_stat = Grin_stats.get_latest()
    print("latest_stat = {}".format(latest_stat))

    if latest_stat == None:
        LOGGER.warn("Initializing Grin_stats")
        grinstats.initialize(avg_over_range, LOGGER)
        latest_stat = Grin_stats.get_latest()
        print("Finished initializing, latest_stat height = {}".format(
            latest_stat.height))
    last_height = latest_stat.height
    height = last_height + 1
    LOGGER.warn(
        "grinStats service starting at block height: {}".format(height))

    # Generate grin stats records - one per grin block
    while True:
        #latest_db_block = Blocks.get_latest()
        latest = Blocks.get_latest().height
        while latest >= height:
            try:
                new_stats = grinstats.calculate(height, avg_over_range)
                # Batch new stats when possible, but commit at reasonable intervals
                database.db.getSession().add(new_stats)
                #                if( (height % BATCHSZ == 0) or (height >= (latest-10)) ):
                database.db.getSession().commit()
                LOGGER.warn(
                    "Added Grin_stats for block: {} - gps:{} diff:{}".format(
                        new_stats.height, new_stats.gps, new_stats.difficulty))
                height = height + 1
            except AssertionError as e:
                LOGGER.error("Something went wrong: {}".format(e))
                sleep(check_interval)
        sys.stdout.flush()
        sleep(check_interval)
    LOGGER.warn("=== Completed {}".format(PROCESS))
示例#6
0
    def get(self, height=None, range=None, fields=None):
        LOGGER = lib.get_logger(PROCESS)
        LOGGER.warn("GrinAPI_stats get height:{} range:{} fields:{}".format(
            height, range, fields))
        fields = lib.fields_to_list(fields)
        if height is None or height == 0:
            stats = Grin_stats.get_latest(range)
        else:
            stats = Grin_stats.get_by_height(height, range)
        #pp.pprint(stats)

        if range == None:
            if stats is None:
                return None
            return stats.to_json(fields)
        else:
            st = []
            for stat in stats:
                st.append(stat.to_json(fields))
            return st
示例#7
0
def calculate(height, avg_range):
    # Get the most recent blocks from which to generate the stats
    recent_blocks = []
    previous_stats_record = Grin_stats.get_by_height(height - 1)
    print("XXX: {}".format(previous_stats_record))
    assert previous_stats_record is not None, "No provious stats record found"
    recent_blocks = Blocks.get_by_height(height, avg_range)
    if len(recent_blocks) < min(avg_range, height):
        # We dont have all of these blocks in the DB
        raise AssertionError("Missing blocks in range: {}:{}".format(
            height - avg_range, height))
    print(recent_blocks[-1])
    print(recent_blocks[-2])
    print(recent_blocks[-3])
    print(recent_blocks[-4])
    assert recent_blocks[
        -1].height == height, "Invalid height in recent_blocks[-1]"
    assert recent_blocks[
        -2].height == height - 1, "Invalid height in recent_blocks[-2]: {} vs {}".format(
            recent_blocks[-2].height, height - 1)
    # Calculate the stats data
    first_block = recent_blocks[0]
    last_block = recent_blocks[-1]
    timestamp = last_block.timestamp
    difficulty = recent_blocks[-1].total_difficulty - recent_blocks[
        -2].total_difficulty
    gps = lib.calculate_graph_rate(difficulty, first_block.timestamp,
                                   last_block.timestamp, len(recent_blocks))
    # utxo set size = sum outputs - sum inputs
    total_utxoset_size = previous_stats_record.total_utxoset_size + last_block.num_outputs - last_block.num_inputs
    return Grin_stats(
        height=height,
        timestamp=timestamp,
        gps=gps,
        difficulty=difficulty,
        total_utxoset_size=total_utxoset_size,
    )
示例#8
0
def recalculate(start_height, avg_range):
    database = lib.get_db()
    height = start_height
    while height <= grin.blocking_get_current_height():
        old_stats = Grin_stats.get_by_height(height)
        new_stats = calculate(height, avg_range)
        if old_stats is None:
            database.db.createDataObj(new_stats)
        else:
            old_stats.timestamp = new_stats.timestamp
            old_stats.difficulty = new_stats.difficulty
            old_stats.gps = new_stats.gps
            old_stats.difficulty = new_stats.difficulty
            old_stats.total_utxoset_size = new_stats.total_utxoset_size
            database.db.getSession().commit()
        height = height + 1
示例#9
0
def avg_network_gps(height=0, range=60):
    if height == 0:
        height = Blocks.get_latest().height
    if range <= 0:
        range = 1
    grinstats = Grin_stats.get_by_height(height, range)
    gpslists = [stat.gps for stat in grinstats]
    gpslists_len = len(gpslists)
    if gpslists_len == 0:
        return 0
    gpstotals = {}
    for gpslist in gpslists:
        for gps in gpslist:
            if gps.edge_bits not in gpstotals:
                gpstotals[gps.edge_bits] = 0
            gpstotals[gps.edge_bits] += gps.gps
    gpsavgs = {}
    for sz, gpstotal in gpstotals.items():
        gpsavgs[sz] = gpstotal / gpslists_len
    return gpsavgs
示例#10
0
def get_stats(height):
    ##
    # Get requested grin network stats as seen by our grin node
    return Grin_stats.get_by_height(height)