diff --git a/src/keri/app/querying.py b/src/keri/app/querying.py index b6a401ad..1c7cd2f1 100644 --- a/src/keri/app/querying.py +++ b/src/keri/app/querying.py @@ -7,6 +7,7 @@ from hio.base import doing from keri.app import agenting +from keri.vdr import viring class QueryDoer(doing.DoDoer): @@ -146,3 +147,121 @@ def recur(self, tyme, deeds=None): return True return super(AnchorQuerier, self).recur(tyme, deeds) + + +class TelStateNoticer(doing.DoDoer): + def __init__(self, hby, tvy, hab, pre, ri, i=None, **opts): + self.hby = hby + self.tvy = tvy + self.hab = hab + self.pre = pre + self.ri = ri + self.i = i + self.cues = tvy.cues + self.witq = agenting.WitnessInquisitor(hby=self.hby) + self.witq.telquery(hab=self.hab, pre=self.pre, r="tsn", ri=self.ri, i=self.i) + + super(TelStateNoticer, self).__init__(doers=[self.witq], **opts) + + def recur(self, tyme, deeds=None): + if self.cues: + cue = self.cues.pull() + match cue['kin']: + case "txnStateSaved": + record = cue['record'] + behind = False + + if isinstance(record, viring.RegStateRecord): + if record.i != self.ri: + self.cues.append(cue) # from a diff TelStateNoticer + return super(TelStateNoticer, self).recur(tyme, deeds) + + if record.i in self.tvy.tevers: + if self.tvy.tevers[self.ri].sn < int(record.s, 16): + behind = True + else: + behind = True + + if behind: + self.extend([RegistryLogQuerier(hby=self.hby, tvy=self.tvy, hab=self.hab, pre=self.pre, record=record)]) + elif isinstance(record, viring.VcStateRecord): + if record.ri != self.ri or not self.i or record.i != self.i: + self.cues.append(cue) # from a diff TelStateNoticer + return super(TelStateNoticer, self).recur(tyme, deeds) + + regsn = int(record.ra["s"], 16) if "s" in record.ra else 0 + if record.ri in self.tvy.tevers and regsn <= self.tvy.tevers[record.ri].sn: + tever = self.tvy.tevers[record.ri] + vcSn = tever.vcSn(record.i) + if vcSn is None or vcSn < int(record.s, 16): + behind = True + else: + behind = True + + if behind: + self.extend([VcLogQuerier(hby=self.hby, tvy=self.tvy, hab=self.hab, pre=self.pre, record=record)]) + + self.remove([self.witq]) + if not behind: + return True + case _: + self.cues.append(cue) + + return super(TelStateNoticer, self).recur(tyme, deeds) + + +class RegistryLogQuerier(doing.DoDoer): + + def __init__(self, hby, tvy, hab, pre, record, **opts): + self.hby = hby + self.tvy = tvy + self.hab = hab + self.pre = pre + self.record = record + self.witq = agenting.WitnessInquisitor(hby=self.hby) + self.witq.telquery(hab=self.hab, pre=self.pre, ri=record.i) + + super(RegistryLogQuerier, self).__init__(doers=[self.witq], **opts) + + def recur(self, tyme, deeds=None): + """ + Returns: doifiable Doist compatible generator method + Usage: + add result of doify on this method to doers list + """ + if self.record.i in self.tvy.tevers: + tever = self.tvy.tevers[self.record.i] + if int(tever.state().s, 16) >= int(self.record.s, 16): + self.remove([self.witq]) + return True + + return super(RegistryLogQuerier, self).recur(tyme, deeds) + + +class VcLogQuerier(doing.DoDoer): + + def __init__(self, hby, tvy, hab, pre, record, **opts): + self.hby = hby + self.tvy = tvy + self.hab = hab + self.pre = pre + self.record = record + self.witq = agenting.WitnessInquisitor(hby=self.hby) + self.witq.telquery(hab=self.hab, pre=self.pre, ri=record.ri, i=record.i) + + super(VcLogQuerier, self).__init__(doers=[self.witq], **opts) + + def recur(self, tyme, deeds=None): + """ + Returns: doifiable Doist compatible generator method + Usage: + add result of doify on this method to doers list + """ + if self.record.ri in self.tvy.tevers: + tever = self.tvy.tevers[self.record.ri] + vcSn = tever.vcSn(self.record.i) + if vcSn is not None and vcSn >= int(self.record.s, 16): + self.remove([self.witq]) + return True + + return super(VcLogQuerier, self).recur(tyme, deeds) diff --git a/src/keri/app/storing.py b/src/keri/app/storing.py index 80cf0f2f..1906de00 100644 --- a/src/keri/app/storing.py +++ b/src/keri/app/storing.py @@ -10,7 +10,7 @@ from . import forwarding from .. import help -from ..core import coring, serdering +from ..core import coring, serdering, eventing from ..core.coring import MtrDex from ..db import dbing, subing @@ -292,8 +292,6 @@ def cueDo(self, tymth=None, tock=0.0): elif cueKin in ("reply",): src = cue["src"] - serder = cue["serder"] - dest = cue["dest"] if dest not in self.hby.kevers: @@ -303,6 +301,11 @@ def cueDo(self, tymth=None, tock=0.0): if hab is None: continue + if "serder" in cue: + serder = cue["serder"] + else: + serder = eventing.reply(route=cue["route"], data=cue["data"]) + atc = hab.endorse(serder) del atc[:serder.size] self.postman.send(hab=hab, dest=dest, topic="reply", serder=serder, attachment=atc) diff --git a/src/keri/kering.py b/src/keri/kering.py index 2177b1be..89cc15ff 100644 --- a/src/keri/kering.py +++ b/src/keri/kering.py @@ -742,21 +742,6 @@ class UnverifiedProofError(ValidationError): """ -class OutOfOrderKeyStateError(ValidationError): - """ - Error referenced event missing from log so can't verify this key state event - Usage: - raise OutOfOrderKeyStateError("error message") - """ - - -class OutOfOrderTxnStateError(ValidationError): - """ - Error referenced event missing from log so can't verify this txn state event - Usage: - raise OutOfOrderTxnStateError("error message") - """ - class MisfitEventSourceError(ValidationError): """ Error referenced event missing from log so can't verify this txn state event diff --git a/src/keri/vdr/eventing.py b/src/keri/vdr/eventing.py index e696baba..74ce5a15 100644 --- a/src/keri/vdr/eventing.py +++ b/src/keri/vdr/eventing.py @@ -1644,14 +1644,15 @@ def processQuery(self, serder, source=None, sigers=None, cigars=None): self.cues.append(dict(kin="replay", src=src, dest=source.qb64, msgs=msgs)) elif route == "tsn": ri = qry["ri"] + src = qry["src"] if ri in self.tevers: tever = self.tevers[ri] tsn = tever.state() - self.cues.push(dict(kin="reply", route="/tsn/registry", data=asdict(tsn), dest=source)) + self.cues.push(dict(kin="reply", route=f"/tsn/registry/{src}", src=src, data=asdict(tsn), dest=source.qb64)) if vcpre := qry["i"]: - tsn = tever.vcState(vcpre=vcpre) - self.cues.push(dict(kin="reply", route="/tsn/credential", data=asdict(tsn), dest=source)) + tsn = tever.vcState(vci=vcpre) + self.cues.push(dict(kin="reply", route=f"/tsn/credential/{src}", src=src, data=asdict(tsn), dest=source.qb64)) else: raise ValidationError("invalid query message {} for evt = {}".format(ilk, ked)) @@ -1784,24 +1785,17 @@ def processReplyRegistryTxnState(self, *, serder, saider, route, cigars=None, ts ldig = self.reger.getTel(key=snKey(pre=regk, sn=sn)) # retrieve dig of last event at sn. - # Only accept key state if for last seen version of event at sn - if ldig is None: # escrow because event does not yet exist in database - if self.reger.txnsb.escrowStateNotice(typ="registry-ooo", pre=regk, aid=aid, serder=serder, saider=saider, - dater=dater, cigars=cigars, tsgs=tsgs): - self.cues.append(dict(kin="telquery", q=dict(ri=regk))) - - raise kering.OutOfOrderTxnStateError("Out of order txn state={}.".format(rsr)) - tsaider = coring.Saider(qb64=rsr.d) - ldig = bytes(ldig) - # retrieve last event itself of signer given sdig - sraw = self.reger.getTvt(key=dgKey(pre=regk, dig=ldig)) - # assumes db ensures that sraw must not be none because sdig was in KE - sserder = serdering.SerderKERI(raw=bytes(sraw)) + if ldig is not None: # escrow because event does not yet exist in database + ldig = bytes(ldig) + # retrieve last event itself of signer given sdig + sraw = self.reger.getTvt(key=dgKey(pre=regk, dig=ldig)) + # assumes db ensures that sraw must not be none because sdig was in KE + sserder = serdering.SerderKERI(raw=bytes(sraw)) - if sserder.said != tsaider.qb64: # mismatch events problem with replay - raise ValidationError("Mismatch keystate at sn = {} with db." - "".format(rsr.s)) + if sserder.said != tsaider.qb64: # mismatch events problem with replay + raise ValidationError("Mismatch keystate at sn = {} with db." + "".format(rsr.s)) self.reger.txnsb.updateReply(aid=aid, serder=serder, saider=tsaider, dater=dater) self.cues.append(dict(kin="txnStateSaved", record=rsr)) @@ -1924,28 +1918,21 @@ def processReplyCredentialTxnState(self, *, serder, saider, route, cigars=None, ldig = self.reger.getTel(key=snKey(pre=vci, sn=sn)) # retrieve dig of last event at sn. - # Only accept key state if for last seen version of event at sn - if ldig is None: # escrow because event does not yet exist in database - if self.reger.txnsb.escrowStateNotice(typ="credential-ooo", pre=vci, aid=aid, serder=serder, - saider=saider, dater=dater, cigars=cigars, tsgs=tsgs): - self.cues.append(dict(kin="telquery", q=dict(ri=regk, i=vci))) - - raise kering.OutOfOrderTxnStateError("Out of order txn state={}.".format(vsr)) - tsaider = coring.Saider(qb64=vsr.d) - ldig = bytes(ldig) - # retrieve last event itself of signer given sdig - sraw = self.reger.getTvt(key=dgKey(pre=vci, dig=ldig)) - # assumes db ensures that sraw must not be none because sdig was in KE - sserder = serdering.SerderKERI(raw=bytes(sraw)) + if ldig is not None: + ldig = bytes(ldig) + # retrieve last event itself of signer given sdig + sraw = self.reger.getTvt(key=dgKey(pre=vci, dig=ldig)) + # assumes db ensures that sraw must not be none because sdig was in KE + sserder = serdering.SerderKERI(raw=bytes(sraw)) - if sn < sserder.sn: - raise ValidationError("Stale txn state at sn = {} with db." - "".format(vsr.s)) + if sn < sserder.sn: + raise ValidationError("Stale txn state at sn = {} with db." + "".format(vsr.s)) - if sserder.said != tsaider.qb64: # mismatch events problem with replay - raise ValidationError("Mismatch txn state at sn = {} with db." - "".format(vsr.s)) + if sserder.said != tsaider.qb64: # mismatch events problem with replay + raise ValidationError("Mismatch txn state at sn = {} with db." + "".format(vsr.s)) self.reger.txnsb.updateReply(aid=aid, serder=serder, saider=tsaider, dater=dater) self.cues.append(dict(kin="txnStateSaved", record=vsr)) @@ -2007,12 +1994,8 @@ def processEscrows(self): extype=kering.MissingRegistryError) self.reger.txnsb.processEscrowState(typ="credential-mae", processReply=self.processReplyCredentialTxnState, extype=kering.MissingAnchorError) - self.reger.txnsb.processEscrowState(typ="credential-ooo", processReply=self.processReplyCredentialTxnState, - extype=kering.OutOfOrderTxnStateError) self.reger.txnsb.processEscrowState(typ="registry-mae", processReply=self.processReplyRegistryTxnState, extype=kering.MissingAnchorError) - self.reger.txnsb.processEscrowState(typ="registry-ooo", processReply=self.processReplyRegistryTxnState, - extype=kering.OutOfOrderTxnStateError) except Exception as ex: # log diagnostics errors etc if logger.isEnabledFor(logging.DEBUG): diff --git a/tests/app/test_querying.py b/tests/app/test_querying.py index ee6c42f4..649fe741 100644 --- a/tests/app/test_querying.py +++ b/tests/app/test_querying.py @@ -5,9 +5,13 @@ """ from hio.base import doing +from keri import kering from keri.app import habbing -from keri.app.querying import QueryDoer, KeyStateNoticer, LogQuerier, SeqNoQuerier, AnchorQuerier -from keri.core import parsing, eventing, serdering +from keri.app.querying import (QueryDoer, KeyStateNoticer, LogQuerier, SeqNoQuerier, AnchorQuerier, + TelStateNoticer, RegistryLogQuerier, VcLogQuerier) +from keri.core import parsing, eventing, serdering, coring, scheming, Counter, Codens +from keri.vdr import credentialing, verifying, eventing as teventing +from keri.vc.proving import credential from keri.db.dbing import dgKey @@ -167,4 +171,241 @@ def test_query_not_found_escrow(): subHab.db.qnfs.add(keys=(inqHab.pre, serder.said), val=serder.saidb) subHab.kvy.processQueryNotFound() - assert subHab.db.qnfs.get(dgkey) == [] \ No newline at end of file + assert subHab.db.qnfs.get(dgkey) == [] + + +def test_tel_querying(seeder): + with habbing.openHby() as hby, \ + habbing.openHby() as hby1: + seeder.seedSchema(hby.db) + seeder.seedSchema(hby1.db) + + inqHab = hby.makeHab(name="inquisitor") + subHab = hby1.makeHab(name="subject") + + icp = subHab.makeOwnInception() + parsing.Parser().parseOne(ims=bytearray(icp), kvy=inqHab.kvy) + + subRgy = credentialing.Regery(hby=hby1, temp=True) + subVer = verifying.Verifier(hby=hby1, reger=subRgy.reger) + + inqTvy = teventing.Tevery(db=hby.db, lax=True) + + # create management registry + issuer = subRgy.makeRegistry(prefix=subHab.pre, name="subject") + rseal = eventing.SealEvent(issuer.regk, "0", issuer.regd)._asdict() + subHab.interact(data=[rseal]) + seqner = coring.Seqner(sn=subHab.kever.sn) + issuer.anchorMsg(pre=issuer.regk, + regd=issuer.regd, + seqner=seqner, + saider=coring.Saider(qb64=subHab.kever.serder.said)) + subRgy.processEscrows() + + # tsn against management registry + tsnDoer = TelStateNoticer(hby=hby, hab=inqHab, tvy=inqTvy, pre=subHab.pre, ri=issuer.regk) + + tock = 0.03125 + limit = 1.0 + doist = doing.Doist(limit=limit, tock=tock, real=True) + deeds = doist.enter(doers=[tsnDoer]) + tever = subVer.reger.tevers.get(issuer.regk) + rsr = tever.state() + + # first wrong registry + rsr.i = "DAtNTPnDFBnmlO6J44LXCrzZTAmpe-82b7BmQGtL4QhM" + cue = dict(kin="txnStateSaved", record=rsr) + inqTvy.cues.append(cue) + doist.recur(deeds=deeds) + assert len(tsnDoer.doers) == 1 + assert tsnDoer.done is False + + # now correct + inqTvy.cues.clear() + rsr = tever.state() + cue = dict(kin="txnStateSaved", record=rsr) + inqTvy.cues.append(cue) + + doist.recur(deeds=deeds) + assert len(tsnDoer.doers) == 1 + regLogDoer = tsnDoer.doers[0] + assert isinstance(regLogDoer, RegistryLogQuerier) + assert len(regLogDoer.doers) == 1 + + anc = subHab.makeOwnEvent(1) + parsing.Parser().parseOne(ims=bytearray(anc), kvy=inqHab.kvy) + + for msg in subRgy.reger.clonePreIter(pre=issuer.regk, fn=0): + parsing.Parser().parseOne(ims=msg, tvy=inqTvy) + + deeds = doist.enter(doers=[regLogDoer]) + doist.recur(deeds=deeds) + assert len(regLogDoer.doers) == 0 + assert regLogDoer.done is True + + # tsn against management regsitry - no update needed + inqTvy.cues.append(cue) + tsnDoer = TelStateNoticer(hby=hby, hab=inqHab, tvy=inqTvy, pre=subHab.pre, ri=issuer.regk) + deeds = doist.enter(doers=[tsnDoer]) + doist.recur(deeds=deeds) + assert len(tsnDoer.doers) == 0 + assert tsnDoer.done is True + + # issue credential in registry + schema = "EMQWEcCnVRk1hatTNyK3sIykYSrrFvafX3bHQ9Gkk1kC" + credSubject = dict( + d="", + i=subHab.pre, + dt="2021-06-27T21:26:21.233257+00:00", + LEI="254900OPPU84GM83MG36", + ) + _, d = scheming.Saider.saidify(sad=credSubject, code=coring.MtrDex.Blake3_256, label=scheming.Saids.d) + + creder = credential(issuer=subHab.pre, + schema=schema, + data=d, + status=issuer.regk) + + iss = issuer.issue(said=creder.said) + rseal = eventing.SealEvent(iss.pre, "0", iss.said)._asdict() + subHab.interact(data=[rseal]) + seqner = coring.Seqner(sn=subHab.kever.sn) + issuer.anchorMsg(pre=iss.pre, + regd=iss.said, + seqner=seqner, + saider=coring.Saider(qb64=subHab.kever.serder.said)) + subRgy.processEscrows() + + msg = creder.raw + atc = bytearray(msg) + atc.extend(Counter(Codens.SealSourceTriples, count=1, gvrsn=kering.Vrsn_1_0).qb64b) + atc.extend(coring.Prefixer(qb64=iss.pre).qb64b) + atc.extend(coring.Seqner(sn=0).qb64b) + atc.extend(iss.saidb) + parsing.Parser().parseOne(ims=bytes(atc), vry=subVer) + + assert subVer.reger.saved.get(keys=(creder.said,)) is not None + + # tsn against vc + tsnDoer = TelStateNoticer(hby=hby, hab=inqHab, tvy=inqTvy, pre=subHab.pre, ri=issuer.regk, i=iss.pre) + deeds = doist.enter(doers=[tsnDoer]) + + vsr = tever.vcState(iss.pre) + + # wrong ri + vsr.ri = "DAtNTPnDFBnmlO6J44LXCrzZTAmpe-82b7BmQGtL4QhM" + cue = dict(kin="txnStateSaved", record=vsr) + inqTvy.cues.append(cue) + doist.recur(deeds=deeds) + assert len(tsnDoer.doers) == 1 + assert tsnDoer.done is False + + # wrong i + inqTvy.cues.clear() + vsr = tever.vcState(iss.pre) + vsr.i = "DAtNTPnDFBnmlO6J44LXCrzZTAmpe-82b7BmQGtL4QhM" + cue = dict(kin="txnStateSaved", record=vsr) + inqTvy.cues.append(cue) + doist.recur(deeds=deeds) + assert len(tsnDoer.doers) == 1 + assert tsnDoer.done is False + + # now correct + inqTvy.cues.clear() + vsr = tever.vcState(iss.pre) + cue = dict(kin="txnStateSaved", record=vsr) + inqTvy.cues.append(cue) + + doist.recur(deeds=deeds) + assert len(tsnDoer.doers) == 1 + vcLogDoer = tsnDoer.doers[0] + assert isinstance(vcLogDoer, VcLogQuerier) + assert len(vcLogDoer.doers) == 1 + + # receive vc updates + anc = subHab.makeOwnEvent(2) + parsing.Parser().parseOne(ims=bytearray(anc), kvy=inqHab.kvy) + + for msg in subRgy.reger.clonePreIter(pre=creder.said, fn=0): + parsing.Parser().parseOne(ims=msg, tvy=inqTvy) + + deeds = doist.enter(doers=[vcLogDoer]) + doist.recur(deeds=deeds) + assert len(vcLogDoer.doers) == 0 + assert vcLogDoer.done is True + + # vc update against querier without i + tsnDoer = TelStateNoticer(hby=hby, hab=inqHab, tvy=inqTvy, pre=subHab.pre, ri=issuer.regk) + deeds = doist.enter(doers=[tsnDoer]) + inqTvy.cues.clear() + vsr = tever.vcState(iss.pre) + cue = dict(kin="txnStateSaved", record=vsr) + inqTvy.cues.append(cue) + doist.recur(deeds=deeds) + assert len(tsnDoer.doers) == 1 + assert tsnDoer.done is False + + # now do a revocation + rev = issuer.revoke(said=creder.said) + rseal = eventing.SealEvent(rev.pre, "1", rev.said)._asdict() + subHab.interact(data=[rseal]) + seqner = coring.Seqner(sn=subHab.kever.sn) + issuer.anchorMsg(pre=rev.pre, + regd=rev.said, + seqner=seqner, + saider=coring.Saider(qb64=subHab.kever.serder.said)) + subRgy.processEscrows() + + msg = creder.raw + atc = bytearray(msg) + atc.extend(Counter(Codens.SealSourceTriples, count=1, gvrsn=kering.Vrsn_1_0).qb64b) + atc.extend(coring.Prefixer(qb64=rev.pre).qb64b) + atc.extend(coring.Seqner(sn=1).qb64b) + atc.extend(rev.saidb) + parsing.Parser().parseOne(ims=bytes(atc), vry=subVer) + + assert tever.vcState(vci=creder.said).et == coring.Ilks.rev + + # tsn with rev + tsnDoer = TelStateNoticer(hby=hby, hab=inqHab, tvy=inqTvy, pre=subHab.pre, ri=issuer.regk, i=iss.pre) + deeds = doist.enter(doers=[tsnDoer]) + inqTvy.cues.clear() + vsr = tever.vcState(iss.pre) + cue = dict(kin="txnStateSaved", record=vsr) + inqTvy.cues.append(cue) + doist.recur(deeds=deeds) + assert len(tsnDoer.doers) == 1 + vcLogDoer = tsnDoer.doers[0] + assert isinstance(vcLogDoer, VcLogQuerier) + + # receive vc updates + anc = subHab.makeOwnEvent(3) + parsing.Parser().parseOne(ims=bytearray(anc), kvy=inqHab.kvy) + + for msg in subRgy.reger.clonePreIter(pre=creder.said, fn=0): + parsing.Parser().parseOne(ims=msg, tvy=inqTvy) + + deeds = doist.enter(doers=[vcLogDoer]) + doist.recur(deeds=deeds) + assert len(vcLogDoer.doers) == 0 + assert vcLogDoer.done is True + + # tsn against vc - no update needed + inqTvy.cues.clear() + inqTvy.cues.append(cue) + tsnDoer = TelStateNoticer(hby=hby, hab=inqHab, tvy=inqTvy, pre=subHab.pre, ri=issuer.regk, i=iss.pre) + deeds = doist.enter(doers=[tsnDoer]) + doist.recur(deeds=deeds) + assert len(tsnDoer.doers) == 0 + assert tsnDoer.done is True + + # tsn with vc if management registry does not exist + inqTvyEmpty = teventing.Tevery(db=hby.db, lax=True) + inqTvyEmpty.cues.append(cue) + + tsnDoer = TelStateNoticer(hby=hby, hab=inqHab, tvy=inqTvyEmpty, pre=subHab.pre, ri=issuer.regk, i=iss.pre) + deeds = doist.enter(doers=[tsnDoer]) + doist.recur(deeds=deeds) + assert len(tsnDoer.doers) == 1 + vcLogDoer = tsnDoer.doers[0] + assert isinstance(vcLogDoer, VcLogQuerier) diff --git a/tests/vdr/test_txn_state.py b/tests/vdr/test_txn_state.py index 8daa46b0..f4106694 100644 --- a/tests/vdr/test_txn_state.py +++ b/tests/vdr/test_txn_state.py @@ -11,87 +11,6 @@ from keri.vdr import viring, credentialing, eventing -def test_tsn_message_out_of_order(mockHelpingNowUTC, mockCoringRandomNonce): - # Bob is the controller - # Bam is verifying the key state for Bob with a stale key state in the way - - default_salt = core.Salter(raw=b'0123456789abcdef').qb64 - - with (habbing.openHby(name="bob", base="test", salt=default_salt) as bobHby, - habbing.openHby(name="bam", base="test", salt=default_salt) as bamHby): - - bobHab = bobHby.makeHab(name="bob", isith='1', icount=1,) - assert bobHab.pre == 'EFggrgspyZwbi-zB2iJzjHu0QU5dh89mA8jOhDcgrTqj' - - regery = credentialing.Regery(hby=bobHby, name="test", temp=True) - issuer = regery.makeRegistry(prefix=bobHab.pre, name=bobHab.name) - rseal = SealEvent(issuer.regk, "0", issuer.regd)._asdict() - bobHab.interact(data=[rseal]) - seqner = coring.Seqner(sn=bobHab.kever.sn) - issuer.anchorMsg(pre=issuer.regk, - regd=issuer.regd, - seqner=seqner, - saider=coring.Saider(qb64=bobHab.kever.serder.said)) - regery.processEscrows() - - assert issuer.regk == 'EClqKVJREM3MWKBqR2j712s3Z6rPxhqO-h-p8Ls6_9hQ' - - # Gather up Bob's key event log - msgs = bytearray() - for msg in bobHby.db.clonePreIter(pre=bobHab.pre, fn=0): - msgs.extend(msg) - - # pass key event log to Bam - bamRtr = routing.Router() - bamRvy = routing.Revery(db=bamHby.db, rtr=bamRtr) - bamKvy = Kevery(db=bamHby.db, lax=False, local=False, rvy=bamRvy) - parsing.Parser().parse(ims=msgs, kvy=bamKvy, rvy=bamRvy) - - tever = issuer.tevers[issuer.regk] - rsr = tever.state() - - assert asdict(rsr) == {'b': [], - 'bt': '0', - 'c': ['NB'], - 'd': 'EClqKVJREM3MWKBqR2j712s3Z6rPxhqO-h-p8Ls6_9hQ', - 'dt': '2021-01-01T00:00:00.000000+00:00', - 'et': 'vcp', - 'i': 'EClqKVJREM3MWKBqR2j712s3Z6rPxhqO-h-p8Ls6_9hQ', - 'ii': 'EFggrgspyZwbi-zB2iJzjHu0QU5dh89mA8jOhDcgrTqj', - 's': '0', - 'vn': [1, 0]} - - rpy = bobHab.reply(route="/tsn/registry/" + bobHab.pre, data=rsr._asdict()) - - bamReger = viring.Reger(name="bam", temp=True) - bamTvy = eventing.Tevery(reger=bamReger, db=bamHby.db, lax=False, local=False, rvy=bamRvy) - bamTvy.registerReplyRoutes(router=bamRtr) - parsing.Parser().parse(ims=bytearray(rpy), tvy=bamTvy, rvy=bamRvy) - - assert len(bamTvy.cues) == 1 - cue = bamTvy.cues.popleft() - assert cue["kin"] == "telquery" - assert cue['q']['ri'] == issuer.regk - - saider = bamReger.txnsb.escrowdb.get(keys=("registry-ooo", issuer.regk, bobHab.pre)) - assert saider[0].qb64b == b'ECZWYxq_Qgs0J0ls_imRWRYxrojzTKL2REjqe0rN8kWy' - - tmsgs = bytearray() - cloner = regery.reger.clonePreIter(pre=issuer.regk, fn=0) # create iterator at 0 - for msg in cloner: - tmsgs.extend(msg) - - parsing.Parser().parse(ims=tmsgs, tvy=bamTvy, rvy=bamRvy) - assert issuer.regk in bamReger.tevers - - bamTvy.processEscrows() - # check to make sure the tsn escrow state is clear - assert bamReger.txnsb.escrowdb.get(keys=(issuer.regk, bobHab.pre)) == [] - # check to make sure the tsn has been saved - saider = bamReger.txnsb.saiderdb.get(keys=(issuer.regk, bobHab.pre)) - assert saider.qb64b == b'EClqKVJREM3MWKBqR2j712s3Z6rPxhqO-h-p8Ls6_9hQ' - - def test_tsn_message_missing_anchor(mockHelpingNowUTC, mockCoringRandomNonce): # Bob is the controller # Bam is verifying the key state for Bob with a stale key state in the way @@ -160,24 +79,9 @@ def test_tsn_message_missing_anchor(mockHelpingNowUTC, mockCoringRandomNonce): assert len(bamTvy.cues) == 1 cue = bamTvy.cues.popleft() - assert cue["kin"] == "telquery" - assert cue['q']['ri'] == issuer.regk - - saider = bamReger.txnsb.escrowdb.get(keys=("registry-ooo", issuer.regk, bobHab.pre)) - assert saider[0].qb64b == said - - tmsgs = bytearray() - cloner = regery.reger.clonePreIter(pre=issuer.regk, fn=0) # create iterator at 0 - for msg in cloner: - tmsgs.extend(msg) - - parsing.Parser().parse(ims=tmsgs, tvy=bamTvy, rvy=bamRvy) - assert issuer.regk in bamReger.tevers + assert cue["kin"] == "txnStateSaved" + assert cue["record"] == tsn - bamTvy.processEscrows() - - # check to make sure the tsn escrow state is clear - assert bamReger.txnsb.escrowdb.get(keys=(issuer.regk, bobHab.pre)) == [] # check to make sure the tsn has been saved saider = bamReger.txnsb.saiderdb.get(keys=(issuer.regk, bobHab.pre)) assert saider.qb64b == b'EClqKVJREM3MWKBqR2j712s3Z6rPxhqO-h-p8Ls6_9hQ' @@ -284,20 +188,9 @@ def test_tsn_from_witness(mockHelpingNowUTC, mockCoringRandomNonce): assert len(bamTvy.cues) == 1 cue = bamTvy.cues.popleft() - assert cue["kin"] == "telquery" - assert cue['q']['ri'] == issuer.regk - - saider = bamReger.txnsb.escrowdb.get(keys=("registry-ooo", issuer.regk, wesHab.pre)) - assert saider[0].qb64b == said - - parsing.Parser().parse(ims=bytearray(tmsgs), tvy=bamTvy, rvy=bamRvy, local=True) + assert cue["kin"] == "txnStateSaved" + assert cue["record"] == tsn - assert issuer.regk in bamReger.tevers - - bamTvy.processEscrows() - - # check to make sure the tsn escrow state is clear - assert bamReger.txnsb.escrowdb.get(keys=(issuer.regk, wesHab.pre)) == [] # check to make sure the tsn has been saved saider = bamReger.txnsb.saiderdb.get(keys=(issuer.regk, wesHab.pre)) assert saider.qb64b == b'EH3hN33719ybSg21Kboy-V2jafwvQSHnY1HUGzzBqqk6' @@ -508,24 +401,9 @@ def test_credential_tsn_message(mockHelpingNowUTC, mockCoringRandomNonce, mockHe assert len(bamTvy.cues) == 1 cue = bamTvy.cues.popleft() - assert cue["kin"] == "telquery" - assert cue['q']['ri'] == issuer.regk - - saider = bamReger.txnsb.escrowdb.get(keys=("credential-ooo", creder.said, bobHab.pre)) - assert saider[0].qb64b == b'EHERhBLfaMik0Ne9ysU3UICXWge0yobK0FQv3QhyeqF7' - - vci = creder.said - tmsgs = bytearray() - cloner = regery.reger.clonePreIter(pre=vci, fn=0) # create iterator at 0 - for msg in cloner: - tmsgs.extend(msg) - - parsing.Parser().parse(ims=tmsgs, tvy=bamTvy, rvy=bamRvy) - - bamTvy.processEscrows() + assert cue["kin"] == "txnStateSaved" + assert cue["record"] == ctsn - # check to make sure the tsn escrow state is clear - assert bamReger.txnsb.escrowdb.get(keys=(creder.said, bobHab.pre)) == [] # check to make sure the tsn has been saved keys = (creder.said, bobHab.pre) saider = bamReger.txnsb.saiderdb.get(keys=keys)