diff --git a/src/keri/app/cli/commands/vc/revoke.py b/src/keri/app/cli/commands/vc/revoke.py index 76dd72e20..05e47c78b 100644 --- a/src/keri/app/cli/commands/vc/revoke.py +++ b/src/keri/app/cli/commands/vc/revoke.py @@ -104,7 +104,7 @@ def revokeDo(self, tymth, tock=0.0): hab = registry.hab state = registry.tever.vcState(vci=creder.said) - if state is None or state.ked["et"] not in (coring.Ilks.iss, coring.Ilks.rev): + if state is None or state.et not in (coring.Ilks.iss, coring.Ilks.rev): raise kering.ValidationError(f"credential {creder.said} not is correct state for revocation") rserder = registry.revoke(said=creder.said, **kwargs) diff --git a/src/keri/vdr/eventing.py b/src/keri/vdr/eventing.py index 9a760b93d..f90f55d0d 100644 --- a/src/keri/vdr/eventing.py +++ b/src/keri/vdr/eventing.py @@ -8,6 +8,7 @@ import json import logging +from dataclasses import asdict from math import ceil from ordered_set import OrderedSet as oset @@ -512,7 +513,7 @@ def state(pre, ".".format(ba)) rsr = viring.RegStateRecord( - vn=list(version), # version number as list [major, minor] + vn=list(version), # version number as list [major, minor] i=ri, # qb64 registry SAID s="{:x}".format(sn), # lowercase hex string no leading zeros d=said, @@ -570,8 +571,6 @@ def vcstate(vcpre, } """ - vs = versify(version=version, kind=kind, size=0) - if sn < 0: raise ValueError("Negative sn = {} in key state.".format(sn)) @@ -584,18 +583,18 @@ def vcstate(vcpre, if ra is None: ra = dict() - vsd = dict(v=vs, # version string - i=vcpre, # qb64 prefix - s="{:x}".format(sn), # lowercase hex string no leading zeros - d=said, - ri=ri, - ra=ra, - a=a, - dt=dts, - et=eilk, - ) + vsr = viring.VcStateRecord(vn=list(version), # version string + i=vcpre, # qb64 prefix + s="{:x}".format(sn), # lowercase hex string no leading zeros + d=said, + ri=ri, + ra=ra, + a=a, + dt=dts, + et=eilk, + ) - return coring.Serder(ked=vsd) # return serialized vsd + return vsr # return vc state record data class def query(regk, @@ -1685,11 +1684,11 @@ def processQuery(self, serder, source=None, sigers=None, cigars=None): if ri in self.tevers: tever = self.tevers[ri] tsn = tever.state() - self.cues.push(dict(kin="reply", route="/tsn/registry", data=tsn.ked, dest=source)) + self.cues.push(dict(kin="reply", route="/tsn/registry", data=asdict(tsn), dest=source)) if vcpre := qry["i"]: tsn = tever.vcState(vcpre=vcpre) - self.cues.push(dict(kin="reply", route="/tsn/credential", data=tsn.ked, dest=source)) + self.cues.push(dict(kin="reply", route="/tsn/credential", data=asdict(tsn), dest=source)) else: raise ValidationError("invalid query message {} for evt = {}".format(ilk, ked)) @@ -1769,19 +1768,12 @@ def processReplyRegistryTxnState(self, *, serder, saider, route, cigars=None, ts data = serder.ked["a"] dater = coring.Dater(dts=serder.ked["dt"]) - tserder = serdering.SerderKERI(sad=data) - - for k in TSN_LABELS: - if k not in tserder.ked: - raise ValidationError("Missing element = {} from {} msg." - " tsn = {}.".format(k, Ilks.tsn, - serder.pretty())) + rsr = viring.RegStateRecord(**data) # fetch from serder to process - ked = tserder.ked - regk = tserder.pre - pre = ked["ii"] - sn = tserder.sn + regk = rsr.i + pre = rsr.ii + sn = int(rsr.s, 16) if pre not in self.kevers: if self.reger.txnsb.escrowStateNotice(typ="registry-mae", pre=regk, aid=aid, serder=serder, saider=saider, @@ -1791,12 +1783,12 @@ def processReplyRegistryTxnState(self, *, serder, saider, route, cigars=None, ts raise kering.MissingAnchorError("Failure verify event = {} ".format(serder.ked)) # Load backers from either tsn or Kever of issuer - cnfg = ked["c"] + cnfg = rsr.c if TraitDex.NoBackers in cnfg: kevers = self.kevers[pre] baks = kevers.wits else: - baks = ked["b"] + baks = rsr.b wats = set() for _, habr in self.db.habs.getItemIter(): @@ -1809,13 +1801,13 @@ def processReplyRegistryTxnState(self, *, serder, saider, route, cigars=None, ts aid not in baks and \ aid not in wats: raise kering.UntrustedKeyStateSource("transaction state notice for {} from untrusted source {} " - .format(tserder.pre, aid)) + .format(rsr.i, aid)) if regk in self.tevers: tever = self.tevers[regk] - if tserder.sn < tever.sn: + if int(rsr.s, 16) < tever.sn: raise ValidationError("Skipped stale transaction state at sn {} for {}." - "".format(tserder.sn, tserder.pre)) + "".format(rsr.s, rsr.i)) keys = (regk, aid,) osaider = self.reger.txnsb.current(keys=keys) # get old said if any @@ -1835,9 +1827,9 @@ def processReplyRegistryTxnState(self, *, serder, saider, route, cigars=None, ts dater=dater, cigars=cigars, tsgs=tsgs): self.cues.append(dict(kin="telquery", q=dict(ri=regk))) - raise kering.OutOfOrderTxnStateError("Out of order txn state={}.".format(ked)) + raise kering.OutOfOrderTxnStateError("Out of order txn state={}.".format(rsr)) - tsaider = coring.Saider(qb64=ked["d"]) + tsaider = coring.Saider(qb64=rsr.d) ldig = bytes(ldig) # retrieve last event itself of signer given sdig sraw = self.reger.getTvt(key=dgKey(pre=regk, dig=ldig)) @@ -1846,10 +1838,10 @@ def processReplyRegistryTxnState(self, *, serder, saider, route, cigars=None, ts if sserder.said != tsaider.qb64: # mismatch events problem with replay raise ValidationError("Mismatch keystate at sn = {} with db." - "".format(ked["s"])) + "".format(rsr.s)) - self.reger.txnsb.updateReply(aid=aid, serder=tserder, saider=tsaider, dater=dater) - self.cues.append(dict(kin="txnStateSaved", serder=tserder)) + self.reger.txnsb.updateReply(aid=aid, serder=serder, saider=tsaider, dater=dater) + self.cues.append(dict(kin="txnStateSaved", record=rsr)) def processReplyCredentialTxnState(self, *, serder, saider, route, cigars=None, tsgs=None, **kwargs): """ Process one reply message for key state = /tsn/registry @@ -1907,19 +1899,13 @@ def processReplyCredentialTxnState(self, *, serder, saider, route, cigars=None, data = serder.ked["a"] dater = coring.Dater(dts=serder.ked["dt"]) - tserder = coring.Serder(ked=data) - for k in CRED_TSN_LABELS: - if k not in tserder.ked: - raise ValidationError("Missing element = {} from {} msg." - " tsn = {}.".format(k, Ilks.tsn, - serder.pretty())) + vsr = viring.VcStateRecord(**data) # fetch from serder to process - ked = tserder.ked - regk = tserder.ked["ri"] - vci = tserder.pre - sn = tserder.sn - ra = tserder.ked["ra"] + regk = vsr.ri + vci = vsr.i + sn = int(vsr.s, 16) + ra = vsr.ra if 's' in ra: regsn = ra["s"] @@ -1961,7 +1947,7 @@ def processReplyCredentialTxnState(self, *, serder, saider, route, cigars=None, aid not in baks and \ aid not in wats: raise kering.UntrustedKeyStateSource("transaction state notice for {} from untrusted source {} " - .format(tserder.pre, aid)) + .format(vsr.i, aid)) keys = (vci, aid,) osaider = self.reger.txnsb.current(keys=keys) # get old said if any @@ -1981,9 +1967,9 @@ def processReplyCredentialTxnState(self, *, serder, saider, route, cigars=None, saider=saider, dater=dater, cigars=cigars, tsgs=tsgs): self.cues.append(dict(kin="telquery", q=dict(ri=regk, i=vci))) - raise kering.OutOfOrderTxnStateError("Out of order txn state={}.".format(ked)) + raise kering.OutOfOrderTxnStateError("Out of order txn state={}.".format(vsr)) - tsaider = coring.Saider(qb64=ked["d"]) + tsaider = coring.Saider(qb64=vsr.d) ldig = bytes(ldig) # retrieve last event itself of signer given sdig sraw = self.reger.getTvt(key=dgKey(pre=vci, dig=ldig)) @@ -1992,14 +1978,14 @@ def processReplyCredentialTxnState(self, *, serder, saider, route, cigars=None, if sn < sserder.sn: raise ValidationError("Stale txn state at sn = {} with db." - "".format(ked["s"])) + "".format(vsr.s)) if sserder.said != tsaider.qb64: # mismatch events problem with replay raise ValidationError("Mismatch txn state at sn = {} with db." - "".format(ked["s"])) + "".format(vsr.s)) - self.reger.txnsb.updateReply(aid=aid, serder=tserder, saider=tsaider, dater=dater) - self.cues.append(dict(kin="txnStateSaved", serder=tserder)) + self.reger.txnsb.updateReply(aid=aid, serder=serder, saider=tsaider, dater=dater) + self.cues.append(dict(kin="txnStateSaved", record=vsr)) @staticmethod def registryKey(serder): diff --git a/src/keri/vdr/verifying.py b/src/keri/vdr/verifying.py index ff7c5f4ef..5d8a61a5c 100644 --- a/src/keri/vdr/verifying.py +++ b/src/keri/vdr/verifying.py @@ -116,12 +116,12 @@ def processCredential(self, creder, prefixer, seqner, saider): raise kering.MissingRegistryError("credential identifier {} not in Tevers".format(vcid)) dtnow = helping.nowUTC() - dte = helping.fromIso8601(state.ked["dt"]) + dte = helping.fromIso8601(state.dt) if (dtnow - dte) > datetime.timedelta(seconds=self.CredentialExpiry): if self.escrowMRE(creder, prefixer, seqner, saider): self.cues.append(dict(kin="telquery", q=dict(ri=regk, i=vcid))) raise kering.MissingRegistryError("credential identifier {} is out of date".format(vcid)) - elif state.ked["et"] in (coring.Ilks.rev, coring.Ilks.brv): # no escrow, credential has been revoked + elif state.et in (coring.Ilks.rev, coring.Ilks.brv): # no escrow, credential has been revoked logger.error("credential {} in registrying is not in issued state".format(vcid, regk)) # Log this and continue instead of the previous exception so we save a revoked credential. # raise kering.InvalidCredentialStateError("...")) @@ -164,13 +164,13 @@ def processCredential(self, creder, prefixer, seqner, saider): .format(creder.said, label, nodeSaid)) dtnow = helping.nowUTC() - dte = helping.fromIso8601(state.ked["dt"]) + dte = helping.fromIso8601(state.dt) if (dtnow - dte) > datetime.timedelta(seconds=self.CredentialExpiry): self.escrowMCE(creder, prefixer, seqner, saider) self.cues.append(dict(kin="query", q=dict(r="tels", pre=nodeSaid))) raise kering.MissingChainError("Failure to verify credential {} chain {}({})" .format(creder.said, label, nodeSaid)) - elif state.ked["et"] in (coring.Ilks.rev, coring.Ilks.brv): + elif state.et in (coring.Ilks.rev, coring.Ilks.brv): raise kering.RevokedChainError("Failure to verify credential {} chain {}({})" .format(creder.said, label, nodeSaid)) else: # VcStatus == VcStates.Issued diff --git a/src/keri/vdr/viring.py b/src/keri/vdr/viring.py index 78e6fb1e4..f14f69de3 100644 --- a/src/keri/vdr/viring.py +++ b/src/keri/vdr/viring.py @@ -8,7 +8,7 @@ A special purpose Verifiable Data Registry (VDR) """ -from dataclasses import dataclass, field +from dataclasses import dataclass, field, asdict from ordered_set import OrderedSet as oset from ..db import koming, subing, escrowing @@ -135,18 +135,28 @@ class RegStateRecord(basing.RawRecord): # reger.state """ vn: list[int] = field(default_factory=list) # version number [major, minor] round trip serializable - i: str ='' # identifier prefix qb64 - s: str ='0' # sequence number of latest event in KEL as hex str - d: str ='' # latest event digest qb64 + i: str = '' # identifier prefix qb64 + s: str = '0' # sequence number of latest event in KEL as hex str + d: str = '' # latest event digest qb64 ii: str = '' # issuer identifier of registry aid qb64 dt: str = '' # datetime of update of state record et: str = '' # TEL evt packet type (ilk) bt: str = '0' # backer threshold hex num str b: list = field(default_factory=list) # backer AID list qb64 - c: list[str] = field(default_factory=list) # config trait list - + c: list[str] = field(default_factory=list) # config trait list +@dataclass +class VcStateRecord(basing.RawRecord): + vn: list[str] = field(default_factory=list) # version number [major, minor] round trip serializable + i: str = '' # identifier prefix qb64 + s: str = '0' # sequence number of latest event in KEL as hex str + d: str = '' # latest event digest qb64 + ri: str = '' # registry identifier of registry aid qb64 + ra: dict = field(default_factory=dict) # registry anchor for registry with backers + a: dict = field(default_factory=dict) # seal for anchor in KEL + dt: str = '' # datetime of update of state record + et: str = '' # TEL evt packet type (ilk) def openReger(name="test", **kwa): @@ -409,7 +419,7 @@ def cloneCreds(self, saids, db): pre=creder.issuer, schema=schemer.sed, chains=chains, - status=status.ked, + status=asdict(status), anchor=dict( pre=prefixer.qb64, sn=seqner.sn, diff --git a/tests/vdr/test_eventing.py b/tests/vdr/test_eventing.py index 8fdbac0f1..df41c766c 100644 --- a/tests/vdr/test_eventing.py +++ b/tests/vdr/test_eventing.py @@ -731,8 +731,8 @@ def test_tevery(): tvy.processEvent(serder=iss, seqner=seqner, saider=diger) status = tev.vcState(vcdig.decode("utf-8")) - assert status.ked['et'] == Ilks.iss - assert status.sn == 0 + assert status.et == Ilks.iss + assert status.s == '0' # revoke the vc rev = eventing.revoke(vcdig=vcdig.decode("utf-8"), regk=regk, dig=iss.said) @@ -746,8 +746,8 @@ def test_tevery(): tvy.processEvent(serder=rev, seqner=seqner, saider=diger) status = tev.vcState(vcdig.decode("utf-8")) - assert status.ked["et"] == Ilks.rev - assert status.sn == 1 + assert status.et == Ilks.rev + assert status.s == '1' def test_tevery_process_escrow(mockCoringRandomNonce): diff --git a/tests/vdr/test_issuing.py b/tests/vdr/test_issuing.py index 09040ab19..54270db65 100644 --- a/tests/vdr/test_issuing.py +++ b/tests/vdr/test_issuing.py @@ -134,7 +134,7 @@ def test_issuer(mockHelpingNowUTC): saider=coring.Saider(qb64=hab.kever.serder.said)) regery.processEscrows() state = issuer.tever.vcState(vci=creder.said) - assert state.ked["et"] == coring.Ilks.iss + assert state.et == coring.Ilks.iss rev = issuer.revoke(said=creder.said) rseal = SealEvent(rev.pre, "1", rev.said)._asdict() @@ -146,7 +146,7 @@ def test_issuer(mockHelpingNowUTC): saider=coring.Saider(qb64=hab.kever.serder.said)) regery.processEscrows() state = issuer.tever.vcState(vci=creder.said) - assert state.ked["et"] == coring.Ilks.rev + assert state.et == coring.Ilks.rev with basing.openDB(name="bob") as db, keeping.openKS(name="bob") as kpr: hby, hab = buildHab(db, kpr) @@ -176,7 +176,7 @@ def test_issuer(mockHelpingNowUTC): saider=coring.Saider(qb64=hab.kever.serder.said)) regery.processEscrows() state = issuer.tever.vcState(vci=creder.said) - assert state.ked["et"] == coring.Ilks.bis + assert state.et == coring.Ilks.bis rot = issuer.rotate(adds=["BCDfgIp33muOuCI0L8db_TldMJXv892UmW8yfpUuKzkw", "BBC_BBLMeVwKFbfYSWU7aATS9itLSrGtIFQzCkfoKnjk"]) @@ -202,7 +202,7 @@ def test_issuer(mockHelpingNowUTC): saider=coring.Saider(qb64=hab.kever.serder.said)) regery.processEscrows() state = issuer.tever.vcState(vci=creder.said) - assert state.ked["et"] == coring.Ilks.brv + assert state.et == coring.Ilks.brv with basing.openDB(name="bob") as db, keeping.openKS(name="bob") as kpr: hby, hab = buildHab(db, kpr) @@ -231,7 +231,7 @@ def test_issuer(mockHelpingNowUTC): saider=coring.Saider(qb64=hab.kever.serder.said)) regery.processEscrows() state = issuer.tever.vcState(vci=creder.said) - assert state.ked["et"] == coring.Ilks.iss + assert state.et == coring.Ilks.iss rev = issuer.revoke(said=creder.said) rseal = SealEvent(rev.pre, "1", rev.said)._asdict() @@ -243,7 +243,7 @@ def test_issuer(mockHelpingNowUTC): saider=coring.Saider(qb64=hab.kever.serder.said)) regery.processEscrows() state = issuer.tever.vcState(vci=creder.said) - assert state.ked["et"] == coring.Ilks.rev + assert state.et == coring.Ilks.rev with pytest.raises(ValueError): issuer.rotate(adds=["BAFbQvUaS4EirvZVPUav7R_KDHB8AKmSfXNpWnZU_YEU"]) @@ -290,7 +290,7 @@ def test_issuer(mockHelpingNowUTC): saider=coring.Saider(qb64=hab.kever.serder.said)) regery.processEscrows() state = issuer.tever.vcState(vci=creder.said) - assert state.ked["et"] == coring.Ilks.bis + assert state.et == coring.Ilks.bis # rotate to 2 backers rot = issuer.rotate(toad=2, cuts=["BAFbQvUaS4EirvZVPUav7R_KDHB8AKmSfXNpWnZU_YEU"]) @@ -316,7 +316,7 @@ def test_issuer(mockHelpingNowUTC): saider=coring.Saider(qb64=hab.kever.serder.said)) regery.processEscrows() state = issuer.tever.vcState(vci=creder.said) - assert state.ked["et"] == coring.Ilks.brv + assert state.et == coring.Ilks.brv """ End Test """ diff --git a/tests/vdr/test_txn_state.py b/tests/vdr/test_txn_state.py index 83a721bdd..e3c729f40 100644 --- a/tests/vdr/test_txn_state.py +++ b/tests/vdr/test_txn_state.py @@ -69,7 +69,7 @@ def test_tsn_message_out_of_order(mockHelpingNowUTC, mockCoringRandomNonce): assert cue['q']['ri'] == issuer.regk saider = bamReger.txnsb.escrowdb.get(keys=("registry-ooo", issuer.regk, bobHab.pre)) - assert saider[0].qb64b == b'EEPziN_7emWTt94juY7X3Nlo44dTAaoCz7PGorkZAWVo' + assert saider[0].qb64b == b'ELprJNCkha3b3t7YKOPzfv-prTZvgJFM_xTnaaJop-3A' tmsgs = bytearray() cloner = regery.reger.clonePreIter(pre=issuer.regk, fn=0) # create iterator at 0 @@ -128,7 +128,7 @@ def test_tsn_message_missing_anchor(mockHelpingNowUTC, mockCoringRandomNonce): 's': '0', 'vn': [1, 0]} - rpy = bobHab.reply(route="/tsn/registry/" + bobHab.pre, data=tsn.ked) + rpy = bobHab.reply(route="/tsn/registry/" + bobHab.pre, data=asdict(tsn)) bamReger = viring.Reger(name="bam", temp=True) bamTvy = eventing.Tevery(reger=bamReger, db=bamHby.db, lax=False, local=False, rvy=bamRvy) @@ -136,7 +136,7 @@ def test_tsn_message_missing_anchor(mockHelpingNowUTC, mockCoringRandomNonce): parsing.Parser().parse(ims=bytearray(rpy), tvy=bamTvy, rvy=bamRvy) saider = bamReger.txnsb.escrowdb.get(keys=("registry-mae", issuer.regk, bobHab.pre)) - said = b'EEPziN_7emWTt94juY7X3Nlo44dTAaoCz7PGorkZAWVo' + said = b'ELprJNCkha3b3t7YKOPzfv-prTZvgJFM_xTnaaJop-3A' assert saider[0].qb64b == said assert len(bamTvy.cues) == 1 cue = bamTvy.cues.popleft() @@ -259,7 +259,7 @@ def test_tsn_from_witness(mockHelpingNowUTC, mockCoringRandomNonce): parsing.Parser().parse(ims=bytearray(rpy), tvy=bamTvy, rvy=bamRvy) saider = bamReger.txnsb.escrowdb.get(keys=("registry-mae", issuer.regk, wesHab.pre)) - said = b'EMpMvmRARP3rm_JmO57iZ6zhEELmAuVVELo660CMapg5' + said = b'EMoqBJpoPJCkCejSUZ8IShTeGd_WQkF0zOQc2l0HQusn' assert saider[0].qb64b == said assert len(bamTvy.cues) == 1 cue = bamTvy.cues.popleft() @@ -460,13 +460,17 @@ def test_credential_tsn_message(mockHelpingNowUTC, mockCoringRandomNonce, mockHe 'c': ['NB']} ctsn = tever.vcState(vci=creder.said) - assert ctsn.raw == (b'{"v":"KERI10JSON000135_","i":"EEqcwL-ew_OaQphSQvy8bRGtnKlL_g_SkXjsAGWgtFGl",' - b'"s":"0","d":"EIxhyBA8h6BMmtWEJzqNkoAquIkMucpXbdY3kQX25GQu","ri":"ECbNKwkTjZq' - b'sfwNLxTnraPImegy1YeQ2-pCrTBQmu3i6","ra":{},"a":{"s":2,"d":"EGJIFzWexy6LQbW4-' - b'IQqhGLD6wA9yR7pcLzxomjb40Ku"},"dt":"2021-06-27T21:26:21.233257+00:00","et":"' - b'iss"}') - - rpy = bobHab.reply(route="/tsn/credential/" + bobHab.pre, data=ctsn.ked) + assert asdict(ctsn) == {'a': {'d': 'EGJIFzWexy6LQbW4-IQqhGLD6wA9yR7pcLzxomjb40Ku', 's': 2}, + 'd': 'EIxhyBA8h6BMmtWEJzqNkoAquIkMucpXbdY3kQX25GQu', + 'dt': '2021-06-27T21:26:21.233257+00:00', + 'et': 'iss', + 'i': 'EEqcwL-ew_OaQphSQvy8bRGtnKlL_g_SkXjsAGWgtFGl', + 'ra': {}, + 'ri': 'ECbNKwkTjZqsfwNLxTnraPImegy1YeQ2-pCrTBQmu3i6', + 's': '0', + 'vn': [1, 0]} + + rpy = bobHab.reply(route="/tsn/credential/" + bobHab.pre, data=asdict(ctsn)) bamReger = viring.Reger(name="bam", temp=True) bamTvy = eventing.Tevery(reger=bamReger, db=bamHby.db, lax=False, local=False, rvy=bamRvy) @@ -474,7 +478,7 @@ def test_credential_tsn_message(mockHelpingNowUTC, mockCoringRandomNonce, mockHe parsing.Parser().parse(ims=bytearray(rpy), tvy=bamTvy, rvy=bamRvy) saider = bamReger.txnsb.escrowdb.get(keys=("credential-mre", creder.said, bobHab.pre)) - assert saider[0].qb64b == b'EAxn6pBNsNuGXP7Ngrr80t5PbJ_XuzDvY7DQ5SYodpin' + assert saider[0].qb64b == b'EAslzIz1FKVBY1zd_0gF-gclpvHMf1V4arW3puZlPv4K' assert len(bamTvy.cues) == 1 cue = bamTvy.cues.popleft() assert cue["kin"] == "telquery" @@ -503,7 +507,7 @@ def test_credential_tsn_message(mockHelpingNowUTC, mockCoringRandomNonce, mockHe assert cue['q']['ri'] == issuer.regk saider = bamReger.txnsb.escrowdb.get(keys=("credential-ooo", creder.said, bobHab.pre)) - assert saider[0].qb64b == b'EAxn6pBNsNuGXP7Ngrr80t5PbJ_XuzDvY7DQ5SYodpin' + assert saider[0].qb64b == b'EAslzIz1FKVBY1zd_0gF-gclpvHMf1V4arW3puZlPv4K' vci = creder.said tmsgs = bytearray()