From 5bdaaec7a75b5fcd0ad9d76aaecf98555884f492 Mon Sep 17 00:00:00 2001 From: Philip Feairheller Date: Fri, 8 Mar 2024 09:09:47 -0800 Subject: [PATCH] Includes 2 fixes (#705) - Fix to saving SignifyGroupHabs to enable reloading - Fix to credential export to support exporting all credentials. Signed-off-by: pfeairheller --- scripts/demo/credentials/multisig-issuer.sh | 26 ++--- .../credentials/oobi-new_multisig_issuer.sh | 12 +++ .../credentials/rotate-multisig-issuer.sh | 40 ++++++++ src/keri/app/cli/commands/migrate.py | 94 +++++++++++++++++-- src/keri/app/cli/commands/vc/export.py | 15 ++- src/keri/app/habbing.py | 6 +- src/keri/vdr/credentialing.py | 8 +- 7 files changed, 173 insertions(+), 28 deletions(-) create mode 100755 scripts/demo/credentials/oobi-new_multisig_issuer.sh create mode 100755 scripts/demo/credentials/rotate-multisig-issuer.sh diff --git a/scripts/demo/credentials/multisig-issuer.sh b/scripts/demo/credentials/multisig-issuer.sh index 8e8969884..69b2da044 100755 --- a/scripts/demo/credentials/multisig-issuer.sh +++ b/scripts/demo/credentials/multisig-issuer.sh @@ -108,16 +108,16 @@ kli vc list --name holder --alias holder --poll SAID=$(kli vc list --name holder --alias holder --said --schema EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao) -echo "Revoking ${SAID}..." -TIME=$(date -Iseconds -u) -kli vc revoke --name multisig1 --alias multisig --registry-name vLEI --said "${SAID}" --time "${TIME}" & -pid=$! -PID_LIST=" $pid" - -kli vc revoke --name multisig2 --alias multisig --registry-name vLEI --said "${SAID}" --time "${TIME}" & -pid=$! -PID_LIST+=" $pid" - - -wait $PID_LIST -kli vc list --name holder --alias holder --poll +#echo "Revoking ${SAID}..." +#TIME=$(date -Iseconds -u) +#kli vc revoke --name multisig1 --alias multisig --registry-name vLEI --said "${SAID}" --time "${TIME}" & +#pid=$! +#PID_LIST=" $pid" +# +#kli vc revoke --name multisig2 --alias multisig --registry-name vLEI --said "${SAID}" --time "${TIME}" & +#pid=$! +#PID_LIST+=" $pid" +# +# +#wait $PID_LIST +#kli vc list --name holder --alias holder --poll diff --git a/scripts/demo/credentials/oobi-new_multisig_issuer.sh b/scripts/demo/credentials/oobi-new_multisig_issuer.sh new file mode 100755 index 000000000..a55689ff6 --- /dev/null +++ b/scripts/demo/credentials/oobi-new_multisig_issuer.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +kli oobi resolve --name multisig1 --oobi-alias new-multisig1 --oobi http://127.0.0.1:3902/oobi/EBFg-5SGDCv5YfwpkArWRBdTxNRUXU8uVcDKNzizOQZc --force +kli oobi resolve --name multisig1 --oobi-alias new-multisig2 --oobi http://127.0.0.1:3902/oobi/EBmW2bXbgsP3HITwW3FmITzAb3wVmHlxCusZ46vgGgP5 --force +kli oobi resolve --name multisig1 --oobi-alias new-multisig3 --oobi http://127.0.0.1:3902/oobi/EL4RpdS2Atb2Syu5xLdpz9CcNNYoFUUDlLHxHD09vcgh --force +kli oobi resolve --name multisig1 --oobi-alias new-multisig4 --oobi http://127.0.0.1:3902/oobi/EAiBVuuhCZrgckeHc9KzROVGJpmGbk2-e1B25GaeRrJs --force + +kli oobi resolve --name multisig2 --oobi-alias new-multisig1 --oobi http://127.0.0.1:3902/oobi/EBFg-5SGDCv5YfwpkArWRBdTxNRUXU8uVcDKNzizOQZc --force +kli oobi resolve --name multisig2 --oobi-alias new-multisig2 --oobi http://127.0.0.1:3902/oobi/EBmW2bXbgsP3HITwW3FmITzAb3wVmHlxCusZ46vgGgP5 --force +kli oobi resolve --name multisig2 --oobi-alias new-multisig3 --oobi http://127.0.0.1:3902/oobi/EL4RpdS2Atb2Syu5xLdpz9CcNNYoFUUDlLHxHD09vcgh --force +kli oobi resolve --name multisig2 --oobi-alias new-multisig4 --oobi http://127.0.0.1:3902/oobi/EAiBVuuhCZrgckeHc9KzROVGJpmGbk2-e1B25GaeRrJs --force + diff --git a/scripts/demo/credentials/rotate-multisig-issuer.sh b/scripts/demo/credentials/rotate-multisig-issuer.sh new file mode 100755 index 000000000..33c0b83b9 --- /dev/null +++ b/scripts/demo/credentials/rotate-multisig-issuer.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +kli rotate --name multisig1 --alias multisig1 +kli query --name multisig2 --alias multisig2 --prefix EKYLUMmNPZeEs77Zvclf0bSN5IN-mLfLpx2ySb-HDlk4 +kli rotate --name multisig2 --alias multisig2 +kli query --name multisig1 --alias multisig1 --prefix EJccSRTfXYF6wrUVuenAIHzwcx3hJugeiJsEKmndi5q1 + +# Perform rotation of mulisig AID from local kli AIDs that roll themselves out and the new AIDs in +kli multisig rotate --name multisig1 --alias multisig \ + --smids EKYLUMmNPZeEs77Zvclf0bSN5IN-mLfLpx2ySb-HDlk4:2 \ + --smids EJccSRTfXYF6wrUVuenAIHzwcx3hJugeiJsEKmndi5q1:2 \ + --smids EBFg-5SGDCv5YfwpkArWRBdTxNRUXU8uVcDKNzizOQZc:0 \ + --smids EBmW2bXbgsP3HITwW3FmITzAb3wVmHlxCusZ46vgGgP5:0 \ + --smids EL4RpdS2Atb2Syu5xLdpz9CcNNYoFUUDlLHxHD09vcgh:0 \ + --smids EAiBVuuhCZrgckeHc9KzROVGJpmGbk2-e1B25GaeRrJs:0 \ + --isith '["0", "0", "1/2", "1/2", "1/2", "1/2"]' \ + --rmids EBFg-5SGDCv5YfwpkArWRBdTxNRUXU8uVcDKNzizOQZc:0 \ + --rmids EBmW2bXbgsP3HITwW3FmITzAb3wVmHlxCusZ46vgGgP5:0 \ + --rmids EL4RpdS2Atb2Syu5xLdpz9CcNNYoFUUDlLHxHD09vcgh:0 \ + --rmids EAiBVuuhCZrgckeHc9KzROVGJpmGbk2-e1B25GaeRrJs:0 \ + --nsith '["1/2", "1/2", "1/2", "1/2"]' & +pid=$! +PID_LIST="$pid" +kli multisig rotate --name multisig2 --alias multisig \ + --smids EKYLUMmNPZeEs77Zvclf0bSN5IN-mLfLpx2ySb-HDlk4:2 \ + --smids EJccSRTfXYF6wrUVuenAIHzwcx3hJugeiJsEKmndi5q1:2 \ + --smids EBFg-5SGDCv5YfwpkArWRBdTxNRUXU8uVcDKNzizOQZc:0 \ + --smids EBmW2bXbgsP3HITwW3FmITzAb3wVmHlxCusZ46vgGgP5:0 \ + --smids EL4RpdS2Atb2Syu5xLdpz9CcNNYoFUUDlLHxHD09vcgh:0 \ + --smids EAiBVuuhCZrgckeHc9KzROVGJpmGbk2-e1B25GaeRrJs:0 \ + --isith '["0", "0", "1/2", "1/2", "1/2", "1/2"]' \ + --rmids EBFg-5SGDCv5YfwpkArWRBdTxNRUXU8uVcDKNzizOQZc:0 \ + --rmids EBmW2bXbgsP3HITwW3FmITzAb3wVmHlxCusZ46vgGgP5:0 \ + --rmids EL4RpdS2Atb2Syu5xLdpz9CcNNYoFUUDlLHxHD09vcgh:0 \ + --rmids EAiBVuuhCZrgckeHc9KzROVGJpmGbk2-e1B25GaeRrJs:0 \ + --nsith '["1/2", "1/2", "1/2", "1/2"]' & +pid=$! +PID_LIST+=" $pid" + +wait $PID_LIST diff --git a/src/keri/app/cli/commands/migrate.py b/src/keri/app/cli/commands/migrate.py index 7661a2433..0f4035f78 100644 --- a/src/keri/app/cli/commands/migrate.py +++ b/src/keri/app/cli/commands/migrate.py @@ -9,8 +9,11 @@ from hio import help from hio.base import doing +from keri import kering from keri.app.cli.common import existing -from keri.db import koming +from keri.core import coring, serdering +from keri.db import koming, subing, dbing +from keri.db.basing import KeyStateRecord, StateEERecord from keri.kering import ConfigurationError, Version from keri.vdr import viring @@ -24,9 +27,22 @@ required=False, default="") parser.add_argument('--passcode', '-p', help='22 character encryption passcode for keystore (is not saved)', dest="bran", default=None) # passcode => bran +parser.add_argument('--force', action="store_true", required=False, + help='True means perform migration without prompting the user') def handler(args): + if not args.force: + print() + print("This command will migrate your datastore to the next version of KERIpy and is not reversible.") + print("After this command, you will not be able to access your data store with this version.") + print() + yn = input("Are you sure you want to continue? [y|N]: ") + + if yn not in ("y", "Y"): + print("...exiting") + return [] + kwa = dict(args=args) return [doing.doify(migrate, **kwa)] @@ -42,15 +58,47 @@ def migrate(tymth, tock=0.0, **opts): bran = args.bran try: + with dbing.openLMDB(name=name, base=base, bran=bran, temp=False) as db: + print(db.path) + states = koming.Komer(db=db, + schema=dict, + subkey='stts.') + nstates = koming.Komer(db=db, + schema=KeyStateRecord, + subkey='stts.') + + for keys, sad in states.getItemIter(): + ksr = KeyStateRecord( + vn=Version, # version number as list [major, minor] + i=sad['i'], # qb64 prefix + s=sad['s'], # lowercase hex string no leading zeros + p=sad['p'], + d=sad['d'], + f=sad['f'], # lowercase hex string no leading zeros + dt=sad['dt'], + et=sad['et'], + kt=sad['kt'], + k=sad['k'], + nt=sad['nt'], + n=sad['n'], + bt=sad['bt'], + b=sad['b'], + c=sad['c'], + ee=StateEERecord._fromdict(sad['ee']), # latest est event dict + di=sad['di'] if sad['di'] else None + ) + + nstates.pin(keys=keys, val=ksr) + with existing.existingHby(name=name, base=base, bran=bran) as hby: - rgy = viring.Reger(name=name, base=base, db=hby.db, temp=hby.temp, + rgy = viring.Reger(name=name, base=base, db=hby.db, temp=False, reopen=True) - states = koming.Komer(db=rgy, - schema=dict, - subkey='stts.') + rstates = koming.Komer(db=rgy, + schema=dict, + subkey='stts.') - for _, sad in states.getItemIter(): + for _, sad in rstates.getItemIter(): rsr = viring.RegStateRecord( vn=list(Version), # version number as list [major, minor] i=sad['i'], # qb64 registry SAID @@ -66,6 +114,40 @@ def migrate(tymth, tock=0.0, **opts): # ksr = stateFromKever(kever) rgy.states.pin(sad['i'], val=rsr) + for (said,), _ in rgy.creds.getItemIter(): + snkey = dbing.snKey(said, 0) + dig = rgy.getTel(key=snkey) + + prefixer = coring.Prefixer(qb64=said) + seqner = coring.Seqner(sn=0) + saider = coring.Saider(qb64b=bytes(dig)) + rgy.cancs.pin(keys=said, val=[prefixer, seqner, saider]) + + migrateKeys(hby.db) + except ConfigurationError: print(f"identifier prefix for {name} does not exist, incept must be run first", ) return -1 + + +def migrateKeys(db): + # public keys mapped to the AID and event seq no they appeared in + pubs = subing.CatCesrIoSetSuber(db=db, subkey="pubs.", + klas=(coring.Prefixer, coring.Seqner)) + + # next key digests mapped to the AID and event seq no they appeared in + digs = subing.CatCesrIoSetSuber(db=db, subkey="digs.", + klas=(coring.Prefixer, coring.Seqner)) + + for pre, fn, dig in db.getFelItemAllPreIter(key=b''): + dgkey = dbing.dgKey(pre, dig) # get message + if not (raw := db.getEvt(key=dgkey)): + raise kering.MissingEntryError("Missing event for dig={}.".format(dig)) + serder = serdering.SerderKERI(raw=bytes(raw)) + val = (coring.Prefixer(qb64b=serder.preb), coring.Seqner(sn=serder.sn)) + verfers = serder.verfers or [] + for verfer in verfers: + pubs.add(keys=(verfer.qb64,), val=val) + ndigers = serder.ndigers or [] + for diger in ndigers: + digs.add(keys=(diger.qb64,), val=val) diff --git a/src/keri/app/cli/commands/vc/export.py b/src/keri/app/cli/commands/vc/export.py index b18c93232..f79e2b693 100644 --- a/src/keri/app/cli/commands/vc/export.py +++ b/src/keri/app/cli/commands/vc/export.py @@ -10,6 +10,7 @@ from hio import help from hio.base import doing +from keri.app import signing from keri.app.cli.common import existing from keri.core import serdering from keri.vdr import credentialing @@ -27,7 +28,7 @@ parser.add_argument('--passcode', '-p', help='22 character encryption passcode for keystore (is not saved)', dest="bran", default=None) # passcode => bran -parser.add_argument("--said", "-s", help="SAID of the credential to export.", required=True) +parser.add_argument("--said", "-s", help="SAID of the credential to export.", required=False, default=None) parser.add_argument("--tels", help="export the transaction event logs for the credential and any chained credentials", action="store_true") parser.add_argument("--kels", help="export the key event logs for the issuer's of the credentials", action="store_true") @@ -93,7 +94,12 @@ def exportDo(self, tymth, tock=0.0): self.tock = tock _ = (yield self.tock) - self.outputCred(said=self.said) + if self.said is None: + for (said,), _ in self.rgy.reger.creds.getItemIter(): + self.outputCred(said=said) + + else: + self.outputCred(said=self.said) def outputCred(self, said): creder, *_ = self.rgy.reger.cloneCred(said=said) @@ -122,12 +128,13 @@ def outputCred(self, said): for said in saids: self.outputCred(said) + (prefixer, seqner, saider) = self.rgy.reger.cancs.get(keys=(creder.said,)) if self.files: f = open(f"{creder.said}-acdc.cesr", 'w') - f.write(creder.raw.decode("utf-8")) + f.write(signing.serialize(creder, prefixer, seqner, saider)) f.close() else: - sys.stdout.write(creder.raw.decode("utf-8")) + sys.stdout.write(signing.serialize(creder, prefixer, seqner, saider).decode("utf-8")) sys.stdout.flush() def outputTEL(self, regk): diff --git a/src/keri/app/habbing.py b/src/keri/app/habbing.py index 98677fd99..965f64f26 100644 --- a/src/keri/app/habbing.py +++ b/src/keri/app/habbing.py @@ -339,7 +339,7 @@ def loadHabs(self): elif habord.sid and habord.mid: hab = SignifyGroupHab(ks=self.ks, db=self.db, cf=self.cf, mgr=self.mgr, rtr=self.rtr, rvy=self.rvy, kvy=self.kvy, psr=self.psr, - name=name, pre=habord.sid) + name=name, pre=pre) groups.append(habord) else: hab = Hab(ks=self.ks, db=self.db, cf=self.cf, mgr=self.mgr, @@ -656,7 +656,7 @@ def joinSignifyGroupHab(self, pre, name, mhab, smids, rmids=None, ns=None): hab.pre = pre habord = basing.HabitatRecord(hid=hab.pre, - mid=mhab.pre, + sid=mhab.pre, smids=smids, rmids=rmids) @@ -1101,7 +1101,7 @@ def make(self, DnD, code, data, delpre, estOnly, isith, verfers, nsith, digers, def save(self, habord): if self.ns is None: - self.db.habs.put(keys=self.name, + self.db.habs.pin(keys=self.name, val=habord) else: self.db.nmsp.put(keys=(self.ns, self.name), diff --git a/src/keri/vdr/credentialing.py b/src/keri/vdr/credentialing.py index b9b8fc223..8a85c8e54 100644 --- a/src/keri/vdr/credentialing.py +++ b/src/keri/vdr/credentialing.py @@ -14,7 +14,7 @@ from ..app.habbing import GroupHab from ..core import parsing, coring, scheming, serdering from ..core.coring import Seqner, MtrDex -from ..core.eventing import SealEvent, TraitDex +from ..core.eventing import TraitDex from ..db import dbing from ..db.dbing import snKey, dgKey from ..vc import proving @@ -405,7 +405,11 @@ def make(self, *, regser): self.reger.regs.put(keys=self.name, val=viring.RegistryRecord(registryKey=self.regk, prefix=pre)) - self.processEvent(serder=regser) + try: + self.processEvent(serder=regser) + except kering.LikelyDuplicitousError: + pass + self.inited = True def rotate(self, serder):