Skip to content
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

New kli command for introductions and a few fixes #817

Merged
merged 1 commit into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why would the topic be "credential" here?

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
Loading