Exemplo n.º 1
0
def test_build_proof():
    sidSalt = coring.Salter(raw=b'0123456789abcdef').qb64

    with basing.openDB(name="sid") as sigDB, \
            keeping.openKS(name="sid") as sigKS:
        sigHab = habbing.Habitat(ks=sigKS, db=sigDB, salt=sidSalt, icount=3, ncount=3, temp=True)

        sed = dict()
        sed["$id"] = ""
        sed["$schema"] = "http://json-schema.org/draft-07/schema#"
        sed.update(dict(
            type="object",
            properties=dict(
                id=dict(
                    type="string"
                ),
                lei=dict(
                    type="string"
                )
            )
        ))

        schemer = scheming.Schemer(sed=sed, typ=scheming.JSONSchema(), code=coring.MtrDex.Blake3_256)
        credSubject = dict(
            id="did:keri:Efaavv0oadfghasdfn443fhbyyr4v",  # this needs to be generated from a KEL
            lei="254900OPPU84GM83MG36",
            issuanceDate="2021-06-27T21:26:21.233257+00:00",
        )

        cache = CacheResolver()
        cache.add(schemer.said, schemer.raw)

        creder = credential(issuer=sigHab.pre,
                            schema=schemer.said,
                            subject=credSubject,
                            typ=JSONSchema(resolver=cache))

        sigHab.rotate()
        sigHab.rotate()
        sigHab.rotate()
        sigHab.rotate()

        prefixer = coring.Prefixer(qb64=sigHab.kever.prefixer.qb64)
        seqner = coring.Seqner(sn=sigHab.kever.lastEst.s)
        diger = coring.Diger(qb64=sigHab.kever.lastEst.d)

        sigers = sigHab.mgr.sign(ser=creder.raw, verfers=sigHab.kever.verfers, indexed=True)

        proof = buildProof(prefixer, seqner, diger, sigers)
        assert proof == (
            b'-FABEiRjCnZfca8gUZqecerjGpjkiY8dIkGudP6GfapWi5MU0AAAAAAAAAAAAAAAAAAAAABAECc96yX1sYswnD6LXEcoNuJ0e'
            b'hi8gkFMEGedqURhXMBU-AADAAGcSUhma16SY3MiKU7n6mK3JzWS2oAiBRB-jeycIDrQ2Z-36QHrMorzRAO9Iw7FvIKrneaLZP'
            b'whz6DFFiXM4oBgAB1g2CudOfOFd9BqesyAIlCDRAkxAQynrED4_ot1MkhKwjmK71XUx1Xer25iWtHMa9sny07AsTO-KE3vu9e'
            b'qTPDQAClDQMXWg3I8qeVEjA6JA9xBW2uESMtMzNVQ8lH31UCizqYVjXort--QEJTsfIt_b0Qq1JOCtaj7Y6U-DWHoulBA')

        prefixer, seqner, diger, isigers = parseProof(proof)
        assert prefixer.qb64 == sigHab.pre
        assert diger.qb64 == sigHab.kever.lastEst.d
        assert seqner.sn == 4
        assert len(isigers) == 3
Exemplo n.º 2
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 basing.openDB(name="deb") as debDB, keeping.openKS(name="deb") as debKS, \
         basing.openDB(name="cam") as camDB, keeping.openKS(name="cam") as camKS, \
         basing.openDB(name="bev") as bevDB, keeping.openKS(name="bev") as bevKS, \
         basing.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 = habbing.Habitat(name='deb',
                                 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 = habbing.Habitat(name='cam',
                                 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 = habbing.Habitat(name='bev',
                                 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 = habbing.Habitat(name='art',
                                 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":"EeTLHxy5Npa4SQlFABzhu66FUuSl_iJAaf'
            b'ez-encK314","s":"0","t":"icp","kt":["1/2","1/2","1/2"],"k":["DRx'
            b'CLERO9eSvG4fluzOsK52GCWCtKOZClVwA38Oa--MA","DCxzT16ikP6LKVJfr6hv'
            b'1jmhynm6I4-KoGYkJtd9uBro","DsDl5xSHnIlcGo13u5jDRr1jJMkQ34nEc5R6N'
            b'YsdPS2k"],"n":"Eer5S019j0eEFNFLb0R0UDMoNLavlLiQ73fHGU7MUHXg","bt'
            b'":"0","b":[],"c":[],"a":[]}-AADAA4HzkCruAhoxet6Vrk_tBCwbwaT78dRw'
            b'w9RQJb0MR_tmSpEYOYDue-pBQCthsgDJzjyElpSmzNedlY-hVd6rbDwABJnfOgI6'
            b'teO_3fESnXgiz_9J_F_VfQliLWvLCM8ZnVjrryBuiMYOUmHbfXuNtRC4iZxb-RU0'
            b'lC55O0r5c5hyrAgACnZEXW7jYpAdrIfmOmH-OEHmhxcwQNu31k-mmzyNTfFvAxmp'
            b'r7-zLdmzlWKfMBlE6eAbDgCdNr_VL2l8xeJExAA{"v":"KERI10JSON000098_",'
            b'"i":"EeTLHxy5Npa4SQlFABzhu66FUuSl_iJAafez-encK314","s":"1","t":"'
            b'ixn","p":"E4gF0E1fkpEPBjeq1Sm-RK_Rvg56KOmtBHGfNe_tPxWc","a":[]}-'
            b'AADAAvo8lxVzu4YS6nG3BXu7PncYdZO57P4gYY-ikaRepVIOeRnZ10iMdJGcyULm'
            b'mdXLRaVxtuxI956cJljg3joSMBgABgHtCeHi-UZjnI1IWW9ZF8E7ni6UwerFOvPV'
            b'7z3i1pI7D3HJCoSx8XkhdXPGzUtrNuAvxVptsJtF17_-rP50bBwACguCjTA2taPP'
            b'EyhVecWjtpoBJCAiYeTdeDv3Hq0pAJXWa7SWjxlDR2-f1TIIXg8PbBD_tgn4Z6zp'
            b'LZcPLLHH5Cg{"v":"KERI10JSON000190_","i":"EeTLHxy5Npa4SQlFABzhu66'
            b'FUuSl_iJAafez-encK314","s":"2","t":"rot","p":"EYROVd3Ho83kEgBkrN'
            b'v6kqTAG4YeCqyPWYBo2jCPteiw","kt":["1/2","1/2","1/2"],"k":["Dj-DU'
            b'wfCmOrE3ijqucR0I89_fYTFbyotaqeQyDfupkEU","DL-k_8BanjLYaAdm6WWKIp'
            b'HcHwcbF834vnLPgpW1NL8k","DWG2ZFsWYUsbDI1Kmu8JH22iGaVDGvM7pnuT4y2'
            b'oR3VI"],"n":"EYd4ha92A2yttnCoLMqFGRzh6nsgduE910LD-scP7C3Q","bt":'
            b'"0","br":[],"ba":[],"a":[]}-AADAAspTV94LrwMhYVzZD0xu16aKjf1YQ8nT'
            b'Ta08ik1Fah545jAoe6n1xdnKSgL9Alucp4F-Yl69ksAttb4hTlnikDwABKspYVa4'
            b'J3r7ox-gDsPbpI5jiFSTcDCjBJGfU6hWhMXx7zpgG1jt4cTeW83oaILMbW85i_U7'
            b'RT3x6Sm2z5ytCCQACf157-iV13AXKaIddVaXexNx5K9INhJ44tfpb3OBjuPk5JMj'
            b'VGIU0iz5LkQlc_rV9D79E1pC5Z--YGplzQMv0Ag{"v":"KERI10JSON000098_",'
            b'"i":"EeTLHxy5Npa4SQlFABzhu66FUuSl_iJAafez-encK314","s":"3","t":"'
            b'ixn","p":"EA4mqdTa4RPrUJ3B_lmEPSxQK50tDkxRRVwVlLzcAdb0","a":[]}-'
            b'AADAAte_OEI-pzZulc4454QS391RR5bPndHIoLG_vLsC4Qmedqz7o04zuisW-7mr'
            b'TcfU6ZWs7rlMdSHTBZFErsY-FDQABiHkOIixpSaHGZ80--2JzhmR0TCla09WiEJH'
            b'5gTd9XXmxDfzDVON9FgDqLKf_Tf1nmgRh_eQFXu42jfvQG4Q1AAACp478kKPjbh1'
            b'pCxlmqa65PplcTa9zG4zsdYz2raYOiregvotKK30LNXm58886gSuSnEWifJvb-zY'
            b'wvdK8GsgqBg{"v":"KERI10JSON000098_","i":"EeTLHxy5Npa4SQlFABzhu66'
            b'FUuSl_iJAafez-encK314","s":"4","t":"ixn","p":"Ecw6XFmjIeMiYp1MTG'
            b'e4KRk9HnygNpnORox6AaCfC44Y","a":[]}-AADAANlbayWV5QQdCTqmh9dSEb13'
            b'stiK3srIyL9z4FWMZr_nwejoqK9j9Ic6wBQiUVksayOmGVtknUWrDNOY-PzzgBQA'
            b'B2FONMatheF144ziEB7uJpGZa3vugxedmLFfOD5CcoX7z6eX6ZZ_fIVkOHRVOxmv'
            b'nfYyVF7uC8G40PeGgkh5eCAACSwyvmjZcik1VBQCCfh5Mq2SQLUvVfFg9plIanMR'
            b'Trp7bG_OXE5SSqou6VFNon3Ub8IlBA90-dR7DRRDNPQ5UBw{"v":"KERI10JSON0'
            b'00098_","i":"EeTLHxy5Npa4SQlFABzhu66FUuSl_iJAafez-encK314","s":"'
            b'5","t":"ixn","p":"EQW9ROsIuNEdKu_ZIm9zDPKIVallegMHz2PVygiZgttc",'
            b'"a":[]}-AADAAtjUR1rNouk9T92o22qUbNvptIEjrnqKU3eJTiwdDGoWIwhTLY1T'
            b'UunYYpqtbk55oaCyc_MXkP-6l57YDiOAsCwAB5Fl7CZj1P1-NsYgrf2caXvWTfkg'
            b'u15C61JRuRpDnjTtevCjxspLQw6hxeJ6-2mTZHqIHC3hzW01Ed2mFOC_eDAACV87'
            b'jI4scXXRlNfqXmRrsivc0p3vBIO1OLNC6fex-bFbwV6U8zd_pjWTDZLwCnDm3KJq'
            b'labzAfGxX32trskGpCQ{"v":"KERI10JSON000098_","i":"EeTLHxy5Npa4SQl'
            b'FABzhu66FUuSl_iJAafez-encK314","s":"6","t":"ixn","p":"E52dhrHeFM'
            b'AYWsROU3fPEmD8pCsO_Q2MfvLuZufX43o0","a":[]}-AADAAVe6bfQeaR2X8UIB'
            b'OS1HMVLWho7FETQ17FQly0USMiSVDIWh8KTEeW-ndMDUlDBBeNEf3UiwDIRE62-k'
            b'ICoofAwABk4ndaxtTYTLmlxWM2Qb38RYtwSRzr7KRRbhLmL_zLXa7KnoAkmCa9LL'
            b'ZT5o_6rNjuFruYo7eSL4JfFhCEEn_CwACdPvsbvEV30PaDhbDmdVqI9fzGOSp34e'
            b'oTChNPt_UGq3uvCAAlwJa66g4WndLiTkN_BmKZP8YCgn40mUj5TFnAQ')

        # Play debMsgs to Cam
        # create non-local kevery for Cam to process msgs from Deb
        camKevery = eventing.Kevery(db=camHab.db, lax=False, local=False)
        parsing.Parser().parse(ims=bytearray(debMsgs), kvy=camKevery)
        # 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":"EnjQHu6cA7Mk4gdlnSbhaKtjOh23I2_1ZZ'
            b'9KYr-ZdNMg","s":"0","t":"icp","kt":"2","k":["DJBtEHHnzNtE-zxH1xe'
            b'X4wxs9rEfUQ8d1ancgJJ1BLKk","DMu6yPITjrOBoTPfsY-r1Rc0ead8GKmoCxA_'
            b'BugKehgY","DfhpvbNyYu1fxTBTXy8eCgghMcOYnxkgoGPBr0ZBZPQA"],"n":"E'
            b'J85AI0se7UiFBFL1Vl80PnmQ-0dU6q_NXCh6BlSJcKg","bt":"0","b":[],"c"'
            b':[],"a":[]}-AADAAya98TxjoKqXBaXKBKmu0_98hrOSjoq8YeT5HlKBZsBvGPGU'
            b'NE3Ex9lkhLTl-U_Gx_1JLqEYJJaVrGLaArb5pDAABiYDraSegcRyxe8Syrd3uYqN'
            b'HTcalW-_hgVqsUDEZcqdsbje2fBxHO4blsODaSDMm2Crvdj5uvaLch-svOBdEDgA'
            b'CVGMTILr9hF9NHVscjqi5yCvtkwMhtZHEqh_6v7N_flmXKCkN2AXAi9OEmf-pdXj'
            b'0UlLdab6MkOfbxSRsmrjTDQ{"v":"KERI10JSON000091_","i":"EeTLHxy5Npa'
            b'4SQlFABzhu66FUuSl_iJAafez-encK314","s":"0","t":"rct","d":"E4gF0E'
            b'1fkpEPBjeq1Sm-RK_Rvg56KOmtBHGfNe_tPxWc"}-FABEnjQHu6cA7Mk4gdlnSbh'
            b'aKtjOh23I2_1ZZ9KYr-ZdNMg0AAAAAAAAAAAAAAAAAAAAAAAEZdlVoasgQzvn7mj'
            b'ai5hTX7JgLyHrRkeo8Mf5SXL10ro-AADAAY7ru97WNltKYXVBeiqSQ2JhCU6W6Uv'
            b'wSmYQRNAQ7Vk3_VslqnAkQDApZwVY-I5nonPybqxS4riBoN8O2MvH3BwABNvm83-'
            b'pYo3WR7BAtg13vvHsaX2PfSZn7ajBCRzUXaQ0ZLNr0wJddMywcVtOrgY0myRmiNq'
            b'YvetEkb0PJwQG4AwACjit5HUQSAeEMyfC5GeAsPHsGqLwbYMJdqxuZrnzfE2xtXe'
            b'3dEz9iSKEFUbykO0f1ThpMLpjat3SsNtZUtn07CQ{"v":"KERI10JSON000091_"'
            b',"i":"EeTLHxy5Npa4SQlFABzhu66FUuSl_iJAafez-encK314","s":"1","t":'
            b'"rct","d":"EYROVd3Ho83kEgBkrNv6kqTAG4YeCqyPWYBo2jCPteiw"}-FABEnj'
            b'QHu6cA7Mk4gdlnSbhaKtjOh23I2_1ZZ9KYr-ZdNMg0AAAAAAAAAAAAAAAAAAAAAA'
            b'AEZdlVoasgQzvn7mjai5hTX7JgLyHrRkeo8Mf5SXL10ro-AADAAx2QNu8staqEHq'
            b'lv3z__tb9wPPuwTqF3uicXv5BAr3npLW541r9RKcDUQ1yMk1TWcs1vO2a_L2rwtC'
            b'h_pP8kzAgABk1B6jf72NOLhSIbAXTbM5JhxiFatklzqYCkiQw12jGxNOHxmEuKNF'
            b'0IatvNc3m96hcOb7dc2ZOIQGxX9Ud9nCwAC9LGHfopCtAgtC7OK-aOfYQXN36_Ll'
            b'RHZu3eeT9E_pFG9I0LYfoRNf0hGVcyPRBpqrIVOTkH1NBWRbVyOMSYhDA{"v":"K'
            b'ERI10JSON000091_","i":"EeTLHxy5Npa4SQlFABzhu66FUuSl_iJAafez-encK'
            b'314","s":"2","t":"rct","d":"EA4mqdTa4RPrUJ3B_lmEPSxQK50tDkxRRVwV'
            b'lLzcAdb0"}-FABEnjQHu6cA7Mk4gdlnSbhaKtjOh23I2_1ZZ9KYr-ZdNMg0AAAAA'
            b'AAAAAAAAAAAAAAAAAAEZdlVoasgQzvn7mjai5hTX7JgLyHrRkeo8Mf5SXL10ro-A'
            b'ADAAmMLDAvNgoQ_hnYEfx6uzg0LzRuODZmgwhou-EZv83BNJ9JwNabG9oSuLL15Z'
            b'Zc0blUm8GJ0BJuBcE4rjNW3-CAABlkXt_qnbOaBjqlfNXbLxZ_Rx2SCy8pVSYSz7'
            b'-UbB2lHpIfGMApVcTamn4pYhyOnaEVVO47tWZ3vDmXkf3WrKBQAC4MZmfqt3B9SY'
            b'DROZk8shO6vWxzHfZVBzLtNZAJrJLq8FoZ66q3bG4Pgn1pc0ID0fjkpXSiR5aOF2'
            b'2QhT06erDA{"v":"KERI10JSON000091_","i":"EeTLHxy5Npa4SQlFABzhu66F'
            b'UuSl_iJAafez-encK314","s":"3","t":"rct","d":"Ecw6XFmjIeMiYp1MTGe'
            b'4KRk9HnygNpnORox6AaCfC44Y"}-FABEnjQHu6cA7Mk4gdlnSbhaKtjOh23I2_1Z'
            b'Z9KYr-ZdNMg0AAAAAAAAAAAAAAAAAAAAAAAEZdlVoasgQzvn7mjai5hTX7JgLyHr'
            b'Rkeo8Mf5SXL10ro-AADAASQpD32fjD-IJuz9w1CFLXYtHE-9rtVRqSvQPqT8yjHO'
            b'lKMNG2apDa___svlQSw_OmgsCB-LzQn7dyyv73w3KCQABcbrlJRw3GaM5l5NCq_7'
            b'czfZBAyXPwvpfjwM3BAMnt-tDmTEoJku4MpruiwpgSWcPw_Xp3SE3nmxPIK6-Q08'
            b'aCAAC58Bw2io7IEt3ZvfEdaHns97Y4QGCnFovmz9VFfp3c2Mjioa1sDgOf9uybHV'
            b'MKBhpsUy2_BfpgkVOhmcY6GtzCw{"v":"KERI10JSON000091_","i":"EeTLHxy'
            b'5Npa4SQlFABzhu66FUuSl_iJAafez-encK314","s":"4","t":"rct","d":"EQ'
            b'W9ROsIuNEdKu_ZIm9zDPKIVallegMHz2PVygiZgttc"}-FABEnjQHu6cA7Mk4gdl'
            b'nSbhaKtjOh23I2_1ZZ9KYr-ZdNMg0AAAAAAAAAAAAAAAAAAAAAAAEZdlVoasgQzv'
            b'n7mjai5hTX7JgLyHrRkeo8Mf5SXL10ro-AADAAsW_khBjW_8JTAMqSmfO719vBlr'
            b'NVpJu-8bpboWZm8hhYfKEEfUWC40GWoYwSN_Xk-2v6oPVp4_oHVVB4hMavAAABuR'
            b'VEC014QaDOacru4RchNJBZCa5jKhfK10vt-Mb88mQY-HF-kVywqvGnkFyCZowKPz'
            b'sLEJbTAa8py3hCKJ-5AQACo4tT9i1sv7JM6zhprqwklVnYKsG6Y1DCfGj6c6vIWz'
            b'StZeO_ICz9iOZkB8IuwJp8r5AYgqJlNl8cl93sgknZDw{"v":"KERI10JSON0000'
            b'91_","i":"EeTLHxy5Npa4SQlFABzhu66FUuSl_iJAafez-encK314","s":"5",'
            b'"t":"rct","d":"E52dhrHeFMAYWsROU3fPEmD8pCsO_Q2MfvLuZufX43o0"}-FA'
            b'BEnjQHu6cA7Mk4gdlnSbhaKtjOh23I2_1ZZ9KYr-ZdNMg0AAAAAAAAAAAAAAAAAA'
            b'AAAAAEZdlVoasgQzvn7mjai5hTX7JgLyHrRkeo8Mf5SXL10ro-AADAA_06qSZGjm'
            b'75-wLDLPBK-p32mM1oeDQAQD2wfdQ75jn-JRkYqGztS2tQDBFlxK4uiceok50-ZJ'
            b'f64An_oB649AQABZpuMeCzUi0oF98kXROI94G3cWLVrDVdbvxDNe60uE7rQ-qwDq'
            b'tErr65hMaCgbTO3zD9aumRQMU5-1uWZrIxWDQACyukFA_3zKJQyctI3JER5XO8r_'
            b'iz9Ga5CXxnZFqSuGmQqQEpA9wMDOZ66hRBRNgImMQh-btX4sqbjO_ycaGmjBg{"v'
            b'":"KERI10JSON000091_","i":"EeTLHxy5Npa4SQlFABzhu66FUuSl_iJAafez-'
            b'encK314","s":"6","t":"rct","d":"ENsvgXw3H4VhL3i-eONdu7tgarzrgm9z'
            b'c2Lj3XlwZ2_4"}-FABEnjQHu6cA7Mk4gdlnSbhaKtjOh23I2_1ZZ9KYr-ZdNMg0A'
            b'AAAAAAAAAAAAAAAAAAAAAAEZdlVoasgQzvn7mjai5hTX7JgLyHrRkeo8Mf5SXL10'
            b'ro-AADAAEjRuwX1j8xEYIXjf1cmhLpmF4IwKBGU2fvL0rbbBMN4bA4VTtnAqo6Nh'
            b'GYK4XKKVL_SKLaL9x9PcFc5ykBqsBwABVwlNGkdx_oScxgYzhLMDmAi-Ro5n85ly'
            b'LRI6DdtMIRfpgyIa2pPw1BkA2FmmsUkkwdTWxNq77AyfbcQzDKOzDAACSIxniS9R'
            b'7dsM11Q8uD5qSAxcGyF-CUNYT7NZmQdL52MnszSYy7Mvpwnq9L842jNgL_G8zqif'
            b'0eizybIVsQj7AQ')

        # Play camMsgs to Deb
        # create non-local kevery for Deb to process msgs from Cam
        debKevery = eventing.Kevery(db=debHab.db, lax=False, local=False)
        parsing.Parser().parse(ims=bytearray(camMsgs), kvy=debKevery)
        # 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":"KERI10JSON000091_","i":"EnjQHu6cA7Mk4gdlnSbhaKtjOh23I2_1ZZ'
            b'9KYr-ZdNMg","s":"0","t":"rct","d":"EZdlVoasgQzvn7mjai5hTX7JgLyHr'
            b'Rkeo8Mf5SXL10ro"}-FABEeTLHxy5Npa4SQlFABzhu66FUuSl_iJAafez-encK31'
            b'40AAAAAAAAAAAAAAAAAAAAAAgEA4mqdTa4RPrUJ3B_lmEPSxQK50tDkxRRVwVlLz'
            b'cAdb0-AADAARwO4P3VantEgLrBs4K7hvStQ_kpN5EiFjklROGNkV19PBtxO0uUU8'
            b'0RDbWBjuUgIm59v9oJQKe-hdS8neEI2CgABAptixkGIj7UX1PU9Vlr1kZexUaIie'
            b'AugElzH99gCfQG2MMtOb3EO5ybgMHkWKKr7PaTpi4H2XrQ-me-PT_fGAgACSUTaW'
            b'0o0XhD0bQn-Qv2TwDj01L8zRyy7dqlGemZSzl2DBnliA_NqGHBQ2QJKIZfuIc6Mc'
            b'c3n_HpqI6s7xt-jCQ')

        # Play disjoints debCamVrcs to Cam
        parsing.Parser().parseOne(ims=bytearray(debCamVrcs), kvy=camKevery)
        # 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(db=bevHab.db, lax=False, local=False)
        parsing.Parser().parse(ims=bytearray(debMsgs), kvy=bevKevery)
        # 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":"BCqmHiYBZx_uaQiCTVeum-vt1ZPti8chqb'
            b'-GpQBPaurA","s":"0","t":"icp","kt":"1","k":["BCqmHiYBZx_uaQiCTVe'
            b'um-vt1ZPti8chqb-GpQBPaurA"],"n":"","bt":"0","b":[],"c":[],"a":[]'
            b'}-AABAAgO3RAPPeeFcl5ZvoIR55jsqjQsfKQNenz9EUITRBtu9Q5Js-Umzd_mvSq'
            b'ZymNJnwLL656s7P-hTZRtG-8-rhBg{"v":"KERI10JSON000091_","i":"EeTLH'
            b'xy5Npa4SQlFABzhu66FUuSl_iJAafez-encK314","s":"0","t":"rct","d":"'
            b'E4gF0E1fkpEPBjeq1Sm-RK_Rvg56KOmtBHGfNe_tPxWc"}-CABBCqmHiYBZx_uaQ'
            b'iCTVeum-vt1ZPti8chqb-GpQBPaurA0B0VYuHkBtlKSqsXj_0-2mSNzQ9UOiO-iX'
            b'jG4V74ivokdt9GUYh5OnZ-lW-SfyzGhQv6QlPRcy7nWTyi_mMzOCAg{"v":"KERI'
            b'10JSON000091_","i":"EeTLHxy5Npa4SQlFABzhu66FUuSl_iJAafez-encK314'
            b'","s":"1","t":"rct","d":"EYROVd3Ho83kEgBkrNv6kqTAG4YeCqyPWYBo2jC'
            b'Pteiw"}-CABBCqmHiYBZx_uaQiCTVeum-vt1ZPti8chqb-GpQBPaurA0B_gS89Rl'
            b'Y4y-YTTgBpjdBiA6l8PbGZkd4ODmA3RQyDGVapnpMB_SLvolQuz7WxyE0NsnpJ-D'
            b'nVFTt-Dv-dKGADA{"v":"KERI10JSON000091_","i":"EeTLHxy5Npa4SQlFABz'
            b'hu66FUuSl_iJAafez-encK314","s":"2","t":"rct","d":"EA4mqdTa4RPrUJ'
            b'3B_lmEPSxQK50tDkxRRVwVlLzcAdb0"}-CABBCqmHiYBZx_uaQiCTVeum-vt1ZPt'
            b'i8chqb-GpQBPaurA0BcbCV4kKek9oab8MDhzvzf0ucYnTIzNiWHLNh65mpxUa2XL'
            b'jrEfbWlrjpiDXTyYShlLNt8fZxnnwoAW4aelTyBA{"v":"KERI10JSON000091_"'
            b',"i":"EeTLHxy5Npa4SQlFABzhu66FUuSl_iJAafez-encK314","s":"3","t":'
            b'"rct","d":"Ecw6XFmjIeMiYp1MTGe4KRk9HnygNpnORox6AaCfC44Y"}-CABBCq'
            b'mHiYBZx_uaQiCTVeum-vt1ZPti8chqb-GpQBPaurA0BZSz6DBrS702RsSJ2qhp5V'
            b'_4UG3u4v9_PZUxZqkTnBmkxkX-dA9Ml5c_2YaZ0_ETfhrbq30r1elT4gXhKJbRAA'
            b'A{"v":"KERI10JSON000091_","i":"EeTLHxy5Npa4SQlFABzhu66FUuSl_iJAa'
            b'fez-encK314","s":"4","t":"rct","d":"EQW9ROsIuNEdKu_ZIm9zDPKIVall'
            b'egMHz2PVygiZgttc"}-CABBCqmHiYBZx_uaQiCTVeum-vt1ZPti8chqb-GpQBPau'
            b'rA0BFvLdsWHk5oGOZQCnDEVww3dMlXZYo9JzNbuJUdK0IqWaJAQBIMEKOqLvZzMx'
            b'FIi6xNmJCQYKFu5328ovxtddCg{"v":"KERI10JSON000091_","i":"EeTLHxy5'
            b'Npa4SQlFABzhu66FUuSl_iJAafez-encK314","s":"5","t":"rct","d":"E52'
            b'dhrHeFMAYWsROU3fPEmD8pCsO_Q2MfvLuZufX43o0"}-CABBCqmHiYBZx_uaQiCT'
            b'Veum-vt1ZPti8chqb-GpQBPaurA0BDaF78ajVz3FOsApq_1iBTK2i1PT8F0Fgz4q'
            b'r4HuboYf5XMWR8IvrYcYvthaaRP5168Ge-npP6UgRUd7t8vwCDw{"v":"KERI10J'
            b'SON000091_","i":"EeTLHxy5Npa4SQlFABzhu66FUuSl_iJAafez-encK314","'
            b's":"6","t":"rct","d":"ENsvgXw3H4VhL3i-eONdu7tgarzrgm9zc2Lj3XlwZ2'
            b'_4"}-CABBCqmHiYBZx_uaQiCTVeum-vt1ZPti8chqb-GpQBPaurA0B9TkOKxh1bS'
            b'1gwzpNCx5R-AW0D_xHbbBNlVSdyPW4VUJm4PvRCK9UFsHHk2LGv0KbqRe7ftiY6o'
            b'V7hSkY4rfGAw')

        # Play bevMsgs to Deb
        parsing.Parser().parse(ims=bytearray(bevMsgs), kvy=debKevery)
        # 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":"KERI10JSON000091_","i":"BCqmHiYBZx_uaQiCTVeum-vt1ZPti8chqb'
            b'-GpQBPaurA","s":"0","t":"rct","d":"ERejsDJsBCs9b2j0Cd3pIDxNoGEw8'
            b'zQd94AXMduyyIF8"}-FABEeTLHxy5Npa4SQlFABzhu66FUuSl_iJAafez-encK31'
            b'40AAAAAAAAAAAAAAAAAAAAAAgEA4mqdTa4RPrUJ3B_lmEPSxQK50tDkxRRVwVlLz'
            b'cAdb0-AADAApoGcQmhmFQ2tQmovG0aZNxBN3QMgynKdfVA3pNyJQ-UMBnliFkeaC'
            b'gioFRXuH9SLm3R1XlFjmIJNvZ7hoJ3bBQABLKipRIasV9TRzcoGF7sQs9vfkcneF'
            b'7y1YqKMw9oWKEzhJKMuk0QUz6E1fse8mUDazKQsXqY1uKnSFhfjuqAhBQACFrF4i'
            b'Nt4Cm0srlq1QsXwJe3duzNKOEdf4z-WxWSw49dDpYyfllWEIs8Eu65IADEycjZR3'
            b'q9BTeO9QARuieV_Dw')

        # Play disjoints debBevVrcs to Bev
        parsing.Parser().parseOne(ims=bytearray(debBevVrcs), kvy=bevKevery)
        # 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.clonePreIter(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.clonePreIter(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
        parsing.Parser().parse(ims=bytearray(camMsgs), kvy=bevKevery)
        # 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
        parsing.Parser().parse(ims=bytearray(bevMsgs), kvy=camKevery)
        # 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(db=artHab.db, lax=False, local=False)
        # process Cam's inception so Art will proces Cam's vrcs without escrowing
        camIcpMsg = camHab.makeOwnInception()
        parsing.Parser().parse(ims=bytearray(camIcpMsg), kvy=artKevery)
        # artKevery.process(ims=bytearray(camIcpMsg))
        assert camHab.pre in artKevery.kevers
        assert len(artKevery.cues) == 1

        # process in cloned mode
        artKevery.cloned = True
        parsing.Parser().parse(ims=bytearray(debFelMsgs), kvy=artKevery)
        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"""
Exemplo n.º 3
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"""
Exemplo n.º 4
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 basing.openDB(name="bob") as bobDB, \
          keeping.openKS(name="bob") as bobKS, \
          basing.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)

        bob = bobSrdr.ked["i"]
        assert bob == 'Eta8KLf1zrE5n-HZpgRAnDmxLASZdXEiU9u6aahqR8TI'

        bobMgr.move(old=verfers[0].qb64,
                    new=bob)  # 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 == (
            b'{"v":"KERI10JSON0000ed_","i":"Eta8KLf1zrE5n-HZpgRAnDmxLASZdXEiU9'
            b'u6aahqR8TI","s":"0","t":"icp","kt":"1","k":["DqI2cOZ06RwGNwCovYU'
            b'WExmdKU983IasmUKMmZflvWdQ"],"n":"E7FuL3Z_KBgt_QAwuZi1lUFNC69wvyH'
            b'SxnMFUsKjZHss","bt":"0","b":[],"c":[],"a":[]}-AABAAp8S6RgfLwdCEi'
            b'z0jL9cXaDwTJF6MLuKyXp7EfJtrp2myOikOJVUB-w9UGZc1Y8dnURxhXPSca-ZEU'
            b'AV73XOaAw')

        # apply msg to bob's Kevery
        parsing.Parser().parse(ims=bytearray(msg), kvy=bobKvy)
        # bobKvy.process(ims=bytearray(msg))  # process local copy of msg
        bobK = bobKvy.kevers[bob]
        assert bobK.prefixer.qb64 == bob
        assert bobK.serder.diger.qb64 == bobSrdr.dig
        assert bobK.serder.diger.qb64 == 'E1-QL0TCdsBTRaKoakLjFhjSlELK60Vv8WdRaG6zMnTM'

        # apply msg to del's Kevery
        parsing.Parser().parse(ims=bytearray(msg), kvy=delKvy)
        # delKvy.process(ims=bytearray(msg))  # process remote copy of msg
        assert bob 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

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

        delPre = delSrdr.ked["i"]
        assert delPre == 'E-9tsnVcfUyXVQyBPGfntoL-xexf4Cldt_EPzHis2W4U'

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

        # 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()])

        assert bobSrdr.dig == 'E3fUycq1G-P1K1pL2OhvY6ZU-9otSa3hXiCcrxuhjyII'

        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 == (
            b'{"v":"KERI10JSON000107_","i":"Eta8KLf1zrE5n-HZpgRAnDmxLASZdXEiU9'
            b'u6aahqR8TI","s":"1","t":"ixn","p":"E1-QL0TCdsBTRaKoakLjFhjSlELK6'
            b'0Vv8WdRaG6zMnTM","a":[{"i":"E-9tsnVcfUyXVQyBPGfntoL-xexf4Cldt_EP'
            b'zHis2W4U","s":"0","d":"E1x1JOub6oEQkxAxTNFu1Pma6y-lrbprNsaILHJHo'
            b'PmY"}]}-AABAAROVSK0qK2gqlr_OUsnHNW_ksCyLVmRaysRne2dI5dweECGIy3_Z'
            b'uFHyOofiDRt5tRE09PlS0uZdot6byFNr-AA')

        # apply msg to bob's Kevery
        parsing.Parser().parse(ims=bytearray(msg), kvy=bobKvy)
        # 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
        parsing.Parser().parse(ims=bytearray(msg), kvy=delKvy)
        # delKvy.process(ims=bytearray(msg))  # process remote copy of msg
        assert delKvy.kevers[bob].serder.diger.qb64 == bobSrdr.dig

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

        #seal = eventing.SealSource(s="{:x}".format(bobK.sn+1),
        #d=bobSrdr.diger.qb64)

        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)
        counter = coring.Counter(code=coring.CtrDex.SealSourceCouples, count=1)
        msg.extend(counter.qb64b)
        seqner = coring.Seqner(sn=bobK.sn)
        msg.extend(seqner.qb64b)
        msg.extend(bobSrdr.diger.qb64b)

        assert msg == (
            b'{"v":"KERI10JSON000121_","i":"E-9tsnVcfUyXVQyBPGfntoL-xexf4Cldt_'
            b'EPzHis2W4U","s":"0","t":"dip","kt":"1","k":["DuK1x8ydpucu3480Jpd'
            b'1XBfjnCwb3dZ3x5b1CJmuUphA"],"n":"EWWkjZkZDXF74O2bOQ4H5hu4nXDlKg2'
            b'm4CBEBkUxibiU","bt":"0","b":[],"c":[],"a":[],"di":"Eta8KLf1zrE5n'
            b'-HZpgRAnDmxLASZdXEiU9u6aahqR8TI"}-AABAA2_8Guj0Gf2JoNTq7hOs4u6eOO'
            b'WhENALJWDfLxkVcS2uLh753FjtyE80lpeS3to1C9yvENyMnyN4q96ehA4exDA-GA'
            b'B0AAAAAAAAAAAAAAAAAAAAAAQE3fUycq1G-P1K1pL2OhvY6ZU-9otSa3hXiCcrxu'
            b'hjyII')

        # apply Del's delegated inception event message to Del's own Kevery
        parsing.Parser().parse(ims=bytearray(msg), kvy=delKvy)
        # delKvy.process(ims=bytearray(msg))  # process remote copy of msg
        assert delPre in delKvy.kevers
        delK = delKvy.kevers[delPre]
        assert delK.delegated
        assert delK.serder.diger.qb64 == delSrdr.dig
        couple = delKvy.db.getAes(dbing.dgKey(delPre, delSrdr.dig))
        assert couple == seqner.qb64b + bobSrdr.diger.qb64b

        # apply Del's delegated inception event message to bob's Kevery
        parsing.Parser().parse(ims=bytearray(msg), kvy=bobKvy)
        # bobKvy.process(ims=bytearray(msg))  # process local copy of msg
        assert delPre in bobKvy.kevers  # successfully validated
        bobDelK = bobKvy.kevers[delPre]
        assert bobDelK.delegated
        assert bobDelK.serder.diger.qb64 == delSrdr.dig  # key state updated so event was validated
        couple = bobKvy.db.getAes(dbing.dgKey(delPre, delSrdr.dig))
        assert couple == seqner.qb64b + bobSrdr.diger.qb64b

        # 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)

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

        assert delSrdr.dig == 'EPjLBcb4pp-3PGvSi_fTvLvsqUqFoJ0CVCHvIFfu93Xc'

        # Now create delegating interaction event
        seal = eventing.SealEvent(i=bobDelK.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":"Eta8KLf1zrE5n-HZpgRAnDmxLASZdXEiU9'
            b'u6aahqR8TI","s":"2","t":"ixn","p":"E3fUycq1G-P1K1pL2OhvY6ZU-9otS'
            b'a3hXiCcrxuhjyII","a":[{"i":"E-9tsnVcfUyXVQyBPGfntoL-xexf4Cldt_EP'
            b'zHis2W4U","s":"1","d":"EPjLBcb4pp-3PGvSi_fTvLvsqUqFoJ0CVCHvIFfu9'
            b'3Xc"}]}-AABAAclMVE-bkIn-wPiAqfgR384nWmslQHQvmo2o3xQvd_4Bt6bflc4B'
            b'AmfBa03KgrDVqmB7qG2VXQbOHevkzOgRdDA')

        # apply msg to bob's Kevery
        parsing.Parser().parse(ims=bytearray(msg), kvy=bobKvy)
        # 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
        parsing.Parser().parse(ims=bytearray(msg), kvy=delKvy)
        # delKvy.process(ims=bytearray(msg))  # process remote copy of msg
        assert delKvy.kevers[bob].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)
        counter = coring.Counter(code=coring.CtrDex.SealSourceCouples, count=1)
        msg.extend(counter.qb64b)
        seqner = coring.Seqner(sn=bobK.sn)
        msg.extend(seqner.qb64b)
        msg.extend(bobSrdr.diger.qb64b)

        assert msg == (
            b'{"v":"KERI10JSON000122_","i":"E-9tsnVcfUyXVQyBPGfntoL-xexf4Cldt_'
            b'EPzHis2W4U","s":"1","t":"drt","p":"E1x1JOub6oEQkxAxTNFu1Pma6y-lr'
            b'bprNsaILHJHoPmY","kt":"1","k":["DTf6QZWoet154o9wvzeMuNhLQRr8JaAU'
            b'eiC6wjB_4_08"],"n":"E8kyiXDfkE7idwWnAZQjHbUZMz-kd_yIMH0miptIFFPo'
            b'","bt":"0","br":[],"ba":[],"a":[]}-AABAAAVUMNfOl9Fcqx-C3fAYnaxvs'
            b'iJJO3zG6rP0FQ2WVp__hMEaprrQbJL6-Esnny3U5zvMOqbso17rvecTwmVIwDw-G'
            b'AB0AAAAAAAAAAAAAAAAAAAAAAgEbOI0OIIFv2VV5bmeSq1pwCn-6b2k6TdWcCbJH'
            b'E6Ly7o')

        # apply msg to del's Kevery
        parsing.Parser().parse(ims=bytearray(msg), kvy=delKvy)
        # delKvy.process(ims=bytearray(msg))  # process remote copy of msg
        assert bobDelK.delegated
        assert delK.serder.diger.qb64 == delSrdr.dig
        couple = delKvy.db.getAes(dbing.dgKey(delPre, delSrdr.dig))
        assert couple == seqner.qb64b + bobSrdr.diger.qb64b

        # apply Del's delegated inception event message to bob's Kevery
        parsing.Parser().parse(ims=bytearray(msg), kvy=bobKvy)
        # bobKvy.process(ims=bytearray(msg))  # process local copy of msg
        assert bobDelK.delegated
        assert bobDelK.serder.diger.qb64 == delSrdr.dig  # key state updated so event was validated
        couple = delKvy.db.getAes(dbing.dgKey(delPre, delSrdr.dig))
        assert couple == seqner.qb64b + bobSrdr.diger.qb64b

        # test replay
        msgs = bytearray()
        for msg in delKvy.db.clonePreIter(pre=delPre, fn=0):
            msgs.extend(msg)
        assert len(msgs) == 1043
        assert couple in msgs

    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"""
Exemplo n.º 5
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"""