Skip to content

Commit

Permalink
Fixes for anchoring multiple delegates in a single delegator event, e…
Browse files Browse the repository at this point in the history
…xn escrow timeout. (#851)

* Updating delegation logic to allow for multiple delegation inception commands to run simultaneously.
Ensure proper use of the proxy for delegation inception and rotation kli commands.
Add timeout to exn escrow for partial sig escrow of peer-to-peer messages.

Signed-off-by: pfeairheller <[email protected]>

* Add test for exchange escrow timeout.

Signed-off-by: pfeairheller <[email protected]>

---------

Signed-off-by: pfeairheller <[email protected]>
  • Loading branch information
pfeairheller authored Aug 22, 2024
1 parent 8701a23 commit 13506a2
Show file tree
Hide file tree
Showing 11 changed files with 213 additions and 44 deletions.
84 changes: 84 additions & 0 deletions src/keri/app/cli/commands/event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# -*- encoding: utf-8 -*-
"""
KERI
keri.kli.commands module
"""
import argparse
import json

from hio import help
from hio.base import doing

from keri.app.cli.common import existing
from keri.kering import ConfigurationError

logger = help.ogler.getLogger()

parser = argparse.ArgumentParser(description='Print an event from an AID, or specific values from an event (defaults to latest event).')
parser.set_defaults(handler=lambda args: handler(args),
transferable=True)
parser.add_argument('--name', '-n', help='keystore name and file location of KERI keystore', required=True)
parser.add_argument('--base', '-b', help='additional optional prefix to file location of KERI keystore',
required=False, default="")
parser.add_argument('--alias', '-a', help='human readable alias for the new identifier prefix', default=None,
required=True)
parser.add_argument('--passcode', '-p', help='21 character encryption passcode for keystore (is not saved)',
dest="bran", default=None) # passcode => bran
parser.add_argument('--said', '-S', help='Print the SAID of the event in question', action="store_true")
parser.add_argument('--sn', '-s', help='Print the decimal value of the sequence number of the event in question',
action="store_true")
parser.add_argument('--snh', help='Print the decimal value of the sequence number of the event in question',
action="store_true")
parser.add_argument('--raw', '-r', help='Print the raw, signed value of the event', action="store_true")
parser.add_argument('--json', '-j', help='Pretty print the JSON of the event.', action="store_true")
parser.add_argument('--seal', help='Print an anchorable seal of the event in question.', action="store_true")


def handler(args):
kwa = dict(args=args)
return [doing.doify(event, **kwa)]


def event(tymth, tock=0.0, **opts):
""" Command line status handler
"""
_ = (yield tock)
args = opts["args"]
name = args.name
alias = args.alias
base = args.base
bran = args.bran

try:
with existing.existingHby(name=name, base=base, bran=bran) as hby:
if alias is None:
alias = existing.aliasInput(hby)

hab = hby.habByName(alias)
if hab is None:
print(f"{alias} is not a valid identifier")

if args.said:
print(hab.kever.serder.said)

if args.sn:
print(hab.kever.sn)

if args.snh:
print(hab.kever.serder.snh)

if args.raw:
print(hab.kever.serder.raw.decode("utf-8"))

if args.json:
print(hab.kever.serder.pretty())

if args.seal:
seal = dict(i=hab.pre, s=hab.kever.serder.snh, d=hab.kever.serder.said)
print(json.dumps(seal))

except ConfigurationError as e:
print(f"identifier prefix for {name} does not exist, incept must be run first", )
return -1
10 changes: 7 additions & 3 deletions src/keri/app/cli/commands/incept.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,10 @@ def __init__(self, name, base, alias, bran, endpoint, proxy=None, cnfg=None, **k
reopen=True,
clear=False)
self.endpoint = endpoint
self.proxy = proxy
self.hby = existing.setupHby(name=name, base=base, bran=bran, cf=cf)
self.proxy = self.hby.habByName(proxy) if proxy is not None else None
self.hbyDoer = habbing.HaberyDoer(habery=self.hby) # setup doer
self.swain = delegating.Anchorer(hby=self.hby, proxy=self.hby.habByName(self.proxy))
self.swain = delegating.Anchorer(hby=self.hby, proxy=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)]
Expand Down Expand Up @@ -185,7 +185,11 @@ def inceptDo(self, tymth, tock=0.0):
_ = yield self.tock

if hab.kever.delpre:
yield from self.postman.sendEvent(hab=hab, fn=hab.kever.sn)
if self.proxy is not None:
sender = self.proxy
else:
sender = hab
yield from self.postman.sendEventToDelegator(hab=hab, sender=sender, fn=hab.kever.sn)

print(f'Prefix {hab.pre}')
for idx, verfer in enumerate(hab.kever.verfers):
Expand Down
17 changes: 15 additions & 2 deletions src/keri/app/cli/commands/interact.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
dest="endpoint", action='store_true')
parser.add_argument("--authenticate", '-z', help="Prompt the controller for authentication codes for each witness",
action='store_true')
parser.add_argument('--code', help='<Witness AID>:<code> formatted witness auth codes. Can appear multiple times',
default=[], action="append", required=False)
parser.add_argument('--code-time', help='Time the witness codes were captured.', default=None, required=False)


def interact(args):
Expand Down Expand Up @@ -57,7 +60,7 @@ def interact(args):
data = None

ixnDoer = InteractDoer(name=name, base=base, alias=alias, bran=bran, data=data, authenticate=args.authenticate,
endpoint=args.endpoint)
endpoint=args.endpoint, codes=args.code, codeTime=args.code_time)

return [ixnDoer]

Expand All @@ -68,7 +71,8 @@ class InteractDoer(doing.DoDoer):
to all appropriate witnesses
"""

def __init__(self, name, base, bran, alias, data: list = None, endpoint=False, authenticate=False):
def __init__(self, name, base, bran, alias, data: list = None, endpoint=False, authenticate=False,
codes=None, codeTime=None):
"""
Returns DoDoer with all registered Doers needed to perform interaction event.
Expand All @@ -82,6 +86,8 @@ def __init__(self, name, base, bran, alias, data: list = None, endpoint=False, a
self.data = data
self.endpoint = endpoint
self.authenticate = authenticate
self.codes = codes if codes is not None else []
self.codeTime = codeTime

self.hby = existing.setupHby(name=name, base=base, bran=bran)
self.hbyDoer = habbing.HaberyDoer(habery=self.hby) # setup doer
Expand All @@ -105,7 +111,14 @@ def interactDo(self, tymth, tock=0.0, **opts):

auths = {}
if self.authenticate:
codeTime = helping.fromIso8601(self.codeTime) if self.codeTime is not None else helping.nowIso8601()
for arg in self.codes:
(wit, code) = arg.split(":")
auths[wit] = f"{code}#{codeTime}"

for wit in hab.kever.wits:
if wit in auths:
continue
code = input(f"Entire code for {wit}: ")
auths[wit] = f"{code}#{helping.nowIso8601()}"

Expand Down
2 changes: 1 addition & 1 deletion src/keri/app/cli/commands/multisig/incept.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def inceptDo(self, tymth, tock=0.0):
yield self.tock

if ghab.kever.delpre:
yield from self.postman.sendEvent(hab=ghab, fn=ghab.kever.sn)
yield from self.postman.sendEventToDelegator(hab=ghab, sender=ghab.mhab, fn=ghab.kever.sn)

print()
displaying.printIdentifier(self.hby, ghab.pre)
Expand Down
2 changes: 1 addition & 1 deletion src/keri/app/cli/commands/multisig/rotate.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ def rotateDo(self, tymth, tock=0.0, **opts):
yield self.tock

if ghab.kever.delpre:
yield from self.postman.sendEvent(hab=ghab, fn=ghab.kever.sn)
yield from self.postman.sendEventToDelegator(hab=ghab, sender=ghab.mhab, fn=ghab.kever.sn)

print()
displaying.printIdentifier(self.hby, ghab.pre)
Expand Down
15 changes: 10 additions & 5 deletions src/keri/app/cli/commands/rotate.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
default=[], action="append", required=False)
parser.add_argument('--code-time', help='Time the witness codes were captured.', default=None, required=False)

parser.add_argument("--proxy", help="alias for delegation communication proxy", default="")
parser.add_argument("--proxy", help="alias for delegation communication proxy", default=None)

rotating.addRotationArgs(parser)

Expand Down Expand Up @@ -148,7 +148,6 @@ def __init__(self, name, base, bran, alias, endpoint=False, isith=None, nsith=No
self.toad = toad
self.data = data
self.endpoint = endpoint
self.proxy = proxy
self.authenticate = authenticate
self.codes = codes if codes is not None else []
self.codeTime = codeTime
Expand All @@ -159,7 +158,9 @@ 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, proxy=self.hby.habByName(self.proxy))

self.proxy = self.hby.habByName(proxy) if proxy is not None else None
self.swain = delegating.Anchorer(hby=self.hby, proxy=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)]
Expand Down Expand Up @@ -213,7 +214,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, auths=auths)
self.swain.delegation(pre=hab.pre, sn=hab.kever.sn, auths=auths, proxy=self.proxy)
print("Waiting for delegation approval...")
while not self.swain.complete(hab.kever.prefixer, coring.Seqner(sn=hab.kever.sn)):
yield self.tock
Expand All @@ -237,7 +238,11 @@ def rotateDo(self, tymth, tock=0.0):
self.remove([witDoer])

if hab.kever.delpre:
yield from self.postman.sendEvent(hab=hab, fn=hab.kever.sn)
if self.proxy is not None:
sender = self.proxy
else:
sender = hab
yield from self.postman.sendEventToDelegator(hab=hab, sender=sender, fn=hab.kever.sn)

print(f'Prefix {hab.pre}')
print(f'New Sequence No. {hab.kever.sn}')
Expand Down
12 changes: 11 additions & 1 deletion src/keri/app/delegating.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,14 @@ def processPartialWitnessEscrow(self):
if not witnessed:
continue
logger.info(f"Witness receipts complete, waiting for delegation approval.")
if pre not in self.hby.habs:
continue

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
Expand Down Expand Up @@ -208,6 +212,9 @@ def processWitnessPublication(self):
"""
for (pre, said), serder in self.hby.db.dpub.getItemIter(): # group partial witness escrow
if pre not in self.publishers:
continue

publisher = self.publishers[pre]

if not publisher.idle:
Expand All @@ -220,8 +227,11 @@ def processWitnessPublication(self):
self.hby.db.cdel.put(keys=(pre, coring.Seqner(sn=serder.sn).qb64), val=coring.Saider(qb64=serder.said))

def publishDelegator(self, pre):
hab = self.hby.habs[pre]
if pre not in self.publishers:
return

publisher = self.publishers[pre]
hab = self.hby.habs[pre]
self.extend([publisher])
for msg in hab.db.cloneDelegation(hab.kever):
publisher.msgs.append(dict(pre=hab.pre, msg=bytes(msg)))
Expand Down
5 changes: 2 additions & 3 deletions src/keri/app/forwarding.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,14 @@ def sent(self, said):

return False

def sendEvent(self, hab, fn=0):
def sendEventToDelegator(self, sender, hab, fn=0):
""" Returns generator for sending event and waiting until send is complete """
# Send KEL event for processing
icp = self.hby.db.cloneEvtMsg(pre=hab.pre, fn=fn, dig=hab.kever.serder.saidb)
ser = serdering.SerderKERI(raw=icp)
del icp[:ser.size]

sender = hab.mhab.pre if isinstance(hab, GroupHab) else hab.pre
self.send(src=sender, dest=hab.kever.delpre, topic="delegate", serder=ser, attachment=icp)
self.send(src=sender.pre, dest=hab.kever.delpre, topic="delegate", serder=ser, attachment=icp)
while True:
if self.cues:
cue = self.cues.popleft()
Expand Down
4 changes: 4 additions & 0 deletions src/keri/db/basing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,10 @@ def reopen(self, **kwa):
# exchange message partial signature escrow
self.epse = subing.SerderSuber(db=self, subkey="epse.")

# exchange message PS escrow date time of message
self.epsd = subing.CesrSuber(db=self, subkey="epsd.",
klas=coring.Dater)

# exchange messages
# TODO: clean
self.exns = subing.SerderSuber(db=self, subkey="exns.")
Expand Down
Loading

0 comments on commit 13506a2

Please sign in to comment.