Skip to content

Commit

Permalink
Fixed admit to work with multisig holder. (#164)
Browse files Browse the repository at this point in the history
* Fixed admit to work with multisig holder.

Signed-off-by: pfeairheller <[email protected]>

* Update test.

Signed-off-by: pfeairheller <[email protected]>

---------

Signed-off-by: pfeairheller <[email protected]>
  • Loading branch information
pfeairheller authored Jan 5, 2024
1 parent 087f62f commit f67227a
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 39 deletions.
1 change: 0 additions & 1 deletion src/keria/app/agenting.py
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,6 @@ def recur(self, tyme=None):
self.cues.append(cue)
return False
elif cue["kin"] == "query":
print("passing it along to the querier!")
self.queries.append(cue['q'])
return False
else:
Expand Down
2 changes: 1 addition & 1 deletion src/keria/app/credentialing.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def on_get(req, rep, name, registryName):
name=registry.name,
regk=registry.regk,
pre=registry.hab.pre,
state=registry.tever.state().ked
state=asdict(registry.tever.state())
)
rep.status = falcon.HTTP_200
rep.content_type = "application/json"
Expand Down
51 changes: 31 additions & 20 deletions src/keria/app/ipexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
import json

import falcon
from keri.app import habbing
from keri.core import coring, eventing, serdering
from keri.peer import exchanging

from keria.core import httping

Expand Down Expand Up @@ -92,42 +94,52 @@ def sendAdmit(agent, hab, ked, sigs, rec):

@staticmethod
def sendMultisigExn(agent, hab, ked, sigs, atc, rec):
if not isinstance(hab, habbing.SignifyGroupHab):
raise falcon.HTTPBadRequest(description=f"attempt to send multisig message with non-group AID={hab.pre}")

for recp in rec: # Have to verify we already know all the recipients.
if recp not in agent.hby.kevers:
raise falcon.HTTPBadRequest(description=f"attempt to send to unknown AID={recp}")

embeds = ked['e']
admit = embeds['exn']
if admit['r'] != "/ipex/admit":
raise falcon.HTTPBadRequest(description=f"invalid route for embedded ipex admit {ked['r']}")
admitked = embeds['exn']
if admitked['r'] != "/ipex/admit":
raise falcon.HTTPBadRequest(description=f"invalid route for embedded ipex admit {admitked['r']}")

# Have to add the atc to the end... this will be Pathed signatures for embeds
if 'exn' not in atc or not atc['exn']:
if not atc:
raise falcon.HTTPBadRequest(description=f"attachment missing for ACDC, unable to process request.")

holder = admit['a']['i']
serder = serdering.SerderKERI(sad=admit)
ims = bytearray(serder.raw) + atc['exn'].encode("utf-8")
agent.hby.psr.parseOne(ims=ims)
agent.exchanges.append(dict(said=serder.said, pre=hab.pre, rec=holder, topic="credential"))
agent.admits.append(dict(said=admit['d'], pre=hab.pre))

# use that data to create th Serder and Sigers for the exn
serder = serdering.SerderKERI(sad=ked)
sigers = [coring.Siger(qb64=sig) for sig in sigs]

# Now create the stream to send, need the signer seal
kever = hab.kever
seal = eventing.SealEvent(i=hab.pre, s="{:x}".format(kever.lastEst.s), d=kever.lastEst.d)
kever = hab.mhab.kever
seal = eventing.SealEvent(i=hab.mhab.pre, s="{:x}".format(kever.lastEst.s), d=kever.lastEst.d)

ims = eventing.messagize(serder=serder, sigers=sigers, seal=seal)

ims.extend(atc['exn'].encode("utf-8")) # add the pathed attachments
ims.extend(atc.encode("utf-8")) # add the pathed attachments

# make a copy and parse
agent.hby.psr.parseOne(ims=bytearray(ims))
agent.exchanges.append(dict(said=serder.said, pre=hab.pre, rec=rec, topic='credential'))

exn, pathed = exchanging.cloneMessage(agent.hby, serder.said)
if not exn:
raise falcon.HTTPBadRequest(description=f"invalid exn request message {serder.said}")

grant, _ = exchanging.cloneMessage(agent.hby, admitked['p'])
embeds = grant.ked['e']
acdc = embeds["acdc"]
issr = acdc['i']

serder = serdering.SerderKERI(sad=admitked)
ims = bytearray(serder.raw) + pathed['exn']
agent.hby.psr.parseOne(ims=ims)
agent.exchanges.append(dict(said=serder.said, pre=hab.pre, rec=[issr], topic="credential"))
agent.admits.append(dict(said=admitked['d'], pre=hab.pre))


class IpexGrantCollectionEnd:

Expand Down Expand Up @@ -201,6 +213,9 @@ def sendGrant(agent, hab, ked, sigs, atc, rec):

@staticmethod
def sendMultisigExn(agent, hab, ked, sigs, atc, rec):
if not isinstance(hab, habbing.SignifyGroupHab):
raise falcon.HTTPBadRequest(description=f"attempt to send multisig message with non-group AID={hab.pre}")

for recp in rec: # Have to verify we already know all the recipients.
if recp not in agent.hby.kevers:
raise falcon.HTTPBadRequest(description=f"attempt to send to unknown AID={recp}")
Expand All @@ -212,11 +227,7 @@ def sendMultisigExn(agent, hab, ked, sigs, atc, rec):

holder = grant['a']['i']
serder = serdering.SerderKERI(sad=grant)
sigers = [coring.Siger(qb64=sig) for sig in sigs]
seal = eventing.SealEvent(i=hab.pre, s="{:x}".format(hab.kever.lastEst.s), d=hab.kever.lastEst.d)

ims = eventing.messagize(serder=serder, sigers=sigers, seal=seal)
ims = ims + atc.encode("utf-8")
ims = bytearray(serder.raw) + atc.encode("utf-8")
agent.hby.psr.parseOne(ims=ims)
agent.exchanges.append(dict(said=serder.said, pre=hab.pre, rec=holder, topic="credential"))
agent.grants.append(dict(said=grant['d'], pre=hab.pre))
Expand Down
1 change: 0 additions & 1 deletion tests/app/test_grouping.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ def test_load_ends(helpers):
def test_multisig_request_ends(helpers):
with helpers.openKeria() as (agency, agent, app, client):
grouping.loadEnds(app=app)

end = aiding.IdentifierCollectionEnd()
app.add_route("/identifiers", end)
aidEnd = aiding.IdentifierResourceEnd()
Expand Down
149 changes: 135 additions & 14 deletions tests/app/test_ipexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ def test_ipex_admit(helpers, mockHelpingNowIso8601):

end = aiding.IdentifierCollectionEnd()
app.add_route("/identifiers", end)
aidEnd = aiding.IdentifierResourceEnd()
app.add_route("/identifiers/{name}", aidEnd)

salt = b'0123456789abcdef'
op = helpers.createAid(client, "test", salt)
aid = op["response"]
Expand Down Expand Up @@ -112,11 +115,67 @@ def test_ipex_admit(helpers, mockHelpingNowIso8601):
agent.exchanges.clear()
agent.admits.clear()

psalt0 = b'0123456789abcM00'
op = helpers.createAid(client, "part0", psalt0)
paid0 = op["response"]
ppre0 = paid0['i']
assert ppre0 == "EI0XLIyKcSFFXi14HZGnLxU24BSsX78ZmZ_w3-N0fRSy"
_, signers0 = helpers.incept(psalt0, "signify:aid", pidx=0)
signer0 = signers0[0]

psalt1 = b'0123456789abcM01'
op = helpers.createAid(client, "part1", psalt1)
paid1 = op["response"]
ppre1 = paid1['i']
assert ppre1 == "EGFFaJOT9HV3jqxk6PaIrLJQz2qQK2TnqbhjwiIij2m8"
_, signers1 = helpers.incept(psalt1, "signify:aid", pidx=0)
signer1 = signers1[0]

# Get their hab dicts
m0 = client.simulate_get("/identifiers/part0").json
m1 = client.simulate_get("/identifiers/part1").json

assert m0["prefix"] == "EI0XLIyKcSFFXi14HZGnLxU24BSsX78ZmZ_w3-N0fRSy"
assert m1["prefix"] == "EGFFaJOT9HV3jqxk6PaIrLJQz2qQK2TnqbhjwiIij2m8"

keys = [m0['state']['k'][0], m1['state']['k'][0]]
ndigs = [m0['state']['n'][0], m1['state']['n'][0]]

# Create the mutlsig inception event
serder = eventing.incept(keys=keys,
isith="2",
nsith="2",
ndigs=ndigs,
code=coring.MtrDex.Blake3_256,
toad=0,
wits=[])
assert serder.said == "ECJg1cFrp4G2ZHk8_ocsdoS1VuptVpaG9fLktBrwx1Fo"

# Send in all signatures as if we are joining the inception event
sigers = [signer0.sign(ser=serder.raw, index=0).qb64, signer1.sign(ser=serder.raw, index=1).qb64]
states = nstates = [m0['state'], m1['state']]

body = {
'name': 'multisig',
'icp': serder.ked,
'sigs': sigers,
"smids": states,
"rmids": nstates,
'group': {
"mhab": m0,
"keys": keys,
"ndigs": ndigs
}
}

res = client.simulate_post(path="/identifiers", body=json.dumps(body))
assert res.status_code == 202

ims = eventing.messagize(serder=exn, sigers=[coring.Siger(qb64=sigs[0])])
# Test sending embedded admit in multisig/exn message
exn, end = exchanging.exchange(route="/multisig/exn",
payload=dict(),
sender=pre,
sender=serder.pre,
embeds=dict(exn=ims),
dig=dig,
date=helping.nowIso8601())
Expand All @@ -125,44 +184,48 @@ def test_ipex_admit(helpers, mockHelpingNowIso8601):
body = dict(
exn=exn.ked,
sigs=sigs,
atc=dict(exn=end.decode("utf-8")),
atc=end.decode("utf-8"),
rec=["EZ-i0d8JZAoTNZH3ULaU6JR2nmwyvYAfSVPzhzS6b5CM"]
)

data = json.dumps(body).encode("utf-8")
res = client.simulate_post(path="/identifiers/test/ipex/admit", body=data)
assert res.status_code == 400
assert res.json == {'description': 'attempt to send to unknown '
'AID=EZ-i0d8JZAoTNZH3ULaU6JR2nmwyvYAfSVPzhzS6b5CM',
assert res.json == {'description': 'attempt to send multisig message with non-group '
'AID=EHgwVwQT15OJvilVvW57HE4w0-GPs_Stj2OFoAHZSysY',
'title': '400 Bad Request'}

# Multi-sign the exn message
sigs = [signer0.sign(ser=exn.raw, index=0).qb64, signer1.sign(ser=exn.raw, index=1).qb64]
# Bad attachments
body = dict(
exn=exn.ked,
sigs=sigs,
atc=dict(bad=end.decode("utf-8")),
atc=end.decode("utf-8"),
rec=[pre1]
)

data = json.dumps(body).encode("utf-8")
res = client.simulate_post(path="/identifiers/test/ipex/admit", body=data)
res = client.simulate_post(path="/identifiers/multisig/ipex/admit", body=data)
assert res.status_code == 400
assert res.json == {'description': 'attachment missing for ACDC, unable to process request.',
assert res.json == {'description': 'invalid exn request message '
'EGJBe7LIp2x3PpeeG0utsj3ScTGR5_TA28622WUFYP8B',
'title': '400 Bad Request'}

body = dict(
exn=exn.ked,
sigs=sigs,
atc=dict(exn=end.decode("utf-8")),
atc=end.decode("utf-8"),
rec=[pre1]
)

data = json.dumps(body).encode("utf-8")
res = client.simulate_post(path="/identifiers/test/ipex/admit", body=data)
res = client.simulate_post(path="/identifiers/multisig/ipex/admit", body=data)

assert res.status_code == 202
# TODO: Fix test
assert res.status_code == 400
assert len(agent.exchanges) == 2
assert len(agent.admits) == 1
assert len(agent.admits) == 0


def test_ipex_grant(helpers, mockHelpingNowIso8601, seeder):
Expand All @@ -181,6 +244,8 @@ def test_ipex_grant(helpers, mockHelpingNowIso8601, seeder):

end = aiding.IdentifierCollectionEnd()
app.add_route("/identifiers", end)
aidEnd = aiding.IdentifierResourceEnd()
app.add_route("/identifiers/{name}", aidEnd)

salt2 = b'0123456789abcdeg'
op = helpers.createAid(client, "legal-entity", salt2)
Expand All @@ -194,6 +259,62 @@ def test_ipex_grant(helpers, mockHelpingNowIso8601, seeder):
pre1 = verifier['i']
assert pre1 == "EEtaMHCGi83N3IJN05DRDhkpIo5S03LOX5_8IgdvMaVq"

psalt0 = b'0123456789abcM00'
op = helpers.createAid(client, "part0", psalt0)
paid0 = op["response"]
ppre0 = paid0['i']
assert ppre0 == "EI0XLIyKcSFFXi14HZGnLxU24BSsX78ZmZ_w3-N0fRSy"
_, signers0 = helpers.incept(psalt0, "signify:aid", pidx=0)
signer0 = signers0[0]

psalt1 = b'0123456789abcM01'
op = helpers.createAid(client, "part1", psalt1)
paid1 = op["response"]
ppre1 = paid1['i']
assert ppre1 == "EGFFaJOT9HV3jqxk6PaIrLJQz2qQK2TnqbhjwiIij2m8"
_, signers1 = helpers.incept(psalt1, "signify:aid", pidx=0)
signer1 = signers1[0]

# Get their hab dicts
m0 = client.simulate_get("/identifiers/part0").json
m1 = client.simulate_get("/identifiers/part1").json

assert m0["prefix"] == "EI0XLIyKcSFFXi14HZGnLxU24BSsX78ZmZ_w3-N0fRSy"
assert m1["prefix"] == "EGFFaJOT9HV3jqxk6PaIrLJQz2qQK2TnqbhjwiIij2m8"

keys = [m0['state']['k'][0], m1['state']['k'][0]]
ndigs = [m0['state']['n'][0], m1['state']['n'][0]]

# Create the mutlsig inception event
serder = eventing.incept(keys=keys,
isith="2",
nsith="2",
ndigs=ndigs,
code=coring.MtrDex.Blake3_256,
toad=0,
wits=[])
assert serder.said == "ECJg1cFrp4G2ZHk8_ocsdoS1VuptVpaG9fLktBrwx1Fo"

# Send in all signatures as if we are joining the inception event
sigers = [signer0.sign(ser=serder.raw, index=0).qb64, signer1.sign(ser=serder.raw, index=1).qb64]
states = nstates = [m0['state'], m1['state']]

body = {
'name': 'multisig',
'icp': serder.ked,
'sigs': sigers,
"smids": states,
"rmids": nstates,
'group': {
"mhab": m0,
"keys": keys,
"ndigs": ndigs
}
}

res = client.simulate_post(path="/identifiers", body=json.dumps(body))
assert res.status_code == 202

# Lets issue a QVI credential to the QVI
issuer.createRegistry(issuerHab.pre, name="issuer")
qvisaid = issuer.issueQVIvLEI("issuer", issuerHab, le['i'], "78I9GKEFM361IFY3PIN0")
Expand Down Expand Up @@ -313,8 +434,8 @@ def test_ipex_grant(helpers, mockHelpingNowIso8601, seeder):
data = json.dumps(body).encode("utf-8")
res = client.simulate_post(path="/identifiers/legal-entity/ipex/grant", body=data)
assert res.status_code == 400
assert res.json == {'description': 'attempt to send to unknown '
'AID=EZ-i0d8JZAoTNZH3ULaU6JR2nmwyvYAfSVPzhzS6b5CM',
assert res.json == {'description': 'attempt to send multisig message with non-group '
'AID=EFnYGvF_ENKJ_4PGsWsvfd_R6m5cN-3KYsz_0mAuNpCm',
'title': '400 Bad Request'}

body = dict(
Expand All @@ -325,7 +446,7 @@ def test_ipex_grant(helpers, mockHelpingNowIso8601, seeder):
)

data = json.dumps(body).encode("utf-8")
res = client.simulate_post(path="/identifiers/legal-entity/ipex/grant", body=data)
res = client.simulate_post(path="/identifiers/multisig/ipex/grant", body=data)

assert res.status_code == 202
assert len(agent.exchanges) == 3
Expand Down
2 changes: 0 additions & 2 deletions tests/app/test_specing.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ def test_spec_resource(helpers):
assert "/states" in paths

js = json.dumps(sd)
print(js)

# Assert on the entire JSON to ensure we are getting all the docs
assert js == ('{"paths": {"/oobis": {"post": {"summary": "Resolve OOBI and assign an '
'alias for the remote identifier", "description": "Resolve OOBI URL or '
Expand Down

0 comments on commit f67227a

Please sign in to comment.