@openzeppelin/miden-multisig-client 0.15.2 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -1
- package/dist/account/builder.d.ts +2 -1
- package/dist/account/builder.d.ts.map +1 -1
- package/dist/account/builder.js +1 -0
- package/dist/account/builder.js.map +1 -1
- package/dist/account/builder.test.js +2 -2
- package/dist/account/builder.test.js.map +1 -1
- package/dist/client.d.ts +17 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +14 -7
- package/dist/client.js.map +1 -1
- package/dist/client.test.js +46 -15
- package/dist/client.test.js.map +1 -1
- package/dist/connectivity.d.ts +38 -0
- package/dist/connectivity.d.ts.map +1 -0
- package/dist/connectivity.js +97 -0
- package/dist/connectivity.js.map +1 -0
- package/dist/connectivity.test.d.ts +2 -0
- package/dist/connectivity.test.d.ts.map +1 -0
- package/dist/connectivity.test.js +61 -0
- package/dist/connectivity.test.js.map +1 -0
- package/dist/index.d.ts +14 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -3
- package/dist/index.js.map +1 -1
- package/dist/multisig.d.ts +130 -8
- package/dist/multisig.d.ts.map +1 -1
- package/dist/multisig.js +220 -24
- package/dist/multisig.js.map +1 -1
- package/dist/multisig.test.js +427 -89
- package/dist/multisig.test.js.map +1 -1
- package/dist/proposal/factory.d.ts.map +1 -1
- package/dist/proposal/factory.js +10 -0
- package/dist/proposal/factory.js.map +1 -1
- package/dist/proposal/factory.test.d.ts +2 -0
- package/dist/proposal/factory.test.d.ts.map +1 -0
- package/dist/proposal/factory.test.js +32 -0
- package/dist/proposal/factory.test.js.map +1 -0
- package/dist/proposal/metadata.d.ts.map +1 -1
- package/dist/proposal/metadata.js +12 -0
- package/dist/proposal/metadata.js.map +1 -1
- package/dist/proposal/metadata.test.js +49 -0
- package/dist/proposal/metadata.test.js.map +1 -1
- package/dist/prover/config.d.ts +16 -0
- package/dist/prover/config.d.ts.map +1 -0
- package/dist/prover/config.js +54 -0
- package/dist/prover/config.js.map +1 -0
- package/dist/prover/config.test.d.ts +2 -0
- package/dist/prover/config.test.d.ts.map +1 -0
- package/dist/prover/config.test.js +54 -0
- package/dist/prover/config.test.js.map +1 -0
- package/dist/prover/errors.d.ts +2 -0
- package/dist/prover/errors.d.ts.map +1 -0
- package/dist/prover/errors.js +158 -0
- package/dist/prover/errors.js.map +1 -0
- package/dist/prover/errors.test.d.ts +2 -0
- package/dist/prover/errors.test.d.ts.map +1 -0
- package/dist/prover/errors.test.js +24 -0
- package/dist/prover/errors.test.js.map +1 -0
- package/dist/prover/retry.d.ts +10 -0
- package/dist/prover/retry.d.ts.map +1 -0
- package/dist/prover/retry.js +32 -0
- package/dist/prover/retry.js.map +1 -0
- package/dist/prover/retry.test.d.ts +2 -0
- package/dist/prover/retry.test.d.ts.map +1 -0
- package/dist/prover/retry.test.js +20 -0
- package/dist/prover/retry.test.js.map +1 -0
- package/dist/prover/workflow.d.ts +11 -0
- package/dist/prover/workflow.d.ts.map +1 -0
- package/dist/prover/workflow.js +18 -0
- package/dist/prover/workflow.js.map +1 -0
- package/dist/prover/workflow.test.d.ts +2 -0
- package/dist/prover/workflow.test.d.ts.map +1 -0
- package/dist/prover/workflow.test.js +80 -0
- package/dist/prover/workflow.test.js.map +1 -0
- package/dist/raw-client.d.ts +2 -2
- package/dist/raw-client.d.ts.map +1 -1
- package/dist/raw-client.js +14 -4
- package/dist/raw-client.js.map +1 -1
- package/dist/raw-client.test.js +25 -3
- package/dist/raw-client.test.js.map +1 -1
- package/dist/transaction/consumeNotes.d.ts +6 -2
- package/dist/transaction/consumeNotes.d.ts.map +1 -1
- package/dist/transaction/consumeNotes.js +0 -4
- package/dist/transaction/consumeNotes.js.map +1 -1
- package/dist/transaction/options.d.ts +3 -0
- package/dist/transaction/options.d.ts.map +1 -1
- package/dist/transaction/p2id.d.ts +27 -2
- package/dist/transaction/p2id.d.ts.map +1 -1
- package/dist/transaction/p2id.js +56 -4
- package/dist/transaction/p2id.js.map +1 -1
- package/dist/transaction/p2id.test.js +66 -6
- package/dist/transaction/p2id.test.js.map +1 -1
- package/dist/transaction/summary.d.ts +2 -1
- package/dist/transaction/summary.d.ts.map +1 -1
- package/dist/transaction/summary.js.map +1 -1
- package/dist/transaction/updateGuardian.d.ts +6 -2
- package/dist/transaction/updateGuardian.d.ts.map +1 -1
- package/dist/transaction/updateGuardian.js.map +1 -1
- package/dist/transaction/updateProcedureThreshold.d.ts +7 -2
- package/dist/transaction/updateProcedureThreshold.d.ts.map +1 -1
- package/dist/transaction/updateProcedureThreshold.js.map +1 -1
- package/dist/transaction/updateSigners.d.ts +7 -2
- package/dist/transaction/updateSigners.d.ts.map +1 -1
- package/dist/transaction/updateSigners.js.map +1 -1
- package/dist/transaction.d.ts +1 -1
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +1 -1
- package/dist/transaction.js.map +1 -1
- package/dist/types/proposal.d.ts +5 -0
- package/dist/types/proposal.d.ts.map +1 -1
- package/dist/types/proposal.js +3 -0
- package/dist/types/proposal.js.map +1 -1
- package/package.json +3 -3
- package/src/account/builder.test.ts +19 -11
- package/src/account/builder.ts +2 -1
- package/src/client.test.ts +67 -15
- package/src/client.ts +35 -12
- package/src/connectivity.test.ts +67 -0
- package/src/connectivity.ts +111 -0
- package/src/index.ts +25 -1
- package/src/multisig.test.ts +526 -94
- package/src/multisig.ts +270 -25
- package/src/proposal/factory.test.ts +40 -0
- package/src/proposal/factory.ts +11 -1
- package/src/proposal/metadata.test.ts +60 -0
- package/src/proposal/metadata.ts +14 -0
- package/src/prover/config.test.ts +90 -0
- package/src/prover/config.ts +78 -0
- package/src/prover/errors.test.ts +53 -0
- package/src/prover/errors.ts +178 -0
- package/src/prover/retry.test.ts +38 -0
- package/src/prover/retry.ts +46 -0
- package/src/prover/test-node.d.ts +6 -0
- package/src/prover/workflow.test.ts +109 -0
- package/src/prover/workflow.ts +19 -0
- package/src/raw-client.test.ts +41 -3
- package/src/raw-client.ts +15 -5
- package/src/transaction/consumeNotes.ts +11 -1
- package/src/transaction/options.ts +4 -0
- package/src/transaction/p2id.test.ts +98 -8
- package/src/transaction/p2id.ts +91 -12
- package/src/transaction/summary.ts +12 -0
- package/src/transaction/updateGuardian.ts +11 -1
- package/src/transaction/updateProcedureThreshold.ts +13 -1
- package/src/transaction/updateSigners.ts +13 -1
- package/src/transaction.ts +4 -0
- package/src/types/proposal.ts +9 -0
package/src/multisig.test.ts
CHANGED
|
@@ -8,10 +8,11 @@ import {
|
|
|
8
8
|
executeForSummary,
|
|
9
9
|
} from './transaction.js';
|
|
10
10
|
|
|
11
|
-
const { mockRpcGetAccountDetails, mockAccountDeserialize, mockDetectConfig } = vi.hoisted(() => ({
|
|
11
|
+
const { mockRpcGetAccountDetails, mockAccountDeserialize, mockDetectConfig, mockNoteFileDeserialize } = vi.hoisted(() => ({
|
|
12
12
|
mockRpcGetAccountDetails: vi.fn(),
|
|
13
13
|
mockAccountDeserialize: vi.fn(),
|
|
14
14
|
mockDetectConfig: vi.fn(),
|
|
15
|
+
mockNoteFileDeserialize: vi.fn(),
|
|
15
16
|
}));
|
|
16
17
|
|
|
17
18
|
// Mock the Miden SDK
|
|
@@ -22,6 +23,18 @@ vi.mock('@miden-sdk/miden-sdk', () => ({
|
|
|
22
23
|
AccountId: {
|
|
23
24
|
fromHex: vi.fn((hex: string) => ({ toString: () => hex })),
|
|
24
25
|
},
|
|
26
|
+
NoteType: {
|
|
27
|
+
Private: 0,
|
|
28
|
+
Public: 1,
|
|
29
|
+
},
|
|
30
|
+
NoteExportFormat: {
|
|
31
|
+
Id: 0,
|
|
32
|
+
Full: 1,
|
|
33
|
+
Details: 2,
|
|
34
|
+
},
|
|
35
|
+
NoteFile: {
|
|
36
|
+
deserialize: mockNoteFileDeserialize,
|
|
37
|
+
},
|
|
25
38
|
TransactionSummary: {
|
|
26
39
|
deserialize: vi.fn().mockReturnValue({
|
|
27
40
|
toCommitment: () => ({
|
|
@@ -87,6 +100,17 @@ vi.mock('./transaction.js', () => ({
|
|
|
87
100
|
request: {},
|
|
88
101
|
salt: { toHex: () => '0x' + 'd'.repeat(64) },
|
|
89
102
|
}),
|
|
103
|
+
buildP2idNoteFromMetadata: vi.fn().mockReturnValue({
|
|
104
|
+
id: () => ({ toString: () => '0x' + 'ab'.repeat(32) }),
|
|
105
|
+
}),
|
|
106
|
+
// Mirrors the real implementations against the mocked NoteType values
|
|
107
|
+
// (Private = 0, Public = 1).
|
|
108
|
+
parseP2idNoteType: vi.fn((value?: string) => {
|
|
109
|
+
if (value === undefined || value === 'public') return 1;
|
|
110
|
+
if (value === 'private') return 0;
|
|
111
|
+
throw new Error(`unsupported metadata.noteType '${value}': expected 'public' or 'private'`);
|
|
112
|
+
}),
|
|
113
|
+
p2idNoteTypeToMetadata: vi.fn((noteType?: number) => (noteType === 0 ? 'private' : undefined)),
|
|
90
114
|
}));
|
|
91
115
|
|
|
92
116
|
vi.mock('./utils/signature.js', async () => {
|
|
@@ -119,6 +143,8 @@ vi.mock('./inspector.js', () => ({
|
|
|
119
143
|
const mockFetch = vi.fn();
|
|
120
144
|
vi.stubGlobal('fetch', mockFetch);
|
|
121
145
|
|
|
146
|
+
const MIDEN_RPC_ENDPOINT = 'https://rpc.devnet.miden.io';
|
|
147
|
+
|
|
122
148
|
function mockedAccount(commitmentHex: string, nonce = 0): any {
|
|
123
149
|
return {
|
|
124
150
|
commitment: () => ({
|
|
@@ -139,6 +165,24 @@ describe('Multisig', () => {
|
|
|
139
165
|
let mockAccount: any;
|
|
140
166
|
let mockWebClient: any;
|
|
141
167
|
|
|
168
|
+
function createTestMultisig(
|
|
169
|
+
config: ConstructorParameters<typeof Multisig>[1],
|
|
170
|
+
signer: Signer = mockSigner,
|
|
171
|
+
accountId?: string,
|
|
172
|
+
proverConfig?: ConstructorParameters<typeof Multisig>[7],
|
|
173
|
+
): Multisig {
|
|
174
|
+
return new Multisig(
|
|
175
|
+
mockAccount,
|
|
176
|
+
config,
|
|
177
|
+
guardian,
|
|
178
|
+
signer,
|
|
179
|
+
mockWebClient,
|
|
180
|
+
accountId,
|
|
181
|
+
MIDEN_RPC_ENDPOINT,
|
|
182
|
+
proverConfig,
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
142
186
|
beforeEach(() => {
|
|
143
187
|
mockFetch.mockReset();
|
|
144
188
|
vi.mocked(executeForSummary).mockResolvedValue({
|
|
@@ -196,13 +240,38 @@ describe('Multisig', () => {
|
|
|
196
240
|
submitNewTransaction: vi.fn(),
|
|
197
241
|
submitNewTransactionWithProver: vi.fn(),
|
|
198
242
|
transactions: {
|
|
199
|
-
|
|
243
|
+
executeRequest: vi.fn(),
|
|
200
244
|
},
|
|
201
245
|
getConsumableNotes: vi.fn().mockResolvedValue([]),
|
|
202
246
|
syncState: vi.fn(),
|
|
203
247
|
getAccount: vi.fn().mockResolvedValue(null),
|
|
204
248
|
newAccount: vi.fn(),
|
|
205
249
|
};
|
|
250
|
+
mockWebClient.transactions.executeRequest.mockImplementation(
|
|
251
|
+
async (accountId: unknown, request: unknown) => {
|
|
252
|
+
const result = await mockWebClient.executeTransaction(accountId, request);
|
|
253
|
+
return {
|
|
254
|
+
result,
|
|
255
|
+
prove: async (options?: { prover?: unknown }) => {
|
|
256
|
+
const proof = options?.prover === undefined
|
|
257
|
+
? await mockWebClient.proveTransaction(result)
|
|
258
|
+
: await mockWebClient.proveTransaction(result, options.prover);
|
|
259
|
+
return {
|
|
260
|
+
proof,
|
|
261
|
+
result,
|
|
262
|
+
submit: async () => {
|
|
263
|
+
const blockNumber = await mockWebClient.submitProvenTransaction(proof, result);
|
|
264
|
+
return {
|
|
265
|
+
blockNumber,
|
|
266
|
+
result,
|
|
267
|
+
apply: () => mockWebClient.applyTransaction(result, blockNumber),
|
|
268
|
+
};
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
},
|
|
274
|
+
);
|
|
206
275
|
});
|
|
207
276
|
|
|
208
277
|
describe('constructor', () => {
|
|
@@ -213,7 +282,7 @@ describe('Multisig', () => {
|
|
|
213
282
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
214
283
|
};
|
|
215
284
|
|
|
216
|
-
const multisig =
|
|
285
|
+
const multisig = createTestMultisig(config);
|
|
217
286
|
|
|
218
287
|
expect(multisig.threshold).toBe(2);
|
|
219
288
|
expect(multisig.signerCommitments).toEqual(config.signerCommitments);
|
|
@@ -229,11 +298,31 @@ describe('Multisig', () => {
|
|
|
229
298
|
};
|
|
230
299
|
|
|
231
300
|
const accountId = '0x' + 'd'.repeat(30);
|
|
232
|
-
const multisig =
|
|
301
|
+
const multisig = createTestMultisig(config, mockSigner, accountId);
|
|
233
302
|
|
|
234
303
|
expect(multisig.account).toBe(mockAccount);
|
|
235
304
|
expect(multisig.accountId).toBe(accountId);
|
|
236
305
|
});
|
|
306
|
+
|
|
307
|
+
it('should reject a missing Miden RPC endpoint immediately', () => {
|
|
308
|
+
const config = {
|
|
309
|
+
threshold: 2,
|
|
310
|
+
signerCommitments: ['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64)],
|
|
311
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
expect(
|
|
315
|
+
() => new Multisig(
|
|
316
|
+
mockAccount,
|
|
317
|
+
config,
|
|
318
|
+
guardian,
|
|
319
|
+
mockSigner,
|
|
320
|
+
mockWebClient,
|
|
321
|
+
undefined,
|
|
322
|
+
undefined as unknown as string
|
|
323
|
+
)
|
|
324
|
+
).toThrow('missing required configuration: midenRpcEndpoint');
|
|
325
|
+
});
|
|
237
326
|
});
|
|
238
327
|
|
|
239
328
|
describe('accountId', () => {
|
|
@@ -244,7 +333,7 @@ describe('Multisig', () => {
|
|
|
244
333
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
245
334
|
};
|
|
246
335
|
|
|
247
|
-
const multisig =
|
|
336
|
+
const multisig = createTestMultisig(config);
|
|
248
337
|
expect(multisig.accountId).toBe('0x' + 'a'.repeat(30));
|
|
249
338
|
});
|
|
250
339
|
|
|
@@ -256,7 +345,7 @@ describe('Multisig', () => {
|
|
|
256
345
|
};
|
|
257
346
|
|
|
258
347
|
const accountId = '0x' + 'e'.repeat(30);
|
|
259
|
-
const multisig =
|
|
348
|
+
const multisig = createTestMultisig(config, mockSigner, accountId);
|
|
260
349
|
expect(multisig.accountId).toBe(accountId);
|
|
261
350
|
});
|
|
262
351
|
});
|
|
@@ -269,7 +358,7 @@ describe('Multisig', () => {
|
|
|
269
358
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
270
359
|
};
|
|
271
360
|
|
|
272
|
-
const multisig =
|
|
361
|
+
const multisig = createTestMultisig(config);
|
|
273
362
|
expect(multisig.signerCommitment).toBe(mockSigner.commitment);
|
|
274
363
|
});
|
|
275
364
|
});
|
|
@@ -282,7 +371,7 @@ describe('Multisig', () => {
|
|
|
282
371
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
283
372
|
};
|
|
284
373
|
|
|
285
|
-
const multisig =
|
|
374
|
+
const multisig = createTestMultisig(config);
|
|
286
375
|
|
|
287
376
|
mockFetch.mockResolvedValueOnce({
|
|
288
377
|
ok: true,
|
|
@@ -503,7 +592,7 @@ describe('Multisig', () => {
|
|
|
503
592
|
expect(mockWebClient.newAccount).not.toHaveBeenCalled();
|
|
504
593
|
});
|
|
505
594
|
|
|
506
|
-
it('
|
|
595
|
+
it('keeps local state and refreshes config from it when GUARDIAN nonce is behind local', async () => {
|
|
507
596
|
const config = {
|
|
508
597
|
threshold: 1,
|
|
509
598
|
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
@@ -520,7 +609,8 @@ describe('Multisig', () => {
|
|
|
520
609
|
'https://rpc.devnet.miden.io'
|
|
521
610
|
);
|
|
522
611
|
|
|
523
|
-
|
|
612
|
+
const localAccount = mockedAccount('0x' + 'a'.repeat(64), 3);
|
|
613
|
+
mockWebClient.getAccount.mockResolvedValueOnce(localAccount);
|
|
524
614
|
mockAccountDeserialize.mockReturnValueOnce(mockedAccount('0x' + 'b'.repeat(64), 2));
|
|
525
615
|
mockFetch.mockResolvedValueOnce({
|
|
526
616
|
ok: true,
|
|
@@ -532,11 +622,24 @@ describe('Multisig', () => {
|
|
|
532
622
|
updated_at: '2024-01-02T00:00:00Z',
|
|
533
623
|
}),
|
|
534
624
|
});
|
|
625
|
+
mockDetectConfig.mockReturnValueOnce({
|
|
626
|
+
threshold: 2,
|
|
627
|
+
numSigners: 2,
|
|
628
|
+
signerCommitments: ['0x' + '1'.repeat(64), '0x' + '2'.repeat(64)],
|
|
629
|
+
guardianEnabled: true,
|
|
630
|
+
guardianCommitment: '0x' + 'd'.repeat(64),
|
|
631
|
+
vaultBalances: [],
|
|
632
|
+
procedureThresholds: new Map(),
|
|
633
|
+
});
|
|
535
634
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
);
|
|
635
|
+
// GUARDIAN behind local (nonce 2 < 3): no throw, local kept, no overwrite,
|
|
636
|
+
// and the decision needs no on-chain round-trip.
|
|
637
|
+
await expect(multisig.syncState()).resolves.toBeDefined();
|
|
539
638
|
expect(mockWebClient.newAccount).not.toHaveBeenCalled();
|
|
639
|
+
expect(mockRpcGetAccountDetails).not.toHaveBeenCalled();
|
|
640
|
+
// Config refreshed from the authoritative local account (UI unfreezes).
|
|
641
|
+
expect(multisig.account).toBe(localAccount);
|
|
642
|
+
expect(multisig.threshold).toBe(2);
|
|
540
643
|
});
|
|
541
644
|
|
|
542
645
|
it('should throw when incoming state nonce equals local nonce but commitment differs', async () => {
|
|
@@ -570,10 +673,49 @@ describe('Multisig', () => {
|
|
|
570
673
|
});
|
|
571
674
|
|
|
572
675
|
await expect(multisig.syncState()).rejects.toThrow(
|
|
573
|
-
'incoming nonce 2
|
|
676
|
+
'incoming nonce 2 equals local nonce 2 but commitments differ'
|
|
574
677
|
);
|
|
575
678
|
expect(mockWebClient.newAccount).not.toHaveBeenCalled();
|
|
576
679
|
});
|
|
680
|
+
|
|
681
|
+
it('unfreezes Multisig.account after execute when GUARDIAN still lags by one nonce (regression, #343)', async () => {
|
|
682
|
+
const config = {
|
|
683
|
+
threshold: 1,
|
|
684
|
+
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
685
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
686
|
+
};
|
|
687
|
+
|
|
688
|
+
const multisig = new Multisig(
|
|
689
|
+
mockAccount,
|
|
690
|
+
config,
|
|
691
|
+
guardian,
|
|
692
|
+
mockSigner,
|
|
693
|
+
mockWebClient,
|
|
694
|
+
undefined,
|
|
695
|
+
'https://rpc.devnet.miden.io'
|
|
696
|
+
);
|
|
697
|
+
|
|
698
|
+
// Post-execute: local advanced to nonce 1, GUARDIAN still reports nonce 0
|
|
699
|
+
// (candidate not canonicalized yet). Before the fix this threw and left
|
|
700
|
+
// Multisig.account frozen at the pre-execute snapshot.
|
|
701
|
+
const localAccount = mockedAccount('0x' + 'a'.repeat(64), 1);
|
|
702
|
+
mockWebClient.getAccount.mockResolvedValueOnce(localAccount);
|
|
703
|
+
mockAccountDeserialize.mockReturnValueOnce(mockedAccount('0x' + 'b'.repeat(64), 0));
|
|
704
|
+
mockFetch.mockResolvedValueOnce({
|
|
705
|
+
ok: true,
|
|
706
|
+
json: async () => ({
|
|
707
|
+
account_id: multisig.accountId,
|
|
708
|
+
commitment: '0x' + 'b'.repeat(64),
|
|
709
|
+
state_json: { data: 'AQID' },
|
|
710
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
711
|
+
updated_at: '2024-01-02T00:00:00Z',
|
|
712
|
+
}),
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
await expect(multisig.syncState()).resolves.toBeDefined();
|
|
716
|
+
expect(mockWebClient.newAccount).not.toHaveBeenCalled();
|
|
717
|
+
expect(multisig.account).toBe(localAccount);
|
|
718
|
+
});
|
|
577
719
|
});
|
|
578
720
|
|
|
579
721
|
describe('verifyStateCommitment', () => {
|
|
@@ -662,7 +804,7 @@ describe('Multisig', () => {
|
|
|
662
804
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
663
805
|
};
|
|
664
806
|
|
|
665
|
-
const multisig =
|
|
807
|
+
const multisig = createTestMultisig(config);
|
|
666
808
|
|
|
667
809
|
mockFetch.mockResolvedValueOnce({
|
|
668
810
|
ok: true,
|
|
@@ -690,7 +832,7 @@ describe('Multisig', () => {
|
|
|
690
832
|
};
|
|
691
833
|
|
|
692
834
|
guardian.setSigner(ecdsaSigner);
|
|
693
|
-
const multisig =
|
|
835
|
+
const multisig = createTestMultisig(config, ecdsaSigner);
|
|
694
836
|
|
|
695
837
|
mockFetch.mockResolvedValueOnce({
|
|
696
838
|
ok: true,
|
|
@@ -726,6 +868,7 @@ describe('Multisig', () => {
|
|
|
726
868
|
mockSigner,
|
|
727
869
|
mockWebClient,
|
|
728
870
|
'0x' + 'e'.repeat(30),
|
|
871
|
+
MIDEN_RPC_ENDPOINT,
|
|
729
872
|
);
|
|
730
873
|
|
|
731
874
|
mockFetch.mockResolvedValueOnce({
|
|
@@ -746,7 +889,7 @@ describe('Multisig', () => {
|
|
|
746
889
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
747
890
|
};
|
|
748
891
|
|
|
749
|
-
const multisig =
|
|
892
|
+
const multisig = createTestMultisig(config);
|
|
750
893
|
|
|
751
894
|
mockFetch.mockResolvedValueOnce({
|
|
752
895
|
ok: true,
|
|
@@ -768,7 +911,7 @@ describe('Multisig', () => {
|
|
|
768
911
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
769
912
|
};
|
|
770
913
|
|
|
771
|
-
const multisig =
|
|
914
|
+
const multisig = createTestMultisig(config);
|
|
772
915
|
|
|
773
916
|
const mockProposals = [
|
|
774
917
|
{
|
|
@@ -819,7 +962,7 @@ describe('Multisig', () => {
|
|
|
819
962
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
820
963
|
};
|
|
821
964
|
|
|
822
|
-
const multisig =
|
|
965
|
+
const multisig = createTestMultisig(config);
|
|
823
966
|
|
|
824
967
|
const mockProposals = [
|
|
825
968
|
{
|
|
@@ -868,7 +1011,7 @@ describe('Multisig', () => {
|
|
|
868
1011
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
869
1012
|
};
|
|
870
1013
|
|
|
871
|
-
const multisig =
|
|
1014
|
+
const multisig = createTestMultisig(config);
|
|
872
1015
|
|
|
873
1016
|
mockFetch.mockResolvedValueOnce({
|
|
874
1017
|
ok: true,
|
|
@@ -917,7 +1060,7 @@ describe('Multisig', () => {
|
|
|
917
1060
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
918
1061
|
};
|
|
919
1062
|
|
|
920
|
-
const multisig =
|
|
1063
|
+
const multisig = createTestMultisig(config);
|
|
921
1064
|
|
|
922
1065
|
const mockProposals = [
|
|
923
1066
|
{
|
|
@@ -964,7 +1107,7 @@ describe('Multisig', () => {
|
|
|
964
1107
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
965
1108
|
};
|
|
966
1109
|
|
|
967
|
-
const multisig =
|
|
1110
|
+
const multisig = createTestMultisig(config);
|
|
968
1111
|
|
|
969
1112
|
const mockProposals = [
|
|
970
1113
|
{
|
|
@@ -1018,7 +1161,7 @@ describe('Multisig', () => {
|
|
|
1018
1161
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1019
1162
|
};
|
|
1020
1163
|
|
|
1021
|
-
const multisig =
|
|
1164
|
+
const multisig = createTestMultisig(config);
|
|
1022
1165
|
expect(multisig.listProposals()).toEqual([]);
|
|
1023
1166
|
});
|
|
1024
1167
|
});
|
|
@@ -1031,7 +1174,7 @@ describe('Multisig', () => {
|
|
|
1031
1174
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1032
1175
|
};
|
|
1033
1176
|
|
|
1034
|
-
const multisig =
|
|
1177
|
+
const multisig = createTestMultisig(config);
|
|
1035
1178
|
|
|
1036
1179
|
const mockDelta = {
|
|
1037
1180
|
account_id: '0x' + 'a'.repeat(30),
|
|
@@ -1075,7 +1218,7 @@ describe('Multisig', () => {
|
|
|
1075
1218
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1076
1219
|
};
|
|
1077
1220
|
|
|
1078
|
-
const multisig =
|
|
1221
|
+
const multisig = createTestMultisig(config);
|
|
1079
1222
|
|
|
1080
1223
|
const mockDelta = {
|
|
1081
1224
|
account_id: '0x' + 'a'.repeat(30),
|
|
@@ -1120,7 +1263,7 @@ describe('Multisig', () => {
|
|
|
1120
1263
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1121
1264
|
};
|
|
1122
1265
|
|
|
1123
|
-
const multisig =
|
|
1266
|
+
const multisig = createTestMultisig(config);
|
|
1124
1267
|
|
|
1125
1268
|
const mockDelta = {
|
|
1126
1269
|
account_id: '0x' + 'a'.repeat(30),
|
|
@@ -1179,7 +1322,7 @@ describe('Multisig', () => {
|
|
|
1179
1322
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1180
1323
|
};
|
|
1181
1324
|
|
|
1182
|
-
const multisig =
|
|
1325
|
+
const multisig = createTestMultisig(config);
|
|
1183
1326
|
|
|
1184
1327
|
const mockDelta = {
|
|
1185
1328
|
account_id: '0x' + 'a'.repeat(30),
|
|
@@ -1216,6 +1359,230 @@ describe('Multisig', () => {
|
|
|
1216
1359
|
|
|
1217
1360
|
expect(proposal.metadata.description).toBe('Send 100 of asset 0xfaucet... to 0xrecipien...');
|
|
1218
1361
|
});
|
|
1362
|
+
|
|
1363
|
+
it('threads a private noteType into the request and wire metadata (issue #322)', async () => {
|
|
1364
|
+
const { executeForSummary, buildP2idTransactionRequest } = await import('./transaction.js');
|
|
1365
|
+
const { NoteType } = await import('@miden-sdk/miden-sdk');
|
|
1366
|
+
vi.mocked(executeForSummary).mockResolvedValue({
|
|
1367
|
+
toCommitment: () => ({
|
|
1368
|
+
toHex: () => '0x' + 'c'.repeat(64),
|
|
1369
|
+
}),
|
|
1370
|
+
serialize: () => new Uint8Array([1, 2, 3]),
|
|
1371
|
+
} as any);
|
|
1372
|
+
|
|
1373
|
+
const config = {
|
|
1374
|
+
threshold: 1,
|
|
1375
|
+
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
1376
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1377
|
+
};
|
|
1378
|
+
|
|
1379
|
+
const multisig = createTestMultisig(config);
|
|
1380
|
+
|
|
1381
|
+
const mockDelta = {
|
|
1382
|
+
account_id: '0x' + 'a'.repeat(30),
|
|
1383
|
+
nonce: 1,
|
|
1384
|
+
prev_commitment: '0x' + 'b'.repeat(64),
|
|
1385
|
+
delta_payload: {
|
|
1386
|
+
tx_summary: { data: 'AQID' },
|
|
1387
|
+
signatures: [],
|
|
1388
|
+
metadata: {
|
|
1389
|
+
proposal_type: 'p2id',
|
|
1390
|
+
recipient_id: '0xrecipient',
|
|
1391
|
+
faucet_id: '0xfaucet',
|
|
1392
|
+
amount: '100',
|
|
1393
|
+
note_type: 'private',
|
|
1394
|
+
description: '',
|
|
1395
|
+
},
|
|
1396
|
+
},
|
|
1397
|
+
status: {
|
|
1398
|
+
status: 'pending',
|
|
1399
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
1400
|
+
proposer_id: '0x' + 'c'.repeat(64),
|
|
1401
|
+
cosigner_sigs: [],
|
|
1402
|
+
},
|
|
1403
|
+
};
|
|
1404
|
+
|
|
1405
|
+
mockFetch.mockResolvedValueOnce({
|
|
1406
|
+
ok: true,
|
|
1407
|
+
json: async () => ({
|
|
1408
|
+
delta: mockDelta,
|
|
1409
|
+
commitment: '0x' + 'c'.repeat(64),
|
|
1410
|
+
}),
|
|
1411
|
+
});
|
|
1412
|
+
|
|
1413
|
+
const proposal = await multisig.createP2idProposal('0xrecipient', '0xfaucet', 100n, 1, {
|
|
1414
|
+
noteType: NoteType.Private,
|
|
1415
|
+
});
|
|
1416
|
+
|
|
1417
|
+
// Propose path builds the private note...
|
|
1418
|
+
expect(vi.mocked(buildP2idTransactionRequest)).toHaveBeenCalledWith(
|
|
1419
|
+
expect.any(String),
|
|
1420
|
+
'0xrecipient',
|
|
1421
|
+
'0xfaucet',
|
|
1422
|
+
100n,
|
|
1423
|
+
expect.anything(),
|
|
1424
|
+
{ noteType: NoteType.Private },
|
|
1425
|
+
);
|
|
1426
|
+
// ...and the rebuild-from-metadata path parses note_type back to Private.
|
|
1427
|
+
const lastCall = vi.mocked(buildP2idTransactionRequest).mock.calls.at(-1)!;
|
|
1428
|
+
expect(lastCall[5]).toMatchObject({ noteType: NoteType.Private });
|
|
1429
|
+
|
|
1430
|
+
// The pushed wire metadata carries note_type so cosigners rebuild the
|
|
1431
|
+
// same private note at verification/execution.
|
|
1432
|
+
const pushBody = JSON.parse(mockFetch.mock.calls.at(-1)![1].body as string);
|
|
1433
|
+
expect(pushBody.delta_payload.metadata.note_type).toBe('private');
|
|
1434
|
+
|
|
1435
|
+
expect(proposal.metadata.proposalType).toBe('p2id');
|
|
1436
|
+
expect((proposal.metadata as { noteType?: string }).noteType).toBe('private');
|
|
1437
|
+
});
|
|
1438
|
+
});
|
|
1439
|
+
|
|
1440
|
+
describe('exportNoteToBytes / importNoteFromBytes (issue #356)', () => {
|
|
1441
|
+
const config = {
|
|
1442
|
+
threshold: 1,
|
|
1443
|
+
signerCommitments: ['0x' + '1'.repeat(64)],
|
|
1444
|
+
guardianCommitment: '0x' + '3'.repeat(64),
|
|
1445
|
+
};
|
|
1446
|
+
|
|
1447
|
+
it('exports the full note with proof when the inclusion proof is known', async () => {
|
|
1448
|
+
const noteFile = { serialize: () => new Uint8Array([9, 9, 9]) };
|
|
1449
|
+
mockWebClient.getOutputNote = vi.fn().mockResolvedValue({
|
|
1450
|
+
inclusionProof: () => ({}),
|
|
1451
|
+
});
|
|
1452
|
+
mockWebClient.exportNoteFile = vi.fn().mockResolvedValue(noteFile);
|
|
1453
|
+
|
|
1454
|
+
const multisig = createTestMultisig(config);
|
|
1455
|
+
const bytes = await multisig.exportNoteToBytes('0x' + 'ab'.repeat(32));
|
|
1456
|
+
|
|
1457
|
+
expect(bytes).toEqual(new Uint8Array([9, 9, 9]));
|
|
1458
|
+
// NoteExportFormat.Full = 1 in the SDK mock
|
|
1459
|
+
expect(mockWebClient.exportNoteFile).toHaveBeenCalledWith('0x' + 'ab'.repeat(32), 1);
|
|
1460
|
+
});
|
|
1461
|
+
|
|
1462
|
+
it('falls back to a details-only export before the note commits on chain', async () => {
|
|
1463
|
+
const noteFile = { serialize: () => new Uint8Array([7]) };
|
|
1464
|
+
mockWebClient.getOutputNote = vi.fn().mockResolvedValue({
|
|
1465
|
+
inclusionProof: () => undefined,
|
|
1466
|
+
});
|
|
1467
|
+
mockWebClient.exportNoteFile = vi.fn().mockResolvedValue(noteFile);
|
|
1468
|
+
|
|
1469
|
+
const multisig = createTestMultisig(config);
|
|
1470
|
+
await multisig.exportNoteToBytes(' 0x' + 'ab'.repeat(32) + ' ');
|
|
1471
|
+
|
|
1472
|
+
// NoteExportFormat.Details = 2 in the SDK mock; the id is trimmed
|
|
1473
|
+
expect(mockWebClient.exportNoteFile).toHaveBeenCalledWith('0x' + 'ab'.repeat(32), 2);
|
|
1474
|
+
});
|
|
1475
|
+
|
|
1476
|
+
it('rejects exporting a note the local store does not know', async () => {
|
|
1477
|
+
mockWebClient.getOutputNote = vi.fn().mockRejectedValue(new Error('no such note'));
|
|
1478
|
+
mockWebClient.exportNoteFile = vi.fn();
|
|
1479
|
+
|
|
1480
|
+
const multisig = createTestMultisig(config);
|
|
1481
|
+
await expect(multisig.exportNoteToBytes('0x' + 'ab'.repeat(32))).rejects.toThrow(
|
|
1482
|
+
/not found in the local store/,
|
|
1483
|
+
);
|
|
1484
|
+
expect(mockWebClient.exportNoteFile).not.toHaveBeenCalled();
|
|
1485
|
+
});
|
|
1486
|
+
|
|
1487
|
+
it('rejects exporting when the store resolves no record', async () => {
|
|
1488
|
+
mockWebClient.getOutputNote = vi.fn().mockResolvedValue(undefined);
|
|
1489
|
+
mockWebClient.exportNoteFile = vi.fn();
|
|
1490
|
+
|
|
1491
|
+
const multisig = createTestMultisig(config);
|
|
1492
|
+
await expect(multisig.exportNoteToBytes('0x' + 'ab'.repeat(32))).rejects.toThrow(
|
|
1493
|
+
/not found in the local store/,
|
|
1494
|
+
);
|
|
1495
|
+
expect(mockWebClient.exportNoteFile).not.toHaveBeenCalled();
|
|
1496
|
+
});
|
|
1497
|
+
|
|
1498
|
+
it('imports note file bytes and returns the resolved identifier', async () => {
|
|
1499
|
+
const decoded = { marker: 'note-file' };
|
|
1500
|
+
mockNoteFileDeserialize.mockReturnValue(decoded);
|
|
1501
|
+
mockWebClient.importNoteFile = vi.fn().mockResolvedValue('0x' + 'cd'.repeat(32));
|
|
1502
|
+
|
|
1503
|
+
const multisig = createTestMultisig(config);
|
|
1504
|
+
const noteId = await multisig.importNoteFromBytes(new Uint8Array([1, 2, 3]));
|
|
1505
|
+
|
|
1506
|
+
expect(mockNoteFileDeserialize).toHaveBeenCalledWith(new Uint8Array([1, 2, 3]));
|
|
1507
|
+
expect(mockWebClient.importNoteFile).toHaveBeenCalledWith(decoded);
|
|
1508
|
+
expect(noteId).toBe('0x' + 'cd'.repeat(32));
|
|
1509
|
+
});
|
|
1510
|
+
|
|
1511
|
+
it('rejects bytes that do not decode as a note file', async () => {
|
|
1512
|
+
mockNoteFileDeserialize.mockImplementation(() => {
|
|
1513
|
+
throw new Error('bad bytes');
|
|
1514
|
+
});
|
|
1515
|
+
mockWebClient.importNoteFile = vi.fn();
|
|
1516
|
+
|
|
1517
|
+
const multisig = createTestMultisig(config);
|
|
1518
|
+
await expect(multisig.importNoteFromBytes(new Uint8Array([0]))).rejects.toThrow(
|
|
1519
|
+
/failed to decode note file: bad bytes/,
|
|
1520
|
+
);
|
|
1521
|
+
expect(mockWebClient.importNoteFile).not.toHaveBeenCalled();
|
|
1522
|
+
});
|
|
1523
|
+
});
|
|
1524
|
+
|
|
1525
|
+
describe('exportNoteToFile / importNoteFromFile (issue #356)', () => {
|
|
1526
|
+
const config = {
|
|
1527
|
+
threshold: 1,
|
|
1528
|
+
signerCommitments: ['0x' + '1'.repeat(64)],
|
|
1529
|
+
guardianCommitment: '0x' + '3'.repeat(64),
|
|
1530
|
+
};
|
|
1531
|
+
|
|
1532
|
+
it('rejects exportNoteToFile outside a browser environment', async () => {
|
|
1533
|
+
const multisig = createTestMultisig(config);
|
|
1534
|
+
await expect(multisig.exportNoteToFile('0x' + 'ab'.repeat(32))).rejects.toThrow(
|
|
1535
|
+
/requires a browser environment/,
|
|
1536
|
+
);
|
|
1537
|
+
});
|
|
1538
|
+
|
|
1539
|
+
it('imports from a File/Blob by delegating to importNoteFromBytes', async () => {
|
|
1540
|
+
const decoded = { marker: 'note-file' };
|
|
1541
|
+
mockNoteFileDeserialize.mockReturnValue(decoded);
|
|
1542
|
+
mockWebClient.importNoteFile = vi.fn().mockResolvedValue('0x' + 'cd'.repeat(32));
|
|
1543
|
+
|
|
1544
|
+
const multisig = createTestMultisig(config);
|
|
1545
|
+
const noteId = await multisig.importNoteFromFile(new Blob([new Uint8Array([1, 2, 3])]));
|
|
1546
|
+
|
|
1547
|
+
expect(mockNoteFileDeserialize).toHaveBeenCalledWith(new Uint8Array([1, 2, 3]));
|
|
1548
|
+
expect(noteId).toBe('0x' + 'cd'.repeat(32));
|
|
1549
|
+
});
|
|
1550
|
+
});
|
|
1551
|
+
|
|
1552
|
+
describe('getP2idNoteId (issue #356)', () => {
|
|
1553
|
+
const config = {
|
|
1554
|
+
threshold: 1,
|
|
1555
|
+
signerCommitments: ['0x' + '1'.repeat(64)],
|
|
1556
|
+
guardianCommitment: '0x' + '3'.repeat(64),
|
|
1557
|
+
};
|
|
1558
|
+
|
|
1559
|
+
it('computes the deterministic note ID from p2id proposal metadata', async () => {
|
|
1560
|
+
const multisig = createTestMultisig(config);
|
|
1561
|
+
const proposal = {
|
|
1562
|
+
metadata: {
|
|
1563
|
+
proposalType: 'p2id',
|
|
1564
|
+
recipientId: '0x' + 'b'.repeat(30),
|
|
1565
|
+
faucetId: '0x' + 'c'.repeat(30),
|
|
1566
|
+
amount: '100',
|
|
1567
|
+
saltHex: '0x' + 'd'.repeat(64),
|
|
1568
|
+
noteType: 'private',
|
|
1569
|
+
},
|
|
1570
|
+
} as any;
|
|
1571
|
+
|
|
1572
|
+
const noteId = await multisig.getP2idNoteId(proposal);
|
|
1573
|
+
expect(noteId).toBe('0x' + 'ab'.repeat(32));
|
|
1574
|
+
});
|
|
1575
|
+
|
|
1576
|
+
it('rejects non-p2id proposals', async () => {
|
|
1577
|
+
const multisig = createTestMultisig(config);
|
|
1578
|
+
const proposal = {
|
|
1579
|
+
metadata: { proposalType: 'consume_notes' },
|
|
1580
|
+
} as any;
|
|
1581
|
+
|
|
1582
|
+
await expect(multisig.getP2idNoteId(proposal)).rejects.toThrow(
|
|
1583
|
+
/requires a P2ID proposal/,
|
|
1584
|
+
);
|
|
1585
|
+
});
|
|
1219
1586
|
});
|
|
1220
1587
|
|
|
1221
1588
|
describe('createChangeThresholdProposal', () => {
|
|
@@ -1269,7 +1636,7 @@ describe('Multisig', () => {
|
|
|
1269
1636
|
}),
|
|
1270
1637
|
});
|
|
1271
1638
|
|
|
1272
|
-
const multisig =
|
|
1639
|
+
const multisig = createTestMultisig(config, ecdsaSigner);
|
|
1273
1640
|
await multisig.createChangeThresholdProposal(2, 1);
|
|
1274
1641
|
|
|
1275
1642
|
expect(buildUpdateSignersTransactionRequest).toHaveBeenCalledWith(
|
|
@@ -1293,7 +1660,7 @@ describe('Multisig', () => {
|
|
|
1293
1660
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1294
1661
|
};
|
|
1295
1662
|
|
|
1296
|
-
const multisig =
|
|
1663
|
+
const multisig = createTestMultisig(config);
|
|
1297
1664
|
const newGuardianPubkey = '0x' + '1'.repeat(64);
|
|
1298
1665
|
|
|
1299
1666
|
mockFetch.mockResolvedValueOnce({
|
|
@@ -1342,7 +1709,7 @@ describe('Multisig', () => {
|
|
|
1342
1709
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1343
1710
|
};
|
|
1344
1711
|
|
|
1345
|
-
const multisig =
|
|
1712
|
+
const multisig = createTestMultisig(config);
|
|
1346
1713
|
|
|
1347
1714
|
mockFetch.mockResolvedValueOnce({
|
|
1348
1715
|
ok: true,
|
|
@@ -1372,7 +1739,7 @@ describe('Multisig', () => {
|
|
|
1372
1739
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1373
1740
|
};
|
|
1374
1741
|
|
|
1375
|
-
const multisig =
|
|
1742
|
+
const multisig = createTestMultisig(config, ecdsaSigner);
|
|
1376
1743
|
const newGuardianCommitment = '0x' + '1'.repeat(64);
|
|
1377
1744
|
|
|
1378
1745
|
mockFetch.mockResolvedValueOnce({
|
|
@@ -1427,7 +1794,7 @@ describe('Multisig', () => {
|
|
|
1427
1794
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1428
1795
|
};
|
|
1429
1796
|
|
|
1430
|
-
const multisig =
|
|
1797
|
+
const multisig = createTestMultisig(config);
|
|
1431
1798
|
|
|
1432
1799
|
const mockDelta = {
|
|
1433
1800
|
account_id: '0x' + 'a'.repeat(30),
|
|
@@ -1495,7 +1862,7 @@ describe('Multisig', () => {
|
|
|
1495
1862
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1496
1863
|
};
|
|
1497
1864
|
|
|
1498
|
-
const multisig =
|
|
1865
|
+
const multisig = createTestMultisig(config, ecdsaSigner);
|
|
1499
1866
|
|
|
1500
1867
|
const mockDelta = {
|
|
1501
1868
|
account_id: '0x' + 'a'.repeat(30),
|
|
@@ -1546,7 +1913,7 @@ describe('Multisig', () => {
|
|
|
1546
1913
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1547
1914
|
};
|
|
1548
1915
|
|
|
1549
|
-
const multisig =
|
|
1916
|
+
const multisig = createTestMultisig(config);
|
|
1550
1917
|
|
|
1551
1918
|
// First create a proposal
|
|
1552
1919
|
const mockDelta = {
|
|
@@ -1624,7 +1991,7 @@ describe('Multisig', () => {
|
|
|
1624
1991
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1625
1992
|
};
|
|
1626
1993
|
|
|
1627
|
-
const multisig =
|
|
1994
|
+
const multisig = createTestMultisig(config);
|
|
1628
1995
|
|
|
1629
1996
|
const mockDelta = {
|
|
1630
1997
|
account_id: '0x' + 'a'.repeat(30),
|
|
@@ -1675,7 +2042,7 @@ describe('Multisig', () => {
|
|
|
1675
2042
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1676
2043
|
};
|
|
1677
2044
|
|
|
1678
|
-
const multisig =
|
|
2045
|
+
const multisig = createTestMultisig(config);
|
|
1679
2046
|
const proposalId = '0x' + 'd'.repeat(64);
|
|
1680
2047
|
|
|
1681
2048
|
mockFetch.mockResolvedValueOnce({
|
|
@@ -1722,7 +2089,7 @@ describe('Multisig', () => {
|
|
|
1722
2089
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1723
2090
|
};
|
|
1724
2091
|
|
|
1725
|
-
const multisig =
|
|
2092
|
+
const multisig = createTestMultisig(config);
|
|
1726
2093
|
|
|
1727
2094
|
vi.mocked(executeForSummary).mockResolvedValueOnce({
|
|
1728
2095
|
toCommitment: () => ({
|
|
@@ -1758,7 +2125,7 @@ describe('Multisig', () => {
|
|
|
1758
2125
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1759
2126
|
};
|
|
1760
2127
|
|
|
1761
|
-
const multisig =
|
|
2128
|
+
const multisig = createTestMultisig(config);
|
|
1762
2129
|
|
|
1763
2130
|
vi.mocked(executeForSummary).mockResolvedValueOnce({
|
|
1764
2131
|
toCommitment: () => ({
|
|
@@ -1809,7 +2176,7 @@ describe('Multisig', () => {
|
|
|
1809
2176
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1810
2177
|
};
|
|
1811
2178
|
|
|
1812
|
-
const multisig =
|
|
2179
|
+
const multisig = createTestMultisig(config);
|
|
1813
2180
|
|
|
1814
2181
|
const mockProposals = [
|
|
1815
2182
|
{
|
|
@@ -1862,7 +2229,7 @@ describe('Multisig', () => {
|
|
|
1862
2229
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1863
2230
|
};
|
|
1864
2231
|
|
|
1865
|
-
const multisig =
|
|
2232
|
+
const multisig = createTestMultisig(config);
|
|
1866
2233
|
const publicKey = '0x' + 'd'.repeat(66);
|
|
1867
2234
|
|
|
1868
2235
|
mockFetch.mockResolvedValueOnce({
|
|
@@ -1920,13 +2287,20 @@ describe('Multisig', () => {
|
|
|
1920
2287
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1921
2288
|
};
|
|
1922
2289
|
|
|
1923
|
-
const multisig =
|
|
2290
|
+
const multisig = createTestMultisig(config);
|
|
1924
2291
|
|
|
1925
2292
|
mockFetch.mockResolvedValueOnce({
|
|
1926
2293
|
ok: false,
|
|
1927
2294
|
status: 404,
|
|
1928
2295
|
statusText: 'Not Found',
|
|
1929
|
-
|
|
2296
|
+
// Feature 009: only a conforming { code, message, meta } envelope is
|
|
2297
|
+
// folded into the error message; raw text bodies are dropped.
|
|
2298
|
+
text: async () =>
|
|
2299
|
+
JSON.stringify({
|
|
2300
|
+
code: 'GUARDIAN_PROPOSAL_NOT_FOUND',
|
|
2301
|
+
message: 'Proposal not found',
|
|
2302
|
+
meta: { retryable: false },
|
|
2303
|
+
}),
|
|
1930
2304
|
});
|
|
1931
2305
|
|
|
1932
2306
|
await expect(
|
|
@@ -1943,7 +2317,7 @@ describe('Multisig', () => {
|
|
|
1943
2317
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1944
2318
|
};
|
|
1945
2319
|
|
|
1946
|
-
const multisig =
|
|
2320
|
+
const multisig = createTestMultisig(config);
|
|
1947
2321
|
|
|
1948
2322
|
const exported = {
|
|
1949
2323
|
accountId: multisig.accountId,
|
|
@@ -1976,7 +2350,7 @@ describe('Multisig', () => {
|
|
|
1976
2350
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1977
2351
|
};
|
|
1978
2352
|
|
|
1979
|
-
const multisig =
|
|
2353
|
+
const multisig = createTestMultisig(config);
|
|
1980
2354
|
const publicKey = '0x' + 'd'.repeat(66);
|
|
1981
2355
|
|
|
1982
2356
|
const proposal = await multisig.importProposal(
|
|
@@ -2023,7 +2397,7 @@ describe('Multisig', () => {
|
|
|
2023
2397
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2024
2398
|
};
|
|
2025
2399
|
|
|
2026
|
-
const multisig =
|
|
2400
|
+
const multisig = createTestMultisig(config);
|
|
2027
2401
|
|
|
2028
2402
|
await expect(
|
|
2029
2403
|
multisig.importProposal(
|
|
@@ -2057,7 +2431,7 @@ describe('Multisig', () => {
|
|
|
2057
2431
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2058
2432
|
};
|
|
2059
2433
|
|
|
2060
|
-
const multisig =
|
|
2434
|
+
const multisig = createTestMultisig(config);
|
|
2061
2435
|
|
|
2062
2436
|
const exported = {
|
|
2063
2437
|
accountId: multisig.accountId,
|
|
@@ -2102,7 +2476,7 @@ describe('Multisig', () => {
|
|
|
2102
2476
|
publicKey: '0x' + '2'.repeat(66),
|
|
2103
2477
|
};
|
|
2104
2478
|
|
|
2105
|
-
const multisig =
|
|
2479
|
+
const multisig = createTestMultisig(config, ecdsaSigner);
|
|
2106
2480
|
const cachedProposalId = '0x' + 'c'.repeat(64);
|
|
2107
2481
|
const requestedProposalId = '0x' + 'C'.repeat(64);
|
|
2108
2482
|
const cosignerPubkey = '0x' + '3'.repeat(66);
|
|
@@ -2225,7 +2599,7 @@ describe('Multisig', () => {
|
|
|
2225
2599
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2226
2600
|
};
|
|
2227
2601
|
|
|
2228
|
-
const multisig =
|
|
2602
|
+
const multisig = createTestMultisig(config);
|
|
2229
2603
|
const proposalId = '0x' + 'c'.repeat(64);
|
|
2230
2604
|
const newGuardianPubkey = '0x' + '1'.repeat(64);
|
|
2231
2605
|
const finalRequest = { kind: 'final-switch-guardian-request' };
|
|
@@ -2280,7 +2654,7 @@ describe('Multisig', () => {
|
|
|
2280
2654
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2281
2655
|
};
|
|
2282
2656
|
|
|
2283
|
-
const multisig =
|
|
2657
|
+
const multisig = createTestMultisig(config);
|
|
2284
2658
|
|
|
2285
2659
|
await expect(
|
|
2286
2660
|
multisig.createTransactionProposalRequest('0x' + 'nonexistent'.repeat(5))
|
|
@@ -2294,7 +2668,7 @@ describe('Multisig', () => {
|
|
|
2294
2668
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2295
2669
|
};
|
|
2296
2670
|
|
|
2297
|
-
const multisig =
|
|
2671
|
+
const multisig = createTestMultisig(config);
|
|
2298
2672
|
|
|
2299
2673
|
const mockProposals = [
|
|
2300
2674
|
{
|
|
@@ -2345,7 +2719,7 @@ describe('Multisig', () => {
|
|
|
2345
2719
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2346
2720
|
};
|
|
2347
2721
|
|
|
2348
|
-
const multisig =
|
|
2722
|
+
const multisig = createTestMultisig(config);
|
|
2349
2723
|
const proposalId = '0x' + 'c'.repeat(64);
|
|
2350
2724
|
|
|
2351
2725
|
vi.mocked(executeForSummary).mockResolvedValueOnce({
|
|
@@ -2388,7 +2762,7 @@ describe('Multisig', () => {
|
|
|
2388
2762
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2389
2763
|
};
|
|
2390
2764
|
|
|
2391
|
-
const multisig =
|
|
2765
|
+
const multisig = createTestMultisig(config);
|
|
2392
2766
|
const proposalId = '0x' + 'c'.repeat(64);
|
|
2393
2767
|
|
|
2394
2768
|
(multisig as any).proposals.set(proposalId, {
|
|
@@ -2430,7 +2804,7 @@ describe('Multisig', () => {
|
|
|
2430
2804
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2431
2805
|
};
|
|
2432
2806
|
|
|
2433
|
-
const multisig =
|
|
2807
|
+
const multisig = createTestMultisig(config);
|
|
2434
2808
|
const proposalId = '0x' + 'c'.repeat(64);
|
|
2435
2809
|
|
|
2436
2810
|
(multisig as any).proposals.set(proposalId, {
|
|
@@ -2502,7 +2876,7 @@ describe('Multisig', () => {
|
|
|
2502
2876
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2503
2877
|
};
|
|
2504
2878
|
|
|
2505
|
-
const multisig =
|
|
2879
|
+
const multisig = createTestMultisig(config);
|
|
2506
2880
|
const proposalId = '0x' + 'c'.repeat(64);
|
|
2507
2881
|
const finalRequest = { kind: 'fresh-message-word-request' };
|
|
2508
2882
|
|
|
@@ -2601,7 +2975,7 @@ describe('Multisig', () => {
|
|
|
2601
2975
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2602
2976
|
};
|
|
2603
2977
|
|
|
2604
|
-
const multisig =
|
|
2978
|
+
const multisig = createTestMultisig(config);
|
|
2605
2979
|
const proposalId = '0x' + 'c'.repeat(64);
|
|
2606
2980
|
|
|
2607
2981
|
(multisig as any).proposals.set(proposalId, {
|
|
@@ -2644,7 +3018,7 @@ describe('Multisig', () => {
|
|
|
2644
3018
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2645
3019
|
};
|
|
2646
3020
|
|
|
2647
|
-
const multisig =
|
|
3021
|
+
const multisig = createTestMultisig(config);
|
|
2648
3022
|
|
|
2649
3023
|
await expect(
|
|
2650
3024
|
multisig.executeProposal('0x' + 'nonexistent'.repeat(5))
|
|
@@ -2658,7 +3032,7 @@ describe('Multisig', () => {
|
|
|
2658
3032
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2659
3033
|
};
|
|
2660
3034
|
|
|
2661
|
-
const multisig =
|
|
3035
|
+
const multisig = createTestMultisig(config);
|
|
2662
3036
|
|
|
2663
3037
|
// Sync with pending proposal (only 1 signature)
|
|
2664
3038
|
const mockProposals = [
|
|
@@ -2711,7 +3085,7 @@ describe('Multisig', () => {
|
|
|
2711
3085
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2712
3086
|
};
|
|
2713
3087
|
|
|
2714
|
-
const multisig =
|
|
3088
|
+
const multisig = createTestMultisig(config);
|
|
2715
3089
|
|
|
2716
3090
|
const readyDelta = {
|
|
2717
3091
|
account_id: '0x' + 'a'.repeat(30),
|
|
@@ -2784,7 +3158,11 @@ describe('Multisig', () => {
|
|
|
2784
3158
|
publicKey: '0x' + '2'.repeat(66),
|
|
2785
3159
|
};
|
|
2786
3160
|
|
|
2787
|
-
const multisig =
|
|
3161
|
+
const multisig = createTestMultisig(config, ecdsaSigner, undefined, {
|
|
3162
|
+
kind: 'remote',
|
|
3163
|
+
maxAttempts: 2,
|
|
3164
|
+
createProver: () => ({} as never),
|
|
3165
|
+
});
|
|
2788
3166
|
const proposalId = '0x' + 'c'.repeat(64);
|
|
2789
3167
|
const cosignerPubkey = '0x' + '3'.repeat(66);
|
|
2790
3168
|
const ackPubkey = '0x' + '4'.repeat(66);
|
|
@@ -2849,10 +3227,21 @@ describe('Multisig', () => {
|
|
|
2849
3227
|
ack_scheme: 'ecdsa',
|
|
2850
3228
|
}),
|
|
2851
3229
|
});
|
|
2852
|
-
mockWebClient.
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
3230
|
+
mockWebClient.proveTransaction
|
|
3231
|
+
.mockRejectedValueOnce(Object.assign(new Error('unavailable'), { code: 'Unavailable' }))
|
|
3232
|
+
.mockResolvedValueOnce({});
|
|
3233
|
+
vi.useFakeTimers();
|
|
3234
|
+
try {
|
|
3235
|
+
const execution = multisig.executeProposal(proposalId);
|
|
3236
|
+
await vi.runAllTimersAsync();
|
|
3237
|
+
await expect(execution).resolves.toBeUndefined();
|
|
3238
|
+
} finally {
|
|
3239
|
+
vi.useRealTimers();
|
|
3240
|
+
}
|
|
3241
|
+
expect(mockWebClient.executeTransaction).toHaveBeenCalledTimes(1);
|
|
3242
|
+
expect(mockWebClient.proveTransaction).toHaveBeenCalledTimes(2);
|
|
3243
|
+
expect(mockWebClient.submitProvenTransaction).toHaveBeenCalledTimes(1);
|
|
3244
|
+
expect(mockWebClient.applyTransaction).toHaveBeenCalledTimes(1);
|
|
2856
3245
|
|
|
2857
3246
|
expect(vi.mocked(signatureHexToBytes)).toHaveBeenNthCalledWith(
|
|
2858
3247
|
1,
|
|
@@ -2900,7 +3289,7 @@ describe('Multisig', () => {
|
|
|
2900
3289
|
publicKey: '0x' + '2'.repeat(66),
|
|
2901
3290
|
};
|
|
2902
3291
|
|
|
2903
|
-
const multisig =
|
|
3292
|
+
const multisig = createTestMultisig(config, ecdsaSigner);
|
|
2904
3293
|
const proposalId = '0x' + 'c'.repeat(64);
|
|
2905
3294
|
const cosignerPubkey = '0x' + '3'.repeat(66);
|
|
2906
3295
|
const ackPubkey = '0x' + '4'.repeat(66);
|
|
@@ -2964,9 +3353,11 @@ describe('Multisig', () => {
|
|
|
2964
3353
|
ack_scheme: 'ecdsa',
|
|
2965
3354
|
}),
|
|
2966
3355
|
});
|
|
2967
|
-
mockWebClient.transactions.submit.mockResolvedValueOnce({});
|
|
2968
|
-
|
|
2969
3356
|
await expect(multisig.executeProposal(proposalId)).resolves.toBeUndefined();
|
|
3357
|
+
expect(mockWebClient.executeTransaction).toHaveBeenCalledTimes(1);
|
|
3358
|
+
expect(mockWebClient.proveTransaction).toHaveBeenCalledTimes(1);
|
|
3359
|
+
expect(mockWebClient.submitProvenTransaction).toHaveBeenCalledTimes(1);
|
|
3360
|
+
expect(mockWebClient.applyTransaction).toHaveBeenCalledTimes(1);
|
|
2970
3361
|
|
|
2971
3362
|
expect(vi.mocked(signatureHexToBytes)).toHaveBeenNthCalledWith(
|
|
2972
3363
|
1,
|
|
@@ -3003,7 +3394,7 @@ describe('Multisig', () => {
|
|
|
3003
3394
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3004
3395
|
};
|
|
3005
3396
|
|
|
3006
|
-
const multisig =
|
|
3397
|
+
const multisig = createTestMultisig(config);
|
|
3007
3398
|
const proposalId = '0x' + 'c'.repeat(64);
|
|
3008
3399
|
const newGuardianPubkey = '0x' + '1'.repeat(64);
|
|
3009
3400
|
|
|
@@ -3073,10 +3464,11 @@ describe('Multisig', () => {
|
|
|
3073
3464
|
ok: true,
|
|
3074
3465
|
json: async () => ({ success: true, message: 'ok', ack_pubkey: '0x' + 'f'.repeat(64) }),
|
|
3075
3466
|
});
|
|
3076
|
-
mockWebClient.transactions.submit.mockResolvedValueOnce({});
|
|
3077
|
-
|
|
3078
3467
|
await expect(multisig.executeProposal(proposalId)).resolves.toBeUndefined();
|
|
3079
|
-
expect(mockWebClient.
|
|
3468
|
+
expect(mockWebClient.executeTransaction).toHaveBeenCalledTimes(1);
|
|
3469
|
+
expect(mockWebClient.proveTransaction).toHaveBeenCalledTimes(1);
|
|
3470
|
+
expect(mockWebClient.submitProvenTransaction).toHaveBeenCalledTimes(1);
|
|
3471
|
+
expect(mockWebClient.applyTransaction).toHaveBeenCalledTimes(1);
|
|
3080
3472
|
});
|
|
3081
3473
|
|
|
3082
3474
|
it('should still switch GUARDIAN when the pre-switch canonicalization push fails', async () => {
|
|
@@ -3086,7 +3478,7 @@ describe('Multisig', () => {
|
|
|
3086
3478
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3087
3479
|
};
|
|
3088
3480
|
|
|
3089
|
-
const multisig =
|
|
3481
|
+
const multisig = createTestMultisig(config);
|
|
3090
3482
|
const proposalId = '0x' + 'c'.repeat(64);
|
|
3091
3483
|
const newGuardianPubkey = '0x' + '1'.repeat(64);
|
|
3092
3484
|
|
|
@@ -3124,10 +3516,11 @@ describe('Multisig', () => {
|
|
|
3124
3516
|
ok: true,
|
|
3125
3517
|
json: async () => ({ success: true, message: 'ok', ack_pubkey: '0x' + 'f'.repeat(64) }),
|
|
3126
3518
|
});
|
|
3127
|
-
mockWebClient.transactions.submit.mockResolvedValueOnce({});
|
|
3128
|
-
|
|
3129
3519
|
await expect(multisig.executeProposal(proposalId)).resolves.toBeUndefined();
|
|
3130
|
-
expect(mockWebClient.
|
|
3520
|
+
expect(mockWebClient.executeTransaction).toHaveBeenCalledTimes(1);
|
|
3521
|
+
expect(mockWebClient.proveTransaction).toHaveBeenCalledTimes(1);
|
|
3522
|
+
expect(mockWebClient.submitProvenTransaction).toHaveBeenCalledTimes(1);
|
|
3523
|
+
expect(mockWebClient.applyTransaction).toHaveBeenCalledTimes(1);
|
|
3131
3524
|
});
|
|
3132
3525
|
|
|
3133
3526
|
it('should reject switch_guardian execution when endpoint commitment mismatches', async () => {
|
|
@@ -3137,7 +3530,7 @@ describe('Multisig', () => {
|
|
|
3137
3530
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3138
3531
|
};
|
|
3139
3532
|
|
|
3140
|
-
const multisig =
|
|
3533
|
+
const multisig = createTestMultisig(config);
|
|
3141
3534
|
const proposalId = '0x' + 'c'.repeat(64);
|
|
3142
3535
|
|
|
3143
3536
|
(multisig as any).proposals.set(proposalId, {
|
|
@@ -3179,7 +3572,7 @@ describe('Multisig', () => {
|
|
|
3179
3572
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3180
3573
|
};
|
|
3181
3574
|
|
|
3182
|
-
const multisig =
|
|
3575
|
+
const multisig = createTestMultisig(config);
|
|
3183
3576
|
const proposalId = '0x' + 'c'.repeat(64);
|
|
3184
3577
|
|
|
3185
3578
|
(multisig as any).proposals.set(proposalId, {
|
|
@@ -3231,7 +3624,7 @@ describe('Multisig', () => {
|
|
|
3231
3624
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3232
3625
|
};
|
|
3233
3626
|
|
|
3234
|
-
const multisig =
|
|
3627
|
+
const multisig = createTestMultisig(config);
|
|
3235
3628
|
const proposalId = '0x' + 'c'.repeat(64);
|
|
3236
3629
|
|
|
3237
3630
|
(multisig as any).proposals.set(proposalId, {
|
|
@@ -3266,6 +3659,45 @@ describe('Multisig', () => {
|
|
|
3266
3659
|
});
|
|
3267
3660
|
});
|
|
3268
3661
|
|
|
3662
|
+
describe('submitTransaction', () => {
|
|
3663
|
+
it('uses the configured total proof-attempt budget without repeating other stages', async () => {
|
|
3664
|
+
const multisig = createTestMultisig(
|
|
3665
|
+
{
|
|
3666
|
+
threshold: 1,
|
|
3667
|
+
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
3668
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3669
|
+
},
|
|
3670
|
+
mockSigner,
|
|
3671
|
+
undefined,
|
|
3672
|
+
{
|
|
3673
|
+
kind: 'remote',
|
|
3674
|
+
maxAttempts: 4,
|
|
3675
|
+
createProver: () => ({} as never),
|
|
3676
|
+
},
|
|
3677
|
+
);
|
|
3678
|
+
const transient = Object.assign(new Error('unavailable'), { code: 'Unavailable' });
|
|
3679
|
+
mockWebClient.proveTransaction
|
|
3680
|
+
.mockRejectedValueOnce(transient)
|
|
3681
|
+
.mockRejectedValueOnce(transient)
|
|
3682
|
+
.mockRejectedValueOnce(transient)
|
|
3683
|
+
.mockResolvedValueOnce({});
|
|
3684
|
+
|
|
3685
|
+
vi.useFakeTimers();
|
|
3686
|
+
try {
|
|
3687
|
+
const submission = multisig.submitTransaction({} as never);
|
|
3688
|
+
await vi.runAllTimersAsync();
|
|
3689
|
+
await submission;
|
|
3690
|
+
} finally {
|
|
3691
|
+
vi.useRealTimers();
|
|
3692
|
+
}
|
|
3693
|
+
|
|
3694
|
+
expect(mockWebClient.executeTransaction).toHaveBeenCalledTimes(1);
|
|
3695
|
+
expect(mockWebClient.proveTransaction).toHaveBeenCalledTimes(4);
|
|
3696
|
+
expect(mockWebClient.submitProvenTransaction).toHaveBeenCalledTimes(1);
|
|
3697
|
+
expect(mockWebClient.applyTransaction).toHaveBeenCalledTimes(1);
|
|
3698
|
+
});
|
|
3699
|
+
});
|
|
3700
|
+
|
|
3269
3701
|
describe('prepareCustomExecution', () => {
|
|
3270
3702
|
const requestBytes = new Uint8Array([9, 8, 7]);
|
|
3271
3703
|
|
|
@@ -3308,7 +3740,7 @@ describe('Multisig', () => {
|
|
|
3308
3740
|
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
3309
3741
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3310
3742
|
};
|
|
3311
|
-
const multisig =
|
|
3743
|
+
const multisig = createTestMultisig(config);
|
|
3312
3744
|
|
|
3313
3745
|
const builtinDelta = {
|
|
3314
3746
|
...customDelta('change_threshold', [falconSig('0x' + 'a'.repeat(64))]),
|
|
@@ -3336,7 +3768,7 @@ describe('Multisig', () => {
|
|
|
3336
3768
|
signerCommitments: ['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64)],
|
|
3337
3769
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3338
3770
|
};
|
|
3339
|
-
const multisig =
|
|
3771
|
+
const multisig = createTestMultisig(config);
|
|
3340
3772
|
|
|
3341
3773
|
mockFetch.mockResolvedValueOnce({
|
|
3342
3774
|
ok: true,
|
|
@@ -3354,7 +3786,7 @@ describe('Multisig', () => {
|
|
|
3354
3786
|
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
3355
3787
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3356
3788
|
};
|
|
3357
|
-
const multisig =
|
|
3789
|
+
const multisig = createTestMultisig(config);
|
|
3358
3790
|
|
|
3359
3791
|
// Signed commitment comes from TransactionSummary.deserialize -> 'c' * 64.
|
|
3360
3792
|
// Make the binding request derive a different commitment so the check fails.
|
|
@@ -3381,7 +3813,7 @@ describe('Multisig', () => {
|
|
|
3381
3813
|
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
3382
3814
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3383
3815
|
};
|
|
3384
|
-
const multisig =
|
|
3816
|
+
const multisig = createTestMultisig(config);
|
|
3385
3817
|
|
|
3386
3818
|
const ready = customDelta('b2agg', [falconSig('0x' + 'a'.repeat(64))]);
|
|
3387
3819
|
|
|
@@ -3410,7 +3842,7 @@ describe('Multisig', () => {
|
|
|
3410
3842
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3411
3843
|
};
|
|
3412
3844
|
|
|
3413
|
-
const multisig =
|
|
3845
|
+
const multisig = createTestMultisig(config);
|
|
3414
3846
|
|
|
3415
3847
|
// Create a proposal with metadata
|
|
3416
3848
|
const mockDelta = {
|
|
@@ -3472,7 +3904,7 @@ describe('Multisig', () => {
|
|
|
3472
3904
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3473
3905
|
};
|
|
3474
3906
|
|
|
3475
|
-
const multisig =
|
|
3907
|
+
const multisig = createTestMultisig(config);
|
|
3476
3908
|
|
|
3477
3909
|
// Sync proposals - no local proposals exist
|
|
3478
3910
|
const mockProposals = [
|
|
@@ -3519,7 +3951,7 @@ describe('Multisig', () => {
|
|
|
3519
3951
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3520
3952
|
};
|
|
3521
3953
|
|
|
3522
|
-
const multisig =
|
|
3954
|
+
const multisig = createTestMultisig(config);
|
|
3523
3955
|
|
|
3524
3956
|
const mockDelta = {
|
|
3525
3957
|
account_id: '0x' + 'a'.repeat(30),
|
|
@@ -3567,7 +3999,7 @@ describe('Multisig', () => {
|
|
|
3567
3999
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3568
4000
|
};
|
|
3569
4001
|
|
|
3570
|
-
const multisig =
|
|
4002
|
+
const multisig = createTestMultisig(config);
|
|
3571
4003
|
|
|
3572
4004
|
const mockDelta = {
|
|
3573
4005
|
account_id: '0x' + 'a'.repeat(30),
|
|
@@ -3617,7 +4049,7 @@ describe('Multisig', () => {
|
|
|
3617
4049
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3618
4050
|
};
|
|
3619
4051
|
|
|
3620
|
-
const multisig =
|
|
4052
|
+
const multisig = createTestMultisig(config);
|
|
3621
4053
|
|
|
3622
4054
|
const mockDelta = {
|
|
3623
4055
|
account_id: '0x' + 'a'.repeat(30),
|
|
@@ -3668,7 +4100,7 @@ describe('Multisig', () => {
|
|
|
3668
4100
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3669
4101
|
};
|
|
3670
4102
|
|
|
3671
|
-
const multisig =
|
|
4103
|
+
const multisig = createTestMultisig(config);
|
|
3672
4104
|
|
|
3673
4105
|
// First sync with 1 signature (pending)
|
|
3674
4106
|
const mockProposalsPending = [
|
|
@@ -3760,7 +4192,7 @@ describe('Multisig', () => {
|
|
|
3760
4192
|
guardianCommitment: '0x' + 'd'.repeat(64),
|
|
3761
4193
|
};
|
|
3762
4194
|
|
|
3763
|
-
const multisig =
|
|
4195
|
+
const multisig = createTestMultisig(config);
|
|
3764
4196
|
expect(multisig.threshold).toBe(3);
|
|
3765
4197
|
});
|
|
3766
4198
|
|
|
@@ -3772,7 +4204,7 @@ describe('Multisig', () => {
|
|
|
3772
4204
|
guardianCommitment: '0x' + 'd'.repeat(64),
|
|
3773
4205
|
};
|
|
3774
4206
|
|
|
3775
|
-
const multisig =
|
|
4207
|
+
const multisig = createTestMultisig(config);
|
|
3776
4208
|
expect(multisig.signerCommitments).toEqual(signerCommitments);
|
|
3777
4209
|
});
|
|
3778
4210
|
|
|
@@ -3784,7 +4216,7 @@ describe('Multisig', () => {
|
|
|
3784
4216
|
guardianCommitment,
|
|
3785
4217
|
};
|
|
3786
4218
|
|
|
3787
|
-
const multisig =
|
|
4219
|
+
const multisig = createTestMultisig(config);
|
|
3788
4220
|
expect(multisig.guardianCommitment).toBe(guardianCommitment);
|
|
3789
4221
|
});
|
|
3790
4222
|
|
|
@@ -3795,7 +4227,7 @@ describe('Multisig', () => {
|
|
|
3795
4227
|
guardianCommitment: '0x' + 'd'.repeat(64),
|
|
3796
4228
|
};
|
|
3797
4229
|
|
|
3798
|
-
const multisig =
|
|
4230
|
+
const multisig = createTestMultisig(config);
|
|
3799
4231
|
expect(multisig.account).toBe(mockAccount);
|
|
3800
4232
|
});
|
|
3801
4233
|
});
|
|
@@ -3808,7 +4240,7 @@ describe('Multisig', () => {
|
|
|
3808
4240
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3809
4241
|
};
|
|
3810
4242
|
|
|
3811
|
-
const multisig =
|
|
4243
|
+
const multisig = createTestMultisig(config);
|
|
3812
4244
|
|
|
3813
4245
|
// Simulates a GUARDIAN response with canonical snake_case metadata
|
|
3814
4246
|
const rustProposals = [
|
|
@@ -3858,7 +4290,7 @@ describe('Multisig', () => {
|
|
|
3858
4290
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3859
4291
|
};
|
|
3860
4292
|
|
|
3861
|
-
const multisig =
|
|
4293
|
+
const multisig = createTestMultisig(config);
|
|
3862
4294
|
|
|
3863
4295
|
// P2ID proposal with canonical snake_case fields
|
|
3864
4296
|
const p2idProposals = [
|
|
@@ -3915,7 +4347,7 @@ describe('Multisig', () => {
|
|
|
3915
4347
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
3916
4348
|
};
|
|
3917
4349
|
|
|
3918
|
-
const multisig =
|
|
4350
|
+
const multisig = createTestMultisig(config);
|
|
3919
4351
|
|
|
3920
4352
|
const switchGuardianProposals = [
|
|
3921
4353
|
{
|