Exemple #1
0
def gen_nontransferable_serialized_aid():
    with openDB() as bsr:
        # Inception: Non-transferable (ephemeral) case
        signer0 = Signer(
            transferable=False)  #  original signing keypair non transferable
        assert signer0.code == CryOneDex.Ed25519_Seed
        assert signer0.verfer.code == CryOneDex.Ed25519N
        keys0 = [signer0.verfer.qb64]
        serder = incept(keys=keys0)  #  default nxt is empty so abandoned

        # Derive AID from ked
        aid0 = Prefixer(ked=serder.ked, code=CryOneDex.Ed25519N)

        # update ked with pre
        serder.ked["pre"] = aid0.qb64

        # Serialize ked0
        tser0 = Serder(ked=serder.ked)

        # sign serialization
        skp0 = Signer()  # original signing keypair transferable default
        tsig0 = skp0.sign(tser0.raw, index=0)

        # verify signature
        assert skp0.verfer.verify(tsig0.raw, tser0.raw)

        # not sure why this errors out when enabled; I guess kevers can't be used with nontransferable ids
        # kever = Kever(serder=tser0, sigers=[tsig0], baser=bsr)  # no error

        # return base 64 serialization of signed aid
        return tsig0.qb64
Exemple #2
0
def test_direct_mode_bob_eve_demo():
    """
    Test direct mode bob and eve
    """
    help.ogler.resetLevel(level=logging.DEBUG)

    # set of secrets  (seeds for private keys)
    bobSecrets = [
        'ArwXoACJgOleVZ2PY7kXn7rA0II0mHYDhc6WrBH8fDAc',
        'A6zz7M08-HQSFq92sJ8KJOT2cZ47x7pXFQLPB0pckB3Q',
        'AcwFTk-wgk3ZT2buPRIbK-zxgPx-TKbaegQvPEivN90Y',
        'Alntkt3u6dDgiQxTATr01dy8M72uuaZEf9eTdM-70Gk8',
        'A1-QxDkso9-MR1A8rZz_Naw6fgaAtayda8hrbkRVVu1E',
        'AKuYMe09COczwf2nIoD5AE119n7GLFOVFlNLxZcKuswc',
        'AxFfJTcSuEE11FINfXMqWttkZGnUZ8KaREhrnyAXTsjw',
        'ALq-w1UKkdrppwZzGTtz4PWYEeWm0-sDHzOv5sq96xJY'
    ]

    bobSecrecies = []
    for secret in bobSecrets:  # convert secrets to secrecies
        bobSecrecies.append([secret])

    #  create bob signers
    bobSigners = [coring.Signer(qb64=secret) for secret in bobSecrets]
    assert [signer.qb64 for signer in bobSigners] == bobSecrets

    # bob inception transferable (nxt digest not empty)
    bobSerder = eventing.incept(
        keys=[bobSigners[0].verfer.qb64],
        nxt=coring.Nexter(keys=[bobSigners[1].verfer.qb64]).qb64,
        code=coring.MtrDex.Blake3_256)

    bob = bobSerder.ked["i"]
    assert bob == 'EH7Oq9oxCgYa-nnNLvwhp9sFZpALILlRYyB-6n4WDi7w'

    # set of secrets (seeds for private keys)
    eveSecrets = [
        'AgjD4nRlycmM5cPcAkfOATAp8wVldRsnc9f1tiwctXlw',
        'AKUotEE0eAheKdDJh9QvNmSEmO_bjIav8V_GmctGpuCQ',
        'AK-nVhMMJciMPvmF5VZE_9H-nhrgng9aJWf7_UHPtRNM',
        'AT2cx-P5YUjIw_SLCHQ0pqoBWGk9s4N1brD-4pD_ANbs',
        'Ap5waegfnuP6ezC18w7jQiPyQwYYsp9Yv9rYMlKAYL8k',
        'Aqlc_FWWrxpxCo7R12uIz_Y2pHUH2prHx1kjghPa8jT8',
        'AagumsL8FeGES7tYcnr_5oN6qcwJzZfLKxoniKUpG4qc',
        'ADW3o9m3udwEf0aoOdZLLJdf1aylokP0lwwI_M2J9h0s'
    ]

    eveSecrecies = []
    for secret in eveSecrets:  # convert secrets to secrecies
        eveSecrecies.append([secret])

    #  create eve signers
    eveSigners = [coring.Signer(qb64=secret) for secret in eveSecrets]
    assert [signer.qb64 for signer in eveSigners] == eveSecrets

    # eve inception transferable (nxt digest not empty)
    eveSerder = eventing.incept(
        keys=[eveSigners[0].verfer.qb64],
        nxt=coring.Nexter(keys=[eveSigners[1].verfer.qb64]).qb64,
        code=coring.MtrDex.Blake3_256)

    eve = eveSerder.ked["i"]
    assert eve == 'EpDA1n-WiBA0A8YOqnKrB-wWQYYC49i5zY_qrIZIicQg'

    with dbing.openDB(name="eve") as eveDB, keeping.openKS(name="eve") as eveKS, \
         dbing.openDB(name="bob") as bobDB, keeping.openKS(name="bob") as bobKS:

        limit = 1.0
        tock = 0.03125
        doist = doing.Doist(limit=limit, tock=tock)

        bobPort = 5620  # bob's TCP listening port for server
        evePort = 5621  # eve's TCP listneing port for server
        bobKevers = dict()
        eveKevers = dict()

        # setup bob
        bobHab = directing.Habitat(name='Bob',
                                   ks=bobKS,
                                   db=bobDB,
                                   kevers=bobKevers,
                                   secrecies=bobSecrecies,
                                   temp=True)
        assert bobHab.ks == bobKS
        assert bobHab.db == bobDB
        assert bobHab.iserder.dig == bobSerder.dig
        assert bobHab.pre == bob

        bobClient = clienting.Client(tymth=doist.tymen(),
                                     host='127.0.0.1',
                                     port=evePort)
        bobClientDoer = doing.ClientDoer(client=bobClient)

        bobDirector = demoing.BobDirector(hab=bobHab,
                                          client=bobClient,
                                          tock=0.125)
        assert bobDirector.hab == bobHab
        assert bobDirector.client == bobClient
        assert bobDirector.hab.kvy.kevers == bobKevers
        assert bobDirector.hab.kvy.db == bobDB
        assert bobDirector.tock == 0.125

        bobReactor = directing.Reactor(hab=bobHab, client=bobClient)
        assert bobReactor.hab == bobHab
        assert bobReactor.client == bobClient
        assert bobReactor.hab.kvy.kevers == bobKevers
        assert bobReactor.hab.kvy.db == bobDB
        assert bobReactor.hab.kvy.ims == bobReactor.client.rxbs

        bobServer = serving.Server(host="", port=bobPort)
        bobServerDoer = doing.ServerDoer(server=bobServer)

        bobDirectant = directing.Directant(hab=bobHab, server=bobServer)
        assert bobDirectant.hab == bobHab
        assert bobDirectant.server == bobServer
        # Bob's Reactants created on demand

        # setup eve
        eveHab = directing.Habitat(name='Eve',
                                   ks=eveKS,
                                   db=eveDB,
                                   kevers=eveKevers,
                                   secrecies=eveSecrecies,
                                   temp=True)

        assert eveHab.ks == eveKS
        assert eveHab.db == eveDB
        assert eveHab.iserder.dig == eveSerder.dig
        assert eveHab.pre == eve

        eveClient = clienting.Client(tymth=doist.tymen(),
                                     host='127.0.0.1',
                                     port=bobPort)
        eveClientDoer = doing.ClientDoer(client=eveClient)

        eveDirector = demoing.EveDirector(hab=eveHab,
                                          client=eveClient,
                                          tock=0.125)
        assert eveDirector.hab == eveHab
        assert eveDirector.client == eveClient
        assert eveDirector.hab.kvy.kevers == eveKevers
        assert eveDirector.hab.kvy.db == eveDB

        eveReactor = directing.Reactor(hab=eveHab, client=eveClient)
        assert eveReactor.hab == eveHab
        assert eveReactor.client == eveClient
        assert eveReactor.hab.kvy.kevers == eveKevers
        assert eveReactor.hab.kvy.db == eveDB
        assert eveReactor.hab.kvy.ims == eveReactor.client.rxbs

        eveServer = serving.Server(host="", port=evePort)
        eveServerDoer = doing.ServerDoer(server=eveServer)

        eveDirectant = directing.Directant(hab=eveHab, server=eveServer)
        assert eveDirectant.hab == eveHab
        assert eveDirectant.server == eveServer
        # Eve's Reactants created on demand

        doers = [
            bobClientDoer, bobDirector, bobReactor, bobServerDoer,
            bobDirectant, eveClientDoer, eveDirector, eveReactor,
            eveServerDoer, eveDirectant
        ]
        doist.do(doers=doers)
        assert doist.tyme == limit

        assert bobClient.opened == False
        assert bobServer.opened == False
        assert eveClient.opened == False
        assert eveServer.opened == False

        assert bobHab.pre in bobHab.kevers
        assert eveHab.pre in eveHab.kevers

        assert not bobClient.txbs

        assert bobHab.pre in eveHab.kevers

        #  verify final event states

    assert not os.path.exists(eveDB.path)
    assert not os.path.exists(bobDB.path)

    help.ogler.resetLevel(level=help.ogler.level)
    """End Test"""
Exemple #3
0
def test_witness():
    """
    Test event validation logic with witnesses

    cam is controller
    van is validator
    wes is a witness
    wok is a witness
    wam is a witness

    """
    salt = coring.Salter(raw=b'abcdef0123456789').qb64

    with dbing.openDB(name="cam") as camDB, keeping.openKS(name="cam") as camKS, \
         dbing.openDB(name="van") as vanDB, keeping.openKS(name="van") as vanKS, \
         dbing.openDB(name="wes") as wesDB, keeping.openKS(name="wes") as wesKS, \
         dbing.openDB(name="wok") as wokDB, keeping.openKS(name="wok") as wokKS, \
         dbing.openDB(name="wam") as wamDB, keeping.openKS(name="wam") as wamKS, \
         dbing.openDB(name="wil") as wilDB, keeping.openKS(name="wil") as wilKS:

        # witnesses first so can setup inception event for cam
        wsith = 1
        # setup Wes's habitat nontrans
        # Wes's receipts will be rcts with a receipt couple attached

        wesHab = directing.Habitat(name='wes',
                                   ks=wesKS,
                                   db=wesDB,
                                   isith=wsith,
                                   icount=1,
                                   salt=salt,
                                   transferable=False,
                                   temp=True)  # stem is .name
        assert wesHab.ks == wesKS
        assert wesHab.db == wesDB
        assert not wesHab.kever.prefixer.transferable
        # create non-local kevery for Wes to process nonlocal msgs
        wesKvy = eventing.Kevery(kevers=wesHab.kevers,
                                 db=wesHab.db,
                                 framed=True,
                                 opre=wesHab.pre,
                                 local=False)

        # setup Wok's habitat nontrans
        # Wok's receipts will be rcts with a receipt couple attached
        wokHab = directing.Habitat(name='wok',
                                   ks=wokKS,
                                   db=wokDB,
                                   isith=wsith,
                                   icount=1,
                                   salt=salt,
                                   transferable=False,
                                   temp=True)  # stem is .name
        assert wokHab.ks == wokKS
        assert wokHab.db == wokDB
        assert not wokHab.kever.prefixer.transferable
        # create non-local kevery for Wok to process nonlocal msgs
        wokKvy = eventing.Kevery(kevers=wokHab.kevers,
                                 db=wokHab.db,
                                 framed=True,
                                 opre=wokHab.pre,
                                 local=False)

        # setup Wam's habitat nontrans
        # Wams's receipts will be rcts with a receipt couple attached
        wamHab = directing.Habitat(name='wam',
                                   ks=wamKS,
                                   db=wamDB,
                                   isith=wsith,
                                   icount=1,
                                   salt=salt,
                                   transferable=False,
                                   temp=True)  # stem is .name
        assert wamHab.ks == wamKS
        assert wamHab.db == wamDB
        assert not wamHab.kever.prefixer.transferable
        # create non-local kevery for Wam to process nonlocal msgs
        wamKvy = eventing.Kevery(kevers=wamHab.kevers,
                                 db=wamHab.db,
                                 framed=True,
                                 opre=wamHab.pre,
                                 local=False)

        # setup Wil's habitat nontrans
        # Wil's receipts will be rcts with a receipt couple attached
        wilHab = directing.Habitat(name='wil',
                                   ks=wilKS,
                                   db=wilDB,
                                   isith=wsith,
                                   icount=1,
                                   salt=salt,
                                   transferable=False,
                                   temp=True)  # stem is .name
        assert wilHab.ks == wilKS
        assert wilHab.db == wilDB
        assert not wilHab.kever.prefixer.transferable
        # create non-local kevery for Wam to process nonlocal msgs
        wilKvy = eventing.Kevery(kevers=wilHab.kevers,
                                 db=wilHab.db,
                                 framed=True,
                                 opre=wilHab.pre,
                                 local=False)

        # setup Cam's habitat trans multisig
        wits = [wesHab.pre, wokHab.pre, wamHab.pre]
        csith = 2  # hex str of threshold int
        camHab = directing.Habitat(name='cam',
                                   ks=camKS,
                                   db=camDB,
                                   isith=csith,
                                   icount=3,
                                   toad=2,
                                   wits=wits,
                                   salt=salt,
                                   temp=True)  # stem is .name
        assert camHab.ks == camKS
        assert camHab.db == camDB
        assert camHab.kever.prefixer.transferable
        for werfer in camHab.iserder.werfers:
            assert werfer.qb64 in wits
        assert camHab.kever.wits == wits
        assert camHab.kever.toad == 2
        assert camHab.kever.sn == 0

        # create non-local kevery for Cam to process onlocal msgs
        camKvy = eventing.Kevery(kevers=camHab.kevers,
                                 db=camHab.db,
                                 framed=True,
                                 opre=camHab.pre,
                                 local=False)

        # setup Van's habitat trans multisig
        vsith = 2  # two of three signing threshold
        vanHab = directing.Habitat(name='van',
                                   ks=vanKS,
                                   db=vanDB,
                                   isith=vsith,
                                   icount=3,
                                   salt=salt,
                                   temp=True)  # stem is .name
        assert vanHab.ks == vanKS
        assert vanHab.db == vanDB
        assert vanHab.kever.prefixer.transferable
        # create non-local kevery for Van to process nonlocal msgs
        vanKvy = eventing.Kevery(kevers=vanHab.kevers,
                                 db=vanHab.db,
                                 framed=True,
                                 opre=vanHab.pre,
                                 local=False)

        # make list so easier to batch
        camWitKvys = [wesKvy, wokKvy, wamKvy]
        camWitHabs = [wesHab, wokHab, wamHab]

        # Create Cam inception and send to each of Cam's witnesses
        camIcpMsg = camHab.makeOwnInception()
        rctMsgs = []  # list of receipts from each witness
        for i in range(len(camWitKvys)):
            kvy = camWitKvys[i]
            kvy.process(ims=bytearray(
                camIcpMsg))  # send copy of cam icp msg to witness
            assert kvy.kevers[camHab.pre].sn == 0  # accepted event
            assert len(kvy.cues) == 1  # queued receipt cue
            hab = camWitHabs[i]
            rctMsg = hab.processCues(kvy.cues)  # process cue returns rct msg
            assert len(rctMsg) == 559
            rctMsgs.append(rctMsg)

        for msg in rctMsgs:  # process rct msgs from all witnesses
            camKvy.process(ims=bytearray(msg))  # make copy
        for hab in camWitHabs:
            assert hab.pre in camKvy.kevers

        # get from Cam database copies of witness receipts received by Cam
        # and send to witnesses so all witnesses have full set of receipts
        # from all other witnesses
        # reply one event or receipt one event with all witness attachments
        dgkey = dbing.dgKey(pre=camHab.pre, dig=camHab.kever.serder.dig)
        wigs = camHab.db.getWigs(dgkey)
        assert len(wigs) == 3
        wigers = [coring.Siger(qb64b=bytes(wig)) for wig in wigs]
        rserder = eventing.receipt(pre=camHab.pre,
                                   sn=camHab.kever.sn,
                                   dig=camHab.kever.serder.dig)
        camIcpWitRctMsg = eventing.messagize(serder=rserder, wigers=wigers)
        assert len(camIcpWitRctMsg) == 413
        for i in range(len(camWitKvys)):
            kvy = camWitKvys[i]
            kvy.process(
                ims=bytearray(camIcpWitRctMsg))  # send copy of witness rcts
            assert len(kvy.db.getWigs(dgkey)) == 3  # fully witnessed
            assert len(kvy.cues) == 0  # no cues

        # send Cam icp and witness rcts to Van
        vanKvy.process(
            ims=bytearray(camIcpMsg))  # should escrow since not witnesses
        assert camHab.pre not in vanKvy.kevers
        vanKvy.process(ims=bytearray(camIcpWitRctMsg))
        vanKvy.processEscrows()
        assert camHab.pre in vanKvy.kevers
        vcKvr = vanKvy.kevers[camHab.pre]
        assert vcKvr.sn == 0
        assert vcKvr.wits == wits

        # Create Cam ixn and send to each of Cam's witnesses
        camIxnMsg = camHab.interact()
        rctMsgs = []  # list of receipts from each witness
        for i in range(len(camWitKvys)):
            kvy = camWitKvys[i]
            kvy.process(ims=bytearray(
                camIxnMsg))  # send copy of cam icp msg to witness
            assert kvy.kevers[camHab.pre].sn == 1  # accepted event
            assert len(kvy.cues) == 1  # queued receipt cue
            hab = camWitHabs[i]
            rctMsg = hab.processCues(kvy.cues)  # process cue returns rct msg
            assert len(rctMsg) == 281
            rctMsgs.append(rctMsg)

        for msg in rctMsgs:  # process rct msgs from all witnesses
            camKvy.process(ims=bytearray(msg))  # make copy
        for hab in camWitHabs:
            assert hab.pre in camKvy.kevers

        # get from Cam database copies of witness receipts received by Cam
        # and send to witnesses so all witnesses have full set of receipts
        # from all other witnesses
        # reply one event or receipt one event with all witness attachments
        dgkey = dbing.dgKey(pre=camHab.pre, dig=camHab.kever.serder.dig)
        wigs = camHab.db.getWigs(dgkey)
        assert len(wigs) == 3
        wigers = [coring.Siger(qb64b=bytes(wig)) for wig in wigs]
        rserder = eventing.receipt(pre=camHab.pre,
                                   sn=camHab.kever.sn,
                                   dig=camHab.kever.serder.dig)
        camIxnWitRctMsg = eventing.messagize(serder=rserder, wigers=wigers)
        assert len(camIxnWitRctMsg) == 413
        for i in range(len(camWitKvys)):
            kvy = camWitKvys[i]
            kvy.process(
                ims=bytearray(camIxnWitRctMsg))  # send copy of witness rcts
            assert len(kvy.db.getWigs(dgkey)) == 3  # fully witnessed
            assert len(kvy.cues) == 0  # no cues

        # send Cam ixn's witness rcts to Van first then send Cam ixn
        vanKvy.process(ims=bytearray(camIxnWitRctMsg))
        vanKvy.processEscrows()
        assert vcKvr.sn == 0
        vanKvy.process(
            ims=bytearray(camIxnMsg))  # should escrow since not witnesses
        assert vcKvr.sn == 0
        vanKvy.processEscrows()
        assert vcKvr.sn == 1

        # Cam replace Wok with Wil as a witness.
        # Cam update Wil all event witnessed events for Cam by replay
        # Cam update itself with Wil receipts including Wils inception
        camReplayMsg = camHab.replay()
        assert len(camReplayMsg) == 1824
        wilKvy.process(ims=bytearray(camReplayMsg))
        assert camHab.pre in wilKvy.kevers
        assert wilKvy.kevers[camHab.pre].sn == 1  # asscepted both events
        assert len(wilKvy.cues) == 2
        wilRctMsg = wilHab.processCues(
            wilKvy.cues)  # process cue returns rct msg
        assert len(wilKvy.cues) == 0
        camKvy.process(ims=bytearray(wilRctMsg))  # make copy
        assert wilHab.pre in camKvy.kevers

        # Cam rotation with witness rotation
        camRotMsg = camHab.rotate(toad=2, cuts=[wokHab.pre], adds=[wilHab.pre])
        assert camHab.kever.wits == [wesHab.pre, wamHab.pre, wilHab.pre]
        assert camHab.kever.toad == 2
        assert camHab.kever.sn == 2

        # update lists of witness kvys and habs
        camWitKvys = [wesKvy, wamKvy, wilKvy]
        camWitHabs = [wesHab, wamHab, wilHab]

        rctMsgs = []  # list of receipt msgs from each witness
        for i in range(len(camWitKvys)):
            kvy = camWitKvys[i]
            kvy.process(
                ims=bytearray(camRotMsg))  # send copy of cam msg to witness
            assert kvy.kevers[camHab.pre].sn == 2  # accepted event
            assert len(kvy.cues) == 1  # queued receipt cue
            hab = camWitHabs[i]
            rctMsg = hab.processCues(kvy.cues)  # process cue returns rct msg
            assert len(rctMsg) == 281
            rctMsgs.append(rctMsg)

        for msg in rctMsgs:  # process rct msgs from all witnesses
            camKvy.process(ims=bytearray(msg))  # make copy
        for hab in camWitHabs:
            assert hab.pre in camKvy.kevers

        # get from Cam database copies of witness receipts received by Cam
        # and send to witnesses so all witnesses have full set of receipts
        # from all other witnesses
        # reply one event or receipt one event with all witness attachments
        dgkey = dbing.dgKey(pre=camHab.pre, dig=camHab.kever.serder.dig)
        wigs = camHab.db.getWigs(dgkey)
        assert len(wigs) == 3
        wigers = [coring.Siger(qb64b=bytes(wig)) for wig in wigs]
        rserder = eventing.receipt(pre=camHab.pre,
                                   sn=camHab.kever.sn,
                                   dig=camHab.kever.serder.dig)
        camRotWitRctMsg = eventing.messagize(serder=rserder, wigers=wigers)
        assert len(camRotWitRctMsg) == 413
        for i in range(len(camWitKvys)):
            kvy = camWitKvys[i]
            kvy.process(
                ims=bytearray(camRotWitRctMsg))  # send copy of witness rcts
            assert len(kvy.db.getWigs(dgkey)) == 3  # fully witnessed
            assert len(kvy.cues) == 0  # no cues

        # send Cam's rot and wit receipts to Van
        #vanKvy.process(ims=bytearray(camRotMsg))  # should escrow since not witnesses
        #vanKvy.process(ims=bytearray(camRotWitRctMsg))
        #vanKvy.processEscrows()
        #assert vcKvr.sn == 2
        #assert vcKvr.wits == camHab.kever.wits

        # send Cam rot's witness rcts to Van first then send Cam rot
        vanKvy.process(ims=bytearray(camRotWitRctMsg))
        vanKvy.processEscrows()
        assert vcKvr.sn == 1
        vanKvy.process(
            ims=bytearray(camRotMsg))  # should escrow since not witnesses
        assert vcKvr.sn == 1
        vanKvy.processEscrows()
        assert vcKvr.sn == 2
        assert vcKvr.wits == camHab.kever.wits

    assert not os.path.exists(wokKS.path)
    assert not os.path.exists(wokDB.path)
    assert not os.path.exists(wesKS.path)
    assert not os.path.exists(wesDB.path)
    assert not os.path.exists(vanKS.path)
    assert not os.path.exists(vanDB.path)
    assert not os.path.exists(camKS.path)
    assert not os.path.exists(camDB.path)
    """End Test"""
Exemple #4
0
def test_replay():
    """
    Test disjoint and conjoint replay

    Deb creates series of events.
    Deb replays Deb's events to Cam and collects Cam's receipts
    Deb replays Deb's events with Cam's recepts to Bev and collects Bev's receipts
    Deb replays Deb's events with both Cam's and  Bev's receipts to Cam
    Compare replay of Deb's events with receipts by both Deb and Cam to confirm identical
    """

    with dbing.openDB(name="deb") as debDB, keeping.openKS(name="deb") as debKS, \
         dbing.openDB(name="cam") as camDB, keeping.openKS(name="cam") as camKS, \
         dbing.openDB(name="bev") as bevDB, keeping.openKS(name="bev") as bevKS, \
         dbing.openDB(name="art") as artDB, keeping.openKS(name="art") as artKS:

        # setup Deb's habitat using default salt multisig already incepts
        sith = ["1/2", "1/2", "1/2"]  # weighted signing threshold
        debHab = directing.Habitat(ks=debKS, db=debDB, isith=sith, icount=3,
                                   temp=True)
        assert debHab.ks == debKS
        assert debHab.db == debDB
        assert debHab.kever.prefixer.transferable

        # setup Cam's habitat using default salt multisig already incepts
        # Cam's receipts will be vrcs with 3 indexed sigantures attached
        sith = '2'  # hex str of threshold int
        camHab = directing.Habitat(ks=camKS, db=camDB, isith=sith, icount=3,
                                   temp=True)
        assert camHab.ks == camKS
        assert camHab.db == camDB
        assert camHab.kever.prefixer.transferable

        # setup Bev's habitat using default salt nonstransferable already incepts
        # Bev's receipts will be rcts with a receipt couple attached
        sith = '1'  # hex str of threshold int
        bevHab = directing.Habitat(ks=bevKS, db=bevDB, isith=sith, icount=1,
                                   transferable=False, temp=True)
        assert bevHab.ks == bevKS
        assert bevHab.db == bevDB
        assert not bevHab.kever.prefixer.transferable

        # setup Art's habitat using custom salt nonstransferable so not match Bev
        # already incepts
        # Art's receipts will be rcts with a receipt couple attached
        salt = coring.Salter(raw=b'abcdef0123456789').qb64
        sith = '1'  # hex str of threshold int
        artHab = directing.Habitat(ks=artKS, db=artDB, isith=sith, icount=1,
                                   salt=salt, transferable=False, temp=True)
        assert artHab.ks == artKS
        assert artHab.db == artDB
        assert not artHab.kever.prefixer.transferable

        # first setup disjoint replay then conjoint replay
        # Create series of event for Deb
        debMsgs = bytearray()
        debMsgs.extend(debHab.makeOwnInception())
        debMsgs.extend(debHab.interact())
        debMsgs.extend(debHab.rotate())
        debMsgs.extend(debHab.interact())
        debMsgs.extend(debHab.interact())
        debMsgs.extend(debHab.interact())
        debMsgs.extend(debHab.interact())

        assert debMsgs == bytearray(b'{"v":"KERI10JSON000154_","i":"E4ReNhXtuh4DAKe4_qcX__uF70MnOvW5Wa'
                                    b'pj3LcQ8CT4","s":"0","t":"icp","kt":["1/2","1/2","1/2"],"k":["DaY'
                                    b'h8uaASuDjMUd8_BoNyQs3GwupzmJL8_RBsuNtZHQg","Duzj-Z2lR2DqB0cI0421'
                                    b'oSMUVWOrN5axojx8g9fSx3PM","DRXPAmNVVqafWvQiN5qQmWUDvVupF2w8xFNGg'
                                    b'1Gays9Y"],"n":"EO5f_IQjtBoeN_-OyzfVJx1_WqBFUL-Ely4x-xmUtOW8","wt'
                                    b'":"0","w":[],"c":[]}-AADAA6Z50BRlXby_uSdkqbybLXds-5OMwQil4miux1s'
                                    b'RxJkiD3kRS4HuCpv5m-wwsPHWwn_Ku5xB2P--NJ1pl7KXjAQABDjMdRtemkn9oyk'
                                    b'LFo9MBwZsS85hGd1yaMMdFb_P1FY8_PZcHBVTc2iF5Bd6T2rGorwS-ChRa24bxUr'
                                    b'kemWD1DAACpxUYq2zrFAlMdWuxdaYTqvh12pgk4Ba-vllsaZP5ct5HcOtJw47B6c'
                                    b'VLcEePwEHk6jHlSoDGgH2YiyOwPbgSBQ{"v":"KERI10JSON000098_","i":"E4'
                                    b'ReNhXtuh4DAKe4_qcX__uF70MnOvW5Wapj3LcQ8CT4","s":"1","t":"ixn","p'
                                    b'":"Egd_fi2QDtfjjdB5p9tT6QCHuBsSWUwQP6AbarcjLgw0","a":[]}-AADAAPL'
                                    b'MNHELcDDuPT1gyI9_TEBM6FRji2xmc0iBfNBwoKJttbJfeQhH41y-ayubtyhyMzH'
                                    b'aqrq-WXaNQkpnzTTOPBAABUawpt1Nd7GR9rTwPD4ucT-M7Vy1xuxGlgRf9pgkOcX'
                                    b'BBbhomjjEpz3aid9PP2vWeJ_rvw7W5rgrTJ38Q2v8bDwACoHNjlZ-IZ1K9opgeu3'
                                    b'3TNIFBd3rNW_gKO_bFa-t2GYwOzlWoDlzF7kSRQnVKlXMeVrLBe3uwO6PjYjeZdU'
                                    b'SlDg{"v":"KERI10JSON000190_","i":"E4ReNhXtuh4DAKe4_qcX__uF70MnOv'
                                    b'W5Wapj3LcQ8CT4","s":"2","t":"rot","p":"E8MU3qwR6gzbMUqEXh0CgG4k3'
                                    b'k4WKkk9hM0iaVeCmG7E","kt":["1/2","1/2","1/2"],"k":["DIsi8qYso1KM'
                                    b'mpLOGYty3NC2BAojZmUCfzR5_5oQRiso","DkdClpaWCAoCPBYgUmqP9gwAtsGq8'
                                    b'1yyPhGQKQ6-W_F0","DKDyq4QQYKnx9ircxeCvEcraI4HUSr_ytWPelDHAM98w"]'
                                    b',"n":"E1oOvJmwenmC4uHjX7qB40LGVbeZY5rYQeZ6IK5zmdmM","wt":"0","wr'
                                    b'":[],"wa":[],"a":[]}-AADAAr5HeTAGJ_WfIMO82lbEnpAMkuqZ0iJO0yYhjwv'
                                    b'LElPYltF_jSOApKPWxepare2O7XMMOvtgxjXj9pvvqpW8WDgABKHoueBd4JgakpV'
                                    b'ydJYADwh5wMSNyHNMKXwhYMGrgApl_EvsTmEt8uS94PmrfCtRjLRbZdzLRZVkX7Y'
                                    b'x4jlNNCgACjKJlODGhL_a0S3-oDRJhOUG0sul4SCJd21Qp-KSFSfGavACAwQdEYQ'
                                    b'L43jko9lFDuhwKDt1BD8kAoy3T-tdoAw{"v":"KERI10JSON000098_","i":"E4'
                                    b'ReNhXtuh4DAKe4_qcX__uF70MnOvW5Wapj3LcQ8CT4","s":"3","t":"ixn","p'
                                    b'":"EO2hh7xg29y3i7uywQ_n0g7vk0W1oGiErUY9QpGjSUhc","a":[]}-AADAA5I'
                                    b'ox67c4HL78UrYqpSNH-UkHZRpR7X0fPQ0GEYJG8OGqCHBvPJica_yohOQP8GNOFQ'
                                    b'9UsmBa0TDji6EAaXivBwAB6BgG2CQ-Ukw8CchtCHf9L5kVsmg1Tu2OuLkcy9Sb9u'
                                    b'Vm23yLx-8I4pc6KHmZke8KCvpXjcdV65gOOE-VUIMOBwACXtTZoFqJHFhoMZABun'
                                    b'XETksrK1nNiP9xzXx13gl4uqoVZkqfwqUTL3C7q0RcxYwaz5sYSNQA8zblA8YxVy'
                                    b'FuCQ{"v":"KERI10JSON000098_","i":"E4ReNhXtuh4DAKe4_qcX__uF70MnOv'
                                    b'W5Wapj3LcQ8CT4","s":"4","t":"ixn","p":"EQI0EXdK6WvQae17PBWDUkMOd'
                                    b'OiTPpx48oMSYTUYsCl0","a":[]}-AADAAbnPY1i0cpo6q0cmvQr2bZOcipzl7LY'
                                    b'Y2h-3ixndlzB3f-4VFLzSnIUtB_qwp1H2NI_DNGqXWGACywJoxkFccAQABHDicUl'
                                    b'iz3Bl6y1T7-sQteMKxoDYZ4A8hVx3p3EjztyO8UnA6PkaV2b7AFwAfk4UbBWKMGj'
                                    b'TtpZ88S7P9EsXLBAACNFFh6nDIWNG1ZbEsqqlCG2aKLgnpHmR6cJr1dq1F4pylAF'
                                    b'1e3-on2aasDMYk3c2fj-AWErRqbsf8ejnJE3YvDg{"v":"KERI10JSON000098_"'
                                    b',"i":"E4ReNhXtuh4DAKe4_qcX__uF70MnOvW5Wapj3LcQ8CT4","s":"5","t":'
                                    b'"ixn","p":"EvrAC5XVQyu01ZuKfq1wiR0kXF2j8TjrCg4QyA0LVjKk","a":[]}'
                                    b'-AADAA1OJn3UHjLcI333fduqTj6nAJY27VtkQqW_lHalnJKtgmb0tk1tV5xUCVzp'
                                    b'al14xWDuyCdImhFzTk0sRgW4MYDQABOR8ay9qQYR3ieant4ujM_FX0Nm_mUHcVVo'
                                    b'4pCqDy8jLaM3EBNmkOKUIfxgZC-8k6OpYcy33gC-qgUpc6C2_PDwACSoZSibaYci'
                                    b'n32vY4ANzflFpJh_EF7mcGbTWSFrNLnwFrrOfhXL3i1Pf39Sk079ApSI87Nt-CvH'
                                    b'pRRdows3TABQ{"v":"KERI10JSON000098_","i":"E4ReNhXtuh4DAKe4_qcX__'
                                    b'uF70MnOvW5Wapj3LcQ8CT4","s":"6","t":"ixn","p":"EwmQtlcszNoEIDfqD'
                                    b'-Zih3N6o5B3humRKvBBln2juTEM","a":[]}-AADAAvYMCRmJgjFM7EG7rWng7Q3'
                                    b'WRfwcd908UdKL-7ZfGw4igpF9DcA-yxwliba59D4pkmhIcrW_Ax76iuaD6yD03Bw'
                                    b'AB9Wp-awBUfw2jnDRjvEU3xpFlLDHwiFLRKpom8Wnx7qDD4aEv6ERZh-H8yP3eL4'
                                    b'sNEFjP5HcRrb5MpFwOp0VyAwACdedbq9E2Exs1NobGwSNQpNxKlgDPiNDE8nOeOq'
                                    b'gXt1rAj8SAh8gX2pOgEFj3g3UB69dNGw2M-bEZ557-p9G-Aw')


        # Play debMsgs to Cam
        # create non-local kevery for Cam to process msgs from Deb
        camKevery = eventing.Kevery(kevers=camHab.kevers,
                                    db=camHab.db,
                                    framed=True,
                                    opre=camHab.pre,
                                    local=False)
        camKevery.process(ims=bytearray(debMsgs))  # give copy to process
        assert debHab.pre in camKevery.kevers
        assert camKevery.kevers[debHab.pre].sn == debHab.kever.sn == 6
        assert len(camKevery.cues) == 7

        # get disjoints receipts (vrcs) from Cam of Deb's events by processing Cam's cues
        camMsgs = camHab.processCues(camKevery.cues)
        assert camMsgs == bytearray(b'{"v":"KERI10JSON000144_","i":"E_T2_p83_gRSuAYvGhqV3S0JzYEF2dIa-O'
                                    b'CPLbIhBO7Y","s":"0","t":"icp","kt":"2","k":["DaYh8uaASuDjMUd8_Bo'
                                    b'NyQs3GwupzmJL8_RBsuNtZHQg","Duzj-Z2lR2DqB0cI0421oSMUVWOrN5axojx8'
                                    b'g9fSx3PM","DRXPAmNVVqafWvQiN5qQmWUDvVupF2w8xFNGg1Gays9Y"],"n":"E'
                                    b'OySO3Oa400n3Ss9JftGYmgS5M4jgPInNnMntC_l-PEQ","wt":"0","w":[],"c"'
                                    b':[]}-AADAA5267UlFg1jHee4Dauht77SzGl8WUC_0oimYG5If3SdIOSzWM8Qs9SF'
                                    b'ajAilQcozXJVnbkY5stG_K4NbKdNB4AQABBgeqntZW3Gu4HL0h3odYz6LaZ_SMfm'
                                    b'ITL-Btoq_7OZFe3L16jmOe49Ur108wH7mnBaq2E_0U0N0c5vgrJtDpAQACTD7NDX'
                                    b'93ZGTkZBBuSeSGsAQ7u0hngpNTZTK_Um7rUZGnLRNJvo5oOnnC1J2iBQHuxoq8Py'
                                    b'jdT3BHS2LiPrs2Cg{"v":"KERI10JSON000105_","i":"E4ReNhXtuh4DAKe4_q'
                                    b'cX__uF70MnOvW5Wapj3LcQ8CT4","s":"0","t":"vrc","d":"Egd_fi2QDtfjj'
                                    b'dB5p9tT6QCHuBsSWUwQP6AbarcjLgw0","a":{"i":"E_T2_p83_gRSuAYvGhqV3'
                                    b'S0JzYEF2dIa-OCPLbIhBO7Y","s":"0","d":"EFSbLZkTmOMfRCyEYLgz53ARZo'
                                    b'ugmEu_edeW-0j2DVRY"}}-AADAA6Z50BRlXby_uSdkqbybLXds-5OMwQil4miux1'
                                    b'sRxJkiD3kRS4HuCpv5m-wwsPHWwn_Ku5xB2P--NJ1pl7KXjAQABDjMdRtemkn9oy'
                                    b'kLFo9MBwZsS85hGd1yaMMdFb_P1FY8_PZcHBVTc2iF5Bd6T2rGorwS-ChRa24bxU'
                                    b'rkemWD1DAACpxUYq2zrFAlMdWuxdaYTqvh12pgk4Ba-vllsaZP5ct5HcOtJw47B6'
                                    b'cVLcEePwEHk6jHlSoDGgH2YiyOwPbgSBQ{"v":"KERI10JSON000105_","i":"E'
                                    b'4ReNhXtuh4DAKe4_qcX__uF70MnOvW5Wapj3LcQ8CT4","s":"1","t":"vrc","'
                                    b'd":"E8MU3qwR6gzbMUqEXh0CgG4k3k4WKkk9hM0iaVeCmG7E","a":{"i":"E_T2'
                                    b'_p83_gRSuAYvGhqV3S0JzYEF2dIa-OCPLbIhBO7Y","s":"0","d":"EFSbLZkTm'
                                    b'OMfRCyEYLgz53ARZougmEu_edeW-0j2DVRY"}}-AADAAPLMNHELcDDuPT1gyI9_T'
                                    b'EBM6FRji2xmc0iBfNBwoKJttbJfeQhH41y-ayubtyhyMzHaqrq-WXaNQkpnzTTOP'
                                    b'BAABUawpt1Nd7GR9rTwPD4ucT-M7Vy1xuxGlgRf9pgkOcXBBbhomjjEpz3aid9PP'
                                    b'2vWeJ_rvw7W5rgrTJ38Q2v8bDwACoHNjlZ-IZ1K9opgeu33TNIFBd3rNW_gKO_bF'
                                    b'a-t2GYwOzlWoDlzF7kSRQnVKlXMeVrLBe3uwO6PjYjeZdUSlDg{"v":"KERI10JS'
                                    b'ON000105_","i":"E4ReNhXtuh4DAKe4_qcX__uF70MnOvW5Wapj3LcQ8CT4","s'
                                    b'":"2","t":"vrc","d":"EO2hh7xg29y3i7uywQ_n0g7vk0W1oGiErUY9QpGjSUh'
                                    b'c","a":{"i":"E_T2_p83_gRSuAYvGhqV3S0JzYEF2dIa-OCPLbIhBO7Y","s":"'
                                    b'0","d":"EFSbLZkTmOMfRCyEYLgz53ARZougmEu_edeW-0j2DVRY"}}-AADAA7JJ'
                                    b'AxJL3nhVur7YboCK2zPSmx_AaYDYeN7UsvoKcZKrYbuScUje_qfx_e9z1SM4tm8b'
                                    b'UbYJnLXTz8dOta9ZiDwABi7dsjnldn7E-L56Rlz4ZWp8XC5y8v7h4XRoZp2sO69H'
                                    b'84dhyRM27UE9_egCWQZJ_MHJKVA5g2s0hXmXvjSKrAQACo0JcZmUhiNBfb_3bBwg'
                                    b'X7KfN52vmazAzEFgJlr8wNfXSvF6rA5lED4J1EWuEnhA00vUHQqPrjk78nnRBBZl'
                                    b'VAA{"v":"KERI10JSON000105_","i":"E4ReNhXtuh4DAKe4_qcX__uF70MnOvW'
                                    b'5Wapj3LcQ8CT4","s":"3","t":"vrc","d":"EQI0EXdK6WvQae17PBWDUkMOdO'
                                    b'iTPpx48oMSYTUYsCl0","a":{"i":"E_T2_p83_gRSuAYvGhqV3S0JzYEF2dIa-O'
                                    b'CPLbIhBO7Y","s":"0","d":"EFSbLZkTmOMfRCyEYLgz53ARZougmEu_edeW-0j'
                                    b'2DVRY"}}-AADAAG1L04T2jREp2pizW-jQ0tglZ8I4CDNoKx4bN2K0ztuf_0ywQ29'
                                    b'p2kFkBVZaRPwljOZlUzJqlPU6P2R-IVORJBQAB2ss-isfVr2WpdCWwNxO_9N75eJ'
                                    b'K-2CZp1J-DicWd8FqziZIc-kAmxNBD9TjxfuYn7pQmXnaWF7g4RhCLJGBuDAACrx'
                                    b'gx3QlrBs-g369i807ntd8rGWGC4WGrrdy60cPy9hjrP10qjDtSTwa2UZPNVEUZol'
                                    b'M-lHsFqoNhjeaHmg_mDA{"v":"KERI10JSON000105_","i":"E4ReNhXtuh4DAK'
                                    b'e4_qcX__uF70MnOvW5Wapj3LcQ8CT4","s":"4","t":"vrc","d":"EvrAC5XVQ'
                                    b'yu01ZuKfq1wiR0kXF2j8TjrCg4QyA0LVjKk","a":{"i":"E_T2_p83_gRSuAYvG'
                                    b'hqV3S0JzYEF2dIa-OCPLbIhBO7Y","s":"0","d":"EFSbLZkTmOMfRCyEYLgz53'
                                    b'ARZougmEu_edeW-0j2DVRY"}}-AADAAh0E0mltmkUz1_TXMirWFa67IGAaK7fThh'
                                    b'rJ8TQyuhY7usunzf8VtWfaaLBQSpofhgppsMlf3zZxDS1g6t-7PCgABECiScuPby'
                                    b'_LbGw5s6qNTJQm2m6Dqbsig7sRdk841XWU6hV3MlD-k_SriiPEJWMAWDmY74lM-U'
                                    b'iNDvnmN4OAJCAACSc48sfSvNtYByMlUQsMPdEsDw5Z6oDX4jlZ9F5eCMcRvYWWAp'
                                    b'AD-OOi85JTIiW3y3nSdbfyt4vS6YvroA68MAQ{"v":"KERI10JSON000105_","i'
                                    b'":"E4ReNhXtuh4DAKe4_qcX__uF70MnOvW5Wapj3LcQ8CT4","s":"5","t":"vr'
                                    b'c","d":"EwmQtlcszNoEIDfqD-Zih3N6o5B3humRKvBBln2juTEM","a":{"i":"'
                                    b'E_T2_p83_gRSuAYvGhqV3S0JzYEF2dIa-OCPLbIhBO7Y","s":"0","d":"EFSbL'
                                    b'ZkTmOMfRCyEYLgz53ARZougmEu_edeW-0j2DVRY"}}-AADAAgXtG2I3AxvU5yHKz'
                                    b'fucOKOvxeKWwChKQvEQJtJnz9iIpsXqyyrgRfOyoyjhk73D-E3FbDg_3k1XK_3i-'
                                    b'yDWeAQAByUVjq4Y_sMWi9iqqWXTo2ES5pBMlBgJbAY3h61aJElQdCIxr2ldx_BSq'
                                    b'4vA-FlELEBUkSbeHnHGXeFfVi6AjCwAC6GmjxPFclVsY7smEcpmptQnZgET9LUO6'
                                    b'06SzhkCaGCe1jR2KZ3vNsgitA_7OQ_VDipLwoWGv_Kz2YnUkjKFsCw{"v":"KERI'
                                    b'10JSON000105_","i":"E4ReNhXtuh4DAKe4_qcX__uF70MnOvW5Wapj3LcQ8CT4'
                                    b'","s":"6","t":"vrc","d":"EvFMG33kYq7JGOY1fWl1_VqfAe0MfPO3IhasTID'
                                    b'kayaY","a":{"i":"E_T2_p83_gRSuAYvGhqV3S0JzYEF2dIa-OCPLbIhBO7Y","'
                                    b's":"0","d":"EFSbLZkTmOMfRCyEYLgz53ARZougmEu_edeW-0j2DVRY"}}-AADA'
                                    b'A9U_Kq0GNM1fFq1Vgp937kHkwxSBn4nT8UciTepjjOdOAR-hvsLCxQx2V2pbyQo3'
                                    b'fubs6mPd6TQ4ZUmXNrtxmBwABuFO678xi0JuYyQWnSOtOVXABknvRo6-0EWFCv7h'
                                    b'xucmqgE6Je2R4120G3nFsJ_ImTjkDibQU8m7CYBGcFh-hAQACBUqcpzMYX373ePK'
                                    b'sfKBjt9aXO2vkl9jAb5vBHFYc0h5r-pGL2TIgoyfMPMAf0zFrsKnDdmN0HmSaE1O'
                                    b'sP2hmDA')

        # Play camMsgs to Deb
        # create non-local kevery for Deb to process msgs from Cam
        debKevery = eventing.Kevery(kevers=debHab.kevers,
                                    db=debHab.db,
                                    framed=True,
                                    opre=debHab.pre,
                                    local=False)
        debKevery.process(ims=bytearray(camMsgs))  # give copy to process
        assert camHab.pre in debKevery.kevers
        assert debKevery.kevers[camHab.pre].sn == camHab.kever.sn == 0
        assert len(debKevery.cues) == 1

        # get disjoints receipts (vrcs) from Deb of Cam's events by processing Deb's cues
        debCamVrcs = debHab.processCues(debKevery.cues)
        assert debCamVrcs == bytearray(b'{"v":"KERI10JSON000105_","i":"E_T2_p83_gRSuAYvGhqV3S0JzYEF2dIa-O'
                                    b'CPLbIhBO7Y","s":"0","t":"vrc","d":"EFSbLZkTmOMfRCyEYLgz53ARZougm'
                                    b'Eu_edeW-0j2DVRY","a":{"i":"E4ReNhXtuh4DAKe4_qcX__uF70MnOvW5Wapj3'
                                    b'LcQ8CT4","s":"2","d":"EO2hh7xg29y3i7uywQ_n0g7vk0W1oGiErUY9QpGjSU'
                                    b'hc"}}-AADAAmZij1Eyp2LOvVf0EevWsIIUiE9OEbhV5MvWvGHWzlvmzoaJ71KxSL'
                                    b'dMkqWG6yPyBLJjVNds_SQVVFnbpoPKwAAABNLo-_rnW2tfAu9GaP6XS2lyHTLUkG'
                                    b'TGKwjBA6hepC-E8XEiFMQekheKx-ir6xWxRPF9vBZuWwZKIqtwR2EwcDwACeHbCs'
                                    b'HbSgD7m9bWGB2ZCN8jxAfrbCMRGWersAEXqtdtkYT0Xxg33W61o5IffZjWxsHY_i'
                                    b'JQOPDVF3tA4DniWBg')

        # Play disjoints debCamVrcs to Cam
        camKevery.processOne(ims=bytearray(debCamVrcs))  # give copy to process

        # Play debMsgs to Bev
        # create non-local kevery for Bev to process msgs from Deb
        bevKevery = eventing.Kevery(kevers=bevHab.kevers,
                                    db=bevHab.db,
                                    framed=True,
                                    opre=bevHab.pre,
                                    local=False)
        bevKevery.process(ims=bytearray(debMsgs))  # give copy to process
        assert debHab.pre in bevKevery.kevers
        assert bevKevery.kevers[debHab.pre].sn == debHab.kever.sn == 6
        assert len(bevKevery.cues) == 7

        # get disjoints receipts (rcts) from Bev of Deb's events by processing Bevs's cues
        bevMsgs = bevHab.processCues(bevKevery.cues)
        assert bevMsgs == bytearray(b'{"v":"KERI10JSON0000ba_","i":"BaYh8uaASuDjMUd8_BoNyQs3GwupzmJL8_'
                                    b'RBsuNtZHQg","s":"0","t":"icp","kt":"1","k":["BaYh8uaASuDjMUd8_Bo'
                                    b'NyQs3GwupzmJL8_RBsuNtZHQg"],"n":"","wt":"0","w":[],"c":[]}-AABAA'
                                    b'dRmfIn6JHxhpyooEf22kqZxsa4OTpl9DVL6GDWNWlyk-MGQeo2pU5mI288Jl8SwP'
                                    b'PbTGbdeKdWUfG15bjil8AA{"v":"KERI10JSON000091_","i":"E4ReNhXtuh4D'
                                    b'AKe4_qcX__uF70MnOvW5Wapj3LcQ8CT4","s":"0","t":"rct","d":"Egd_fi2'
                                    b'QDtfjjdB5p9tT6QCHuBsSWUwQP6AbarcjLgw0"}-CABBaYh8uaASuDjMUd8_BoNy'
                                    b'Qs3GwupzmJL8_RBsuNtZHQg0B6Z50BRlXby_uSdkqbybLXds-5OMwQil4miux1sR'
                                    b'xJkiD3kRS4HuCpv5m-wwsPHWwn_Ku5xB2P--NJ1pl7KXjAQ{"v":"KERI10JSON0'
                                    b'00091_","i":"E4ReNhXtuh4DAKe4_qcX__uF70MnOvW5Wapj3LcQ8CT4","s":"'
                                    b'1","t":"rct","d":"E8MU3qwR6gzbMUqEXh0CgG4k3k4WKkk9hM0iaVeCmG7E"}'
                                    b'-CABBaYh8uaASuDjMUd8_BoNyQs3GwupzmJL8_RBsuNtZHQg0BPLMNHELcDDuPT1'
                                    b'gyI9_TEBM6FRji2xmc0iBfNBwoKJttbJfeQhH41y-ayubtyhyMzHaqrq-WXaNQkp'
                                    b'nzTTOPBA{"v":"KERI10JSON000091_","i":"E4ReNhXtuh4DAKe4_qcX__uF70'
                                    b'MnOvW5Wapj3LcQ8CT4","s":"2","t":"rct","d":"EO2hh7xg29y3i7uywQ_n0'
                                    b'g7vk0W1oGiErUY9QpGjSUhc"}-CABBaYh8uaASuDjMUd8_BoNyQs3GwupzmJL8_R'
                                    b'BsuNtZHQg0B7JJAxJL3nhVur7YboCK2zPSmx_AaYDYeN7UsvoKcZKrYbuScUje_q'
                                    b'fx_e9z1SM4tm8bUbYJnLXTz8dOta9ZiDw{"v":"KERI10JSON000091_","i":"E'
                                    b'4ReNhXtuh4DAKe4_qcX__uF70MnOvW5Wapj3LcQ8CT4","s":"3","t":"rct","'
                                    b'd":"EQI0EXdK6WvQae17PBWDUkMOdOiTPpx48oMSYTUYsCl0"}-CABBaYh8uaASu'
                                    b'DjMUd8_BoNyQs3GwupzmJL8_RBsuNtZHQg0BG1L04T2jREp2pizW-jQ0tglZ8I4C'
                                    b'DNoKx4bN2K0ztuf_0ywQ29p2kFkBVZaRPwljOZlUzJqlPU6P2R-IVORJBQ{"v":"'
                                    b'KERI10JSON000091_","i":"E4ReNhXtuh4DAKe4_qcX__uF70MnOvW5Wapj3LcQ'
                                    b'8CT4","s":"4","t":"rct","d":"EvrAC5XVQyu01ZuKfq1wiR0kXF2j8TjrCg4'
                                    b'QyA0LVjKk"}-CABBaYh8uaASuDjMUd8_BoNyQs3GwupzmJL8_RBsuNtZHQg0Bh0E'
                                    b'0mltmkUz1_TXMirWFa67IGAaK7fThhrJ8TQyuhY7usunzf8VtWfaaLBQSpofhgpp'
                                    b'sMlf3zZxDS1g6t-7PCg{"v":"KERI10JSON000091_","i":"E4ReNhXtuh4DAKe'
                                    b'4_qcX__uF70MnOvW5Wapj3LcQ8CT4","s":"5","t":"rct","d":"EwmQtlcszN'
                                    b'oEIDfqD-Zih3N6o5B3humRKvBBln2juTEM"}-CABBaYh8uaASuDjMUd8_BoNyQs3'
                                    b'GwupzmJL8_RBsuNtZHQg0BgXtG2I3AxvU5yHKzfucOKOvxeKWwChKQvEQJtJnz9i'
                                    b'IpsXqyyrgRfOyoyjhk73D-E3FbDg_3k1XK_3i-yDWeAQ{"v":"KERI10JSON0000'
                                    b'91_","i":"E4ReNhXtuh4DAKe4_qcX__uF70MnOvW5Wapj3LcQ8CT4","s":"6",'
                                    b'"t":"rct","d":"EvFMG33kYq7JGOY1fWl1_VqfAe0MfPO3IhasTIDkayaY"}-CA'
                                    b'BBaYh8uaASuDjMUd8_BoNyQs3GwupzmJL8_RBsuNtZHQg0B9U_Kq0GNM1fFq1Vgp'
                                    b'937kHkwxSBn4nT8UciTepjjOdOAR-hvsLCxQx2V2pbyQo3fubs6mPd6TQ4ZUmXNr'
                                    b'txmBw')

        # Play bevMsgs to Deb
        debKevery.process(ims=bytearray(bevMsgs))  # give copy to process
        assert bevHab.pre in debKevery.kevers
        assert debKevery.kevers[bevHab.pre].sn == bevHab.kever.sn == 0
        assert len(debKevery.cues) == 1

        # get disjoints receipts (vrcs) from Deb of Bev's events by processing Deb's cues
        debBevVrcs = debHab.processCues(debKevery.cues)
        assert debBevVrcs == bytearray(b'{"v":"KERI10JSON000105_","i":"BaYh8uaASuDjMUd8_BoNyQs3GwupzmJL8_'
                                        b'RBsuNtZHQg","s":"0","t":"vrc","d":"EtTEz3ofbRmq4qeoKSc5uYWUhxeZa'
                                        b'8OjmCkZnesb0gws","a":{"i":"E4ReNhXtuh4DAKe4_qcX__uF70MnOvW5Wapj3'
                                        b'LcQ8CT4","s":"2","d":"EO2hh7xg29y3i7uywQ_n0g7vk0W1oGiErUY9QpGjSU'
                                        b'hc"}}-AADAAk0o2XsjZ8tfbaCKZZcSvmYdUxmqWMVMH1PLD6081VC04_c_nIXHfy'
                                        b'G5gRVXDsoncZk7euiZ9Q60E7rGi-FOLBQAB6xngS-To8PAVjMSz0bv4oqju1vmke'
                                        b'Hwq7EQOWMvM5WeKzLOwpgnCxCyZkYCzXU6Yyym9_TJOxL144wRVS92sAQACSG9_s'
                                        b'dTl_1t_bFi-fnkBwX7QLvB53NDNQShHwUjdvxupDMUJkx6QLwsUH_SwybCFO0rX5'
                                        b'K5TQKbTKbQ9F9TcAg')


        # Play disjoints debBevVrcs to Bev
        bevKevery.processOne(ims=bytearray(debBevVrcs))  # give copy to process

        # now setup conjoint replay

        # Replay Deb's First Seen Events with receipts (vrcs and rcts) from both Cam and Bev
        # datetime is different in each run in the fse attachment in clone replay
        # so we either have to force dts in db or we parse in pieces
        debFelMsgs = bytearray()
        fn = 0
        cloner = debHab.db.cloneIter(pre=debHab.pre, fn=fn)  # create iterator
        msg = next(cloner)  # get zeroth event with attachments
        assert len(msg) == 1416
        debFelMsgs.extend(msg)

        # parse msg
        serder = coring.Serder(raw=msg)
        assert serder.raw == debHab.iserder.raw
        assert serder.sn == fn  # no recovery forks so sn == fn
        assert serder.ked["t"] == coring.Ilks.icp
        del msg[:len(serder.raw)]
        assert len(msg) == 1076

        counter = coring.Counter(qb64b=msg)  # attachment length quadlets counter
        assert counter.code == coring.CtrDex.AttachedMaterialQuadlets
        assert counter.count == (len(msg) - len(counter.qb64b)) // 4 ==  268
        del msg[:len(counter.qb64b)]
        assert len(msg) == 1072 == 268 *  4

        counter = coring.Counter(qb64b=msg)  # indexed signatures counter
        assert counter.code == coring.CtrDex.ControllerIdxSigs
        assert counter.count == 3  #  multisig deb
        del msg[:len(counter.qb64b)]
        assert len(msg) == 1068

        for i in range(counter.count):  # parse signatures
            siger = coring.Siger(qb64b=msg)
            del msg[:len(siger.qb64b)]
        assert len(msg) == 1068 - 3 * len(siger.qb64b) == 804

        counter = coring.Counter(qb64b=msg)  # trans receipt (vrc) counter
        assert counter.code == coring.CtrDex.TransReceiptQuadruples
        assert counter.count == 3  #  multisig cam
        del msg[:len(counter.qb64b)]
        assert len(msg) == 800

        for i in range(counter.count):  # parse receipt quadruples
            prefixer, seqner, diger, siger = eventing.deTransReceiptQuadruple(msg, strip=True)
        assert len(msg) == 800 - 3 * (len(prefixer.qb64b) + len(seqner.qb64b) +
                                len(diger.qb64b) + len(siger.qb64b)) == 200

        counter = coring.Counter(qb64b=msg)  # nontrans receipt (rct) counter
        assert counter.code == coring.CtrDex.NonTransReceiptCouples
        assert counter.count == 1  #  single sig bev
        del msg[:len(counter.qb64b)]
        assert len(msg) == 196

        for i in range(counter.count):  # parse receipt couples
            prefixer, cigar = eventing.deReceiptCouple(msg, strip=True)
        assert len(msg) == 196 - 1 * (len(prefixer.qb64b) + len(cigar.qb64b)) == 64

        counter = coring.Counter(qb64b=msg)  # first seen replay couple counter
        assert counter.code == coring.CtrDex.FirstSeenReplayCouples
        assert counter.count == 1
        del msg[:len(counter.qb64b)]
        assert len(msg) == 60

        seqner = coring.Seqner(qb64b=msg)
        assert seqner.sn == fn == 0
        del msg[:len(seqner.qb64b)]
        assert len(msg) == 36  # 24 less

        dater = coring.Dater(qb64b=msg)
        assert (helping.fromIso8601(helping.nowIso8601()) -
                helping.fromIso8601(dater.dts)) > datetime.timedelta()
        del msg[:len(dater.qb64b)]
        assert len(msg) == 0  # 36 less

        cloner.close()  # must close or get lmdb error upon with exit
        """Exception ignored in: <generator object LMDBer.getAllOrdItemPreIter at 0x106fe1c10>
        Traceback (most recent call last):
        File "/Users/Load/Data/Code/public/keripy/src/keri/db/dbing.py", line 512, in getAllOrdItemPreIter
        yield (cn, bytes(val))  # (on, dig) of event
        lmdb.Error: Attempt to operate on closed/deleted/dropped object.
        """

        fn += 1
        cloner = debHab.db.cloneIter(pre=debHab.pre, fn=fn)  # create iterator not at 0
        msg = next(cloner)  # next event with attachments
        assert len(msg) == 1228
        serder = coring.Serder(raw=msg)
        assert serder.sn == fn  # no recovery forks so sn == fn
        assert serder.ked["t"] == coring.Ilks.ixn
        debFelMsgs.extend(msg)

        fn += 1
        msg = next(cloner)  # get zeroth event with attachments
        serder = coring.Serder(raw=msg)
        assert serder.sn == fn  # no recovery forks so sn == fn
        assert serder.ked["t"] == coring.Ilks.rot
        assert len(msg) == 1476
        assert ([verfer.qb64 for verfer in serder.verfers] ==
                [verfer.qb64 for verfer in debHab.kever.verfers])
        debFelMsgs.extend(msg)

        fn += 1
        while (fn <= 6 ):
            msg = next(cloner)  # get zeroth event with attachments
            serder = coring.Serder(raw=msg)
            assert serder.sn == fn  # no recovery forks so sn == fn
            assert serder.ked["t"] == coring.Ilks.ixn
            assert len(msg) == 1228
            debFelMsgs.extend(msg)
            fn += 1

        assert len(debFelMsgs) == 9032
        cloner.close()  # must close or get lmdb error upon with exit

        msgs = debHab.replay()
        assert msgs == debFelMsgs

        # Play Cam's messages to Bev
        bevKevery.process(ims=bytearray(camMsgs))  # give copy to process
        assert camHab.pre in bevKevery.kevers
        assert bevKevery.kevers[camHab.pre].sn == camHab.kever.sn == 0
        assert len(bevKevery.cues) == 1

        # Play Bev's messages to Cam
        camKevery.process(ims=bytearray(bevMsgs))  # give copy to process
        assert bevHab.pre in camKevery.kevers
        assert camKevery.kevers[bevHab.pre].sn == bevHab.kever.sn == 0
        assert len(camKevery.cues) == 1

        camDebFelMsgs = camHab.replay(pre=debHab.pre)
        bevDebFelMsgs = bevHab.replay(pre=debHab.pre)

        assert len(bevDebFelMsgs) == len(camDebFelMsgs) == len(debFelMsgs) == 9032

        # create non-local kevery for Art to process conjoint replay msgs from Deb
        artKevery = eventing.Kevery(kevers=artHab.kevers,
                                        db=artHab.db,
                                        framed=True,
                                        opre=artHab.pre,
                                        local=False)
        # process Cam's inception so Art will proces Cam's vrcs without escrowing
        camIcpMsg = camHab.makeOwnInception()
        artKevery.process(ims=bytearray(camIcpMsg))
        assert camHab.pre in artKevery.kevers
        assert len(artKevery.cues) == 1

        artKevery.process(ims=bytearray(debFelMsgs), cloned=True)  # give copy to process
        assert debHab.pre in artKevery.kevers
        assert artKevery.kevers[debHab.pre].sn == debHab.kever.sn == 6
        assert len(artKevery.cues) == 8
        artDebFelMsgs = artHab.replay(pre=debHab.pre)
        assert len(artDebFelMsgs) == 9032


    assert not os.path.exists(artKS.path)
    assert not os.path.exists(artDB.path)
    assert not os.path.exists(bevKS.path)
    assert not os.path.exists(bevDB.path)
    assert not os.path.exists(camKS.path)
    assert not os.path.exists(camDB.path)
    assert not os.path.exists(debKS.path)
    assert not os.path.exists(debDB.path)

    """End Test"""
def test_weighted():
    """
    Test multisig with weighted threshold

    """
    wesSalt = coring.Salter(raw=b'0123456789abcdef').qb64  # init wes Salter

    # init event DB and keep DB
    with dbing.openDB(name="wes") as wesDB, keeping.openKS(
            name="wes") as wesKS:
        # Init key pair manager
        wesMgr = keeping.Manager(keeper=wesKS, salt=wesSalt)

        # Init Kevery with event DB
        wesKvy = eventing.Kevery(db=wesDB)

        # create inception event for Wes with 3 keys each in incept and next sets
        # defaults are algo salty and rooted
        sith = ["1/2", "1/2", "1/2"]  #  2 of 3 but with weighted threshold
        nxtsith = ["1/2", "1/2", "1/2"]
        verfers, digers, cst, nst = wesMgr.incept(icount=3,
                                                  isith=sith,
                                                  ncount=3,
                                                  nsith=nxtsith,
                                                  stem='wes',
                                                  temp=True)
        assert cst == nst == sith

        wesSrdr = eventing.incept(
            keys=[verfer.qb64 for verfer in verfers],
            sith=sith,
            nxt=coring.Nexter(sith=nxtsith,
                              digs=[diger.qb64 for diger in digers]).qb64,
            code=coring.MtrDex.Blake3_256)

        wesPre = wesSrdr.ked["i"]

        wesMgr.move(old=verfers[0].qb64,
                    new=wesPre)  # move key pair label to prefix

        sigers = wesMgr.sign(ser=wesSrdr.raw, verfers=verfers)

        msg = bytearray(wesSrdr.raw)
        counter = coring.Counter(coring.CtrDex.ControllerIdxSigs,
                                 count=len(sigers))
        msg.extend(counter.qb64b)
        for siger in sigers:
            msg.extend(siger.qb64b)

        assert msg == bytearray(
            b'{"v":"KERI10JSON000154_","i":"EM8ac0UPJZCaWOw2uRcvx6FaygyxFvGzA5'
            b'MTob9WfbDQ","s":"0","t":"icp","kt":["1/2","1/2","1/2"],"k":["DK4'
            b'OJI8JOr6oEEUMeSF_X-SbKysfwpKwW-ho5KARvH5c","D1RZLgYke0GmfZm-CH8A'
            b'sW4HoTU4m-2mFgu8kbwp8jQU","DBVwzum-jPfuUXUcHEWdplB4YcoL3BWGXK0TM'
            b'oF_NeFU"],"n":"EhJGhyJQTpSlZ9oWfQT-lHNl1woMazLC42O89fRHocTI","wt'
            b'":"0","w":[],"c":[]}-AADAAc4jIKyjjpK7rJzywkX2AXXaNGgUGfcUgT6fm7P'
            b'iqL8H8tDsxHb6dcnybE7Hc34jtUq47OWWwCV3K9oCTUUAHAwABlP9qpCcMow8Lq5'
            b'bzE-DLHlItNuQYD9SqOQDNyJoTpk_BEW6Q8UIG012MJEM7GoFTMV5H9UUztQfSQp'
            b'l9Jh9lBQACVn_l3CTPIrCyGZpvW9qxVfZll0su-vIv1gvx0GQfo1qAMNk4c_7t-x'
            b'bXKTw3hwDPt46m5zGd38Y3qIEwQD3jCA')

        # apply msg to Wes's Kevery
        wesKvy.process(ims=bytearray(msg))  # process local copy of msg
        wesK = wesKvy.kevers[wesPre]  # kever created so event was validated
        assert wesK.prefixer.qb64 == wesPre
        assert wesK.serder.diger.qb64 == wesSrdr.dig  # key state updated so event was validated

        # create interaction event for Wes
        wesSrdr = eventing.interact(pre=wesK.prefixer.qb64,
                                    dig=wesK.serder.diger.qb64,
                                    sn=wesK.sn + 1,
                                    data=[])

        sigers = wesMgr.sign(ser=wesSrdr.raw, verfers=wesK.verfers)

        msg = bytearray(wesSrdr.raw)
        counter = coring.Counter(coring.CtrDex.ControllerIdxSigs,
                                 count=len(sigers))
        msg.extend(counter.qb64b)
        for siger in sigers:
            msg.extend(siger.qb64b)

        assert msg == bytearray(
            b'{"v":"KERI10JSON000098_","i":"EM8ac0UPJZCaWOw2uRcvx6FaygyxFvGzA5'
            b'MTob9WfbDQ","s":"1","t":"ixn","p":"E3-lhMd85oc8Uwrd_7c6xUy5tvZhr'
            b'b9ZHvcOO4HxHB1c","a":[]}-AADAAWmzu83wDFTn9Hc6_xskGe8Ed_PhiOpVQ2H'
            b'kxAx28qgLP_Zz7pwCsvmRDM1x9sL8Ygg7hQman5qDaeJS4fJm1DQABlc4hfziecy'
            b'_DXVN2a8AttmuBL_Oh0-Ro_Rz3Mf6KWOJTMLQIHaRJ62L01Q5vP6KmiSr2zwJUT_'
            b'urfGLZoaRUBwACt4l7pTFqmzfzk6p6FKlT1KGXYJ2ea2SmU7I-7agz0i4lCDNQf-'
            b'Y_NJWs6NTWEs5vsPOskNcGnr8nIpQ51N1qBQ')

        # apply msg to wes's Kevery
        wesKvy.process(ims=bytearray(msg))  # process local copy of msg
        assert wesK.serder.diger.qb64 == wesSrdr.dig  # key state updated so event was validated

        # Create rotation event for Wes
        # get current keys as verfers and next digests as digers
        nxtsith = ["1/2", "1/2", "1/2"]  #  2 of 3 but with weighted threshold
        verfers, digers, cst, nst = wesMgr.rotate(pre=wesPre,
                                                  count=3,
                                                  sith=nxtsith,
                                                  temp=True)
        assert nst == nxtsith

        wesSrdr = eventing.rotate(
            pre=wesK.prefixer.qb64,
            keys=[verfer.qb64 for verfer in verfers],
            sith=sith,
            dig=wesK.serder.diger.qb64,
            nxt=coring.Nexter(sith=nxtsith,
                              digs=[diger.qb64 for diger in digers]).qb64,
            sn=wesK.sn + 1,
            data=[])

        sigers = wesMgr.sign(ser=wesSrdr.raw, verfers=verfers)

        msg = bytearray(wesSrdr.raw)
        counter = coring.Counter(coring.CtrDex.ControllerIdxSigs,
                                 count=len(sigers))
        msg.extend(counter.qb64b)
        for siger in sigers:
            msg.extend(siger.qb64b)

        assert msg == bytearray(
            b'{"v":"KERI10JSON000190_","i":"EM8ac0UPJZCaWOw2uRcvx6FaygyxFvGzA5'
            b'MTob9WfbDQ","s":"2","t":"rot","p":"E6wjlP_oqJzmo65d56XuTL602ABcK'
            b'X0ZBEy9M-k7E1Eg","kt":["1/2","1/2","1/2"],"k":["DeonYM2bKnAwp6VZ'
            b'cuCXdX72kNFw56czlZ_Tc7XHHVGI","DQghKIy-2do9OkweSgazh3Ql1vCOt5bnc'
            b'5QF8x50tRoU","DNAUn-5dxm6b8Njo01O0jlStMRCjo9FYQA2mfqFW1_JA"],"n"'
            b':"EX5fxvjOg5VuDboWbqnTjTPpXa3nNIm99hlsB1EmhTo8","wt":"0","wr":[]'
            b',"wa":[],"a":[]}-AADAApZ3U4zacSPm5embDTRD2IxB1e4FrdAToP-tsXB-VVp'
            b'fX6Yk78iIdFyeNi9U_sgefzvhR3_mH5Bj_ZlfpEMCQDAABWURvCkE1HjbE_noEqj'
            b'BWEpdG1hUfP3_Oye5Ys0zquigDrOSv2ApXzlq1-ALDTZeqMX4lbVlqubRjDu3Qog'
            b'xrAgACtyNpfXHvly2emXyAdJ5sAVUVCnodONK2CG8WGipISYLGIlyfmNoTVeHw-f'
            b'_3ZY2tAgbmLZika4kEL8REfr5VCA')

        # apply msg to Wes's Kevery
        wesKvy.process(ims=bytearray(msg))  # process local copy of msg
        assert wesK.serder.diger.qb64 == wesSrdr.dig  # key state updated so event was validated

        # Create rotation event for Wes
        # get current keys as verfers and next digests as digers
        sith = nxtsith  # rotate so nxtsith is now current sith and need new nextsith
        #  2 of first 3 and 1 of last 2
        nxtsith = [["1/2", "1/2", "1/2"], ["1/1", "1/1"]]
        verfers, digers, cst, nst = wesMgr.rotate(pre=wesPre,
                                                  count=5,
                                                  sith=nxtsith,
                                                  temp=True)
        assert cst == sith
        assert nst == nxtsith

        wesSrdr = eventing.rotate(
            pre=wesK.prefixer.qb64,
            keys=[verfer.qb64 for verfer in verfers],
            sith=sith,
            dig=wesK.serder.diger.qb64,
            nxt=coring.Nexter(sith=nxtsith,
                              digs=[diger.qb64 for diger in digers]).qb64,
            sn=wesK.sn + 1,
            data=[])

        sigers = wesMgr.sign(ser=wesSrdr.raw, verfers=verfers)

        msg = bytearray(wesSrdr.raw)
        counter = coring.Counter(coring.CtrDex.ControllerIdxSigs,
                                 count=len(sigers))
        msg.extend(counter.qb64b)
        for siger in sigers:
            msg.extend(siger.qb64b)

        assert msg == bytearray(
            b'{"v":"KERI10JSON000190_","i":"EM8ac0UPJZCaWOw2uRcvx6FaygyxFvGzA5'
            b'MTob9WfbDQ","s":"3","t":"rot","p":"E9tuWqXCN31LqElTSdfGp3lWDetle'
            b'T4Pa9tuSUi2V87k","kt":["1/2","1/2","1/2"],"k":["D7WWKDLVwYxYMLAj'
            b'DceIEs66xPMY4Afzx-RQw2x0mQzI","Dmg6Aah8qyKKDiQyNXTiO71QJwizjZfGM'
            b'61BA-s0A5F4","DS3fhKpvPCDL5WmfN4_PkmJMMsSCdRTxG24OQuf_EmHQ"],"n"'
            b':"EcM4iw7fElXWhad8V-za4Px7nBKjndxoh3XZRkohghKY","wt":"0","wr":[]'
            b',"wa":[],"a":[]}-AADAAO0Ma_uiLbrXrqkNsLccCNgWcfvopoo2NwZ5aJLKBa9'
            b'7OMuZibsiVL6bDues9r65o2Tq1hzuuQQK6cHg_OH3xDAAB-cLMTqhogxrxyhMVoP'
            b'RXJ-rtQaV5oEsXSqcU3phI0bxFJvtydfnySe30LXbOwnFS-_HhCRMOulhBdcAvFR'
            b'dKAAACXhumJPsAS1UWSjlKiSby_TCC_W82jkTcvWBB4pwrcYmno8jRpQoB0ubPyG'
            b'96I2RqNql0Q9p5LcMPsLtT_Zt4DA')

        # apply msg to Wes's Kevery
        wesKvy.process(ims=bytearray(msg))  # process local copy of msg
        assert wesK.serder.diger.qb64 == wesSrdr.dig  # key state updated so event was validated

        # Create rotation event for Wes
        # get current keys as verfers and next digests as digers
        sith = nxtsith  # rotate so nxtsith is now current sith and need new nextsith
        #  2 of first 3 and 1 of last 2
        nxtsith = [["1/2", "1/2", "1/2"], ["1/1", "1/1"]]
        verfers, digers, cst, nst = wesMgr.rotate(pre=wesPre,
                                                  count=5,
                                                  sith=nxtsith,
                                                  temp=True)
        assert cst == nst == nxtsith

        wesSrdr = eventing.rotate(
            pre=wesK.prefixer.qb64,
            keys=[verfer.qb64 for verfer in verfers],
            sith=sith,
            dig=wesK.serder.diger.qb64,
            nxt=coring.Nexter(sith=nxtsith,
                              digs=[diger.qb64 for diger in digers]).qb64,
            sn=wesK.sn + 1,
            data=[])

        sigers = wesMgr.sign(ser=wesSrdr.raw, verfers=verfers)

        msg = bytearray(wesSrdr.raw)
        counter = coring.Counter(coring.CtrDex.ControllerIdxSigs,
                                 count=len(sigers))
        msg.extend(counter.qb64b)
        for siger in sigers:
            msg.extend(siger.qb64b)

        assert msg == bytearray(
            b'{"v":"KERI10JSON0001fe_","i":"EM8ac0UPJZCaWOw2uRcvx6FaygyxFvGzA5'
            b'MTob9WfbDQ","s":"4","t":"rot","p":"EkBxzyMDQGRCNmoMOWwh58wuNuERR'
            b'cLoMH2_F0w99Dw4","kt":[["1/2","1/2","1/2"],["1/1","1/1"]],"k":["'
            b'DToUWoemnetqJoLFIqDI7lxIJEfF0W7xG5ZlqAseVUQc","Drz-IZjko61q-sPMD'
            b'IW6n-0NGFubbXiZhzWZrO_BZ0Wc","DiGwL3hjQqiUgQlFPeA6kRR1EBXX0vSLm9'
            b'b6QhPS8IkQ","Dxj5pcStgZ6CbQ2YktNaj8KLE_g9YAOZF6AL9fyLcWQw","DE5z'
            b'r5eH8EUVQXyAaxWfQUWkGCId-QDCvvxMT77ibj2Q"],"n":"E3in3Z14va0kk4Wq'
            b'd3vcCAojKNtQq7ZTrQaavR8x0yu4","wt":"0","wr":[],"wa":[],"a":[]}-A'
            b'AFAAEjpPTMtLre--y96OaTckIov-qfWT1lqOvwNBAcdTfmsfCLIJgZO4Y2ybJqGw'
            b'l2Q6DqLdfNQWHiDwnyllo1zZBgABny8aZlKENxCnulxSzSWIbFsg1Kv7RrdgTt4r'
            b'19taFq-bmBmMTLrkidNbeMHwgsNhhT8f3KJnPTaHEZ2Myd3BDQACaJ2sc2SpEcM0'
            b'9qMbk-8maWuxjAdMCb8n5P1vJesnf7TW6p3Vu2Mart5HuXW44r79DQ91sAmyYB_0'
            b'4q--ZyNYAQAD5trFl0S9G0GQmFF7FCgMYWzKNe7x16622OvT1-HjDP-eXxf9dani'
            b'dlUIbVWqalLgXOdhhsCNUDasvOHLByjSBgAEs-ovUeu2--2wnCJLpfHzLZUbc5fL'
            b'8bpOShEoPUwxEH4H1Wxsn3xPlvL3_pe5Mun3sq2jIhl1EOjcDaKOHofZCA')

        # apply msg to Wes's Kevery
        wesKvy.process(ims=bytearray(msg))  # process local copy of msg
        assert wesK.serder.diger.qb64 == wesSrdr.dig  # key state updated so event was validated

    assert not os.path.exists(wesKS.path)
    assert not os.path.exists(wesDB.path)
    """End Test"""
Exemple #6
0
def test_delegation():
    """
    Test creation and validation of delegated identifer prefixes and events

    """
    # bob is the delegator del is bob's delegate

    bobSalt = coring.Salter(raw=b'0123456789abcdef').qb64
    delSalt = coring.Salter(raw=b'abcdef0123456789').qb64

    with dbing.openDB(name="bob") as bobDB, \
          keeping.openKS(name="bob") as bobKS, \
          dbing.openDB(name="del") as delDB, \
          keeping.openKS(name="del") as delKS:

        # Init key pair managers
        bobMgr = keeping.Manager(keeper=bobKS, salt=bobSalt)
        delMgr = keeping.Manager(keeper=delKS, salt=delSalt)

        # Init Keverys
        bobKvy = eventing.Kevery(db=bobDB)
        delKvy = eventing.Kevery(db=delDB)

        # Setup Bob by creating inception event
        verfers, digers, cst, nst = bobMgr.incept(
            stem='bob', temp=True)  # algo default salty and rooted
        bobSrdr = eventing.incept(
            keys=[verfer.qb64 for verfer in verfers],
            nxt=coring.Nexter(digs=[diger.qb64 for diger in digers]).qb64,
            code=coring.MtrDex.Blake3_256)

        bobPre = bobSrdr.ked["i"]
        assert bobPre == 'EiBlVttjqvySMbA4ShN19rSrz3D0ioNW-Uj92Ri7XnFE'

        bobMgr.move(old=verfers[0].qb64,
                    new=bobPre)  # move key pair label to prefix

        sigers = bobMgr.sign(ser=bobSrdr.raw, verfers=verfers)

        msg = bytearray(bobSrdr.raw)
        counter = coring.Counter(code=coring.CtrDex.ControllerIdxSigs,
                                 count=len(sigers))
        msg.extend(counter.qb64b)
        for siger in sigers:
            msg.extend(siger.qb64b)

        assert msg == bytearray(
            b'{"v":"KERI10JSON0000e6_","i":"EiBlVttjqvySMbA4ShN19rSrz3D0ioNW-U'
            b'j92Ri7XnFE","s":"0","t":"icp","kt":"1","k":["DqI2cOZ06RwGNwCovYU'
            b'WExmdKU983IasmUKMmZflvWdQ"],"n":"E7FuL3Z_KBgt_QAwuZi1lUFNC69wvyH'
            b'SxnMFUsKjZHss","wt":"0","w":[],"c":[]}-AABAAQPFdtnncXLz6dE6A-tXG'
            b'YYK0BHu3I3Pj-G8DxlbzC3yx5MV8yucZILqAA5toZNODnHVHZtPIMkDknqldL4utBQ'
        )

        # apply msg to bob's Kevery
        bobKvy.process(ims=bytearray(msg))  # process local copy of msg
        bobK = bobKvy.kevers[bobPre]
        assert bobK.prefixer.qb64 == bobPre
        assert bobK.serder.diger.qb64 == bobSrdr.dig
        assert bobK.serder.diger.qb64 == 'EvP2kWxEjTMI3auc6x64EpU-nMQZHiBeKeuavcGdRB24'

        # apply msg to del's Kevery
        delKvy.process(ims=bytearray(msg))  # process remote copy of msg
        assert bobPre in delKvy.kevers

        # Setup Del's inception event assuming that Bob's next event will be an ixn delegating event
        verfers, digers, cst, nst = delMgr.incept(
            stem='del', temp=True)  # algo default salty and rooted

        seal = eventing.SealLocation(i=bobK.prefixer.qb64,
                                     s="{:x}".format(bobK.sn + 1),
                                     t=coring.Ilks.ixn,
                                     p=bobK.serder.diger.qb64)

        assert seal._asdict() == dict(
            i='EiBlVttjqvySMbA4ShN19rSrz3D0ioNW-Uj92Ri7XnFE',
            s='1',
            t='ixn',
            p='EvP2kWxEjTMI3auc6x64EpU-nMQZHiBeKeuavcGdRB24')

        delSrdr = eventing.delcept(
            keys=[verfer.qb64 for verfer in verfers],
            seal=seal,
            nxt=coring.Nexter(digs=[diger.qb64 for diger in digers]).qb64)

        delPre = delSrdr.ked["i"]
        assert delPre == 'ErLe2qWp4VCmDp7v_R01tC-ha13ZEZY0VGcgYtPRhqPs'

        delMgr.move(old=verfers[0].qb64,
                    new=delPre)  # move key pair label to prefix
        assert delSrdr.dig == 'ESDuaqpoI8-HLD8-eLijUMZpXqYFkNArJFDvt3ABYr9I'

        # Now create delegating event
        seal = eventing.SealEvent(i=delPre, s=delSrdr.ked["s"], d=delSrdr.dig)
        bobSrdr = eventing.interact(pre=bobK.prefixer.qb64,
                                    dig=bobK.serder.diger.qb64,
                                    sn=bobK.sn + 1,
                                    data=[seal._asdict()])

        sigers = bobMgr.sign(ser=bobSrdr.raw, verfers=bobK.verfers)

        msg = bytearray(bobSrdr.raw)
        counter = coring.Counter(code=coring.CtrDex.ControllerIdxSigs,
                                 count=len(sigers))
        msg.extend(counter.qb64b)
        for siger in sigers:
            msg.extend(siger.qb64b)

        assert msg == bytearray(
            b'{"v":"KERI10JSON000107_","i":"EiBlVttjqvySMbA4ShN19rSrz3D0ioNW-U'
            b'j92Ri7XnFE","s":"1","t":"ixn","p":"EvP2kWxEjTMI3auc6x64EpU-nMQZH'
            b'iBeKeuavcGdRB24","a":[{"i":"ErLe2qWp4VCmDp7v_R01tC-ha13ZEZY0VGcg'
            b'YtPRhqPs","s":"0","d":"ESDuaqpoI8-HLD8-eLijUMZpXqYFkNArJFDvt3ABY'
            b'r9I"}]}-AABAAZ4V2cSIXYEPg5BtkJSHVBj-A0dGI6rH2XGaVt1kewqGeJjpy4uz'
            b'ObPWnoBpaEojFa5AnrUJEgMytORoWMqEhCw')

        # apply msg to bob's Kevery
        bobKvy.process(ims=bytearray(msg))  # process local copy of msg
        assert bobK.serder.diger.qb64 == bobSrdr.dig  # key state updated so event was validated
        assert bobK.serder.diger.qb64 == 'EtzXPztLsGC5DGyooSdHdBGIOHjhblBWtZ_AOhGS-hDE'

        # apply msg to del's Kevery
        delKvy.process(ims=bytearray(msg))  # process remote copy of msg
        assert delKvy.kevers[bobPre].serder.diger.qb64 == bobSrdr.dig

        # now create msg with Del's delegated inception event
        sigers = delMgr.sign(ser=delSrdr.raw, verfers=verfers)

        msg = bytearray(delSrdr.raw)
        counter = coring.Counter(code=coring.CtrDex.ControllerIdxSigs,
                                 count=len(sigers))
        msg.extend(counter.qb64b)
        for siger in sigers:
            msg.extend(siger.qb64b)

        assert msg == bytearray(
            b'{"v":"KERI10JSON000165_","i":"ErLe2qWp4VCmDp7v_R01tC-ha13ZEZY0VG'
            b'cgYtPRhqPs","s":"0","t":"dip","kt":"1","k":["DuK1x8ydpucu3480Jpd'
            b'1XBfjnCwb3dZ3x5b1CJmuUphA"],"n":"EWWkjZkZDXF74O2bOQ4H5hu4nXDlKg2'
            b'm4CBEBkUxibiU","wt":"0","w":[],"c":[],"da":{"i":"EiBlVttjqvySMbA'
            b'4ShN19rSrz3D0ioNW-Uj92Ri7XnFE","s":"1","t":"ixn","p":"EvP2kWxEjT'
            b'MI3auc6x64EpU-nMQZHiBeKeuavcGdRB24"}}-AABAADv-a3LeXEStuY1LHknepu'
            b'J7mBcTByugqQ1TNRMrIa0rctfjKsh-hkkkpwDj6M_OLLaFtLqBpmdNTUgBPANLzCQ'
        )

        # apply Del's delegated inception event message to bob's Kevery
        bobKvy.process(ims=bytearray(msg))  # process local copy of msg
        assert delPre in bobKvy.kevers  # successfully validated
        delK = bobKvy.kevers[delPre]
        assert delK.delegated
        assert delK.serder.diger.qb64 == delSrdr.dig  # key state updated so event was validated
        assert delK.serder.diger.qb64 == 'ESDuaqpoI8-HLD8-eLijUMZpXqYFkNArJFDvt3ABYr9I'

        # apply msg to del's Kevery
        delKvy.process(ims=bytearray(msg))  # process remote copy of msg
        assert delKvy.kevers[delPre].serder.diger.qb64 == delSrdr.dig

        # Setup Del rotation event assuming that Bob's next event will be an ixn delegating event
        verfers, digers, cst, nst = delMgr.rotate(pre=delPre, temp=True)

        seal = eventing.SealLocation(i=bobK.prefixer.qb64,
                                     s="{:x}".format(bobK.sn + 1),
                                     t=coring.Ilks.ixn,
                                     p=bobK.serder.diger.qb64)

        assert seal._asdict() == {
            'i': 'EiBlVttjqvySMbA4ShN19rSrz3D0ioNW-Uj92Ri7XnFE',
            's': '2',
            't': 'ixn',
            'p': 'EtzXPztLsGC5DGyooSdHdBGIOHjhblBWtZ_AOhGS-hDE'
        }

        delSrdr = eventing.deltate(
            pre=delK.prefixer.qb64,
            keys=[verfer.qb64 for verfer in verfers],
            dig=delK.serder.diger.qb64,
            seal=seal,
            sn=delK.sn + 1,
            nxt=coring.Nexter(digs=[diger.qb64 for diger in digers]).qb64)

        assert delSrdr.dig == 'E-dZsWLp2IIPVDbGdGS-yvuw4HeV_w_w76FHsofmuiq0'

        # Now create delegating rotation event
        seal = eventing.SealEvent(i=delK.prefixer.qb64,
                                  s=delSrdr.ked["s"],
                                  d=delSrdr.dig)
        bobSrdr = eventing.interact(pre=bobK.prefixer.qb64,
                                    dig=bobK.serder.diger.qb64,
                                    sn=bobK.sn + 1,
                                    data=[seal._asdict()])

        sigers = bobMgr.sign(ser=bobSrdr.raw, verfers=bobK.verfers)

        msg = bytearray(bobSrdr.raw)
        counter = coring.Counter(code=coring.CtrDex.ControllerIdxSigs,
                                 count=len(sigers))
        msg.extend(counter.qb64b)
        for siger in sigers:
            msg.extend(siger.qb64b)

        assert msg == bytearray(
            b'{"v":"KERI10JSON000107_","i":"EiBlVttjqvySMbA4ShN19rSrz3D0ioNW-U'
            b'j92Ri7XnFE","s":"2","t":"ixn","p":"EtzXPztLsGC5DGyooSdHdBGIOHjhb'
            b'lBWtZ_AOhGS-hDE","a":[{"i":"ErLe2qWp4VCmDp7v_R01tC-ha13ZEZY0VGcg'
            b'YtPRhqPs","s":"1","d":"E-dZsWLp2IIPVDbGdGS-yvuw4HeV_w_w76FHsofmu'
            b'iq0"}]}-AABAAmloDxOwz6ztvRR_4N8Hn-6ZJk6_0nQhfNE7bzX6NpJRfYDwmUw3'
            b'rXod0g46iFOLqEWw12oaFVzVH85NYAh67Ag')

        # apply msg to bob's Kevery
        bobKvy.process(ims=bytearray(msg))  # process local copy of msg
        assert bobK.serder.diger.qb64 == bobSrdr.dig  # key state updated so event was validated

        # apply msg to del's Kevery
        delKvy.process(ims=bytearray(msg))  # process remote copy of msg
        assert delKvy.kevers[bobPre].serder.diger.qb64 == bobSrdr.dig

        # now create msg from Del's delegated rotation event
        sigers = delMgr.sign(ser=delSrdr.raw, verfers=verfers)

        msg = bytearray(delSrdr.raw)
        counter = coring.Counter(code=coring.CtrDex.ControllerIdxSigs,
                                 count=len(sigers))
        msg.extend(counter.qb64b)
        for siger in sigers:
            msg.extend(siger.qb64b)

        assert msg == bytearray(
            b'{"v":"KERI10JSON0001a1_","i":"ErLe2qWp4VCmDp7v_R01tC-ha13ZEZY0VG'
            b'cgYtPRhqPs","s":"1","t":"drt","p":"ESDuaqpoI8-HLD8-eLijUMZpXqYFk'
            b'NArJFDvt3ABYr9I","kt":"1","k":["DTf6QZWoet154o9wvzeMuNhLQRr8JaAU'
            b'eiC6wjB_4_08"],"n":"E8kyiXDfkE7idwWnAZQjHbUZMz-kd_yIMH0miptIFFPo'
            b'","wt":"0","wr":[],"wa":[],"a":[],"da":{"i":"EiBlVttjqvySMbA4ShN'
            b'19rSrz3D0ioNW-Uj92Ri7XnFE","s":"2","t":"ixn","p":"EtzXPztLsGC5DG'
            b'yooSdHdBGIOHjhblBWtZ_AOhGS-hDE"}}-AABAAXcUl6KlY4VOx8ZumFMc0uR4iH'
            b'BGmPQo4IAx0nIiiEDB_u2ewkvgIDIp1ELDGxfc2VVUkl38Z7PqwydBdpIK0DA')

        # apply Del's delegated inception event message to bob's Kevery
        bobKvy.process(ims=bytearray(msg))  # process local copy of msg
        assert delK.delegated
        assert delK.serder.diger.qb64 == delSrdr.dig  # key state updated so event was validated
        assert delK.serder.diger.qb64 == 'E-dZsWLp2IIPVDbGdGS-yvuw4HeV_w_w76FHsofmuiq0'

        # apply msg to del's Kevery
        delKvy.process(ims=bytearray(msg))  # process remote copy of msg
        assert delKvy.kevers[delPre].serder.diger.qb64 == delSrdr.dig

    assert not os.path.exists(delKS.path)
    assert not os.path.exists(delDB.path)
    assert not os.path.exists(bobKS.path)
    assert not os.path.exists(bobDB.path)
    """End Test"""
Exemple #7
0
def test_directing_basic():
    """
    Test directing
    """
    help.ogler.resetLevel(level=logging.DEBUG)

    # set of secrets  (seeds for private keys)
    bobSecrets = [
        'ArwXoACJgOleVZ2PY7kXn7rA0II0mHYDhc6WrBH8fDAc',
        'A6zz7M08-HQSFq92sJ8KJOT2cZ47x7pXFQLPB0pckB3Q',
        'AcwFTk-wgk3ZT2buPRIbK-zxgPx-TKbaegQvPEivN90Y',
        'Alntkt3u6dDgiQxTATr01dy8M72uuaZEf9eTdM-70Gk8',
        'A1-QxDkso9-MR1A8rZz_Naw6fgaAtayda8hrbkRVVu1E',
        'AKuYMe09COczwf2nIoD5AE119n7GLFOVFlNLxZcKuswc',
        'AxFfJTcSuEE11FINfXMqWttkZGnUZ8KaREhrnyAXTsjw',
        'ALq-w1UKkdrppwZzGTtz4PWYEeWm0-sDHzOv5sq96xJY'
    ]

    bobSecrecies = []
    for secret in bobSecrets:  # convert secrets to secrecies
        bobSecrecies.append([secret])

    #  create bob signers
    bobSigners = [coring.Signer(qb64=secret) for secret in bobSecrets]
    assert [signer.qb64 for signer in bobSigners] == bobSecrets

    # bob inception transferable (nxt digest not empty)
    bobSerder = eventing.incept(
        keys=[bobSigners[0].verfer.qb64],
        nxt=coring.Nexter(keys=[bobSigners[1].verfer.qb64]).qb64,
        code=coring.MtrDex.Blake3_256)

    bob = bobSerder.ked["i"]
    assert bob == 'EQf1hzB6s5saaQPdDAsEzSMEFoQx_WLsq93bjPu5wuqA'

    # set of secrets (seeds for private keys)
    eveSecrets = [
        'AgjD4nRlycmM5cPcAkfOATAp8wVldRsnc9f1tiwctXlw',
        'AKUotEE0eAheKdDJh9QvNmSEmO_bjIav8V_GmctGpuCQ',
        'AK-nVhMMJciMPvmF5VZE_9H-nhrgng9aJWf7_UHPtRNM',
        'AT2cx-P5YUjIw_SLCHQ0pqoBWGk9s4N1brD-4pD_ANbs',
        'Ap5waegfnuP6ezC18w7jQiPyQwYYsp9Yv9rYMlKAYL8k',
        'Aqlc_FWWrxpxCo7R12uIz_Y2pHUH2prHx1kjghPa8jT8',
        'AagumsL8FeGES7tYcnr_5oN6qcwJzZfLKxoniKUpG4qc',
        'ADW3o9m3udwEf0aoOdZLLJdf1aylokP0lwwI_M2J9h0s'
    ]

    eveSecrecies = []
    for secret in eveSecrets:  # convert secrets to secrecies
        eveSecrecies.append([secret])

    #  create eve signers
    eveSigners = [coring.Signer(qb64=secret) for secret in eveSecrets]
    assert [signer.qb64 for signer in eveSigners] == eveSecrets

    # eve inception transferable (nxt digest not empty)
    eveSerder = eventing.incept(
        keys=[eveSigners[0].verfer.qb64],
        nxt=coring.Nexter(keys=[eveSigners[1].verfer.qb64]).qb64,
        code=coring.MtrDex.Blake3_256)

    eve = eveSerder.ked["i"]
    assert eve == 'ED9EB3sA5u2vCPOEmX3d7bEyHiSh7Xi8fjew2KMl3FQM'

    with dbing.openDB(name="eve") as eveDB, keeping.openKS(name="eve") as eveKS, \
         dbing.openDB(name="bob") as bobDB, keeping.openKS(name="bob") as bobKS:

        limit = 0.125
        tock = 0.03125
        doist = doing.Doist(limit=limit, tock=tock)

        bobPort = 5620  # bob's TCP listening port for server
        evePort = 5621  # eve's TCP listneing port for server
        bobKevers = dict()
        eveKevers = dict()

        # setup bob
        bobHab = directing.Habitat(ks=bobKS,
                                   db=bobDB,
                                   kevers=bobKevers,
                                   secrecies=bobSecrecies,
                                   temp=True)
        assert bobHab.ks == bobKS
        assert bobHab.db == bobDB
        assert bobHab.iserder.dig == bobSerder.dig
        assert bobHab.pre == bob

        bobClient = clienting.Client(tymth=doist.tymen(),
                                     host='127.0.0.1',
                                     port=evePort)
        bobClientDoer = doing.ClientDoer(tymth=doist.tymen(), client=bobClient)

        bobDirector = directing.Director(hab=bobHab, client=bobClient)
        assert bobDirector.hab == bobHab
        assert bobDirector.client == bobClient
        assert id(bobDirector.hab.kvy.kevers) == id(bobKevers)
        assert bobDirector.hab.kvy.db == bobDB

        bobReactor = directing.Reactor(hab=bobHab, client=bobClient)
        assert bobReactor.hab == bobHab
        assert bobReactor.client == bobClient
        assert id(bobReactor.hab.kvy.kevers) == id(bobKevers)
        assert bobReactor.hab.kvy.db == bobDB
        assert id(bobReactor.kevery.ims) == id(bobReactor.client.rxbs)
        assert id(bobReactor.client.rxbs) == id(bobDirector.client.rxbs)

        bobServer = serving.Server(host="", port=bobPort)
        bobServerDoer = doing.ServerDoer(server=bobServer)

        bobDirectant = directing.Directant(hab=bobHab, server=bobServer)
        assert bobDirectant.hab == bobHab
        assert bobDirectant.server == bobServer
        # Bob's Reactants created on demand

        # setup eve
        eveHab = directing.Habitat(ks=eveKS,
                                   db=eveDB,
                                   kevers=eveKevers,
                                   secrecies=eveSecrecies,
                                   temp=True)
        assert eveHab.ks == eveKS
        assert eveHab.db == eveDB
        assert eveHab.iserder.dig == eveSerder.dig
        assert eveHab.pre == eve

        eveClient = clienting.Client(tymth=doist.tymen(),
                                     host='127.0.0.1',
                                     port=bobPort)
        eveClientDoer = doing.ClientDoer(tymth=doist.tymen(), client=eveClient)

        eveDirector = directing.Director(hab=eveHab, client=eveClient)
        assert eveDirector.hab == eveHab
        assert eveDirector.client == eveClient
        assert id(eveDirector.hab.kvy.kevers) == id(eveKevers)
        assert eveDirector.hab.kvy.db == eveDB

        eveReactor = directing.Reactor(hab=eveHab, client=eveClient)
        assert eveReactor.hab == eveHab
        assert eveReactor.client == eveClient
        assert id(eveReactor.hab.kvy.kevers) == id(eveKevers)
        assert eveReactor.hab.kvy.db == eveDB
        assert id(eveReactor.kevery.ims) == id(eveReactor.client.rxbs)
        assert id(eveReactor.client.rxbs) == id(eveDirector.client.rxbs)

        eveServer = serving.Server(host="", port=evePort)
        eveServerDoer = doing.ServerDoer(server=eveServer)

        eveDirectant = directing.Directant(hab=eveHab, server=eveServer)
        assert eveDirectant.hab == eveHab
        assert eveDirectant.server == eveServer
        # Eve's Reactants created on demand

        bobMsgTx = b"Hi Eve I am  Bob"
        bobDirector.client.tx(bobMsgTx)

        eveMsgTx = b"Hi Bob its me Eve"
        eveDirector.client.tx(eveMsgTx)

        doers = [
            bobClientDoer, bobDirector, bobReactor, bobServerDoer,
            bobDirectant, eveClientDoer, eveDirector, eveReactor,
            eveServerDoer, eveDirectant
        ]
        doist.do(doers=doers)
        assert doist.tyme == limit

        assert bobClient.opened == False
        assert bobServer.opened == False
        assert eveClient.opened == False
        assert eveServer.opened == False

        assert not bobClient.txbs
        ca, ix = list(eveServer.ixes.items())[0]
        eveMsgRx = bytes(ix.rxbs)  # ColdStart Error fluhes buffer
        assert eveMsgRx == b''
        # assert eveMsgRx == bobMsgTx

        assert not eveClient.txbs
        ca, ix = list(bobServer.ixes.items())[0]
        bobMsgRx = bytes(ix.rxbs)  # ColdStart Error fluhes buffer
        assert bobMsgRx == b''
        # assert bobMsgRx == eveMsgTx

    assert not os.path.exists(eveDB.path)
    assert not os.path.exists(bobDB.path)

    help.ogler.resetLevel(level=help.ogler.level)
    """End Test"""
Exemple #8
0
def gen_serialized_aid(witnesses):
    # taken from https://github.com/decentralized-identity/keripy/blob/6b85417ce1188543493efff48f95ebabd12fb0c6/tests/core/test_eventing.py
    with openDB() as bsr:
        # Transferable case
        # Setup inception key event dict
        # create current key
        sith = 1  #  one signer
        skp0 = Signer()  #  original signing keypair transferable default
        assert skp0.code == CryOneDex.Ed25519_Seed
        assert skp0.verfer.code == CryOneDex.Ed25519
        keys = [skp0.verfer.qb64]

        # create next key
        nxtsith = 1  #  one signer
        skp1 = Signer()  #  next signing keypair transferable is default
        assert skp1.code == CryOneDex.Ed25519_Seed
        assert skp1.verfer.code == CryOneDex.Ed25519
        nxtkeys = [skp1.verfer.qb64]
        # compute nxt digest
        nexter = Nexter(sith=nxtsith, keys=nxtkeys)
        nxt = nexter.qb64  # transferable so nxt is not empty

        sn = 0  #  inception event so 0
        toad = len(witnesses)
        nsigs = 1  #  one attached signature unspecified index

        ked0 = dict(
            vs=Versify(kind=Serials.json, size=0),
            pre="",  # qual base 64 prefix
            sn="{:x}".format(sn),  # hex string no leading zeros lowercase
            ilk=Ilks.icp,
            sith="{:x}".format(sith),  # hex string no leading zeros lowercase
            keys=keys,  # list of signing keys each qual Base64
            nxt=nxt,  # hash qual Base64
            toad="{:x}".format(toad),  # hex string no leading zeros lowercase
            # I think these are always necessary for direct mode
            wits=witnesses or [],  # list of qual Base64 may be empty
            cnfg=[],  # list of config ordered mappings may be empty
        )

        # Derive AID from ked
        aid0 = Prefixer(ked=ked0, code=CryOneDex.Ed25519)
        assert aid0.code == CryOneDex.Ed25519
        assert aid0.qb64 == skp0.verfer.qb64

        # update ked with pre
        ked0["pre"] = aid0.qb64

        # Serialize ked0
        tser0 = Serder(ked=ked0)

        # sign serialization
        tsig0 = skp0.sign(tser0.raw, index=0)

        # verify signature
        assert skp0.verfer.verify(tsig0.raw, tser0.raw)

        kever = Kever(serder=tser0, sigers=[tsig0], baser=bsr)  # no error

        # return base 64 serialization of signed aid
        # return tsig0.qb64
        return tsig0, tser0, tsig0.qb64
Exemple #9
0
def test_direct_mode_with_manager():
    """
    Test direct mode with transferable validator event receipts

    """
    # manual process to generate a list of secrets
    # root = pysodium.randombytes(pysodium.crypto_pwhash_SALTBYTES)
    # secrets = generateSecrets(root=root, count=8)

    # Direct Mode initiated by coe is controller, val is validator
    # but goes both ways once initiated.

    # set of secrets  (seeds for private keys)
    coeSalt = Salter(raw=b'0123456789abcdea').qb64

    # set of secrets (seeds for private keys)
    valSalt = Salter(raw=b'1123456789abcdea').qb64


    with openDB("controller") as coeLogger, openDB("validator") as valLogger, openKS(name="controller") as coeKpr, openKS(name="validator") as valKpr:
        # Init key pair manager
        coeMgr = Manager(keeper=coeKpr, salt=coeSalt)
        coeVerfers, coeDigers = coeMgr.incept(icount=1, ncount=1)

        #  init Keverys
        coeKevery = Kevery(db=coeLogger)
        valKevery = Kevery(db=valLogger)

        coe_event_digs = []  # list of controller's own event log digs to verify against database
        val_event_digs = []  # list of validator's own event log digs to verify against database

        #  init sequence numbers for both controller and validator
        csn = cesn = 0  # sn and last establishment sn = esn
        vsn = vesn = 0  # sn and last establishment sn = esn

        # Controller Event 0  Inception Transferable (nxt digest not empty)
        coeSerder = incept(keys=[coeVerfers[0].qb64],
                           nxt=Nexter(digs=[coeDigers[0].qb64]).qb64,
                           code=MtrDex.Blake3_256)

        assert csn == int(coeSerder.ked["s"], 16) == 0
        coepre = coeSerder.ked["i"]
        assert coepre == 'EsU9ZQwug7DS-GU040Ugj1t7p6Au14VkBOCJnPYabcas'

        coe_event_digs.append(coeSerder.dig)
        # sign serialization
        sigers = coeMgr.sign(ser=coeSerder.raw, verfers=coeVerfers)

        #  create serialized message
        cmsg = messagize(coeSerder, sigers)
        assert cmsg == bytearray(b'{"v":"KERI10JSON0000e6_","i":"EsU9ZQwug7DS-GU040Ugj1t7p6Au14VkBO'
                                 b'CJnPYabcas","s":"0","t":"icp","kt":"1","k":["Dpt7mGZ3y5UmhT1NLEx'
                                 b'b1IW8vMJ8ylQW3K44LfkTgAqE"],"n":"Erpltchg7BUv21Qz3ZXhOhVu63m7S7Y'
                                 b'bPb21lSeGYd90","wt":"0","w":[],"c":[]}-AABAA2dW-FXhcUiGQZh1JhRrh'
                                 b'_JDqEPU678KT0U8F_a-l8Q3sO25xJAs3Iu2bBonBPZjVo_Zc8FVqrqXjQxxUPt4ICg')

        # create own Controller Kever in  Controller's Kevery
        coeKevery.processOne(ims=bytearray(cmsg))  # send copy of cmsg
        coeKever = coeKevery.kevers[coepre]
        assert coeKever.prefixer.qb64 == coepre

        # Validator Event 0  Inception Transferable (nxt digest not empty)
        # Init key pair manager
        valMgr = Manager(keeper=valKpr, salt=valSalt)
        valVerfers, valDigers = valMgr.incept(icount=1, ncount=1)

        valSerder = incept(keys=[valVerfers[0].qb64],
                           nxt=Nexter(digs=[valDigers[0].qb64]).qb64,
                           code=MtrDex.Blake3_256)

        assert vsn == int(valSerder.ked["s"], 16) == 0
        valpre = valSerder.ked["i"]
        assert valpre == 'EBiIFxr_o1b4x1YR21PblAFpFG61qDghqFBDyVSOXYW0'

        val_event_digs.append(valSerder.dig)

        # sign serialization
        sigers = valMgr.sign(valSerder.raw, verfers=valVerfers)  # return Siger if index

        #  create serialized message
        vmsg = messagize(valSerder, sigers)
        assert vmsg == bytearray(b'{"v":"KERI10JSON0000e6_","i":"EBiIFxr_o1b4x1YR21PblAFpFG61qDghqF'
                                 b'BDyVSOXYW0","s":"0","t":"icp","kt":"1","k":["DLSBUmklGu6eLqnA5DA'
                                 b'gj41jetAJYkyn34crqejwXxVw"],"n":"EwmUJaS6DSPRQprlGp_3CIg8BZwmaJl'
                                 b'KPlE4LHcx0Zms","wt":"0","w":[],"c":[]}-AABAAxvl1581mKQME95XZrjsy'
                                 b'CXxJ3fCnmNSG_Bc1I4FcxEoeQbgdLAQ8sudwb0FHOYXfqRE6Z7PraaU82YQDyVShDw')

        # create own Validator Kever in  Validator's Kevery
        valKevery.processOne(ims=bytearray(vmsg))  # send copy of vmsg
        valKever = valKevery.kevers[valpre]
        assert valKever.prefixer.qb64 == valpre

        # simulate sending of controller's inception message to validator
        valKevery.process(ims=bytearray(cmsg))  # make copy of msg
        assert coepre in valKevery.kevers  # creates Kever for controller in validator's .kevers

        # create receipt of controller's inception
        # create seal of validator's last establishment event
        seal = SealEvent(i=valpre,
                         s="{:x}".format(valKever.lastEst.s),
                         d=valKever.lastEst.d)
        coeK = valKevery.kevers[coepre]  # lookup coeKever from validator's .kevers
        # create validator receipt
        reserder = chit(pre=coeK.prefixer.qb64,
                        sn=coeK.sn,
                        dig=coeK.serder.diger.qb64,
                        seal=seal)
        # Validate receipt
        assert reserder.raw == (b'{"v":"KERI10JSON000105_","i":"EsU9ZQwug7DS-GU040Ugj1t7p6Au14VkBOCJnPYabcas",'
                                b'"s":"0","t":"vrc","d":"Ey2pXEnaoQVwxA4jB6k0QH5G2Us-0juFL5hOAHAwIEkc","a":{"i'
                                b'":"EBiIFxr_o1b4x1YR21PblAFpFG61qDghqFBDyVSOXYW0","s":"0","d":"ElsHFkbZQjRb7x'
                                b'HnuE-wyiarIZ9j-1CEQ89I0E3WevcE"}}')

        # sign controller's event not receipt
        # look up event to sign from validator's kever for coe
        coeIcpDig = bytes(valKevery.db.getKeLast(key=snKey(pre=coepre, sn=csn)))
        assert coeIcpDig == coeK.serder.diger.qb64b == b'Ey2pXEnaoQVwxA4jB6k0QH5G2Us-0juFL5hOAHAwIEkc'
        coeIcpRaw = bytes(valKevery.db.getEvt(key=dgKey(pre=coepre, dig=coeIcpDig)))
        assert coeIcpRaw == (b'{"v":"KERI10JSON0000e6_","i":"EsU9ZQwug7DS-GU040Ugj1t7p6Au14VkBOCJnPYabcas",'
                             b'"s":"0","t":"icp","kt":"1","k":["Dpt7mGZ3y5UmhT1NLExb1IW8vMJ8ylQW3K44LfkTgAq'
                             b'E"],"n":"Erpltchg7BUv21Qz3ZXhOhVu63m7S7YbPb21lSeGYd90","wt":"0","w":[],"c":['
                             b']}')
        counter = Counter(CtrDex.ControllerIdxSigs)
        assert counter.qb64 == '-AAB'
        sigers = valMgr.sign(ser=coeIcpRaw, verfers=valVerfers)  # return Siger if index

        # process own validator receipt in validator's Kevery so have copy in own log
        rmsg = messagize(reserder, sigers)
        assert rmsg == bytearray(b'{"v":"KERI10JSON000105_","i":"EsU9ZQwug7DS-GU040Ugj1t7p6Au14VkBOCJnPYabcas",'
                                 b'"s":"0","t":"vrc","d":"Ey2pXEnaoQVwxA4jB6k0QH5G2Us-0juFL5hOAHAwIEkc","a":{"i'
                                 b'":"EBiIFxr_o1b4x1YR21PblAFpFG61qDghqFBDyVSOXYW0","s":"0","d":"ElsHFkbZQjRb7x'
                                 b'HnuE-wyiarIZ9j-1CEQ89I0E3WevcE"}}-AABAARG0my55RTX81fFzUbbcfygZXfz04VglNA8Zwy'
                                 b'qst_ZvLo05jau9GsF0IS9Vm6yGr8QQPdB7M4oVkrd9IEZ8PDA')

        valKevery.processOne(ims=bytearray(rmsg))  # process copy of rmsg

        # attach receipt message to existing message with validators inception message
        # simulate streaming. validator first sends it's inception event, then sends a receipt to controller
        vmsg.extend(rmsg)
        assert vmsg == bytearray(b'{"v":"KERI10JSON0000e6_","i":"EBiIFxr_o1b4x1YR21PblAFpFG61qDghqF'
                                 b'BDyVSOXYW0","s":"0","t":"icp","kt":"1","k":["DLSBUmklGu6eLqnA5DA'
                                 b'gj41jetAJYkyn34crqejwXxVw"],"n":"EwmUJaS6DSPRQprlGp_3CIg8BZwmaJl'
                                 b'KPlE4LHcx0Zms","wt":"0","w":[],"c":[]}-AABAAxvl1581mKQME95XZrjsy'
                                 b'CXxJ3fCnmNSG_Bc1I4FcxEoeQbgdLAQ8sudwb0FHOYXfqRE6Z7PraaU82YQDyVSh'
                                 b'Dw{"v":"KERI10JSON000105_","i":"EsU9ZQwug7DS-GU040Ugj1t7p6Au14Vk'
                                 b'BOCJnPYabcas","s":"0","t":"vrc","d":"Ey2pXEnaoQVwxA4jB6k0QH5G2Us'
                                 b'-0juFL5hOAHAwIEkc","a":{"i":"EBiIFxr_o1b4x1YR21PblAFpFG61qDghqFB'
                                 b'DyVSOXYW0","s":"0","d":"ElsHFkbZQjRb7xHnuE-wyiarIZ9j-1CEQ89I0E3W'
                                 b'evcE"}}-AABAARG0my55RTX81fFzUbbcfygZXfz04VglNA8Zwyqst_ZvLo05jau9'
                                 b'GsF0IS9Vm6yGr8QQPdB7M4oVkrd9IEZ8PDA')

        # Simulate sending validator's inception event and receipt of controller's inception message to controller
        coeKevery.process(ims=vmsg)  # controller process validator's inception and receipt

        # check if validator's Kever in controller's .kevers
        assert valpre in coeKevery.kevers
        #  check if receipt quadruple from validator in receipt database
        result = coeKevery.db.getVrcs(key=dgKey(pre=coeKever.prefixer.qb64,
                                                   dig=coeKever.serder.diger.qb64))
        assert bytes(result[0]) == (valKever.prefixer.qb64b +
                                    Seqner(sn=valKever.sn).qb64b +
                                    valKever.serder.diger.qb64b +
                                    sigers[0].qb64b)

        assert bytes(result[0]) == (b'EBiIFxr_o1b4x1YR21PblAFpFG61qDghqFBDyVSOXYW00AAAAAAAAAAAAAAAAAAAAAAAElsHFkbZ'
                                    b'QjRb7xHnuE-wyiarIZ9j-1CEQ89I0E3WevcEAARG0my55RTX81fFzUbbcfygZXfz04VglNA8Zwyq'
                                    b'st_ZvLo05jau9GsF0IS9Vm6yGr8QQPdB7M4oVkrd9IEZ8PDA')

        # create receipt to escrow use invalid digest and sequence number so not in controller's db
        fake = reserder.dig  # some other digest
        reserder = chit(pre=coeK.prefixer.qb64,
                        sn=10,
                        dig=fake,
                        seal=seal)
        # sign event not receipt
        sigers = valMgr.sign(ser=coeIcpRaw, verfers=valVerfers)  # return Siger if index

        # create receipt message
        vmsg = messagize(reserder, sigers)
        assert vmsg == bytearray(b'{"v":"KERI10JSON000105_","i":"EsU9ZQwug7DS-GU040Ugj1t7p6Au14VkBO'
                                 b'CJnPYabcas","s":"a","t":"vrc","d":"EwxY7Vhkeyr7LBnLAzdGXZzSmTmJV'
                                 b'RctQfNUO0YUqeOU","a":{"i":"EBiIFxr_o1b4x1YR21PblAFpFG61qDghqFBDy'
                                 b'VSOXYW0","s":"0","d":"ElsHFkbZQjRb7xHnuE-wyiarIZ9j-1CEQ89I0E3Wev'
                                 b'cE"}}-AABAARG0my55RTX81fFzUbbcfygZXfz04VglNA8Zwyqst_ZvLo05jau9Gs'
                                 b'F0IS9Vm6yGr8QQPdB7M4oVkrd9IEZ8PDA')

        coeKevery.process(ims=vmsg)  # controller process the escrow receipt from validator
        #  check if receipt quadruple in escrow database
        result = coeKevery.db.getVres(key=snKey(pre=coeKever.prefixer.qb64,
                                                   sn=10))
        assert bytes(result[0]) == (fake.encode("utf-8") +
                                    valKever.prefixer.qb64b +
                                    Seqner(sn=valKever.sn).qb64b +
                                    valKever.serder.diger.qb64b +
                                    sigers[0].qb64b)

        # Send receipt from controller to validator
        # create receipt of validator's inception
        # create seal of controller's last establishment event
        seal = SealEvent(i=coepre,
                         s="{:x}".format(coeKever.lastEst.s),
                         d=coeKever.lastEst.d)
        valK = coeKevery.kevers[valpre]  # lookup valKever from controller's .kevers
        # create validator receipt
        reserder = chit(pre=valK.prefixer.qb64,
                        sn=valK.sn,
                        dig=valK.serder.diger.qb64,
                        seal=seal)
        # sign validator's event not receipt
        # look up event to sign from controller's kever for validator
        valIcpDig = bytes(coeKevery.db.getKeLast(key=snKey(pre=valpre, sn=vsn)))
        assert valIcpDig == valK.serder.diger.qb64b == b'ElsHFkbZQjRb7xHnuE-wyiarIZ9j-1CEQ89I0E3WevcE'
        valIcpRaw = bytes(coeKevery.db.getEvt(key=dgKey(pre=valpre, dig=valIcpDig)))
        assert valIcpRaw == (b'{"v":"KERI10JSON0000e6_","i":"EBiIFxr_o1b4x1YR21PblAFpFG61qDghqF'
                             b'BDyVSOXYW0","s":"0","t":"icp","kt":"1","k":["DLSBUmklGu6eLqnA5DA'
                             b'gj41jetAJYkyn34crqejwXxVw"],"n":"EwmUJaS6DSPRQprlGp_3CIg8BZwmaJl'
                             b'KPlE4LHcx0Zms","wt":"0","w":[],"c":[]}')

        counter = Counter(CtrDex.ControllerIdxSigs)
        assert counter.qb64 == '-AAB'
        sigers = coeMgr.sign(ser=valIcpRaw, verfers=coeVerfers)  # return Siger if index

        # create receipt message
        cmsg = messagize(reserder, sigers)
        assert cmsg == bytearray(b'{"v":"KERI10JSON000105_","i":"EBiIFxr_o1b4x1YR21PblAFpFG61qDghqF'
                                 b'BDyVSOXYW0","s":"0","t":"vrc","d":"ElsHFkbZQjRb7xHnuE-wyiarIZ9j-'
                                 b'1CEQ89I0E3WevcE","a":{"i":"EsU9ZQwug7DS-GU040Ugj1t7p6Au14VkBOCJn'
                                 b'PYabcas","s":"0","d":"Ey2pXEnaoQVwxA4jB6k0QH5G2Us-0juFL5hOAHAwIE'
                                 b'kc"}}-AABAAKXFMBGw559YHoxyeDrmpilQo5JMbr5WSfYTn1IXV_rMtg23_GHrNQ'
                                 b'Ua7y45UkNftT48O0MekxT7geRBU84dACA')

        # controller process own receipt in own Kevery so have copy in own log
        coeKevery.processOne(ims=bytearray(cmsg))  # make copy

        # Simulate sending controller's receipt of validator's inception message to validator
        valKevery.process(ims=cmsg)  # controller process validator's inception and receipt

        #  check if receipt quadruple from controller in validator's receipt database
        result = valKevery.db.getVrcs(key=dgKey(pre=valKever.prefixer.qb64,
                                                   dig=valKever.serder.diger.qb64))
        assert bytes(result[0]) == (coeKever.prefixer.qb64b +
                                    Seqner(sn=coeKever.sn).qb64b +
                                    coeKever.serder.diger.qb64b +
                                    sigers[0].qb64b)
        assert bytes(result[0]) == (b'EsU9ZQwug7DS-GU040Ugj1t7p6Au14VkBOCJnPYabcas0AAAAAAAAAAAAAAAAAAAAAAAEy2pXEna'
                                    b'oQVwxA4jB6k0QH5G2Us-0juFL5hOAHAwIEkcAAKXFMBGw559YHoxyeDrmpilQo5JMbr5WSfYTn1I'
                                    b'XV_rMtg23_GHrNQUa7y45UkNftT48O0MekxT7geRBU84dACA')

        # Controller Event 1 Rotation Transferable
        csn += 1
        cesn += 1
        assert csn == cesn == 1
        coeVerfers, coeDigers = coeMgr.rotate(coeVerfers[0].qb64)
        coeSerder = rotate(pre=coeKever.prefixer.qb64,
                           keys=[coeVerfers[0].qb64],
                           dig=coeKever.serder.diger.qb64,
                           nxt=Nexter(digs=[coeDigers[0].qb64]).qb64,
                           sn=csn)
        coe_event_digs.append(coeSerder.dig)

        # sign serialization
        sigers = coeMgr.sign(coeSerder.raw, verfers=coeVerfers)  # returns sigers

        #  create serialized message
        cmsg = messagize(coeSerder, sigers)

        assert cmsg == bytearray(b'{"v":"KERI10JSON000122_","i":"EsU9ZQwug7DS-GU040Ugj1t7p6Au14VkBO'
                                 b'CJnPYabcas","s":"1","t":"rot","p":"Ey2pXEnaoQVwxA4jB6k0QH5G2Us-0'
                                 b'juFL5hOAHAwIEkc","kt":"1","k":["D-HwiqmaETxls3vAVSh0xpXYTs94NUJX'
                                 b'6juupWj_EgsA"],"n":"ED6lKZwg-BWl_jlCrjosQkOEhqKD4BJnlqYqWmhqPhaU'
                                 b'","wt":"0","wr":[],"wa":[],"a":[]}-AABAAsDhyw43CAo29zyTZ7WIuztBG'
                                 b'L3WELM78qSwaEYh8NzwNAPqDtiuL-QmKd22om1qYGDU7cuFM-AlTKaFjsVOzBg')

        # update controller's key event verifier state
        coeKevery.processOne(ims=bytearray(cmsg))  # make copy
        # verify controller's copy of controller's event stream is updated
        assert coeKever.sn == csn
        assert coeKever.serder.diger.qb64 == coeSerder.dig

        # simulate send message from controller to validator
        valKevery.process(ims=cmsg)
        # verify validator's copy of controller's event stream is updated
        assert coeK.sn == csn
        assert coeK.serder.diger.qb64 == coeSerder.dig

        # create receipt of controller's rotation
        # create seal of validator's last establishment event
        seal = SealEvent(i=valpre,
                         s="{:x}".format(valKever.lastEst.s),
                         d=valKever.lastEst.d)
        # create validator receipt
        reserder = chit(pre=coeK.prefixer.qb64,
                        sn=coeK.sn,
                        dig=coeK.serder.diger.qb64,
                        seal=seal)
        # sign controller's event not receipt
        # look up event to sign from validator's kever for controller
        coeRotDig = bytes(valKevery.db.getKeLast(key=snKey(pre=coepre, sn=csn)))
        assert coeRotDig == coeK.serder.diger.qb64b == b'EO7V6wDClWWiN_7sfGDTD8KsfRQaHyap6fz_O4CYvsek'
        coeRotRaw = bytes(valKevery.db.getEvt(key=dgKey(pre=coepre, dig=coeRotDig)))
        assert coeRotRaw == (b'{"v":"KERI10JSON000122_","i":"EsU9ZQwug7DS-GU040Ugj1t7p6Au14VkBOCJnPYabcas",'
                             b'"s":"1","t":"rot","p":"Ey2pXEnaoQVwxA4jB6k0QH5G2Us-0juFL5hOAHAwIEkc","kt":"1'
                             b'","k":["D-HwiqmaETxls3vAVSh0xpXYTs94NUJX6juupWj_EgsA"],"n":"ED6lKZwg-BWl_jlC'
                             b'rjosQkOEhqKD4BJnlqYqWmhqPhaU","wt":"0","wr":[],"wa":[],"a":[]}')

        sigers = valMgr.sign(ser=coeRotRaw, verfers=valVerfers)

        # validator create receipt message
        vmsg = messagize(reserder, sigers)
        assert vmsg == bytearray(b'{"v":"KERI10JSON000105_","i":"EsU9ZQwug7DS-GU040Ugj1t7p6Au14VkBO'
                                 b'CJnPYabcas","s":"1","t":"vrc","d":"EO7V6wDClWWiN_7sfGDTD8KsfRQaH'
                                 b'yap6fz_O4CYvsek","a":{"i":"EBiIFxr_o1b4x1YR21PblAFpFG61qDghqFBDy'
                                 b'VSOXYW0","s":"0","d":"ElsHFkbZQjRb7xHnuE-wyiarIZ9j-1CEQ89I0E3Wev'
                                 b'cE"}}-AABAAjVFBjhbM2RdHKEk2rtHA0tXMe0iswn6IS5ShALtR3JHMz-NePCN_f'
                                 b'lUEUbV2F22CGRgmnCe71n42ywWyzsFmDg')

        # validator process own receipt in own kevery so have copy in own log
        valKevery.processOne(ims=bytearray(vmsg))  # make copy

        # Simulate send to controller of validator's receipt of controller's rotation message
        coeKevery.process(ims=vmsg)  # controller process validator's incept and receipt

        # check if receipt quadruple from validator in receipt database
        result = coeKevery.db.getVrcs(key=dgKey(pre=coeKever.prefixer.qb64,
                                                   dig=coeKever.serder.diger.qb64))
        assert bytes(result[0]) == (valKever.prefixer.qb64b +
                                    Seqner(sn=valKever.sn).qb64b +
                                    valKever.serder.diger.qb64b +
                                    sigers[0].qb64b)

        assert bytes(result[0]) == (b'EBiIFxr_o1b4x1YR21PblAFpFG61qDghqFBDyVSOXYW00AAAAAAAAAAAAAAAAAAAAAAAElsHFkbZ'
                                    b'QjRb7xHnuE-wyiarIZ9j-1CEQ89I0E3WevcEAAjVFBjhbM2RdHKEk2rtHA0tXMe0iswn6IS5ShAL'
                                    b'tR3JHMz-NePCN_flUEUbV2F22CGRgmnCe71n42ywWyzsFmDg')

        # Next Event 2 Controller Interaction
        csn += 1  # do not increment esn
        assert csn == 2
        assert cesn == 1
        coeSerder = interact(pre=coeKever.prefixer.qb64,
                             dig=coeKever.serder.diger.qb64,
                             sn=csn)
        coe_event_digs.append(coeSerder.dig)

        # sign serialization
        sigers = coeMgr.sign(coeSerder.raw, verfers=coeVerfers)

        # create msg
        cmsg = messagize(coeSerder, sigers)
        assert cmsg == bytearray(b'{"v":"KERI10JSON000098_","i":"EsU9ZQwug7DS-GU040Ugj1t7p6Au14VkBO'
                                 b'CJnPYabcas","s":"2","t":"ixn","p":"EO7V6wDClWWiN_7sfGDTD8KsfRQaH'
                                 b'yap6fz_O4CYvsek","a":[]}-AABAAstaU9Hu1ti8erlnFwEdCrXWkkkW_ydYgrr'
                                 b'ryB6EtEOrWY_tQh5jZLGRWrClefeX6AfDDw7JS5JY15n8_ueJWBQ')

        # update controller's key event verifier state
        coeKevery.processOne(ims=bytearray(cmsg))  # make copy
        # verify controller's copy of controller's event stream is updated
        assert coeKever.sn == csn
        assert coeKever.serder.diger.qb64 == coeSerder.dig

        # simulate send message from controller to validator
        valKevery.process(ims=cmsg)
        # verify validator's copy of controller's event stream is updated
        assert coeK.sn == csn
        assert coeK.serder.diger.qb64 == coeSerder.dig

        # create receipt of controller's interaction
        # create seal of validator's last est event
        seal = SealEvent(i=valpre,
                         s="{:x}".format(valKever.lastEst.s),
                         d=valKever.lastEst.d)
        # create validator receipt
        reserder = chit(pre=coeK.prefixer.qb64,
                        sn=coeK.sn,
                        dig=coeK.serder.diger.qb64,
                        seal=seal)
        # sign controller's event not receipt
        # look up event to sign from validator's kever for controller
        coeIxnDig = bytes(valKevery.db.getKeLast(key=snKey(pre=coepre, sn=csn)))
        assert coeIxnDig == coeK.serder.diger.qb64b == b'EuCLxtdKdRgzzgBnPhTwFKz36u58DqQyMqhX5CUrurPE'
        coeIxnRaw = bytes(valKevery.db.getEvt(key=dgKey(pre=coepre, dig=coeIxnDig)))
        assert coeIxnRaw == (b'{"v":"KERI10JSON000098_","i":"EsU9ZQwug7DS-GU040Ugj1t7p6Au14VkBOCJnPYabcas",'
                             b'"s":"2","t":"ixn","p":"EO7V6wDClWWiN_7sfGDTD8KsfRQaHyap6fz_O4CYvsek","a":[]}')

        sigers = valMgr.sign(ser=coeIxnRaw, verfers=valVerfers)

        # create receipt message
        vmsg = messagize(reserder, sigers)
        assert vmsg == bytearray(b'{"v":"KERI10JSON000105_","i":"EsU9ZQwug7DS-GU040Ugj1t7p6Au14VkBO'
                                 b'CJnPYabcas","s":"2","t":"vrc","d":"EuCLxtdKdRgzzgBnPhTwFKz36u58D'
                                 b'qQyMqhX5CUrurPE","a":{"i":"EBiIFxr_o1b4x1YR21PblAFpFG61qDghqFBDy'
                                 b'VSOXYW0","s":"0","d":"ElsHFkbZQjRb7xHnuE-wyiarIZ9j-1CEQ89I0E3Wev'
                                 b'cE"}}-AABAAboeSfNNgX04wuUrQp-3eY0oUzcLYnLUmtqYETBZqXEL97pjSjmm81'
                                 b'1KzCRu2cnSHVlKqzIaEBaXyBpWBDexLBQ')

        # ------------------------------END CONVERTED CODE------------------------------

        # validator process own receipt in own kevery so have copy in own log
        valKevery.processOne(ims=bytearray(vmsg))  # make copy

        # Simulate send to controller of validator's receipt of controller's rotation message
        coeKevery.process(ims=vmsg)  # controller process validator's incept and receipt

        #  check if receipt quadruple from validator in receipt database
        result = coeKevery.db.getVrcs(key=dgKey(pre=coeKever.prefixer.qb64,
                                                   dig=coeKever.serder.diger.qb64))
        assert bytes(result[0]) == (valKever.prefixer.qb64b +
                                    Seqner(sn=valKever.sn).qb64b +
                                    valKever.serder.diger.qb64b +
                                    sigers[0].qb64b)

        assert bytes(result[0]) == (b'EBiIFxr_o1b4x1YR21PblAFpFG61qDghqFBDyVSOXYW00AAAAAAAAAAAAAAAAAAAAAAAElsHFkbZ'
                                    b'QjRb7xHnuE-wyiarIZ9j-1CEQ89I0E3WevcEAAboeSfNNgX04wuUrQp-3eY0oUzcLYnLUmtqYETB'
                                    b'ZqXEL97pjSjmm811KzCRu2cnSHVlKqzIaEBaXyBpWBDexLBQ')

        #  verify final controller event state
        assert coeKever.sn == coeK.sn == csn

        db_digs = [bytes(v).decode("utf-8") for v in coeKever.baser.getKelIter(coepre)]
        assert len(db_digs) == len(coe_event_digs) == csn + 1
        assert db_digs == coe_event_digs == ['Ey2pXEnaoQVwxA4jB6k0QH5G2Us-0juFL5hOAHAwIEkc',
                                             'EO7V6wDClWWiN_7sfGDTD8KsfRQaHyap6fz_O4CYvsek',
                                             'EuCLxtdKdRgzzgBnPhTwFKz36u58DqQyMqhX5CUrurPE']

        db_digs = [bytes(v).decode("utf-8") for v in valKever.baser.getKelIter(coepre)]
        assert len(db_digs) == len(coe_event_digs) == csn + 1
        assert db_digs == coe_event_digs

        #  verify final validator event state
        assert valKever.sn == valK.sn == vsn

        db_digs = [bytes(v).decode("utf-8") for v in valKever.baser.getKelIter(valpre)]
        assert len(db_digs) == len(val_event_digs) == vsn + 1
        assert db_digs == val_event_digs == ['ElsHFkbZQjRb7xHnuE-wyiarIZ9j-1CEQ89I0E3WevcE']

        db_digs = [bytes(v).decode("utf-8") for v in coeKever.baser.getKelIter(valpre)]
        assert len(db_digs) == len(val_event_digs) == vsn + 1
        assert db_digs == val_event_digs

    assert not os.path.exists(valKevery.db.path)
    assert not os.path.exists(coeKever.baser.path)
def test_direct_mode_with_manager():
    """
    Test direct mode with transferable validator event receipts

    """
    # manual process to generate a list of secrets
    # root = pysodium.randombytes(pysodium.crypto_pwhash_SALTBYTES)
    # secrets = generateSecrets(root=root, count=8)

    # Direct Mode initiated by coe is controller, val is validator
    # but goes both ways once initiated.

    # set of secrets  (seeds for private keys)
    coeSalt = Salter(raw=b'0123456789abcdea').qb64

    # set of secrets (seeds for private keys)
    valSalt = Salter(raw=b'1123456789abcdea').qb64

    with openDB("controller") as coeLogger, openDB(
            "validator") as valLogger, openKS(
                name="controller") as coeKpr, openKS(
                    name="validator") as valKpr:
        # Init key pair manager
        coeMgr = Manager(keeper=coeKpr, salt=coeSalt)
        coeVerfers, coeDigers, cst, nst = coeMgr.incept(icount=1, ncount=1)

        #  init Keverys
        coeKevery = Kevery(db=coeLogger)
        valKevery = Kevery(db=valLogger)

        coe_event_digs = [
        ]  # list of controller's own event log digs to verify against database
        val_event_digs = [
        ]  # list of validator's own event log digs to verify against database

        #  init sequence numbers for both controller and validator
        csn = cesn = 0  # sn and last establishment sn = esn
        vsn = vesn = 0  # sn and last establishment sn = esn

        # Controller Event 0  Inception Transferable (nxt digest not empty)
        coeSerder = incept(keys=[coeVerfers[0].qb64],
                           nxt=Nexter(digs=[coeDigers[0].qb64]).qb64,
                           code=MtrDex.Blake3_256)

        assert csn == int(coeSerder.ked["s"], 16) == 0
        coepre = coeSerder.ked["i"]

        coe_event_digs.append(coeSerder.dig)
        # sign serialization
        sigers = coeMgr.sign(ser=coeSerder.raw, verfers=coeVerfers)

        #  create serialized message
        cmsg = messagize(coeSerder, sigers=sigers)

        # create own Controller Kever in  Controller's Kevery
        coeKevery.processOne(ims=bytearray(cmsg))  # send copy of cmsg
        coeKever = coeKevery.kevers[coepre]
        assert coeKever.prefixer.qb64 == coepre

        # Validator Event 0  Inception Transferable (nxt digest not empty)
        # Init key pair manager
        valMgr = Manager(keeper=valKpr, salt=valSalt)
        valVerfers, valDigers, cst, nst = valMgr.incept(icount=1, ncount=1)

        valSerder = incept(keys=[valVerfers[0].qb64],
                           nxt=Nexter(digs=[valDigers[0].qb64]).qb64,
                           code=MtrDex.Blake3_256)

        assert vsn == int(valSerder.ked["s"], 16) == 0
        valpre = valSerder.ked["i"]

        val_event_digs.append(valSerder.dig)

        # sign serialization
        sigers = valMgr.sign(valSerder.raw,
                             verfers=valVerfers)  # return Siger if index

        #  create serialized message
        vmsg = messagize(valSerder, sigers=sigers)

        # create own Validator Kever in  Validator's Kevery
        valKevery.processOne(ims=bytearray(vmsg))  # send copy of vmsg
        valKever = valKevery.kevers[valpre]
        assert valKever.prefixer.qb64 == valpre

        # simulate sending of controller's inception message to validator
        valKevery.process(ims=bytearray(cmsg))  # make copy of msg
        assert coepre in valKevery.kevers  # creates Kever for controller in validator's .kevers

        # create receipt of controller's inception
        # create seal of validator's last establishment event
        seal = SealEvent(i=valpre,
                         s="{:x}".format(valKever.lastEst.s),
                         d=valKever.lastEst.d)
        coeK = valKevery.kevers[
            coepre]  # lookup coeKever from validator's .kevers
        # create validator receipt
        reserder = chit(pre=coeK.prefixer.qb64,
                        sn=coeK.sn,
                        dig=coeK.serder.diger.qb64,
                        seal=seal)
        # Validate receipt

        # sign controller's event not receipt
        # look up event to sign from validator's kever for coe
        coeIcpDig = bytes(
            valKevery.db.getKeLast(key=snKey(pre=coepre, sn=csn)))
        assert coeIcpDig == coeK.serder.diger.qb64b
        coeIcpRaw = bytes(
            valKevery.db.getEvt(key=dgKey(pre=coepre, dig=coeIcpDig)))

        counter = Counter(CtrDex.ControllerIdxSigs)
        assert counter.qb64 == '-AAB'
        sigers = valMgr.sign(ser=coeIcpRaw,
                             verfers=valVerfers)  # return Siger if index

        # process own validator receipt in validator's Kevery so have copy in own log
        rmsg = messagize(reserder, sigers=sigers)

        valKevery.processOne(ims=bytearray(rmsg))  # process copy of rmsg

        # attach receipt message to existing message with validators inception message
        # simulate streaming. validator first sends it's inception event, then sends a receipt to controller
        vmsg.extend(rmsg)

        # Simulate sending validator's inception event and receipt of controller's inception message to controller
        coeKevery.process(
            ims=vmsg)  # controller process validator's inception and receipt

        # check if validator's Kever in controller's .kevers
        assert valpre in coeKevery.kevers
        #  check if receipt quadruple from validator in receipt database
        result = coeKevery.db.getVrcs(key=dgKey(
            pre=coeKever.prefixer.qb64, dig=coeKever.serder.diger.qb64))
        assert bytes(
            result[0]) == (valKever.prefixer.qb64b +
                           Seqner(sn=valKever.sn).qb64b +
                           valKever.serder.diger.qb64b + sigers[0].qb64b)

        # create receipt to escrow use invalid digest and sequence number so not in controller's db
        fake = reserder.dig  # some other digest
        reserder = chit(pre=coeK.prefixer.qb64, sn=10, dig=fake, seal=seal)
        # sign event not receipt
        sigers = valMgr.sign(ser=coeIcpRaw,
                             verfers=valVerfers)  # return Siger if index

        # create receipt message
        vmsg = messagize(reserder, sigers=sigers)

        coeKevery.process(
            ims=vmsg)  # controller process the escrow receipt from validator
        #  check if receipt quadruple in escrow database
        result = coeKevery.db.getVres(
            key=snKey(pre=coeKever.prefixer.qb64, sn=10))
        assert bytes(
            result[0]) == (fake.encode("utf-8") + valKever.prefixer.qb64b +
                           Seqner(sn=valKever.sn).qb64b +
                           valKever.serder.diger.qb64b + sigers[0].qb64b)

        # Send receipt from controller to validator
        # create receipt of validator's inception
        # create seal of controller's last establishment event
        seal = SealEvent(i=coepre,
                         s="{:x}".format(coeKever.lastEst.s),
                         d=coeKever.lastEst.d)
        valK = coeKevery.kevers[
            valpre]  # lookup valKever from controller's .kevers
        # create validator receipt
        reserder = chit(pre=valK.prefixer.qb64,
                        sn=valK.sn,
                        dig=valK.serder.diger.qb64,
                        seal=seal)
        # sign validator's event not receipt
        # look up event to sign from controller's kever for validator
        valIcpDig = bytes(
            coeKevery.db.getKeLast(key=snKey(pre=valpre, sn=vsn)))
        assert valIcpDig == valK.serder.diger.qb64b
        valIcpRaw = bytes(
            coeKevery.db.getEvt(key=dgKey(pre=valpre, dig=valIcpDig)))

        counter = Counter(CtrDex.ControllerIdxSigs)
        assert counter.qb64 == '-AAB'
        sigers = coeMgr.sign(ser=valIcpRaw,
                             verfers=coeVerfers)  # return Siger if index

        # create receipt message
        cmsg = messagize(reserder, sigers=sigers)
        # controller process own receipt in own Kevery so have copy in own log
        coeKevery.processOne(ims=bytearray(cmsg))  # make copy

        # Simulate sending controller's receipt of validator's inception message to validator
        valKevery.process(
            ims=cmsg)  # controller process validator's inception and receipt

        #  check if receipt quadruple from controller in validator's receipt database
        result = valKevery.db.getVrcs(key=dgKey(
            pre=valKever.prefixer.qb64, dig=valKever.serder.diger.qb64))
        assert bytes(
            result[0]) == (coeKever.prefixer.qb64b +
                           Seqner(sn=coeKever.sn).qb64b +
                           coeKever.serder.diger.qb64b + sigers[0].qb64b)

        # Controller Event 1 Rotation Transferable
        csn += 1
        cesn += 1
        assert csn == cesn == 1
        coeVerfers, coeDigers, cst, nst = coeMgr.rotate(pre=coeVerfers[0].qb64)
        coeSerder = rotate(pre=coeKever.prefixer.qb64,
                           keys=[coeVerfers[0].qb64],
                           dig=coeKever.serder.diger.qb64,
                           nxt=Nexter(digs=[coeDigers[0].qb64]).qb64,
                           sn=csn)
        coe_event_digs.append(coeSerder.dig)

        # sign serialization
        sigers = coeMgr.sign(coeSerder.raw,
                             verfers=coeVerfers)  # returns sigers

        #  create serialized message
        cmsg = messagize(coeSerder, sigers=sigers)

        # update controller's key event verifier state
        coeKevery.processOne(ims=bytearray(cmsg))  # make copy
        # verify controller's copy of controller's event stream is updated
        assert coeKever.sn == csn
        assert coeKever.serder.diger.qb64 == coeSerder.dig

        # simulate send message from controller to validator
        valKevery.process(ims=cmsg)
        # verify validator's copy of controller's event stream is updated
        assert coeK.sn == csn
        assert coeK.serder.diger.qb64 == coeSerder.dig

        # create receipt of controller's rotation
        # create seal of validator's last establishment event
        seal = SealEvent(i=valpre,
                         s="{:x}".format(valKever.lastEst.s),
                         d=valKever.lastEst.d)
        # create validator receipt
        reserder = chit(pre=coeK.prefixer.qb64,
                        sn=coeK.sn,
                        dig=coeK.serder.diger.qb64,
                        seal=seal)
        # sign controller's event not receipt
        # look up event to sign from validator's kever for controller
        coeRotDig = bytes(
            valKevery.db.getKeLast(key=snKey(pre=coepre, sn=csn)))
        assert coeRotDig == coeK.serder.diger.qb64b
        coeRotRaw = bytes(
            valKevery.db.getEvt(key=dgKey(pre=coepre, dig=coeRotDig)))

        sigers = valMgr.sign(ser=coeRotRaw, verfers=valVerfers)

        # validator create receipt message
        vmsg = messagize(reserder, sigers=sigers)

        # validator process own receipt in own kevery so have copy in own log
        valKevery.processOne(ims=bytearray(vmsg))  # make copy

        # Simulate send to controller of validator's receipt of controller's rotation message
        coeKevery.process(
            ims=vmsg)  # controller process validator's incept and receipt

        # check if receipt quadruple from validator in receipt database
        result = coeKevery.db.getVrcs(key=dgKey(
            pre=coeKever.prefixer.qb64, dig=coeKever.serder.diger.qb64))
        assert bytes(
            result[0]) == (valKever.prefixer.qb64b +
                           Seqner(sn=valKever.sn).qb64b +
                           valKever.serder.diger.qb64b + sigers[0].qb64b)

        # Next Event 2 Controller Interaction
        csn += 1  # do not increment esn
        assert csn == 2
        assert cesn == 1
        coeSerder = interact(pre=coeKever.prefixer.qb64,
                             dig=coeKever.serder.diger.qb64,
                             sn=csn)
        coe_event_digs.append(coeSerder.dig)

        # sign serialization
        sigers = coeMgr.sign(coeSerder.raw, verfers=coeVerfers)

        # create msg
        cmsg = messagize(coeSerder, sigers=sigers)

        # update controller's key event verifier state
        coeKevery.processOne(ims=bytearray(cmsg))  # make copy
        # verify controller's copy of controller's event stream is updated
        assert coeKever.sn == csn
        assert coeKever.serder.diger.qb64 == coeSerder.dig

        # simulate send message from controller to validator
        valKevery.process(ims=cmsg)
        # verify validator's copy of controller's event stream is updated
        assert coeK.sn == csn
        assert coeK.serder.diger.qb64 == coeSerder.dig

        # create receipt of controller's interaction
        # create seal of validator's last est event
        seal = SealEvent(i=valpre,
                         s="{:x}".format(valKever.lastEst.s),
                         d=valKever.lastEst.d)
        # create validator receipt
        reserder = chit(pre=coeK.prefixer.qb64,
                        sn=coeK.sn,
                        dig=coeK.serder.diger.qb64,
                        seal=seal)
        # sign controller's event not receipt
        # look up event to sign from validator's kever for controller
        coeIxnDig = bytes(
            valKevery.db.getKeLast(key=snKey(pre=coepre, sn=csn)))
        assert coeIxnDig == coeK.serder.diger.qb64b
        coeIxnRaw = bytes(
            valKevery.db.getEvt(key=dgKey(pre=coepre, dig=coeIxnDig)))

        sigers = valMgr.sign(ser=coeIxnRaw, verfers=valVerfers)

        # create receipt message
        vmsg = messagize(reserder, sigers=sigers)

        # validator process own receipt in own kevery so have copy in own log
        valKevery.processOne(ims=bytearray(vmsg))  # make copy

        # Simulate send to controller of validator's receipt of controller's rotation message
        coeKevery.process(
            ims=vmsg)  # controller process validator's incept and receipt

        #  check if receipt quadruple from validator in receipt database
        result = coeKevery.db.getVrcs(key=dgKey(
            pre=coeKever.prefixer.qb64, dig=coeKever.serder.diger.qb64))
        assert bytes(
            result[0]) == (valKever.prefixer.qb64b +
                           Seqner(sn=valKever.sn).qb64b +
                           valKever.serder.diger.qb64b + sigers[0].qb64b)

        #  verify final controller event state
        assert coeKever.sn == coeK.sn == csn

        db_digs = [
            bytes(v).decode("utf-8") for v in coeKever.baser.getKelIter(coepre)
        ]
        assert len(db_digs) == len(coe_event_digs) == csn + 1
        assert db_digs == coe_event_digs

        db_digs = [
            bytes(v).decode("utf-8") for v in valKever.baser.getKelIter(coepre)
        ]
        assert len(db_digs) == len(coe_event_digs) == csn + 1
        assert db_digs == coe_event_digs

        #  verify final validator event state
        assert valKever.sn == valK.sn == vsn

        db_digs = [
            bytes(v).decode("utf-8") for v in valKever.baser.getKelIter(valpre)
        ]
        assert len(db_digs) == len(val_event_digs) == vsn + 1
        assert db_digs == val_event_digs

        db_digs = [
            bytes(v).decode("utf-8") for v in coeKever.baser.getKelIter(valpre)
        ]
        assert len(db_digs) == len(val_event_digs) == vsn + 1
        assert db_digs == val_event_digs

    assert not os.path.exists(valKevery.db.path)
    assert not os.path.exists(coeKever.baser.path)
Exemple #11
0
def test_weighted():
    """
    Test multisig with weighted threshold

    """
    wesSalt = coring.Salter(raw=b'0123456789abcdef').qb64  # init wes Salter

    # init event DB and keep DB
    with dbing.openDB(name="wes") as wesDB, keeping.openKS(
            name="wes") as wesKS:
        # Init key pair manager
        wesMgr = keeping.Manager(keeper=wesKS, salt=wesSalt)

        # Init Kevery with event DB
        wesKvy = eventing.Kevery(db=wesDB)

        # create inception event for Wes with 3 keys each in incept and next sets
        # defaults are algo salty and rooted
        sith = ["1/2", "1/2", "1/2"]  #  2 of 3 but with weighted threshold
        nxtsith = ["1/2", "1/2", "1/2"]
        verfers, digers, cst, nst = wesMgr.incept(icount=3,
                                                  isith=sith,
                                                  ncount=3,
                                                  nsith=nxtsith,
                                                  stem='wes',
                                                  temp=True)
        assert cst == nst == sith

        wesSrdr = eventing.incept(
            keys=[verfer.qb64 for verfer in verfers],
            sith=sith,
            nxt=coring.Nexter(sith=nxtsith,
                              digs=[diger.qb64 for diger in digers]).qb64,
            code=coring.MtrDex.Blake3_256)

        wesPre = wesSrdr.ked["i"]

        wesMgr.move(old=verfers[0].qb64,
                    new=wesPre)  # move key pair label to prefix

        sigers = wesMgr.sign(ser=wesSrdr.raw, verfers=verfers)

        msg = bytearray(wesSrdr.raw)
        counter = coring.Counter(coring.CtrDex.ControllerIdxSigs,
                                 count=len(sigers))
        msg.extend(counter.qb64b)
        for siger in sigers:
            msg.extend(siger.qb64b)

        assert msg == bytearray(
            b'{"v":"KERI10JSON00015b_","i":"EX0WJtv6vc0IWzOqa92Pv9v9pgs1f0BfIV'
            b'rSch648Zf0","s":"0","t":"icp","kt":["1/2","1/2","1/2"],"k":["DK4'
            b'OJI8JOr6oEEUMeSF_X-SbKysfwpKwW-ho5KARvH5c","D1RZLgYke0GmfZm-CH8A'
            b'sW4HoTU4m-2mFgu8kbwp8jQU","DBVwzum-jPfuUXUcHEWdplB4YcoL3BWGXK0TM'
            b'oF_NeFU"],"n":"EhJGhyJQTpSlZ9oWfQT-lHNl1woMazLC42O89fRHocTI","bt'
            b'":"0","b":[],"c":[],"a":[]}-AADAAKWMK8k4Po2A0rBrUBjBom73DfTCNg_b'
            b'iwR-_LWm6DMHZHGDfCuOmEyR8sEdp7cPxhsavq4istIZ_QQ42yyUcDAABeTClYkN'
            b'-yjbW3Kz3ot6MvAt5Se-jmcjhu-Cfsv4m_GKYgc_qwel1SbAcqF0TiY0EHFdjNKv'
            b'Ikg3q19KlhSbuBgACA6QMnsnZuy66xrZVg3c84mTodZCEvOFrAIDQtm8jeXeCTg7'
            b'yFauoQECZyNIlUnnxVHuk2_Fqi5xK_Lu9Pt76Aw')

        # apply msg to Wes's Kevery
        wesKvy.process(ims=bytearray(msg))  # process local copy of msg
        wesK = wesKvy.kevers[wesPre]  # kever created so event was validated
        assert wesK.prefixer.qb64 == wesPre
        assert wesK.serder.diger.qb64 == wesSrdr.dig  # key state updated so event was validated

        # create interaction event for Wes
        wesSrdr = eventing.interact(pre=wesK.prefixer.qb64,
                                    dig=wesK.serder.diger.qb64,
                                    sn=wesK.sn + 1,
                                    data=[])

        sigers = wesMgr.sign(ser=wesSrdr.raw, verfers=wesK.verfers)

        msg = bytearray(wesSrdr.raw)
        counter = coring.Counter(coring.CtrDex.ControllerIdxSigs,
                                 count=len(sigers))
        msg.extend(counter.qb64b)
        for siger in sigers:
            msg.extend(siger.qb64b)

        assert msg == bytearray(
            b'{"v":"KERI10JSON000098_","i":"EX0WJtv6vc0IWzOqa92Pv9v9pgs1f0BfIV'
            b'rSch648Zf0","s":"1","t":"ixn","p":"EInuqF20s1O0JhVJaOuKCZZDDyw6D'
            b'YxATbiuC5Hv3WXs","a":[]}-AADAAmg8UoBCTlnENiySBpn6j7mR1w0gdkfC8Ai'
            b'aYL5NCFfePp5ZK3CmnP7oQdj_ggiNp9FZNE0Q69A99wNK5FrwzDgABQZZunmJr2X'
            b'3BYgX34-6SOpzkHZQS99ZL0tDsDyUIL7jZhD1e1203Fh6BnkDjzum2au2dGHJcIP'
            b'giFGfDsrI5DwACwwYqqYYdEXeLpx_o6LTSKU-Fz_WF2gebP9Z72bZ75atg7_ZM3H'
            b'g6hhztstGt8TthRQ0TJn6rkvatkbn6yzRjBw')

        # apply msg to wes's Kevery
        wesKvy.process(ims=bytearray(msg))  # process local copy of msg
        assert wesK.serder.diger.qb64 == wesSrdr.dig  # key state updated so event was validated

        # Create rotation event for Wes
        # get current keys as verfers and next digests as digers
        nxtsith = ["1/2", "1/2", "1/2"]  #  2 of 3 but with weighted threshold
        verfers, digers, cst, nst = wesMgr.rotate(pre=wesPre,
                                                  count=3,
                                                  sith=nxtsith,
                                                  temp=True)
        assert nst == nxtsith

        wesSrdr = eventing.rotate(
            pre=wesK.prefixer.qb64,
            keys=[verfer.qb64 for verfer in verfers],
            sith=sith,
            dig=wesK.serder.diger.qb64,
            nxt=coring.Nexter(sith=nxtsith,
                              digs=[diger.qb64 for diger in digers]).qb64,
            sn=wesK.sn + 1,
            data=[])

        sigers = wesMgr.sign(ser=wesSrdr.raw, verfers=verfers)

        msg = bytearray(wesSrdr.raw)
        counter = coring.Counter(coring.CtrDex.ControllerIdxSigs,
                                 count=len(sigers))
        msg.extend(counter.qb64b)
        for siger in sigers:
            msg.extend(siger.qb64b)

        assert bytearray(
            b'{"v":"KERI10JSON000190_","i":"EX0WJtv6vc0IWzOqa92Pv9v9pgs1f0BfIV'
            b'rSch648Zf0","s":"2","t":"rot","p":"EznUtmH2XJF04dyqpUHLzwkNgwk6D'
            b'jbDFbjXVI3UJLe0","kt":["1/2","1/2","1/2"],"k":["DeonYM2bKnAwp6VZ'
            b'cuCXdX72kNFw56czlZ_Tc7XHHVGI","DQghKIy-2do9OkweSgazh3Ql1vCOt5bnc'
            b'5QF8x50tRoU","DNAUn-5dxm6b8Njo01O0jlStMRCjo9FYQA2mfqFW1_JA"],"n"'
            b':"EX5fxvjOg5VuDboWbqnTjTPpXa3nNIm99hlsB1EmhTo8","bt":"0","br":[]'
            b',"ba":[],"a":[]}-AADAAahiASmZJY2KjXKRvVwdRSESmesNsfxUnOQ6buEk6S-'
            b'4rxRdztde_6_CX2Q4MyUSErHMtmLhesrKjenPBairZAQABbnbZ3lOKcKCMmLYtpT'
            b'hDEm-tRTsnEh_8loXpA6G3q1oJZNeVJphJjPm2HR0mX2ptC2DEt6p9i4GH1Y56HY'
            b'TsAgACqF6e_29QkxgXvqDLEUnAIB_XJ7SUhDNpt3cYk6pF1-ULgrhGdZLS1h-c_V'
            b'KpKITRx3ZTvme7sKbvr_NfR-0ECg')

        # apply msg to Wes's Kevery
        wesKvy.process(ims=bytearray(msg))  # process local copy of msg
        assert wesK.serder.diger.qb64 == wesSrdr.dig  # key state updated so event was validated

        # Create rotation event for Wes
        # get current keys as verfers and next digests as digers
        sith = nxtsith  # rotate so nxtsith is now current sith and need new nextsith
        #  2 of first 3 and 1 of last 2
        nxtsith = [["1/2", "1/2", "1/2"], ["1/1", "1/1"]]
        verfers, digers, cst, nst = wesMgr.rotate(pre=wesPre,
                                                  count=5,
                                                  sith=nxtsith,
                                                  temp=True)
        assert cst == sith
        assert nst == nxtsith

        wesSrdr = eventing.rotate(
            pre=wesK.prefixer.qb64,
            keys=[verfer.qb64 for verfer in verfers],
            sith=sith,
            dig=wesK.serder.diger.qb64,
            nxt=coring.Nexter(sith=nxtsith,
                              digs=[diger.qb64 for diger in digers]).qb64,
            sn=wesK.sn + 1,
            data=[])

        sigers = wesMgr.sign(ser=wesSrdr.raw, verfers=verfers)

        msg = bytearray(wesSrdr.raw)
        counter = coring.Counter(coring.CtrDex.ControllerIdxSigs,
                                 count=len(sigers))
        msg.extend(counter.qb64b)
        for siger in sigers:
            msg.extend(siger.qb64b)

        assert msg == bytearray(
            b'{"v":"KERI10JSON000190_","i":"EX0WJtv6vc0IWzOqa92Pv9v9pgs1f0BfIV'
            b'rSch648Zf0","s":"3","t":"rot","p":"EK1BTah7lTyaaol7sLdg9uObplAjP'
            b'o_JOz1m4WPaLJBw","kt":["1/2","1/2","1/2"],"k":["D7WWKDLVwYxYMLAj'
            b'DceIEs66xPMY4Afzx-RQw2x0mQzI","Dmg6Aah8qyKKDiQyNXTiO71QJwizjZfGM'
            b'61BA-s0A5F4","DS3fhKpvPCDL5WmfN4_PkmJMMsSCdRTxG24OQuf_EmHQ"],"n"'
            b':"EcM4iw7fElXWhad8V-za4Px7nBKjndxoh3XZRkohghKY","bt":"0","br":[]'
            b',"ba":[],"a":[]}-AADAAl6FtC6Ynm8RAoa2utkIqJX5xW1ZxIkEH7I_MUCXL0p'
            b'OUT8P0lCgPzn9dvmUagHbzZ4GIwOBqGI-lQJbeESnZBQAB_nJLQJTf9t1NJxNoP5'
            b'gve9QEQbHFkn2aX6O78_bzOGUf01y8KSl-ugi0_B9-w0dk4J7gjYbv7RhG-TmFPE'
            b'mEAAACEpJiOTGarwK4jWZ9ZKue05uYPDW5wp4HC8VIt6R93h7WHLqqLVH1m3n5jd'
            b'AkiM4RFdhUqBwt-jKBfHQmVoBBCA')

        # apply msg to Wes's Kevery
        wesKvy.process(ims=bytearray(msg))  # process local copy of msg
        assert wesK.serder.diger.qb64 == wesSrdr.dig  # key state updated so event was validated

        # Create rotation event for Wes
        # get current keys as verfers and next digests as digers
        sith = nxtsith  # rotate so nxtsith is now current sith and need new nextsith
        #  2 of first 3 and 1 of last 2
        nxtsith = [["1/2", "1/2", "1/2"], ["1/1", "1/1"]]
        verfers, digers, cst, nst = wesMgr.rotate(pre=wesPre,
                                                  count=5,
                                                  sith=nxtsith,
                                                  temp=True)
        assert cst == nst == nxtsith

        wesSrdr = eventing.rotate(
            pre=wesK.prefixer.qb64,
            keys=[verfer.qb64 for verfer in verfers],
            sith=sith,
            dig=wesK.serder.diger.qb64,
            nxt=coring.Nexter(sith=nxtsith,
                              digs=[diger.qb64 for diger in digers]).qb64,
            sn=wesK.sn + 1,
            data=[])

        sigers = wesMgr.sign(ser=wesSrdr.raw, verfers=verfers)

        msg = bytearray(wesSrdr.raw)
        counter = coring.Counter(coring.CtrDex.ControllerIdxSigs,
                                 count=len(sigers))
        msg.extend(counter.qb64b)
        for siger in sigers:
            msg.extend(siger.qb64b)

        assert msg == bytearray(
            b'{"v":"KERI10JSON0001fe_","i":"EX0WJtv6vc0IWzOqa92Pv9v9pgs1f0BfIV'
            b'rSch648Zf0","s":"4","t":"rot","p":"EVfMO5GK8tg4KE8XCelX1s_TG_Hqr'
            b'_kzb3ghIBYvzC6U","kt":[["1/2","1/2","1/2"],["1/1","1/1"]],"k":["'
            b'DToUWoemnetqJoLFIqDI7lxIJEfF0W7xG5ZlqAseVUQc","Drz-IZjko61q-sPMD'
            b'IW6n-0NGFubbXiZhzWZrO_BZ0Wc","DiGwL3hjQqiUgQlFPeA6kRR1EBXX0vSLm9'
            b'b6QhPS8IkQ","Dxj5pcStgZ6CbQ2YktNaj8KLE_g9YAOZF6AL9fyLcWQw","DE5z'
            b'r5eH8EUVQXyAaxWfQUWkGCId-QDCvvxMT77ibj2Q"],"n":"E3in3Z14va0kk4Wq'
            b'd3vcCAojKNtQq7ZTrQaavR8x0yu4","bt":"0","br":[],"ba":[],"a":[]}-A'
            b'AFAAdxx4UfoNYdXckLY9nSYvqYLJzvIRhixshBbqkQ6uwvqaVmwPqmvck0V9xl5x'
            b'3ssVclasm8Ga3FTkcbmbV2jXDgABBWUhku-qDq8wYn5XMQuKzidAsA6bth8-EsCx'
            b'9WwTIqWBR-AecW-3X1haAyJshqplDsS9MnZfVgmSHokwdLnRCQACp2tB0pFRv_C7'
            b'nUXPf9rFKvlWUllrsY6Y1_F4bAOMvyCU-PES4HwyUQv3kQnLxEqnf0fbOYdHJNGo'
            b'sXi-UqL9BAADW89YpsS5m3IASAtXvXEPez-0y11JRP8bAiUUBdIxGB9ms79jPZnQ'
            b'tF3045byf3m0Dvi91Y9d4sh-xkzZ15v9DAAE6QR9qNXnHXLisg4Mbadav9AdMjS4'
            b'uz6jNG1AL6UCa7P90Y53v1V6VRaOPu_RTWXcXYRGqA9BHJ2rLNYWJTJTBA')

        # apply msg to Wes's Kevery
        wesKvy.process(ims=bytearray(msg))  # process local copy of msg
        assert wesK.serder.diger.qb64 == wesSrdr.dig  # key state updated so event was validated

    assert not os.path.exists(wesKS.path)
    assert not os.path.exists(wesDB.path)
    """End Test"""
Exemple #12
0
def test_issuer():
    with dbing.openDB(name="bob") as db, keeping.openKS(name="bob") as kpr:
        hab = buildHab(db, kpr)

        # setup issuer with defaults for allowBackers, backers and estOnly
        issuer = Issuer(hab=hab, name="test")
        assert issuer.incept == (b'{"v":"KERI10JSON0000a9_","i":"EoN_Ln_JpgqsIys-jDOH8oWdxgWqs7hzkD'
                                b'GeLWHb9vSY","ii":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMtY",'
                                b'"s":"0","t":"vcp","c":[],"bt":"0","b":[]}-eABEaKJ0FoLxO1TYmyuprg'
                                b'uKO7kJ7Hbn0m0Wuk5aMtSrMtY0AAAAAAAAAAAAAAAAAAAAAAQEoDaZfC2yqtPwKJ'
                                b'BrhAGzP20SOslMZ-eQ7hAbl3w4JP0')
        assert issuer.ianchor == (b'{"v":"KERI10JSON0000f9_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                                b'k5aMtSrMtY","s":"1","t":"ixn","p":"Eg3wsIOW3RdCqhcG4xZ4uZhTA_qTE'
                                b'24DoLeyjFBB8rks","a":["EoN_Ln_JpgqsIys-jDOH8oWdxgWqs7hzkDGeLWHb9'
                                b'vSY","0","EvpB-_BWD7tOhLI0cDyEQbziBt6IMyQnkrh0booR4vhg"]}-AABAAw'
                                b'3jupSvehfh-Ow0v_E3Er49HUvwQp0Qa0P9KYNdaf9ihtzZU0bJtrbIW1z6eMoR3B'
                                b'52SDSxw9gfMmqlZRZfaBQ')
        # ensure the digest in the seal from the key event matches the transacript event digest
        ser = Serder(raw=issuer.incept)
        assert ser.diger.qb64 == 'EvpB-_BWD7tOhLI0cDyEQbziBt6IMyQnkrh0booR4vhg'

        tevt, kevt = issuer.rotate(adds=["EqoNZAX5Lu8RuHzwwyn5tCZTe-mDBq5zusCrRo5TDugs"])
        assert tevt == (b'{"v":"KERI10JSON0000d8_","i":"EoN_Ln_JpgqsIys-jDOH8oWdxgWqs7hzkD'
                        b'GeLWHb9vSY","p":"EvpB-_BWD7tOhLI0cDyEQbziBt6IMyQnkrh0booR4vhg","'
                        b's":"1","t":"vrt","bt":"1","br":[],"ba":["EqoNZAX5Lu8RuHzwwyn5tCZ'
                        b'Te-mDBq5zusCrRo5TDugs"]}-eABEaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5'
                        b'aMtSrMtY0AAAAAAAAAAAAAAAAAAAAAAgEoDJpf8xcmVXj3chkgVpVXvFgAaHyohm'
                        b'v-Bkgjsf5yf4')
        assert kevt == (b'{"v":"KERI10JSON0000f9_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                        b'k5aMtSrMtY","s":"2","t":"ixn","p":"EoDaZfC2yqtPwKJBrhAGzP20SOslM'
                        b'Z-eQ7hAbl3w4JP0","a":["EoN_Ln_JpgqsIys-jDOH8oWdxgWqs7hzkDGeLWHb9'
                        b'vSY","1","Ex1ZICku_jaiYzNIjfw1Q46T_srpyz7YJwpqS1xA9xuo"]}-AABAAG'
                        b'XF1gyvCxtP3GaL-MenYOYSAqf0_BzzyRknY6mhCohXK5cIA0CrJfkPandYmDvGxo'
                        b'63K0BPxCR3ey6PbjabkBg')
        ser = Serder(raw=tevt)
        assert ser.diger.qb64 == 'Ex1ZICku_jaiYzNIjfw1Q46T_srpyz7YJwpqS1xA9xuo'

        tevt, kevt = issuer.issue(vcdig="EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3ULvaU6Z-i0d8")
        assert tevt == (b'{"v":"KERI10JSON000105_","i":"EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3UL'
                        b'vaU6Z-i0d8","ii":"EoN_Ln_JpgqsIys-jDOH8oWdxgWqs7hzkDGeLWHb9vSY",'
                        b'"s":"0","t":"bis","ra":{"i":"EoN_Ln_JpgqsIys-jDOH8oWdxgWqs7hzkDG'
                        b'eLWHb9vSY","s":1,"d":"Ex1ZICku_jaiYzNIjfw1Q46T_srpyz7YJwpqS1xA9x'
                        b'uo"}}-eABEaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMtY0AAAAAAAAAA'
                        b'AAAAAAAAAAAAwEJDkcdO3kE_gFLxSZA53HsEr9DK3gI1j6qEcwsZjzcZo')
        assert kevt == (b'{"v":"KERI10JSON0000f9_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                        b'k5aMtSrMtY","s":"3","t":"ixn","p":"EoDJpf8xcmVXj3chkgVpVXvFgAaHy'
                        b'ohmv-Bkgjsf5yf4","a":["EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3ULvaU6Z-i'
                        b'0d8","0","E_RmCtCYGKOUj9-r2HbZlTOTzrViYvlthhlhZFElyjzw"]}-AABAAN'
                        b'bk_fVhHJVPZpwLA2Bmj9ZvD6T885Krwd8RJn2AGgQHVux7fsr-ZW4BXtFT7DW9Cj'
                        b'jXkxP8gBSmIQt9gHPljBA')
        ser = Serder(raw=tevt)
        assert ser.diger.qb64 == 'E_RmCtCYGKOUj9-r2HbZlTOTzrViYvlthhlhZFElyjzw'

        tevt, kevt = issuer.revoke(vcdig="EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3ULvaU6Z-i0d8")
        assert tevt == (b'{"v":"KERI10JSON000104_","i":"EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3UL'
                        b'vaU6Z-i0d8","s":"1","t":"brv","p":"E_RmCtCYGKOUj9-r2HbZlTOTzrViY'
                        b'vlthhlhZFElyjzw","ra":{"i":"EoN_Ln_JpgqsIys-jDOH8oWdxgWqs7hzkDGe'
                        b'LWHb9vSY","s":1,"d":"Ex1ZICku_jaiYzNIjfw1Q46T_srpyz7YJwpqS1xA9xu'
                        b'o"}}-eABEaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMtY0AAAAAAAAAAA'
                        b'AAAAAAAAAABAEUQewfkI5B3VEU1w0BPpikSBdchw52PW4MrMcgizKVpc')

        assert kevt == (b'{"v":"KERI10JSON0000f9_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                        b'k5aMtSrMtY","s":"4","t":"ixn","p":"EJDkcdO3kE_gFLxSZA53HsEr9DK3g'
                        b'I1j6qEcwsZjzcZo","a":["EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3ULvaU6Z-i'
                        b'0d8","1","Ei1-r5vju2kh44KY09nd1KzeB1mq5_a33CwlYFs0tH3c"]}-AABAA3'
                        b'3POBHT4hao0mAXiOAsji3ft-NLbGRAVJ1kh1VBu9eTddSO6mUYwZpQCDgQc2SwqS'
                        b'C7VuegB_UVHbRtQcNiLCA')
        ser = Serder(raw=tevt)
        assert ser.diger.qb64 == 'Ei1-r5vju2kh44KY09nd1KzeB1mq5_a33CwlYFs0tH3c'

        # issuer, not allowed to issue backers
        issuer = Issuer(hab=hab, name="test", allowBackers=False)
        assert issuer.incept == (b'{"v":"KERI10JSON0000ad_","i":"Ezm53Qww2LTJ1yksEL06Wtt-5D23QKdJEG'
                                b'I0egFyLehw","ii":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMtY",'
                                b'"s":"0","t":"vcp","c":["NB"],"bt":"0","b":[]}-eABEaKJ0FoLxO1TYmy'
                                b'uprguKO7kJ7Hbn0m0Wuk5aMtSrMtY0AAAAAAAAAAAAAAAAAAAAABQEAUius1E3mN'
                                b'za_tVygjmKAd5tIz9JVAP8PTLaEHwnx7w')
        assert issuer.ianchor == (b'{"v":"KERI10JSON0000f9_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                                b'k5aMtSrMtY","s":"5","t":"ixn","p":"EUQewfkI5B3VEU1w0BPpikSBdchw5'
                                b'2PW4MrMcgizKVpc","a":["Ezm53Qww2LTJ1yksEL06Wtt-5D23QKdJEGI0egFyL'
                                b'ehw","0","ElYstqTocyQixLLz4zYCAs2unaFco_p6LqH0W01loIg4"]}-AABAAN'
                                b'Tokkv5aZ_MPLauMFsgzASyFs5qMb4-fo7HIofmpRa-XMfDS9vccchXXZb47774Be'
                                b'YR6Nljg9m_ehk3b8NnTCg')
        with pytest.raises(ValueError):
            issuer.rotate(adds=["EqoNZAX5Lu8RuHzwwyn5tCZTe-mDBq5zusCrRo5TDugs"])

        tevt, kevt = issuer.issue(vcdig="EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3ULvaU6Z-i0d8")
        assert tevt == (b'{"v":"KERI10JSON000092_","i":"EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3UL'
                        b'vaU6Z-i0d8","s":"0","t":"iss","ri":"Ezm53Qww2LTJ1yksEL06Wtt-5D23'
                        b'QKdJEGI0egFyLehw"}-eABEaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrM'
                        b'tY0AAAAAAAAAAAAAAAAAAAAABgErPUCiDOsokTzqSx3ktSFx6P6bhfWLps3PbvbY'
                        b'ZIdjMw')
        assert kevt == (b'{"v":"KERI10JSON0000f9_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                        b'k5aMtSrMtY","s":"6","t":"ixn","p":"EAUius1E3mNza_tVygjmKAd5tIz9J'
                        b'VAP8PTLaEHwnx7w","a":["EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3ULvaU6Z-i'
                        b'0d8","0","EXTVuADWAm9XOG6XKMyKRs8FO2dYPFo12rinap96BUjU"]}-AABAAf'
                        b'tQ5Ccj6aiZCVArCRlcBPhUKnO0m5q75dRgs316rxbsbEdXC3lB2AC4TWCMB0EVv5'
                        b'rzGRu6Gnw6134VpkkrPCw')


        tevt, kevt = issuer.revoke(vcdig="EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3ULvaU6Z-i0d8")
        assert tevt == (b'{"v":"KERI10JSON000091_","i":"EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3UL'
                        b'vaU6Z-i0d8","s":"1","t":"rev","p":"EXTVuADWAm9XOG6XKMyKRs8FO2dYP'
                        b'Fo12rinap96BUjU"}-eABEaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMt'
                        b'Y0AAAAAAAAAAAAAAAAAAAAABwEpzwTULkTXErmB12S-vR4Ysi22kFCtqaV9_uoP2'
                        b'zBWNE')
        assert kevt == (b'{"v":"KERI10JSON0000f9_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                        b'k5aMtSrMtY","s":"7","t":"ixn","p":"ErPUCiDOsokTzqSx3ktSFx6P6bhfW'
                        b'Lps3PbvbYZIdjMw","a":["EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3ULvaU6Z-i'
                        b'0d8","1","EgaGSsEExjY_19HbFsfWjtrj_nmtYmDU23qaod0KSr2o"]}-AABAAM'
                        b'w_8vSj-GBc1dMDTeNZg1sRhqOOBIROUDXAEvY5nICWhgp1RP-XYOYaVlJpLOLN6M'
                        b'nm6JU_z3rvsq475D4WsBQ')
        # issuer, allowed backers, initial set of backers
        issuer = Issuer(hab=hab, name="test", baks=["EqoNZAX5Lu8RuHzwwyn5tCZTe-mDBq5zusCrRo5TDugs"])
        assert issuer.incept == (b'{"v":"KERI10JSON0000d7_","i":"EZRowynuVBviCH0ZfUx24mkMWn-jGRBm78'
                                b'p90WN3sG3I","ii":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMtY",'
                                b'"s":"0","t":"vcp","c":[],"bt":"1","b":["EqoNZAX5Lu8RuHzwwyn5tCZT'
                                b'e-mDBq5zusCrRo5TDugs"]}-eABEaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5a'
                                b'MtSrMtY0AAAAAAAAAAAAAAAAAAAAACAERI1IUUGtVVKDEqLw59qPJzIIwRFVU1sN'
                                b'n__B8Z6GgXk')
        assert issuer.ianchor == (b'{"v":"KERI10JSON0000f9_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                                b'k5aMtSrMtY","s":"8","t":"ixn","p":"EpzwTULkTXErmB12S-vR4Ysi22kFC'
                                b'tqaV9_uoP2zBWNE","a":["EZRowynuVBviCH0ZfUx24mkMWn-jGRBm78p90WN3s'
                                b'G3I","0","EMMt2bfrg5ACOrCLQRuU21qWMBxDPwzIhOANvHKAGJWc"]}-AABAAZ'
                                b'Zo51JRK2aU0zppx12N584195BP-UjAtCly9_Z1dfuoUQz5yV4m_NJSt-w86t9VsH'
                                b'UMDtI20EbRtenypM3NyDw')

        tevt, kevt = issuer.issue(vcdig="EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3ULvaU6Z-i0d8")
        assert tevt == (b'{"v":"KERI10JSON000105_","i":"EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3UL'
                        b'vaU6Z-i0d8","ii":"EZRowynuVBviCH0ZfUx24mkMWn-jGRBm78p90WN3sG3I",'
                        b'"s":"0","t":"bis","ra":{"i":"EZRowynuVBviCH0ZfUx24mkMWn-jGRBm78p'
                        b'90WN3sG3I","s":0,"d":"EMMt2bfrg5ACOrCLQRuU21qWMBxDPwzIhOANvHKAGJ'
                        b'Wc"}}-eABEaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMtY0AAAAAAAAAA'
                        b'AAAAAAAAAAACQETPkpmuLwJY4SXHPw0kjrKG5CYTTkf-OMxTgDnBFx7_k')
        assert kevt == (b'{"v":"KERI10JSON0000f9_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                        b'k5aMtSrMtY","s":"9","t":"ixn","p":"ERI1IUUGtVVKDEqLw59qPJzIIwRFV'
                        b'U1sNn__B8Z6GgXk","a":["EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3ULvaU6Z-i'
                        b'0d8","0","Eu9JBjmUh10w5FLNORAdHuICsQ0VJ7WLoxvAA56fQr0w"]}-AABAAY'
                        b'Dm3lQah_ZQhX9wJmgHY6eWTtFozD2HLA004TIm-w2LIdqS-tw6pHSNgYQKBvNt0T'
                        b'4t2Y1pL0rsDBTGAEaw_Cg')

        tevt, kevt = issuer.rotate(adds=["EtEBUSHpJDMfzHdDt3QCtrA-iVlP-0DT03AdqeeDa7vs",
                                         "ERVZTggTUOPmLcWBESrxcI-VsB48FerF6sz2boziikcY"])
        vrtser = Serder(raw=tevt)

        assert tevt == (b'{"v":"KERI10JSON000107_","i":"EZRowynuVBviCH0ZfUx24mkMWn-jGRBm78'
                        b'p90WN3sG3I","p":"EMMt2bfrg5ACOrCLQRuU21qWMBxDPwzIhOANvHKAGJWc","'
                        b's":"1","t":"vrt","bt":"3","br":[],"ba":["EtEBUSHpJDMfzHdDt3QCtrA'
                        b'-iVlP-0DT03AdqeeDa7vs","ERVZTggTUOPmLcWBESrxcI-VsB48FerF6sz2bozi'
                        b'ikcY"]}-eABEaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMtY0AAAAAAAA'
                        b'AAAAAAAAAAAAACgE58EtRRxJROE7qmMnHV6fnP8FeFTBkX8eMlZbMNDFY6w')

        assert kevt == (b'{"v":"KERI10JSON0000f9_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                        b'k5aMtSrMtY","s":"a","t":"ixn","p":"ETPkpmuLwJY4SXHPw0kjrKG5CYTTk'
                        b'f-OMxTgDnBFx7_k","a":["EZRowynuVBviCH0ZfUx24mkMWn-jGRBm78p90WN3s'
                        b'G3I","1","EKwtenOwTRhQCzIiBWTPWPCWB6PQ9sF0pnPrsCS_YhuA"]}-AABAAp'
                        b'fZ6LoLMi4L_nabHRQZgW59NT3xt6IYrZ5D4lc7gUoalP-VraZ-TIThFSJSKsZER7'
                        b'W0Ev1FD6Zn5pb1JTAgKAg')

        tevt, kevt = issuer.revoke(vcdig="EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3ULvaU6Z-i0d8")
        assert tevt == (b'{"v":"KERI10JSON000104_","i":"EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3UL'
                        b'vaU6Z-i0d8","s":"1","t":"brv","p":"Eu9JBjmUh10w5FLNORAdHuICsQ0VJ'
                        b'7WLoxvAA56fQr0w","ra":{"i":"EZRowynuVBviCH0ZfUx24mkMWn-jGRBm78p9'
                        b'0WN3sG3I","s":1,"d":"EKwtenOwTRhQCzIiBWTPWPCWB6PQ9sF0pnPrsCS_Yhu'
                        b'A"}}-eABEaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMtY0AAAAAAAAAAA'
                        b'AAAAAAAAAACwE71WIaYxok1t0xzC9OYyX1TYjsKG1o9LCnj_o_gsGH4M')

        assert kevt == (b'{"v":"KERI10JSON0000f9_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                        b'k5aMtSrMtY","s":"b","t":"ixn","p":"E58EtRRxJROE7qmMnHV6fnP8FeFTB'
                        b'kX8eMlZbMNDFY6w","a":["EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3ULvaU6Z-i'
                        b'0d8","1","E9lcc71zkJXoc5E7qcCKOjZrhsNqqenXhTJMShSVek04"]}-AABAAq'
                        b'1GKbPLjSoNJLTiAbSP6EM0j2d3IOzw9LTbGGrXw3GVT6P6P-S9y8kPdmIXszP5PB'
                        b'CDJehu8GsgvxLR2f_alCg')

        # ensure the ra seal digest matches the vrt event digest
        assert vrtser.diger.qb64 == 'EKwtenOwTRhQCzIiBWTPWPCWB6PQ9sF0pnPrsCS_YhuA'

        # issuer, no backers allowed, establishment events only
        issuer = Issuer(hab=hab, name="test", allowBackers=False, estOnly=True)
        assert issuer.incept == (b'{"v":"KERI10JSON0000ad_","i":"Ezm53Qww2LTJ1yksEL06Wtt-5D23QKdJEG'
                                b'I0egFyLehw","ii":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMtY",'
                                b'"s":"0","t":"vcp","c":["NB"],"bt":"0","b":[]}-eABEaKJ0FoLxO1TYmy'
                                b'uprguKO7kJ7Hbn0m0Wuk5aMtSrMtY0AAAAAAAAAAAAAAAAAAAAADAEE4ISn-pS8v'
                                b'oter-KsYyHlMb8pxiG_Uazvjw-cNRlm8s')

        assert issuer.ianchor == (b'{"v":"KERI10JSON000183_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                                b'k5aMtSrMtY","s":"c","t":"rot","p":"E71WIaYxok1t0xzC9OYyX1TYjsKG1'
                                b'o9LCnj_o_gsGH4M","kt":"1","k":["DKPE5eeJRzkRTMOoRGVd2m18o8fLqM2j'
                                b'9kaxLhV3x8AQ"],"n":"ELqHYQwWR0h2vP1_cxTsutU0wKJ_NrwBVKJCgPgWGgwc'
                                b'","bt":"0","br":[],"ba":[],"a":["Ezm53Qww2LTJ1yksEL06Wtt-5D23QKd'
                                b'JEGI0egFyLehw","0","ElYstqTocyQixLLz4zYCAs2unaFco_p6LqH0W01loIg4'
                                b'"]}-AABAATpTzNLJAV5CLD8znuTh2w73ZwqlsrOJIXa-XK2uY7QhnFHAD16yoDma'
                                b'BhdNFEKhFhqFLWnwUVe8myYkVnh8YCQ')

        tevt, kevt = issuer.issue(vcdig="EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3ULvaU6Z")
        assert tevt == (b'{"v":"KERI10JSON00008d_","i":"EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3UL'
                        b'vaU6Z","s":"0","t":"iss","ri":"Ezm53Qww2LTJ1yksEL06Wtt-5D23QKdJE'
                        b'GI0egFyLehw"}-eABEaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMtY0AA'
                        b'AAAAAAAAAAAAAAAAAAADQEDrLbf5h3GE06g3v-Ox2fFoolQyrvKW_sTrIxtQxuZAU')
        assert kevt == (b'{"v":"KERI10JSON00017e_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                        b'k5aMtSrMtY","s":"d","t":"rot","p":"EE4ISn-pS8voter-KsYyHlMb8pxiG'
                        b'_Uazvjw-cNRlm8s","kt":"1","k":["DSuhyBcPZEZLK-fcw5tzHn2N46wRCG_Z'
                        b'OoeKtWTOunRA"],"n":"EPYuj8mq_PYYsoBKkzX1kxSPGYBWaIya3slgCOyOtlqU'
                        b'","bt":"0","br":[],"ba":[],"a":["EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH'
                        b'3ULvaU6Z","0","EnZpkCQXGps7J8hO5BbFrVG7KSaEd1J3u-mAL8-E-JoY"]}-A'
                        b'ABAANcQvSou7f1vUanuNPB0QWSsv0_NUupscqNl4sY7HijmH0eUDxiz9ryWa-UdQ'
                        b'nzHLI-gY7ITVB5JgXJMtxKkxBw')

        ser = Serder(raw=tevt)
        assert ser.diger.qb64 == 'EnZpkCQXGps7J8hO5BbFrVG7KSaEd1J3u-mAL8-E-JoY'

        tevt, kevt = issuer.revoke(vcdig="EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3ULvaU6Z")
        assert tevt == (b'{"v":"KERI10JSON00008c_","i":"EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3UL'
                        b'vaU6Z","s":"1","t":"rev","p":"EnZpkCQXGps7J8hO5BbFrVG7KSaEd1J3u-'
                        b'mAL8-E-JoY"}-eABEaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMtY0AAA'
                        b'AAAAAAAAAAAAAAAAAADgE9-23oNfUrdBvXi-x89tgF8cO6mLCW5rGdQZ-C6agszE')

        assert kevt == (b'{"v":"KERI10JSON00017e_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                        b'k5aMtSrMtY","s":"e","t":"rot","p":"EDrLbf5h3GE06g3v-Ox2fFoolQyrv'
                        b'KW_sTrIxtQxuZAU","kt":"1","k":["DVcuJOOJF1IE8svqEtrSuyQjGTd2HhfA'
                        b'kt9y2QkUtFJI"],"n":"E-dapdcC6XR1KWmWDsNl4J_OxcGxNZw1Xd95JH5a34fI'
                        b'","bt":"0","br":[],"ba":[],"a":["EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH'
                        b'3ULvaU6Z","1","EVFiCQMPCoXtMpK-yoLWIVfwifQkLSH1Dj4RtzyOCVuo"]}-A'
                        b'ABAArUM8moanrzuFmxW48V4XE06zRkvnRHmtQtxt-q8ZqDoZeU0fTvJu_qQC0Qrb'
                        b'KVfVBNQ8ajphcJDdRP82d5aWAQ')

        with pytest.raises(ValueError):
            issuer.rotate(adds=["EqoNZAX5Lu8RuHzwwyn5tCZTe-mDBq5zusCrRo5TDugs"])

        # issuer, backers allowed, initial backer, establishment events only
        issuer = Issuer(hab=hab, name="test", baks=["EqoNZAX5Lu8RuHzwwyn5tCZTe-mDBq5zusCrRo5TDugs"], estOnly=True)
        assert issuer.incept == (b'{"v":"KERI10JSON0000d7_","i":"EZRowynuVBviCH0ZfUx24mkMWn-jGRBm78'
                                b'p90WN3sG3I","ii":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMtY",'
                                b'"s":"0","t":"vcp","c":[],"bt":"1","b":["EqoNZAX5Lu8RuHzwwyn5tCZT'
                                b'e-mDBq5zusCrRo5TDugs"]}-eABEaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5a'
                                b'MtSrMtY0AAAAAAAAAAAAAAAAAAAAADwEvDmjSZQmSLqNzTJDq9rdDd7X-ffGPt6z'
                                b'uD2n51EFRLw')

        assert issuer.ianchor == (b'{"v":"KERI10JSON000183_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                                b'k5aMtSrMtY","s":"f","t":"rot","p":"E9-23oNfUrdBvXi-x89tgF8cO6mLC'
                                b'W5rGdQZ-C6agszE","kt":"1","k":["DT1iAhBWCkvChxNWsby2J0pJyxBIxbAt'
                                b'bLA0Ljx-Grh8"],"n":"EDs-qIrh79lTtoIz4K9q_vu7-avDc79YkNCfK49HpwQg'
                                b'","bt":"0","br":[],"ba":[],"a":["EZRowynuVBviCH0ZfUx24mkMWn-jGRB'
                                b'm78p90WN3sG3I","0","EMMt2bfrg5ACOrCLQRuU21qWMBxDPwzIhOANvHKAGJWc'
                                b'"]}-AABAAmTxyOx_38hK74779sN9vPXxcRHV49li9vt0RvAKlfuCBKG2hwWyy0P-'
                                b'9tFF_2VMvAfrWChEsjWPm9lsPeWIwBw')
        ser = Serder(raw=issuer.incept)
        assert ser.diger.qb64 == 'EMMt2bfrg5ACOrCLQRuU21qWMBxDPwzIhOANvHKAGJWc'

        tevt, kevt = issuer.rotate(adds=["EtEBUSHpJDMfzHdDt3QCtrA-iVlP-0DT03AdqeeDa7vs",
                                         "ERVZTggTUOPmLcWBESrxcI-VsB48FerF6sz2boziikcY"])
        vrtser = Serder(raw=tevt)
        assert tevt == (b'{"v":"KERI10JSON000107_","i":"EZRowynuVBviCH0ZfUx24mkMWn-jGRBm78'
                        b'p90WN3sG3I","p":"EMMt2bfrg5ACOrCLQRuU21qWMBxDPwzIhOANvHKAGJWc","'
                        b's":"1","t":"vrt","bt":"3","br":[],"ba":["EtEBUSHpJDMfzHdDt3QCtrA'
                        b'-iVlP-0DT03AdqeeDa7vs","ERVZTggTUOPmLcWBESrxcI-VsB48FerF6sz2bozi'
                        b'ikcY"]}-eABEaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMtY0AAAAAAAA'
                        b'AAAAAAAAAAAAAEAEKKopp_VUWhCpagBvKuWMfuSwRe5gcmh4LO4kJB1rItE')
        assert kevt == (b'{"v":"KERI10JSON000184_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                        b'k5aMtSrMtY","s":"10","t":"rot","p":"EvDmjSZQmSLqNzTJDq9rdDd7X-ff'
                        b'GPt6zuD2n51EFRLw","kt":"1","k":["D4JDgo3WNSUpt-NG14Ni31_GCmrU0r3'
                        b'8yo7kgDuyGkQM"],"n":"EvbWtNrsw7dfaWRiDMXcF6P90KM1gdfPhg7FWTIwD39'
                        b'c","bt":"0","br":[],"ba":[],"a":["EZRowynuVBviCH0ZfUx24mkMWn-jGR'
                        b'Bm78p90WN3sG3I","1","EKwtenOwTRhQCzIiBWTPWPCWB6PQ9sF0pnPrsCS_Yhu'
                        b'A"]}-AABAAonXgmX0PD7e94oqW9yhkm9ydZjwivpNWEPPLIQkOzzvfqGlI79io4x'
                        b'FF8-8K8UWok5dfb9j9fhrqR-e9p23bBw')

        tevt, kevt = issuer.issue(vcdig="EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3ULvaU6Z")
        assert tevt == (b'{"v":"KERI10JSON000100_","i":"EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3UL'
                        b'vaU6Z","ii":"EZRowynuVBviCH0ZfUx24mkMWn-jGRBm78p90WN3sG3I","s":"'
                        b'0","t":"bis","ra":{"i":"EZRowynuVBviCH0ZfUx24mkMWn-jGRBm78p90WN3'
                        b'sG3I","s":1,"d":"EKwtenOwTRhQCzIiBWTPWPCWB6PQ9sF0pnPrsCS_YhuA"}}'
                        b'-eABEaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMtY0AAAAAAAAAAAAAAA'
                        b'AAAAAAEQEoRSZSkIHCJjvW9KDO26tFW4VQkhZXVXuYm8OrfxUfh8')
        assert kevt == (b'{"v":"KERI10JSON00017f_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                        b'k5aMtSrMtY","s":"11","t":"rot","p":"EKKopp_VUWhCpagBvKuWMfuSwRe5'
                        b'gcmh4LO4kJB1rItE","kt":"1","k":["DVjWcaNX2gCkHOjk6rkmqPBCxkRCqwI'
                        b'J-3OjdYmMwxf4"],"n":"EpusdZwamtwTwqtwOenXWKQ0FpX9yWnq0XHlOEgQmss'
                        b'0","bt":"0","br":[],"ba":[],"a":["EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZ'
                        b'H3ULvaU6Z","0","EXklP9Aj6ZXeC4Ox-TFExo_pk5u-ocMacfq82evq0rVo"]}-'
                        b'AABAAIcH6E9px8Tcz2kbJd8vmOvcvnb4Pe2QYL5Y6hkbIPsymR7awzvThHx8qkXB'
                        b'G51sJIgUExNoyaAOnkp20psoeAQ')
        assert vrtser.diger.qb64 == 'EKwtenOwTRhQCzIiBWTPWPCWB6PQ9sF0pnPrsCS_YhuA'

        # rotate to no backers
        tevt, kevt = issuer.rotate(cuts=["EqoNZAX5Lu8RuHzwwyn5tCZTe-mDBq5zusCrRo5TDugs"])
        assert tevt == (b'{"v":"KERI10JSON0000d8_","i":"EZRowynuVBviCH0ZfUx24mkMWn-jGRBm78'
                        b'p90WN3sG3I","p":"EKwtenOwTRhQCzIiBWTPWPCWB6PQ9sF0pnPrsCS_YhuA","'
                        b's":"2","t":"vrt","bt":"0","br":["EqoNZAX5Lu8RuHzwwyn5tCZTe-mDBq5'
                        b'zusCrRo5TDugs"],"ba":[]}-eABEaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5'
                        b'aMtSrMtY0AAAAAAAAAAAAAAAAAAAAAEgEX0HvF8uLvwvQcbnMq1JaMqoPSiJ0RqZ'
                        b'dhyM7gWfYS4g')
        assert kevt == (b'{"v":"KERI10JSON000184_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                        b'k5aMtSrMtY","s":"12","t":"rot","p":"EoRSZSkIHCJjvW9KDO26tFW4VQkh'
                        b'ZXVXuYm8OrfxUfh8","kt":"1","k":["DT1nEDepd6CSAMCE7NY_jlLdG6_mKUl'
                        b'KS_mW-2HJY1hg"],"n":"ER0SqaQnpyIxxtL_UFvE8wpooAjKNiq36zhpwwbfuZo'
                        b'w","bt":"0","br":[],"ba":[],"a":["EZRowynuVBviCH0ZfUx24mkMWn-jGR'
                        b'Bm78p90WN3sG3I","2","ETtfhi2rdeM4yqMuBb1fLXMjZlG_n_I3N00JMfaIBUn'
                        b's"]}-AABAARKOiQnD9BSRUqFg63Q3lUjyMAJ-cZiVVCHO4POe0iEAXdIRp4Ylzdt'
                        b'PJzVTRpuJC2YecICPXkEehBbnQhXwHBg')
        vrtser = Serder(raw=tevt)

        tevt, kevt = issuer.revoke(vcdig="EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3ULvaU6Z")
        assert tevt == (b'{"v":"KERI10JSON0000ff_","i":"EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZH3UL'
                        b'vaU6Z","s":"1","t":"brv","p":"EXklP9Aj6ZXeC4Ox-TFExo_pk5u-ocMacf'
                        b'q82evq0rVo","ra":{"i":"EZRowynuVBviCH0ZfUx24mkMWn-jGRBm78p90WN3s'
                        b'G3I","s":2,"d":"ETtfhi2rdeM4yqMuBb1fLXMjZlG_n_I3N00JMfaIBUns"}}-'
                        b'eABEaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMtY0AAAAAAAAAAAAAAAA'
                        b'AAAAAEwE97hmLY8BYtFhPxzmN0ZweLfeU_hU7RVgD8e6BvZA92U')
        assert kevt == (b'{"v":"KERI10JSON00017f_","i":"EaKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wu'
                        b'k5aMtSrMtY","s":"13","t":"rot","p":"EX0HvF8uLvwvQcbnMq1JaMqoPSiJ'
                        b'0RqZdhyM7gWfYS4g","kt":"1","k":["DiDeeYNZLsQncGJZ6DR54gAy-HySmzz'
                        b'gl61KFMZ4iR0U"],"n":"E9IUWbvzBjn0ubo_lpKsjCb6ajDS1V23iLHrJFHZ2rV'
                        b'k","bt":"0","br":[],"ba":[],"a":["EJJR2nmwyYAfSVPzhzS6b5CMZAoTNZ'
                        b'H3ULvaU6Z","1","EI_uyS9EE7t3s_TD5PpqqpLXb3PfPt8K0J7VnNLF50-o"]}-'
                        b'AABAAdKHkxbgf1PgVw8dfg4taD8igLLzGlZkifbMcVL3cLOciDn6Ovi39Xsk36Y8'
                        b'a3xHh8WJkIfOaONYscc_bz-jJBw')
        assert vrtser.diger.qb64 == 'ETtfhi2rdeM4yqMuBb1fLXMjZlG_n_I3N00JMfaIBUns'

    """ End Test """
Exemple #13
0
def test_replay():
    """
    Test disjoint and conjoint replay

    Deb creates series of events.
    Deb replays Deb's events to Cam and collects Cam's receipts
    Deb replays Deb's events with Cam's recepts to Bev and collects Bev's receipts
    Deb replays Deb's events with both Cam's and  Bev's receipts to Cam
    Compare replay of Deb's events with receipts by both Deb and Cam to confirm identical
    """

    with dbing.openDB(name="deb") as debDB, keeping.openKS(name="deb") as debKS, \
         dbing.openDB(name="cam") as camDB, keeping.openKS(name="cam") as camKS, \
         dbing.openDB(name="bev") as bevDB, keeping.openKS(name="bev") as bevKS, \
         dbing.openDB(name="art") as artDB, keeping.openKS(name="art") as artKS:

        # setup Deb's habitat using default salt multisig already incepts
        sith = ["1/2", "1/2", "1/2"]  # weighted signing threshold
        debHab = directing.Habitat(ks=debKS,
                                   db=debDB,
                                   isith=sith,
                                   icount=3,
                                   temp=True)
        assert debHab.ks == debKS
        assert debHab.db == debDB
        assert debHab.kever.prefixer.transferable

        # setup Cam's habitat using default salt multisig already incepts
        # Cam's receipts will be vrcs with 3 indexed sigantures attached
        sith = '2'  # hex str of threshold int
        camHab = directing.Habitat(ks=camKS,
                                   db=camDB,
                                   isith=sith,
                                   icount=3,
                                   temp=True)
        assert camHab.ks == camKS
        assert camHab.db == camDB
        assert camHab.kever.prefixer.transferable

        # setup Bev's habitat using default salt nonstransferable already incepts
        # Bev's receipts will be rcts with a receipt couple attached
        sith = '1'  # hex str of threshold int
        bevHab = directing.Habitat(ks=bevKS,
                                   db=bevDB,
                                   isith=sith,
                                   icount=1,
                                   transferable=False,
                                   temp=True)
        assert bevHab.ks == bevKS
        assert bevHab.db == bevDB
        assert not bevHab.kever.prefixer.transferable

        # setup Art's habitat using custom salt nonstransferable so not match Bev
        # already incepts
        # Art's receipts will be rcts with a receipt couple attached
        salt = coring.Salter(raw=b'abcdef0123456789').qb64
        sith = '1'  # hex str of threshold int
        artHab = directing.Habitat(ks=artKS,
                                   db=artDB,
                                   isith=sith,
                                   icount=1,
                                   salt=salt,
                                   transferable=False,
                                   temp=True)
        assert artHab.ks == artKS
        assert artHab.db == artDB
        assert not artHab.kever.prefixer.transferable

        # first setup disjoint replay then conjoint replay
        # Create series of event for Deb
        debMsgs = bytearray()
        debMsgs.extend(debHab.makeOwnInception())
        debMsgs.extend(debHab.interact())
        debMsgs.extend(debHab.rotate())
        debMsgs.extend(debHab.interact())
        debMsgs.extend(debHab.interact())
        debMsgs.extend(debHab.interact())
        debMsgs.extend(debHab.interact())

        assert debMsgs == (
            b'{"v":"KERI10JSON00015b_","i":"EBfdpo5wnI3XTcdUIgJRf1-xLhy8Ud8lry'
            b'kGGHz2vlMw","s":"0","t":"icp","kt":["1/2","1/2","1/2"],"k":["DaY'
            b'h8uaASuDjMUd8_BoNyQs3GwupzmJL8_RBsuNtZHQg","Duzj-Z2lR2DqB0cI0421'
            b'oSMUVWOrN5axojx8g9fSx3PM","DRXPAmNVVqafWvQiN5qQmWUDvVupF2w8xFNGg'
            b'1Gays9Y"],"n":"EO5f_IQjtBoeN_-OyzfVJx1_WqBFUL-Ely4x-xmUtOW8","bt'
            b'":"0","b":[],"c":[],"a":[]}-AADAA1G77zOmX-GYRN5yk5X704dneyog8BHJ'
            b'ItCZdLmXl4Tlfd-bE3K8WpbApL_-n1o18Ato90tRhAIZjuBIlxF9vAgAByElIwoU'
            b'aqbuJzHevggmdBySCIropnrylNFmSETWjOwLT2ifZgCJ1lm27IbknR_33LPPIyN3'
            b'U6dbIAG3kko7IDgACdOTaaqRtwquJiBZJfWYKtH48gZTezMLzXviMUeo2Z1cJ-_M'
            b'xQvDNh85FjXAOEQ-3hPEiqmY1SpjElZIXGs13DA{"v":"KERI10JSON000098_",'
            b'"i":"EBfdpo5wnI3XTcdUIgJRf1-xLhy8Ud8lrykGGHz2vlMw","s":"1","t":"'
            b'ixn","p":"E5OQH-DOSjcX8JlBtznPaaawhP0iuZhjf9cxWVAXNTX0","a":[]}-'
            b'AADAAO7JjY0oHH5z68S4ZlYUAOAFnMfRu6OZB9hMGgu6teSzvL_3kzAiiPig6vch'
            b'lnXDxmKFWMDLXAZsCBN3T0chVCwAB_I3BVOYI2K_VSeLDcq32czYe-kTyPZ1E0wd'
            b'-F78Ixsz99mQwwylJsbRBb2l1Q2-1UnbQ4NZzj0w2xo5fEBv4BAACHO5PyuMrekU'
            b'FWbirPNt7etpA3cUVAR94XFlJDUYYSE4tq1gD6Pab-L2PP3ifFlluO-aoVpf3G8h'
            b'Sl75t2k7rCg{"v":"KERI10JSON000190_","i":"EBfdpo5wnI3XTcdUIgJRf1-'
            b'xLhy8Ud8lrykGGHz2vlMw","s":"2","t":"rot","p":"EjevD0KmiBZQHqVNND'
            b'mpTfrp0lqZI5eicRRNf3OqLW9o","kt":["1/2","1/2","1/2"],"k":["DIsi8'
            b'qYso1KMmpLOGYty3NC2BAojZmUCfzR5_5oQRiso","DkdClpaWCAoCPBYgUmqP9g'
            b'wAtsGq81yyPhGQKQ6-W_F0","DKDyq4QQYKnx9ircxeCvEcraI4HUSr_ytWPelDH'
            b'AM98w"],"n":"E1oOvJmwenmC4uHjX7qB40LGVbeZY5rYQeZ6IK5zmdmM","bt":'
            b'"0","br":[],"ba":[],"a":[]}-AADAAfELYptGBeOzZ1ex7MIxYAUN_f4mr0gZ'
            b'gUZAQTZQbZKsTykDGqTcsbuLurhFviHttWylHBBjDwfCRF8eFCpLkDgABRLbYyJQ'
            b'W8plPZ3PcdBLHgl4NWnB5NeTOI9tjW53DL4le2N-nVPVXr_fAvWcksevbGNRZxCU'
            b'ePoDlThcBShDdBwACSPQd27SozRqfeW7YWWQS87JXdgy-ZGTrhrT1bUTTQKAngwE'
            b'1hwWgIYw8LUgz3YH6SZC5zAWUN_Fv3OzSb_BXBg{"v":"KERI10JSON000098_",'
            b'"i":"EBfdpo5wnI3XTcdUIgJRf1-xLhy8Ud8lrykGGHz2vlMw","s":"3","t":"'
            b'ixn","p":"Ew3t8tlmqfRSwyyRF1nsKLjNOySvj-KTd-SmDu_AjzuA","a":[]}-'
            b'AADAAJ4MM4lGyFUsszt7fXksb13wqyiBTd3AirhQaTO3udtTilMfviCutx-ipkgT'
            b'u56huDbWLiA47LqUzqP63rKv3DQAB9hmDtEawFFGHMeS92RBuuMMQroBM5fodzeo'
            b'leSrV0IyETDSpjaRhcsDf25EqNTJUcnv-_jSzRPEtM8GEv3AJCgACxWtyOC4ks1F'
            b'8-YdHSM32VLysW0ypRBpfYDOHyfmtktb1XQjdAAJpkSDe9wvrttvE2xJ5GzyfpVv'
            b'Ps4zK54pCDA{"v":"KERI10JSON000098_","i":"EBfdpo5wnI3XTcdUIgJRf1-'
            b'xLhy8Ud8lrykGGHz2vlMw","s":"4","t":"ixn","p":"EY_w2vUVqsE6jdgdxJ'
            b'VvMW3434NG1w_asCW7ohG1nmMY","a":[]}-AADAANw16XHQyB4Edm0MF4b0m8Ez'
            b'8jOZSYr_bYn7ilsFTNBypC_tSIcLnOUarG1xuhFU21WjXiSHWt2t2BSIHulgtDgA'
            b'Bm1DN8JigUofEC8mXb7YgklycIqDt7F7p8s6x8VHlAqLsCiMsXGQlRCwUwF7DFeu'
            b'6Fw_43Io6evqKpzaTR31SCwACJE0jOjykDr4SU59Mpd-EBTwKc8hUUWeIQTF3qU4'
            b'H56jqKozmgsyzzViob_DZ828OGBLRG_WoIQxTvstXql3QDw{"v":"KERI10JSON0'
            b'00098_","i":"EBfdpo5wnI3XTcdUIgJRf1-xLhy8Ud8lrykGGHz2vlMw","s":"'
            b'5","t":"ixn","p":"EwJ79SUIE69dA0my9ai9hK3yH8cqqyD9CS62lyRTDn-o",'
            b'"a":[]}-AADAAhAypLrhzTbvSPdErva4IzRRSq6EZCC_dCe3pkLGpPcVHdi3Mu2B'
            b'-c0oW1My7HFFa1-JNTbjnNtgK-Or297PmAgABM1DYwa0Khbr79SbRaC6l8rAwsxs'
            b'Vopeid8KfS-7pt60y9drfLpXIUFzt5rk24KUuZROO33KiHmfKNbviW6GVCgACQRj'
            b'qwHlELgvpFJwQx-6yBVuAgbsT7AK1mbxfsUo2XfzkAUTbn9H1vxOQX1Rg_3cLYZv'
            b'ryKcP4MdjZFfFYaNmBQ{"v":"KERI10JSON000098_","i":"EBfdpo5wnI3XTcd'
            b'UIgJRf1-xLhy8Ud8lrykGGHz2vlMw","s":"6","t":"ixn","p":"EBjW8_7rqn'
            b'AXV0Il5BJ4XWZcIb355Ltj-9F9JRZLn75c","a":[]}-AADAAbbH94e474Pflg_Y'
            b'dlivHMQQL_7rUlr1DEut8SSbEs6cmUixWHW8SuZG2UlpKoqsAL-STNALsRCmDw_2'
            b'wWsmWAAABnedMdYxUbNgwJpG5AcNsxMIZCjuu486-wuiUm3BO_1h40_qvoMicneV'
            b'edtBOLxD5zKtdZhBHZqtd3-qQDmIVDgACqms_mYs0LAwAi2zGN6lpKmdqs2twyJz'
            b'9xiyPeERHG7D2FiTZqow19UieVYobmhGeHuoS5WxNPgcponbhHeFnDA')

        # Play debMsgs to Cam
        # create non-local kevery for Cam to process msgs from Deb
        camKevery = eventing.Kevery(kevers=camHab.kevers,
                                    db=camHab.db,
                                    framed=True,
                                    opre=camHab.pre,
                                    local=False)
        camKevery.process(ims=bytearray(debMsgs))  # give copy to process
        assert debHab.pre in camKevery.kevers
        assert camKevery.kevers[debHab.pre].sn == debHab.kever.sn == 6
        assert len(camKevery.cues) == 7

        # get disjoints receipts (vrcs) from Cam of Deb's events by processing Cam's cues
        camMsgs = camHab.processCues(camKevery.cues)
        assert camMsgs == (
            b'{"v":"KERI10JSON00014b_","i":"EiRjCnZfca8gUZqecerjGpjkiY8dIkGudP'
            b'6GfapWi5MU","s":"0","t":"icp","kt":"2","k":["DaYh8uaASuDjMUd8_Bo'
            b'NyQs3GwupzmJL8_RBsuNtZHQg","Duzj-Z2lR2DqB0cI0421oSMUVWOrN5axojx8'
            b'g9fSx3PM","DRXPAmNVVqafWvQiN5qQmWUDvVupF2w8xFNGg1Gays9Y"],"n":"E'
            b'OySO3Oa400n3Ss9JftGYmgS5M4jgPInNnMntC_l-PEQ","bt":"0","b":[],"c"'
            b':[],"a":[]}-AADAATacW---OhatYudCOUeNdVpYq8Vk_LIKMQML86xz4b1ZQG9r'
            b'ahEGEHMtDacANGyKFSkJBq4F3x8h30lWfrth2BQABnyZMjYDQs2IgFuVcRKCLi9F'
            b'DFOw7uPqIvwossbC4H2Eu4_cIntaKeEmH7LBEzDbfQaQxWdgZ2YTnfFkoznL3AgA'
            b'Ckf4d23ErgdwPZWJf_0jVtzVwoKsh_6W0V6BclmrbnL1NWM8ox2m3ff7LzZeSjF5'
            b'9AvO-QmqCD325H3igOF0HCg{"v":"KERI10JSON000105_","i":"EBfdpo5wnI3'
            b'XTcdUIgJRf1-xLhy8Ud8lrykGGHz2vlMw","s":"0","t":"vrc","d":"E5OQH-'
            b'DOSjcX8JlBtznPaaawhP0iuZhjf9cxWVAXNTX0","a":{"i":"EiRjCnZfca8gUZ'
            b'qecerjGpjkiY8dIkGudP6GfapWi5MU","s":"0","d":"E1tSV5RBIG7dGPN2Oof'
            b'5DmZCqgGgpF7P9BbfOTnOEEpM"}}-AADAA1G77zOmX-GYRN5yk5X704dneyog8BH'
            b'JItCZdLmXl4Tlfd-bE3K8WpbApL_-n1o18Ato90tRhAIZjuBIlxF9vAgAByElIwo'
            b'UaqbuJzHevggmdBySCIropnrylNFmSETWjOwLT2ifZgCJ1lm27IbknR_33LPPIyN'
            b'3U6dbIAG3kko7IDgACdOTaaqRtwquJiBZJfWYKtH48gZTezMLzXviMUeo2Z1cJ-_'
            b'MxQvDNh85FjXAOEQ-3hPEiqmY1SpjElZIXGs13DA{"v":"KERI10JSON000105_"'
            b',"i":"EBfdpo5wnI3XTcdUIgJRf1-xLhy8Ud8lrykGGHz2vlMw","s":"1","t":'
            b'"vrc","d":"EjevD0KmiBZQHqVNNDmpTfrp0lqZI5eicRRNf3OqLW9o","a":{"i'
            b'":"EiRjCnZfca8gUZqecerjGpjkiY8dIkGudP6GfapWi5MU","s":"0","d":"E1'
            b'tSV5RBIG7dGPN2Oof5DmZCqgGgpF7P9BbfOTnOEEpM"}}-AADAAO7JjY0oHH5z68'
            b'S4ZlYUAOAFnMfRu6OZB9hMGgu6teSzvL_3kzAiiPig6vchlnXDxmKFWMDLXAZsCB'
            b'N3T0chVCwAB_I3BVOYI2K_VSeLDcq32czYe-kTyPZ1E0wd-F78Ixsz99mQwwylJs'
            b'bRBb2l1Q2-1UnbQ4NZzj0w2xo5fEBv4BAACHO5PyuMrekUFWbirPNt7etpA3cUVA'
            b'R94XFlJDUYYSE4tq1gD6Pab-L2PP3ifFlluO-aoVpf3G8hSl75t2k7rCg{"v":"K'
            b'ERI10JSON000105_","i":"EBfdpo5wnI3XTcdUIgJRf1-xLhy8Ud8lrykGGHz2v'
            b'lMw","s":"2","t":"vrc","d":"Ew3t8tlmqfRSwyyRF1nsKLjNOySvj-KTd-Sm'
            b'Du_AjzuA","a":{"i":"EiRjCnZfca8gUZqecerjGpjkiY8dIkGudP6GfapWi5MU'
            b'","s":"0","d":"E1tSV5RBIG7dGPN2Oof5DmZCqgGgpF7P9BbfOTnOEEpM"}}-A'
            b'ADAABkB5LzkcturaQSzTGH_KrWsEJR-x_CH8UPl9FQ1Dc461z5-Fdn3TLJ7DpUw-'
            b'6VrbKGGjuDy2Nkg0xJdzh4F8CQABPgHmWCG4uUicqcBiHOJcygFsSqFMU2jkOgU7'
            b'3eG-Jony_ZwctQl_1BCQ8eVTli44Uou4YMdgvRMfmiRGTuxeAwAC386oYzhQFZCk'
            b'S6TM9vIFahT8vf0cQ7t2v5MqKhyJxBgA6CHJeQ8mxS8P7trjcEOGl79jwb6L-jyt'
            b'qAnNPDJFCA{"v":"KERI10JSON000105_","i":"EBfdpo5wnI3XTcdUIgJRf1-x'
            b'Lhy8Ud8lrykGGHz2vlMw","s":"3","t":"vrc","d":"EY_w2vUVqsE6jdgdxJV'
            b'vMW3434NG1w_asCW7ohG1nmMY","a":{"i":"EiRjCnZfca8gUZqecerjGpjkiY8'
            b'dIkGudP6GfapWi5MU","s":"0","d":"E1tSV5RBIG7dGPN2Oof5DmZCqgGgpF7P'
            b'9BbfOTnOEEpM"}}-AADAAraP5JCHU-ZQwsDAWuLu_fvvYmkpVEu071l5P7fwHzqL'
            b'bJ7kkvpSsXcGs2HpW_Bw_fjp07LfnN4de5zn7-owxAgABQUHJIy3inow-7ctn-jO'
            b'F6r2IvOsC-Pl2jAueDZfH9p2pS_L9OhgHBr9ToilY4H_1bbIZK2kERtt47Qd0VVq'
            b'qDAAC_0A73HjuuB42XhAqgPMWt1Fm-FwO55oT0z7TJR9PQ4ppaEuip5FUp-miRS9'
            b'Rnoq0ZYPWskncUmLgcqxsOksvBw{"v":"KERI10JSON000105_","i":"EBfdpo5'
            b'wnI3XTcdUIgJRf1-xLhy8Ud8lrykGGHz2vlMw","s":"4","t":"vrc","d":"Ew'
            b'J79SUIE69dA0my9ai9hK3yH8cqqyD9CS62lyRTDn-o","a":{"i":"EiRjCnZfca'
            b'8gUZqecerjGpjkiY8dIkGudP6GfapWi5MU","s":"0","d":"E1tSV5RBIG7dGPN'
            b'2Oof5DmZCqgGgpF7P9BbfOTnOEEpM"}}-AADAApIX866iuD6j14MFQbVdiJHMeTM'
            b'Svd2EoibE7PPfwU7f6HcDCwmLmMCNpRVwM-Kf1kKIor7TETSX80jrliA_XBgAB1h'
            b'phj5XH3E0oTANv6GVwJ5s0ZnLIPSYoBuvXaPOzWgW3nynVPwWnqCNuP7rdh-1NVB'
            b'QUc9QHqrDWVnJaoVo5CQAC9PBjGWWN9J6jQXcLmQOfQxrWL3NFm93r7-nDiSbG-T'
            b'KDvbcXcnoLfCitTt_B96JlvIpe6cI8DJZw3_SERLsaCg{"v":"KERI10JSON0001'
            b'05_","i":"EBfdpo5wnI3XTcdUIgJRf1-xLhy8Ud8lrykGGHz2vlMw","s":"5",'
            b'"t":"vrc","d":"EBjW8_7rqnAXV0Il5BJ4XWZcIb355Ltj-9F9JRZLn75c","a"'
            b':{"i":"EiRjCnZfca8gUZqecerjGpjkiY8dIkGudP6GfapWi5MU","s":"0","d"'
            b':"E1tSV5RBIG7dGPN2Oof5DmZCqgGgpF7P9BbfOTnOEEpM"}}-AADAApBHqjI7V9'
            b'yrCqUP1ZsnSHov3nNF90QNZEwPGZToAf6l3KeXPh4UQMZU70-5Cbbs2mswX8_Tg4'
            b'5orHQz_mQkMCgABF3FoOib-wh0KQ26kdzfEBtnenPVN12GiP7NpIy2j3wW-enfJc'
            b'gRTEE3XWVekl3IkU3o70Cnk4K1PONYCrO6hAwACWMhg7tNGae9I4mLtv5rVpb9Rr'
            b'G70zGIwBDxN4QahABHlAvRdDpaSE5BpJ7nlOkShOZIva-qdcWS5TiRX8I43DQ{"v'
            b'":"KERI10JSON000105_","i":"EBfdpo5wnI3XTcdUIgJRf1-xLhy8Ud8lrykGG'
            b'Hz2vlMw","s":"6","t":"vrc","d":"E8BEZ7sVSL-vamQnB8Oc72ov-gpiXJzL'
            b'GXeiAW9_Vht8","a":{"i":"EiRjCnZfca8gUZqecerjGpjkiY8dIkGudP6GfapW'
            b'i5MU","s":"0","d":"E1tSV5RBIG7dGPN2Oof5DmZCqgGgpF7P9BbfOTnOEEpM"'
            b'}}-AADAAlQ8kt9KwijVTzAS8-LUziqMPwvLDhoU9sVHN0a9wkICnezEmzrb4skeO'
            b'wdNVbpek3Wn6xcRxa5wCuF9ub3T-CAAByaYGW-0ZX6oDmjk70BOpkRl8JvgVCm9w'
            b'skxESXXFcMs_FWssXcUH1oDRzA2q7BMW80DpEtKtcY8phmbH8TTBBwACQd7bqYf-'
            b'hcHe2B_FESYMXH2SloJ1o7XOry4KyBxZ9oJwtoa0iR4JPScb4_ix1p8p9n3HGMXT'
            b'_Lou1q1l6AGAAQ')

        # Play camMsgs to Deb
        # create non-local kevery for Deb to process msgs from Cam
        debKevery = eventing.Kevery(kevers=debHab.kevers,
                                    db=debHab.db,
                                    framed=True,
                                    opre=debHab.pre,
                                    local=False)
        debKevery.process(ims=bytearray(camMsgs))  # give copy to process
        assert camHab.pre in debKevery.kevers
        assert debKevery.kevers[camHab.pre].sn == camHab.kever.sn == 0
        assert len(debKevery.cues) == 1

        # get disjoints receipts (vrcs) from Deb of Cam's events by processing Deb's cues
        debCamVrcs = debHab.processCues(debKevery.cues)
        assert debCamVrcs == (
            b'{"v":"KERI10JSON000105_","i":"EiRjCnZfca8gUZqecerjGpjkiY8dIkGudP'
            b'6GfapWi5MU","s":"0","t":"vrc","d":"E1tSV5RBIG7dGPN2Oof5DmZCqgGgp'
            b'F7P9BbfOTnOEEpM","a":{"i":"EBfdpo5wnI3XTcdUIgJRf1-xLhy8Ud8lrykGG'
            b'Hz2vlMw","s":"2","d":"Ew3t8tlmqfRSwyyRF1nsKLjNOySvj-KTd-SmDu_Ajz'
            b'uA"}}-AADAAII8AatcRUlekxpknQfnpZJ2KBrATxmFRLxb_zpdPOaG3pCQg6vqP0'
            b'G96WmJO0hFwaGL-xheGy-SvX_5Q8b0gDQABRgVbtBmb3lR7UjuBjHmny7QkJ6waR'
            b'MTwz2B_1ANJu9yDa5qsgJiMQ7aTc7lCpLJgZNyKUJaUmW8YJL6JrzteDwAC1zKj3'
            b'HCcHwhw7OtEVXrgIobJO27d6389xdPXpkdVENb6XbsQLDEPNtv3g2POvWx1vESlp'
            b'pIfOxaY8VATudBBBg')

        # Play disjoints debCamVrcs to Cam
        camKevery.processOne(ims=bytearray(debCamVrcs))  # give copy to process

        # Play debMsgs to Bev
        # create non-local kevery for Bev to process msgs from Deb
        bevKevery = eventing.Kevery(kevers=bevHab.kevers,
                                    db=bevHab.db,
                                    framed=True,
                                    opre=bevHab.pre,
                                    local=False)
        bevKevery.process(ims=bytearray(debMsgs))  # give copy to process
        assert debHab.pre in bevKevery.kevers
        assert bevKevery.kevers[debHab.pre].sn == debHab.kever.sn == 6
        assert len(bevKevery.cues) == 7

        # get disjoints receipts (rcts) from Bev of Deb's events by processing Bevs's cues
        bevMsgs = bevHab.processCues(bevKevery.cues)
        assert bevMsgs == (
            b'{"v":"KERI10JSON0000c1_","i":"BaYh8uaASuDjMUd8_BoNyQs3GwupzmJL8_'
            b'RBsuNtZHQg","s":"0","t":"icp","kt":"1","k":["BaYh8uaASuDjMUd8_Bo'
            b'NyQs3GwupzmJL8_RBsuNtZHQg"],"n":"","bt":"0","b":[],"c":[],"a":[]'
            b'}-AABAA8dCt6i3swKOHoV10pEEOT7LOHxDWCfPWJm0Qvf6CXNaxTEOthHVgLihIz'
            b'1ZwQYc_nvunt0Hkh5TnnG4OmnulCQ{"v":"KERI10JSON000091_","i":"EBfdp'
            b'o5wnI3XTcdUIgJRf1-xLhy8Ud8lrykGGHz2vlMw","s":"0","t":"rct","d":"'
            b'E5OQH-DOSjcX8JlBtznPaaawhP0iuZhjf9cxWVAXNTX0"}-CABBaYh8uaASuDjMU'
            b'd8_BoNyQs3GwupzmJL8_RBsuNtZHQg0B1G77zOmX-GYRN5yk5X704dneyog8BHJI'
            b'tCZdLmXl4Tlfd-bE3K8WpbApL_-n1o18Ato90tRhAIZjuBIlxF9vAg{"v":"KERI'
            b'10JSON000091_","i":"EBfdpo5wnI3XTcdUIgJRf1-xLhy8Ud8lrykGGHz2vlMw'
            b'","s":"1","t":"rct","d":"EjevD0KmiBZQHqVNNDmpTfrp0lqZI5eicRRNf3O'
            b'qLW9o"}-CABBaYh8uaASuDjMUd8_BoNyQs3GwupzmJL8_RBsuNtZHQg0BO7JjY0o'
            b'HH5z68S4ZlYUAOAFnMfRu6OZB9hMGgu6teSzvL_3kzAiiPig6vchlnXDxmKFWMDL'
            b'XAZsCBN3T0chVCw{"v":"KERI10JSON000091_","i":"EBfdpo5wnI3XTcdUIgJ'
            b'Rf1-xLhy8Ud8lrykGGHz2vlMw","s":"2","t":"rct","d":"Ew3t8tlmqfRSwy'
            b'yRF1nsKLjNOySvj-KTd-SmDu_AjzuA"}-CABBaYh8uaASuDjMUd8_BoNyQs3Gwup'
            b'zmJL8_RBsuNtZHQg0BBkB5LzkcturaQSzTGH_KrWsEJR-x_CH8UPl9FQ1Dc461z5'
            b'-Fdn3TLJ7DpUw-6VrbKGGjuDy2Nkg0xJdzh4F8CQ{"v":"KERI10JSON000091_"'
            b',"i":"EBfdpo5wnI3XTcdUIgJRf1-xLhy8Ud8lrykGGHz2vlMw","s":"3","t":'
            b'"rct","d":"EY_w2vUVqsE6jdgdxJVvMW3434NG1w_asCW7ohG1nmMY"}-CABBaY'
            b'h8uaASuDjMUd8_BoNyQs3GwupzmJL8_RBsuNtZHQg0BraP5JCHU-ZQwsDAWuLu_f'
            b'vvYmkpVEu071l5P7fwHzqLbJ7kkvpSsXcGs2HpW_Bw_fjp07LfnN4de5zn7-owxA'
            b'g{"v":"KERI10JSON000091_","i":"EBfdpo5wnI3XTcdUIgJRf1-xLhy8Ud8lr'
            b'ykGGHz2vlMw","s":"4","t":"rct","d":"EwJ79SUIE69dA0my9ai9hK3yH8cq'
            b'qyD9CS62lyRTDn-o"}-CABBaYh8uaASuDjMUd8_BoNyQs3GwupzmJL8_RBsuNtZH'
            b'Qg0BpIX866iuD6j14MFQbVdiJHMeTMSvd2EoibE7PPfwU7f6HcDCwmLmMCNpRVwM'
            b'-Kf1kKIor7TETSX80jrliA_XBg{"v":"KERI10JSON000091_","i":"EBfdpo5w'
            b'nI3XTcdUIgJRf1-xLhy8Ud8lrykGGHz2vlMw","s":"5","t":"rct","d":"EBj'
            b'W8_7rqnAXV0Il5BJ4XWZcIb355Ltj-9F9JRZLn75c"}-CABBaYh8uaASuDjMUd8_'
            b'BoNyQs3GwupzmJL8_RBsuNtZHQg0BpBHqjI7V9yrCqUP1ZsnSHov3nNF90QNZEwP'
            b'GZToAf6l3KeXPh4UQMZU70-5Cbbs2mswX8_Tg45orHQz_mQkMCg{"v":"KERI10J'
            b'SON000091_","i":"EBfdpo5wnI3XTcdUIgJRf1-xLhy8Ud8lrykGGHz2vlMw","'
            b's":"6","t":"rct","d":"E8BEZ7sVSL-vamQnB8Oc72ov-gpiXJzLGXeiAW9_Vh'
            b't8"}-CABBaYh8uaASuDjMUd8_BoNyQs3GwupzmJL8_RBsuNtZHQg0BlQ8kt9Kwij'
            b'VTzAS8-LUziqMPwvLDhoU9sVHN0a9wkICnezEmzrb4skeOwdNVbpek3Wn6xcRxa5'
            b'wCuF9ub3T-CA')

        # Play bevMsgs to Deb
        debKevery.process(ims=bytearray(bevMsgs))  # give copy to process
        assert bevHab.pre in debKevery.kevers
        assert debKevery.kevers[bevHab.pre].sn == bevHab.kever.sn == 0
        assert len(debKevery.cues) == 1

        # get disjoints receipts (vrcs) from Deb of Bev's events by processing Deb's cues
        debBevVrcs = debHab.processCues(debKevery.cues)
        assert debBevVrcs == (
            b'{"v":"KERI10JSON000105_","i":"BaYh8uaASuDjMUd8_BoNyQs3GwupzmJL8_'
            b'RBsuNtZHQg","s":"0","t":"vrc","d":"EW4yC5ZUXv8xhM3gXDvKwOCZkltCh'
            b'RZe-hTb2mi1Zf04","a":{"i":"EBfdpo5wnI3XTcdUIgJRf1-xLhy8Ud8lrykGG'
            b'Hz2vlMw","s":"2","d":"Ew3t8tlmqfRSwyyRF1nsKLjNOySvj-KTd-SmDu_Ajz'
            b'uA"}}-AADAAmQ-kOahYYNCaatYN5YHfuruD93tOhJNQCt7Wy6LUCCkITxSj7Ogux'
            b'aDrBo15FN7wk-BTgEV8ufOIsxhqVfmVBgAB5DhNTiOesOQxfxSn-0D7Ec9_S80xO'
            b'9ck6Q6FKROXz2Evd4_TwfzMbgJKjSPXqkA16zju5GN6aDWeGWCJOTceDwACrkW_1'
            b'_sKmtEWtlcON3IGzRygPc0tF-f5qTRJewOEIRIhCB81WnDi8PBa7F43YzSoJiSGV'
            b'_PgAcg6zh6q8wxVDQ')

        # Play disjoints debBevVrcs to Bev
        bevKevery.processOne(ims=bytearray(debBevVrcs))  # give copy to process

        # now setup conjoint replay

        # Replay Deb's First Seen Events with receipts (vrcs and rcts) from both Cam and Bev
        # datetime is different in each run in the fse attachment in clone replay
        # so we either have to force dts in db or we parse in pieces
        debFelMsgs = bytearray()
        fn = 0
        cloner = debHab.db.cloneIter(pre=debHab.pre, fn=fn)  # create iterator
        msg = next(cloner)  # get zeroth event with attachments
        assert len(msg) == 1423
        debFelMsgs.extend(msg)

        # parse msg
        serder = coring.Serder(raw=msg)
        assert serder.raw == debHab.iserder.raw
        assert serder.sn == fn  # no recovery forks so sn == fn
        assert serder.ked["t"] == coring.Ilks.icp
        del msg[:len(serder.raw)]
        assert len(msg) == 1076

        counter = coring.Counter(
            qb64b=msg)  # attachment length quadlets counter
        assert counter.code == coring.CtrDex.AttachedMaterialQuadlets
        assert counter.count == (len(msg) - len(counter.qb64b)) // 4 == 268
        del msg[:len(counter.qb64b)]
        assert len(msg) == 1072 == 268 * 4

        counter = coring.Counter(qb64b=msg)  # indexed signatures counter
        assert counter.code == coring.CtrDex.ControllerIdxSigs
        assert counter.count == 3  #  multisig deb
        del msg[:len(counter.qb64b)]
        assert len(msg) == 1068

        for i in range(counter.count):  # parse signatures
            siger = coring.Siger(qb64b=msg)
            del msg[:len(siger.qb64b)]
        assert len(msg) == 1068 - 3 * len(siger.qb64b) == 804

        counter = coring.Counter(qb64b=msg)  # trans receipt (vrc) counter
        assert counter.code == coring.CtrDex.TransReceiptQuadruples
        assert counter.count == 3  #  multisig cam
        del msg[:len(counter.qb64b)]
        assert len(msg) == 800

        for i in range(counter.count):  # parse receipt quadruples
            prefixer, seqner, diger, siger = eventing.deTransReceiptQuadruple(
                msg, strip=True)
        assert len(msg) == 800 - 3 * (len(prefixer.qb64b) + len(
            seqner.qb64b) + len(diger.qb64b) + len(siger.qb64b)) == 200

        counter = coring.Counter(qb64b=msg)  # nontrans receipt (rct) counter
        assert counter.code == coring.CtrDex.NonTransReceiptCouples
        assert counter.count == 1  #  single sig bev
        del msg[:len(counter.qb64b)]
        assert len(msg) == 196

        for i in range(counter.count):  # parse receipt couples
            prefixer, cigar = eventing.deReceiptCouple(msg, strip=True)
        assert len(
            msg) == 196 - 1 * (len(prefixer.qb64b) + len(cigar.qb64b)) == 64

        counter = coring.Counter(qb64b=msg)  # first seen replay couple counter
        assert counter.code == coring.CtrDex.FirstSeenReplayCouples
        assert counter.count == 1
        del msg[:len(counter.qb64b)]
        assert len(msg) == 60

        seqner = coring.Seqner(qb64b=msg)
        assert seqner.sn == fn == 0
        del msg[:len(seqner.qb64b)]
        assert len(msg) == 36  # 24 less

        dater = coring.Dater(qb64b=msg)
        assert (helping.fromIso8601(helping.nowIso8601()) -
                helping.fromIso8601(dater.dts)) > datetime.timedelta()
        del msg[:len(dater.qb64b)]
        assert len(msg) == 0  # 36 less

        cloner.close()  # must close or get lmdb error upon with exit
        """Exception ignored in: <generator object LMDBer.getAllOrdItemPreIter at 0x106fe1c10>
        Traceback (most recent call last):
        File "/Users/Load/Data/Code/public/keripy/src/keri/db/dbing.py", line 512, in getAllOrdItemPreIter
        yield (cn, bytes(val))  # (on, dig) of event
        lmdb.Error: Attempt to operate on closed/deleted/dropped object.
        """

        fn += 1
        cloner = debHab.db.cloneIter(pre=debHab.pre,
                                     fn=fn)  # create iterator not at 0
        msg = next(cloner)  # next event with attachments
        assert len(msg) == 1228
        serder = coring.Serder(raw=msg)
        assert serder.sn == fn  # no recovery forks so sn == fn
        assert serder.ked["t"] == coring.Ilks.ixn
        debFelMsgs.extend(msg)

        fn += 1
        msg = next(cloner)  # get zeroth event with attachments
        serder = coring.Serder(raw=msg)
        assert serder.sn == fn  # no recovery forks so sn == fn
        assert serder.ked["t"] == coring.Ilks.rot
        assert len(msg) == 1476
        assert ([verfer.qb64 for verfer in serder.verfers
                 ] == [verfer.qb64 for verfer in debHab.kever.verfers])
        debFelMsgs.extend(msg)

        fn += 1
        while (fn <= 6):
            msg = next(cloner)  # get zeroth event with attachments
            serder = coring.Serder(raw=msg)
            assert serder.sn == fn  # no recovery forks so sn == fn
            assert serder.ked["t"] == coring.Ilks.ixn
            assert len(msg) == 1228
            debFelMsgs.extend(msg)
            fn += 1

        assert len(debFelMsgs) == 9039
        cloner.close()  # must close or get lmdb error upon with exit

        msgs = debHab.replay()
        assert msgs == debFelMsgs

        # Play Cam's messages to Bev
        bevKevery.process(ims=bytearray(camMsgs))  # give copy to process
        assert camHab.pre in bevKevery.kevers
        assert bevKevery.kevers[camHab.pre].sn == camHab.kever.sn == 0
        assert len(bevKevery.cues) == 1

        # Play Bev's messages to Cam
        camKevery.process(ims=bytearray(bevMsgs))  # give copy to process
        assert bevHab.pre in camKevery.kevers
        assert camKevery.kevers[bevHab.pre].sn == bevHab.kever.sn == 0
        assert len(camKevery.cues) == 1

        camDebFelMsgs = camHab.replay(pre=debHab.pre)
        bevDebFelMsgs = bevHab.replay(pre=debHab.pre)

        assert len(bevDebFelMsgs) == len(camDebFelMsgs) == len(
            debFelMsgs) == 9039

        # create non-local kevery for Art to process conjoint replay msgs from Deb
        artKevery = eventing.Kevery(kevers=artHab.kevers,
                                    db=artHab.db,
                                    framed=True,
                                    opre=artHab.pre,
                                    local=False)
        # process Cam's inception so Art will proces Cam's vrcs without escrowing
        camIcpMsg = camHab.makeOwnInception()
        artKevery.process(ims=bytearray(camIcpMsg))
        assert camHab.pre in artKevery.kevers
        assert len(artKevery.cues) == 1

        artKevery.process(ims=bytearray(debFelMsgs),
                          cloned=True)  # give copy to process
        assert debHab.pre in artKevery.kevers
        assert artKevery.kevers[debHab.pre].sn == debHab.kever.sn == 6
        assert len(artKevery.cues) == 8
        artDebFelMsgs = artHab.replay(pre=debHab.pre)
        assert len(artDebFelMsgs) == 9039

    assert not os.path.exists(artKS.path)
    assert not os.path.exists(artDB.path)
    assert not os.path.exists(bevKS.path)
    assert not os.path.exists(bevDB.path)
    assert not os.path.exists(camKS.path)
    assert not os.path.exists(camDB.path)
    assert not os.path.exists(debKS.path)
    assert not os.path.exists(debDB.path)
    """End Test"""