From 67fb1804f322cb44796a5291fd0031c26168e0d1 Mon Sep 17 00:00:00 2001 From: Philip Feairheller Date: Sat, 18 May 2024 13:58:48 -0700 Subject: [PATCH] Updates to delegation processing to fix delegation. Reversed the order of witness receipting and delegation approval request and updated command line tools to work correctly. Re-enabled the delegate.sh script in CI/CD. (#784) Signed-off-by: pfeairheller --- scripts/demo/basic/delegate.sh | 4 +- scripts/demo/test_scripts.sh | 6 +- src/keri/app/cli/commands/delegate/confirm.py | 16 ++--- src/keri/app/cli/commands/incept.py | 13 ++-- src/keri/app/cli/commands/rotate.py | 4 +- src/keri/app/delegating.py | 67 ++++++++++--------- src/keri/core/eventing.py | 22 ------ src/keri/core/parsing.py | 4 +- src/keri/db/basing.py | 5 +- 9 files changed, 56 insertions(+), 85 deletions(-) diff --git a/scripts/demo/basic/delegate.sh b/scripts/demo/basic/delegate.sh index cefc2fa3e..4a1e40dfb 100755 --- a/scripts/demo/basic/delegate.sh +++ b/scripts/demo/basic/delegate.sh @@ -9,7 +9,6 @@ kli incept --name delegate --alias delegate --proxy proxy --file ${KERI_DEMO_SCR pid=$! PID_LIST+=" $pid" -sleep 2 kli delegate confirm --name delegator --alias delegator -Y & pid=$! PID_LIST+=" $pid" @@ -23,10 +22,11 @@ kli rotate --name delegate --alias delegate --proxy proxy & pid=$! PID_LIST="$pid" -sleep 2 echo "Checking for delegate rotate..." kli delegate confirm --name delegator --alias delegator -Y & pid=$! PID_LIST+=" $pid" wait $PID_LIST + +kli status --name delegate --alias delegate diff --git a/scripts/demo/test_scripts.sh b/scripts/demo/test_scripts.sh index 8fe0a4c29..dd2c3cc88 100755 --- a/scripts/demo/test_scripts.sh +++ b/scripts/demo/test_scripts.sh @@ -42,10 +42,10 @@ printf "\n************************************\n" isSuccess printf "\n************************************\n" -printf "Skipping delegate.sh" +printf "Running delegate.sh" printf "\n************************************\n" -#"${script_dir}/basic/delegate.sh" -#isSuccess +"${script_dir}/basic/delegate.sh" +isSuccess printf "\n************************************\n" printf "Running multisig.sh" diff --git a/src/keri/app/cli/commands/delegate/confirm.py b/src/keri/app/cli/commands/delegate/confirm.py index 0161a2eec..a595630e4 100644 --- a/src/keri/app/cli/commands/delegate/confirm.py +++ b/src/keri/app/cli/commands/delegate/confirm.py @@ -96,9 +96,8 @@ def confirmDo(self, tymth, tock=0.0): while True: esc = self.escrowed() - for ekey, edig in esc: - pre, sn = dbing.splitKeySN(ekey) # get pre and sn from escrow item - dgkey = dbing.dgKey(pre, bytes(edig)) + for pre, sn, edig in esc: + dgkey = dbing.dgKey(pre, edig) eraw = self.hby.db.getEvt(dgkey) if eraw is None: continue @@ -204,6 +203,7 @@ def confirmDo(self, tymth, tock=0.0): print(f"Delegate {eserder.pre} {typ} event committed.") + self.hby.db.delegables.rem(keys=(pre, sn)) self.remove(self.toRemove) return True @@ -213,12 +213,6 @@ def confirmDo(self, tymth, tock=0.0): def escrowed(self): esc = [] - key = ekey = b'' # both start same. when not same means escrows found - while True: # break when done - for ekey, edig in self.hby.db.getPseItemsNextIter(key=key): - esc.append((ekey, edig)) - if ekey == key: # still same so no escrows found on last while iteration - break - key = ekey # setup next while iteration, with key after ekey - + for (pre, sn), edig in self.hby.db.delegables.getItemIter(): + esc.append((pre, sn, edig)) return esc diff --git a/src/keri/app/cli/commands/incept.py b/src/keri/app/cli/commands/incept.py index 68e771c45..3576f797b 100644 --- a/src/keri/app/cli/commands/incept.py +++ b/src/keri/app/cli/commands/incept.py @@ -137,16 +137,15 @@ def __init__(self, name, base, alias, bran, endpoint, proxy=None, cnfg=None, **k clear=False) self.endpoint = endpoint self.proxy = proxy - hby = existing.setupHby(name=name, base=base, bran=bran, cf=cf) - self.hbyDoer = habbing.HaberyDoer(habery=hby) # setup doer - self.swain = delegating.Anchorer(hby=hby) - self.postman = forwarding.Poster(hby=hby) - self.mbx = indirecting.MailboxDirector(hby=hby, topics=['/receipt', "/replay", "/reply"]) + self.hby = existing.setupHby(name=name, base=base, bran=bran, cf=cf) + self.hbyDoer = habbing.HaberyDoer(habery=self.hby) # setup doer + self.swain = delegating.Anchorer(hby=self.hby, proxy=self.hby.habByName(self.proxy)) + self.postman = forwarding.Poster(hby=self.hby) + self.mbx = indirecting.MailboxDirector(hby=self.hby, topics=['/receipt', "/replay", "/reply"]) doers = [self.hbyDoer, self.postman, self.mbx, self.swain, doing.doify(self.inceptDo)] self.inits = kwa self.alias = alias - self.hby = hby super(InceptDoer, self).__init__(doers=doers) def inceptDo(self, tymth, tock=0.0): @@ -169,7 +168,7 @@ def inceptDo(self, tymth, tock=0.0): self.extend([witDoer, receiptor]) if hab.kever.delpre: - self.swain.delegation(pre=hab.pre, sn=0, proxy=self.hby.habByName(self.proxy)) + self.swain.delegation(pre=hab.pre, sn=0) print("Waiting for delegation approval...") while not self.swain.complete(hab.kever.prefixer, coring.Seqner(sn=hab.kever.sn)): yield self.tock diff --git a/src/keri/app/cli/commands/rotate.py b/src/keri/app/cli/commands/rotate.py index c5eb3b586..530288b94 100644 --- a/src/keri/app/cli/commands/rotate.py +++ b/src/keri/app/cli/commands/rotate.py @@ -151,7 +151,7 @@ def __init__(self, name, base, bran, alias, endpoint=False, isith=None, nsith=No self.hby = existing.setupHby(name=name, base=base, bran=bran) self.hbyDoer = habbing.HaberyDoer(habery=self.hby) # setup doer - self.swain = delegating.Anchorer(hby=self.hby) + self.swain = delegating.Anchorer(hby=self.hby, proxy=self.hby.habByName(self.proxy)) self.postman = forwarding.Poster(hby=self.hby) self.mbx = indirecting.MailboxDirector(hby=self.hby, topics=['/receipt', "/replay", "/reply"]) doers = [self.hbyDoer, self.mbx, self.swain, self.postman, doing.doify(self.rotateDo)] @@ -198,7 +198,7 @@ def rotateDo(self, tymth, tock=0.0): auths[wit] = f"{code}#{helping.nowIso8601()}" if hab.kever.delpre: - self.swain.delegation(pre=hab.pre, sn=hab.kever.sn, proxy=self.hby.habByName(self.proxy)) + self.swain.delegation(pre=hab.pre, sn=hab.kever.sn) print("Waiting for delegation approval...") while not self.swain.complete(hab.kever.prefixer, coring.Seqner(sn=hab.kever.sn)): yield self.tock diff --git a/src/keri/app/delegating.py b/src/keri/app/delegating.py index 2ffa80ce6..fcbdb053b 100644 --- a/src/keri/app/delegating.py +++ b/src/keri/app/delegating.py @@ -47,50 +47,30 @@ def __init__(self, hby, proxy=None, **kwa): self.proxy = proxy super(Anchorer, self).__init__(doers=[self.witq, self.witDoer, self.postman, doing.doify(self.escrowDo)], - **kwa) + **kwa) def delegation(self, pre, sn=None, proxy=None): if pre not in self.hby.habs: raise kering.ValidationError(f"{pre} is not a valid local AID for delegation") + if proxy is not None: + self.proxy = proxy + # load the hab of the delegated identifier to anchor hab = self.hby.habs[pre] delpre = hab.kever.delpre # get the delegator identifier if delpre not in hab.kevers: raise kering.ValidationError(f"delegator {delpre} not found, unable to process delegation") - dkever = hab.kevers[delpre] # and the delegator's kever sn = sn if sn is not None else hab.kever.sner.num # load the event and signatures evt = hab.makeOwnEvent(sn=sn) - smids = [] - if isinstance(hab, GroupHab): - phab = hab.mhab - smids = hab.smids - elif proxy is not None: - phab = proxy - elif hab.kever.sn > 0: - phab = hab - elif self.proxy is not None: - phab = self.proxy - else: - raise kering.ValidationError("no proxy to send messages for delegation") - # Send exn message for notification purposes - exn, atc = delegateRequestExn(phab, delpre=delpre, evt=bytes(evt), aids=smids) - - self.postman.send(hab=phab, dest=hab.kever.delpre, topic="delegate", serder=exn, attachment=atc) - srdr = serdering.SerderKERI(raw=evt) - del evt[:srdr.size] - self.postman.send(hab=phab, dest=delpre, topic="delegate", serder=srdr, attachment=evt) - - seal = dict(i=srdr.pre, s=srdr.snh, d=srdr.said) - self.witq.query(hab=phab, pre=dkever.prefixer.qb64, anchor=seal) - - self.hby.db.dune.pin(keys=(srdr.pre, srdr.said), val=srdr) + self.witDoer.msgs.append(dict(pre=pre, sn=srdr.sn)) + self.hby.db.dpwe.pin(keys=(srdr.pre, srdr.said), val=srdr) def complete(self, prefixer, seqner, saider=None): """ Check for completed delegation protocol for the specific event @@ -139,8 +119,8 @@ def escrowDo(self, tymth, tock=1.0): yield 0.5 def processEscrows(self): - self.processUnanchoredEscrow() self.processPartialWitnessEscrow() + self.processUnanchoredEscrow() def processUnanchoredEscrow(self): """ @@ -159,11 +139,10 @@ def processUnanchoredEscrow(self): couple = seqner.qb64b + dserder.saidb dgkey = dbing.dgKey(kever.prefixer.qb64b, kever.serder.saidb) self.hby.db.setAes(dgkey, couple) # authorizer event seal (delegator/issuer) - self.witDoer.msgs.append(dict(pre=pre, sn=serder.sn)) # Move to escrow waiting for witness receipts - logger.info(f"Waiting for fully signed witness receipts for {serder.sn}") - self.hby.db.dpwe.pin(keys=(pre, said), val=serder) + logger.info(f"Delegation approval received, {serder.pre} confirmed") + self.hby.db.cdel.put(keys=(pre, coring.Seqner(sn=serder.sn).qb64), val=coring.Saider(qb64=serder.said)) self.hby.db.dune.rem(keys=(pre, said)) def processPartialWitnessEscrow(self): @@ -188,9 +167,33 @@ def processPartialWitnessEscrow(self): witnessed = True if not witnessed: continue - logger.info(f"Witness receipts complete, {pre} confirmed.") + logger.info(f"Witness receipts complete, waiting for delegation approval.") + hab = self.hby.habs[pre] + delpre = hab.kever.delpre # get the delegator identifier + dkever = hab.kevers[delpre] # and the delegator's kever + smids = [] + if isinstance(hab, GroupHab): + phab = hab.mhab + smids = hab.smids + elif self.proxy is not None: + phab = self.proxy + else: + raise kering.ValidationError("no proxy to send messages for delegation") + + evt = hab.db.cloneEvtMsg(pre=serder.pre, fn=0, dig=serder.said) + exn, atc = delegateRequestExn(phab, delpre=delpre, evt=bytes(evt), aids=smids) + + self.postman.send(hab=phab, dest=hab.kever.delpre, topic="delegate", serder=exn, attachment=atc) + + srdr = serdering.SerderKERI(raw=evt) + del evt[:srdr.size] + self.postman.send(hab=phab, dest=delpre, topic="delegate", serder=srdr, attachment=evt) + + seal = dict(i=srdr.pre, s=srdr.snh, d=srdr.said) + self.witq.query(hab=phab, pre=dkever.prefixer.qb64, anchor=seal) + self.hby.db.dpwe.rem(keys=(pre, said)) - self.hby.db.cdel.put(keys=(pre, seqner.qb64), val=coring.Saider(qb64=serder.said)) + self.hby.db.dune.pin(keys=(srdr.pre, srdr.said), val=srdr) def loadHandlers(hby, exc, notifier): diff --git a/src/keri/core/eventing.py b/src/keri/core/eventing.py index 5285e5b3d..3e809dd6d 100644 --- a/src/keri/core/eventing.py +++ b/src/keri/core/eventing.py @@ -2632,38 +2632,16 @@ def validateDelegation(self, serder, sigers, wigers, wits, local=True, f" delegation by {delpre} of" f"event = {serder.ked}.") - # ToDo XXXX This logic moves to the Delegable escrow processing - # ToDo XXXX create process escrow for delegable events "dees." - #in order to get delegator approval - # any virtual delegation or sandboxing logic happens there - # create virtual anchor seal so local delegator can evaluate - # superseding logic with provisional virtual seal - #dkever = self.kevers[delpre] - #dseal = SealEvent(i=serder.pre, s=serder.snh, d=serder.said) - #dserder = interact(pre=dkever.prefixer.qb64, - #dig=dkever.serder.said, - #sn=dkever.sner.num + 1, - #data=[dseal._asdict()]) - #delseqner = coring.Seqner(snh=dserder.snh) - #delsaider = coring.Saider(qb64=dserder.said) - # ToDo XXXX need to cue task here to approve delegation by generating - # an anchoring SealEvent of serder in delegators KEL - # may include MFA and or business logic for the delegator i.e. is local - # event that designates this controller as delegator triggers - # this cue to approave delegation #self.cues.push(dict(kin="approveDelegation", #delegator=kever.delpre, #serder=serder)) - else: # not local delegator so escrow self.escrowPSEvent(serder=serder, sigers=sigers, wigers=wigers, local=local) raise MissingDelegationError(f"No delegation seal for delegator " "{delpre} of evt = {serder.ked}.") - #ssn = validateSN(sn=delseqner.snh, inceptive=False) # delseqner Number should already do this ssn = Number(num=delseqner.sn).validate(inceptive=False).sn - #ssn = sner.num sner is Number seqner is Seqner # ToDo XXXX need to replace Seqners with Numbers # get the dig of the delegating event. Using getKeLast ensures delegating diff --git a/src/keri/core/parsing.py b/src/keri/core/parsing.py index e5f7eb1a0..9273f6255 100644 --- a/src/keri/core/parsing.py +++ b/src/keri/core/parsing.py @@ -994,10 +994,10 @@ def msgParsator(self, ims=None, framed=True, pipeline=False, if cigars: kvy.processAttachedReceiptCouples(serder, cigars, - firner=firner, local=local) + firner=firner, local=local) if trqs: kvy.processAttachedReceiptQuadruples(serder, trqs, - firner=firner, local=local) + firner=firner, local=local) except AttributeError as ex: raise kering.ValidationError("No kevery to process so dropped msg" diff --git a/src/keri/db/basing.py b/src/keri/db/basing.py index db24fbd53..0a1ec1f0a 100644 --- a/src/keri/db/basing.py +++ b/src/keri/db/basing.py @@ -949,7 +949,7 @@ def reopen(self, **kwa): self.misfits = subing.IoSetSuber(db=self, subkey='mfes.') # delegable events escrows. events with local delegator that need approval - self.delegables = subing.CesrIoSetSuber(db=self, subkey='dees.', klas=coring.Diger) + self.delegables = subing.IoSetSuber(db=self, subkey='dees.') # events as ordered by first seen ordinals self.fons = subing.CesrSuber(db=self, subkey='fons.', klas=core.Number) @@ -1500,9 +1500,6 @@ def cloneEvtMsg(self, pre, fn, dig): atc.extend(coring.Counter(code=coring.CtrDex.SealSourceCouples, count=1).qb64b) atc.extend(couple) - elif self.kevers[pre].delegated: - if coring.SerderKERI(raw=raw).estive: - raise kering.MissingEntryError("Missing delegator anchor seal for dig={}.".format(dig)) # add trans endorsement quadruples to attachments not controller # may have been originally key event attachments or receipted endorsements