From 953c352987aa23df0ded42f041ca227ea0a3edf8 Mon Sep 17 00:00:00 2001 From: Moul <moul@moul.re> Date: Sat, 13 Apr 2019 22:05:08 +0200 Subject: [PATCH] [enh] #135, #189, #206: wot requests improvements: - #135: remove get_uid_from_pubkey() Replace two uppers function with identity_of() which requests /wot/identity-of/<pubkey/uid> and only returns members identities with their pubkey and uid, which improves performances. - change is_member() as a wrapper of identity_of() - change usage in `id`, `cert`, `tx`, `net`, `blocks` - #189: Handle in a good way wot/identity-of requests exceptions - #206: Set a sleep for async requests: `blocks` and `net` for leaves --- silkaj/cert.py | 12 +++++------ silkaj/commands.py | 25 +++++++++++------------ silkaj/constants.py | 1 + silkaj/network_tools.py | 3 +++ silkaj/tx.py | 22 ++++++++++---------- silkaj/wot.py | 45 ++++++++++++++++++++++++----------------- 6 files changed, 60 insertions(+), 48 deletions(-) diff --git a/silkaj/cert.py b/silkaj/cert.py index 8bde21ee..f29d7301 100644 --- a/silkaj/cert.py +++ b/silkaj/cert.py @@ -26,7 +26,7 @@ from silkaj.tools import convert_time, message_exit, coroutine from silkaj.network_tools import ClientInstance, HeadBlock from silkaj.blockchain_tools import BlockchainParams from silkaj.license import license_approval -from silkaj.wot import is_member, get_uid_from_pubkey, get_informations_for_identity +from silkaj.wot import is_member, get_informations_for_identity @command("cert", help="Send certification") @@ -42,8 +42,8 @@ async def send_certification(id_to_certify): # Check whether current user is member issuer_pubkey = key.pubkey - issuer_id = await get_uid_from_pubkey(issuer_pubkey) - if not await is_member(issuer_pubkey, issuer_id): + issuer = await is_member(issuer_pubkey) + if not issuer: message_exit("Current identity is not member.") if issuer_pubkey == id_to_certify["pubkey"]: @@ -74,7 +74,7 @@ async def send_certification(id_to_certify): # Certification confirmation await certification_confirmation( - issuer_id, issuer_pubkey, id_to_certify, main_id_to_certify + issuer, issuer_pubkey, id_to_certify, main_id_to_certify ) identity = Identity( @@ -110,11 +110,11 @@ async def send_certification(id_to_certify): async def certification_confirmation( - issuer_id, issuer_pubkey, id_to_certify, main_id_to_certify + issuer, issuer_pubkey, id_to_certify, main_id_to_certify ): cert = list() cert.append(["Cert", "From", "–>", "To"]) - cert.append(["ID", issuer_id, "–>", main_id_to_certify["uid"]]) + cert.append(["ID", issuer["uid"], "–>", main_id_to_certify["uid"]]) cert.append(["Pubkey", issuer_pubkey, "–>", id_to_certify["pubkey"]]) params = await BlockchainParams().params cert_begins = convert_time(time(), "date") diff --git a/silkaj/commands.py b/silkaj/commands.py index 160a74e5..8370564a 100644 --- a/silkaj/commands.py +++ b/silkaj/commands.py @@ -17,11 +17,11 @@ along with Silkaj. If not, see <https://www.gnu.org/licenses/>. from click import command, option, argument, IntRange, get_terminal_size 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 asyncio import sleep import aiohttp from _socket import gaierror import jsonschema @@ -30,7 +30,7 @@ from duniterpy.api.client import Client, parse_text from duniterpy.api.bma import blockchain, node, ws from silkaj.tools import coroutine -from silkaj.wot import get_uid_from_pubkey +from silkaj.wot import identity_of from silkaj.network_tools import ( discover_peers, best_endpoint_address, @@ -39,7 +39,7 @@ from silkaj.network_tools import ( HeadBlock, ) from silkaj.tools import convert_time, message_exit, CurrencySymbol -from silkaj.constants import NO_MATCHING_ID +from silkaj.constants import ASYNC_SLEEP @command("info", help="Display information about currency") @@ -201,16 +201,14 @@ async def network_info(discover, sort): best_ep = best_endpoint_address(info, False) print(best_ep if best_ep is None else info[best_ep], end=" ") print(info["port"]) + await sleep(ASYNC_SLEEP) try: - info["uid"] = await get_uid_from_pubkey(ep, info["pubkey"]) - if info["uid"] is NO_MATCHING_ID: - info["uid"] = None - else: - info["member"] = "yes" - members += 1 + info["uid"] = await identity_of(info["pubkey"]) + info["uid"] = info["uid"]["uid"] + info["member"] = "yes" + members += 1 except: - pass - if info.get("member") is None: + info["uid"] = None info["member"] = "no" info["pubkey"] = info["pubkey"][:5] + "…" for d in diffi["levels"]: @@ -286,15 +284,16 @@ async def list_blocks(number, detailed): j += 1 for pubkey in issuers_dict.keys(): issuer = issuers_dict[pubkey] - uid = await get_uid_from_pubkey(issuer["pubkey"]) + idty = await identity_of(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["uid"] = idty["uid"] issuer2.pop("pubkey") + await sleep(ASYNC_SLEEP) await client.close() print( "Last {0} blocks from n°{1} to n°{2}".format( diff --git a/silkaj/constants.py b/silkaj/constants.py index eecf843d..5831112a 100644 --- a/silkaj/constants.py +++ b/silkaj/constants.py @@ -22,4 +22,5 @@ GTEST_SYMBOL = "ĞTest" G1_DEFAULT_ENDPOINT = "g1.duniter.org", "443" G1_TEST_DEFAULT_ENDPOINT = "g1-test.duniter.org", "443" CONNECTION_TIMEOUT = 10 +ASYNC_SLEEP = 0.1 SOURCES_PER_TX = 40 diff --git a/silkaj/network_tools.py b/silkaj/network_tools.py index 21134d58..7ed3865a 100644 --- a/silkaj/network_tools.py +++ b/silkaj/network_tools.py @@ -21,6 +21,7 @@ import socket import logging from sys import exit, stderr from click import pass_context +from asyncio import sleep from duniterpy.api.client import Client from duniterpy.api.bma import blockchain, network @@ -28,6 +29,7 @@ from silkaj.constants import ( G1_DEFAULT_ENDPOINT, G1_TEST_DEFAULT_ENDPOINT, CONNECTION_TIMEOUT, + ASYNC_SLEEP, ) @@ -75,6 +77,7 @@ async def get_peers_among_leaves(client): leaves = await client(network.peers, leaves=True) peers = list() for leaf in leaves["leaves"]: + await sleep(ASYNC_SLEEP + 0.05) leaf_response = await client(network.peers, leaf=leaf) peers.append(leaf_response["leaf"]["value"]) return parse_endpoints(peers) diff --git a/silkaj/tx.py b/silkaj/tx.py index fcd030ff..d8fd8cca 100644 --- a/silkaj/tx.py +++ b/silkaj/tx.py @@ -25,14 +25,14 @@ from silkaj.network_tools import ClientInstance, HeadBlock from silkaj.crypto_tools import check_public_key from silkaj.tools import message_exit, CurrencySymbol, coroutine from silkaj.auth import auth_method -from silkaj.wot import get_uid_from_pubkey +from silkaj.wot import is_member from silkaj.money import ( get_sources, get_amount_from_pubkey, UDValue, amount_in_current_base, ) -from silkaj.constants import NO_MATCHING_ID, SOURCES_PER_TX +from silkaj.constants import SOURCES_PER_TX from duniterpy.api.bma.tx import process from duniterpy.documents import BlockUID, Transaction @@ -165,19 +165,19 @@ async def transaction_confirmation( ] ) tx.append(["from (pubkey)", issuer_pubkey]) - id_from = await get_uid_from_pubkey(issuer_pubkey) - if id_from is not NO_MATCHING_ID: - tx.append(["from (id)", id_from]) + id_from = await is_member(issuer_pubkey) + if id_from: + tx.append(["from (id)", id_from["uid"]]) for outputAddress in outputAddresses: tx.append(["to (pubkey)", outputAddress]) - id_to = await get_uid_from_pubkey(outputAddress) - if id_to is not NO_MATCHING_ID: - tx.append(["to (id)", id_to]) + id_to = await is_member(outputAddress) + if id_to: + tx.append(["to (id)", id_to["uid"]]) if outputBackChange: tx.append(["Backchange (pubkey)", outputBackChange]) - id_backchange = await get_uid_from_pubkey(outputBackChange) - if id_backchange is not NO_MATCHING_ID: - tx.append(["Backchange (id)", id_backchange]) + id_backchange = await is_member(outputBackChange) + if id_backchange: + tx.append(["Backchange (id)", id_backchange["uid"]]) tx.append(["comment", comment]) return tx diff --git a/silkaj/wot.py b/silkaj/wot.py index 582702bc..3ea2cc32 100644 --- a/silkaj/wot.py +++ b/silkaj/wot.py @@ -20,6 +20,7 @@ from time import time from tabulate import tabulate from collections import OrderedDict from duniterpy.api.bma import wot, blockchain +from duniterpy.api.errors import DuniterError from silkaj.network_tools import ClientInstance from silkaj.crypto_tools import check_public_key @@ -119,7 +120,9 @@ async def membership_status(certifications, certs, pubkey, req): len(certifications["received"]) - params["sigQty"] ] ) - member = await is_member(pubkey, certs["uid"]) + member = await is_member(pubkey) + if member: + member = True print("member:", member) if req["revoked"]: print( @@ -159,7 +162,7 @@ async def id_pubkey_correspondence(id_pubkey): if check_public_key(id_pubkey, False): print( "{} public key corresponds to identity: {}".format( - id_pubkey, await get_uid_from_pubkey(id_pubkey) + id_pubkey, await identity_of(id_pubkey) ) ) else: @@ -193,15 +196,30 @@ async def get_informations_for_identity(id): message_exit(NO_MATCHING_ID) -async def get_uid_from_pubkey(pubkey): +async def identity_of(pubkey_uid): + """ + Only works for members + Not able to get corresponding uid from a non-member identity + Able to know if an identity is member or not + """ + client = ClientInstance().client + try: + return await client(wot.identity_of, pubkey_uid) + except DuniterError as e: + raise DuniterError(e) + except ValueError as e: + pass + + +async def is_member(pubkey_uid): + """ + Check identity is member + If member, return corresponding identity, else: False + """ try: - client = ClientInstance().client - lookups = await client(wot.lookup, pubkey) + return await identity_of(pubkey_uid) except: - return NO_MATCHING_ID - for lookup in lookups["results"]: - if lookup["uids"][0]["uid"] != pubkey: - return lookup["uids"][0]["uid"] + return False async def get_informations_for_identities(identifier): @@ -216,12 +234,3 @@ async def get_informations_for_identities(identifier): except: return NO_MATCHING_ID return results["results"] - - -async def is_member(pubkey, uid): - client = ClientInstance().client - members = await client(wot.members) - for member in members["results"]: - if pubkey in member["pubkey"] and uid in member["uid"]: - return True - return False -- GitLab