From cd25246c43782d1d778bd6955d1271433e5cb476 Mon Sep 17 00:00:00 2001 From: Philip Feairheller Date: Fri, 21 Jul 2023 08:02:26 -0700 Subject: [PATCH] Multisig notice command for resending notifications of a rotation to other pariticpants. (#543) --- src/keri/app/cli/commands/multisig/notice.py | 133 +++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 src/keri/app/cli/commands/multisig/notice.py diff --git a/src/keri/app/cli/commands/multisig/notice.py b/src/keri/app/cli/commands/multisig/notice.py new file mode 100644 index 000000000..fe885478e --- /dev/null +++ b/src/keri/app/cli/commands/multisig/notice.py @@ -0,0 +1,133 @@ +# -*- encoding: utf-8 -*- +""" +keri.kli.commands module + +""" +import argparse +from ordered_set import OrderedSet as oset + +from hio import help +from hio.base import doing + +from keri.app import habbing, forwarding, grouping +from keri.app.cli.common import existing +from keri.core import coring +from keri.core.coring import Ilks + +logger = help.ogler.getLogger() + +parser = argparse.ArgumentParser(description='Notify other participants of the last event in a group multisig AID') +parser.set_defaults(handler=lambda args: handler(args), + transferable=True) +parser.add_argument('--name', '-n', help='keystore name and file location of KERI keystore', required=True) +parser.add_argument('--base', '-b', help='additional optional prefix to file location of KERI keystore', + required=False, default="") +parser.add_argument('--alias', '-a', help='human readable alias for the new identifier prefix', required=True) +parser.add_argument("--config", "-c", help="directory override for configuration data") + +# Authentication for keystore +parser.add_argument('--passcode', '-p', help='22 character encryption passcode for keystore (is not saved)', + dest="bran", default=None) # passcode => bran +parser.add_argument('--aeid', help='qualified base64 of non-transferable identifier prefix for authentication ' + 'and encryption of secrets in keystore', default=None) + + +def handler(args): + """ + Send the /multisig/rot EXN notification message to other members of a multisig group about the last event in the KEL + Args: + args(Namespace): arguments object from command line + """ + + name = args.name + base = args.base + bran = args.bran + alias = args.alias + + noticeDoer = NoticeDoer(name=name, base=base, alias=alias, bran=bran) + + doers = [noticeDoer] + return doers + + +class NoticeDoer(doing.DoDoer): + """ DoDoer Sending EXN notices to other participants. + """ + + def __init__(self, name, base, alias, bran): + + hby = existing.setupHby(name=name, base=base, bran=bran) + self.hbyDoer = habbing.HaberyDoer(habery=hby) # setup doer + self.alias = alias + self.hby = hby + + self.postman = forwarding.Postman(hby=self.hby) + doers = [self.hbyDoer, self.postman, doing.doify(self.noticeDo)] + + super(NoticeDoer, self).__init__(doers=doers) + + def noticeDo(self, tymth, tock=0.0): + """ + Parameters: + tymth (function): injected function wrapper closure returned by .tymen() of + Tymist instance. Calling tymth() returns associated Tymist .tyme. + tock (float): injected initial tock value + + Returns: doifiable Doist compatible generator method + """ + # enter context + self.wind(tymth) + self.tock = tock + _ = (yield self.tock) + + hab = self.hby.habByName(name=self.alias) + habord = hab.db.habs.get(keys=self.alias) + + if hab.group and habord is not None: + serder = hab.kever.serder + rot = hab.makeOwnEvent(sn=hab.kever.sn) + eserder = coring.Serder(raw=rot) + del rot[:eserder.size] + + ilk = serder.ked['t'] + others = list(oset(habord.smids + (habord.rmids or []))) # list(rec.smids) + others.remove(hab.mhab.pre) + + if ilk in (Ilks.rot,): + print(f"Sending rot event to {len(others)} participants.") + exn, ims = grouping.multisigRotateExn(hab, + aids=habord.smids, + smids=habord.smids, + rmids=habord.rmids, + ked=serder.ked) + elif ilk in (Ilks.icp,): + print(f"Sending icp event to {len(others)} participants.") + exn, ims = grouping.multisigInceptExn(hab, + aids=habord.smids, + ked=serder.ked) + elif ilk in (Ilks.ixn,): + print(f"Sending ixn event to {len(others)} participants.") + exn, ims = grouping.multisigInteractExn(hab, + aids=habord.smids, + sn=serder.sn, + data=serder.ked["a"]) + else: + raise ValueError(f"unsupport event type={ilk}") + + for recpt in others: + self.postman.send(src=hab.mhab.pre, dest=recpt, topic="multisig", + serder=eserder, attachment=rot) + self.postman.send(src=hab.mhab.pre, + dest=recpt, + topic="multisig", + serder=exn, + attachment=ims) + + while len(self.postman.cues) != (2 * len(others)): + yield self.tock + + print(f"Notice for event #{serder.sn} ({serder.ked['t']}) sent.") + toRemove = [self.hbyDoer, self.postman] + self.remove(toRemove) + + return