From c712ba6b878e4001d12ea15a8b6371c6bc6d8472 Mon Sep 17 00:00:00 2001 From: Philip Feairheller Date: Fri, 11 Oct 2024 12:37:32 -0700 Subject: [PATCH] Two command line changes: (#871) (#876) - OOBI resolve now waits until the AID is in Kevers before completing - Witness authenticate includes the CESR http header. Fix OOBI generation to favor HTTPS over HTTP and to honor the full URL of the service endpoint. Use the "Last" variant of the method for finding event seals in all locations. Signed-off-by: pfeairheller --- src/keri/app/cli/commands/did/generate.py | 16 +++++++------- src/keri/app/cli/commands/ipex/grant.py | 4 ++-- src/keri/app/cli/commands/oobi/generate.py | 22 +++++++++---------- src/keri/app/cli/commands/oobi/resolve.py | 5 +++++ .../app/cli/commands/witness/authenticate.py | 4 +++- src/keri/app/delegating.py | 2 +- src/keri/app/grouping.py | 4 ++-- src/keri/app/oobiing.py | 11 +++++----- src/keri/app/querying.py | 3 +-- src/keri/core/eventing.py | 18 +++++++-------- src/keri/db/basing.py | 1 - src/keri/end/ending.py | 2 +- 12 files changed, 47 insertions(+), 45 deletions(-) diff --git a/src/keri/app/cli/commands/did/generate.py b/src/keri/app/cli/commands/did/generate.py index 0200d40ba..0aca604ce 100644 --- a/src/keri/app/cli/commands/did/generate.py +++ b/src/keri/app/cli/commands/did/generate.py @@ -73,20 +73,20 @@ def generate(tymth, tock=0.0, **opts): sys.exit(-1) wit = random.choice(hab.kever.wits) - urls = hab.fetchUrls(eid=wit, scheme=kering.Schemes.http) or hab.fetchUrls(eid=wit, scheme=kering.Schemes.https) + urls = hab.fetchUrls(eid=wit, scheme=kering.Schemes.http) \ + or hab.fetchUrls(eid=wit, scheme=kering.Schemes.https) if not urls: raise kering.ConfigurationError(f"unable to query witness {wit}, no http endpoint") - url = urls[kering.Schemes.http] if kering.Schemes.http in urls else urls[kering.Schemes.https] - up = urlparse(url) - enc = urllib.parse.quote_plus(f"{up.scheme}://{up.hostname}:{up.port}/oobi/{hab.pre}/witness") + url = urls[kering.Schemes.https] if kering.Schemes.https in urls else urls[kering.Schemes.http] + enc = urllib.parse.quote_plus(f"{url.rstrip("/")}/oobi/{hab.pre}/witness") print(f"did:keri:{hab.pre}?oobi={enc}") elif role in (kering.Roles.controller,): - urls = hab.fetchUrls(eid=hab.pre, scheme=kering.Schemes.http) or hab.fetchUrls(eid=hab.pre, scheme=kering.Schemes.https) + urls = hab.fetchUrls(eid=hab.pre, scheme=kering.Schemes.http) \ + or hab.fetchUrls(eid=hab.pre, scheme=kering.Schemes.https) if not urls: print(f"{alias} identifier {hab.pre} does not have any controller endpoints") return - url = urls[kering.Schemes.http] if kering.Schemes.http in urls else urls[kering.Schemes.https] - up = urlparse(url) - enc = urllib.parse.quote_plus(f"{up.scheme}://{up.hostname}:{up.port}/oobi/{hab.pre}/controller") + url = urls[kering.Schemes.https] if kering.Schemes.https in urls else urls[kering.Schemes.http] + enc = urllib.parse.quote_plus(f"{url.rstrip("/")}/oobi/{hab.pre}/controller") print(f"did:keri:{hab.pre}?oobi={enc}") diff --git a/src/keri/app/cli/commands/ipex/grant.py b/src/keri/app/cli/commands/ipex/grant.py index cc766664a..5787089f6 100644 --- a/src/keri/app/cli/commands/ipex/grant.py +++ b/src/keri/app/cli/commands/ipex/grant.py @@ -111,8 +111,8 @@ def grantDo(self, tymth, tock=0.0): iserder = serdering.SerderKERI(raw=bytes(iss)) seqner = coring.Seqner(sn=iserder.sn) - serder = self.hby.db.fetchAllSealingEventByEventSeal(creder.sad['i'], - seal=dict(i=iserder.pre, s=seqner.snh, d=iserder.said)) + serder = self.hby.db.fetchLastSealingEventByEventSeal(creder.sad['i'], + seal=dict(i=iserder.pre, s=seqner.snh, d=iserder.said)) anc = self.hby.db.cloneEvtMsg(pre=serder.pre, fn=0, dig=serder.said) exn, atc = protocoling.ipexGrantExn(hab=self.hab, recp=recp, message=self.message, acdc=acdc, iss=iss, anc=anc, diff --git a/src/keri/app/cli/commands/oobi/generate.py b/src/keri/app/cli/commands/oobi/generate.py index e35a53354..406d5f08f 100644 --- a/src/keri/app/cli/commands/oobi/generate.py +++ b/src/keri/app/cli/commands/oobi/generate.py @@ -4,7 +4,6 @@ """ import argparse -from urllib.parse import urlparse import sys from hio import help @@ -66,21 +65,21 @@ def generate(tymth, tock=0.0, **opts): sys.exit(-1) for wit in hab.kever.wits: - urls = hab.fetchUrls(eid=wit, scheme=kering.Schemes.http) or hab.fetchUrls(eid=wit, scheme=kering.Schemes.https) + urls = hab.fetchUrls(eid=wit, scheme=kering.Schemes.http) \ + or hab.fetchUrls(eid=wit, scheme=kering.Schemes.https) if not urls: raise kering.ConfigurationError(f"unable to query witness {wit}, no http endpoint") - url = urls[kering.Schemes.http] if kering.Schemes.http in urls else urls[kering.Schemes.https] - up = urlparse(url) - print(f"{up.scheme}://{up.hostname}:{up.port}/oobi/{hab.pre}/witness") + url = urls[kering.Schemes.https] if kering.Schemes.https in urls else urls[kering.Schemes.http] + print(f"{url.rstrip("/")}/oobi/{hab.pre}/witness") elif role in (kering.Roles.controller,): - urls = hab.fetchUrls(eid=hab.pre, scheme=kering.Schemes.http) or hab.fetchUrls(eid=hab.pre, scheme=kering.Schemes.https) + urls = hab.fetchUrls(eid=hab.pre, scheme=kering.Schemes.http) \ + or hab.fetchUrls(eid=hab.pre, scheme=kering.Schemes.https) if not urls: print(f"{alias} identifier {hab.pre} does not have any controller endpoints") return - url = urls[kering.Schemes.http] if kering.Schemes.http in urls else urls[kering.Schemes.https] - up = urlparse(url) - print(f"{up.scheme}://{up.hostname}:{up.port}/oobi/{hab.pre}/controller") + url = urls[kering.Schemes.https] if kering.Schemes.https in urls else urls[kering.Schemes.http] + print(f"{url.rstrip("/")}/oobi/{hab.pre}/controller") elif role in (kering.Roles.mailbox,): for (_, _, eid), end in hab.db.ends.getItemIter(keys=(hab.pre, kering.Roles.mailbox, )): if not (end.allowed and end.enabled is not False): @@ -91,6 +90,5 @@ def generate(tymth, tock=0.0, **opts): if not urls: print(f"{alias} identifier {hab.pre} does not have any mailbox endpoints") return - url = urls[kering.Schemes.http] if kering.Schemes.http in urls else urls[kering.Schemes.https] - up = urlparse(url) - print(f"{up.scheme}://{up.hostname}:{up.port}/oobi/{hab.pre}/mailbox/{eid}") + url = urls[kering.Schemes.https] if kering.Schemes.https in urls else urls[kering.Schemes.http] + print(f"{url.rstrip("/")}/oobi/{hab.pre}/mailbox/{eid}") diff --git a/src/keri/app/cli/commands/oobi/resolve.py b/src/keri/app/cli/commands/oobi/resolve.py index dc6e62dc4..747c67c50 100644 --- a/src/keri/app/cli/commands/oobi/resolve.py +++ b/src/keri/app/cli/commands/oobi/resolve.py @@ -107,6 +107,11 @@ def waitDo(self, tymth, tock=0.0): yield 0.25 obr = self.obi.hby.db.roobi.get(keys=(self.oobi,)) + if self.force: + while obr.cid not in self.hby.kevers: + self.hby.kvy.processEscrows() + yield 0.25 + print(self.oobi, obr.state) self.remove([self.hbyDoer, *self.obi.doers, *self.authn.doers]) diff --git a/src/keri/app/cli/commands/witness/authenticate.py b/src/keri/app/cli/commands/witness/authenticate.py index f0a2b4192..532415361 100644 --- a/src/keri/app/cli/commands/witness/authenticate.py +++ b/src/keri/app/cli/commands/witness/authenticate.py @@ -16,6 +16,7 @@ from keri.app import httping, connecting from keri.app.agenting import httpClient from keri.app.cli.common import existing +from keri.app.httping import CESR_DESTINATION_HEADER from keri.core import coring logger = help.ogler.getLogger() @@ -107,7 +108,8 @@ def authDo(self, tymth, tock=0.0): fargs['delkel'] = delkel.decode("utf-8") headers = (Hict([ - ("Content-Type", "multipart/form-data") + ("Content-Type", "multipart/form-data"), + (CESR_DESTINATION_HEADER, self.witness) ])) client, clientDoer = httpClient(self.hab, self.witness) diff --git a/src/keri/app/delegating.py b/src/keri/app/delegating.py index bddb7dd4e..1e09e6596 100644 --- a/src/keri/app/delegating.py +++ b/src/keri/app/delegating.py @@ -138,7 +138,7 @@ def processUnanchoredEscrow(self): dkever = self.hby.kevers[kever.delpre] seal = dict(i=serder.pre, s=serder.snh, d=serder.said) - if dserder := self.hby.db.fetchAllSealingEventByEventSeal(dkever.prefixer.qb64, seal=seal): + if dserder := self.hby.db.fetchLastSealingEventByEventSeal(dkever.prefixer.qb64, seal=seal): seqner = coring.Seqner(sn=dserder.sn) couple = seqner.qb64b + dserder.saidb dgkey = dbing.dgKey(kever.prefixer.qb64b, kever.serder.saidb) diff --git a/src/keri/app/grouping.py b/src/keri/app/grouping.py index 096798f73..f87ef2490 100644 --- a/src/keri/app/grouping.py +++ b/src/keri/app/grouping.py @@ -171,8 +171,8 @@ def processDelegateEscrow(self): self.hby.db.cgms.put(keys=(pre, seqner.qb64), val=saider) else: # Not witnesser, we need to look for the anchor and then wait for receipts - if serder := self.hby.db.fetchAllSealingEventByEventSeal(kever.delpre, - seal=anchor): + if serder := self.hby.db.fetchLastSealingEventByEventSeal(kever.delpre, + seal=anchor): aseq = coring.Seqner(sn=serder.sn) couple = aseq.qb64b + serder.saidb dgkey = dbing.dgKey(pre, saider.qb64b) diff --git a/src/keri/app/oobiing.py b/src/keri/app/oobiing.py index cb8b41d3a..7228b9187 100644 --- a/src/keri/app/oobiing.py +++ b/src/keri/app/oobiing.py @@ -115,15 +115,15 @@ def on_get_alias(self, req, rep, alias=None): if role in (kering.Roles.witness,): # Fetch URL OOBIs for all witnesses oobis = [] for wit in hab.kever.wits: - urls = hab.fetchUrls(eid=wit, scheme=kering.Schemes.http) or hab.fetchUrls(eid=wit, scheme=kering.Schemes.https) + urls = hab.fetchUrls(eid=wit, scheme=kering.Schemes.http) \ + or hab.fetchUrls(eid=wit, scheme=kering.Schemes.https) if not urls: rep.status = falcon.HTTP_404 rep.text = f"unable to query witness {wit}, no http endpoint" return - url = urls[kering.Schemes.http] if kering.Schemes.http in urls else urls[kering.Schemes.https] - up = urlparse(url) - oobis.append(f"{up.scheme}://{up.hostname}:{up.port}/oobi/{hab.pre}/witness/{wit}") + url = urls[kering.Schemes.https] if kering.Schemes.https in urls else urls[kering.Schemes.http] + oobis.append(f"{url.rstrip("/")}/oobi/{hab.pre}/witness/{wit}") res["oobis"] = oobis elif role in (kering.Roles.controller,): # Fetch any controller URL OOBIs oobis = [] @@ -134,8 +134,7 @@ def on_get_alias(self, req, rep, alias=None): rep.text = f"unable to query controller {hab.pre}, no http endpoint" return url = urls[kering.Schemes.http] if kering.Schemes.http in urls else urls[kering.Schemes.https] - up = urlparse(url) - oobis.append(f"{up.scheme}://{up.hostname}:{up.port}/oobi/{hab.pre}/controller") + oobis.append(f"{url.rstrip("/")}/oobi/{hab.pre}/controller") res["oobis"] = oobis else: rep.status = falcon.HTTP_404 diff --git a/src/keri/app/querying.py b/src/keri/app/querying.py index b6a401ada..21ff01297 100644 --- a/src/keri/app/querying.py +++ b/src/keri/app/querying.py @@ -140,8 +140,7 @@ def recur(self, tyme, deeds=None): if self.pre not in self.hab.kevers: return False - kever = self.hab.kevers[self.pre] - if self.hby.db.fetchAllSealingEventByEventSeal(self.pre, seal=self.anchor): + if self.hby.db.fetchLastSealingEventByEventSeal(self.pre, seal=self.anchor): self.remove([self.witq]) return True diff --git a/src/keri/core/eventing.py b/src/keri/core/eventing.py index b244af681..3e8ba393f 100644 --- a/src/keri/core/eventing.py +++ b/src/keri/core/eventing.py @@ -3020,22 +3020,22 @@ def fetchDelegatingEvent(self, delpre, serder, *, original=True, eager=False): dserder = serdering.SerderKERI(raw=bytes(raw)) return dserder - elif eager: #missing aes but try to find seal by walking delegator's KEL + elif eager: # missing aes but try to find seal by walking delegator's KEL seal = SealEvent(i=serder.pre, s=serder.snh, d=serder.said)._asdict if original: # search all events in delegator's kel not just last - if not (dserder:=self.db.fetchAllSealingEventByEventSeal(pre=delpre, - seal=seal)): + if not (dserder := self.db.fetchLastSealingEventByEventSeal(pre=delpre, + seal=seal)): # database broken this should never happen so do not validate # since original must have been validated so it must have # all its delegation chain. raise ValidationError(f"Missing delegation source seal for {serder.ked}") - else: # only search last events in delegator's kel - if not (dserder:=self.db.fetchLastSealingEventByEventSeal(pre=delpre, - seal=seal)): + else: # only search last events in delegator's kel + if not (dserder := self.db.fetchLastSealingEventByEventSeal(pre=delpre, + seal=seal)): # superseding delegation may not have happened yet so escrow # ToDo XXXX need to cue up to get latest events in # delegator's kel. - #raise ValidationError(f"Missing delegation source seal for {serder.ked}") + # raise ValidationError(f"Missing delegation source seal for {serder.ked}") return None # Only repair .aess when found delegation is for delegated event that @@ -3788,7 +3788,7 @@ def processEvent(self, serder, sigers, *, wigers=None, else: # not inception so can't verify sigs etc, add to out-of-order escrow self.escrowOOEvent(serder=serder, sigers=sigers, - seqner=delseqner, saider=delsaider, wigers=wigers) + seqner=delseqner, saider=delsaider, wigers=wigers, local=local) raise OutOfOrderError("Out-of-order event={}.".format(ked)) else: # already accepted inception event for pre so already first seen @@ -3829,7 +3829,7 @@ def processEvent(self, serder, sigers, *, wigers=None, if sn > sno: # sn later than sno so out of order escrow # escrow out-of-order event self.escrowOOEvent(serder=serder, sigers=sigers, - seqner=delseqner, saider=delsaider, wigers=wigers) + seqner=delseqner, saider=delsaider, wigers=wigers, local=local) raise OutOfOrderError("Out-of-order event={}.".format(ked)) elif ((sn == sno) or # inorder event (ixn, rot, drt) or diff --git a/src/keri/db/basing.py b/src/keri/db/basing.py index 32077072b..35fc63626 100644 --- a/src/keri/db/basing.py +++ b/src/keri/db/basing.py @@ -1726,7 +1726,6 @@ def fetchAllSealingEventByEventSeal(self, pre, seal, sn=0): # use alias here until can change everywhere for backwards compatibility findAnchoringSealEvent = fetchAllSealingEventByEventSeal # alias - def fetchLastSealingEventByEventSeal(self, pre, seal, sn=0): """ Search through a KEL for the last event at any sn but that contains a diff --git a/src/keri/end/ending.py b/src/keri/end/ending.py index 6ff62ef65..72729316f 100644 --- a/src/keri/end/ending.py +++ b/src/keri/end/ending.py @@ -275,7 +275,7 @@ def siginput(name, method, path, headers, fields, hab=None, signers=None, expire expires (str): iso8601 formated date string indicating exiration of header signature signers (list): Optional signer objects used to sign the values hab (Hab): Optional Hab used to sign the values. One of signers or Hab is required - fields (str): Fields in request to sign. Includes special fields as well as Header fields + fields (list): Fields in request to sign. Includes special fields as well as Header fields headers (dict): HTTP request headers path (str): HTTP request path method (str): HTTP request method (POST, GET, PUT, etc)