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

Multisig Group Key Event Interop #80

Merged
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
139 changes: 0 additions & 139 deletions integration/app/integration_clienting.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,145 +391,6 @@ def test_delegation():
assert icp1.pre == pre


def test_multisig():
""" This test assumes a running Demo Witnesses and KERIA agent with the following comands:

`kli witness demo`
`keria start --config-file demo-witness-oobis --config-dir <path to KERIpy>/scripts`

"""
url = "http://localhost:3901"
bran = b'0123456789abcdefghijk'
tier = Tiers.low

client = SignifyClient(passcode=bran, tier=tier)
print(client.controller)
assert client.controller == "ELI7pg979AdhmvrjDeam2eAO2SR5niCgnjAJXJHtJose"

evt, siger = client.ctrl.event()
res = requests.post(url="http://localhost:3903/boot",
json=dict(
icp=evt.ked,
sig=siger.qb64,
stem=client.ctrl.stem,
pidx=1,
tier=client.ctrl.tier))

client.connect(url=url)
assert client.agent is not None
assert client.agent.delpre == "ELI7pg979AdhmvrjDeam2eAO2SR5niCgnjAJXJHtJose"
assert client.agent.pre == "EEXekkGu9IAzav6pZVJhkLnjtjM5v3AcyA-pdKUcaGei"
# assert client.ctrl.ridx == 0

if res.status_code != requests.codes.accepted:
raise kering.AuthNError(f"unable to initialize cloud agent connection, {res.status_code}, {res.text}")

identifiers = client.identifiers()
operations = client.operations()
oobis = client.oobis()

op = identifiers.create("multisig3", bran="0123456789lmnopqrstuv")
icp = op["response"]
serder = coring.Serder(ked=icp)
assert serder.pre == "EOGvmhJDBbJP4zeXaRun5vSz0O3_1zB10DwNMyjXlJEv"
print(f"created AID {serder.pre}")

identifiers.addEndRole("multisig3", eid=client.agent.pre)

print(f"OOBI for {serder.pre}:")
oobi = oobis.get("multisig3")
print(oobi)

op = oobis.resolve(oobi="http://127.0.0.1:5642/oobi/EKYLUMmNPZeEs77Zvclf0bSN5IN-mLfLpx2ySb-HDlk4/witness/BBilc4"
"-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha",
alias="multisig1")

print("resolving oobi for multisig1")
while not op["done"]:
op = operations.get(op["name"])
sleep(1)

multisig1 = op["response"]
print("resolving oobi for multisig2")
op = oobis.resolve(oobi="http://127.0.0.1:5642/oobi/EJccSRTfXYF6wrUVuenAIHzwcx3hJugeiJsEKmndi5q1/witness/BBilc4"
"-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha",
alias="multisig2")

while not op["done"]:
op = operations.get(op["name"])
sleep(1)
multisig2 = op["response"]

m3 = identifiers.get("multisig3")
agent0 = m3["state"]
print(f"agent is {agent0}")

states = rstates = [multisig2, multisig1, agent0]

op = identifiers.create("multisig", algo=Algos.group, mhab=m3,
isith=["1/3", "1/3", "1/3"], nsith=["1/3", "1/3", "1/3"],
toad=3,
wits=[
"BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha",
"BLskRTInXnMxWaGqcpSyMgo0nYbalW99cGZESrz3zapM",
"BIKKuvBwpmDVA4Ds-EpL5bt9OqPzWPja2LigFYZN2YfX"
],
states=states,
rstates=rstates)
print("waiting on multisig creation...")
while not op["done"]:
op = operations.get(op["name"])
sleep(1)
gAid = op["response"]
print(f"group multisig created {gAid}")

# Join an interaction event with the group
data = {"i": "EE77q3_zWb5ojgJr-R1vzsL5yiL4Nzm-bfSOQzQl02dy"}
op = identifiers.interact("multisig", data=data)
while not op["done"]:
op = operations.get(op["name"])
sleep(1)

ixn = coring.Serder(ked=op["response"])
events = client.keyEvents()
log = events.get(pre=ixn.pre)
assert len(log) == 2

for event in log:
print(coring.Serder(ked=event).pretty())

op2 = identifiers.rotate("multisig3")
rot = op2["response"]
serder = coring.Serder(ked=rot)
print(f"rotated multisig3 to {serder.sn}")

aid1 = identifiers.get("multisig3")
agent0 = aid1["state"]
keyState = client.keyStates()
op = keyState.query(pre="EKYLUMmNPZeEs77Zvclf0bSN5IN-mLfLpx2ySb-HDlk4", sn=1)
while not op["done"]:
op = operations.get(op["name"])
sleep(1)

multisig1 = op["response"]
print(f"using key {multisig1['k'][0]}")
print(f"using dig {multisig1['n'][0]}")

op = keyState.query(pre="EJccSRTfXYF6wrUVuenAIHzwcx3hJugeiJsEKmndi5q1", sn=1)
while not op["done"]:
op = operations.get(op["name"])
sleep(1)

multisig2 = op["response"]
print(f"using key {multisig2['k'][0]}")
print(f"using dig {multisig2['n'][0]}")

states = rstates = [multisig1, multisig2, agent0]

op = identifiers.rotate("multisig", states=states, rstates=rstates)
print(op)


def test_randy():
""" This test assumes a running KERIA agent with the following comand:

Expand Down
4 changes: 0 additions & 4 deletions scripts/multisig-endrole.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
Testing clienting with integration tests that require a running KERIA Cloud Agent
"""

import json
from time import sleep

from keri.app.keeping import Algos
from keri.core.coring import Tiers
from signify.app.clienting import SignifyClient

Expand Down
186 changes: 186 additions & 0 deletions scripts/multisig-kli-rotation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
from time import sleep

import requests
from keri import kering
from keri.app.keeping import Algos
from keri.core import coring, eventing
from keri.core.coring import Tiers
from signify.app.clienting import SignifyClient


def create_multisig():
url = "http://localhost:3901"
bran = b'0123456789abcdefghijk'
tier = Tiers.low

client = SignifyClient(passcode=bran, tier=tier)
print(client.controller)
assert client.controller == "ELI7pg979AdhmvrjDeam2eAO2SR5niCgnjAJXJHtJose"

evt, siger = client.ctrl.event()
res = requests.post(url="http://localhost:3903/boot",
json=dict(
icp=evt.ked,
sig=siger.qb64,
stem=client.ctrl.stem,
pidx=1,
tier=client.ctrl.tier))

client.connect(url=url)
assert client.agent is not None
assert client.agent.delpre == "ELI7pg979AdhmvrjDeam2eAO2SR5niCgnjAJXJHtJose"
assert client.agent.pre == "EEXekkGu9IAzav6pZVJhkLnjtjM5v3AcyA-pdKUcaGei"
# assert client.ctrl.ridx == 0

if res.status_code != requests.codes.accepted:
raise kering.AuthNError(f"unable to initialize cloud agent connection, {res.status_code}, {res.text}")

identifiers = client.identifiers()
operations = client.operations()
oobis = client.oobis()
exchanges = client.exchanges()

(_, _, op) = identifiers.create("multisig3", bran="0123456789lmnopqrstuv")
icp = op["response"]
serder = coring.Serder(ked=icp)
assert serder.pre == "EOGvmhJDBbJP4zeXaRun5vSz0O3_1zB10DwNMyjXlJEv"
print(f"created AID {serder.pre}")

identifiers.addEndRole("multisig3", eid=client.agent.pre)

print(f"OOBI for {serder.pre}:")
oobi = oobis.get("multisig3")
print(oobi)

op = oobis.resolve(oobi="http://127.0.0.1:5642/oobi/EKYLUMmNPZeEs77Zvclf0bSN5IN-mLfLpx2ySb-HDlk4/witness",
alias="multisig1")

print("resolving oobi for multisig1")
while not op["done"]:
op = operations.get(op["name"])
sleep(1)
print("... done")

multisig1 = op["response"]
print("resolving oobi for multisig2")
op = oobis.resolve(oobi="http://127.0.0.1:5642/oobi/EJccSRTfXYF6wrUVuenAIHzwcx3hJugeiJsEKmndi5q1/witness",
alias="multisig2")
print("... done")

while not op["done"]:
op = operations.get(op["name"])
sleep(1)
multisig2 = op["response"]

m3 = identifiers.get("multisig3")
agent0 = m3["state"]
print(f"agent is {agent0}")

states = rstates = [multisig2, multisig1, agent0]

icp, isigs, op = identifiers.create("multisig", algo=Algos.group, mhab=m3,
isith=["1/3", "1/3", "1/3"], nsith=["1/3", "1/3", "1/3"],
toad=3,
wits=[
"BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha",
"BLskRTInXnMxWaGqcpSyMgo0nYbalW99cGZESrz3zapM",
"BIKKuvBwpmDVA4Ds-EpL5bt9OqPzWPja2LigFYZN2YfX"
],
states=states,
rstates=rstates)

smids = [state['i'] for state in states]
recp = [state['i'] for state in [multisig2, multisig1]]

embeds = dict(
icp=eventing.messagize(serder=icp, sigers=[coring.Siger(qb64=sig) for sig in isigs])
)

exchanges.send("multisig3", "multisig", sender=m3, route="/multisig/icp",
payload=dict(gid=icp.pre, smids=smids, rmids=smids),
embeds=embeds, recipients=recp)

print("waiting on multisig creation...")
while not op["done"]:
op = operations.get(op["name"])
sleep(1)
gAid = op["response"]
print(f"group multisig created {gAid}")

# Join an interaction event with the group
data = {"i": "EE77q3_zWb5ojgJr-R1vzsL5yiL4Nzm-bfSOQzQl02dy"}
ixn, xsigs, op = identifiers.interact("multisig", data=data)

embeds = dict(
ixn=eventing.messagize(serder=ixn, sigers=[coring.Siger(qb64=sig) for sig in xsigs])
)

exchanges.send("multisig3", "multisig", sender=m3, route="/multisig/ixn",
payload=dict(gid=icp.pre, smids=smids),
embeds=embeds, recipients=recp)

print("waiting for ixn to finish...")
while not op["done"]:
op = operations.get(op["name"])
sleep(1)

ixn = coring.Serder(ked=op["response"])
events = client.keyEvents()
log = events.get(pre=ixn.pre)
assert len(log) == 2

for event in log:
print(coring.Serder(ked=event).pretty())

(_, _, op2) = identifiers.rotate("multisig3")
rot = op2["response"]
serder = coring.Serder(ked=rot)
print(f"rotated multisig3 to {serder.sn}")

input("hit any key when other two participants have rotated their AIDs")

m3 = identifiers.get("multisig3")
agent0 = m3["state"]

keyState = client.keyStates()
op = keyState.query(pre="EJccSRTfXYF6wrUVuenAIHzwcx3hJugeiJsEKmndi5q1", sn=1)
while not op["done"]:
op = operations.get(op["name"])
sleep(1)

multisig2 = op["response"]
print(f"using key {multisig2['k'][0]}")
print(f"using dig {multisig2['n'][0]}")

op = keyState.query(pre="EKYLUMmNPZeEs77Zvclf0bSN5IN-mLfLpx2ySb-HDlk4", sn=1)
while not op["done"]:
op = operations.get(op["name"])
sleep(1)

multisig1 = op["response"]
print(f"using key {multisig1['k'][0]}")
print(f"using dig {multisig1['n'][0]}")

states = rstates = [multisig1, multisig2, agent0]

rot, rsigs, op = identifiers.rotate("multisig", states=states, rstates=rstates)
embeds = dict(
rot=eventing.messagize(serder=rot, sigers=[coring.Siger(qb64=sig) for sig in rsigs])
)

smids = [state['i'] for state in states]
recp = [state['i'] for state in [multisig1, multisig2]]

rexn, _, _ = exchanges.send("multisig3", "multisig", sender=m3, route="/multisig/rot",
payload=dict(gid=icp.pre, smids=smids, rmids=smids),
embeds=embeds, recipients=recp)

print(rexn.pretty(size=5000))
print("Waiting for multisig rotation...")
while not op["done"]:
op = operations.get(op["name"])
sleep(1)


if __name__ == "__main__":
create_multisig()
4 changes: 2 additions & 2 deletions src/signify/app/aiding.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def interact(self, name, data=None):
json[keeper.algo] = keeper.params()

res = self.client.put(f"/identifiers/{name}?type=ixn", json=json)
return res.json()
return serder, sigs, res.json()

def rotate(self, name, *, transferable=True, nsith=None, toad=None, cuts=None, adds=None,
data=None, ncode=MtrDex.Ed25519_Seed, ncount=1, ncodes=None, states=None, rstates=None):
Expand Down Expand Up @@ -181,7 +181,7 @@ def rotate(self, name, *, transferable=True, nsith=None, toad=None, cuts=None, a
json['rmids'] = [state['i'] for state in rstates]

res = self.client.put(f"/identifiers/{name}", json=json)
return res.json()
return serder, sigs, res.json()

def addEndRole(self, name, *, role=Roles.agent, eid=None, stamp=None):
hab = self.get(name)
Expand Down
6 changes: 3 additions & 3 deletions src/signify/core/keeping.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ def new(self, algo, pidx, **kwargs):
def get(self, aid):
pre = coring.Prefixer(qb64=aid["prefix"])
if keeping.Algos.salty in aid:
if "pidx" not in aid:
raise kering.ConfigurationError(f"missing pidx in {aid}")
kwargs = aid[keeping.Algos.salty]
return SaltyKeeper(salter=self.salter, pidx=aid["pidx"], **kwargs)
if "pidx" not in kwargs:
raise kering.ConfigurationError(f"missing pidx in {kwargs}")
return SaltyKeeper(salter=self.salter, **kwargs)

elif keeping.Algos.randy in aid:
kwargs = aid[keeping.Algos.randy]
Expand Down
2 changes: 1 addition & 1 deletion src/signify/peer/exchanging.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def send(self, name, topic, sender, route, payload, embeds, recipients):
rec=recipients
)

self.client.post(f"/identifiers/{name}/exchanges", json=body)
return exn, sigs, self.client.post(f"/identifiers/{name}/exchanges", json=body)

def createExchangeMessage(self, sender, route, payload, embeds):
""" Create exn message from parameters and return Serder with signatures and additional attachments.
Expand Down
2 changes: 1 addition & 1 deletion tests/app/test_aiding.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ def test_aiding_rotate():
expect(mock_client, times=1).put('/identifiers/aid1', json=expected_data).thenReturn(mock_response)
expect(mock_response, times=1).json().thenReturn({'success': 'yay'})

out = ids.rotate(name='aid1', states=[{'i': 'state 1'}, {'i': 'state 2'}],
_, _, out = ids.rotate(name='aid1', states=[{'i': 'state 1'}, {'i': 'state 2'}],
rstates=[{'i': 'rstate 1'}, {'i': 'rstate 2'}])
assert out['success'] == 'yay'

Expand Down
Loading
Loading