Skip to content

Commit

Permalink
- A new kli command to send an /introduce message with an AID and O…
Browse files Browse the repository at this point in the history
…OBI. (WebOfTrust#817)

- Bug fix to watching to check against the correct key state.
- Logging additions, fixes and typo fixes.

Signed-off-by: pfeairheller <[email protected]>
  • Loading branch information
pfeairheller authored Jul 15, 2024
1 parent 12a134e commit d050499
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 11 deletions.
137 changes: 137 additions & 0 deletions src/keri/app/cli/commands/introduce.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# -*- encoding: utf-8 -*-
"""
keri.kli.commands module
"""
import argparse

from hio.base import doing

from keri.core import serdering
from ..common import existing
from ... import habbing, connecting, forwarding

parser = argparse.ArgumentParser(description='Send an rpy /introduce message to recipient with OOBI')
parser.set_defaults(handler=lambda args: introduce(args))
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', 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('--recipient', help='alias or contact to send the introduction to', required=True)
parser.add_argument('--introducee', help='alias or contact of the OOBI to send', required=True)
parser.add_argument("--role", "-r", help="role of oobi to send", required=True)


def introduce(args):
"""
Performs a rotation of the identifier of the environment represented by the provided name parameter
args (parseargs): Command line argument
"""
name = args.name
alias = args.alias
base = args.base
bran = args.bran
introducee = args.introducee
recipient = args.recipient
role = args.role

ixnDoer = IntroduceDoer(name=name, base=base, alias=alias, bran=bran, introducee=introducee, recipient=recipient,
role=role,)

return [ixnDoer]


class IntroduceDoer(doing.DoDoer):
"""
DoDoer that launches Doers needed to introduce one controller of an AID to another
"""

def __init__(self, name, base, bran, alias, introducee, recipient, role):
"""
Returns DoDoer with all registered Doers needed to perform an introduction.
Parameters:
name is human readable str of identifier
"""

self.alias = alias
self.introducee = introducee
self.recipient = recipient
self.role = role

self.hby = existing.setupHby(name=name, base=base, bran=bran)
self.hbyDoer = habbing.HaberyDoer(habery=self.hby) # setup doer
self.org = connecting.Organizer(hby=self.hby)
self.postman = forwarding.Poster(hby=self.hby)
doers = [self.hbyDoer, self.postman, doing.doify(self.introduceDo)]

super(IntroduceDoer, self).__init__(doers=doers)

def introduceDo(self, tymth, tock=0.0, **opts):
"""
Returns: doifiable Doist compatible generator method
Usage:
add result of doify on this method to doers list
"""
self.wind(tymth)
self.tock = tock
_ = (yield self.tock)

hab = self.hby.habByName(name=self.alias)

if self.recipient in self.hby.kevers:
recp = self.recipient
else:
recp = self.org.find("alias", self.recipient)
if len(recp) != 1:
raise ValueError(f"invalid recipient {self.recipient}")
recp = recp[0]['id']

if (ihab := self.hby.habByName(self.introducee)) is not None:
introducee = ihab.pre
elif self.introducee in self.hby.habs:
introducee = self.introducee
elif self.introducee in self.hby.kevers:
introducee = self.introducee
else:
introducee = None
results = self.org.find("alias", self.introducee)
for result in results:
if result["alias"] == self.introducee:
introducee = result['id']
if not introducee:
raise ValueError(f"invalid introducee {self.introducee}")

oobi = None
for (key,), obr in self.hby.db.roobi.getItemIter():
if obr.cid == introducee and obr.role == self.role:
oobi = key

if oobi is None:
raise ValueError(f"Unable to find OOBI with role {self.role} for {introducee}")

msg = hab.reply(route="/introduce", data=dict(
cid=hab.pre,
oobi=oobi
))

serder = serdering.SerderKERI(raw=msg)
atc = msg[serder.size:]
self.postman.send(src=hab.pre, dest=recp, topic="credential", serder=serder,
attachment=atc)

while not len(self.postman.cues) == 1:
yield self.tock

print(f"Introduction with OOBI {oobi} sent for {self.introducee} sent to {self.recipient}")

toRemove = [self.hbyDoer, self.postman]
self.remove(toRemove)

return
5 changes: 3 additions & 2 deletions src/keri/app/cli/commands/watcher/adjudicate.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,11 @@ def adjudicate(self, tymth, tock=0.0, **opts):

case "keyStateUpdate":
ahds = cue["aheads"]
logger.info(f"Threshold ({self.toad}) satisfying number of watchers ({len(ahds)}) are ahead")
print(f"Threshold ({self.toad}) satisfying number of watchers ({len(ahds)}) are ahead")
for state in ahds:
logger.info(f"\tWatcher {state.wit} at Seq No. {state.sn} with digest: {state.dig}")
print(f"\tWatcher {state.wit} at Seq No. {state.sn} with digest: {state.dig}")

print("Submitting query to update local copy of latest events.")
state = random.choice(ahds)
querier = querying.SeqNoQuerier(hby=self.hby, hab=hab, pre=self.watched, sn=state.sn,
wits=[state.wit])
Expand Down
2 changes: 1 addition & 1 deletion src/keri/app/forwarding.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def deliverDo(self, tymth=None, tock=0.0):
elif Roles.witness in ends:
yield from self.forwardToWitness(hab, ends[Roles.witness], recp=recp, serder=srdr, atc=atc, topic=tpc)
else:
logger.info(f"No end roles for {recp} to send evt={recp}")
logger.info(f"No end roles for {recp} to send evt={srdr.said}")
continue
except kering.ConfigurationError as e:
logger.error(f"Error sending to {recp} with ends={ends}. Err={e}")
Expand Down
2 changes: 1 addition & 1 deletion src/keri/app/oobiing.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ def processReply(self, *, serder, saider, route, cigars=None, tsgs=None, **kwarg
aid=aid, osaider=None, cigars=cigars,
tsgs=tsgs)
if not accepted:
raise UnverifiedReplyError(f"Unverified introduciton reply. {serder.ked}")
raise UnverifiedReplyError(f"Unverified introduction reply. {serder.ked}")

obr = basing.OobiRecord(cid=cid, date=dt)
self.hby.db.oobis.put(keys=(oobi,), val=obr)
Expand Down
2 changes: 1 addition & 1 deletion src/keri/app/watching.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def adjudicate(self, watched, toad=None):
raise ValueError(f"Threshold of {toad} is greater than number watchers {len(watchers)}")

states = []
mystate = self.hab.kever.state()
mystate = self.hab.kevers[watched].state()
for watcher in watchers:
saider = self.hab.db.knas.get(keys=(watched, watcher))
if saider is None:
Expand Down
7 changes: 4 additions & 3 deletions src/keri/core/eventing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2130,8 +2130,8 @@ def deriveBacks(self, serder):
Parameters:
serder (SerderKeri): instance of current event
"""
if serder.ilk not in (Ilks.rot, Ilks.drt): # no changes
return (self.wits, self.cuts, self.adds)
if serder.ilk not in (Ilks.rot, Ilks.drt) or self.sn >= serder.sn: # no changes
return self.wits, self.cuts, self.adds

witset = oset(self.wits)
cuts = serder.cuts
Expand Down Expand Up @@ -4170,7 +4170,8 @@ def processReplyEndRole(self, *, serder, saider, route, cigars=None, tsgs=None,
aid=aid, osaider=osaider, cigars=cigars,
tsgs=tsgs)
if not accepted:
raise UnverifiedReplyError(f"Unverified end role reply. {serder.ked}")
logger.debug(f"Unverified end role reply ked={serder.ked}")
raise UnverifiedReplyError(f"Unverified end role reply. {serder.said}")

self.updateEnd(keys=keys, saider=saider, allowed=allowed) # update .eans and .ends

Expand Down
6 changes: 3 additions & 3 deletions src/keri/core/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ def allParsator(self, ims=None, framed=None, pipeline=None, kvy=None,
if logger.isEnabledFor(logging.DEBUG):
logger.exception("Parser msg non-extraction error: %s", ex)
else:
logger.exception("Parser msg non-extraction error: %s", ex)
logger.error("Parser msg non-extraction error: %s", ex)
yield

return True
Expand Down Expand Up @@ -530,7 +530,7 @@ def onceParsator(self, ims=None, framed=None, pipeline=None, kvy=None,
if logger.isEnabledFor(logging.DEBUG):
logger.exception("Kevery msg non-extraction error: %s", ex)
else:
logger.exception("Kevery msg non-extraction error: %s", ex)
logger.error("Kevery msg non-extraction error: %s", ex)
finally:
done = True

Expand Down Expand Up @@ -620,7 +620,7 @@ def parsator(self, ims=None, framed=None, pipeline=None, kvy=None, tvy=None,
if logger.isEnabledFor(logging.DEBUG):
logger.exception("Parser msg non-extraction error: %s", ex.args[0])
else:
logger.exception("Parser msg non-extraction error: %s", ex.args[0])
logger.error("Parser msg non-extraction error: %s", ex.args[0])
yield

return True # should never return
Expand Down
4 changes: 4 additions & 0 deletions src/keri/core/routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ def acceptReply(self, serder, saider, route, aid, osaider=None,

for cigar in cigars: # process each couple to verify sig and write to db
if cigar.verfer.transferable: # ignore invalid transferable verfers
logger.info("Kevery process: skipped invalid transferable verfers"
" on reply said=", serder.said)
continue # skip invalid transferable

if not self.lax and cigar.verfer.qb64 in self.prefixes: # own cig
Expand Down Expand Up @@ -338,6 +340,8 @@ def acceptReply(self, serder, saider, route, aid, osaider=None,
if sdig is None:
# create cue here to request key state for sprefixer signer
# signer's est event not yet in signer's KEL
logger.info("Kevery process: escrowing without key state for signer"
" on reply said=", serder.said)
self.escrowReply(serder=serder, saider=saider, dater=dater,
route=route, prefixer=prefixer, seqner=seqner,
ssaider=ssaider, sigers=sigers)
Expand Down

0 comments on commit d050499

Please sign in to comment.