From 5227681d6ba42dcd3706f81d3aa382814967ae97 Mon Sep 17 00:00:00 2001 From: Philip Feairheller Date: Wed, 12 Jun 2024 19:40:38 -0700 Subject: [PATCH] Many additions and fixes to kli commands, new ESSR payload attachment support (#803) * New mailbox commands for using bespoke mailbox services. Signed-off-by: pfeairheller * Resolving merge conflicts Signed-off-by: pfeairheller * Resolving merge conflicts Signed-off-by: pfeairheller * 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 * Updated test Signed-off-by: pfeairheller --------- Signed-off-by: pfeairheller --- images/keripy.base.dockerfile | 15 ++ src/keri/app/agenting.py | 13 +- src/keri/app/cli/commands/aid.py | 58 +++++++ src/keri/app/cli/commands/delegate/confirm.py | 28 ++- src/keri/app/cli/commands/incept.py | 2 + src/keri/app/cli/commands/mailbox/add.py | 135 ++++++++++++++ src/keri/app/cli/commands/oobi/generate.py | 13 ++ src/keri/app/cli/commands/status.py | 2 +- .../app/cli/commands/witness/authenticate.py | 31 +++- src/keri/app/cli/common/incepting.py | 2 + src/keri/app/delegating.py | 8 +- src/keri/app/httping.py | 3 + src/keri/app/indirecting.py | 2 +- src/keri/core/coring.py | 8 +- src/keri/core/counting.py | 3 + src/keri/core/eventing.py | 18 -- src/keri/core/parsing.py | 41 +++-- src/keri/core/serdering.py | 4 +- src/keri/db/basing.py | 2 + src/keri/peer/exchanging.py | 67 +++++-- 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 | 164 ++++++++++++------ tests/vc/test_protocoling.py | 158 ++++++++--------- 28 files changed, 722 insertions(+), 257 deletions(-) create mode 100644 images/keripy.base.dockerfile create mode 100644 src/keri/app/cli/commands/aid.py 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/agenting.py b/src/keri/app/agenting.py index 2fd13cf49..ad164a9b3 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 @@ -616,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/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/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 new file mode 100644 index 000000000..67abf1990 --- /dev/null +++ b/src/keri/app/cli/commands/mailbox/add.py @@ -0,0 +1,135 @@ +# -*- 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, WitnessPublisher +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) + self.witpub = WitnessPublisher(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), self.witpub] + + 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: + 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.witpub]) 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/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 126fc0417..1758093ce 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() @@ -32,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): @@ -46,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 @@ -94,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) @@ -106,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 @@ -120,10 +131,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/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 fcbdb053b..8d9e4c194 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,13 +64,14 @@ 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) # 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/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/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/core/coring.py b/src/keri/core/coring.py index 5bea6584b..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=}.") @@ -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/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 diff --git a/src/keri/core/parsing.py b/src/keri/core/parsing.py index 9273f6255..4faa7f36a 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 @@ -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 @@ -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 1ceb53ce0..cf7fbd30d 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.CesrIoSetSuber(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 fcbefa8a8..ea96b7d41 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,23 @@ def processEvent(self, serder, tsgs=None, cigars=None, **kwargs): np = pather.strip(e) 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 'essr' not in kwargs: + raise ValidationError("at least one essr attachment is required") + + essr = kwargs['essr'] + dig = serder.seals + diger = coring.Diger(qb64=dig) + if not diger.verify(ser=essr): + raise ValidationError(f"essr diger={diger.qb64} is invalid against content") + # 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 @@ -129,13 +146,13 @@ 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 - self.logEvent(serder, pathed, tsgs, cigars) + # Always persist events + 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") @@ -187,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): @@ -210,12 +231,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 +248,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.add(keys=(dig,), val=texter) if pdig: self.hby.db.erpy.pin(keys=(pdig,), val=saider) @@ -278,8 +302,9 @@ def complete(self, said): def exchange(route, - payload, sender, + payload=None, + diger=None, recipient=None, date=None, dig=None, @@ -292,6 +317,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 +333,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 +349,38 @@ 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 + # 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="", 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..5e7e96949 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,51 @@ 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) + + 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) + 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=(serder.said,)) + raw = recHab.decrypt(texter[0].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[0].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 +151,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 +193,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 +224,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)