Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interactive and non-Interactive multisig credential issuance with IPEX grant and admit #573

Merged
merged 5 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions scripts/demo/credentials/multisig-issuer-interactive.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/bin/bash
# To run this script you need to run the following command in separate terminals:
# > kli witness demo
# and from the vLEI repo run:
# > vLEI-server -s ./schema/acdc -c ./samples/acdc/ -o ./samples/oobis/
#

# Create local environments for multisig group
kli init --name multisig1 --salt 0ACDEyMzQ1Njc4OWxtbm9aBc --nopasscode --config-dir ${KERI_SCRIPT_DIR} --config-file demo-witness-oobis
kli incept --name multisig1 --alias multisig1 --file ${KERI_DEMO_SCRIPT_DIR}/data/multisig-1-sample.json

# Incept both local identifiers for multisig group
kli init --name multisig2 --salt 0ACDEyMzQ1Njc4OWdoaWpsaw --nopasscode --config-dir ${KERI_SCRIPT_DIR} --config-file demo-witness-oobis
kli incept --name multisig2 --alias multisig2 --file ${KERI_DEMO_SCRIPT_DIR}/data/multisig-2-sample.json

# Exchange OOBIs between multisig group
kli oobi resolve --name multisig1 --oobi-alias multisig2 --oobi http://127.0.0.1:5642/oobi/EJccSRTfXYF6wrUVuenAIHzwcx3hJugeiJsEKmndi5q1/witness
kli oobi resolve --name multisig2 --oobi-alias multisig1 --oobi http://127.0.0.1:5642/oobi/EKYLUMmNPZeEs77Zvclf0bSN5IN-mLfLpx2ySb-HDlk4/witness

# Create the identifier to which the credential will be issued
kli init --name holder --salt 0ACDEyMzQ1Njc4OWxtbm9qWc --nopasscode --config-dir ${KERI_SCRIPT_DIR} --config-file demo-witness-oobis
kli incept --name holder --alias holder --file ${KERI_DEMO_SCRIPT_DIR}/data/gleif-sample.json

# Introduce multisig to Holder
kli oobi resolve --name holder --oobi-alias multisig2 --oobi http://127.0.0.1:5642/oobi/EJccSRTfXYF6wrUVuenAIHzwcx3hJugeiJsEKmndi5q1/witness
kli oobi resolve --name holder --oobi-alias multisig1 --oobi http://127.0.0.1:5642/oobi/EKYLUMmNPZeEs77Zvclf0bSN5IN-mLfLpx2ySb-HDlk4/witness

# Introduce the holder to all participants in the multisig group
kli oobi resolve --name multisig1 --oobi-alias holder --oobi http://127.0.0.1:5642/oobi/ELjSFdrTdCebJlmvbFNX9-TLhR2PO0_60al1kQp5_e6k/witness
kli oobi resolve --name multisig2 --oobi-alias holder --oobi http://127.0.0.1:5642/oobi/ELjSFdrTdCebJlmvbFNX9-TLhR2PO0_60al1kQp5_e6k/witness

# Load Data OOBI for schema of credential to issue
kli oobi resolve --name multisig1 --oobi-alias vc --oobi http://127.0.0.1:7723/oobi/EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao
kli oobi resolve --name multisig2 --oobi-alias vc --oobi http://127.0.0.1:7723/oobi/EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao
kli oobi resolve --name holder --oobi-alias vc --oobi http://127.0.0.1:7723/oobi/EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao

# Run the follow in parallel and wait for the group to be created:
kli multisig incept --name multisig1 --alias multisig1 --group multisig --file ${KERI_DEMO_SCRIPT_DIR}/data/multisig-sample.json &
pid=$!
PID_LIST+=" $pid"

kli multisig incept --name multisig2 --alias multisig2 --group multisig --file ${KERI_DEMO_SCRIPT_DIR}/data/multisig-sample.json &
pid=$!
PID_LIST+=" $pid"

wait $PID_LIST
kli oobi resolve --name holder --oobi-alias multisig --oobi http://127.0.0.1:5642/oobi/EC61gZ9lCKmHAS7U5ehUfEbGId5rcY0D7MirFZHDQcE2/witness

# Create a credential registry owned by the multisig issuer
kli vc registry incept --name multisig1 --alias multisig --registry-name vLEI --usage "Issue vLEIs" --nonce AHSNDV3ABI6U8OIgKaj3aky91ZpNL54I5_7-qwtC6q2s &
pid=$!
PID_LIST=" $pid"

#kli vc registry incept --name multisig2 --alias multisig --registry-name vLEI --usage "Issue vLEIs" --nonce AHSNDV3ABI6U8OIgKaj3aky91ZpNL54I5_7-qwtC6q2s &
#pid=$!
#PID_LIST+=" $pid"

echo "Multisig2 looking to join credential registry creation"
kli multisig join --name multisig2

wait $PID_LIST

# Issue Credential
kli vc create --name multisig1 --alias multisig --registry-name vLEI --schema EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao --recipient ELjSFdrTdCebJlmvbFNX9-TLhR2PO0_60al1kQp5_e6k --data @${KERI_DEMO_SCRIPT_DIR}/data/credential-data.json &
pid=$!
PID_LIST+=" $pid"

# Wait for 3 seconds to allow credential.json to be created, but still launch in parallel because they will wait for each other
echo "Multisig2 looking to join credential creation"
kli multisig join --name multisig2

wait $PID_LIST

SAID=$(kli vc list --name multisig1 --alias multisig --issued --said)

kli ipex grant --name multisig1 --alias multisig --said "${SAID}" --recipient ELjSFdrTdCebJlmvbFNX9-TLhR2PO0_60al1kQp5_e6k &
pid=$!
PID_LIST="$pid"

kli multisig join --name multisig2

wait ${PID_LIST}

echo "Polling for holder's IPEX message..."
SAID=$(kli ipex list --name holder --alias holder --poll --said)

echo "Admitting GRANT ${SAID}"
kli ipex admit --name holder --alias holder --said "${SAID}"

kli vc list --name holder --alias holder

SAID=$(kli vc list --name holder --alias holder --said --schema EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao)

echo "Revoking ${SAID}..."
kli vc revoke --name multisig1 --alias multisig --registry-name vLEI --said "${SAID}"&
pid=$!
PID_LIST="$pid"

kli multisig join --name multisig2

wait $PID_LIST
kli vc list --name holder --alias holder --poll
44 changes: 33 additions & 11 deletions scripts/demo/credentials/multisig-issuer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,43 +47,65 @@ wait $PID_LIST
kli oobi resolve --name holder --oobi-alias multisig --oobi http://127.0.0.1:5642/oobi/EC61gZ9lCKmHAS7U5ehUfEbGId5rcY0D7MirFZHDQcE2/witness

# Create a credential registry owned by the multisig issuer
kli vc registry incept --name multisig1 --alias multisig --registry-name vLEI --nonce AHSNDV3ABI6U8OIgKaj3aky91ZpNL54I5_7-qwtC6q2s &
kli vc registry incept --name multisig1 --alias multisig --registry-name vLEI --usage "Issue vLEIs" --nonce AHSNDV3ABI6U8OIgKaj3aky91ZpNL54I5_7-qwtC6q2s &
pid=$!
PID_LIST=" $pid"

kli vc registry incept --name multisig2 --alias multisig --registry-name vLEI --nonce AHSNDV3ABI6U8OIgKaj3aky91ZpNL54I5_7-qwtC6q2s &
kli vc registry incept --name multisig2 --alias multisig --registry-name vLEI --usage "Issue vLEIs" --nonce AHSNDV3ABI6U8OIgKaj3aky91ZpNL54I5_7-qwtC6q2s &
pid=$!
PID_LIST+=" $pid"

wait $PID_LIST
# Rotate multisig keys:
kli multisig rotate --name multisig1 --alias multisig &

## Rotate multisig keys:
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

kli multisig rotate --name multisig1 --alias multisig --smids EJccSRTfXYF6wrUVuenAIHzwcx3hJugeiJsEKmndi5q1:1 --smids EKYLUMmNPZeEs77Zvclf0bSN5IN-mLfLpx2ySb-HDlk4:1 &
pid=$!
PID_LIST=" $pid"

kli multisig rotate --name multisig2 --alias multisig &
kli multisig rotate --name multisig2 --alias multisig --smids EJccSRTfXYF6wrUVuenAIHzwcx3hJugeiJsEKmndi5q1:1 --smids EKYLUMmNPZeEs77Zvclf0bSN5IN-mLfLpx2ySb-HDlk4:1 &
pid=$!
PID_LIST+=" $pid"

wait $PID_LIST


# Issue Credential
kli vc issue --name multisig1 --alias multisig --registry-name vLEI --schema EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao --recipient ELjSFdrTdCebJlmvbFNX9-TLhR2PO0_60al1kQp5_e6k --data @${KERI_DEMO_SCRIPT_DIR}/data/credential-data.json &
TIME=$(date -Iseconds -u)
kli vc create --name multisig1 --alias multisig --registry-name vLEI --schema EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao --recipient ELjSFdrTdCebJlmvbFNX9-TLhR2PO0_60al1kQp5_e6k --data @${KERI_DEMO_SCRIPT_DIR}/data/credential-data.json --time "${TIME}" &
pid=$!
PID_LIST+=" $pid"

# Wait for 3 seconds to allow credential.json to be created, but still launch in parallel because they will wait for each other
sleep 3
kli vc issue --name multisig2 --alias multisig --credential @./credential.json &
kli vc create --name multisig2 --alias multisig --registry-name vLEI --schema EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao --recipient ELjSFdrTdCebJlmvbFNX9-TLhR2PO0_60al1kQp5_e6k --data @${KERI_DEMO_SCRIPT_DIR}/data/credential-data.json --time "${TIME}" &
pid=$!
PID_LIST+=" $pid"

wait $PID_LIST

SAID=$(kli vc list --name multisig1 --alias multisig --issued --said)

kli ipex grant --name multisig1 --alias multisig --said "${SAID}" --recipient ELjSFdrTdCebJlmvbFNX9-TLhR2PO0_60al1kQp5_e6k --time "${TIME}" &
pid=$!
PID_LIST+=" $pid"

kli ipex grant --name multisig2 --alias multisig --said "${SAID}" --recipient ELjSFdrTdCebJlmvbFNX9-TLhR2PO0_60al1kQp5_e6k --time "${TIME}" &
pid=$!
PID_LIST+=" $pid"

wait $PID_LIST

echo "Polling for holder's IPEX message..."
SAID=$(kli ipex list --name holder --alias holder --poll --said)

echo "Admitting GRANT ${SAID}"
kli ipex admit --name holder --alias holder --said "${SAID}"

kli vc list --name holder --alias holder --poll

SAID=`kli vc list --name holder --alias holder --said --schema EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao`
SAID=$(kli vc list --name holder --alias holder --said --schema EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao)

echo "Revoking ${SAID}..."
TIME=$(date -Iseconds -u)
Expand Down
19 changes: 16 additions & 3 deletions src/keri/app/agenting.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ def msgDo(self, tymth=None, tock=1.0, **opts):
src = evt["src"]
r = evt["r"]
q = evt["q"]
wits = evt["wits"]
wits = evt["wits"] if "wits" in evt else None

if "hab" in evt:
hab = evt["hab"]
Expand Down Expand Up @@ -534,9 +534,9 @@ def query(self, pre, r="logs", sn=0, src=None, hab=None, anchor=None, wits=None,

self.msgs.append(msg)

def telquery(self, src, ri, i=None, r="tels", **kwa):
def telquery(self, src, ri, i=None, r="tels", wits=None, **kwa):
qry = dict(ri=ri)
self.msgs.append(dict(src=src, pre=i, r=r, q=qry))
self.msgs.append(dict(src=src, pre=i, r=r, wits=wits, q=qry))


class WitnessPublisher(doing.DoDoer):
Expand Down Expand Up @@ -611,6 +611,19 @@ def sendDo(self, tymth=None, tock=0.0, **opts):

yield self.tock

def sent(self, said):
""" Check if message with given SAID was sent

Parameters:
said (str): qb64 SAID of message to check for
"""

for cue in self.cues:
if cue["said"] == said:
return True

return False


class TCPMessenger(doing.DoDoer):
""" Send events to witnesses for receipting using TCP direct connection
Expand Down
1 change: 0 additions & 1 deletion src/keri/app/cli/commands/escrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,5 @@ def escrows(tymth, tock=0.0, **opts):
pass

except ConfigurationError as e:
print(e)
print(f"identifier prefix for {name} does not exist, incept must be run first", )
return -1
28 changes: 18 additions & 10 deletions src/keri/app/cli/commands/ipex/admit.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from hio.base import doing

from keri.app import forwarding, connecting, habbing, grouping, indirecting
from keri.app import forwarding, connecting, habbing, grouping, indirecting, agenting
from keri.app.cli.common import existing
from keri.app.notifying import Notifier
from keri.core import parsing, coring, eventing
Expand Down Expand Up @@ -53,12 +53,13 @@ def __init__(self, name, alias, base, bran, said, message):
self.rgy = credentialing.Regery(hby=self.hby, name=name, base=base)
self.org = connecting.Organizer(hby=self.hby)
self.postman = forwarding.Poster(hby=self.hby)
self.witq = agenting.WitnessInquisitor(hby=self.hby)

kvy = eventing.Kevery(db=self.hby.db)
tvy = teventing.Tevery(db=self.hby.db, reger=self.rgy.reger)
vry = verifying.Verifier(hby=self.hby, reger=self.rgy.reger)
self.kvy = eventing.Kevery(db=self.hby.db)
self.tvy = teventing.Tevery(db=self.hby.db, reger=self.rgy.reger)
self.vry = verifying.Verifier(hby=self.hby, reger=self.rgy.reger)

self.psr = parsing.Parser(kvy=kvy, tvy=tvy, vry=vry)
self.psr = parsing.Parser(kvy=self.kvy, tvy=self.tvy, vry=self.vry)

notifier = Notifier(self.hby)
mux = grouping.Multiplexor(self.hby, notifier=notifier)
Expand All @@ -69,9 +70,9 @@ def __init__(self, name, alias, base, bran, said, message):

mbx = indirecting.MailboxDirector(hby=self.hby,
topics=["/receipt", "/multisig", "/replay", "/credential"],
exc=self.exc)
exc=self.exc, kvy=self.kvy, tvy=self.tvy, verifier=self.vry)

self.toRemove = [self.postman, mbx]
self.toRemove = [self.postman, mbx, self.witq]
super(AdmitDoer, self).__init__(doers=self.toRemove + [doing.doify(self.admitDo)])

def admitDo(self, tymth, tock=0.0):
Expand Down Expand Up @@ -99,14 +100,21 @@ def admitDo(self, tymth, tock=0.0):
raise ValueError(f"exn said={self.said} is not a grant message, route={route}")

embeds = grant.ked['e']
acdc = embeds["acdc"]
issr = acdc['i']

# Lets get the latest KEL and Registry if needed
self.witq.query(src=self.hab.pre, pre=issr)
if "ri" in acdc:
self.witq.telquery(src=self.hab.pre, wits=self.hab.kevers[issr].wits, ri=acdc["ri"], i=acdc["d"])

for label in ("anc", "iss", "acdc"):
ked = embeds[label]
sadder = coring.Sadder(ked=ked)
ims = bytearray(sadder.raw) + pathed[label]
self.psr.parseOne(ims=ims)

said = embeds["acdc"]["d"]
said = acdc["d"]
while not self.rgy.reger.saved.get(keys=said):
yield self.tock

Expand Down Expand Up @@ -134,14 +142,14 @@ def admitDo(self, tymth, tock=0.0):
yield self.tock

if self.exc.lead(self.hab, said=exn.said):
print("Sending admit message...")
print(f"Sending admit message to {recp}")
self.postman.send(src=self.hab.pre,
dest=recp,
topic="credential",
serder=exn,
attachment=atc)

while not self.postman.cues:
while not self.postman.sent(exn.said):
yield self.tock

self.remove(self.toRemove)
24 changes: 15 additions & 9 deletions src/keri/app/cli/commands/ipex/grant.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
parser.add_argument("--said", "-s", help="SAID of the credential to grant", required=True)
parser.add_argument("--message", "-m", help="optional human readable message to "
"send to recipient", required=False, default="")
parser.add_argument("--time", help="timestamp for the revocation", required=False, default=None)


def handler(args):
Expand All @@ -40,16 +41,18 @@ def handler(args):
bran=args.bran,
said=args.said,
recp=args.recipient,
message=args.message)
message=args.message,
timestamp=args.time)
return [ed]


class GrantDoer(doing.DoDoer):

def __init__(self, name, alias, base, bran, said, recp, message):
def __init__(self, name, alias, base, bran, said, recp, message, timestamp):
self.said = said
self.recp = recp
self.message = message
self.timestamp = timestamp
self.hby = existing.setupHby(name=name, base=base, bran=bran)
self.hab = self.hby.habByName(alias)
self.rgy = credentialing.Regery(hby=self.hby, name=name, base=base)
Expand Down Expand Up @@ -113,7 +116,8 @@ def grantDo(self, tymth, tock=0.0):
anchor=dict(i=iserder.pre, s=seqner.snh, d=iserder.said))
anc = self.hby.db.cloneEvtMsg(pre=serder.pre, fn=0, dig=serder.said)

exn, atc = protocoling.ipexGrantExn(hab=self.hab, message=self.message, acdc=acdc, iss=iss, anc=anc)
exn, atc = protocoling.ipexGrantExn(hab=self.hab, recp=recp, message=self.message, acdc=acdc, iss=iss, anc=anc,
dt=self.timestamp)
msg = bytearray(exn.raw)
msg.extend(atc)

Expand All @@ -125,20 +129,21 @@ def grantDo(self, tymth, tock=0.0):
smids = self.hab.db.signingMembers(pre=self.hab.pre)
smids.remove(self.hab.mhab.pre)

for recp in smids: # this goes to other participants only as a signaling mechanism
for part in smids: # this goes to other participants
self.postman.send(src=self.hab.mhab.pre,
dest=recp,
dest=part,
topic="multisig",
serder=wexn,
attachment=watc)

while not self.exc.complete(said=wexn.said):
while not self.exc.complete(said=exn.said):
yield self.tock

if self.exc.lead(self.hab, said=exn.said):
print(f"Sending grant message {exn.said}...")
credentialing.sendRegistry(self.hby, self.rgy.reger, self.postman, creder, self.hab.pre, recp)
self.postman.send(src=self.hab.pre,
print(f"Sending message {exn.said} to {recp}")
atc = exchanging.serializeMessage(self.hby, exn.said)
del atc[:exn.size]
self.postman.send(src=self.hab.mhab.pre,
dest=recp,
topic="credential",
serder=exn,
Expand All @@ -148,4 +153,5 @@ def grantDo(self, tymth, tock=0.0):
yield self.tock

print("... grant message sent")

self.remove(self.toRemove)
3 changes: 1 addition & 2 deletions src/keri/app/cli/commands/ipex/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,7 @@ def admit(self, note, exn, pathed):

print(f"Credential {sad['d']}:")
print(f" Type: {schemer.sed['title']}")
print(
f" Status: Accepted {terming.Colors.OKGREEN}{terming.Symbols.CHECKMARK}{terming.Colors.ENDC}")
print(f" Status: Accepted {terming.Colors.OKGREEN}{terming.Symbols.CHECKMARK}{terming.Colors.ENDC}")

def deleteNote(self, keys):
yn = input(f"\n Delete the notification [Y|n]?")
Expand Down
Loading