async def id_pubkey_correspondence(id_pubkey): client = ClientInstance().client # determine if id_pubkey is a pubkey checked_pubkey = is_pubkey_and_check(id_pubkey) if checked_pubkey: id_pubkey = checked_pubkey try: idty = await identity_of(id_pubkey) print( "{} public key corresponds to identity: {}".format( display_pubkey_and_checksum(id_pubkey), idty["uid"] ) ) except: message_exit("No matching identity") # if not ; then it is a uid else: pubkeys = await wot_lookup(id_pubkey) print("Public keys found matching '{}':\n".format(id_pubkey)) for pubkey in pubkeys: print("→", display_pubkey_and_checksum(pubkey["pubkey"]), end=" ") try: corresponding_id = await client(wot.identity_of, pubkey["pubkey"]) print("↔ " + corresponding_id["uid"]) except: print("") await client.close()
async def cmd_amount(ctx, pubkeys): client = ClientInstance().client if not has_auth_method(): if not pubkeys: message_exit("You should specify one or many pubkeys") pubkey_list = list() for pubkey in pubkeys: if check_pubkey_format(pubkey): pubkey_list.append(validate_checksum(pubkey)) else: pubkey_list.append(pubkey) total = [0, 0] for pubkey in pubkey_list: inputs_balance = await get_amount_from_pubkey(pubkey) await show_amount_from_pubkey(pubkey, inputs_balance) total[0] += inputs_balance[0] total[1] += inputs_balance[1] if len(pubkey_list) > 1: await show_amount_from_pubkey("Total", total) else: key = auth_method() pubkey = key.pubkey await show_amount_from_pubkey(pubkey, await get_amount_from_pubkey(pubkey)) await client.close()
async def certification_confirmation(issuer, issuer_pubkey, pubkey_to_certify, idty_to_certify): cert = list() cert.append( ["Cert", "Issuer", "–>", "Recipient: Published: #block-hash date"]) client = ClientInstance().client idty_timestamp = idty_to_certify["meta"]["timestamp"] block_uid_idty = block_uid(idty_timestamp) block = await client(bma.blockchain.block, block_uid_idty.number) block_uid_date = (": #" + idty_timestamp[:15] + "… " + convert_time(block["time"], "all")) cert.append( ["ID", issuer["uid"], "–>", idty_to_certify["uid"] + block_uid_date]) cert.append([ "Pubkey", display_pubkey_and_checksum(issuer_pubkey), "–>", display_pubkey_and_checksum(pubkey_to_certify), ]) params = await BlockchainParams().params cert_begins = convert_time(time(), "date") cert_ends = convert_time(time() + params["sigValidity"], "date") cert.append(["Valid", cert_begins, "—>", cert_ends]) echo(tabulate(cert, tablefmt="fancy_grid")) if not confirm("Do you confirm sending this certification?"): await client.close() sys.exit(SUCCESS_EXIT_STATUS)
async def argos_info(): head_block = await HeadBlock().head_block print(await CurrencySymbol().symbol, "|") print("---") ep = EndPoint().ep endpoint_address = ep[best_endpoint_address(ep, False)] if ep["port"] == "443": href = "href=https://%s/" % (endpoint_address) else: href = "href=http://%s:%s/" % (endpoint_address, ep["port"]) print( "Connected to node:", ep[best_endpoint_address(ep, False)], ep["port"], "|", href, "\nCurrent block number:", head_block["number"], "\nCurrency name:", await CurrencySymbol().symbol, "\nNumber of members:", head_block["membersCount"], "\nMinimal Proof-of-Work:", head_block["powMin"], "\nCurrent time:", convert_time(head_block["time"], "all"), "\nMedian time:", convert_time(head_block["medianTime"], "all"), "\nDifference time:", convert_time(head_block["time"] - head_block["medianTime"], "hour"), ) client = ClientInstance().client await client.close()
async def test_display_confirmation_table( patched_wot_requirements, monkeypatch, capsys ): monkeypatch.setattr(bma.wot, "requirements", patched_wot_requirements) monkeypatch.setattr(bma.blockchain, "parameters", patched_params) monkeypatch.setattr(bma.blockchain, "block", patched_block) client = ClientInstance().client identities_requirements = await client(bma.wot.requirements, pubkey) for identity_requirements in identities_requirements["identities"]: if identity_requirements["uid"] == identity_uid: membership_expires = identity_requirements["membershipExpiresIn"] pending_expires = identity_requirements["membershipPendingExpiresIn"] pending_memberships = identity_requirements["pendingMemberships"] break table = list() if membership_expires: expires = pendulum.now().add(seconds=membership_expires).diff_for_humans() table.append(["Expiration date of current membership", expires]) if pending_memberships: line = [ "Number of pending membership(s) in the mempool", len(pending_memberships), ] table.append(line) expiration = pendulum.now().add(seconds=pending_expires).diff_for_humans() table.append(["Pending membership documents will expire", expiration]) table.append(["User Identifier (UID)", identity_uid]) table.append(["Public Key", display_pubkey_and_checksum(pubkey)]) table.append(["Block Identity", str(identity_timestamp)[:45] + "…"]) block = await client(bma.blockchain.block, identity_timestamp.number) table.append( ["Identity published", pendulum.from_timestamp(block["time"]).format("LL")], ) params = await BlockchainParams().params membership_validity = ( pendulum.now().add(seconds=params["msValidity"]).diff_for_humans() ) table.append(["Expiration date of new membership", membership_validity]) membership_mempool = ( pendulum.now().add(seconds=params["msPeriod"]).diff_for_humans() ) table.append( ["Expiration date of new membership from the mempool", membership_mempool] ) expected = tabulate(table, tablefmt="fancy_grid") + "\n" await membership.display_confirmation_table( identity_uid, pubkey, identity_timestamp ) captured = capsys.readouterr() assert expected == captured.out
async def display_confirmation_table(identity_uid, pubkey, identity_timestamp): """ Check whether there is pending memberships already in the mempool Display their expiration date Actually, it works sending a membership document even if the time between two renewals is not awaited as for the certification """ client = ClientInstance().client identities_requirements = await client(bma.wot.requirements, pubkey) for identity_requirements in identities_requirements["identities"]: if identity_requirements["uid"] == identity_uid: membership_expires = identity_requirements["membershipExpiresIn"] pending_expires = identity_requirements["membershipPendingExpiresIn"] pending_memberships = identity_requirements["pendingMemberships"] break table = list() if membership_expires: expires = pendulum.now().add(seconds=membership_expires).diff_for_humans() table.append(["Expiration date of current membership", expires]) if pending_memberships: line = [ "Number of pending membership(s) in the mempool", len(pending_memberships), ] table.append(line) expiration = pendulum.now().add(seconds=pending_expires).diff_for_humans() table.append(["Pending membership documents will expire", expiration]) table.append(["User Identifier (UID)", identity_uid]) table.append(["Public Key", display_pubkey_and_checksum(pubkey)]) table.append(["Block Identity", str(identity_timestamp)[:45] + "…"]) block = await client(bma.blockchain.block, identity_timestamp.number) table.append( ["Identity published", pendulum.from_timestamp(block["time"]).format("LL")] ) params = await BlockchainParams().params membership_validity = ( pendulum.now().add(seconds=params["msValidity"]).diff_for_humans() ) table.append(["Expiration date of new membership", membership_validity]) membership_mempool = ( pendulum.now().add(seconds=params["msPeriod"]).diff_for_humans() ) table.append( ["Expiration date of new membership from the mempool", membership_mempool] ) click.echo(tabulate(table, tablefmt="fancy_grid"))
async def send_transaction(amounts, amountsud, allsources, recipients, comment, outputbackchange, yes): """ Main function """ if not (amounts or amountsud or allsources): message_exit("Error: amount, amountUD or allSources is not set.") if allsources and len(recipients) > 1: message_exit( "Error: the --allSources option can only be used with one recipient." ) # compute amounts and amountsud if not allsources: tx_amounts = await transaction_amount(amounts, amountsud, recipients) key = auth_method() issuer_pubkey = key.pubkey pubkey_amount = await money.get_amount_from_pubkey(issuer_pubkey) if allsources: tx_amounts = [pubkey_amount[0]] recipients = list(recipients) outputbackchange = check_transaction_values( comment, recipients, outputbackchange, pubkey_amount[0] < sum(tx_amounts), issuer_pubkey, ) if (yes or input( tabulate( await transaction_confirmation( issuer_pubkey, pubkey_amount[0], tx_amounts, recipients, outputbackchange, comment, ), tablefmt="fancy_grid", ) + "\nDo you confirm sending this transaction? [yes/no]: ") == "yes"): await handle_intermediaries_transactions( key, issuer_pubkey, tx_amounts, recipients, comment, outputbackchange, ) else: client = ClientInstance().client await client.close()
async def send_membership(dry_run): # Authentication key = auth.auth_method() # Get the identity information head_block = await HeadBlock().head_block membership_timestamp = BlockUID(head_block["number"], head_block["hash"]) identity = (await wot.choose_identity(key.pubkey))[0] identity_uid = identity["uid"] identity_timestamp = block_uid(identity["meta"]["timestamp"]) # Display license and ask for confirmation currency = head_block["currency"] if not dry_run: license_approval(currency) # Confirmation client = ClientInstance().client await display_confirmation_table(identity_uid, key.pubkey, identity_timestamp) if not dry_run: if not click.confirm( "Do you confirm sending a membership document for this identity?" ): await client.close() sys.exit(SUCCESS_EXIT_STATUS) membership = generate_membership_document( currency, key.pubkey, membership_timestamp, identity_uid, identity_timestamp, ) # Sign document membership.sign([key]) logging.debug(membership.signed_raw()) if dry_run: await client.close() click.echo(membership.signed_raw()) sys.exit(SUCCESS_EXIT_STATUS) # Send the membership signed raw document to the node response = await client(bma.blockchain.membership, membership.signed_raw()) if response.status == 200: print("Membership successfully sent") else: print("Error while publishing membership: {0}".format(await response.text())) logging.debug(await response.text()) await client.close()
async def received_sent_certifications(uid_pubkey): """ get searched id get id of received and sent certifications display in a table the result with the numbers """ client = ClientInstance().client first_block = await client(blockchain.block, 1) time_first_block = first_block["time"] checked_pubkey = is_pubkey_and_check(uid_pubkey) if checked_pubkey: uid_pubkey = checked_pubkey identity, pubkey, signed = await choose_identity(uid_pubkey) certifications = OrderedDict() params = await BlockchainParams().params req = await client(wot.requirements, pubkey) req = req["identities"][0] certifications["received_expire"] = list() certifications["received"] = list() for cert in identity["others"]: certifications["received_expire"].append( expiration_date_from_block_id( cert["meta"]["block_number"], time_first_block, params ) ) certifications["received"].append( cert_written_in_the_blockchain(req["certifications"], cert) ) ( certifications["sent"], certifications["sent_expire"], ) = get_sent_certifications(signed, time_first_block, params) nbr_sent_certs = len(certifications["sent"]) if "sent" in certifications else 0 print( "{0} ({1}) from block #{2}\nreceived {3} and sent {4}/{5} certifications:\n{6}\n{7}\n".format( identity["uid"], display_pubkey_and_checksum(pubkey, True), identity["meta"]["timestamp"][:15] + "…", len(certifications["received"]), nbr_sent_certs, params["sigStock"], tabulate( certifications, headers="keys", tablefmt="orgtbl", stralign="center", ), "✔: Certifications written into the blockchain", ) ) await membership_status(certifications, pubkey, req) await client.close()
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 wot_lookup(identifier): """ :identifier: identity or pubkey in part or whole Return received and sent certifications lists of matching identities if one identity found """ client = ClientInstance().client try: results = await client(wot.lookup, identifier) return results["results"] except DuniterError as e: message_exit(e.message) except ValueError as e: pass
async def get_sources(pubkey): client = ClientInstance().client # Sources written into the blockchain sources = await client(tx.sources, pubkey) listinput = list() amount = 0 for source in sources["sources"]: if source["conditions"] == "SIG(" + pubkey + ")": listinput.append( InputSource( amount=source["amount"], base=source["base"], source=source["type"], origin_id=source["identifier"], index=source["noffset"], )) amount += amount_in_current_base(listinput[-1]) # pending source history = await client(tx.pending, pubkey) history = history["history"] pendings = history["sending"] + history["receiving"] + history["pending"] # add pending output pending_sources = list() for pending in pendings: identifier = pending["hash"] for i, output in enumerate(pending["outputs"]): outputsplited = output.split(":") if outputsplited[2] == "SIG(" + pubkey + ")": inputgenerated = InputSource( amount=int(outputsplited[0]), base=int(outputsplited[1]), source="T", origin_id=identifier, index=i, ) if inputgenerated not in listinput: listinput.append(inputgenerated) for input in pending["inputs"]: pending_sources.append(InputSource.from_inline(input)) # remove input already used for input in pending_sources: if input in listinput: listinput.remove(input) return listinput, amount
async def difficulties(): client = ClientInstance().client try: ws = await client(bma.ws.block) while True: current = await ws.receive_json() jsonschema.validate(current, bma.ws.WS_BLOCK_SCHEMA) diffi = await client(bma.blockchain.difficulties) await display_diffi(current, diffi) await client.close() except (aiohttp.WSServerHandshakeError, ValueError) as e: print("Websocket block {0} : {1}".format(type(e).__name__, str(e))) except (aiohttp.ClientError, gaierror, TimeoutError) as e: print("{0} : {1}".format(str(e), BMAS_ENDPOINT)) except jsonschema.ValidationError as e: print("{:}:{:}".format(str(e.__class__.__name__), str(e)))
async def transaction_history(pubkey, uids): if check_pubkey_format(pubkey): pubkey = validate_checksum(pubkey) client = ClientInstance().client ud_value = await UDValue().ud_value currency_symbol = await CurrencySymbol().symbol header = await generate_header(pubkey, currency_symbol, ud_value) received_txs, sent_txs = list(), list() await get_transactions_history(client, pubkey, received_txs, sent_txs) remove_duplicate_txs(received_txs, sent_txs) txs_list = await generate_table( received_txs, sent_txs, pubkey, ud_value, currency_symbol, uids ) table = Texttable(max_width=get_terminal_size()[0]) table.add_rows(txs_list) await client.close() echo_via_pager(header + table.draw())
async def generate_and_send_transaction( key, issuers, tx_amounts, listinput_and_amount, outputAddresses, Comment, OutputbackChange=None, ): """ Display sent transaction Generate, sign, and send transaction document """ intermediate_tx = listinput_and_amount[2] if intermediate_tx: print("Generate Change Transaction") else: print("Generate Transaction:") print(" - From: " + display_pubkey_and_checksum(issuers)) for tx_amount, outputAddress in zip(tx_amounts, outputAddresses): display_sent_tx(outputAddress, tx_amount) print(" - Total: " + str(sum(tx_amounts) / 100)) client = ClientInstance().client transaction = await generate_transaction_document( issuers, tx_amounts, listinput_and_amount, outputAddresses, Comment, OutputbackChange, ) transaction.sign([key]) response = await client(process, transaction.signed_raw()) if response.status == 200: print("Transaction successfully sent.") else: message_exit("Error while publishing transaction: {0}".format( await response.text()))
async def handle_intermediaries_transactions( key, issuers, tx_amounts, outputAddresses, Comment="", OutputbackChange=None, ): client = ClientInstance().client while True: listinput_and_amount = await get_list_input_for_transaction( issuers, sum(tx_amounts)) intermediatetransaction = listinput_and_amount[2] if intermediatetransaction: totalAmountInput = listinput_and_amount[1] await generate_and_send_transaction( key, issuers, [totalAmountInput], listinput_and_amount, [issuers], "Change operation", ) await sleep(1) # wait 1 second before sending a new transaction else: await generate_and_send_transaction( key, issuers, tx_amounts, listinput_and_amount, outputAddresses, Comment, OutputbackChange, ) await client.close() break
async def currency_info(): head_block = await HeadBlock().head_block ep = EndPoint().ep print( "Connected to node:", ep[best_endpoint_address(ep, False)], ep["port"], "\nCurrent block number:", head_block["number"], "\nCurrency name:", await CurrencySymbol().symbol, "\nNumber of members:", head_block["membersCount"], "\nMinimal Proof-of-Work:", head_block["powMin"], "\nCurrent time:", convert_time(head_block["time"], "all"), "\nMedian time:", convert_time(head_block["medianTime"], "all"), "\nDifference time:", convert_time(head_block["time"] - head_block["medianTime"], "hour"), ) client = ClientInstance().client await client.close()
async def send_certification(uid_pubkey_to_certify): client = ClientInstance().client checked_pubkey = is_pubkey_and_check(uid_pubkey_to_certify) if checked_pubkey: uid_pubkey_to_certify = checked_pubkey idty_to_certify, pubkey_to_certify, send_certs = await wot.choose_identity( uid_pubkey_to_certify) # Authentication key = auth_method() # Check whether current user is member issuer_pubkey = key.pubkey issuer = await wot.is_member(issuer_pubkey) if not issuer: message_exit("Current identity is not member.") if issuer_pubkey == pubkey_to_certify: message_exit("You can’t certify yourself!") # Check if the certification can be renewed req = await client(bma.wot.requirements, pubkey_to_certify) req = req["identities"][0] for cert in req["certifications"]: if cert["from"] == issuer_pubkey: params = await BlockchainParams().params # Ğ1: 0<–>2y - 2y + 2m # ĞT: 0<–>4.8m - 4.8m + 12.5d renewable = cert["expiresIn"] - params["sigValidity"] + params[ "sigReplay"] if renewable > 0: renewable_date = convert_time(time() + renewable, "date") message_exit("Certification renewable the " + renewable_date) # Check if the certification is already in the pending certifications for pending_cert in req["pendingCerts"]: if pending_cert["from"] == issuer_pubkey: message_exit("Certification is currently been processed") # Display license and ask for confirmation head = await HeadBlock().head_block currency = head["currency"] license_approval(currency) # Certification confirmation await certification_confirmation(issuer, issuer_pubkey, pubkey_to_certify, idty_to_certify) identity = Identity( version=10, currency=currency, pubkey=pubkey_to_certify, uid=idty_to_certify["uid"], ts=block_uid(idty_to_certify["meta"]["timestamp"]), signature=idty_to_certify["self"], ) certification = Certification( version=10, currency=currency, pubkey_from=issuer_pubkey, identity=identity, timestamp=BlockUID(head["number"], head["hash"]), signature="", ) # Sign document certification.sign([key]) # Send certification document response = await client(bma.wot.certify, certification.signed_raw()) if response.status == 200: print("Certification successfully sent.") else: print("Error while publishing certification: {0}".format( await response.text())) await client.close()
async def get_head(self): client = ClientInstance().client return await client(blockchain.current)
async def get_params(self): client = ClientInstance().client return await client(blockchain.parameters)
async def get_ud_value(self): client = ClientInstance().client blockswithud = await client(blockchain.ud) NBlastUDblock = blockswithud["result"]["blocks"][-1] lastUDblock = await client(blockchain.block, NBlastUDblock) return lastUDblock["dividend"] * 10**lastUDblock["unitbase"]
async def list_blocks(number, detailed): head_block = await HeadBlock().head_block current_nbr = head_block["number"] if number == 0: number = head_block["issuersFrame"] client = ClientInstance().client blocks = await client(bma.blockchain.blocks, number, current_nbr - number + 1) issuers = list() issuers_dict = dict() for block in blocks: issuer = OrderedDict() issuer["pubkey"] = block["issuer"] if detailed or number <= 30: issuer["block"] = block["number"] issuer["gentime"] = convert_time(block["time"], "all") issuer["mediantime"] = convert_time(block["medianTime"], "all") issuer["hash"] = block["hash"][:10] issuer["powMin"] = block["powMin"] issuers_dict[issuer["pubkey"]] = issuer issuers.append(issuer) for pubkey in issuers_dict.keys(): issuer = issuers_dict[pubkey] idty = await identity_of(issuer["pubkey"]) for issuer2 in issuers: if (issuer2.get("pubkey") is not None and issuer.get("pubkey") is not None and issuer2["pubkey"] == issuer["pubkey"]): 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(number, current_nbr - number + 1, current_nbr), end=" ", ) if detailed or number <= 30: sorted_list = sorted(issuers, key=itemgetter("block"), reverse=True) print("\n" + tabulate( sorted_list, headers="keys", tablefmt="orgtbl", stralign="center")) else: list_issued = list() for issuer in issuers: found = False for issued in list_issued: if issued.get( "uid") is not None and issued["uid"] == issuer["uid"]: issued["blocks"] += 1 found = True break if not found: issued = OrderedDict() issued["uid"] = issuer["uid"] issued["blocks"] = 1 list_issued.append(issued) for issued in list_issued: issued["percent"] = issued["blocks"] / number * 100 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", ), ))