-
Notifications
You must be signed in to change notification settings - Fork 70
fix: kli delegate confirm no longer hangs; and other delegated ixn fixes #1100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2c824fe
069df1b
ccc8f4f
3a66908
0ab751f
90cae71
1c1c71e
780d8f5
4b3806c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -121,12 +121,10 @@ def confirmDo(self, tymth, tock=0.0): | |
| if ilk in (coring.Ilks.dip,): | ||
| typ = "inception" | ||
| delpre = eserder.sad["di"] | ||
|
|
||
| elif ilk in (coring.Ilks.drt,): | ||
| typ = "rotation" | ||
| dkever = self.hby.kevers[eserder.pre] | ||
| delpre = dkever.delpre | ||
|
|
||
| else: | ||
| continue | ||
|
|
||
|
|
@@ -170,11 +168,11 @@ def confirmDo(self, tymth, tock=0.0): | |
| saider = self.hby.db.cgms.get(keys=(prefixer.qb64, sner.qb64)) | ||
| if saider is not None: | ||
| break | ||
|
|
||
| yield self.tock | ||
|
|
||
| print(f"Delegate {eserder.pre} {typ} event committed.") | ||
| print(f"Delegate {typ} event {eserder.pre} committed.") | ||
|
|
||
| self.hby.db.delegables.rem(keys=(pre, sn), val=edig) | ||
| self.remove(self.toRemove) | ||
| return True | ||
|
|
||
|
|
@@ -211,27 +209,23 @@ def confirmDo(self, tymth, tock=0.0): | |
| while not witDoer.cues: | ||
| _ = yield self.tock | ||
|
|
||
| print(f'Delegagtor Prefix {hab.pre}') | ||
| print(f'\tDelegate {eserder.pre} {typ} Anchored at Seq. No. {hab.kever.sner.num}') | ||
| print(f'Delegagtor Prefix {hab.pre}') | ||
| print(f'\tDelegate {typ} event {eserder.pre} Anchored at Seq. No. {hab.kever.sner.num}') | ||
|
|
||
| # wait for confirmation of fully commited event | ||
| if eserder.pre in self.hby.kevers: | ||
| self.witq.query(src=hab.pre, pre=eserder.pre, sn=eserder.sn) | ||
|
|
||
| while eserder.sn < self.hby.kevers[eserder.pre].sn: | ||
| yield self.tock | ||
|
|
||
| print(f"Delegate {eserder.pre} {typ} event committed.") | ||
| else: # It should be an inception event then... | ||
| wits = [werfer.qb64 for werfer in eserder.berfers] | ||
| self.witq.query(src=hab.pre, pre=eserder.pre, sn=eserder.sn, wits=wits) | ||
|
|
||
| while eserder.pre not in self.hby.kevers: | ||
| yield self.tock | ||
|
|
||
| print(f"Delegate {eserder.pre} {typ} event committed.") | ||
| print(f"Delegate {typ} event {eserder.pre} committed.") | ||
|
|
||
| self.hby.db.delegables.rem(keys=(pre, sn)) | ||
| self.hby.db.delegables.rem(keys=(pre, sn), val=edig) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
| self.remove(self.toRemove) | ||
| return True | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -187,7 +187,7 @@ def incept(self, attrs): | |
|
|
||
| inits["toad"] = oicp.ked["bt"] | ||
| inits["wits"] = oicp.ked["b"] | ||
| inits["delpre"] = oicp.ked["di"] if "di" in ked else None | ||
| inits["delpre"] = oicp.ked["di"] if "di" in oicp.ked else None | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was a bug that prevented |
||
|
|
||
| print() | ||
| print("Group Multisig Inception proposed:") | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -102,7 +102,7 @@ def openHab(name="test", base="", salt=None, temp=True, cf=None, **kwa): | |
|
|
||
| with openHby(name=name, base=base, salt=salt, temp=temp, cf=cf) as hby: | ||
| if (hab := hby.habByName(name)) is None: | ||
| hab = hby.makeHab(name=name, icount=1, isith='1', ncount=1, nsith='1', **kwa) | ||
| hab = hby.makeHab(name=name, icount=1, isith='1', ncount=1, nsith='1', cf=cf, **kwa) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. small config bugfix to make so |
||
|
|
||
| yield hby, hab | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1682,27 +1682,58 @@ def locallyOwned(self, pre: str | None = None): | |
|
|
||
|
|
||
| def locallyDelegated(self, pre: str): | ||
| """Returns True if pre is in .prefixes and not in .groups | ||
| False otherwise. Use when pre is a delegator for some event and | ||
| want to confirm that pre is also locallyOwned thereby making the | ||
| associated event locallyDelegated. | ||
| """Returns True if pre w is in .prefixes which includes group AIDs in | ||
| self.groups which have a local member AID. | ||
|
|
||
| Which means it is either locally controlled single sig or a multi-sig | ||
| group with a locally controlled member. | ||
| False otherwise. | ||
|
|
||
| Use when pre is a delegator, i.e. the delpre from some delegated event and | ||
| want to confirm that pre is also locally controller as either the single | ||
| sig AID or the group multisig AID of a locally controlled member of the group. | ||
|
|
||
| Indicates that provided identifier prefix is controlled by a local | ||
| controller from .prefixes but is not a group with local member. | ||
| i.e pre is a locally owned (controlled) AID (identifier prefix) | ||
| controller from .prefixes is a group prefix that is controlled by a local | ||
| member of that group. | ||
|
|
||
| Because delpre may be None, changes the default to "" instead of | ||
| self.prefixer.pre because self.prefixer.pre is delegate not delegator | ||
| of self. Unaccepted dip events do not have self.delpre set yet. | ||
|
|
||
| Returns: | ||
| (bool): True if pre is local hab but not group hab | ||
| (bool): True if pre is local hab or group hab that has a local member | ||
| When pre="" empty or None then returns False | ||
|
|
||
| Parameters: | ||
| pre (str): qb64 identifier prefix if any. | ||
|
|
||
|
|
||
| ToDo: this code does not account for stale group members as delegators. | ||
| i.e. a stale group membed is a member AID for a group AID in .groups | ||
| for which the member AID was a signing (smids) or rotating (rmids) member | ||
| in the past but is no longer. For delegation approval there must be | ||
| a local member for the delegator group AID that is a current signing member | ||
| i,e. in .smids for the group hab. | ||
|
|
||
| The current logic allows an event to be escrowed for later approval | ||
| but whose delpre (delegator) is a group with a stale local member | ||
| That later approval must detect and properly handle the staleness. | ||
|
|
||
| Alternatively the logic could be changed to short circut that later | ||
| work by checking here for staleness. For example: | ||
| delpre.mhab.pre in delpre's hab.smids (not stale ) | ||
|
|
||
|
|
||
| if pre in self.groups: # local group delegator | ||
| habord = self.db.habs.get(keys=(pre,)) | ||
| return habord.mid in habord.smids # True not stale, False stale | ||
|
|
||
| return pre in self.prefixes # otherwise local non-group delegator | ||
|
|
||
| """ | ||
| pre = pre if pre is not None else "" | ||
| return self.locallyOwned(pre=pre) | ||
| return pre in self.prefixes | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is part of the big delegation fix.
|
||
|
|
||
|
|
||
| def locallyWitnessed(self, *, wits: list[str]=None, serder: (str)=None): | ||
|
|
@@ -2388,8 +2419,7 @@ def valSigsWigsDel(self, serder, sigers, verfers, tholder, | |
| # seal in this case can't be malicious since sourced locally. | ||
| # Doesn't get to here until fully signed and witnessed. | ||
|
|
||
| if self.locallyDelegated(delpre) and not self.locallyOwned(): # local delegator | ||
| # must be local if locallyDelegated or caught above as misfit | ||
| if serder.ilk in (Ilks.dip, Ilks.drt) and self.locallyDelegated(delpre) and not self.locallyOwned(): # local delegator of delegated event | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the big fix to Only delegated inception and delegated rotation should be going to the delegables escrow. |
||
| if delseqner is None or delsaider is None: # missing delegation seal | ||
| # so escrow delegable. So local delegator can approve OOB. | ||
| # and create delegator event with valid event seal of this | ||
|
|
@@ -5408,6 +5438,7 @@ def processEscrows(self): | |
| self.processEscrowPartialWigs() | ||
| self.processEscrowPartialSigs() | ||
| self.processEscrowDuplicitous() | ||
| self.processEscrowDelegables() | ||
| self.processQueryNotFound() | ||
|
|
||
| except Exception as ex: # log diagnostics errors etc | ||
|
|
@@ -6398,17 +6429,9 @@ def processEscrowDelegables(self): | |
| wigers = [Siger(qb64b=bytes(wig)) for wig in wigs] | ||
|
|
||
| # get delgate seal | ||
| couple = self.db.getAes(dgkey) | ||
| if couple is not None: # Only try to parse the event if we have the del seal | ||
| raw = bytearray(couple) | ||
| seqner = coring.Seqner(qb64b=raw, strip=True) | ||
| saider = coring.Saider(qb64b=raw) | ||
|
|
||
| # process event | ||
| self.processEvent(serder=eserder, sigers=sigers, wigers=wigers, delseqner=seqner, | ||
| delsaider=saider, local=esr.local) | ||
| else: | ||
| raise MissingDelegableApprovalError("No delegation seal found for event.") | ||
| seqner, saider = self._getDelegationSeal(eserder=eserder, dgkey=dgkey) | ||
| self.processEvent(serder=eserder, sigers=sigers, wigers=wigers, delseqner=seqner, | ||
| delsaider=saider, local=esr.local) | ||
|
|
||
| except MissingDelegableApprovalError as ex: | ||
| # still waiting on missing delegation approval | ||
|
|
@@ -6432,6 +6455,58 @@ def processEscrowDelegables(self): | |
| "event=%s", eserder.said) | ||
| logger.debug("event=\n%s\n", eserder.pretty()) | ||
|
|
||
| def _getDelegationSeal(self, eserder: serdering.SerderKERI, dgkey: bytes) -> tuple[ | ||
| coring.Seqner, coring.Saider]: | ||
| """ | ||
| Get sequence number (delseqner) and event digest (delsaider) | ||
| for delegated inception (dip) or rotation (drt) event from AES seal database or KEL state. | ||
|
|
||
| Parameters: | ||
| eserder: SerderKERI instance of the delegated event | ||
| dgkey: bytes of the digest key of the delegated event | ||
| Returns: | ||
| (Seqner, Saider): sequence number and event digest | ||
| Raises: | ||
| MissingDelegableApprovalError: if the delegation seal is not found | ||
| """ | ||
| # get delgate seal | ||
| couple = self.db.getAes(dgkey) | ||
| if couple is not None: # Only try to parse the event if we have the del seal | ||
| raw = bytearray(couple) | ||
| seqner = coring.Seqner(qb64b=raw, strip=True) | ||
| saider = coring.Saider(qb64b=raw) | ||
| return seqner, saider | ||
| else: | ||
| # Check KEL for seal (like in valSigsWigsDel) | ||
| # This handles the case where delegation was approved | ||
| # and the seal is in the delegator's KEL | ||
| if eserder.ilk in (Ilks.dip, Ilks.drt): | ||
| # Get delpre (delegator prefix) from dip or drt | ||
| if eserder.ilk == Ilks.dip: | ||
| delpre = eserder.delpre # delegator from dip event | ||
| if not delpre: | ||
| raise MissingDelegableApprovalError( | ||
| f"Empty or missing delegator for delegated inception event = {eserder.said}.") | ||
| else: # For drt, delpre is in kever state | ||
| # If we have the kever, use it; otherwise we can't process | ||
| if eserder.pre in self.kevers: | ||
| delpre = self.kevers[eserder.pre].delpre | ||
| else: | ||
| raise MissingDelegableApprovalError( | ||
| f"No kever found for delegated rotation event = {eserder.said}.") | ||
|
|
||
| # Look up seal in delegator's KEL | ||
| seal = dict(i=eserder.pre, s=eserder.snh, d=eserder.said) | ||
| dserder = self.db.fetchLastSealingEventByEventSeal(pre=delpre, seal=seal) | ||
| if dserder is not None: # found seal - use it | ||
| seqner = coring.Seqner(sn=dserder.sn) | ||
| saider = coring.Saider(qb64=dserder.said) | ||
| return seqner, saider | ||
| else: | ||
| raise MissingDelegableApprovalError("No delegation seal found for event.") | ||
| else: | ||
| raise MissingDelegableApprovalError("No delegation seal found for event.") | ||
|
|
||
| def processQueryNotFound(self): | ||
| """ | ||
| Process qry events escrowed by Kevery for KELs that have not yet met the criteria of the query. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Print statements in this file were reordered for readability.