Skip to content

Commit

Permalink
converted state(), Kever.state(), and dbdict to use KeyStateRecord. N…
Browse files Browse the repository at this point in the history
…ow need to convert all uses

of those three to expect KeyStateRecord instance
  • Loading branch information
SmithSamuelM committed Jun 13, 2023
1 parent 3b5bd17 commit 8c3b003
Show file tree
Hide file tree
Showing 4 changed files with 277 additions and 159 deletions.
109 changes: 66 additions & 43 deletions src/keri/core/eventing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import json
import logging
from collections import namedtuple
from dataclasses import dataclass, astuple
from dataclasses import dataclass, astuple, asdict
from urllib.parse import urlsplit
from math import ceil
from ordered_set import OrderedSet as oset
Expand All @@ -20,6 +20,7 @@
from .. import help
from .. import kering
from ..db import basing, dbing
from ..db.basing import KeyStateRecord
from ..db.dbing import dgKey, snKey, fnKey, splitKeySN, splitKey

from ..kering import (MissingEntryError,
Expand All @@ -28,7 +29,7 @@
MissingDelegationError, OutOfOrderError,
LikelyDuplicitousError, UnverifiedWitnessReceiptError,
UnverifiedReceiptError, UnverifiedTransferableReceiptError, QueryNotFoundError)
from ..kering import Version
from ..kering import Version, Versionage
from ..kering import (ICP_LABELS, DIP_LABELS, ROT_LABELS, DRT_LABELS, IXN_LABELS,
KSN_LABELS, RPY_LABELS)

Expand Down Expand Up @@ -1144,8 +1145,8 @@ def state(pre,
raise ValueError(f"Intersecting cuts = {cuts} and adds = {adds} in "
f"latest est event.")


ksd = dict(v=vs, # version string
ksr = basing.KeyStateRecord(
v=vs, # version string
vn=list(version), # version number as list [major, minor]
i=pre, # qb64 prefix
s=sner.numh, # lowercase hex string no leading zeros
Expand All @@ -1166,8 +1167,31 @@ def state(pre,
ee=eevt._asdict(), # latest est event dict
di=dpre if dpre is not None else "",
)

return Serder(ked=ksd) # return serialized ksd
return ksr # return KeyStateRecord use asdict(ksr) to get dict version

#ksd = dict(v=vs, # version string
#vn=list(version), # version number as list [major, minor]
#i=pre, # qb64 prefix
#s=sner.numh, # lowercase hex string no leading zeros
#p=pig,
#d=dig,
#f=fner.numh, # lowercase hex string no leading zeros
#dt=stamp,
#et=eilk,
#kt=(tholder.num if intive and tholder.num is not None and
#tholder.num <= MaxIntThold else tholder.sith),
#k=keys, # list of qb64
#nt=(ntholder.num if intive and ntholder.num is not None and
#ntholder.num <= MaxIntThold else ntholder.sith),
#n=ndigs,
#bt=toader.num if intive and toader.num <= MaxIntThold else toader.numh,
#b=wits, # list of qb64 may be empty
#c=cnfg if cnfg is not None else [],
#ee=eevt._asdict(), # latest est event dict
#di=dpre if dpre is not None else "",
#)

#return Serder(ked=ksd) # return serialized ksd


def query(route="",
Expand Down Expand Up @@ -1607,7 +1631,7 @@ def __init__(self, *, state=None, serder=None, sigers=None, wigers=None,
Verify incepting serder against sigers raises ValidationError if not
Parameters:
state (Serder | None): instance of key state notice 'ksn' message body
state (KeyStateRecord | None): instance for key state notice
serder (Serder | None): instance of inception event
sigers (list | None): of Siger instances of indexed controller signatures
of event. Index is offset into keys list from latest est event
Expand Down Expand Up @@ -1706,8 +1730,10 @@ def __init__(self, *, state=None, serder=None, sigers=None, wigers=None,
self.fner = Number(num=fn)
self.dater = Dater(dts=dts)
self.db.states.pin(keys=self.prefixer.qb64,
val=helping.datify(basing.KeyStateRecord,
self.state().ked))
val=self.state())
#self.db.states.pin(keys=self.prefixer.qb64,
#val=helping.datify(basing.KeyStateRecord,
#self.state().ked))


@property
Expand Down Expand Up @@ -1758,43 +1784,43 @@ def transferable(self):

def reload(self, state):
"""
Reload Kever attributes (aka its state) from state serder
Reload Kever attributes (aka its state) from state (KeyStateRecord)
Parameters:
state (Serder): instance of key state notice 'ksn' message body
state (KeyStateRecord | None): instance for key state notice
"""
for k in KSN_LABELS:
if k not in state.ked:
raise ValidationError(f"Missing element = {k} from state."
f" = {state}.")

self.version = state.version
self.prefixer = Prefixer(qb64=state.pre)
self.sner = state.sner # sequence number Number instance hex str
self.fner = state.fner # first seen ordinal Number hex str
self.dater = Dater(dts=state.ked["dt"])
self.ilk = state.ked["et"]
self.tholder = Tholder(sith=state.ked["kt"])
self.ntholder = Tholder(sith=state.ked["nt"])
self.verfers = [Verfer(qb64=key) for key in state.ked["k"]]
self.digers = [Diger(qb64=dig) for dig in state.ked["n"]]
self.toader = Number(num=state.ked["bt"]) # auto converts from hex num
self.wits = state.ked["b"]
self.cuts = state.ked["ee"]["br"]
self.adds = state.ked["ee"]["ba"]
#for k in KSN_LABELS:
#if k not in state.ked:
#raise ValidationError(f"Missing element = {k} from state."
#f" = {state}.")

self.version = Versionage._make(state.vn)
self.prefixer = Prefixer(qb64=state.i)
self.sner = Number(numh=state.s) # sequence number Number instance hex str
self.fner = Number(numh=state.f) # first seen ordinal Number hex str
self.dater = Dater(dts=state.dt)
self.ilk = state.et
self.tholder = Tholder(sith=state.kt)
self.ntholder = Tholder(sith=state.nt)
self.verfers = [Verfer(qb64=key) for key in state.k]
self.digers = [Diger(qb64=dig) for dig in state.n]
self.toader = Number(numh=state.bt) # auto converts from hex num
self.wits = state.b
self.cuts = state.ee["br"]
self.adds = state.ee["ba"]
self.estOnly = False
self.doNotDelegate = True if "DND" in state.ked["c"] else False
self.estOnly = True if "EO" in state.ked["c"] else False
self.lastEst = LastEstLoc(s=int(state.ked['ee']['s'], 16),
d=state.ked['ee']['d'])
self.delegator = state.ked['di'] if state.ked['di'] else None
self.doNotDelegate = True if "DND" in state.c else False
self.estOnly = True if "EO" in state.c else False
self.lastEst = LastEstLoc(s=int(state.ee['s'], 16),
d=state.ee['d'])
self.delegator = state.di if state.di else None
self.delegated = True if self.delegator else False

if (raw := self.db.getEvt(key=dgKey(pre=self.prefixer.qb64,
dig=state.ked['d']))) is None:
raise MissingEntryError("Corresponding event for state={} not found."
"".format(state.pretty()))
dig=state.d))) is None:
raise MissingEntryError(f"Corresponding event not found for state="
f"{state}.")
self.serder = Serder(raw=bytes(raw))
# May want to do additional checks here

Expand Down Expand Up @@ -2586,12 +2612,10 @@ def escrowPWEvent(self, serder, wigers, sigers=None, seqner=None, saider=None):
return self.db.addPwe(snKey(serder.preb, serder.sn), serder.saidb)


def state(self, kind=Serials.json):
def state(self):
"""
Returns Serder instance of current key state notification message
Returns KeyStateRecord instance of current key state
Parameters:
kind is serialization kind for message json, cbor, mgpk
"""
eevt = StateEstEvent(s="{:x}".format(self.lastEst.s),
d=self.lastEst.d,
Expand Down Expand Up @@ -2620,7 +2644,6 @@ def state(self, kind=Serials.json):
wits=self.wits,
cnfg=cnfg,
dpre=self.delegator,
kind=kind
)
)

Expand Down
50 changes: 45 additions & 5 deletions src/keri/db/basing.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@
import shutil
from contextlib import contextmanager
from dataclasses import dataclass, asdict, field
import json


import cbor2 as cbor
import msgpack
import lmdb
from ordered_set import OrderedSet as oset

Expand All @@ -35,6 +39,7 @@
from ..core import coring, eventing, parsing

from .. import help
from ..help import helping


logger = help.ogler.getLogger()
Expand All @@ -58,10 +63,10 @@ def __getitem__(self, k):
except KeyError as ex:
if not self.db:
raise ex # reraise KeyError
if (ked := self.db.states.getDict(keys=k)) is None:
if (ksr := self.db.states.get(keys=k)) is None:
raise ex # reraise KeyError
try:
kever = eventing.Kever(state=coring.Serder(ked=ked), db=self.db)
kever = eventing.Kever(state=ksr, db=self.db)
except kering.MissingEntryError: # no kel event for keystate
raise ex # reraise KeyError
self.__setitem__(k, kever)
Expand All @@ -83,8 +88,44 @@ def get(self, k, default=None):
else:
return self.__getitem__(k)


@dataclass
class RawRecord:
"""RawRecord is base class for dataclasses that provides private utility
methods for representing the dataclass as some other format like dict,
json bytes, cbor bytes, mgpk bytes as a raw format. Typically uses case
is to transform dataclass into dict or serialization of its transformation
into dict so that it can be included in messages or stored in a database.
"""
def __iter__(self):
return iter(asdict(self))


def _asdict(self):
"""Returns dict version of record"""
return helping.dictify(self)


def _asjson(self):
"""Returns json bytes version of record"""
return json.dumps(self._asdict(),
separators=(",", ":"),
ensure_ascii=False).encode("utf-8")


def _ascbor(self):
"""Returns cbor bytes version of record"""
return cbor.dumps(self._asdict())


def _asmgpk(self):
"""Returns mgpk bytes version of record"""
return msgpack.dumps(self._asdict())



@dataclass
class KeyStateRecord: # baser.state
class KeyStateRecord(RawRecord): # baser.state
"""
Key State information keyed by Identifier Prefix of associated KEL.
For local AIDs that correspond to Habs this is the Hab AID.
Expand Down Expand Up @@ -123,8 +164,7 @@ class KeyStateRecord: # baser.state
# ba = backer (witness) add list (adds) from latest est event
di: str = '' # delegator aid qb64 if any otherwise empty '' str

def __iter__(self):
return iter(asdict(self))




Expand Down
Loading

0 comments on commit 8c3b003

Please sign in to comment.