Skip to content

Commit 3c1993d

Browse files
authored
Create delegation-multisig.ts
1 parent 2d3443f commit 3c1993d

File tree

1 file changed

+232
-0
lines changed

1 file changed

+232
-0
lines changed
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
import { strict as assert } from 'assert';
2+
import signify from 'signify-ts';
3+
4+
const url = 'http://127.0.0.1:3901';
5+
const boot_url = 'http://127.0.0.1:3903';
6+
7+
await run();
8+
9+
async function run() {
10+
await signify.ready();
11+
// Boot three clients
12+
const client0 = await bootClient();
13+
const client1 = await bootClient();
14+
const client2 = await bootClient();
15+
16+
// Create four identifiers, one for each client
17+
let aid0 = await createAID(client0, 'delegator');
18+
let aid1 = await createAID(client1, 'member1');
19+
let aid2 = await createAID(client2, 'member2');
20+
21+
// Exchange OOBIs
22+
console.log('Resolving OOBIs');
23+
let oobi0 = await client0.oobis().get('delegator', 'agent');
24+
let oobi1 = await client1.oobis().get('member1', 'agent');
25+
let oobi2 = await client2.oobis().get('member2', 'agent');
26+
27+
let op1 = await client1.oobis().resolve(oobi0.oobis[0], 'delegator');
28+
op1 = await waitForOp(client1, op1);
29+
op1 = await client1.oobis().resolve(oobi2.oobis[0], 'member2');
30+
op1 = await waitForOp(client1, op1);
31+
console.log('Member1 resolved 2 OOBIs');
32+
33+
let op2 = await client2.oobis().resolve(oobi0.oobis[0], 'delegator');
34+
op1 = await waitForOp(client2, op1);
35+
op1 = await client2.oobis().resolve(oobi1.oobis[0], 'member1');
36+
op1 = await waitForOp(client2, op1);
37+
console.log('Member2 resolved 2 OOBIs');
38+
39+
// First member challenge the other members with a random list of words
40+
// List of words should be passed to the other members out of band
41+
// The other members should do the same challenge/response flow, not shown here for brevity
42+
const words = (await client1.challenges().generate(128)).words;
43+
console.log('Member1 generated challenge words:', words);
44+
45+
await client2.challenges().respond('member2', aid1.prefix, words);
46+
console.log('Member2 responded challenge with signed words');
47+
48+
op1 = await client1.challenges().verify('member1', aid2.prefix, words);
49+
op1 = await waitForOp(client1, op1);
50+
console.log('Member1 verified challenge response from member2');
51+
let exnwords = new signify.Serder(op1.response.exn);
52+
op1 = await client1
53+
.challenges()
54+
.responded('member1', aid2.prefix, exnwords.ked.d);
55+
console.log('Member1 marked challenge response as accepted');
56+
57+
// First member start the creation of a multisig identifier
58+
let rstates = [aid1['state'], aid2['state']];
59+
let states = rstates;
60+
let icpResult1 = await client1.identifiers().create('multisig', {
61+
algo: signify.Algos.group,
62+
mhab: aid1,
63+
isith: 2,
64+
nsith: 2,
65+
toad: 3,
66+
wits: [
67+
'BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha',
68+
'BLskRTInXnMxWaGqcpSyMgo0nYbalW99cGZESrz3zapM',
69+
'BIKKuvBwpmDVA4Ds-EpL5bt9OqPzWPja2LigFYZN2YfX',
70+
],
71+
states: states,
72+
rstates: rstates,
73+
delpre: aid0.prefix
74+
});
75+
op1 = await icpResult1.op();
76+
let serder = icpResult1.serder;
77+
78+
let sigs = icpResult1.sigs;
79+
let sigers = sigs.map((sig: any) => new signify.Siger({ qb64: sig }));
80+
let ims = signify.d(signify.messagize(serder, sigers));
81+
let atc = ims.substring(serder.size);
82+
let embeds = {
83+
icp: [serder, atc],
84+
};
85+
86+
let smids = states.map((state) => state['i']);
87+
let recp = [aid2['state']].map((state) => state['i']);
88+
89+
await client1
90+
.exchanges()
91+
.send(
92+
'member1',
93+
'multisig',
94+
aid1,
95+
'/multisig/icp',
96+
{ gid: serder.pre, smids: smids, rmids: smids },
97+
embeds,
98+
recp
99+
);
100+
console.log('Member1 initiated multisig, waiting for others to join...');
101+
102+
// Second member check notifications and join the multisig
103+
let msgSaid = await waitForMessage(client2, '/multisig/icp');
104+
console.log('Member2 received exchange message to join multisig');
105+
106+
let res = await client2.groups().getRequest(msgSaid);
107+
let exn = res[0].exn;
108+
let icp = exn.e.icp;
109+
110+
let icpResult2 = await client2.identifiers().create('multisig', {
111+
algo: signify.Algos.group,
112+
mhab: aid2,
113+
isith: icp.kt,
114+
nsith: icp.nt,
115+
toad: parseInt(icp.bt),
116+
wits: icp.b,
117+
states: states,
118+
rstates: rstates,
119+
delpre: aid0.prefix,
120+
});
121+
op2 = await icpResult2.op();
122+
serder = icpResult2.serder;
123+
sigs = icpResult2.sigs;
124+
sigers = sigs.map((sig: any) => new signify.Siger({ qb64: sig }));
125+
126+
ims = signify.d(signify.messagize(serder, sigers));
127+
atc = ims.substring(serder.size);
128+
embeds = {
129+
icp: [serder, atc],
130+
};
131+
132+
smids = exn.a.smids;
133+
recp = [aid1['state']].map((state) => state['i']);
134+
135+
await client2
136+
.exchanges()
137+
.send(
138+
'member2',
139+
'multisig',
140+
aid2,
141+
'/multisig/icp',
142+
{ gid: serder.pre, smids: smids, rmids: smids },
143+
embeds,
144+
recp
145+
);
146+
console.log('Member2 joined multisig, waiting for others...');
147+
148+
let delegatePrefix = op1.name.split('.')[1];
149+
assert.equal(op2.name.split('.')[1], delegatePrefix);
150+
console.log("Delegate's prefix:", delegatePrefix);
151+
console.log('Delegate waiting for approval...');
152+
153+
// Client 0 approves delegation
154+
const anchor = {
155+
i: delegatePrefix,
156+
s: 0,
157+
d: delegatePrefix,
158+
};
159+
await client0.identifiers().interact('delegator', anchor);
160+
console.log('Delegator approved delegation');
161+
162+
// Check for completion
163+
op1 = await waitForOp(client1, op1);
164+
op2 = await waitForOp(client2, op2);
165+
console.log('Delegated multisig created!');
166+
167+
const aid_delegate = await client1.identifiers().get('multisig');
168+
assert.equal(aid_delegate, delegatePrefix);
169+
console.log('Delegation approved for aid:', aid2.prefix);
170+
}
171+
172+
async function waitForOp(client:signify.SignifyClient, op:any) {
173+
while (!op['done']) {
174+
op = await client.operations().get(op.name);
175+
await new Promise((resolve) => setTimeout(resolve, 1000));
176+
}
177+
return op
178+
}
179+
180+
async function waitForMessage(client:signify.SignifyClient, route:string) {
181+
let msgSaid = '';
182+
while (msgSaid == '') {
183+
let notifications = await client.notifications().list();
184+
for (let notif of notifications.notes) {
185+
if (notif.a.r == route) {
186+
msgSaid = notif.a.d;
187+
await client.notifications().mark(notif.i);
188+
}
189+
}
190+
await new Promise((resolve) => setTimeout(resolve, 1000));
191+
}
192+
return msgSaid
193+
}
194+
195+
async function bootClient():Promise<signify.SignifyClient>{
196+
let bran = signify.randomPasscode();
197+
let client = new signify.SignifyClient(
198+
url,
199+
bran,
200+
signify.Tier.low,
201+
boot_url
202+
);
203+
await client.boot();
204+
await client.connect();
205+
let state = await client.state();
206+
console.log(
207+
'Client AID:',
208+
state.controller.state.i,
209+
'Agent AID: ',
210+
state.agent.i
211+
);
212+
return client
213+
}
214+
215+
async function createAID(client:signify.SignifyClient, name:string){
216+
let icpResult1 = await client.identifiers().create(name, {
217+
toad: 3,
218+
wits: [
219+
'BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha',
220+
'BLskRTInXnMxWaGqcpSyMgo0nYbalW99cGZESrz3zapM',
221+
'BIKKuvBwpmDVA4Ds-EpL5bt9OqPzWPja2LigFYZN2YfX',
222+
],
223+
});
224+
let op = await icpResult1.op();
225+
op = await waitForOp(client, op);
226+
let aid = await client.identifiers().get(name);
227+
await client
228+
.identifiers()
229+
.addEndRole(name, 'agent', client!.agent!.pre);
230+
console.log(name, "AID:", aid.prefix);
231+
return aid
232+
}

0 commit comments

Comments
 (0)