From f740d4f2ace5e6f72ba733f03a2ca098b9d20e48 Mon Sep 17 00:00:00 2001 From: pfeairheller Date: Sat, 18 May 2024 08:24:26 -0700 Subject: [PATCH 1/5] New mailbox commands for using bespoke mailbox services. Signed-off-by: pfeairheller --- images/keripy.base.dockerfile | 15 ++ src/keri/app/cli/commands/mailbox/add.py | 128 ++++++++++++++++++ src/keri/app/cli/commands/oobi/generate.py | 13 ++ .../app/cli/commands/witness/authenticate.py | 1 - src/keri/app/indirecting.py | 2 +- src/keri/peer/exchanging.py | 2 +- 6 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 images/keripy.base.dockerfile create mode 100644 src/keri/app/cli/commands/mailbox/add.py diff --git a/images/keripy.base.dockerfile b/images/keripy.base.dockerfile new file mode 100644 index 000000000..23de45f8d --- /dev/null +++ b/images/keripy.base.dockerfile @@ -0,0 +1,15 @@ +# Builder layer +FROM python:3.12-alpine as builder + +# Install compilation dependencies +RUN apk --no-cache add \ + bash \ + alpine-sdk \ + libffi-dev \ + libsodium \ + libsodium-dev + +SHELL ["/bin/bash", "-c"] + +# Setup Rust for blake3 dependency build +RUN curl https://sh.rustup.rs -sSf | bash -s -- -y diff --git a/src/keri/app/cli/commands/mailbox/add.py b/src/keri/app/cli/commands/mailbox/add.py new file mode 100644 index 000000000..73297b8f9 --- /dev/null +++ b/src/keri/app/cli/commands/mailbox/add.py @@ -0,0 +1,128 @@ +# -*- encoding: utf-8 -*- +""" +KERI +keri.kli.commands module + +""" +import argparse + +from hio import help +from hio.base import doing +from hio.help import Hict + +from keri import kering +from keri.app import connecting, habbing, forwarding +from keri.app.agenting import httpClient +from keri.app.cli.common import existing +from keri.core import serdering + +logger = help.ogler.getLogger() + +parser = argparse.ArgumentParser(description='Add mailbox role') +parser.set_defaults(handler=lambda args: add(args), + transferable=True) +parser.add_argument('--name', '-n', help='keystore name and file location of KERI keystore', required=True) +parser.add_argument('--alias', '-a', help='human readable alias for the identifier to whom the credential was issued', + required=True) +parser.add_argument('--base', '-b', help='additional optional prefix to file location of KERI keystore', + required=False, default="") +parser.add_argument('--passcode', '-p', help='22 character encryption passcode for keystore (is not saved)', + dest="bran", default=None) # passcode => bran +parser.add_argument("--mailbox", '-w', help="the mailbox AID or alias to add", required=True) + + +def add(args): + """ Command line handler for adding an aid to a watcher's list of AIds to watch + + Parameters: + args(Namespace): parsed command line arguments + + """ + + ed = AddDoer(name=args.name, + alias=args.alias, + base=args.base, + bran=args.bran, + mailbox=args.mailbox) + return [ed] + + +class AddDoer(doing.DoDoer): + + def __init__(self, name, alias, base, bran, mailbox): + self.hby = existing.setupHby(name=name, base=base, bran=bran) + self.hab = self.hby.habByName(alias) + self.org = connecting.Organizer(hby=self.hby) + + if mailbox in self.hby.kevers: + mbx = mailbox + else: + mbx = self.org.find("alias", mailbox) + if len(mbx) != 1: + raise ValueError(f"invalid mailbox {mailbox}") + mbx = mbx[0]['id'] + + if not mbx: + raise ValueError(f"unknown mailbox {mailbox}") + + self.mailbox = mbx + + doers = [doing.doify(self.addDo)] + + super(AddDoer, self).__init__(doers=doers) + + def addDo(self, tymth, tock=0.0): + """ Grant credential by creating /ipex/grant exn message + + Parameters: + tymth (function): injected function wrapper closure returned by .tymen() of + Tymist instance. Calling tymth() returns associated Tymist .tyme. + tock (float): injected initial tock value + + Returns: doifiable Doist compatible generator method + + """ + # enter context + self.wind(tymth) + self.tock = tock + _ = (yield self.tock) + + if isinstance(self.hab, habbing.GroupHab): + raise ValueError("watchers for multisig AIDs not currently supported") + + kel = self.hab.replay() + data = dict(cid=self.hab.pre, + role=kering.Roles.mailbox, + eid=self.mailbox) + + route = "/end/role/add" + msg = self.hab.reply(route=route, data=data) + self.hab.psr.parseOne(ims=(bytes(msg))) # make copy to preserve + + fargs = dict([("kel", kel.decode("utf-8")), + ("rpy", msg.decode("utf-8"))]) + + headers = (Hict([ + ("Content-Type", "multipart/form-data"), + ])) + + client, clientDoer = httpClient(self.hab, self.mailbox) + self.extend([clientDoer]) + + client.request( + method="POST", + path=f"{client.requester.path}/mailboxes", + headers=headers, + fargs=fargs + ) + while not client.responses: + yield self.tock + + rep = client.respond() + if rep.status == 200: + print("I can't believe it worked!") + + else: + print(rep.status, rep.data) + + self.remove([clientDoer]) diff --git a/src/keri/app/cli/commands/oobi/generate.py b/src/keri/app/cli/commands/oobi/generate.py index f487f3546..e35a53354 100644 --- a/src/keri/app/cli/commands/oobi/generate.py +++ b/src/keri/app/cli/commands/oobi/generate.py @@ -81,3 +81,16 @@ def generate(tymth, tock=0.0, **opts): url = urls[kering.Schemes.http] if kering.Schemes.http in urls else urls[kering.Schemes.https] up = urlparse(url) print(f"{up.scheme}://{up.hostname}:{up.port}/oobi/{hab.pre}/controller") + elif role in (kering.Roles.mailbox,): + for (_, _, eid), end in hab.db.ends.getItemIter(keys=(hab.pre, kering.Roles.mailbox, )): + if not (end.allowed and end.enabled is not False): + continue + + urls = hab.fetchUrls(eid=eid, scheme=kering.Schemes.http) or hab.fetchUrls(eid=hab.pre, + scheme=kering.Schemes.https) + if not urls: + print(f"{alias} identifier {hab.pre} does not have any mailbox endpoints") + return + url = urls[kering.Schemes.http] if kering.Schemes.http in urls else urls[kering.Schemes.https] + up = urlparse(url) + print(f"{up.scheme}://{up.hostname}:{up.port}/oobi/{hab.pre}/mailbox/{eid}") diff --git a/src/keri/app/cli/commands/witness/authenticate.py b/src/keri/app/cli/commands/witness/authenticate.py index 126fc0417..dc33c5de2 100644 --- a/src/keri/app/cli/commands/witness/authenticate.py +++ b/src/keri/app/cli/commands/witness/authenticate.py @@ -16,7 +16,6 @@ from keri.app import httping, connecting from keri.app.agenting import httpClient from keri.app.cli.common import existing -from keri.app.httping import CESR_CONTENT_TYPE from keri.core import coring logger = help.ogler.getLogger() diff --git a/src/keri/app/indirecting.py b/src/keri/app/indirecting.py index 32dc0b190..4dedb432a 100644 --- a/src/keri/app/indirecting.py +++ b/src/keri/app/indirecting.py @@ -971,7 +971,7 @@ def __iter__(self): def __next__(self): if self.iter is None: if self.cues: - cue = self.cues.pull() # self.cues.popleft() + cue = self.cues.pull() serder = cue["serder"] if serder.said == self.said: kin = cue["kin"] diff --git a/src/keri/peer/exchanging.py b/src/keri/peer/exchanging.py index fcbefa8a8..4f6466d95 100644 --- a/src/keri/peer/exchanging.py +++ b/src/keri/peer/exchanging.py @@ -129,7 +129,7 @@ def processEvent(self, serder, tsgs=None, cigars=None, **kwargs): logger.info(f"Behavior for {route} missing or does not have verify for said={serder.said}") logger.debug(f"event=\n{serder.pretty()}\n") - # Always persis events + # Always persist events self.logEvent(serder, pathed, tsgs, cigars) self.cues.append(dict(kin="saved", said=serder.said)) From b415b65273e14440a595d3912f49d27db620550c Mon Sep 17 00:00:00 2001 From: pfeairheller Date: Mon, 10 Jun 2024 14:22:38 -0700 Subject: [PATCH 2/5] Resolving merge conflicts Signed-off-by: pfeairheller --- src/keri/core/coring.py | 4 + src/keri/core/counting.py | 3 + src/keri/core/parsing.py | 35 +++++--- src/keri/core/serdering.py | 4 +- src/keri/db/basing.py | 2 + src/keri/peer/exchanging.py | 58 +++++++++--- tests/app/test_delegating.py | 14 +-- tests/app/test_grouping.py | 32 +++---- tests/app/test_oobiing.py | 11 +-- tests/core/test_coring.py | 46 +++++++++- tests/core/test_counting.py | 71 ++++++++++++++- tests/core/test_serdering.py | 28 +++--- tests/peer/test_exchanging.py | 165 ++++++++++++++++++++++------------ tests/vc/test_protocoling.py | 158 ++++++++++++++++---------------- 14 files changed, 423 insertions(+), 208 deletions(-) diff --git a/src/keri/core/coring.py b/src/keri/core/coring.py index 5bea6584b..17b134334 100644 --- a/src/keri/core/coring.py +++ b/src/keri/core/coring.py @@ -3926,8 +3926,10 @@ class CounterCodex: SadPathSigGroups: str = '-J' # Composed Base64 Group path+TransIdxSigGroup of SAID of content RootSadPathSigGroups: str = '-K' # Composed Base64 Group, root(path)+SaidPathCouples PathedMaterialGroup: str = '-L' # Composed Grouped Pathed Material Quadlet (4 char each) + BigPathedMaterialGroup: str = '-0L' # Composed Grouped Pathed Material Quadlet (4 char each) AttachmentGroup: str = '-V' # Composed Grouped Attached Material Quadlet (4 char each) BigAttachmentGroup: str = '-0V' # Composed Grouped Attached Material Quadlet (4 char each) + ESSRPayloadGroup: str = '-Z' # ESSR Payload Group, dig of content+Texter group KERIACDCGenusVersion: str = '--AAA' # KERI ACDC Protocol Stack CESR Version def __iter__(self): @@ -3995,7 +3997,9 @@ class Counter: '-J': Sizage(hs=2, ss=2, fs=4, ls=0), '-K': Sizage(hs=2, ss=2, fs=4, ls=0), '-L': Sizage(hs=2, ss=2, fs=4, ls=0), + '-0L': Sizage(hs=3, ss=5, fs=8, ls=0), '-V': Sizage(hs=2, ss=2, fs=4, ls=0), + '-Z': Sizage(hs=2, ss=2, fs=4, ls=0), '-0V': Sizage(hs=3, ss=5, fs=8, ls=0), '--AAA': Sizage(hs=5, ss=3, fs=8, ls=0), } diff --git a/src/keri/core/counting.py b/src/keri/core/counting.py index cd14e01cd..404b9b69b 100644 --- a/src/keri/core/counting.py +++ b/src/keri/core/counting.py @@ -66,8 +66,10 @@ class CounterCodex_1_0(MapDom): SadPathSigGroups: str = '-J' # Composed Base64 Group path+TransIdxSigGroup of SAID of content RootSadPathSigGroups: str = '-K' # Composed Base64 Group, root(path)+SaidPathCouples PathedMaterialGroup: str = '-L' # Composed Grouped Pathed Material Quadlet (4 char each) + BigPathedMaterialGroup: str = '-0L' # Composed Grouped Pathed Material Quadlet (4 char each) AttachmentGroup: str = '-V' # Composed Grouped Attached Material Quadlet (4 char each) BigAttachmentGroup: str = '-0V' # Composed Grouped Attached Material Quadlet (4 char each) + ESSRPayloadGroup: str = '-Z' # ESSR Payload Group, dig of content+Texter group KERIACDCGenusVersion: str = '--AAA' # KERI ACDC Protocol Stack CESR Version @@ -345,6 +347,7 @@ class Counter: '-J': Sizage(hs=2, ss=2, fs=4, ls=0), '-K': Sizage(hs=2, ss=2, fs=4, ls=0), '-L': Sizage(hs=2, ss=2, fs=4, ls=0), + '-0L': Sizage(hs=3, ss=5, fs=8, ls=0), '-V': Sizage(hs=2, ss=2, fs=4, ls=0), '-0V': Sizage(hs=3, ss=5, fs=8, ls=0), '--AAA': Sizage(hs=5, ss=3, fs=8, ls=0), diff --git a/src/keri/core/parsing.py b/src/keri/core/parsing.py index 9273f6255..2a54c5204 100644 --- a/src/keri/core/parsing.py +++ b/src/keri/core/parsing.py @@ -8,7 +8,7 @@ import logging from .coring import (Ilks, CtrDex, Counter, Seqner, Cigar, - Dater, Verfer, Prefixer, Saider, Pather) + Dater, Verfer, Prefixer, Saider, Pather, Texter) from .indexing import (Siger, ) from . import serdering from .. import help @@ -721,6 +721,7 @@ def msgParsator(self, ims=None, framed=True, pipeline=False, # List of tuples from extracted SAD path sig groups from non-trans identifiers sadcigs = [] # each converted group is path plus list of non-trans sigs pathed = [] # grouped attachments targetting a subpath + essrs = [] # group texter pipelined = False # all attachments in one big pipeline counted group # extract and deserialize attachments try: # catch errors here to flush only counted part of stream @@ -919,16 +920,6 @@ def msgParsator(self, ims=None, framed=True, pipeline=False, else: sadcigs.append(sigs) - elif ctr.code == CtrDex.SadPathSigGroups: - for code, sigs in self._sadPathSigGroup(ctr=ctr, - ims=ims, - cold=cold, - pipelined=pipelined): - if code == CtrDex.TransIdxSigGroups: - sadtsgs.append(sigs) - else: - sadcigs.append(sigs) - elif ctr.code == CtrDex.PathedMaterialGroup: # pathed ctr? # compute pipelined attached group size based on txt or bny pags = ctr.count * 4 if cold == Colds.txt else ctr.count * 3 @@ -939,6 +930,25 @@ def msgParsator(self, ims=None, framed=True, pipeline=False, del ims[:pags] # strip off from ims pathed.append(pims) + elif ctr.code == CtrDex.BigPathedMaterialGroup: # pathed ctr? + # compute pipelined attached group size based on txt or bny + pags = ctr.count * 4 if cold == Colds.txt else ctr.count * 3 + while len(ims) < pags: # wait until rx full pipelned group + yield + + pims = ims[:pags] # copy out substream pipeline group + del ims[:pags] # strip off from ims + pathed.append(pims) + + elif ctr.code == CtrDex.ESSRPayloadGroup: + for i in range(ctr.count): + texter = yield from self._extractor(ims, + klas=Texter, + cold=cold, + abort=pipelined) + essrs.append(texter) + + else: raise kering.UnexpectedCountCodeError("Unsupported count" " code={}.".format(ctr.code)) @@ -1079,6 +1089,9 @@ def msgParsator(self, ims=None, framed=True, pipeline=False, if pathed: args["pathed"] = pathed + if essrs: + args["essrs"] = essrs + try: if cigars: exc.processEvent(cigars=cigars, **args) diff --git a/src/keri/core/serdering.py b/src/keri/core/serdering.py index 312bc4b5b..9c46826d0 100644 --- a/src/keri/core/serdering.py +++ b/src/keri/core/serdering.py @@ -427,8 +427,8 @@ class Serder: Ilks.bar: FieldDom(alls=dict(v='', t='',d='', dt='', r='', a=[]), saids={Saids.d: DigDex.Blake3_256}), - Ilks.exn: FieldDom(alls=dict(v='', t='', d='', i="", p="", - dt='', r='',q={}, a=[], e={}), + Ilks.exn: FieldDom(alls=dict(v='', t='', d='', i="", rp="", + p="", dt='', r='',q={}, a=[], e={}), saids={Saids.d: DigDex.Blake3_256}), Ilks.vcp: FieldDom(alls=dict(v='', t='',d='', i='', ii='', s='0', c=[], bt='0', b=[], n=''), diff --git a/src/keri/db/basing.py b/src/keri/db/basing.py index 0a1ec1f0a..cec20d4ea 100644 --- a/src/keri/db/basing.py +++ b/src/keri/db/basing.py @@ -1063,6 +1063,8 @@ def reopen(self, **kwa): # TODO: clean self.epath = subing.IoSetSuber(db=self, subkey=".epath") + self.essrs = subing.CesrSuber(db=self, subkey=".essrs", klass=coring.Texter) + # accepted signed 12-word challenge response exn messages keys by prefix of signer # TODO: clean self.chas = subing.CesrIoSetSuber(db=self, subkey='chas.', klas=coring.Saider) diff --git a/src/keri/peer/exchanging.py b/src/keri/peer/exchanging.py index 4f6466d95..7519cba4c 100644 --- a/src/keri/peer/exchanging.py +++ b/src/keri/peer/exchanging.py @@ -71,6 +71,7 @@ def processEvent(self, serder, tsgs=None, cigars=None, **kwargs): route = serder.ked["r"] sender = serder.ked["i"] pathed = kwargs["pathed"] if "pathed" in kwargs else [] + essrs = kwargs["essrs"] if "essrs" in kwargs else [] behavior = self.routes[route] if route in self.routes else None if tsgs is not None: @@ -110,6 +111,8 @@ def processEvent(self, serder, tsgs=None, cigars=None, **kwargs): " for evt = {}.".format(serder.ked)) e = coring.Pather(path=["e"]) + + kwargs = dict() attachments = [] for p in pathed: pattach = bytearray(p) @@ -118,9 +121,24 @@ def processEvent(self, serder, tsgs=None, cigars=None, **kwargs): np = pather.strip(e) attachments.append((np, pattach)) + kwargs["attachments"] = attachments + + if isinstance(serder.seals, str): + if len(essrs) != 1: + raise ValidationError("one and only one essr attachment allowed") + + texter = essrs[0] + dig = serder.seals + diger = coring.Diger(qb64=dig) + if not diger.verify(ser=texter.qb64b): + raise ValidationError(f"essr diger={diger.qb64} is invalid against content") + + if essrs: + kwargs["essrs"] = essrs + # Perform behavior specific verification, think IPEX chaining requirements try: - if not behavior.verify(serder=serder, attachments=attachments): + if not behavior.verify(serder=serder, **kwargs): logger.info(f"exn event for route {route} failed behavior verfication. said={serder.said}") logger.debug(f"event=\n{serder.pretty()}\n") return @@ -130,12 +148,12 @@ def processEvent(self, serder, tsgs=None, cigars=None, **kwargs): logger.debug(f"event=\n{serder.pretty()}\n") # Always persist events - self.logEvent(serder, pathed, tsgs, cigars) + self.logEvent(serder, pathed, tsgs, cigars, essrs) self.cues.append(dict(kin="saved", said=serder.said)) # Execute any behavior specific handling, not sure if this should be different than verify try: - behavior.handle(serder=serder, attachments=attachments) + behavior.handle(serder=serder, **kwargs) except AttributeError: logger.info(f"Behavior for {route} missing or does not have handle for said={serder.said}") logger.debug(f"event=\n{serder.pretty()}\n") @@ -210,12 +228,13 @@ def processEscrowPartialSigned(self): "creder=%s", serder.said) logger.debug(f"event=\n{serder.pretty()}\n") - def logEvent(self, serder, pathed=None, tsgs=None, cigars=None): + def logEvent(self, serder, pathed=None, tsgs=None, cigars=None, essrs=None): dig = serder.said pdig = serder.ked['p'] pathed = pathed or [] tsgs = tsgs or [] cigars = cigars or [] + essrs = essrs or [] for prefixer, seqner, ssaider, sigers in tsgs: # iterate over each tsg quadkeys = (serder.said, prefixer.qb64, f"{seqner.sn:032x}", ssaider.qb64) @@ -226,6 +245,8 @@ def logEvent(self, serder, pathed=None, tsgs=None, cigars=None): saider = coring.Saider(qb64=serder.said) self.hby.db.epath.pin(keys=(dig,), vals=[bytes(p) for p in pathed]) + for texter in essrs: + self.hby.db.essrs.pin(keys=(serder.seals,), val=texter) if pdig: self.hby.db.erpy.pin(keys=(pdig,), val=saider) @@ -278,8 +299,9 @@ def complete(self, said): def exchange(route, - payload, sender, + payload=None, + diger=None, recipient=None, date=None, dig=None, @@ -292,6 +314,7 @@ def exchange(route, Parameters: route (str): to destination route of the message payload (list | dict): body of message to deliver to route + diger (Diger): qb64 digest of payload sender (str): qb64 AID of sender of the exn recipient (str) optional qb64 AID recipient of exn date (str): Iso8601 formatted date string to use for this request @@ -307,6 +330,7 @@ def exchange(route, ilk = eventing.Ilks.exn dt = date if date is not None else helping.nowIso8601() p = dig if dig is not None else "" + rp = recipient if recipient is not None else "" embeds = embeds if embeds is not None else {} e = dict() @@ -322,26 +346,36 @@ def exchange(route, pather = coring.Pather(path=["e", label]) pathed.extend(pather.qb64b) pathed.extend(atc) - end.extend(coring.Counter(code=coring.CtrDex.PathedMaterialGroup, - count=(len(pathed) // 4)).qb64b) + if len(pathed) // 4 < 4096: + end.extend(coring.Counter(code=coring.CtrDex.PathedMaterialGroup, + count=(len(pathed) // 4)).qb64b) + else: + end.extend(coring.Counter(code=coring.CtrDex.BigPathedMaterialGroup, + count=(len(pathed) // 4)).qb64b) end.extend(pathed) if e: e["d"] = "" _, e = coring.Saider.saidify(sad=e, label=coring.Saids.d) - attrs = dict( - ) + modifiers = modifiers if modifiers is not None else {} + + if diger is None: + attrs = dict() - if recipient is not None: - attrs['i'] = recipient + if recipient is not None: + attrs['i'] = recipient - attrs |= payload + attrs |= payload + + else: + attrs = diger.qb64 ked = dict(v=vs, t=ilk, d="", i=sender, + rp=rp, p=p, dt=dt, r=route, diff --git a/tests/app/test_delegating.py b/tests/app/test_delegating.py index 132a588c5..f5c83870f 100644 --- a/tests/app/test_delegating.py +++ b/tests/app/test_delegating.py @@ -129,16 +129,16 @@ def test_delegation_request(mockHelpingNowUTC): exn, atc = delegating.delegateRequestExn(hab=hab, delpre=delpre, evt=evt) assert atc == (b'-FABEIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI30AAAAAAAAAAAAAAA' - b'AAAAAAAAEIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI3-AABAADECnBl' - b'0c14SVi7Keh__sd1PVhinSy-itPr33ZxvSjJYFastqXw9ZTFGNKsY6iALUk5xP3S' - b'399tJrPFe7PtuNAN') + b'AAAAAAAAEIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI3-AABAACzeUyP' + b'6__0oDca-Oiv2iGXKghBw_8sI4ZHyyeMedvz0iZIIQYqJd2Zt7cDHRh7xBGWI85J' + b'_oOixLET3mFZUu0A') assert exn.ked["r"] == '/delegate/request' - assert exn.saidb == b'EOiDc2wEmhHc7sbLG64y2gveCIRlFe4BuISaz0mlOuZz' + assert exn.saidb == b'EHPkcmdLGql9_1WD0wl0OalYk8PcF4HMMd7gGi-iqfSe' assert atc == (b'-FABEIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI30AAAAAAAAAAAAAAA' - b'AAAAAAAAEIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI3-AABAADECnBl' - b'0c14SVi7Keh__sd1PVhinSy-itPr33ZxvSjJYFastqXw9ZTFGNKsY6iALUk5xP3S' - b'399tJrPFe7PtuNAN') + b'AAAAAAAAEIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI3-AABAACzeUyP' + b'6__0oDca-Oiv2iGXKghBw_8sI4ZHyyeMedvz0iZIIQYqJd2Zt7cDHRh7xBGWI85J' + b'_oOixLET3mFZUu0A') data = exn.ked["a"] assert data["delpre"] == delpre embeds = exn.ked['e'] diff --git a/tests/app/test_grouping.py b/tests/app/test_grouping.py index 6d0cbe59e..5fd0090a7 100644 --- a/tests/app/test_grouping.py +++ b/tests/app/test_grouping.py @@ -638,11 +638,11 @@ def test_multisig_incept(mockHelpingNowUTC): icp=hab.makeOwnEvent(sn=hab.kever.sn)) assert exn.ked["r"] == '/multisig/icp' - assert exn.saidb == b'EGDEBUZW--n-GqOOwRflzBeqoQsYWKMOQVU_1YglG-BL' + assert exn.saidb == b'EJ6Kl50IBicAa8zND_3wMSQ5itw555V7NKid9y1SKobe' assert atc == (b'-FABEIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI30AAAAAAAAAAAAAAA' - b'AAAAAAAAEIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI3-AABAAC84-o2' - b'HKwKxhL1ttzykB9zuFaGV6OpQ05b1ZJYAeBFrR7kVON1aNjpLgQCG_0bY4FUiP7F' - b'GTVDrBjuFhbeDKAH-LAa5AACAA-e-icp-AABAACihaKoLnoXxRoxGbFfOy67YSh6' + b'AAAAAAAAEIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI3-AABAACL4cf7' + b'LxzKJgaJbb7wWHLuTfj3wManDV0SW7euFNZDiEhD1kUiP3_wtOIfqB_ZsEceE4oI' + b'gOOZwFROyrcf9ScB-LAa5AACAA-e-icp-AABAACihaKoLnoXxRoxGbFfOy67YSh6' b'UxtgjT2oxupnLDz2FlhevGJKTMObbdex9f0Hqob6uTavSJvsXf5RzitskkkC') data = exn.ked["a"] assert data["smids"] == aids @@ -662,11 +662,11 @@ def test_multisig_rotate(mockHelpingNowUTC): exn, atc = grouping.multisigRotateExn(ghab=ghab1, smids=ghab1.smids, rmids=ghab1.rmids, rot=rot) assert exn.ked["r"] == '/multisig/rot' - assert exn.saidb == b'EAE5RLyDb_3W8fUOzDOHWwpMAvHePaz8Jpz1XWL0b0lQ' + assert exn.saidb == b'EL4LeEHvTiOxs1UDNTv5qWxCYVYojdpEMfKI62O-UsPm' assert atc == (b'-FABEH__mobl7NDyyQCB1DoLK-OPSueraPtZAlWEjfOYkaba0AAAAAAAAAAAAAAA' - b'AAAAAAAAEH__mobl7NDyyQCB1DoLK-OPSueraPtZAlWEjfOYkaba-AABAACzqlzb' - b'yRO_M5Kp6nyN1K5JZ9s9D4UAreliSs4OiyCe_y9KnDeP65tub3DW5hUKlVQWnPv4' - b'TrOBHk2vJNOEJtAF') + b'AAAAAAAAEH__mobl7NDyyQCB1DoLK-OPSueraPtZAlWEjfOYkaba-AABAACH_qI1' + b'JebS_iehZT6XmvxylpOy2hS2BjO41e4mNmscSBdun2MyGk82SC-rHfQfvDJZlRRw' + b'NhLw-pKKKxql8wUF') data = exn.ked["a"] assert data["smids"] == ghab1.smids @@ -681,11 +681,11 @@ def test_multisig_interact(mockHelpingNowUTC): ixn=ixn) assert exn.ked["r"] == '/multisig/ixn' - assert exn.saidb == b'EGQ_DqGlSBx2MKJfHr6liXAngFpQ0UCtV1cdVMUtJHdN' + assert exn.saidb == b'EDF8o6SK-s2jxUVnlGtqAVtXTF-wyZ26c0dUsS5p766q' assert atc == (b'-FABEH__mobl7NDyyQCB1DoLK-OPSueraPtZAlWEjfOYkaba0AAAAAAAAAAAAAAA' - b'AAAAAAAAEH__mobl7NDyyQCB1DoLK-OPSueraPtZAlWEjfOYkaba-AABAAB3yX6b' - b'EXb8N63PKaMaFqijZVT5TqVtoO8q1BFnoJW3rDkNuJ9lEMpEN-44HKGtvniWZ6-d' - b'CVPS4fsEXKZAKGkB-LAa5AACAA-e-ixn-AABAABG58m7gibjdrQ8YU-8WQ8A70nc' + b'AAAAAAAAEH__mobl7NDyyQCB1DoLK-OPSueraPtZAlWEjfOYkaba-AABAABFfU5s' + b'o86inNogCPN7Ko8WXvkMKeiUKPScQ3FYrVmngNpVmW8xmhOTfixuWFlLcQPjEf3b' + b'RQhvNvx7azcI_vwB-LAa5AACAA-e-ixn-AABAABG58m7gibjdrQ8YU-8WQ8A70nc' b'tYekYr3xdfZ5WgDQOD0bb9pI7SuuaJvzfAQisLAYQnztA82pAo1Skhf1vQwD') data = exn.ked["a"] assert data["smids"] == ghab1.smids @@ -701,11 +701,11 @@ def test_multisig_registry_incept(mockHelpingNowUTC, mockCoringRandomNonce): usage="Issue vLEI Credentials") assert exn.ked["r"] == '/multisig/vcp' - assert exn.saidb == b'EJN27EYqgxTS2NCHdnjE-CU0UikV5a1Cw5OZdv-g0jQ6' + assert exn.saidb == b'EBum6f9SwkUUjQTl_vDplKs7L-shzQT6fS5jJlzdP9PP' assert atc == (b'-FABEDEf72ZZ9mhpT1Xz-_YkXl7cg93sjZUFLIsxaFNTbXQO0AAAAAAAAAAAAAAA' - b'AAAAAAAAEDEf72ZZ9mhpT1Xz-_YkXl7cg93sjZUFLIsxaFNTbXQO-AABAABsPiWf' - b'UE9L7D9KBVOYMg1rt88gK9DBkiBYb21xMR0YH7sCT0hqwX9y8CM5Y6jQwzz3NqqN' - b'-aJWShzz1mbtb5AG-LAa5AACAA-e-anc-AABAABXlwkzbp_tC4MEbx1Uyny1o7dB' + b'AAAAAAAAEDEf72ZZ9mhpT1Xz-_YkXl7cg93sjZUFLIsxaFNTbXQO-AABAAAS5k5D' + b'9jH0rbS6jCtZIPyTJRS2l8TZBnChwG8try3kZUJuiAPoBLo7UuhFYmZlpTZ6MfSg' + b'cDS7XNg0ETj6L3QF-LAa5AACAA-e-anc-AABAABXlwkzbp_tC4MEbx1Uyny1o7dB' b'GHrYjU3u90Mhv2GtrIGG-7va1jZnlXef2R_LM4TRN8_XjmpLv1skcJaM90UB') data = exn.ked["a"] assert data == {'gid': 'EEVG5a8c88Fg9vH-6zQP6gJdc4LxVbUTRydx-JhpDcob', diff --git a/tests/app/test_oobiing.py b/tests/app/test_oobiing.py index 2e81a3050..b9280f7d9 100644 --- a/tests/app/test_oobiing.py +++ b/tests/app/test_oobiing.py @@ -53,19 +53,20 @@ def test_oobi_share(mockHelpingNowUTC): oobi="http://127.0.0.1/oobi") assert exn.ked == {'a': {'dest': 'EO2kxXW0jifQmuPevqg6Zpi3vE-WYoj65i_XhpruWtOg', 'oobi': 'http://127.0.0.1/oobi'}, - 'd': 'EMAhEMPbBU2B-Ha-yLxMEZk49KHYkzZgMv9aZS8gDl1m', + 'd': 'EII7EvdWFqv0jkjRv10t01zAUcRYbjVhZ_yo3VPZEbpS', 'dt': '2021-01-01T00:00:00.000000+00:00', 'e': {}, 'i': 'EIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI3', 'p': '', 'q': {}, 'r': '/oobis', + 'rp': '', 't': 'exn', - 'v': 'KERI10JSON00012e_'} + 'v': 'KERI10JSON000136_'} assert atc == (b'-FABEIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI30AAAAAAAAAAAAAAA' - b'AAAAAAAAEIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI3-AABAACsgmsu' - b'VJoY5a7vicZQ7pT_MZqCe-0psgReRxyoBfFaAPxZ7Vss2eteFuvwDWBeyKc1B-yc' - b'p-2QZzIZJ94_9hIP') + b'AAAAAAAAEIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI3-AABAABdw3eS' + b'w_7BW2o3z1ufxxs1CPgX1TgtJzn-MxvMjLYTidUd8KSxNKbPU9M3A4orYJDMGMIz' + b'habHJmKA4ZIGbcgK') def test_oobiery(): diff --git a/tests/core/test_coring.py b/tests/core/test_coring.py index 0933c0e89..e8eee29b4 100644 --- a/tests/core/test_coring.py +++ b/tests/core/test_coring.py @@ -2179,7 +2179,9 @@ def test_counter(): 'SadPathSigGroups': '-J', 'RootSadPathSigGroups': '-K', 'PathedMaterialGroup': '-L', + 'BigPathedMaterialGroup': '-0L', 'AttachmentGroup': '-V', + 'ESSRPayloadGroup': '-Z', 'BigAttachmentGroup': '-0V', 'KERIACDCGenusVersion': '--AAA', } @@ -2215,7 +2217,9 @@ def test_counter(): '-J': Sizage(hs=2, ss=2, fs=4, ls=0), '-K': Sizage(hs=2, ss=2, fs=4, ls=0), '-L': Sizage(hs=2, ss=2, fs=4, ls=0), + '-0L': Sizage(hs=3, ss=5, fs=8, ls=0), '-V': Sizage(hs=2, ss=2, fs=4, ls=0), + '-Z': Sizage(hs=2, ss=2, fs=4, ls=0), '-0V': Sizage(hs=3, ss=5, fs=8, ls=0), '--AAA': Sizage(hs=5, ss=3, fs=8, ls=0) } @@ -2333,10 +2337,10 @@ def test_counter(): assert counter.qb64 == qsc assert counter.qb2 == qscb2 - # test with big codes index=1024 - count = 1024 + # test with big codes index=1024000 + count = 1024000 qsc = CtrDex.BigAttachmentGroup + intToB64(count, l=5) - assert qsc == '-0VAAAQA' + assert qsc == '-0VAD6AA' qscb = qsc.encode("utf-8") qscb2 = decodeB64(qscb) @@ -2383,6 +2387,42 @@ def test_counter(): test = counter._binfil() assert test == qb2 + # Test limits of PathedMaterialGroup + count = 255 + qsc = CtrDex.PathedMaterialGroup + intToB64(count, l=2) + assert qsc == '-LD_' + qscb = qsc.encode("utf-8") + qscb2 = decodeB64(qscb) + + counter = Counter(code=CtrDex.PathedMaterialGroup, count=count) + assert counter.code == CtrDex.PathedMaterialGroup + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + counter = Counter(qb64='-L__') + assert counter.count == 4095 + + with pytest.raises(kering.InvalidVarIndexError): + Counter(code=CtrDex.PathedMaterialGroup, count=4096) # Too big + + # Test BigPathedMaterialGroup + # test with big codes index=1024000 + count = 1024000 + qsc = CtrDex.BigPathedMaterialGroup + intToB64(count, l=5) + assert qsc == '-0LAD6AA' + qscb = qsc.encode("utf-8") + qscb2 = decodeB64(qscb) + + counter = Counter(code=CtrDex.BigPathedMaterialGroup, count=count) + assert counter.code == CtrDex.BigPathedMaterialGroup + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + + # Test with strip # create code manually count = 1 diff --git a/tests/core/test_counting.py b/tests/core/test_counting.py index 7887a610f..e94d18e5e 100644 --- a/tests/core/test_counting.py +++ b/tests/core/test_counting.py @@ -74,7 +74,9 @@ def test_codexes_tags(): 'SadPathSigGroups': '-J', 'RootSadPathSigGroups': '-K', 'PathedMaterialGroup': '-L', + 'BigPathedMaterialGroup': '-0L', 'AttachmentGroup': '-V', + 'ESSRPayloadGroup': '-Z', 'BigAttachmentGroup': '-0V', 'KERIACDCGenusVersion': '--AAA' } @@ -151,8 +153,10 @@ def test_codexes_tags(): 'SadPathSigGroups': 'SadPathSigGroups', 'RootSadPathSigGroups': 'RootSadPathSigGroups', 'PathedMaterialGroup': 'PathedMaterialGroup', + 'BigPathedMaterialGroup': 'BigPathedMaterialGroup', 'AttachmentGroup': 'AttachmentGroup', 'BigAttachmentGroup': 'BigAttachmentGroup', + 'ESSRPayloadGroup': 'ESSRPayloadGroup', 'KERIACDCGenusVersion': 'KERIACDCGenusVersion' } @@ -353,6 +357,7 @@ def test_counter_class(): '-J': Sizage(hs=2, ss=2, fs=4, ls=0), '-K': Sizage(hs=2, ss=2, fs=4, ls=0), '-L': Sizage(hs=2, ss=2, fs=4, ls=0), + '-0L': Sizage(hs=3, ss=5, fs=8, ls=0), '-V': Sizage(hs=2, ss=2, fs=4, ls=0), '-0V': Sizage(hs=3, ss=5, fs=8, ls=0), '--AAA': Sizage(hs=5, ss=3, fs=8, ls=0) @@ -663,10 +668,10 @@ def test_counter_v1(): assert counter.qb2 == qscb2 assert counter.version == Vrsn_1_0 - # test with big codes index=1024 - count = 1024 + # test with big codes index=100024000 + count = 100024000 qsc = CtrDex.BigAttachmentGroup + intToB64(count, l=5) - assert qsc == '-0VAAAQA' + assert qsc == '-0VF9j7A' qscb = qsc.encode("utf-8") qscb2 = decodeB64(qscb) @@ -723,6 +728,66 @@ def test_counter_v1(): test = counter._binfil() assert test == qb2 + # test BigPathedMaterialGroup with big codes index=100024000 + count = 100024000 + qsc = CtrDex.BigPathedMaterialGroup + intToB64(count, l=5) + assert qsc == '-0LF9j7A' + qscb = qsc.encode("utf-8") + qscb2 = decodeB64(qscb) + + counter = Counter(code=CtrDex.BigPathedMaterialGroup, count=count, gvrsn=Vrsn_1_0) + assert counter.code == CtrDex.BigPathedMaterialGroup + assert counter.tag == AllTags.BigPathedMaterialGroup + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + assert counter.version == Vrsn_1_0 + + counter = Counter(qb64b=qscb, gvrsn=Vrsn_1_0) # test with bytes not str + assert counter.code == CtrDex.BigPathedMaterialGroup + assert counter.tag == AllTags.BigPathedMaterialGroup + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + assert counter.version == Vrsn_1_0 + + counter = Counter(qb64=qsc, gvrsn=Vrsn_1_0) # test with str not bytes + assert counter.code == CtrDex.BigPathedMaterialGroup + assert counter.tag == AllTags.BigPathedMaterialGroup + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + assert counter.version == Vrsn_1_0 + + counter = Counter(qb2=qscb2, gvrsn=Vrsn_1_0) # test with qb2 + assert counter.code == CtrDex.BigPathedMaterialGroup + assert counter.tag == AllTags.BigPathedMaterialGroup + assert counter.count == count + assert counter.qb64b == qscb + assert counter.qb64 == qsc + assert counter.qb2 == qscb2 + assert counter.version == Vrsn_1_0 + + # Test ._bexfil + counter = Counter(qb64=qsc, gvrsn=Vrsn_1_0) # + code = counter.code + count = counter.count + qb2 = counter.qb2 + counter._bexfil(qb2) + assert counter.code == code + assert counter.tag == AllTags.BigPathedMaterialGroup + assert counter.count == count + assert counter.qb64 == qsc + assert counter.qb2 == qb2 + assert counter.version == Vrsn_1_0 + + # Test ._binfil + test = counter._binfil() + assert test == qb2 + # Test with strip # create code manually count = 1 diff --git a/tests/core/test_serdering.py b/tests/core/test_serdering.py index 5ca21c30c..ef7cbd07e 100644 --- a/tests/core/test_serdering.py +++ b/tests/core/test_serdering.py @@ -2225,20 +2225,20 @@ def test_serderkeri_exn(): # Test KERI JSON with makify defaults for self bootstrap with ilk ixn serder = SerderKERI(makify=True, ilk=kering.Ilks.exn) # make with defaults - assert serder.sad == {'v': 'KERI10JSON000088_', - 't': 'exn', - 'd': 'EMuAoRSE4zREKKYyvuNeYCDM9_MwPQIh1WL0cFC4e-bU', - 'i': '', - 'p': '', - 'dt': '', - 'r': '', - 'q': {}, - 'a': [], - 'e': {}} - - assert serder.raw == (b'{"v":"KERI10JSON000088_","t":"exn",' - b'"d":"EMuAoRSE4zREKKYyvuNeYCDM9_MwPQIh1WL0' - b'cFC4e-bU","i":"","p":"","dt":"","r":"","q":{},"a":[],"e":{}}') + assert serder.sad == {'a': [], + 'd': 'EPx9pShQTfv2FoISZJAZ4dlUcekG8-CSkgJh0i0q_iJn', + 'dt': '', + 'e': {}, + 'i': '', + 'p': '', + 'q': {}, + 'r': '', + 'rp': '', + 't': 'exn', + 'v': 'KERI10JSON000090_'} + + assert serder.raw == (b'{"v":"KERI10JSON000090_","t":"exn","d":"EPx9pShQTfv2FoISZJAZ4dlUcekG8-CSkgJh' + b'0i0q_iJn","i":"","rp":"","p":"","dt":"","r":"","q":{},"a":[],"e":{}}') diff --git a/tests/peer/test_exchanging.py b/tests/peer/test_exchanging.py index 6cb20d739..512d4ac86 100644 --- a/tests/peer/test_exchanging.py +++ b/tests/peer/test_exchanging.py @@ -3,10 +3,15 @@ tests.peer.test_exchanging module """ +import pysodium +from base64 import urlsafe_b64encode as encodeB64 +from base64 import urlsafe_b64decode as decodeB64 + from keri import core -from keri.core import coring, serdering +from keri.core import coring, serdering, MtrDex, parsing from keri.app import habbing, forwarding, storing, signing +from keri.core.coring import CtrDex from keri.peer import exchanging from keri.vdr.eventing import incept @@ -46,6 +51,52 @@ def test_nesting(): assert pathed == {} +def test_essrs(): + with habbing.openHab(name="sid", base="test", salt=b'0123456789abcdef') as (hby, hab), \ + habbing.openHab(name="rec", base="test", salt=b'0123456789abcdef') as (recHby, recHab): + + ims = hab.makeOwnInception() + parsing.Parser().parse(ims=ims, kvy=recHby.kvy) + # create the test message with essr attachment + msg = "This is a test message that must be secured" + rkever = recHab.kever + pubkey = pysodium.crypto_sign_pk_to_box_pk(rkever.verfers[0].raw) + raw = pysodium.crypto_box_seal(msg.encode("utf-8"), pubkey) + b64 = encodeB64(raw) + + texter = coring.Texter(raw=b64) + diger = coring.Diger(ser=texter.qb64b, code=MtrDex.Blake3_256) + essr, _ = exchanging.exchange(route='/essr/req', sender=hab.pre, diger=diger, + modifiers=dict(src=hab.pre, dest=recHab.pre)) + ims = hab.endorse(serder=essr, pipelined=False) + ims.extend(coring.Counter(code=CtrDex.ESSRPayloadGroup, count=1).qb64b) + ims.extend(texter.qb64b) + + exc = exchanging.Exchanger(hby=recHby, handlers=[]) + parsing.Parser().parse(ims=ims, kvy=recHby.kvy, exc=exc) + + # Pull the logged exn and verify the attributes digest matches the attachment + serder = recHby.db.exns.get(keys=(essr.said,)) + assert serder.ked['a'] == diger.qb64 + + # Pull the logged ESSR attachment and verify it is the one attached + texter = recHby.db.essrs.get(keys=(diger.qb64,)) + raw = recHab.decrypt(decodeB64(texter.raw)) + assert raw.decode("utf-8") == msg + + # Test with invalid diger + diger = coring.Diger(qb64="EKC8085pwSwzLwUGzh-HrEoFDwZnCJq27bVp5atdMT9o") + essr, _ = exchanging.exchange(route='/essr/req', sender=hab.pre, diger=diger, + modifiers=dict(src=hab.pre, dest=recHab.pre)) + ims = hab.endorse(serder=essr, pipelined=False) + ims.extend(coring.Counter(code=CtrDex.ESSRPayloadGroup, count=1).qb64b) + ims.extend(texter.qb64b) + + parsing.Parser().parse(ims=ims, kvy=recHby.kvy, exc=exc) + assert recHby.db.exns.get(keys=(essr.said,)) is None + + + def test_exchanger(): with habbing.openHab(name="sid", base="test", salt=b'0123456789abcdef') as (hby, hab), \ habbing.openHab(name="rec", base="test", salt=b'0123456789abcdef') as (recHby, recHab): @@ -101,26 +152,26 @@ def test_hab_exchange(mockHelpingNowUTC): data = dict(m="Let's create a registry") msg = hab.exchange(route="/multisig/registry/incept", recipient="", payload=data, embeds=embeds) - assert msg == (b'{"v":"KERI10JSON000398_","t":"exn","d":"ECcmfGnlqnc5-1_oXNpbfowv' - b'RsEa-V8tfeKmQDRJJ50i","i":"EIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2Q' - b'V8dDjI3","p":"","dt":"2021-01-01T00:00:00.000000+00:00","r":"/mu' - b'ltisig/registry/incept","q":{},"a":{"i":"","m":"Let\'s create a r' - b'egistry"},"e":{"vcp":{"v":"KERI10JSON00010f_","t":"vcp","d":"EI6' - b'hBlgkWoJgkZyfLW35_UyM4nIK44OgsSwFR_WOfvVB","i":"EI6hBlgkWoJgkZyf' - b'LW35_UyM4nIK44OgsSwFR_WOfvVB","ii":"EIaGMMWJFPmtXznY1IIiKDIrg-vI' - b'yge6mBl2QV8dDjI3","s":"0","c":[],"bt":"0","b":[],"n":"AH3-1EZWXU' - b'9I0fv3Iz_9ZIhjj13JO7u4GNFYC3-l8_K-"},"ixn":{"v":"KERI10JSON00013' - b'8_","t":"ixn","d":"EFuFnevyDFfpWG6il-6Qcv0ne0ZIItLwanCwI-SU8A9j"' - b',"i":"EIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI3","s":"1","p":' - b'"EIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI3","a":[{"i":"EI6hBl' - b'gkWoJgkZyfLW35_UyM4nIK44OgsSwFR_WOfvVB","s":0,"d":"EI6hBlgkWoJgk' - b'ZyfLW35_UyM4nIK44OgsSwFR_WOfvVB"}]},"d":"EL5Nkm6T7HG_0GW6uwqYSZw' - b'lH23khtXvsVE-dq8eO_eE"}}-FABEIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2' - b'QV8dDjI30AAAAAAAAAAAAAAAAAAAAAAAEIaGMMWJFPmtXznY1IIiKDIrg-vIyge6' - b'mBl2QV8dDjI3-AABAACahD6g7IwjUyQRyGUPGLvlr5-DsvLxeJtCUVIIECYfAQ_q' - b'p3Z2pe__HRqIl-NrUv85oQrZBm0kpKn8LBQtQfkO-LAa5AACAA-e-ixn-AABAADp' - b'rTWp4llIzVzBM7VVsDOgXVJdoiVXutsWJEbDJ2pMdjXjNi1xKALBSZ1ZgRoUsD--' - b'LgUQkXIdjLoQ19XPvJMJ') + assert msg == (b'{"v":"KERI10JSON0003a0_","t":"exn","d":"ELkHqph-Tj4LGHYfFfoVmJJo' + b'09S2gp6ci8rK96upIAKE","i":"EIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2Q' + b'V8dDjI3","rp":"","p":"","dt":"2021-01-01T00:00:00.000000+00:00",' + b'"r":"/multisig/registry/incept","q":{},"a":{"i":"","m":"Let\'s cr' + b'eate a registry"},"e":{"vcp":{"v":"KERI10JSON00010f_","t":"vcp",' + b'"d":"EI6hBlgkWoJgkZyfLW35_UyM4nIK44OgsSwFR_WOfvVB","i":"EI6hBlgk' + b'WoJgkZyfLW35_UyM4nIK44OgsSwFR_WOfvVB","ii":"EIaGMMWJFPmtXznY1IIi' + b'KDIrg-vIyge6mBl2QV8dDjI3","s":"0","c":[],"bt":"0","b":[],"n":"AH' + b'3-1EZWXU9I0fv3Iz_9ZIhjj13JO7u4GNFYC3-l8_K-"},"ixn":{"v":"KERI10J' + b'SON000138_","t":"ixn","d":"EFuFnevyDFfpWG6il-6Qcv0ne0ZIItLwanCwI' + b'-SU8A9j","i":"EIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI3","s":' + b'"1","p":"EIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI3","a":[{"i"' + b':"EI6hBlgkWoJgkZyfLW35_UyM4nIK44OgsSwFR_WOfvVB","s":0,"d":"EI6hB' + b'lgkWoJgkZyfLW35_UyM4nIK44OgsSwFR_WOfvVB"}]},"d":"EL5Nkm6T7HG_0GW' + b'6uwqYSZwlH23khtXvsVE-dq8eO_eE"}}-FABEIaGMMWJFPmtXznY1IIiKDIrg-vI' + b'yge6mBl2QV8dDjI30AAAAAAAAAAAAAAAAAAAAAAAEIaGMMWJFPmtXznY1IIiKDIr' + b'g-vIyge6mBl2QV8dDjI3-AABAAB-teJc_7zot5TAZT6lQi2-GlBzMHXICvt3tIYo' + b'Po2gYXF7PpWDozo3y3wVW9mgHln-1DvQlqn9Aip1YnBgKUQB-LAa5AACAA-e-ixn' + b'-AABAADprTWp4llIzVzBM7VVsDOgXVJdoiVXutsWJEbDJ2pMdjXjNi1xKALBSZ1Z' + b'gRoUsD--LgUQkXIdjLoQ19XPvJMJ') exn = serdering.SerderKERI(raw=msg) @@ -143,27 +194,27 @@ def test_hab_exchange(mockHelpingNowUTC): data = dict(m="Lets create this registry instead") msg = hab2.exchange(route="/multisig/registry/incept", payload=data, recipient="", dig=exn.said, embeds=embeds) - assert msg == (b'{"v":"KERI10JSON0003ce_","t":"exn","d":"EEMxkjO9HzZoekfzmjrkE19y' - b'pU259apUWuY7alFu_GmE","i":"EIREQlatUJODbKogZfa3IqXZ90XdZA0qJMVli' - b'I61Bcc2","p":"ECcmfGnlqnc5-1_oXNpbfowvRsEa-V8tfeKmQDRJJ50i","dt"' - b':"2021-01-01T00:00:00.000000+00:00","r":"/multisig/registry/ince' - b'pt","q":{},"a":{"i":"","m":"Lets create this registry instead"},' - b'"e":{"vcp":{"v":"KERI10JSON00010f_","t":"vcp","d":"EB5mts6qrWOZr' - b'xjma6lSTjAdPZ0NSHM1HC3IndbS_giB","i":"EB5mts6qrWOZrxjma6lSTjAdPZ' - b'0NSHM1HC3IndbS_giB","ii":"EIREQlatUJODbKogZfa3IqXZ90XdZA0qJMVliI' - b'61Bcc2","s":"0","c":[],"bt":"0","b":[],"n":"AH3-1EZWXU9I0fv3Iz_9' - b'ZIhjj13JO7u4GNFYC3-l8_K-"},"ixn":{"v":"KERI10JSON000138_","t":"i' - b'xn","d":"EOek9JVKNeuW-5UNeHYCTDe70_GtvRwP672oWMNBJpA5","i":"EIRE' - b'QlatUJODbKogZfa3IqXZ90XdZA0qJMVliI61Bcc2","s":"1","p":"EIREQlatU' - b'JODbKogZfa3IqXZ90XdZA0qJMVliI61Bcc2","a":[{"i":"EB5mts6qrWOZrxjm' - b'a6lSTjAdPZ0NSHM1HC3IndbS_giB","s":0,"d":"EB5mts6qrWOZrxjma6lSTjA' - b'dPZ0NSHM1HC3IndbS_giB"}]},"d":"EM3gLTzQ9GmKd50Rlm_kiIkeYkxb004eo' - b'OsWahz70TqJ"}}-FABEIREQlatUJODbKogZfa3IqXZ90XdZA0qJMVliI61Bcc20A' - b'AAAAAAAAAAAAAAAAAAAAAAEIREQlatUJODbKogZfa3IqXZ90XdZA0qJMVliI61Bc' - b'c2-AABAAAxpwQLr9-D7hOZYHvvDB_ffo5sRgBf0NufowF0g_YMI1wdnttlYA2o_d' - b'wtK_WNbfh_iAytFw9nHZziCED13AwH-LAa5AACAA-e-ixn-AABAACaoxfQp5L_Gd' - b'0nKqJXMbLTXzkrJJDd8RFxWdTSesAMydUzmJQlGt0T9h8L7SwIrq8yBinj990PLJ' - b'Hl7sXmq04I') + assert msg == (b'{"v":"KERI10JSON0003d6_","t":"exn","d":"EPO_XC9nwSixqSoOvsHymFr-' + b'l3udclHBdOh4OUEqZ33P","i":"EIREQlatUJODbKogZfa3IqXZ90XdZA0qJMVli' + b'I61Bcc2","rp":"","p":"ELkHqph-Tj4LGHYfFfoVmJJo09S2gp6ci8rK96upIA' + b'KE","dt":"2021-01-01T00:00:00.000000+00:00","r":"/multisig/regis' + b'try/incept","q":{},"a":{"i":"","m":"Lets create this registry in' + b'stead"},"e":{"vcp":{"v":"KERI10JSON00010f_","t":"vcp","d":"EB5mt' + b's6qrWOZrxjma6lSTjAdPZ0NSHM1HC3IndbS_giB","i":"EB5mts6qrWOZrxjma6' + b'lSTjAdPZ0NSHM1HC3IndbS_giB","ii":"EIREQlatUJODbKogZfa3IqXZ90XdZA' + b'0qJMVliI61Bcc2","s":"0","c":[],"bt":"0","b":[],"n":"AH3-1EZWXU9I' + b'0fv3Iz_9ZIhjj13JO7u4GNFYC3-l8_K-"},"ixn":{"v":"KERI10JSON000138_' + b'","t":"ixn","d":"EOek9JVKNeuW-5UNeHYCTDe70_GtvRwP672oWMNBJpA5","' + b'i":"EIREQlatUJODbKogZfa3IqXZ90XdZA0qJMVliI61Bcc2","s":"1","p":"E' + b'IREQlatUJODbKogZfa3IqXZ90XdZA0qJMVliI61Bcc2","a":[{"i":"EB5mts6q' + b'rWOZrxjma6lSTjAdPZ0NSHM1HC3IndbS_giB","s":0,"d":"EB5mts6qrWOZrxj' + b'ma6lSTjAdPZ0NSHM1HC3IndbS_giB"}]},"d":"EM3gLTzQ9GmKd50Rlm_kiIkeY' + b'kxb004eoOsWahz70TqJ"}}-FABEIREQlatUJODbKogZfa3IqXZ90XdZA0qJMVliI' + b'61Bcc20AAAAAAAAAAAAAAAAAAAAAAAEIREQlatUJODbKogZfa3IqXZ90XdZA0qJM' + b'VliI61Bcc2-AABAADY5nUsBgL23ulcrTgkV09hSzktNHZSlEH1zmVpEggrGgQUq0' + b'tLQeOXztUFDxNQ4Kq2ddIYDVz6d_y0kkU3__YJ-LAa5AACAA-e-ixn-AABAACaox' + b'fQp5L_Gd0nKqJXMbLTXzkrJJDd8RFxWdTSesAMydUzmJQlGt0T9h8L7SwIrq8yBi' + b'nj990PLJHl7sXmq04I') # Test exn from non-transferable AID hab = hby.makeHab(name="test1", transferable=False) @@ -174,18 +225,18 @@ def test_hab_exchange(mockHelpingNowUTC): ) msg = hab.exchange(route="/multisig/registry/incept", payload=data, embeds=embeds, recipient="") - assert msg == (b'{"v":"KERI10JSON000263_","t":"exn","d":"ENRFAVDU_ZbcVpx6l6lrC5Mu' - b'UqHXfT3N9VjUkvU4t29S","i":"BJZ_LF61JTCCSCIw2Q4ozE2MsbRC4m-N6-tFV' - b'lCeiZPG","p":"","dt":"2021-01-01T00:00:00.000000+00:00","r":"/mu' - b'ltisig/registry/incept","q":{},"a":{"i":"","m":"Lets create this' - b' registry instead"},"e":{"vcp":{"v":"KERI10JSON00010f_","t":"vcp' - b'","d":"EB5mts6qrWOZrxjma6lSTjAdPZ0NSHM1HC3IndbS_giB","i":"EB5mts' - b'6qrWOZrxjma6lSTjAdPZ0NSHM1HC3IndbS_giB","ii":"EIREQlatUJODbKogZf' - b'a3IqXZ90XdZA0qJMVliI61Bcc2","s":"0","c":[],"bt":"0","b":[],"n":"' - b'AH3-1EZWXU9I0fv3Iz_9ZIhjj13JO7u4GNFYC3-l8_K-"},"d":"ENC6w8wUj-Gp' - b'_RpAJN5q4Lf00IHstzNLUvkh3ZvgHGP_"}}-CABBJZ_LF61JTCCSCIw2Q4ozE2Ms' - b'bRC4m-N6-tFVlCeiZPG0BCxLApuSnk1MF9IUq1RJNjVmr6s-fLwvP6aAPa0ag34t' - b'4G7EKKk-UFwy74-0StSlHcS8KBkN5ZbtuHvV9tXRqUJ-LAl5AACAA-e-vcp-CABB' - b'JZ_LF61JTCCSCIw2Q4ozE2MsbRC4m-N6-tFVlCeiZPG0BDjOC4j0Co6P0giMylR4' - b'7149eJ8Yf_hO-32_TpY77KMVCWCf0U8GuZPIN76R2zsyT_eARvS_zQsX1ebjl3PM' - b'P0D') + assert msg == (b'{"v":"KERI10JSON00026b_","t":"exn","d":"EMBm0p7fCIqJrP4Z-PBI-yEv' + b'Xin_-eY1dU4XTCM9ykRC","i":"BJZ_LF61JTCCSCIw2Q4ozE2MsbRC4m-N6-tFV' + b'lCeiZPG","rp":"","p":"","dt":"2021-01-01T00:00:00.000000+00:00",' + b'"r":"/multisig/registry/incept","q":{},"a":{"i":"","m":"Lets cre' + b'ate this registry instead"},"e":{"vcp":{"v":"KERI10JSON00010f_",' + b'"t":"vcp","d":"EB5mts6qrWOZrxjma6lSTjAdPZ0NSHM1HC3IndbS_giB","i"' + b':"EB5mts6qrWOZrxjma6lSTjAdPZ0NSHM1HC3IndbS_giB","ii":"EIREQlatUJ' + b'ODbKogZfa3IqXZ90XdZA0qJMVliI61Bcc2","s":"0","c":[],"bt":"0","b":' + b'[],"n":"AH3-1EZWXU9I0fv3Iz_9ZIhjj13JO7u4GNFYC3-l8_K-"},"d":"ENC6' + b'w8wUj-Gp_RpAJN5q4Lf00IHstzNLUvkh3ZvgHGP_"}}-CABBJZ_LF61JTCCSCIw2' + b'Q4ozE2MsbRC4m-N6-tFVlCeiZPG0BB-sQs0WS9wsyuT4hXQD7rbczSfpnQz21wZG' + b'YucRkE0ynKy5draELEKBsckeD0Im1i-kIfMEdbY08YqVfSrEoAA-LAl5AACAA-e-' + b'vcp-CABBJZ_LF61JTCCSCIw2Q4ozE2MsbRC4m-N6-tFVlCeiZPG0BDjOC4j0Co6P' + b'0giMylR47149eJ8Yf_hO-32_TpY77KMVCWCf0U8GuZPIN76R2zsyT_eARvS_zQsX' + b'1ebjl3PMP0D') diff --git a/tests/vc/test_protocoling.py b/tests/vc/test_protocoling.py index f507f9fad..f6dde10bd 100644 --- a/tests/vc/test_protocoling.py +++ b/tests/vc/test_protocoling.py @@ -120,26 +120,26 @@ def test_ipex(seeder, mockCoringRandomNonce, mockHelpingNowIso8601, mockHelpingN apply0, apply0atc = protocoling.ipexApplyExn(sidHab, message="Please give me a credential", schema=schema, recp=redPre, attrs={}) - assert apply0.raw == (b'{"v":"KERI10JSON00016d_","t":"exn","d":"EIPeVB3u7L-mEKjhY6zIu5M7LErPwlUccxIN' - b'ddwhcFrH","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","p":"","dt":"20' - b'21-06-27T21:26:21.233257+00:00","r":"/ipex/apply","q":{},"a":{"m":"Please gi' - b've me a credential","s":"EMQWEcCnVRk1hatTNyK3sIykYSrrFvafX3bHQ9Gkk1kC","a":{' - b'},"i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl"},"e":{}}') + assert apply0.raw == (b'{"v":"KERI10JSON000175_","t":"exn","d":"EHVK5cO32UQJCkpK9RqRP_ONViK8u3JNXn73' + b'nJ8hdmXr","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","rp":"","p":"",' + b'"dt":"2021-06-27T21:26:21.233257+00:00","r":"/ipex/apply","q":{},"a":{"m":"P' + b'lease give me a credential","s":"EMQWEcCnVRk1hatTNyK3sIykYSrrFvafX3bHQ9Gkk1k' + b'C","a":{},"i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl"},"e":{}}') # No requirements for apply, except that its first, no `p` assert ipexhan.verify(serder=apply0) is True offer0, offer0atc = protocoling.ipexOfferExn(sidHab, "How about this", acdc=creder.raw, apply=apply0) - assert offer0.raw == (b'{"v":"KERI10JSON0002f0_","t":"exn","d":"EO4NXvOU-UpwwAR67txzKrFBHGAtDu9ehg8g' - b'Ic5haJy3","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","p":"EIPeVB3u7L' - b'-mEKjhY6zIu5M7LErPwlUccxINddwhcFrH","dt":"2021-06-27T21:26:21.233257+00:00",' - b'"r":"/ipex/offer","q":{},"a":{"m":"How about this"},"e":{"acdc":{"v":"ACDC10' - b'JSON000197_","d":"EElymNmgs1u0mSaoCeOtSsNOROLuqOz103V3-4E-ClXH","i":"EMl4Rhu' - b'R_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","ri":"EB-u4VAF7A7_GR8PXJoAVHv5X9vjtXe' - b'w8Yo6Z3w9mQUQ","s":"EMQWEcCnVRk1hatTNyK3sIykYSrrFvafX3bHQ9Gkk1kC","a":{"d":"' - b'EO9_6NattzsFiO8Fw1cxjYmDjOsKKSbootn-wXn9S3iB","dt":"2021-06-27T21:26:21.2332' - b'57+00:00","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","LEI":"254900OP' - b'PU84GM83MG36"}},"d":"EOG-KWyllXlb2HVIuewN1YJAOT304PaSczyt3V5Z878S"}}') + assert offer0.raw == (b'{"v":"KERI10JSON0002f8_","t":"exn","d":"ENdVOCsP5Xz57qs1xa_msznozvBs6Ii0_JRo' + b'i6tp2NBu","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","rp":"","p":"EH' + b'VK5cO32UQJCkpK9RqRP_ONViK8u3JNXn73nJ8hdmXr","dt":"2021-06-27T21:26:21.233257' + b'+00:00","r":"/ipex/offer","q":{},"a":{"m":"How about this"},"e":{"acdc":{"v"' + b':"ACDC10JSON000197_","d":"EElymNmgs1u0mSaoCeOtSsNOROLuqOz103V3-4E-ClXH","i":' + b'"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","ri":"EB-u4VAF7A7_GR8PXJoAVHv' + b'5X9vjtXew8Yo6Z3w9mQUQ","s":"EMQWEcCnVRk1hatTNyK3sIykYSrrFvafX3bHQ9Gkk1kC","a' + b'":{"d":"EO9_6NattzsFiO8Fw1cxjYmDjOsKKSbootn-wXn9S3iB","dt":"2021-06-27T21:26' + b':21.233257+00:00","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","LEI":"' + b'254900OPPU84GM83MG36"}},"d":"EOG-KWyllXlb2HVIuewN1YJAOT304PaSczyt3V5Z878S"}}') # This should fail because it is not first and the apply isn't persisted yet assert ipexhan.verify(serder=offer0) is False @@ -166,26 +166,26 @@ def test_ipex(seeder, mockCoringRandomNonce, mockHelpingNowIso8601, mockHelpingN # Let's see if we can spurn a message we previously accepted. spurn0, spurn0atc = protocoling.ipexSpurnExn(sidHab, "I reject you", spurned=apply0) - assert spurn0.raw == (b'{"v":"KERI10JSON00011d_","t":"exn","d":"ENWl0Dd-9idlgrpkFL2aA0wfnuGHzvT4bHCN' - b'G6C0WBZk","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","p":"EIPeVB3u7L' - b'-mEKjhY6zIu5M7LErPwlUccxINddwhcFrH","dt":"2021-06-27T21:26:21.233257+00:00",' - b'"r":"/ipex/spurn","q":{},"a":{"m":"I reject you"},"e":{}}') + assert spurn0.raw == (b'{"v":"KERI10JSON000125_","t":"exn","d":"EHijfrof83z7JeFR-wJO9Ptgl-PieQHhKC-F' + b'bZIDvGvM","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","rp":"","p":"EH' + b'VK5cO32UQJCkpK9RqRP_ONViK8u3JNXn73nJ8hdmXr","dt":"2021-06-27T21:26:21.233257' + b'+00:00","r":"/ipex/spurn","q":{},"a":{"m":"I reject you"},"e":{}}') # This will fail, we've already responded with an offer assert ipexhan.verify(spurn0) is False # Now lets try an offer without a pointer back to a reply offer1, offer1atc = protocoling.ipexOfferExn(sidHab, "Here a credential offer", acdc=creder.raw) - assert offer1.raw == (b'{"v":"KERI10JSON0002cd_","t":"exn","d":"ELnRdb-cA_rLckt9jwlSY-1nnPKwzRc4Up_7' - b'tCdzI12n","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","p":"","dt":"20' - b'21-06-27T21:26:21.233257+00:00","r":"/ipex/offer","q":{},"a":{"m":"Here a cr' - b'edential offer"},"e":{"acdc":{"v":"ACDC10JSON000197_","d":"EElymNmgs1u0mSaoC' - b'eOtSsNOROLuqOz103V3-4E-ClXH","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiU' - b'bl","ri":"EB-u4VAF7A7_GR8PXJoAVHv5X9vjtXew8Yo6Z3w9mQUQ","s":"EMQWEcCnVRk1hat' - b'TNyK3sIykYSrrFvafX3bHQ9Gkk1kC","a":{"d":"EO9_6NattzsFiO8Fw1cxjYmDjOsKKSbootn' - b'-wXn9S3iB","dt":"2021-06-27T21:26:21.233257+00:00","i":"EMl4RhuR_JxpiMd1N8DE' - b'JEhTxM3Ovvn9Xya8AN-tiUbl","LEI":"254900OPPU84GM83MG36"}},"d":"EOG-KWyllXlb2H' - b'VIuewN1YJAOT304PaSczyt3V5Z878S"}}') + assert offer1.raw == (b'{"v":"KERI10JSON0002d5_","t":"exn","d":"EC8fiu3IoCex-7uhTskkEodJOiQYQpO61l3Y' + b'HCXWuuFi","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","rp":"","p":"",' + b'"dt":"2021-06-27T21:26:21.233257+00:00","r":"/ipex/offer","q":{},"a":{"m":"H' + b'ere a credential offer"},"e":{"acdc":{"v":"ACDC10JSON000197_","d":"EElymNmgs' + b'1u0mSaoCeOtSsNOROLuqOz103V3-4E-ClXH","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xy' + b'a8AN-tiUbl","ri":"EB-u4VAF7A7_GR8PXJoAVHv5X9vjtXew8Yo6Z3w9mQUQ","s":"EMQWEcC' + b'nVRk1hatTNyK3sIykYSrrFvafX3bHQ9Gkk1kC","a":{"d":"EO9_6NattzsFiO8Fw1cxjYmDjOs' + b'KKSbootn-wXn9S3iB","dt":"2021-06-27T21:26:21.233257+00:00","i":"EMl4RhuR_Jxp' + b'iMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","LEI":"254900OPPU84GM83MG36"}},"d":"EOG-KW' + b'yllXlb2HVIuewN1YJAOT304PaSczyt3V5Z878S"}}') # Will work because it is starting a new conversation assert ipexhan.verify(serder=offer1) is True @@ -197,10 +197,11 @@ def test_ipex(seeder, mockCoringRandomNonce, mockHelpingNowIso8601, mockHelpingN assert serder.ked == offer1.ked agree, argeeAtc = protocoling.ipexAgreeExn(sidHab, "I'll accept that offer", offer=offer0) - assert agree.raw == (b'{"v":"KERI10JSON000127_","t":"exn","d":"EEtu1OAPj03IdbhMwsQtgbJJaWgG2tdYLJ_3' - b'BuJQekdP","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","p":"EO4NXvOU-U' - b'pwwAR67txzKrFBHGAtDu9ehg8gIc5haJy3","dt":"2021-06-27T21:26:21.233257+00:00",' - b'"r":"/ipex/agree","q":{},"a":{"m":"I\'ll accept that offer"},"e":{}}') + assert agree.raw == (b'{"v":"KERI10JSON00012f_","t":"exn","d":"ECU3UjnSY1_6Wl3aYEW19jaGiKuyFh_chIQQ' + b'w48bcT_X","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","rp":"","p":"EN' + b'dVOCsP5Xz57qs1xa_msznozvBs6Ii0_JRoi6tp2NBu","dt":"2021-06-27T21:26:21.233257' + b'+00:00","r":"/ipex/agree","q":{},"a":{"m":"I\'ll accept that offer"},"e":' + b'{}}') # Can not create an agree without an offer, so this will pass since it has an offer that has no response assert ipexhan.verify(serder=agree) is True @@ -215,24 +216,24 @@ def test_ipex(seeder, mockCoringRandomNonce, mockHelpingNowIso8601, mockHelpingN anc = sidHab.makeOwnEvent(sn=2) grant0, grant0atc = protocoling.ipexGrantExn(sidHab, message="Here's a credential", recp=sidHab.pre, acdc=msg, iss=iss.raw, anc=anc) - assert grant0.raw == (b'{"v":"KERI10JSON000531_","t":"exn","d":"EC-EsfvXD2cNw4GNgCFp9UTl7_DgWUgk9Rnw' - b'eCxocaG-","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","p":"","dt":"20' - b'21-06-27T21:26:21.233257+00:00","r":"/ipex/grant","q":{},"a":{"m":"Here\'' - b's a credential","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl"},"e":{"ac' - b'dc":{"v":"ACDC10JSON000197_","d":"EElymNmgs1u0mSaoCeOtSsNOROLuqOz103V3-4E-Cl' - b'XH","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","ri":"EB-u4VAF7A7_GR8' - b'PXJoAVHv5X9vjtXew8Yo6Z3w9mQUQ","s":"EMQWEcCnVRk1hatTNyK3sIykYSrrFvafX3bHQ9Gk' - b'k1kC","a":{"d":"EO9_6NattzsFiO8Fw1cxjYmDjOsKKSbootn-wXn9S3iB","dt":"2021-06-' - b'27T21:26:21.233257+00:00","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl"' - b',"LEI":"254900OPPU84GM83MG36"}},"iss":{"v":"KERI10JSON0000ed_","t":"iss","d"' - b':"ECUw7AdWEE3fvr7dgbFDXj0CEZuJTTa_H8-iLLAmIUPO","i":"EElymNmgs1u0mSaoCeOtSsN' - b'OROLuqOz103V3-4E-ClXH","s":"0","ri":"EB-u4VAF7A7_GR8PXJoAVHv5X9vjtXew8Yo6Z3w' - b'9mQUQ","dt":"2021-06-27T21:26:21.233257+00:00"},"anc":{"v":"KERI10JSON00013a' - b'_","t":"ixn","d":"EGhSHKIV5-nkeirdkqzqsvmeF1FXw_yH8NvPSAY1Rgyd","i":"EMl4Rhu' - b'R_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","s":"2","p":"ED1kkh5_ECYriK-j2gSv6Zjr' - b'5way88XVhwRCxk5zoTRG","a":[{"i":"EElymNmgs1u0mSaoCeOtSsNOROLuqOz103V3-4E-ClX' - b'H","s":"0","d":"ECUw7AdWEE3fvr7dgbFDXj0CEZuJTTa_H8-iLLAmIUPO"}]},"d":"EJ4-dl' - b'S9ktlb9HDWPYc0IJ2hS2NbvnCQBhUsFSkEPwIo"}}') + assert grant0.raw == (b'{"v":"KERI10JSON000539_","t":"exn","d":"ELnjKvzdgO57JZwG3giIScoOeTB0rLuevniv' + b'zRE5DbTE","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","rp":"","p":"",' + b'"dt":"2021-06-27T21:26:21.233257+00:00","r":"/ipex/grant","q":{},"a":{"m":"H' + b'ere\'s a credential","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl"},' + b'"e":{"acdc":{"v":"ACDC10JSON000197_","d":"EElymNmgs1u0mSaoCeOtSsNOROLuqOz103' + b'V3-4E-ClXH","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","ri":"EB-u4VA' + b'F7A7_GR8PXJoAVHv5X9vjtXew8Yo6Z3w9mQUQ","s":"EMQWEcCnVRk1hatTNyK3sIykYSrrFvaf' + b'X3bHQ9Gkk1kC","a":{"d":"EO9_6NattzsFiO8Fw1cxjYmDjOsKKSbootn-wXn9S3iB","dt":"' + b'2021-06-27T21:26:21.233257+00:00","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8A' + b'N-tiUbl","LEI":"254900OPPU84GM83MG36"}},"iss":{"v":"KERI10JSON0000ed_","t":"' + b'iss","d":"ECUw7AdWEE3fvr7dgbFDXj0CEZuJTTa_H8-iLLAmIUPO","i":"EElymNmgs1u0mSa' + b'oCeOtSsNOROLuqOz103V3-4E-ClXH","s":"0","ri":"EB-u4VAF7A7_GR8PXJoAVHv5X9vjtXe' + b'w8Yo6Z3w9mQUQ","dt":"2021-06-27T21:26:21.233257+00:00"},"anc":{"v":"KERI10JS' + b'ON00013a_","t":"ixn","d":"EGhSHKIV5-nkeirdkqzqsvmeF1FXw_yH8NvPSAY1Rgyd","i":' + b'"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","s":"2","p":"ED1kkh5_ECYriK-j' + b'2gSv6Zjr5way88XVhwRCxk5zoTRG","a":[{"i":"EElymNmgs1u0mSaoCeOtSsNOROLuqOz103V' + b'3-4E-ClXH","s":"0","d":"ECUw7AdWEE3fvr7dgbFDXj0CEZuJTTa_H8-iLLAmIUPO"}]},"d"' + b':"EJ4-dlS9ktlb9HDWPYc0IJ2hS2NbvnCQBhUsFSkEPwIo"}}') assert ipexhan.verify(serder=grant0) is True @@ -245,10 +246,10 @@ def test_ipex(seeder, mockCoringRandomNonce, mockHelpingNowIso8601, mockHelpingN # Let's see if we can spurn a message we previously accepted. spurn1, spurn1atc = protocoling.ipexSpurnExn(sidHab, "I reject you", spurned=grant0) - assert spurn1.raw == (b'{"v":"KERI10JSON00011d_","t":"exn","d":"EJA0LVnMxOdrOEArWudVtdonorCUa4nCIRgX' - b'vibhxdp3","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","p":"EC-EsfvXD2' - b'cNw4GNgCFp9UTl7_DgWUgk9RnweCxocaG-","dt":"2021-06-27T21:26:21.233257+00:00",' - b'"r":"/ipex/spurn","q":{},"a":{"m":"I reject you"},"e":{}}') + assert spurn1.raw == (b'{"v":"KERI10JSON000125_","t":"exn","d":"ELHFilyCgYvVq6vczgPQc7ZuRMs7Cv10U_h-' + b'2LIvJ1-Z","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","rp":"","p":"EL' + b'njKvzdgO57JZwG3giIScoOeTB0rLuevnivzRE5DbTE","dt":"2021-06-27T21:26:21.233257' + b'+00:00","r":"/ipex/spurn","q":{},"a":{"m":"I reject you"},"e":{}}') smsg = bytearray(spurn1.raw) smsg.extend(spurn1atc) parsing.Parser().parse(ims=smsg, exc=sidExc) @@ -258,25 +259,25 @@ def test_ipex(seeder, mockCoringRandomNonce, mockHelpingNowIso8601, mockHelpingN # Now we'll run a grant pointing back to the agree all the way to the database grant1, grant1atc = protocoling.ipexGrantExn(sidHab, message="Here's a credential", acdc=msg, iss=iss.raw, recp=sidHab.pre, anc=anc, agree=agree) - assert grant1.raw == (b'{"v":"KERI10JSON00055d_","t":"exn","d":"EBAhSTTx3--xDZZRoCIemBzxybFV_FoicvPf' - b'4hSfeyAJ","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","p":"EEtu1OAPj0' - b'3IdbhMwsQtgbJJaWgG2tdYLJ_3BuJQekdP","dt":"2021-06-27T21:26:21.233257+00:00",' - b'"r":"/ipex/grant","q":{},"a":{"m":"Here\'s a credential","i":"EMl4RhuR_Jx' - b'piMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl"},"e":{"acdc":{"v":"ACDC10JSON000197_","d"' - b':"EElymNmgs1u0mSaoCeOtSsNOROLuqOz103V3-4E-ClXH","i":"EMl4RhuR_JxpiMd1N8DEJEh' - b'TxM3Ovvn9Xya8AN-tiUbl","ri":"EB-u4VAF7A7_GR8PXJoAVHv5X9vjtXew8Yo6Z3w9mQUQ","' - b's":"EMQWEcCnVRk1hatTNyK3sIykYSrrFvafX3bHQ9Gkk1kC","a":{"d":"EO9_6NattzsFiO8F' - b'w1cxjYmDjOsKKSbootn-wXn9S3iB","dt":"2021-06-27T21:26:21.233257+00:00","i":"E' - b'Ml4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","LEI":"254900OPPU84GM83MG36"}},' - b'"iss":{"v":"KERI10JSON0000ed_","t":"iss","d":"ECUw7AdWEE3fvr7dgbFDXj0CEZuJTT' - b'a_H8-iLLAmIUPO","i":"EElymNmgs1u0mSaoCeOtSsNOROLuqOz103V3-4E-ClXH","s":"0","' - b'ri":"EB-u4VAF7A7_GR8PXJoAVHv5X9vjtXew8Yo6Z3w9mQUQ","dt":"2021-06-27T21:26:21' - b'.233257+00:00"},"anc":{"v":"KERI10JSON00013a_","t":"ixn","d":"EGhSHKIV5-nkei' - b'rdkqzqsvmeF1FXw_yH8NvPSAY1Rgyd","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-' - b'tiUbl","s":"2","p":"ED1kkh5_ECYriK-j2gSv6Zjr5way88XVhwRCxk5zoTRG","a":[{"i":' - b'"EElymNmgs1u0mSaoCeOtSsNOROLuqOz103V3-4E-ClXH","s":"0","d":"ECUw7AdWEE3fvr7d' - b'gbFDXj0CEZuJTTa_H8-iLLAmIUPO"}]},"d":"EJ4-dlS9ktlb9HDWPYc0IJ2hS2NbvnCQBhUsFS' - b'kEPwIo"}}') + assert grant1.raw == (b'{"v":"KERI10JSON000565_","t":"exn","d":"EHAY_L6Ig4k_5qIw6uH-QZwBswWLfwVzCqaG' + b'sjtdnubK","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","rp":"","p":"EC' + b'U3UjnSY1_6Wl3aYEW19jaGiKuyFh_chIQQw48bcT_X","dt":"2021-06-27T21:26:21.233257' + b'+00:00","r":"/ipex/grant","q":{},"a":{"m":"Here\'s a credential","i":"EMl' + b'4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl"},"e":{"acdc":{"v":"ACDC10JSON0001' + b'97_","d":"EElymNmgs1u0mSaoCeOtSsNOROLuqOz103V3-4E-ClXH","i":"EMl4RhuR_JxpiMd' + b'1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","ri":"EB-u4VAF7A7_GR8PXJoAVHv5X9vjtXew8Yo6Z3w' + b'9mQUQ","s":"EMQWEcCnVRk1hatTNyK3sIykYSrrFvafX3bHQ9Gkk1kC","a":{"d":"EO9_6Nat' + b'tzsFiO8Fw1cxjYmDjOsKKSbootn-wXn9S3iB","dt":"2021-06-27T21:26:21.233257+00:00' + b'","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","LEI":"254900OPPU84GM83' + b'MG36"}},"iss":{"v":"KERI10JSON0000ed_","t":"iss","d":"ECUw7AdWEE3fvr7dgbFDXj' + b'0CEZuJTTa_H8-iLLAmIUPO","i":"EElymNmgs1u0mSaoCeOtSsNOROLuqOz103V3-4E-ClXH","' + b's":"0","ri":"EB-u4VAF7A7_GR8PXJoAVHv5X9vjtXew8Yo6Z3w9mQUQ","dt":"2021-06-27T' + b'21:26:21.233257+00:00"},"anc":{"v":"KERI10JSON00013a_","t":"ixn","d":"EGhSHK' + b'IV5-nkeirdkqzqsvmeF1FXw_yH8NvPSAY1Rgyd","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn' + b'9Xya8AN-tiUbl","s":"2","p":"ED1kkh5_ECYriK-j2gSv6Zjr5way88XVhwRCxk5zoTRG","a' + b'":[{"i":"EElymNmgs1u0mSaoCeOtSsNOROLuqOz103V3-4E-ClXH","s":"0","d":"ECUw7AdW' + b'EE3fvr7dgbFDXj0CEZuJTTa_H8-iLLAmIUPO"}]},"d":"EJ4-dlS9ktlb9HDWPYc0IJ2hS2Nbvn' + b'CQBhUsFSkEPwIo"}}') assert ipexhan.verify(serder=grant1) is True gmsg = bytearray(grant1.raw) @@ -287,10 +288,11 @@ def test_ipex(seeder, mockCoringRandomNonce, mockHelpingNowIso8601, mockHelpingN # And now the last... admit the granted credential to complete the full flow admit0, admit0atc = protocoling.ipexAdmitExn(sidHab, "Thanks for the credential", grant=grant1) - assert admit0.raw == (b'{"v":"KERI10JSON00012a_","t":"exn","d":"EDkQZpUOKKOzsQ50yoZxzLz8tDaChAid_llr' - b'QNvKVAdO","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","p":"EBAhSTTx3-' - b'-xDZZRoCIemBzxybFV_FoicvPf4hSfeyAJ","dt":"2021-06-27T21:26:21.233257+00:00",' - b'"r":"/ipex/admit","q":{},"a":{"m":"Thanks for the credential"},"e":{}}') + assert admit0.raw == (b'{"v":"KERI10JSON000132_","t":"exn","d":"EMxU5rfeqKnZzrbqnL7weXQGaC8Zum4qowj2' + b'eiL6GxqL","i":"EMl4RhuR_JxpiMd1N8DEJEhTxM3Ovvn9Xya8AN-tiUbl","rp":"","p":"EH' + b'AY_L6Ig4k_5qIw6uH-QZwBswWLfwVzCqaGsjtdnubK","dt":"2021-06-27T21:26:21.233257' + b'+00:00","r":"/ipex/admit","q":{},"a":{"m":"Thanks for the credential"},"e":{' + b'}}') assert ipexhan.verify(serder=admit0) is True amsg = bytearray(admit0.raw) From 4786293c24c3cbfab6f8d106a1cc389792e6ebd9 Mon Sep 17 00:00:00 2001 From: pfeairheller Date: Mon, 10 Jun 2024 14:30:10 -0700 Subject: [PATCH 3/5] Resolving merge conflicts Signed-off-by: pfeairheller --- src/keri/app/agenting.py | 3 +- src/keri/app/cli/commands/delegate/confirm.py | 28 +++++++++++++++++-- src/keri/app/cli/commands/mailbox/add.py | 2 +- src/keri/app/cli/commands/rotate.py | 17 +++++++++-- .../app/cli/commands/witness/authenticate.py | 16 +++++++---- src/keri/app/delegating.py | 6 ++-- src/keri/app/httping.py | 3 ++ src/keri/core/coring.py | 4 +-- src/keri/core/parsing.py | 6 ++-- src/keri/db/basing.py | 2 +- src/keri/peer/exchanging.py | 23 +++++++++------ 11 files changed, 80 insertions(+), 30 deletions(-) diff --git a/src/keri/app/agenting.py b/src/keri/app/agenting.py index 2fd13cf49..cdc01c529 100644 --- a/src/keri/app/agenting.py +++ b/src/keri/app/agenting.py @@ -227,8 +227,9 @@ def witDo(self, tymth=None, tock=0.0): msg = self.msgs.popleft() pre = msg["pre"] sn = msg["sn"] if "sn" in msg else None + auths = msg["auths"] if "auths" in msg else None - yield from self.receipt(pre, sn) + yield from self.receipt(pre, sn, auths) self.cues.push(msg) yield self.tock diff --git a/src/keri/app/cli/commands/delegate/confirm.py b/src/keri/app/cli/commands/delegate/confirm.py index 374f017ac..a0ddb7525 100644 --- a/src/keri/app/cli/commands/delegate/confirm.py +++ b/src/keri/app/cli/commands/delegate/confirm.py @@ -16,6 +16,7 @@ from keri import core from keri.core import coring, serdering from keri.db import dbing +from keri.help import helping from keri.peer import exchanging logger = help.ogler.getLogger() @@ -32,6 +33,10 @@ parser.add_argument("--interact", "-i", help="anchor the delegation approval in an interaction event. " "Default is to use a rotation event.", action="store_true") parser.add_argument("--auto", "-Y", help="auto approve any delegation request non-interactively", 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=': formatted witness auth codes. Can appear multiple times', + default=[], action="append", required=False) def confirm(args): @@ -47,15 +52,18 @@ def confirm(args): alias = args.alias interact = args.interact auto = args.auto + authenticate = args.authenticate + codes = args.code - confirmDoer = ConfirmDoer(name=name, base=base, alias=alias, bran=bran, interact=interact, auto=auto) + confirmDoer = ConfirmDoer(name=name, base=base, alias=alias, bran=bran, interact=interact, auto=auto, + authenticate=authenticate, codes=codes) doers = [confirmDoer] return doers class ConfirmDoer(doing.DoDoer): - def __init__(self, name, base, alias, bran, interact=False, auto=False): + def __init__(self, name, base, alias, bran, interact=False, auto=False, authenticate=False, codes=None): hby = existing.setupHby(name=name, base=base, bran=bran) self.hbyDoer = habbing.HaberyDoer(habery=hby) # setup doer self.witq = agenting.WitnessInquisitor(hby=hby) @@ -63,6 +71,8 @@ def __init__(self, name, base, alias, bran, interact=False, auto=False): self.counselor = grouping.Counselor(hby=hby) self.notifier = notifying.Notifier(hby=hby) self.mux = grouping.Multiplexor(hby=hby, notifier=self.notifier) + self.authenticate = authenticate + self.codes = codes if codes is not None else [] exc = exchanging.Exchanger(hby=hby, handlers=[]) delegating.loadHandlers(hby=hby, exc=exc, notifier=self.notifier) @@ -173,7 +183,19 @@ def confirmDo(self, tymth, tock=0.0): else: hab.rotate(data=[anchor]) - witDoer = agenting.WitnessReceiptor(hby=self.hby) + auths = {} + if self.authenticate: + for arg in self.codes: + (wit, code) = arg.split(":") + auths[wit] = f"{code}#{helping.nowIso8601()}" + + for wit in hab.kever.wits: + if wit in auths: + continue + code = input(f"Entire code for {wit}: ") + auths[wit] = f"{code}#{helping.nowIso8601()}" + + witDoer = agenting.WitnessReceiptor(hby=self.hby, auths=auths) self.extend(doers=[witDoer]) self.toRemove.append(witDoer) yield self.tock diff --git a/src/keri/app/cli/commands/mailbox/add.py b/src/keri/app/cli/commands/mailbox/add.py index 73297b8f9..9433f612a 100644 --- a/src/keri/app/cli/commands/mailbox/add.py +++ b/src/keri/app/cli/commands/mailbox/add.py @@ -120,7 +120,7 @@ def addDo(self, tymth, tock=0.0): rep = client.respond() if rep.status == 200: - print("I can't believe it worked!") + print(f"Mailbox {self.mailbox} added for {self.hab.name}") else: print(rep.status, rep.data) diff --git a/src/keri/app/cli/commands/rotate.py b/src/keri/app/cli/commands/rotate.py index 530288b94..6adbac029 100644 --- a/src/keri/app/cli/commands/rotate.py +++ b/src/keri/app/cli/commands/rotate.py @@ -29,6 +29,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=': formatted witness auth codes. Can appear multiple times', + default=[], action="append", required=False) + parser.add_argument("--proxy", help="alias for delegation communication proxy", default="") rotating.addRotationArgs(parser) @@ -63,7 +66,7 @@ def rotate(args): cuts=opts.witsCut, adds=opts.witsAdd, isith=opts.isith, nsith=opts.nsith, count=opts.ncount, toad=opts.toad, - data=opts.data, proxy=args.proxy, authenticate=args.authenticate) + data=opts.data, proxy=args.proxy, authenticate=args.authenticate, codes=args.code) doers = [rotDoer] @@ -118,7 +121,8 @@ class RotateDoer(doing.DoDoer): """ def __init__(self, name, base, bran, alias, endpoint=False, isith=None, nsith=None, count=None, - toad=None, wits=None, cuts=None, adds=None, data: list = None, proxy=None, authenticate=False): + toad=None, wits=None, cuts=None, adds=None, data: list = None, proxy=None, authenticate=False, + codes=None): """ Returns DoDoer with all registered Doers needed to perform rotation. @@ -144,6 +148,7 @@ def __init__(self, name, base, bran, alias, endpoint=False, isith=None, nsith=No self.endpoint = endpoint self.proxy = proxy self.authenticate = authenticate + self.codes = codes if codes is not None else [] self.wits = wits if wits is not None else [] self.cuts = cuts if cuts is not None else [] @@ -193,12 +198,18 @@ def rotateDo(self, tymth, tock=0.0): auths = {} if self.authenticate: + for arg in self.codes: + (wit, code) = arg.split(":") + auths[wit] = f"{code}#{helping.nowIso8601()}" + for wit in hab.kever.wits: + if wit in auths: + continue code = input(f"Entire code for {wit}: ") auths[wit] = f"{code}#{helping.nowIso8601()}" if hab.kever.delpre: - self.swain.delegation(pre=hab.pre, sn=hab.kever.sn) + self.swain.delegation(pre=hab.pre, sn=hab.kever.sn, auths=auths) 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/witness/authenticate.py b/src/keri/app/cli/commands/witness/authenticate.py index dc33c5de2..c9d3b8762 100644 --- a/src/keri/app/cli/commands/witness/authenticate.py +++ b/src/keri/app/cli/commands/witness/authenticate.py @@ -31,6 +31,8 @@ parser.add_argument('--passcode', '-p', help='22 character encryption passcode for keystore (is not saved)', dest="bran", default=None) # passcode => bran parser.add_argument("--witness", '-w', help="the witness AID or alias to authenticate against", required=True) +parser.add_argument("--url-only", '-u', dest="url", help="display only the URL (no QR Code).", required=False, + action="store_true") def auth(args): @@ -45,16 +47,18 @@ def auth(args): alias=args.alias, base=args.base, bran=args.bran, - witness=args.witness) + witness=args.witness, + urlOnly=args.url) return [ed] class AuthDoer(doing.DoDoer): - def __init__(self, name, alias, base, bran, witness): + def __init__(self, name, alias, base, bran, witness, urlOnly): self.hby = existing.setupHby(name=name, base=base, bran=bran) self.hab = self.hby.habByName(alias) self.org = connecting.Organizer(hby=self.hby) + self.urlOnly = urlOnly if witness in self.hby.kevers: wit = witness @@ -119,10 +123,12 @@ def authDo(self, tymth, tock=0.0): d = coring.Matter(qb64=self.hab.decrypt(m.raw)) otpurl = f"otpauth://totp/KERIpy:{self.witness}?secret={d.raw.decode('utf-8')}&issuer=KERIpy" - qr = qrcode.QRCode() - qr.add_data(otpurl) + if not self.urlOnly: + qr = qrcode.QRCode() + qr.add_data(otpurl) + + qr.print_ascii() - qr.print_ascii() print(otpurl) else: diff --git a/src/keri/app/delegating.py b/src/keri/app/delegating.py index fcbdb053b..43b364093 100644 --- a/src/keri/app/delegating.py +++ b/src/keri/app/delegating.py @@ -28,7 +28,7 @@ class Anchorer(doing.DoDoer): """ - def __init__(self, hby, proxy=None, **kwa): + def __init__(self, hby, proxy=None, auths=None, **kwa): """ For the current event, gather the current set of witnesses, send the event, gather all receipts and send them to all other witnesses @@ -45,11 +45,12 @@ def __init__(self, hby, proxy=None, **kwa): self.witq = agenting.WitnessInquisitor(hby=hby) self.witDoer = agenting.Receiptor(hby=self.hby) self.proxy = proxy + self.auths = auths super(Anchorer, self).__init__(doers=[self.witq, self.witDoer, self.postman, doing.doify(self.escrowDo)], **kwa) - def delegation(self, pre, sn=None, proxy=None): + def delegation(self, pre, sn=None, proxy=None, auths=None): if pre not in self.hby.habs: raise kering.ValidationError(f"{pre} is not a valid local AID for delegation") @@ -63,6 +64,7 @@ def delegation(self, pre, sn=None, proxy=None): raise kering.ValidationError(f"delegator {delpre} not found, unable to process delegation") sn = sn if sn is not None else hab.kever.sner.num + self.auths = auths if auths is not None else self.auths # load the event and signatures evt = hab.makeOwnEvent(sn=sn) diff --git a/src/keri/app/httping.py b/src/keri/app/httping.py index d3ac5e8ac..346b870e0 100644 --- a/src/keri/app/httping.py +++ b/src/keri/app/httping.py @@ -233,6 +233,9 @@ def request(self, method, url, body=None, headers=None): print(f"error establishing client connection={e}") return None + if hasattr(body, "encode"): + body = body.encode("utf-8") + client.request( method=method, path=f"{purl.path}?{purl.query}", diff --git a/src/keri/core/coring.py b/src/keri/core/coring.py index 17b134334..fc2f51009 100644 --- a/src/keri/core/coring.py +++ b/src/keri/core/coring.py @@ -989,8 +989,8 @@ def __init__(self, raw=None, code=MtrDex.Ed25519N, soft='', rize=None, code = f"{s}{code[1:hs]}" ss = 4 else: - raise InvalidVarRawSizeError(f"Unsupported raw size for " - f"{code=}.") + raise InvalidVarRawSizeError(f"Unsupported raw size for large " + f"{code=}. {size} <= {64 ** 4 - 1}") else: raise InvalidVarRawSizeError(f"Unsupported variable raw size " f"{code=}.") diff --git a/src/keri/core/parsing.py b/src/keri/core/parsing.py index 2a54c5204..4faa7f36a 100644 --- a/src/keri/core/parsing.py +++ b/src/keri/core/parsing.py @@ -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.error("Parser msg non-extraction error: %s", ex) + logger.exception("Parser msg non-extraction error: %s", ex) yield return True @@ -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.args[0]) else: - logger.error("Kevery msg non-extraction error: %s", ex.args[0]) + logger.exception("Kevery msg non-extraction error: %s", ex.args[0]) finally: done = True @@ -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.error("Parser msg non-extraction error: %s", ex.args[0]) + logger.exception("Parser msg non-extraction error: %s", ex.args[0]) yield return True # should never return diff --git a/src/keri/db/basing.py b/src/keri/db/basing.py index cec20d4ea..d911eeff2 100644 --- a/src/keri/db/basing.py +++ b/src/keri/db/basing.py @@ -1063,7 +1063,7 @@ def reopen(self, **kwa): # TODO: clean self.epath = subing.IoSetSuber(db=self, subkey=".epath") - self.essrs = subing.CesrSuber(db=self, subkey=".essrs", klass=coring.Texter) + self.essrs = subing.CesrIoSetSuber(db=self, subkey=".essrs", klass=coring.Texter) # accepted signed 12-word challenge response exn messages keys by prefix of signer # TODO: clean diff --git a/src/keri/peer/exchanging.py b/src/keri/peer/exchanging.py index 7519cba4c..ea96b7d41 100644 --- a/src/keri/peer/exchanging.py +++ b/src/keri/peer/exchanging.py @@ -122,20 +122,19 @@ def processEvent(self, serder, tsgs=None, cigars=None, **kwargs): attachments.append((np, pattach)) kwargs["attachments"] = attachments + if essrs: + kwargs["essr"] = b''.join([texter.raw for texter in essrs]) if isinstance(serder.seals, str): - if len(essrs) != 1: - raise ValidationError("one and only one essr attachment allowed") + if 'essr' not in kwargs: + raise ValidationError("at least one essr attachment is required") - texter = essrs[0] + essr = kwargs['essr'] dig = serder.seals diger = coring.Diger(qb64=dig) - if not diger.verify(ser=texter.qb64b): + if not diger.verify(ser=essr): raise ValidationError(f"essr diger={diger.qb64} is invalid against content") - if essrs: - kwargs["essrs"] = essrs - # Perform behavior specific verification, think IPEX chaining requirements try: if not behavior.verify(serder=serder, **kwargs): @@ -205,9 +204,13 @@ def processEscrowPartialSigned(self): tsgs.append((prefixer, seqner, saider, sigers)) pathed = [bytearray(p.encode("utf-8")) for p in self.hby.db.epath.get(keys=(dig,))] + essrs = [texter for texter in self.hby.db.essrs.get(keys=(dig,))] try: - self.processEvent(serder=serder, tsgs=tsgs, pathed=pathed) + kwargs = dict() + if essrs: + kwargs["essrs"] = essrs + self.processEvent(serder=serder, tsgs=tsgs, pathed=pathed, **kwargs) except MissingSignatureError as ex: if logger.isEnabledFor(logging.DEBUG): @@ -246,7 +249,7 @@ def logEvent(self, serder, pathed=None, tsgs=None, cigars=None, essrs=None): saider = coring.Saider(qb64=serder.said) self.hby.db.epath.pin(keys=(dig,), vals=[bytes(p) for p in pathed]) for texter in essrs: - self.hby.db.essrs.pin(keys=(serder.seals,), val=texter) + self.hby.db.essrs.add(keys=(dig,), val=texter) if pdig: self.hby.db.erpy.pin(keys=(pdig,), val=saider) @@ -371,6 +374,8 @@ def exchange(route, else: attrs = diger.qb64 + # Attr field 'a' can be either a said or a nested block and the fields + # of the nested block can be saids of further nested block or nested blocks ked = dict(v=vs, t=ilk, d="", From 33c28c51702e51ddd90ed676a8aa7bf89aea5856 Mon Sep 17 00:00:00 2001 From: pfeairheller Date: Wed, 12 Jun 2024 14:08:48 -0700 Subject: [PATCH 4/5] Improvements to kli commands `mailbox add` and `witness authenticate` to work in all cases (like delegated AIDs). New `kli aid` command for printing the AID of an alias (useful in scripts). Added `--delpre` as a command line argument to `kli icncept` (useful in scripts). Fix for witness publisher to account for multiple events in one cue'ed message. Added support for witness auth codes for delegated AIDs. Removed logging messages in the INFO case for escrow reprocessing. Signed-off-by: pfeairheller --- src/keri/app/agenting.py | 10 ++-- src/keri/app/cli/commands/aid.py | 58 +++++++++++++++++++ src/keri/app/cli/commands/incept.py | 2 + src/keri/app/cli/commands/mailbox/add.py | 13 ++++- src/keri/app/cli/commands/status.py | 2 +- .../app/cli/commands/witness/authenticate.py | 14 ++++- src/keri/app/cli/common/incepting.py | 2 + src/keri/app/delegating.py | 2 +- src/keri/core/eventing.py | 18 ------ 9 files changed, 89 insertions(+), 32 deletions(-) create mode 100644 src/keri/app/cli/commands/aid.py diff --git a/src/keri/app/agenting.py b/src/keri/app/agenting.py index cdc01c529..ad164a9b3 100644 --- a/src/keri/app/agenting.py +++ b/src/keri/app/agenting.py @@ -617,12 +617,10 @@ def sendDo(self, tymth=None, tock=0.0, **opts): _ = (yield self.tock) - total = len(witers) - count = 0 - while count < total: - for witer in witers: - count += len(witer.sent) - _ = (yield self.tock) + while witers: + witer = witers.pop() + while not witer.idle: + _ = (yield self.tock) self.remove(witers) self.cues.push(evt) diff --git a/src/keri/app/cli/commands/aid.py b/src/keri/app/cli/commands/aid.py new file mode 100644 index 000000000..856f65dda --- /dev/null +++ b/src/keri/app/cli/commands/aid.py @@ -0,0 +1,58 @@ +# -*- encoding: utf-8 -*- +""" +KERI +keri.kli.commands module + +""" +import argparse + +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 the AID for a given alias') +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 + + +def handler(args): + kwa = dict(args=args) + return [doing.doify(status, **kwa)] + + +def status(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 alias for an identifier") + + print(hab.pre) + + except ConfigurationError as e: + print(f"identifier prefix for {name} does not exist, incept must be run first", ) + return -1 diff --git a/src/keri/app/cli/commands/incept.py b/src/keri/app/cli/commands/incept.py index 3576f797b..4af084c73 100644 --- a/src/keri/app/cli/commands/incept.py +++ b/src/keri/app/cli/commands/incept.py @@ -117,6 +117,8 @@ def mergeArgsWithFile(args): incept_opts.estOnly = args.est_only if args.data is not None: incept_opts.data = config.parseData(args.data) + if args.delpre is not None: + incept_opts.delpre = args.delpre return incept_opts diff --git a/src/keri/app/cli/commands/mailbox/add.py b/src/keri/app/cli/commands/mailbox/add.py index 9433f612a..67abf1990 100644 --- a/src/keri/app/cli/commands/mailbox/add.py +++ b/src/keri/app/cli/commands/mailbox/add.py @@ -12,7 +12,7 @@ from keri import kering from keri.app import connecting, habbing, forwarding -from keri.app.agenting import httpClient +from keri.app.agenting import httpClient, WitnessPublisher from keri.app.cli.common import existing from keri.core import serdering @@ -53,6 +53,7 @@ def __init__(self, name, alias, base, bran, mailbox): self.hby = existing.setupHby(name=name, base=base, bran=bran) self.hab = self.hby.habByName(alias) self.org = connecting.Organizer(hby=self.hby) + self.witpub = WitnessPublisher(hby=self.hby) if mailbox in self.hby.kevers: mbx = mailbox @@ -67,7 +68,7 @@ def __init__(self, name, alias, base, bran, mailbox): self.mailbox = mbx - doers = [doing.doify(self.addDo)] + doers = [doing.doify(self.addDo), self.witpub] super(AddDoer, self).__init__(doers=doers) @@ -120,9 +121,15 @@ def addDo(self, tymth, tock=0.0): rep = client.respond() if rep.status == 200: + msg = self.hab.replyEndRole(cid=self.hab.pre, role=kering.Roles.mailbox) + self.witpub.msgs.append(dict(pre=self.hab.pre, msg=bytes(msg))) + + while not self.witpub.cues: + yield self.tock + print(f"Mailbox {self.mailbox} added for {self.hab.name}") else: print(rep.status, rep.data) - self.remove([clientDoer]) + self.remove([clientDoer, self.witpub]) diff --git a/src/keri/app/cli/commands/status.py b/src/keri/app/cli/commands/status.py index 662a6b625..96f531828 100644 --- a/src/keri/app/cli/commands/status.py +++ b/src/keri/app/cli/commands/status.py @@ -10,7 +10,7 @@ from hio.base import doing from keri.app.cli.common import displaying, existing -from keri.core import coring, serdering +from keri.core import serdering from keri.kering import ConfigurationError logger = help.ogler.getLogger() diff --git a/src/keri/app/cli/commands/witness/authenticate.py b/src/keri/app/cli/commands/witness/authenticate.py index c9d3b8762..1758093ce 100644 --- a/src/keri/app/cli/commands/witness/authenticate.py +++ b/src/keri/app/cli/commands/witness/authenticate.py @@ -97,9 +97,17 @@ def authDo(self, tymth, tock=0.0): for msg in self.hab.db.clonePreIter(pre=self.hab.pre): body.extend(msg) + fargs = dict([("kel", body.decode("utf-8"))]) + + if self.hab.kever.delegated: + delkel = bytearray() + for msg in self.hab.db.clonePreIter(self.hab.kever.delpre): + delkel.extend(msg) + + fargs['delkel'] = delkel.decode("utf-8") + headers = (Hict([ - ("Content-Type", "application/cesr"), - ("Content-Length", len(body)), + ("Content-Type", "multipart/form-data") ])) client, clientDoer = httpClient(self.hab, self.witness) @@ -109,7 +117,7 @@ def authDo(self, tymth, tock=0.0): method="POST", path=f"{client.requester.path}/aids", headers=headers, - body=bytes(body) + fargs=fargs ) while not client.responses: yield self.tock diff --git a/src/keri/app/cli/common/incepting.py b/src/keri/app/cli/common/incepting.py index 6a0789c91..6fe211fa3 100644 --- a/src/keri/app/cli/common/incepting.py +++ b/src/keri/app/cli/common/incepting.py @@ -28,4 +28,6 @@ def addInceptingArgs(parser): help='only allow establishment events in KEL for this prefix') parser.add_argument('--data', '-d', default=None, required=False, action="store", help='Anchor data, \'@\' allowed',) + parser.add_argument('--delpre', '-di', default=None, required=False, action="store", + help='Delegator AID for delegated identfiers',) diff --git a/src/keri/app/delegating.py b/src/keri/app/delegating.py index 43b364093..8d9e4c194 100644 --- a/src/keri/app/delegating.py +++ b/src/keri/app/delegating.py @@ -71,7 +71,7 @@ def delegation(self, pre, sn=None, proxy=None, auths=None): # Send exn message for notification purposes srdr = serdering.SerderKERI(raw=evt) - self.witDoer.msgs.append(dict(pre=pre, sn=srdr.sn)) + self.witDoer.msgs.append(dict(pre=pre, sn=srdr.sn, auths=self.auths)) self.hby.db.dpwe.pin(keys=(srdr.pre, srdr.said), val=srdr) def complete(self, prefixer, seqner, saider=None): diff --git a/src/keri/core/eventing.py b/src/keri/core/eventing.py index 6b4e743f5..dd9cb2244 100644 --- a/src/keri/core/eventing.py +++ b/src/keri/core/eventing.py @@ -5065,8 +5065,6 @@ def processEscrowOutOfOrders(self): # still waiting on missing prior event to validate if logger.isEnabledFor(logging.DEBUG): logger.exception("Kevery unescrow failed: %s", ex.args[0]) - else: - logger.error("Kevery unescrow failed: %s", ex.args[0]) except Exception as ex: # log diagnostics errors etc # error other than out of order so remove from OO escrow @@ -5221,8 +5219,6 @@ def processEscrowPartialSigs(self): # still waiting on missing sigs or missing seal to validate if logger.isEnabledFor(logging.DEBUG): logger.exception("Kevery unescrow failed: %s", ex.args[0]) - else: - logger.error("Kevery unescrow failed: %s", ex.args[0]) except Exception as ex: # log diagnostics errors etc # error other than waiting on sigs or seal so remove from escrow @@ -5393,8 +5389,6 @@ def processEscrowPartialWigs(self): # still waiting on missing witness sigs if logger.isEnabledFor(logging.DEBUG): logger.exception("Kevery unescrow failed: %s", ex.args[0]) - else: - logger.error("Kevery unescrow failed: %s", ex.args[0]) except Exception as ex: # log diagnostics errors etc # error other than waiting on sigs or seal so remove from escrow @@ -5518,8 +5512,6 @@ def processEscrowUnverWitness(self): # only happens if we process above if logger.isEnabledFor(logging.DEBUG): # adds exception data logger.exception("Kevery unescrow failed: %s", ex.args[0]) - else: - logger.error("Kevery unescrow failed: %s", ex.args[0]) except Exception as ex: # log diagnostics errors etc # error other than out of order so remove from OO escrow @@ -5691,8 +5683,6 @@ def processEscrowUnverNonTrans(self): # only happens if we process above if logger.isEnabledFor(logging.DEBUG): # adds exception data logger.exception("Kevery unescrow failed: %s", ex.args[0]) - else: - logger.error("Kevery unescrow failed: %s", ex.args[0]) except Exception as ex: # log diagnostics errors etc # error other than out of order so remove from OO escrow @@ -5812,8 +5802,6 @@ def processEscrowDelegables(self): # still waiting on missing delegation approval if logger.isEnabledFor(logging.DEBUG): logger.exception("Kevery unescrow failed: %s", ex.args[0]) - else: - logger.error("Kevery unescrow failed: %s", ex.args[0]) except Exception as ex: # log diagnostics errors etc # error other than out of order so remove from OO escrow @@ -5930,8 +5918,6 @@ def processQueryNotFound(self): # still waiting on missing prior event to validate if logger.isEnabledFor(logging.DEBUG): logger.exception("Kevery unescrow failed: %s", ex.args[0]) - else: - logger.error("Kevery unescrow failed: %s", ex.args[0]) except Exception as ex: # log diagnostics errors etc # error other than out of order so remove from OO escrow @@ -6221,8 +6207,6 @@ def processEscrowUnverTrans(self): # only happens if we process above if logger.isEnabledFor(logging.DEBUG): # adds exception data logger.exception("Kevery unescrow failed: %s", ex.args[0]) - else: - logger.error("Kevery unescrow failed: %s", ex.args[0]) except Exception as ex: # log diagnostics errors etc # error other than out of order so remove from OO escrow @@ -6355,8 +6339,6 @@ def processEscrowDuplicitous(self): # still can't determine if duplicitous if logger.isEnabledFor(logging.DEBUG): logger.exception("Kevery unescrow failed: %s", ex.args[0]) - else: - logger.error("Kevery unescrow failed: %s", ex.args[0]) except Exception as ex: # log diagnostics errors etc # error other than likely duplicitous so remove from escrow From dea797965f03e492269afa29332496f8c5dd44b0 Mon Sep 17 00:00:00 2001 From: pfeairheller Date: Wed, 12 Jun 2024 17:48:00 -0700 Subject: [PATCH 5/5] Updated test Signed-off-by: pfeairheller --- tests/peer/test_exchanging.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/peer/test_exchanging.py b/tests/peer/test_exchanging.py index 512d4ac86..5e7e96949 100644 --- a/tests/peer/test_exchanging.py +++ b/tests/peer/test_exchanging.py @@ -62,10 +62,9 @@ def test_essrs(): rkever = recHab.kever pubkey = pysodium.crypto_sign_pk_to_box_pk(rkever.verfers[0].raw) raw = pysodium.crypto_box_seal(msg.encode("utf-8"), pubkey) - b64 = encodeB64(raw) - texter = coring.Texter(raw=b64) - diger = coring.Diger(ser=texter.qb64b, code=MtrDex.Blake3_256) + texter = coring.Texter(raw=raw) + diger = coring.Diger(ser=raw, code=MtrDex.Blake3_256) essr, _ = exchanging.exchange(route='/essr/req', sender=hab.pre, diger=diger, modifiers=dict(src=hab.pre, dest=recHab.pre)) ims = hab.endorse(serder=essr, pipelined=False) @@ -80,8 +79,8 @@ def test_essrs(): assert serder.ked['a'] == diger.qb64 # Pull the logged ESSR attachment and verify it is the one attached - texter = recHby.db.essrs.get(keys=(diger.qb64,)) - raw = recHab.decrypt(decodeB64(texter.raw)) + texter = recHby.db.essrs.get(keys=(serder.said,)) + raw = recHab.decrypt(texter[0].raw) assert raw.decode("utf-8") == msg # Test with invalid diger @@ -90,7 +89,7 @@ def test_essrs(): modifiers=dict(src=hab.pre, dest=recHab.pre)) ims = hab.endorse(serder=essr, pipelined=False) ims.extend(coring.Counter(code=CtrDex.ESSRPayloadGroup, count=1).qb64b) - ims.extend(texter.qb64b) + ims.extend(texter[0].qb64b) parsing.Parser().parse(ims=ims, kvy=recHby.kvy, exc=exc) assert recHby.db.exns.get(keys=(essr.said,)) is None