コード例 #1
0
def pocv10_violations(hotspot, chals):
    """

    :param hotspot: hotspot object to analyze
    :param chals: list of challenges
    :return:
    """
    H = Hotspots()
    haddr = hotspot['address']
    hlat, hlng = hotspot['lat'], hotspot['lng']
    transmits_w = dict(total=0, bad_rssi=0, bad_snr=0)
    receives_w = dict(total=0, bad_rssi=0, bad_snr=0)
    poc_rcv = dict(total=0, bad_rssi=0, bad_snr=0)
    bad_neighbors = dict()


    for chal in chals:
        transmitter = None
        for p in chal['path']:
            if p['challengee'] == haddr:
                for w in p['witnesses']:
                    dist = utils.haversine_km(
                        hlat, hlng,
                        H.get_hotspot_by_addr(w['gateway'])['lat'], H.get_hotspot_by_addr(w['gateway'])['lng'])
                    if dist < .3:
                        continue
                    rssi_lim = utils.max_rssi(dist)
                    snr_rssi_lim = utils.snr_min_rssi(w['snr'])
                    transmits_w['total'] += 1
                    if w['gateway'] not in bad_neighbors:
                        bad_neighbors[w['gateway']] = dict(rssi=0, snr=0, ttl=0)
                    bad_neighbors[w['gateway']]['ttl'] += 1
                    if w['signal'] > rssi_lim:
                        transmits_w['bad_rssi'] += 1
                        bad_neighbors[w['gateway']]['rssi'] += 1
                    if w['signal'] < snr_rssi_lim:
                        transmits_w['bad_snr'] += 1
                        bad_neighbors[w['gateway']]['snr'] += 1
                if p['receipt'] and transmitter:
                    dist = utils.haversine_km(
                        hlat, hlng,
                        H.get_hotspot_by_addr(transmitter)['lat'], H.get_hotspot_by_addr(transmitter)['lng']
                    )
                    rssi_lim = utils.max_rssi(dist)
                    snr_rssi_lim = utils.snr_min_rssi(p['receipt']['snr'])
                    poc_rcv['total'] += 1
                    if transmitter not in bad_neighbors:
                        bad_neighbors[transmitter] = dict(rssi=0, snr=0, ttl=0)
                    bad_neighbors[transmitter]['ttl'] += 1
                    if p['receipt']['signal'] > rssi_lim:
                        poc_rcv['bad_rssi'] += 1
                        bad_neighbors[transmitter]['rssi'] += 1
                    if p['receipt']['signal'] < snr_rssi_lim:
                        poc_rcv['bad_snr'] += 1
                        bad_neighbors[transmitter]['snr'] += 1
            else:
                for w in p['witnesses']:
                    if w['gateway'] != haddr:
                        continue
                    dist = utils.haversine_km(
                        hlat, hlng,
                        H.get_hotspot_by_addr(p['challengee'])['lat'], H.get_hotspot_by_addr(p['challengee'])['lng']
                    )
                    if dist < .3:
                        continue
                    rssi_lim = utils.max_rssi(dist)
                    snr_rssi_lim = utils.snr_min_rssi(w['snr'])
                    receives_w['total'] += 1
                    if p['challengee'] not in bad_neighbors:
                        bad_neighbors[p['challengee']] = dict(rssi=0, snr=0, ttl=0)
                    bad_neighbors[p['challengee']]['ttl'] += 1
                    if w['signal'] > rssi_lim:
                        receives_w['bad_rssi'] += 1
                        bad_neighbors[p['challengee']]['rssi'] += 1
                    if w['signal'] < snr_rssi_lim:
                        receives_w['bad_snr'] += 1
                        bad_neighbors[p['challengee']]['snr'] += 1
            transmitter = p['challengee']

    days, remainder = divmod(chals[0]['time'] - chals[-1]['time'], 3600 * 24)
    hours = int(round(remainder / 3600, 0))
    print(
        f"analyzing {len(chals)} challenges from block {chals[0]['height']}-{chals[-1]['height']} over {days} days, {hours} hrs")

    print(f"PoC v10 failures for {hotspot['name']}")

    print(F"SUMMARY")
    print(f"Category                   | Total | bad RSSI (%) | bad SNR (%) |")
    print(f"-----------------------------------------------------------------")
    print(f"Witnesses to hotspot >300m | {transmits_w['total']:5d} | {transmits_w['bad_rssi']:4d} ({transmits_w['bad_rssi']*100/max(1, transmits_w['total']):3.0f}%)  | {transmits_w['bad_snr']:4d} ({transmits_w['bad_snr']*100/max(1, transmits_w['total']):3.0f}%) |")
    print(f"Hotspot witnessing  >300m  | {receives_w['total']:5d} | {receives_w['bad_rssi']:4d} ({receives_w['bad_rssi']*100/max(1, receives_w['total']):3.0f}%)  | {receives_w['bad_snr']:4d} ({receives_w['bad_snr']*100/max(1, receives_w['total']):3.0f}%) |")
    print(f"Hotspot PoC receipts       | {poc_rcv['total']:5d} | {poc_rcv['bad_rssi']:4d} ({poc_rcv['bad_rssi']*100/max(1, poc_rcv['total']):3.0f}%)  | {poc_rcv['bad_snr']:4d} ({poc_rcv['bad_snr']*100/max(1, poc_rcv['total']):3.0f}%) |")

    print()
    print()
    print(f'BY "BAD" NEIGHBOR')
    print(f"Neighboring Hotspot           | dist km | heading |  bad RSSI (%)  |  bad SNR (%)   |")
    print(f"------------------------------+---------+---------+----------------+----------------|")
    hlat, hlng = hotspot['lat'], hotspot['lng']
    for n in bad_neighbors:
        if bad_neighbors[n]['rssi'] or bad_neighbors[n]['snr']:
            bad_h = H.get_hotspot_by_addr(n)
            dist_km, heading = utils.haversine_km(
                hlat,
                hlng,
                bad_h['lat'],
                bad_h['lng'],
                return_heading=True
            )

            print(f"{H.get_hotspot_by_addr(n)['name']:29} | {dist_km:5.1f}   | {__heading2str__(heading):7} | {bad_neighbors[n]['rssi']:3d}/{bad_neighbors[n]['ttl']:3d} ({bad_neighbors[n]['rssi']*100/bad_neighbors[n]['ttl']:3.0f}%) | {bad_neighbors[n]['snr']:3d}/{bad_neighbors[n]['ttl']:3d} ({bad_neighbors[n]['snr']*100/bad_neighbors[n]['ttl']:3.0f}%) |")
コード例 #2
0
def witness_detail(hotspot, chals, smry_only=False):
    haddr = hotspot['address']
    H = Hotspots()
    H.update_reference_hspot(address=haddr)
    hotspot = H.get_hotspot_by_addr(haddr)
    vars = utils.api_call(path='vars')['data']
    print()
    print(f"Witnesses for: {hotspot['name']}")
    if not smry_only:
        print(
            f"{'time':14} | {'block':7} | {'transmitting hotspot':25} | dist km | valid? |  snr  | rssi | RUs  | inval reason"
        )

    tx_smry = dict()
    total_RUs = 0
    for c in chals:
        p = c['path'][0]
        for w in p['witnesses']:
            if w['gateway'] == haddr:
                transmitter = H.get_hotspot_by_addr(p['challengee'])

                # time, transmitter, distance, val/inval, RU, reason inval
                time_str = dt.datetime.fromtimestamp(w['timestamp'] /
                                                     1e9).isoformat()[5:19]
                time_str = time_str.replace('T', ' ')
                transmitter_name = transmitter['name']
                reward_units = 0
                valid = 'INVAL'
                reason = ''
                dist_km = utils.haversine_km(transmitter['lat'],
                                             transmitter['lng'],
                                             hotspot['lat'], hotspot['lng'])
                max_rssi = utils.max_rssi(dist_km)
                min_rssi = utils.snr_min_rssi(w['snr'])
                if w['is_valid']:
                    valid = 'valid'
                    hip15_rus = 1
                    if len(p['witnesses']) > vars['witness_redundancy']:
                        hip15_rus = (vars['witness_redundancy'] - (1 - pow(
                            vars['poc_reward_decay_rate'],
                            len(p['witnesses']) - vars['witness_redundancy']))
                                     ) / len(p['witnesses'])
                    reward_units = transmitter['reward_scale'] * hip15_rus
                else:
                    if dist_km < 0.3:
                        reason = 'too close'
                    elif w['signal'] > max_rssi:
                        reason = f'rssi too high ({w["signal"]}dbm,{w["snr"]:.1f}snr)'
                    elif w['signal'] < min_rssi:
                        reason = f'snr too high (snr:{w["snr"]:.1f}, rssi: {w["signal"]}<{min_rssi})'
                    else:
                        reason = 'unknown'
                total_RUs += reward_units
                if not smry_only:
                    print(
                        f"{time_str:14} | {c['height']:7} | {transmitter_name[:25]:25} | {dist_km:6.1f}  | {valid:6} | {w['snr']:5.1f} | {w['signal']:4d} | {reward_units:4.2f} | {reason}"
                    )

                if transmitter['address'] not in tx_smry:
                    tx_smry[transmitter['address']] = dict(valid_cnt=0,
                                                           invalid_cnt=0,
                                                           RUs=0)
                tx_smry[transmitter['address']]['RUs'] += reward_units
                tx_smry[
                    transmitter['address']]['valid_cnt'] += valid == 'valid'
                tx_smry[
                    transmitter['address']]['invalid_cnt'] += valid != 'valid'

    if smry_only:
        idx_sort = []
        for k in tx_smry.keys():
            idx_sort.append((tx_smry[k]['RUs'], k))
        idx_sort.sort()
        idx_sort = [x[1] for x in idx_sort[::-1]]
        print(
            f"{'transmitting hotspot':25} | scale | owner | dist km | heading | valids | invlds | RUs"
        )

        earning_by_compass = dict()

        for addr in idx_sort:
            txer = H.get_hotspot_by_addr(addr)
            dist, heading = utils.haversine_km(hotspot['lat'],
                                               hotspot['lng'],
                                               txer['lat'],
                                               txer['lng'],
                                               return_heading=True)
            compass = utils.heading_to_compass(heading)
            if compass not in earning_by_compass:
                earning_by_compass[compass] = 0
            earning_by_compass[compass] += tx_smry[addr]['RUs']
            heading = round(heading / 5, 0) * 5
            owner = 'same'
            if hotspot['owner'] != txer['owner']:
                owner = txer['owner'][-5:]
            heading_str = f"{heading:3.0f} {compass:3}"
            print(
                f"{txer['name'][:25]:25} | {txer['reward_scale']:5.2f} | {owner:5} | {dist:7.1f} | {heading_str:7} | {tx_smry[addr]['valid_cnt']:6} | {tx_smry[addr]['invalid_cnt']:6} | {tx_smry[addr]['RUs']:.2f}"
            )

        print()
        print(f"Earnings by compass heading")
        print(f"heading |   RUs  | bar chart")
        max_compass = max(list(earning_by_compass.values()))
        if max_compass == 0:
            max_compass = 1
        for h in utils.compass_headings:
            earnings = earning_by_compass.get(h, 0)
            print(
                f"   {h:4} | {earnings:6.2f} | {'X' * round(32 * earnings / max_compass) }"
            )

        print(f"total RUs earned: {total_RUs:.4f}")
        if has_mpl and show_plots:
            ax = plt.subplot(111, projection='polar')
            ax.set_theta_offset(math.pi / 2)
            ax.set_theta_direction(-1)
            width = 2 * math.pi / len(utils.compass_headings)
            theta = [
                math.radians(utils.compass_to_heading(h))
                for h in utils.compass_headings
            ]
            earnings = [
                math.sqrt(earning_by_compass.get(h, 0))
                for h in utils.compass_headings
            ]
            # earnings = [(earning_by_compass.get(h, 0)) for h in utils.compass_headings]

            ax.bar(theta, earnings, width=width, bottom=0.0)
            ax.set_xticks(theta)
            ax.set_yticks([])
            ax.set_xticklabels(utils.compass_headings)
            plt.title(f"{hotspot['name']} RUs by compass heading")
            plt.show()