250 lines
11 KiB
Python
250 lines
11 KiB
Python
|
from datetime import datetime
|
|||
|
from time import sleep
|
|||
|
from os import system, popen
|
|||
|
from collections import OrderedDict
|
|||
|
from tabulate import tabulate
|
|||
|
from operator import itemgetter
|
|||
|
|
|||
|
from wot import get_uid_from_pubkey
|
|||
|
from network_tools import discover_peers, get_request, best_node, get_current_block
|
|||
|
from tools import convert_time, get_currency_symbol, message_exit
|
|||
|
from constants import NO_MATCHING_ID
|
|||
|
|
|||
|
|
|||
|
def currency_info(ep):
|
|||
|
info_type = ["newcomers", "certs", "actives", "leavers", "excluded", "ud", "tx"]
|
|||
|
i, info_data = 0, dict()
|
|||
|
while (i < len(info_type)):
|
|||
|
info_data[info_type[i]] = get_request(ep, "blockchain/with/" + info_type[i])["result"]["blocks"]
|
|||
|
i += 1
|
|||
|
current = get_current_block(ep)
|
|||
|
system("clear")
|
|||
|
print("Connected to node:", ep[best_node(ep, 1)], ep["port"],
|
|||
|
"\nCurrent block number:", current["number"],
|
|||
|
"\nCurrency name:", get_currency_symbol(current["currency"]),
|
|||
|
"\nNumber of members:", current["membersCount"],
|
|||
|
"\nMinimal Proof-of-Work:", current["powMin"],
|
|||
|
"\nCurrent time:", convert_time(current["time"], "all"),
|
|||
|
"\nMedian time:", convert_time(current["medianTime"], "all"),
|
|||
|
"\nDifference time:", convert_time(current["time"] - current["medianTime"], "hour"),
|
|||
|
"\nNumber of blocks containing: \
|
|||
|
\n- new comers:", len(info_data["newcomers"]),
|
|||
|
"\n- Certifications:", len(info_data["certs"]),
|
|||
|
"\n- Actives (members updating their membership):", len(info_data["actives"]),
|
|||
|
"\n- Leavers:", len(info_data["leavers"]),
|
|||
|
"\n- Excluded:", len(info_data["excluded"]),
|
|||
|
"\n- UD created:", len(info_data["ud"]),
|
|||
|
"\n- transactions:", len(info_data["tx"]))
|
|||
|
|
|||
|
|
|||
|
def match_pattern(pow, match='', p=1):
|
|||
|
while pow > 0:
|
|||
|
if pow >= 16:
|
|||
|
match += "0"
|
|||
|
pow -= 16
|
|||
|
p *= 16
|
|||
|
else:
|
|||
|
match += "[0-" + hex(15 - pow)[2:].upper() + "]"
|
|||
|
p *= pow
|
|||
|
pow = 0
|
|||
|
return match + '*', p
|
|||
|
|
|||
|
|
|||
|
def power(nbr, pow=0):
|
|||
|
while nbr >= 10:
|
|||
|
nbr /= 10
|
|||
|
pow += 1
|
|||
|
return "{0:.1f} × 10^{1}".format(nbr, pow)
|
|||
|
|
|||
|
|
|||
|
def difficulties(ep):
|
|||
|
while True:
|
|||
|
diffi = get_request(ep, "blockchain/difficulties")
|
|||
|
levels = [OrderedDict((i, d[i]) for i in ("uid", "level")) for d in diffi["levels"]]
|
|||
|
diffi["levels"] = levels
|
|||
|
current = get_current_block(ep)
|
|||
|
issuers, sorted_diffi = 0, sorted(diffi["levels"], key=itemgetter("level"), reverse=True)
|
|||
|
for d in diffi["levels"]:
|
|||
|
if d["level"] / 2 < current["powMin"]:
|
|||
|
issuers += 1
|
|||
|
d["match"] = match_pattern(d["level"])[0][:20]
|
|||
|
d["Π diffi"] = power(match_pattern(d["level"])[1])
|
|||
|
d["Σ diffi"] = d.pop("level")
|
|||
|
system("clear")
|
|||
|
print("Minimal Proof-of-Work: {0} to match `{1}`\nDifficulty to generate next block n°{2} for {3}/{4} nodes:\n{5}"
|
|||
|
.format(current["powMin"], match_pattern(int(current["powMin"]))[0], diffi["block"], issuers, len(diffi["levels"]),
|
|||
|
tabulate(sorted_diffi, headers="keys", tablefmt="orgtbl", stralign="center")))
|
|||
|
sleep(5)
|
|||
|
|
|||
|
|
|||
|
network_sort_keys = ["block", "member", "diffi", "uid"]
|
|||
|
|
|||
|
|
|||
|
def set_network_sort_keys(some_keys):
|
|||
|
global network_sort_keys
|
|||
|
if some_keys.endswith(","):
|
|||
|
message_exit("Argument 'sort' ends with a comma, you have probably inserted a space after the comma, which is incorrect.")
|
|||
|
network_sort_keys = some_keys.split(",")
|
|||
|
|
|||
|
|
|||
|
def get_network_sort_key(endpoint):
|
|||
|
t = list()
|
|||
|
for akey in network_sort_keys:
|
|||
|
if akey == 'diffi' or akey == 'block' or akey == 'port':
|
|||
|
t.append(int(endpoint[akey]) if akey in endpoint else 0)
|
|||
|
else:
|
|||
|
t.append(str(endpoint[akey]) if akey in endpoint else "")
|
|||
|
return tuple(t)
|
|||
|
|
|||
|
|
|||
|
def network_info(ep, discover):
|
|||
|
rows, columns = popen('stty size', 'r').read().split()
|
|||
|
# print(rows, columns) # debug
|
|||
|
wide = int(columns)
|
|||
|
if wide < 146:
|
|||
|
message_exit("Wide screen need to be larger than 146. Current wide: " + wide)
|
|||
|
# discover peers
|
|||
|
# and make sure fields are always ordered the same
|
|||
|
endpoints = [OrderedDict((i, p.get(i, None)) for i in ("domain", "port", "ip4", "ip6", "pubkey")) for p in discover_peers(ep, discover)]
|
|||
|
# Todo : renommer endpoints en info
|
|||
|
diffi = get_request(ep, "blockchain/difficulties")
|
|||
|
i, members = 0, 0
|
|||
|
print("Getting informations about nodes:")
|
|||
|
while (i < len(endpoints)):
|
|||
|
print("{0:.0f}%".format(i/len(endpoints) * 100, 1), end=" ")
|
|||
|
best_ep = best_node(endpoints[i], 0)
|
|||
|
print(best_ep if best_ep is None else endpoints[i][best_ep], end=" ")
|
|||
|
print(endpoints[i]["port"])
|
|||
|
try:
|
|||
|
endpoints[i]["uid"] = get_uid_from_pubkey(ep, endpoints[i]["pubkey"])
|
|||
|
if endpoints[i]["uid"] is NO_MATCHING_ID:
|
|||
|
endpoints[i]["uid"] = None
|
|||
|
else:
|
|||
|
endpoints[i]["member"] = "yes"
|
|||
|
members += 1
|
|||
|
except:
|
|||
|
pass
|
|||
|
if endpoints[i].get("member") is None:
|
|||
|
endpoints[i]["member"] = "no"
|
|||
|
endpoints[i]["pubkey"] = endpoints[i]["pubkey"][:5] + "…"
|
|||
|
# Todo: request difficulty from node point of view: two nodes with same pubkey id could be on diffrent branches and have different difficulties
|
|||
|
# diffi = get_request(endpoints[i], "blockchain/difficulties") # super long, doit être requetté uniquement pour les nœuds d’une autre branche
|
|||
|
for d in diffi["levels"]:
|
|||
|
if endpoints[i].get("uid") is not None:
|
|||
|
if endpoints[i]["uid"] == d["uid"]:
|
|||
|
endpoints[i]["diffi"] = d["level"]
|
|||
|
if len(endpoints[i]["uid"]) > 10:
|
|||
|
endpoints[i]["uid"] = endpoints[i]["uid"][:9] + "…"
|
|||
|
current_blk = get_current_block(endpoints[i])
|
|||
|
if current_blk is not None:
|
|||
|
endpoints[i]["gen_time"] = convert_time(current_blk["time"], "hour")
|
|||
|
if wide > 171:
|
|||
|
endpoints[i]["mediantime"] = convert_time(current_blk["medianTime"], "hour")
|
|||
|
if wide > 185:
|
|||
|
endpoints[i]["difftime"] = convert_time(current_blk["time"] - current_blk["medianTime"], "hour")
|
|||
|
endpoints[i]["block"] = current_blk["number"]
|
|||
|
endpoints[i]["hash"] = current_blk["hash"][:10] + "…"
|
|||
|
endpoints[i]["version"] = get_request(endpoints[i], "node/summary")["duniter"]["version"]
|
|||
|
if endpoints[i].get("domain") is not None and len(endpoints[i]["domain"]) > 20:
|
|||
|
endpoints[i]["domain"] = "…" + endpoints[i]["domain"][-20:]
|
|||
|
if endpoints[i].get("ip6") is not None:
|
|||
|
if wide < 156:
|
|||
|
endpoints[i].pop("ip6")
|
|||
|
else:
|
|||
|
endpoints[i]["ip6"] = endpoints[i]["ip6"][:8] + "…"
|
|||
|
i += 1
|
|||
|
system("clear")
|
|||
|
print(len(endpoints), "peers ups, with", members, "members and", len(endpoints) - members, "non-members at", datetime.now().strftime("%H:%M:%S"))
|
|||
|
endpoints = sorted(endpoints, key=get_network_sort_key)
|
|||
|
print(tabulate(endpoints, headers="keys", tablefmt="orgtbl", stralign="center"))
|
|||
|
|
|||
|
|
|||
|
def list_issuers(ep, nbr, last):
|
|||
|
current_blk = get_current_block(ep)
|
|||
|
current_nbr = current_blk["number"]
|
|||
|
if nbr == 0:
|
|||
|
nbr = current_blk["issuersFrame"]
|
|||
|
url = "blockchain/blocks/" + str(nbr) + "/" + str(current_nbr - nbr + 1)
|
|||
|
blocks, list_issuers, j = get_request(ep, url), list(), 0
|
|||
|
issuers_dict = dict()
|
|||
|
while j < len(blocks):
|
|||
|
issuer = OrderedDict()
|
|||
|
issuer["pubkey"] = blocks[j]["issuer"]
|
|||
|
if last or nbr <= 30:
|
|||
|
issuer["block"] = blocks[j]["number"]
|
|||
|
issuer["gentime"] = convert_time(blocks[j]["time"], "hour")
|
|||
|
issuer["mediantime"] = convert_time(blocks[j]["medianTime"], "hour")
|
|||
|
issuer["hash"] = blocks[j]["hash"][:10]
|
|||
|
issuers_dict[issuer["pubkey"]] = issuer
|
|||
|
list_issuers.append(issuer)
|
|||
|
j += 1
|
|||
|
for pubkey in issuers_dict.keys():
|
|||
|
issuer = issuers_dict[pubkey]
|
|||
|
uid = get_uid_from_pubkey(ep, issuer["pubkey"])
|
|||
|
for issuer2 in list_issuers:
|
|||
|
if issuer2.get("pubkey") is not None and issuer.get("pubkey") is not None and \
|
|||
|
issuer2["pubkey"] == issuer["pubkey"]:
|
|||
|
issuer2["uid"] = uid
|
|||
|
issuer2.pop("pubkey")
|
|||
|
system("clear")
|
|||
|
print("Issuers for last {0} blocks from block n°{1} to block n°{2}".format(nbr, current_nbr - nbr + 1, current_nbr), end=" ")
|
|||
|
if last or nbr <= 30:
|
|||
|
sorted_list = sorted(list_issuers, key=itemgetter("block"), reverse=True)
|
|||
|
print("\n{0}".format(tabulate(sorted_list, headers="keys", tablefmt="orgtbl", stralign="center")))
|
|||
|
else:
|
|||
|
i, list_issued = 0, list()
|
|||
|
while i < len(list_issuers):
|
|||
|
j, found = 0, 0
|
|||
|
while j < len(list_issued):
|
|||
|
if list_issued[j].get("uid") is not None and \
|
|||
|
list_issued[j]["uid"] == list_issuers[i]["uid"]:
|
|||
|
list_issued[j]["blocks"] += 1
|
|||
|
found = 1
|
|||
|
break
|
|||
|
j += 1
|
|||
|
if found == 0:
|
|||
|
issued = OrderedDict()
|
|||
|
issued["uid"] = list_issuers[i]["uid"]
|
|||
|
issued["blocks"] = 1
|
|||
|
list_issued.append(issued)
|
|||
|
i += 1
|
|||
|
i = 0
|
|||
|
while i < len(list_issued):
|
|||
|
list_issued[i]["percent"] = list_issued[i]["blocks"] / nbr * 100
|
|||
|
i += 1
|
|||
|
sorted_list = sorted(list_issued, key=itemgetter("blocks"), reverse=True)
|
|||
|
print("from {0} issuers\n{1}".format(len(list_issued),
|
|||
|
tabulate(sorted_list, headers="keys", tablefmt="orgtbl", floatfmt=".1f", stralign="center")))
|
|||
|
|
|||
|
|
|||
|
def argos_info(ep):
|
|||
|
info_type = ["newcomers", "certs", "actives", "leavers", "excluded", "ud", "tx"]
|
|||
|
pretty_names = {'g1': 'Ğ1', 'gtest': 'Ğtest'}
|
|||
|
i, info_data = 0, dict()
|
|||
|
while (i < len(info_type)):
|
|||
|
info_data[info_type[i]] = get_request(ep, "blockchain/with/" + info_type[i])["result"]["blocks"]
|
|||
|
i += 1
|
|||
|
current = get_current_block(ep)
|
|||
|
pretty = current["currency"]
|
|||
|
if current["currency"] in pretty_names:
|
|||
|
pretty = pretty_names[current["currency"]]
|
|||
|
print(pretty, "|")
|
|||
|
print("---")
|
|||
|
href = 'href=http://%s:%s/' % (ep[best_node(ep, 1)], ep["port"])
|
|||
|
print("Connected to node:", ep[best_node(ep, 1)], ep["port"], "|", href,
|
|||
|
"\nCurrent block number:", current["number"],
|
|||
|
"\nCurrency name:", get_currency_symbol(current["currency"]),
|
|||
|
"\nNumber of members:", current["membersCount"],
|
|||
|
"\nMinimal Proof-of-Work:", current["powMin"],
|
|||
|
"\nCurrent time:", convert_time(current["time"], "all"),
|
|||
|
"\nMedian time:", convert_time(current["medianTime"], "all"),
|
|||
|
"\nDifference time:", convert_time(current["time"] - current["medianTime"], "hour"),
|
|||
|
"\nNumber of blocks containing… \
|
|||
|
\n-- new comers:", len(info_data["newcomers"]),
|
|||
|
"\n-- Certifications:", len(info_data["certs"]),
|
|||
|
"\n-- Actives (members updating their membership):", len(info_data["actives"]),
|
|||
|
"\n-- Leavers:", len(info_data["leavers"]),
|
|||
|
"\n-- Excluded:", len(info_data["excluded"]),
|
|||
|
"\n-- UD created:", len(info_data["ud"]),
|
|||
|
"\n-- transactions:", len(info_data["tx"]))
|