Improved rnid options and control flow

This commit is contained in:
Mark Qvist
2026-05-07 17:59:31 +02:00
parent 8a1d3aedd4
commit 8b6609c588
+54 -41
View File
@@ -128,6 +128,7 @@ def main():
# Information Flow # Information Flow
parser.add_argument("-R", "--request", action="store_true", default=False, help="request unknown Identities from the network") parser.add_argument("-R", "--request", action="store_true", default=False, help="request unknown Identities from the network")
parser.add_argument("-N", "--no-cache", action="store_true", default=False, help="never used cached or network-sourced information")
parser.add_argument("-t", action="store", metavar="seconds", type=float, help="identity request timeout before giving up", default=RNS.Transport.PATH_REQUEST_TIMEOUT) parser.add_argument("-t", action="store", metavar="seconds", type=float, help="identity request timeout before giving up", default=RNS.Transport.PATH_REQUEST_TIMEOUT)
parser.add_argument("-p", "--print-identity", action="store_true", default=False, help="print identity info and exit") parser.add_argument("-p", "--print-identity", action="store_true", default=False, help="print identity info and exit")
parser.add_argument("-P", "--print-private", action="store_true", default=False, help="allow displaying private keys") parser.add_argument("-P", "--print-private", action="store_true", default=False, help="allow displaying private keys")
@@ -141,15 +142,15 @@ def main():
args = parser.parse_args() args = parser.parse_args()
validate_args(args) validate_args(args)
op_requires_identity = (args.sign or args.encrypt or args.decrypt or args.hash or args.announce or args.write op_requires_identity = (args.sign or args.encrypt or args.decrypt or args.announce or args.write
or args.print_identity or args.print_identity or args.export_pub or args.export_prv) or args.print_identity or args.print_identity or args.export_pub or args.export_prv)
identity = get_operating_identity(args); op = False identity = get_operating_identity(args, allow_none=not op_requires_identity, no_cache=args.no_cache); op = False
if not identity and op_requires_identity: print("Could not get working identity"); exit(R_NO_IDENTITY) if not identity and op_requires_identity: print("Could not get working identity"); exit(R_NO_IDENTITY)
if args.print_identity: print_identity_information(args, identity); op = True if args.print_identity: print_identity_information(args, identity); op = True
if args.export_pub: export_pub_identity(args, identity); op = True if args.export_pub: export_pub_identity(args, identity); op = True
if args.export_prv: export_prv_identity(args, identity); op = True if args.export_prv: export_prv_identity(args, identity); op = True
if args.hash: print_hash_information(args, identity); op = True if args.hash: print_hash_information(args, identity or args.identity); op = True
if args.announce: announce(args, identity); op = True if args.announce: announce(args, identity); op = True
if args.validate: validate(args, identity); op = True if args.validate: validate(args, identity); op = True
if args.sign: sign(args, identity); op = True if args.sign: sign(args, identity); op = True
@@ -182,7 +183,7 @@ def ensure_reticulum(args):
# Identity Loading & Resolution # # Identity Loading & Resolution #
################################# #################################
def get_operating_identity(args): def get_operating_identity(args, allow_none=False, no_cache=False):
global reticulum global reticulum
identity = None identity = None
@@ -209,36 +210,45 @@ def get_operating_identity(args):
if not identity.get_private_key() or not identity.get_public_key(): if not identity.get_private_key() or not identity.get_public_key():
raise SystemError("Missing key data in loaded identity") raise SystemError("Missing key data in loaded identity")
except Exception as e: except Exception as e: print(f"Could not load Identity from specified file: {e}"); exit(R_INVALID_IDENTITY)
print(f"Could not load Identity from specified file: {e}")
exit(9) elif no_cache:
if allow_none: return None
else: print("Could not resolve identity"); exit(R_NO_IDENTITY)
# Attempt to recall Identity from hex-encoded hash # Attempt to recall Identity from hex-encoded hash
elif len(args.identity) == RNS.Reticulum.TRUNCATED_HASHLENGTH//8*2: elif len(args.identity) == RNS.Reticulum.TRUNCATED_HASHLENGTH//8*2:
try: try:
ensure_reticulum(args) ensure_reticulum(args)
ident_hash = bytes.fromhex(args.identity) requested_hash = bytes.fromhex(args.identity)
identity = RNS.Identity.recall(ident_hash) or RNS.Identity.recall(ident_hash, from_identity_hash=True) identity = RNS.Identity.recall(requested_hash) or RNS.Identity.recall(requested_hash, from_identity_hash=True)
if identity == None: if identity == None:
if not args.request: if allow_none and not args.request: return None
print("Could not recall Identity for "+RNS.prettyhexrep(ident_hash)+".") elif not args.request:
print("Could not recall Identity for "+RNS.prettyhexrep(requested_hash)+".")
print("You can query the network for unknown Identities with the -R option.") print("You can query the network for unknown Identities with the -R option.")
exit(5) exit(R_NO_IDENTITY)
else: else:
RNS.Transport.request_path(ident_hash) id_destination_hash = RNS.Destination.hash_from_name_and_identity(DEFAULT_ASPECTS, identity)
def spincheck(): return RNS.Identity.recall(ident_hash) != None RNS.Transport.request_path(requested_hash) # Acquire if this was a destination hash
spin(spincheck, "Requesting unknown Identity for "+RNS.prettyhexrep(ident_hash), args.t) RNS.Transport.request_path(id_destination_hash) # Acquire if this was an identity hash
def spincheck(): return RNS.Identity.recall(requested_hash) != None
spin(spincheck, "Requesting unknown Identity for "+RNS.prettyhexrep(requested_hash), args.t)
if not spincheck(): print("Identity request timed out"); exit(6) if not spincheck():
print("Identity request timed out");
if not allow_none: exit(R_NO_IDENTITY)
else: return None
else: else:
identity = RNS.Identity.recall(ident_hash) identity = RNS.Identity.recall(requested_hash)
print("Received Identity "+str(identity)+" for destination "+RNS.prettyhexrep(ident_hash)+" from the network") print("Received Identity "+str(identity)+" for destination "+RNS.prettyhexrep(requested_hash)+" from the network")
else: else:
ident_str = str(identity) ident_str = str(identity)
hash_str = RNS.prettyhexrep(ident_hash) hash_str = RNS.prettyhexrep(requested_hash)
if ident_str == hash_str: print(f"Recalled Identity {ident_str}") if ident_str == hash_str: print(f"Recalled Identity {ident_str}")
else: print(f"Recalled Identity {ident_str} for destination {hash_str}") else: print(f"Recalled Identity {ident_str} for destination {hash_str}")
@@ -284,13 +294,9 @@ def get_operating_identity(args):
print("Reticulum Identity imported from base64 input") print("Reticulum Identity imported from base64 input")
except: pass except: pass
if not identity_bytes: if not identity_bytes: print("Could not decode specified data to a valid public Reticulum Identity"); exit(R_INVALID_IDENTITY)
print("Could not decode specified data to a valid public Reticulum Identity")
exit(41)
except Exception as e: except Exception as e: print("Invalid identity data specified for private identity import: "+str(e)); exit(R_INVALID_IDENTITY)
print("Invalid identity data specified for private identity import: "+str(e))
exit(41)
elif args.import_prv: elif args.import_prv:
try: try:
@@ -327,27 +333,19 @@ def get_operating_identity(args):
print("Reticulum Identity imported from base64 input") print("Reticulum Identity imported from base64 input")
except: pass except: pass
if not identity_bytes: if not identity_bytes: print("Could not decode specified data to a valid private Reticulum Identity"); exit(R_INVALID_IDENTITY)
print("Could not decode specified data to a valid private Reticulum Identity")
exit(41)
except Exception as e: except Exception as e: print("Invalid identity data specified for private identity import: "+str(e)); exit(R_INVALID_IDENTITY)
print("Invalid identity data specified for private identity import: "+str(e))
exit(41)
if args.import_prv: if args.import_prv:
try: identity = RNS.Identity.from_bytes(identity_bytes) try: identity = RNS.Identity.from_bytes(identity_bytes)
except Exception as e: except Exception as e: print("Could not create Reticulum identity from specified data: "+str(e)); exit(R_INVALID_IDENTITY)
print("Could not create Reticulum identity from specified data: "+str(e))
exit(42)
elif args.import_pub: elif args.import_pub:
try: try:
identity = RNS.Identity(create_keys=False) identity = RNS.Identity(create_keys=False)
identity.load_public_key(identity_bytes) identity.load_public_key(identity_bytes)
except Exception as e: except Exception as e: print("Could not create Reticulum identity from specified data: "+str(e)); exit(R_INVALID_IDENTITY)
print("Could not create Reticulum identity from specified data: "+str(e))
exit(42)
return identity return identity
@@ -661,15 +659,30 @@ def print_identity_information(args, identity):
def print_hash_information(args, identity): def print_hash_information(args, identity):
try: try:
hashlen = RNS.Reticulum.TRUNCATED_HASHLENGTH//8*2
if not type(identity) in [RNS.Identity, str]: print("Invalid identity"); exit(R_INVALID_IDENTITY)
if type(identity) == str and len(identity) != hashlen: print("Invalid identity hash length"); exit(R_INVALID_IDENTITY)
aspects = args.hash.split(".") aspects = args.hash.split(".")
if not len(aspects) > 0: print("Invalid destination aspects specified"); exit(R_INVALID_ASPECTS) if not len(aspects) > 0: print("Invalid destination aspects specified"); exit(R_INVALID_ASPECTS)
else: else:
app_name = aspects[0]; aspects = aspects[1:] app_name = aspects[0]; aspects = aspects[1:]
if not identity.get_public_key(): print("Identity does not hold a public key"); exit(R_NO_PUBKEY) if type(identity) == RNS.Identity and not identity.get_public_key(): print("Identity does not hold a public key"); exit(R_NO_PUBKEY)
else: else:
destination = RNS.Destination(identity, RNS.Destination.OUT, RNS.Destination.SINGLE, app_name, *aspects) if type(identity) == RNS.Identity:
print("The "+str(args.hash)+" destination for this Identity is "+RNS.prettyhexrep(destination.hash)) identity_hash = identity.hash
print("The full destination specifier is "+str(destination)) destination = RNS.Destination(identity, RNS.Destination.OUT, RNS.Destination.SINGLE, app_name, *aspects)
elif type(identity) == str:
destination = None
try: identity_hash = bytes.fromhex(identity)
except Exception as e: print(f"Invalid identity: {e}"); exit(R_INVALID_IDENTITY)
else: print("Invalid identity"); exit(R_INVALID_IDENTITY)
destination_hash = RNS.Destination.hash_from_name_and_identity(args.hash, identity_hash)
print(f"The {args.hash} destination for this Identity is {RNS.prettyhexrep(destination_hash)}")
if destination: print("The full destination specifier is "+str(destination))
except Exception as e: print(f"An error ocurred while attempting to get hash information: {e}"); exit(R_UNKNOWN_ERROR) except Exception as e: print(f"An error ocurred while attempting to get hash information: {e}"); exit(R_UNKNOWN_ERROR)