@openzeppelin/miden-multisig-client 0.16.1 → 0.17.0-rc.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 +192 -11
- package/dist/account/builder.d.ts.map +1 -1
- package/dist/account/builder.js +32 -25
- package/dist/account/builder.js.map +1 -1
- package/dist/account/builder.test.js +73 -21
- package/dist/account/builder.test.js.map +1 -1
- package/dist/account/layout.d.ts +31 -0
- package/dist/account/layout.d.ts.map +1 -0
- package/dist/account/layout.js +31 -0
- package/dist/account/layout.js.map +1 -0
- package/dist/account/masm/account-components/auth.d.ts +1 -4
- package/dist/account/masm/account-components/auth.d.ts.map +1 -1
- package/dist/account/masm/account-components/auth.js +36 -53
- package/dist/account/masm/account-components/auth.js.map +1 -1
- package/dist/account/masm/index.d.ts +0 -1
- package/dist/account/masm/index.d.ts.map +1 -1
- package/dist/account/masm/index.js +0 -1
- package/dist/account/masm/index.js.map +1 -1
- package/dist/account/storage.d.ts +4 -0
- package/dist/account/storage.d.ts.map +1 -1
- package/dist/account/storage.js +9 -20
- package/dist/account/storage.js.map +1 -1
- package/dist/client.d.ts +4 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +10 -5
- package/dist/client.js.map +1 -1
- package/dist/client.test.js +74 -16
- package/dist/client.test.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/inspector.d.ts +59 -1
- package/dist/inspector.d.ts.map +1 -1
- package/dist/inspector.js +157 -29
- package/dist/inspector.js.map +1 -1
- package/dist/inspector.test.js +246 -37
- package/dist/inspector.test.js.map +1 -1
- package/dist/multisig.d.ts +109 -33
- package/dist/multisig.d.ts.map +1 -1
- package/dist/multisig.js +307 -104
- package/dist/multisig.js.map +1 -1
- package/dist/multisig.test.js +582 -58
- package/dist/multisig.test.js.map +1 -1
- package/dist/procedures.d.ts +6 -7
- package/dist/procedures.d.ts.map +1 -1
- package/dist/procedures.js +6 -7
- package/dist/procedures.js.map +1 -1
- package/dist/proposal/metadata.d.ts.map +1 -1
- package/dist/proposal/metadata.js +13 -2
- package/dist/proposal/metadata.js.map +1 -1
- package/dist/proposal/metadata.test.js +57 -0
- package/dist/proposal/metadata.test.js.map +1 -1
- package/dist/prover/errors.d.ts +5 -0
- package/dist/prover/errors.d.ts.map +1 -1
- package/dist/prover/errors.js +7 -155
- package/dist/prover/errors.js.map +1 -1
- package/dist/prover/errors.test.js +5 -0
- package/dist/prover/errors.test.js.map +1 -1
- package/dist/prover/retry.d.ts +1 -6
- package/dist/prover/retry.d.ts.map +1 -1
- package/dist/prover/retry.js +5 -28
- package/dist/prover/retry.js.map +1 -1
- package/dist/prover/retry.test.js +1 -1
- package/dist/prover/retry.test.js.map +1 -1
- package/dist/prover/workflow.d.ts +4 -3
- package/dist/prover/workflow.d.ts.map +1 -1
- package/dist/prover/workflow.js +5 -2
- package/dist/prover/workflow.js.map +1 -1
- package/dist/prover/workflow.test.js +28 -3
- package/dist/prover/workflow.test.js.map +1 -1
- package/dist/retry/classify.d.ts +16 -0
- package/dist/retry/classify.d.ts.map +1 -0
- package/dist/retry/classify.js +187 -0
- package/dist/retry/classify.js.map +1 -0
- package/dist/retry/runtime.d.ts +13 -0
- package/dist/retry/runtime.d.ts.map +1 -0
- package/dist/retry/runtime.js +33 -0
- package/dist/retry/runtime.js.map +1 -0
- package/dist/rpc/config.d.ts +11 -0
- package/dist/rpc/config.d.ts.map +1 -0
- package/dist/rpc/config.js +17 -0
- package/dist/rpc/config.js.map +1 -0
- package/dist/rpc/config.test.d.ts +2 -0
- package/dist/rpc/config.test.d.ts.map +1 -0
- package/dist/rpc/config.test.js +24 -0
- package/dist/rpc/config.test.js.map +1 -0
- package/dist/rpc/errors.d.ts +2 -0
- package/dist/rpc/errors.d.ts.map +1 -0
- package/dist/rpc/errors.js +11 -0
- package/dist/rpc/errors.js.map +1 -0
- package/dist/rpc/errors.test.d.ts +2 -0
- package/dist/rpc/errors.test.d.ts.map +1 -0
- package/dist/rpc/errors.test.js +34 -0
- package/dist/rpc/errors.test.js.map +1 -0
- package/dist/rpc/retry.d.ts +4 -0
- package/dist/rpc/retry.d.ts.map +1 -0
- package/dist/rpc/retry.js +6 -0
- package/dist/rpc/retry.js.map +1 -0
- package/dist/rpc/retry.test.d.ts +2 -0
- package/dist/rpc/retry.test.d.ts.map +1 -0
- package/dist/rpc/retry.test.js +98 -0
- package/dist/rpc/retry.test.js.map +1 -0
- package/dist/transaction/index.d.ts +1 -1
- package/dist/transaction/index.d.ts.map +1 -1
- package/dist/transaction/index.js +1 -1
- package/dist/transaction/index.js.map +1 -1
- package/dist/transaction/p2id.d.ts +17 -6
- package/dist/transaction/p2id.d.ts.map +1 -1
- package/dist/transaction/p2id.js +22 -31
- package/dist/transaction/p2id.js.map +1 -1
- package/dist/transaction/p2id.test.js +62 -24
- package/dist/transaction/p2id.test.js.map +1 -1
- package/dist/transaction/summary.d.ts +45 -2
- package/dist/transaction/summary.d.ts.map +1 -1
- package/dist/transaction/summary.js +42 -2
- package/dist/transaction/summary.js.map +1 -1
- package/dist/transaction/summary.test.d.ts +2 -0
- package/dist/transaction/summary.test.d.ts.map +1 -0
- package/dist/transaction/summary.test.js +26 -0
- package/dist/transaction/summary.test.js.map +1 -0
- package/dist/transaction/updateGuardian.d.ts.map +1 -1
- package/dist/transaction/updateGuardian.js +16 -18
- package/dist/transaction/updateGuardian.js.map +1 -1
- package/dist/transaction/updateProcedureThreshold.d.ts.map +1 -1
- package/dist/transaction/updateProcedureThreshold.js +15 -17
- package/dist/transaction/updateProcedureThreshold.js.map +1 -1
- package/dist/transaction/updateSigners.d.ts +6 -1
- package/dist/transaction/updateSigners.d.ts.map +1 -1
- package/dist/transaction/updateSigners.js +20 -17
- package/dist/transaction/updateSigners.js.map +1 -1
- package/dist/transaction.d.ts +2 -2
- 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 +28 -4
- package/dist/types/proposal.d.ts.map +1 -1
- package/dist/types/proposal.js +18 -0
- package/dist/types/proposal.js.map +1 -1
- package/dist/types.d.ts +0 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/signature.d.ts +11 -7
- package/dist/utils/signature.d.ts.map +1 -1
- package/dist/utils/signature.js +24 -58
- package/dist/utils/signature.js.map +1 -1
- package/dist/utils/word.d.ts +7 -0
- package/dist/utils/word.d.ts.map +1 -1
- package/dist/utils/word.js +15 -0
- package/dist/utils/word.js.map +1 -1
- package/masm/account_components/auth/guarded_multisig.masm +42 -0
- package/package.json +7 -4
- package/src/account/builder.test.ts +111 -45
- package/src/account/builder.ts +45 -33
- package/src/account/layout.ts +33 -0
- package/src/account/masm/account-components/auth.ts +36 -56
- package/src/account/masm/index.ts +0 -1
- package/src/account/storage.ts +9 -22
- package/src/client.test.ts +87 -16
- package/src/client.ts +16 -3
- package/src/index.ts +27 -1
- package/src/inspector.test.ts +330 -38
- package/src/inspector.ts +196 -33
- package/src/multisig.test.ts +680 -63
- package/src/multisig.ts +400 -115
- package/src/procedures.ts +6 -7
- package/src/proposal/metadata.test.ts +76 -0
- package/src/proposal/metadata.ts +13 -2
- package/src/prover/errors.test.ts +8 -0
- package/src/prover/errors.ts +7 -175
- package/src/prover/retry.test.ts +1 -1
- package/src/prover/retry.ts +10 -35
- package/src/prover/workflow.test.ts +40 -4
- package/src/prover/workflow.ts +16 -4
- package/src/retry/classify.ts +220 -0
- package/src/retry/runtime.ts +45 -0
- package/src/rpc/config.test.ts +45 -0
- package/src/rpc/config.ts +30 -0
- package/src/rpc/errors.test.ts +69 -0
- package/src/rpc/errors.ts +12 -0
- package/src/rpc/retry.test.ts +144 -0
- package/src/rpc/retry.ts +12 -0
- package/src/transaction/index.ts +7 -1
- package/src/transaction/p2id.test.ts +112 -31
- package/src/transaction/p2id.ts +39 -38
- package/src/transaction/summary.test.ts +32 -0
- package/src/transaction/summary.ts +83 -4
- package/src/transaction/updateGuardian.ts +15 -25
- package/src/transaction/updateProcedureThreshold.ts +13 -29
- package/src/transaction/updateSigners.ts +38 -30
- package/src/transaction.ts +8 -1
- package/src/types/proposal.ts +43 -4
- package/src/types.ts +0 -1
- package/src/utils/signature.ts +32 -65
- package/src/utils/word.ts +17 -0
- package/dist/account/masm/auth.d.ts +0 -5
- package/dist/account/masm/auth.d.ts.map +0 -1
- package/dist/account/masm/auth.js +0 -1509
- package/dist/account/masm/auth.js.map +0 -1
- package/masm/account_components/auth/multisig.masm +0 -12
- package/masm/account_components/auth/multisig_ecdsa.masm +0 -12
- package/masm/account_components/auth/multisig_guardian.masm +0 -16
- package/masm/account_components/auth/multisig_guardian_ecdsa.masm +0 -16
- package/masm/auth/guardian.masm +0 -199
- package/masm/auth/guardian_ecdsa.masm +0 -195
- package/masm/auth/multisig.masm +0 -554
- package/masm/auth/multisig_ecdsa.masm +0 -554
- package/src/account/masm/auth.ts +0 -1512
package/src/multisig.test.ts
CHANGED
|
@@ -5,16 +5,38 @@ import {
|
|
|
5
5
|
buildUpdateProcedureThresholdTransactionRequest,
|
|
6
6
|
buildUpdateGuardianTransactionRequest,
|
|
7
7
|
buildUpdateSignersTransactionRequest,
|
|
8
|
+
chainAnchorFromBase64,
|
|
8
9
|
executeForSummary,
|
|
10
|
+
executeForSummaryAt,
|
|
9
11
|
} from './transaction.js';
|
|
10
12
|
|
|
11
|
-
const {
|
|
13
|
+
const {
|
|
14
|
+
mockRpcGetAccountDetails,
|
|
15
|
+
mockAccountDeserialize,
|
|
16
|
+
mockDetectConfig,
|
|
17
|
+
mockNoteFileDeserialize,
|
|
18
|
+
mockGetSignerCommitments,
|
|
19
|
+
mockGetGuardianCommitment,
|
|
20
|
+
} = vi.hoisted(() => ({
|
|
12
21
|
mockRpcGetAccountDetails: vi.fn(),
|
|
13
22
|
mockAccountDeserialize: vi.fn(),
|
|
14
23
|
mockDetectConfig: vi.fn(),
|
|
15
24
|
mockNoteFileDeserialize: vi.fn(),
|
|
25
|
+
mockGetSignerCommitments: vi.fn(),
|
|
26
|
+
mockGetGuardianCommitment: vi.fn(),
|
|
16
27
|
}));
|
|
17
28
|
|
|
29
|
+
const { MOCK_CHAIN_ANCHOR_B64, createMockChainAnchor } = vi.hoisted(() => {
|
|
30
|
+
const MOCK_CHAIN_ANCHOR_B64 = 'bW9jay1jaGFpbi1hbmNob3I=';
|
|
31
|
+
const createMockChainAnchor = () =>
|
|
32
|
+
({
|
|
33
|
+
commitment: () => ({ toHex: () => '0x' + 'b'.repeat(64) }),
|
|
34
|
+
free: () => {},
|
|
35
|
+
serialize: () => new Uint8Array([9, 9, 9]),
|
|
36
|
+
}) as never;
|
|
37
|
+
return { MOCK_CHAIN_ANCHOR_B64, createMockChainAnchor };
|
|
38
|
+
});
|
|
39
|
+
|
|
18
40
|
// Mock the Miden SDK
|
|
19
41
|
vi.mock('@miden-sdk/miden-sdk', () => ({
|
|
20
42
|
Account: {
|
|
@@ -40,9 +62,10 @@ vi.mock('@miden-sdk/miden-sdk', () => ({
|
|
|
40
62
|
toCommitment: () => ({
|
|
41
63
|
toHex: () => '0x' + 'c'.repeat(64),
|
|
42
64
|
}),
|
|
43
|
-
|
|
44
|
-
toHex: () => '0x' + '
|
|
65
|
+
blockCommitment: () => ({
|
|
66
|
+
toHex: () => '0x' + 'b'.repeat(64),
|
|
45
67
|
}),
|
|
68
|
+
userParams: () => [0, 0, 0, 1, 2, 3, 4],
|
|
46
69
|
serialize: () => new Uint8Array([1, 2, 3]),
|
|
47
70
|
}),
|
|
48
71
|
},
|
|
@@ -78,6 +101,12 @@ vi.mock('@miden-sdk/miden-sdk', () => ({
|
|
|
78
101
|
// Mock transaction module
|
|
79
102
|
vi.mock('./transaction.js', () => ({
|
|
80
103
|
executeForSummary: vi.fn(),
|
|
104
|
+
executeForSummaryAt: vi.fn(),
|
|
105
|
+
chainAnchorToBase64: vi.fn(() => MOCK_CHAIN_ANCHOR_B64),
|
|
106
|
+
chainAnchorFromBase64: vi.fn(() => createMockChainAnchor()),
|
|
107
|
+
summarySalt: vi.fn(() => ({
|
|
108
|
+
toHex: () => '0x' + 'd'.repeat(64),
|
|
109
|
+
})),
|
|
81
110
|
buildUpdateSignersTransactionRequest: vi.fn().mockResolvedValue({
|
|
82
111
|
request: {},
|
|
83
112
|
salt: { toHex: () => '0x' + 'd'.repeat(64) },
|
|
@@ -122,6 +151,9 @@ vi.mock('./utils/signature.js', async () => {
|
|
|
122
151
|
values: [1, 2, 3],
|
|
123
152
|
})),
|
|
124
153
|
signatureHexToBytes: vi.fn((hex: string) => new Uint8Array([0, 1, 2, 3])),
|
|
154
|
+
// These tests use synthetic signature bytes to exercise advice routing;
|
|
155
|
+
// recoverability is covered by tests/ecdsa-advice-encoding.test.ts.
|
|
156
|
+
assertEcdsaSignatureRecoverable: vi.fn(),
|
|
125
157
|
};
|
|
126
158
|
});
|
|
127
159
|
|
|
@@ -133,11 +165,19 @@ vi.mock('./utils/encoding.js', async () => {
|
|
|
133
165
|
};
|
|
134
166
|
});
|
|
135
167
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
168
|
+
// Keep the real assertCompleteDetectedConfig so refreshConfigFromAccount's
|
|
169
|
+
// fail-closed validation is exercised.
|
|
170
|
+
vi.mock('./inspector.js', async (importOriginal) => {
|
|
171
|
+
const actual = await importOriginal<typeof import('./inspector.js')>();
|
|
172
|
+
return {
|
|
173
|
+
...actual,
|
|
174
|
+
AccountInspector: {
|
|
175
|
+
fromAccount: mockDetectConfig,
|
|
176
|
+
getSignerPublicKeyCommitments: mockGetSignerCommitments,
|
|
177
|
+
getGuardianPublicKeyCommitment: mockGetGuardianCommitment,
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
});
|
|
141
181
|
|
|
142
182
|
// Mock fetch for GUARDIAN client
|
|
143
183
|
const mockFetch = vi.fn();
|
|
@@ -186,6 +226,15 @@ describe('Multisig', () => {
|
|
|
186
226
|
beforeEach(() => {
|
|
187
227
|
mockFetch.mockReset();
|
|
188
228
|
vi.mocked(executeForSummary).mockResolvedValue({
|
|
229
|
+
summary: {
|
|
230
|
+
toCommitment: () => ({
|
|
231
|
+
toHex: () => '0x' + 'c'.repeat(64),
|
|
232
|
+
}),
|
|
233
|
+
serialize: () => new Uint8Array([1, 2, 3]),
|
|
234
|
+
},
|
|
235
|
+
anchor: createMockChainAnchor(),
|
|
236
|
+
} as any);
|
|
237
|
+
vi.mocked(executeForSummaryAt).mockResolvedValue({
|
|
189
238
|
toCommitment: () => ({
|
|
190
239
|
toHex: () => '0x' + 'c'.repeat(64),
|
|
191
240
|
}),
|
|
@@ -204,7 +253,6 @@ describe('Multisig', () => {
|
|
|
204
253
|
threshold: 1,
|
|
205
254
|
numSigners: 1,
|
|
206
255
|
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
207
|
-
guardianEnabled: true,
|
|
208
256
|
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
209
257
|
vaultBalances: [],
|
|
210
258
|
procedureThresholds: new Map(),
|
|
@@ -350,6 +398,38 @@ describe('Multisig', () => {
|
|
|
350
398
|
});
|
|
351
399
|
});
|
|
352
400
|
|
|
401
|
+
describe('history (issue #413)', () => {
|
|
402
|
+
it('delegates to the guardian client with the account id and options', async () => {
|
|
403
|
+
const config = {
|
|
404
|
+
threshold: 1,
|
|
405
|
+
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
406
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
407
|
+
};
|
|
408
|
+
const multisig = createTestMultisig(config);
|
|
409
|
+
|
|
410
|
+
const page = {
|
|
411
|
+
entries: [
|
|
412
|
+
{
|
|
413
|
+
nonce: 3,
|
|
414
|
+
status: 'canonical' as const,
|
|
415
|
+
timestamp: '2026-08-01T12:00:03Z',
|
|
416
|
+
newCommitment: '0x' + 'b'.repeat(64),
|
|
417
|
+
inputNotes: [],
|
|
418
|
+
outputNotes: [],
|
|
419
|
+
decodeWarnings: [],
|
|
420
|
+
},
|
|
421
|
+
],
|
|
422
|
+
nextCursor: 'cursor-token',
|
|
423
|
+
};
|
|
424
|
+
const spy = vi.spyOn(guardian, 'getDeltaHistory').mockResolvedValue(page);
|
|
425
|
+
|
|
426
|
+
const result = await multisig.deltaHistory({ limit: 5, cursor: 'prev' });
|
|
427
|
+
|
|
428
|
+
expect(result).toBe(page);
|
|
429
|
+
expect(spy).toHaveBeenCalledWith('0x' + 'a'.repeat(30), { limit: 5, cursor: 'prev' });
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
|
|
353
433
|
describe('signerCommitment', () => {
|
|
354
434
|
it('should return signer commitment', () => {
|
|
355
435
|
const config = {
|
|
@@ -363,6 +443,56 @@ describe('Multisig', () => {
|
|
|
363
443
|
});
|
|
364
444
|
});
|
|
365
445
|
|
|
446
|
+
describe('getSignerPublicKeyCommitments (issue #306)', () => {
|
|
447
|
+
const config = {
|
|
448
|
+
threshold: 1,
|
|
449
|
+
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
450
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
it('reads commitments from the store-backed account', async () => {
|
|
454
|
+
const storeAccount = mockedAccount('0x' + 'b'.repeat(64), 1);
|
|
455
|
+
mockWebClient.getAccount.mockResolvedValueOnce(storeAccount);
|
|
456
|
+
const expected = ['0x' + '1'.repeat(64), '0x' + '2'.repeat(64)];
|
|
457
|
+
mockGetSignerCommitments.mockReturnValueOnce(expected);
|
|
458
|
+
|
|
459
|
+
const multisig = createTestMultisig(config);
|
|
460
|
+
const commitments = await multisig.getSignerPublicKeyCommitments();
|
|
461
|
+
|
|
462
|
+
expect(commitments).toEqual(expected);
|
|
463
|
+
expect(mockGetSignerCommitments).toHaveBeenCalledWith(storeAccount);
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
it('falls back to the account snapshot when the store has no record', async () => {
|
|
467
|
+
mockWebClient.getAccount.mockResolvedValueOnce(null);
|
|
468
|
+
mockGetSignerCommitments.mockReturnValueOnce(['0x' + '3'.repeat(64)]);
|
|
469
|
+
|
|
470
|
+
const multisig = createTestMultisig(config);
|
|
471
|
+
await multisig.getSignerPublicKeyCommitments();
|
|
472
|
+
|
|
473
|
+
expect(mockGetSignerCommitments).toHaveBeenCalledWith(mockAccount);
|
|
474
|
+
});
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
describe('getGuardianPublicKeyCommitment (issue #306)', () => {
|
|
478
|
+
it('reads the guardian commitment from the store-backed account', async () => {
|
|
479
|
+
const storeAccount = mockedAccount('0x' + 'b'.repeat(64), 1);
|
|
480
|
+
mockWebClient.getAccount.mockResolvedValueOnce(storeAccount);
|
|
481
|
+
mockGetGuardianCommitment.mockReturnValueOnce('0x' + '4'.repeat(64));
|
|
482
|
+
|
|
483
|
+
const multisig = createTestMultisig({
|
|
484
|
+
threshold: 1,
|
|
485
|
+
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
486
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
const commitment = await multisig.getGuardianPublicKeyCommitment();
|
|
490
|
+
|
|
491
|
+
expect(commitment).toBe('0x' + '4'.repeat(64));
|
|
492
|
+
expect(mockGetGuardianCommitment).toHaveBeenCalledWith(storeAccount);
|
|
493
|
+
});
|
|
494
|
+
});
|
|
495
|
+
|
|
366
496
|
describe('fetchState', () => {
|
|
367
497
|
it('should fetch account state from GUARDIAN', async () => {
|
|
368
498
|
const config = {
|
|
@@ -499,7 +629,6 @@ describe('Multisig', () => {
|
|
|
499
629
|
threshold: 2,
|
|
500
630
|
numSigners: 2,
|
|
501
631
|
signerCommitments: ['0x' + '1'.repeat(64), '0x' + '2'.repeat(64)],
|
|
502
|
-
guardianEnabled: true,
|
|
503
632
|
guardianCommitment: '0x' + 'd'.repeat(64),
|
|
504
633
|
vaultBalances: [],
|
|
505
634
|
procedureThresholds: new Map(),
|
|
@@ -516,6 +645,44 @@ describe('Multisig', () => {
|
|
|
516
645
|
expect(mockWebClient.newAccount).not.toHaveBeenCalled();
|
|
517
646
|
});
|
|
518
647
|
|
|
648
|
+
it('keeps the previous config when a refresh reads an incomplete signer set (issue #306 review)', async () => {
|
|
649
|
+
const config = {
|
|
650
|
+
threshold: 1,
|
|
651
|
+
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
652
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
653
|
+
};
|
|
654
|
+
const multisig = createTestMultisig(config, mockSigner, '0x' + 'a'.repeat(30));
|
|
655
|
+
|
|
656
|
+
mockWebClient.getAccount.mockResolvedValueOnce(mockedAccount('0x' + 'b'.repeat(64), 0));
|
|
657
|
+
mockFetch.mockResolvedValueOnce({
|
|
658
|
+
ok: true,
|
|
659
|
+
json: async () => ({
|
|
660
|
+
account_id: multisig.accountId,
|
|
661
|
+
commitment: '0x' + 'b'.repeat(64),
|
|
662
|
+
state_json: { data: 'AQID' },
|
|
663
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
664
|
+
updated_at: '2024-01-02T00:00:00Z',
|
|
665
|
+
}),
|
|
666
|
+
});
|
|
667
|
+
// Storage reports 3 signers but only 1 entry was readable: adopting
|
|
668
|
+
// this would let membership proposals rewrite the on-chain set without
|
|
669
|
+
// the omitted keys. The refresh must keep the previous config instead.
|
|
670
|
+
mockDetectConfig.mockReturnValueOnce({
|
|
671
|
+
threshold: 2,
|
|
672
|
+
numSigners: 3,
|
|
673
|
+
signerCommitments: ['0x' + '1'.repeat(64)],
|
|
674
|
+
guardianCommitment: '0x' + 'd'.repeat(64),
|
|
675
|
+
vaultBalances: [],
|
|
676
|
+
procedureThresholds: new Map(),
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
await multisig.syncState();
|
|
680
|
+
|
|
681
|
+
expect(multisig.threshold).toBe(1);
|
|
682
|
+
expect(multisig.signerCommitments).toEqual(['0x' + 'a'.repeat(64)]);
|
|
683
|
+
expect(multisig.guardianCommitment).toBe('0x' + 'c'.repeat(64));
|
|
684
|
+
});
|
|
685
|
+
|
|
519
686
|
it('should overwrite local state when account is not found on-chain', async () => {
|
|
520
687
|
const config = {
|
|
521
688
|
threshold: 1,
|
|
@@ -923,6 +1090,7 @@ describe('Multisig', () => {
|
|
|
923
1090
|
signatures: [],
|
|
924
1091
|
metadata: {
|
|
925
1092
|
proposal_type: 'add_signer',
|
|
1093
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
926
1094
|
target_threshold: 1,
|
|
927
1095
|
signer_commitments: ['0x' + 'a'.repeat(64)],
|
|
928
1096
|
description: '',
|
|
@@ -974,6 +1142,7 @@ describe('Multisig', () => {
|
|
|
974
1142
|
signatures: [],
|
|
975
1143
|
metadata: {
|
|
976
1144
|
proposal_type: 'add_signer',
|
|
1145
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
977
1146
|
target_threshold: 1,
|
|
978
1147
|
signer_commitments: ['0x' + 'a'.repeat(64)],
|
|
979
1148
|
description: '',
|
|
@@ -1026,6 +1195,7 @@ describe('Multisig', () => {
|
|
|
1026
1195
|
signatures: [],
|
|
1027
1196
|
metadata: {
|
|
1028
1197
|
proposal_type: 'add_signer',
|
|
1198
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
1029
1199
|
target_threshold: 1,
|
|
1030
1200
|
signer_commitments: ['0x' + 'a'.repeat(64)],
|
|
1031
1201
|
description: '',
|
|
@@ -1042,7 +1212,7 @@ describe('Multisig', () => {
|
|
|
1042
1212
|
}),
|
|
1043
1213
|
});
|
|
1044
1214
|
|
|
1045
|
-
vi.mocked(
|
|
1215
|
+
vi.mocked(executeForSummaryAt).mockResolvedValueOnce({
|
|
1046
1216
|
toCommitment: () => ({
|
|
1047
1217
|
toHex: () => '0x' + 'f'.repeat(64),
|
|
1048
1218
|
}),
|
|
@@ -1053,6 +1223,65 @@ describe('Multisig', () => {
|
|
|
1053
1223
|
);
|
|
1054
1224
|
});
|
|
1055
1225
|
|
|
1226
|
+
/// A structurally valid anchor pinned to the wrong block must be rejected
|
|
1227
|
+
/// before anything executes against it: its commitment disagrees with the
|
|
1228
|
+
/// block commitment signed into the tx_summary.
|
|
1229
|
+
it('should reject a proposal whose chain anchor does not match the summary block commitment', async () => {
|
|
1230
|
+
const config = {
|
|
1231
|
+
threshold: 1,
|
|
1232
|
+
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
1233
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1234
|
+
};
|
|
1235
|
+
|
|
1236
|
+
const multisig = createTestMultisig(config);
|
|
1237
|
+
|
|
1238
|
+
mockFetch.mockResolvedValueOnce({
|
|
1239
|
+
ok: true,
|
|
1240
|
+
json: async () => ({
|
|
1241
|
+
proposals: [
|
|
1242
|
+
{
|
|
1243
|
+
account_id: '0x' + 'a'.repeat(30),
|
|
1244
|
+
nonce: 1,
|
|
1245
|
+
prev_commitment: '0x' + 'b'.repeat(64),
|
|
1246
|
+
delta_payload: {
|
|
1247
|
+
tx_summary: { data: 'AQID' },
|
|
1248
|
+
signatures: [],
|
|
1249
|
+
metadata: {
|
|
1250
|
+
proposal_type: 'add_signer',
|
|
1251
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
1252
|
+
target_threshold: 1,
|
|
1253
|
+
signer_commitments: ['0x' + 'a'.repeat(64)],
|
|
1254
|
+
description: '',
|
|
1255
|
+
},
|
|
1256
|
+
},
|
|
1257
|
+
status: {
|
|
1258
|
+
status: 'pending',
|
|
1259
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
1260
|
+
proposer_id: '0x' + 'c'.repeat(64),
|
|
1261
|
+
cosigner_sigs: [],
|
|
1262
|
+
},
|
|
1263
|
+
},
|
|
1264
|
+
],
|
|
1265
|
+
}),
|
|
1266
|
+
});
|
|
1267
|
+
|
|
1268
|
+
// Deserializes fine, but pins a different block than the one bound into
|
|
1269
|
+
// the summary (mock summary blockCommitment is 'b' * 64).
|
|
1270
|
+
const freed = vi.fn();
|
|
1271
|
+
vi.mocked(chainAnchorFromBase64).mockReturnValueOnce({
|
|
1272
|
+
commitment: () => ({ toHex: () => '0x' + 'e'.repeat(64) }),
|
|
1273
|
+
free: freed,
|
|
1274
|
+
serialize: () => new Uint8Array([9, 9, 9]),
|
|
1275
|
+
} as never);
|
|
1276
|
+
|
|
1277
|
+
const reExecutionsBefore = vi.mocked(executeForSummaryAt).mock.calls.length;
|
|
1278
|
+
await expect(multisig.syncProposals()).rejects.toThrow(
|
|
1279
|
+
'chain anchor does not match the block commitment bound into the tx_summary'
|
|
1280
|
+
);
|
|
1281
|
+
expect(vi.mocked(executeForSummaryAt).mock.calls.length).toBe(reExecutionsBefore);
|
|
1282
|
+
expect(freed).toHaveBeenCalledTimes(1);
|
|
1283
|
+
});
|
|
1284
|
+
|
|
1056
1285
|
it('should reject non-32-byte signer IDs from GUARDIAN proposals', async () => {
|
|
1057
1286
|
const config = {
|
|
1058
1287
|
threshold: 1,
|
|
@@ -1072,6 +1301,7 @@ describe('Multisig', () => {
|
|
|
1072
1301
|
signatures: [],
|
|
1073
1302
|
metadata: {
|
|
1074
1303
|
proposal_type: 'add_signer',
|
|
1304
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
1075
1305
|
target_threshold: 1,
|
|
1076
1306
|
signer_commitments: ['0x' + 'a'.repeat(64)],
|
|
1077
1307
|
description: '',
|
|
@@ -1119,6 +1349,7 @@ describe('Multisig', () => {
|
|
|
1119
1349
|
signatures: [],
|
|
1120
1350
|
metadata: {
|
|
1121
1351
|
proposal_type: 'add_signer',
|
|
1352
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
1122
1353
|
target_threshold: 2,
|
|
1123
1354
|
signer_commitments: ['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64)],
|
|
1124
1355
|
description: '',
|
|
@@ -1202,6 +1433,7 @@ describe('Multisig', () => {
|
|
|
1202
1433
|
|
|
1203
1434
|
const proposal = await multisig.createProposal(1, 'AQID', {
|
|
1204
1435
|
proposalType: 'add_signer',
|
|
1436
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
1205
1437
|
targetThreshold: 1,
|
|
1206
1438
|
targetSignerCommitments: ['0x' + 'a'.repeat(64)],
|
|
1207
1439
|
description: '',
|
|
@@ -1247,6 +1479,7 @@ describe('Multisig', () => {
|
|
|
1247
1479
|
await expect(
|
|
1248
1480
|
multisig.createProposal(1, 'AQID', {
|
|
1249
1481
|
proposalType: 'add_signer',
|
|
1482
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
1250
1483
|
targetThreshold: 1,
|
|
1251
1484
|
targetSignerCommitments: ['0x' + 'a'.repeat(64)],
|
|
1252
1485
|
description: '',
|
|
@@ -1289,7 +1522,7 @@ describe('Multisig', () => {
|
|
|
1289
1522
|
}),
|
|
1290
1523
|
});
|
|
1291
1524
|
|
|
1292
|
-
vi.mocked(
|
|
1525
|
+
vi.mocked(executeForSummaryAt).mockResolvedValueOnce({
|
|
1293
1526
|
toCommitment: () => ({
|
|
1294
1527
|
toHex: () => '0x' + 'f'.repeat(64),
|
|
1295
1528
|
}),
|
|
@@ -1298,6 +1531,7 @@ describe('Multisig', () => {
|
|
|
1298
1531
|
await expect(
|
|
1299
1532
|
multisig.createProposal(1, 'AQID', {
|
|
1300
1533
|
proposalType: 'add_signer',
|
|
1534
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
1301
1535
|
targetThreshold: 1,
|
|
1302
1536
|
targetSignerCommitments: ['0x' + 'a'.repeat(64)],
|
|
1303
1537
|
description: '',
|
|
@@ -1310,10 +1544,13 @@ describe('Multisig', () => {
|
|
|
1310
1544
|
it('should include the faucet asset in the proposal description', async () => {
|
|
1311
1545
|
const { executeForSummary } = await import('./transaction.js');
|
|
1312
1546
|
vi.mocked(executeForSummary).mockResolvedValue({
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1547
|
+
summary: {
|
|
1548
|
+
toCommitment: () => ({
|
|
1549
|
+
toHex: () => '0x' + 'c'.repeat(64),
|
|
1550
|
+
}),
|
|
1551
|
+
serialize: () => new Uint8Array([1, 2, 3]),
|
|
1552
|
+
},
|
|
1553
|
+
anchor: createMockChainAnchor(),
|
|
1317
1554
|
} as any);
|
|
1318
1555
|
|
|
1319
1556
|
const config = {
|
|
@@ -1333,6 +1570,7 @@ describe('Multisig', () => {
|
|
|
1333
1570
|
signatures: [],
|
|
1334
1571
|
metadata: {
|
|
1335
1572
|
proposal_type: 'p2id',
|
|
1573
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
1336
1574
|
recipient_id: '0xrecipient',
|
|
1337
1575
|
faucet_id: '0xfaucet',
|
|
1338
1576
|
amount: '100',
|
|
@@ -1355,7 +1593,7 @@ describe('Multisig', () => {
|
|
|
1355
1593
|
}),
|
|
1356
1594
|
});
|
|
1357
1595
|
|
|
1358
|
-
const proposal = await multisig.createP2idProposal('0xrecipient', '0xfaucet', 100n, 1);
|
|
1596
|
+
const proposal = await multisig.createP2idProposal('0xrecipient', '0xfaucet', 100n, { nonce: 1 });
|
|
1359
1597
|
|
|
1360
1598
|
expect(proposal.metadata.description).toBe('Send 100 of asset 0xfaucet... to 0xrecipien...');
|
|
1361
1599
|
});
|
|
@@ -1364,10 +1602,13 @@ describe('Multisig', () => {
|
|
|
1364
1602
|
const { executeForSummary, buildP2idTransactionRequest } = await import('./transaction.js');
|
|
1365
1603
|
const { NoteType } = await import('@miden-sdk/miden-sdk');
|
|
1366
1604
|
vi.mocked(executeForSummary).mockResolvedValue({
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1605
|
+
summary: {
|
|
1606
|
+
toCommitment: () => ({
|
|
1607
|
+
toHex: () => '0x' + 'c'.repeat(64),
|
|
1608
|
+
}),
|
|
1609
|
+
serialize: () => new Uint8Array([1, 2, 3]),
|
|
1610
|
+
},
|
|
1611
|
+
anchor: createMockChainAnchor(),
|
|
1371
1612
|
} as any);
|
|
1372
1613
|
|
|
1373
1614
|
const config = {
|
|
@@ -1387,6 +1628,7 @@ describe('Multisig', () => {
|
|
|
1387
1628
|
signatures: [],
|
|
1388
1629
|
metadata: {
|
|
1389
1630
|
proposal_type: 'p2id',
|
|
1631
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
1390
1632
|
recipient_id: '0xrecipient',
|
|
1391
1633
|
faucet_id: '0xfaucet',
|
|
1392
1634
|
amount: '100',
|
|
@@ -1410,7 +1652,8 @@ describe('Multisig', () => {
|
|
|
1410
1652
|
}),
|
|
1411
1653
|
});
|
|
1412
1654
|
|
|
1413
|
-
const proposal = await multisig.createP2idProposal('0xrecipient', '0xfaucet', 100n,
|
|
1655
|
+
const proposal = await multisig.createP2idProposal('0xrecipient', '0xfaucet', 100n, {
|
|
1656
|
+
nonce: 1,
|
|
1414
1657
|
noteType: NoteType.Private,
|
|
1415
1658
|
});
|
|
1416
1659
|
|
|
@@ -1420,12 +1663,11 @@ describe('Multisig', () => {
|
|
|
1420
1663
|
'0xrecipient',
|
|
1421
1664
|
'0xfaucet',
|
|
1422
1665
|
100n,
|
|
1423
|
-
expect.anything(),
|
|
1424
1666
|
{ noteType: NoteType.Private },
|
|
1425
1667
|
);
|
|
1426
1668
|
// ...and the rebuild-from-metadata path parses note_type back to Private.
|
|
1427
1669
|
const lastCall = vi.mocked(buildP2idTransactionRequest).mock.calls.at(-1)!;
|
|
1428
|
-
expect(lastCall[
|
|
1670
|
+
expect(lastCall[4]).toMatchObject({ noteType: NoteType.Private });
|
|
1429
1671
|
|
|
1430
1672
|
// The pushed wire metadata carries note_type so cosigners rebuild the
|
|
1431
1673
|
// same private note at verification/execution.
|
|
@@ -1435,6 +1677,137 @@ describe('Multisig', () => {
|
|
|
1435
1677
|
expect(proposal.metadata.proposalType).toBe('p2id');
|
|
1436
1678
|
expect((proposal.metadata as { noteType?: string }).noteType).toBe('private');
|
|
1437
1679
|
});
|
|
1680
|
+
|
|
1681
|
+
it('threads P2IDE reclaim/timelock heights into the request and wire metadata (issue #366)', async () => {
|
|
1682
|
+
const { executeForSummary, buildP2idTransactionRequest } = await import('./transaction.js');
|
|
1683
|
+
vi.mocked(executeForSummary).mockResolvedValue({
|
|
1684
|
+
summary: {
|
|
1685
|
+
toCommitment: () => ({
|
|
1686
|
+
toHex: () => '0x' + 'c'.repeat(64),
|
|
1687
|
+
}),
|
|
1688
|
+
serialize: () => new Uint8Array([1, 2, 3]),
|
|
1689
|
+
},
|
|
1690
|
+
anchor: createMockChainAnchor(),
|
|
1691
|
+
} as any);
|
|
1692
|
+
|
|
1693
|
+
const config = {
|
|
1694
|
+
threshold: 1,
|
|
1695
|
+
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
1696
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1697
|
+
};
|
|
1698
|
+
|
|
1699
|
+
const multisig = createTestMultisig(config);
|
|
1700
|
+
|
|
1701
|
+
const mockDelta = {
|
|
1702
|
+
account_id: '0x' + 'a'.repeat(30),
|
|
1703
|
+
nonce: 1,
|
|
1704
|
+
prev_commitment: '0x' + 'b'.repeat(64),
|
|
1705
|
+
delta_payload: {
|
|
1706
|
+
tx_summary: { data: 'AQID' },
|
|
1707
|
+
signatures: [],
|
|
1708
|
+
metadata: {
|
|
1709
|
+
proposal_type: 'p2id',
|
|
1710
|
+
recipient_id: '0xrecipient',
|
|
1711
|
+
faucet_id: '0xfaucet',
|
|
1712
|
+
amount: '100',
|
|
1713
|
+
reclaim_height: 12345,
|
|
1714
|
+
timelock_height: 700,
|
|
1715
|
+
description: '',
|
|
1716
|
+
},
|
|
1717
|
+
},
|
|
1718
|
+
status: {
|
|
1719
|
+
status: 'pending',
|
|
1720
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
1721
|
+
proposer_id: '0x' + 'c'.repeat(64),
|
|
1722
|
+
cosigner_sigs: [],
|
|
1723
|
+
},
|
|
1724
|
+
};
|
|
1725
|
+
|
|
1726
|
+
mockFetch.mockResolvedValueOnce({
|
|
1727
|
+
ok: true,
|
|
1728
|
+
json: async () => ({
|
|
1729
|
+
delta: mockDelta,
|
|
1730
|
+
commitment: '0x' + 'c'.repeat(64),
|
|
1731
|
+
}),
|
|
1732
|
+
});
|
|
1733
|
+
|
|
1734
|
+
const proposal = await multisig.createP2idProposal('0xrecipient', '0xfaucet', 100n, {
|
|
1735
|
+
nonce: 1,
|
|
1736
|
+
reclaimHeight: 12345,
|
|
1737
|
+
timelockHeight: 700,
|
|
1738
|
+
});
|
|
1739
|
+
|
|
1740
|
+
// Propose path builds the P2IDE note from the heights...
|
|
1741
|
+
const lastCall = vi.mocked(buildP2idTransactionRequest).mock.calls.at(-1)!;
|
|
1742
|
+
expect(lastCall[4]).toMatchObject({ reclaimHeight: 12345, timelockHeight: 700 });
|
|
1743
|
+
|
|
1744
|
+
// ...and the pushed wire metadata carries the heights so cosigners
|
|
1745
|
+
// rebuild the same P2IDE note at verification/execution.
|
|
1746
|
+
const pushBody = JSON.parse(mockFetch.mock.calls.at(-1)![1].body as string);
|
|
1747
|
+
expect(pushBody.delta_payload.metadata.reclaim_height).toBe(12345);
|
|
1748
|
+
expect(pushBody.delta_payload.metadata.timelock_height).toBe(700);
|
|
1749
|
+
|
|
1750
|
+
expect(proposal.metadata.proposalType).toBe('p2id');
|
|
1751
|
+
expect(proposal.metadata).toMatchObject({ reclaimHeight: 12345, timelockHeight: 700 });
|
|
1752
|
+
});
|
|
1753
|
+
|
|
1754
|
+
it('omits the heights from wire metadata for a plain P2ID send (pre-#366 shape)', async () => {
|
|
1755
|
+
const { executeForSummary } = await import('./transaction.js');
|
|
1756
|
+
vi.mocked(executeForSummary).mockResolvedValue({
|
|
1757
|
+
summary: {
|
|
1758
|
+
toCommitment: () => ({
|
|
1759
|
+
toHex: () => '0x' + 'c'.repeat(64),
|
|
1760
|
+
}),
|
|
1761
|
+
serialize: () => new Uint8Array([1, 2, 3]),
|
|
1762
|
+
},
|
|
1763
|
+
anchor: createMockChainAnchor(),
|
|
1764
|
+
} as any);
|
|
1765
|
+
|
|
1766
|
+
const config = {
|
|
1767
|
+
threshold: 1,
|
|
1768
|
+
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
1769
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
1770
|
+
};
|
|
1771
|
+
|
|
1772
|
+
const multisig = createTestMultisig(config);
|
|
1773
|
+
|
|
1774
|
+
const mockDelta = {
|
|
1775
|
+
account_id: '0x' + 'a'.repeat(30),
|
|
1776
|
+
nonce: 1,
|
|
1777
|
+
prev_commitment: '0x' + 'b'.repeat(64),
|
|
1778
|
+
delta_payload: {
|
|
1779
|
+
tx_summary: { data: 'AQID' },
|
|
1780
|
+
signatures: [],
|
|
1781
|
+
metadata: {
|
|
1782
|
+
proposal_type: 'p2id',
|
|
1783
|
+
recipient_id: '0xrecipient',
|
|
1784
|
+
faucet_id: '0xfaucet',
|
|
1785
|
+
amount: '100',
|
|
1786
|
+
description: '',
|
|
1787
|
+
},
|
|
1788
|
+
},
|
|
1789
|
+
status: {
|
|
1790
|
+
status: 'pending',
|
|
1791
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
1792
|
+
proposer_id: '0x' + 'c'.repeat(64),
|
|
1793
|
+
cosigner_sigs: [],
|
|
1794
|
+
},
|
|
1795
|
+
};
|
|
1796
|
+
|
|
1797
|
+
mockFetch.mockResolvedValueOnce({
|
|
1798
|
+
ok: true,
|
|
1799
|
+
json: async () => ({
|
|
1800
|
+
delta: mockDelta,
|
|
1801
|
+
commitment: '0x' + 'c'.repeat(64),
|
|
1802
|
+
}),
|
|
1803
|
+
});
|
|
1804
|
+
|
|
1805
|
+
await multisig.createP2idProposal('0xrecipient', '0xfaucet', 100n, { nonce: 1 });
|
|
1806
|
+
|
|
1807
|
+
const pushBody = JSON.parse(mockFetch.mock.calls.at(-1)![1].body as string);
|
|
1808
|
+
expect('reclaim_height' in pushBody.delta_payload.metadata).toBe(false);
|
|
1809
|
+
expect('timelock_height' in pushBody.delta_payload.metadata).toBe(false);
|
|
1810
|
+
});
|
|
1438
1811
|
});
|
|
1439
1812
|
|
|
1440
1813
|
describe('exportNoteToBytes / importNoteFromBytes (issue #356)', () => {
|
|
@@ -1561,6 +1934,7 @@ describe('Multisig', () => {
|
|
|
1561
1934
|
const proposal = {
|
|
1562
1935
|
metadata: {
|
|
1563
1936
|
proposalType: 'p2id',
|
|
1937
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
1564
1938
|
recipientId: '0x' + 'b'.repeat(30),
|
|
1565
1939
|
faucetId: '0x' + 'c'.repeat(30),
|
|
1566
1940
|
amount: '100',
|
|
@@ -1588,10 +1962,13 @@ describe('Multisig', () => {
|
|
|
1588
1962
|
describe('createChangeThresholdProposal', () => {
|
|
1589
1963
|
it('passes the signer scheme to update-signers requests', async () => {
|
|
1590
1964
|
vi.mocked(executeForSummary).mockResolvedValue({
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1965
|
+
summary: {
|
|
1966
|
+
toCommitment: () => ({
|
|
1967
|
+
toHex: () => '0x' + 'c'.repeat(64),
|
|
1968
|
+
}),
|
|
1969
|
+
serialize: () => new Uint8Array([1, 2, 3]),
|
|
1970
|
+
},
|
|
1971
|
+
anchor: createMockChainAnchor(),
|
|
1595
1972
|
} as any);
|
|
1596
1973
|
|
|
1597
1974
|
const ecdsaSigner: Signer = {
|
|
@@ -1616,6 +1993,7 @@ describe('Multisig', () => {
|
|
|
1616
1993
|
signatures: [],
|
|
1617
1994
|
metadata: {
|
|
1618
1995
|
proposal_type: 'change_threshold',
|
|
1996
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
1619
1997
|
target_threshold: 2,
|
|
1620
1998
|
description: '',
|
|
1621
1999
|
},
|
|
@@ -1637,7 +2015,7 @@ describe('Multisig', () => {
|
|
|
1637
2015
|
});
|
|
1638
2016
|
|
|
1639
2017
|
const multisig = createTestMultisig(config, ecdsaSigner);
|
|
1640
|
-
await multisig.createChangeThresholdProposal(2, 1);
|
|
2018
|
+
await multisig.createChangeThresholdProposal(2, { nonce: 1 });
|
|
1641
2019
|
|
|
1642
2020
|
expect(buildUpdateSignersTransactionRequest).toHaveBeenCalledWith(
|
|
1643
2021
|
mockWebClient,
|
|
@@ -1648,10 +2026,153 @@ describe('Multisig', () => {
|
|
|
1648
2026
|
});
|
|
1649
2027
|
});
|
|
1650
2028
|
|
|
2029
|
+
describe('createAddSignerProposal / createRemoveSignerProposal', () => {
|
|
2030
|
+
const config = {
|
|
2031
|
+
threshold: 2,
|
|
2032
|
+
signerCommitments: ['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64), '0x' + 'd'.repeat(64)],
|
|
2033
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2034
|
+
};
|
|
2035
|
+
|
|
2036
|
+
const mockPushResponse = (proposalType: string) => {
|
|
2037
|
+
mockFetch.mockResolvedValueOnce({
|
|
2038
|
+
ok: true,
|
|
2039
|
+
json: async () => ({
|
|
2040
|
+
delta: {
|
|
2041
|
+
account_id: '0x' + 'a'.repeat(30),
|
|
2042
|
+
nonce: 1,
|
|
2043
|
+
prev_commitment: '0x' + 'b'.repeat(64),
|
|
2044
|
+
delta_payload: {
|
|
2045
|
+
tx_summary: { data: 'AQID' },
|
|
2046
|
+
signatures: [],
|
|
2047
|
+
metadata: { proposal_type: proposalType, description: '' },
|
|
2048
|
+
},
|
|
2049
|
+
status: {
|
|
2050
|
+
status: 'pending',
|
|
2051
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
2052
|
+
proposer_id: '0x' + 'c'.repeat(64),
|
|
2053
|
+
cosigner_sigs: [],
|
|
2054
|
+
},
|
|
2055
|
+
},
|
|
2056
|
+
commitment: '0x' + 'c'.repeat(64),
|
|
2057
|
+
}),
|
|
2058
|
+
});
|
|
2059
|
+
};
|
|
2060
|
+
|
|
2061
|
+
beforeEach(() => {
|
|
2062
|
+
vi.mocked(executeForSummary).mockResolvedValue({
|
|
2063
|
+
summary: {
|
|
2064
|
+
toCommitment: () => ({ toHex: () => '0x' + 'c'.repeat(64) }),
|
|
2065
|
+
serialize: () => new Uint8Array([1, 2, 3]),
|
|
2066
|
+
},
|
|
2067
|
+
anchor: createMockChainAnchor(),
|
|
2068
|
+
} as any);
|
|
2069
|
+
});
|
|
2070
|
+
|
|
2071
|
+
it('add: passes newThreshold from the options bag and appends the commitment', async () => {
|
|
2072
|
+
mockPushResponse('add_signer');
|
|
2073
|
+
const newCommitment = '0x' + 'e'.repeat(64);
|
|
2074
|
+
|
|
2075
|
+
const multisig = createTestMultisig(config);
|
|
2076
|
+
await multisig.createAddSignerProposal(newCommitment, { nonce: 1, newThreshold: 3 });
|
|
2077
|
+
|
|
2078
|
+
expect(buildUpdateSignersTransactionRequest).toHaveBeenCalledWith(
|
|
2079
|
+
mockWebClient,
|
|
2080
|
+
3,
|
|
2081
|
+
[...config.signerCommitments, newCommitment],
|
|
2082
|
+
{ signatureScheme: mockSigner.scheme },
|
|
2083
|
+
);
|
|
2084
|
+
});
|
|
2085
|
+
|
|
2086
|
+
it('add: defaults to the current threshold when newThreshold is omitted', async () => {
|
|
2087
|
+
mockPushResponse('add_signer');
|
|
2088
|
+
|
|
2089
|
+
const multisig = createTestMultisig(config);
|
|
2090
|
+
await multisig.createAddSignerProposal('0x' + 'e'.repeat(64), { nonce: 1 });
|
|
2091
|
+
|
|
2092
|
+
expect(buildUpdateSignersTransactionRequest).toHaveBeenCalledWith(
|
|
2093
|
+
mockWebClient,
|
|
2094
|
+
config.threshold,
|
|
2095
|
+
expect.any(Array),
|
|
2096
|
+
{ signatureScheme: mockSigner.scheme },
|
|
2097
|
+
);
|
|
2098
|
+
});
|
|
2099
|
+
|
|
2100
|
+
it('remove: passes newThreshold from the options bag and drops the commitment', async () => {
|
|
2101
|
+
mockPushResponse('remove_signer');
|
|
2102
|
+
|
|
2103
|
+
const multisig = createTestMultisig(config);
|
|
2104
|
+
await multisig.createRemoveSignerProposal('0x' + 'd'.repeat(64), { nonce: 1, newThreshold: 1 });
|
|
2105
|
+
|
|
2106
|
+
expect(buildUpdateSignersTransactionRequest).toHaveBeenCalledWith(
|
|
2107
|
+
mockWebClient,
|
|
2108
|
+
1,
|
|
2109
|
+
[config.signerCommitments[0], config.signerCommitments[1]],
|
|
2110
|
+
{ signatureScheme: mockSigner.scheme },
|
|
2111
|
+
);
|
|
2112
|
+
});
|
|
2113
|
+
|
|
2114
|
+
it('remove: defaults to min(current threshold, remaining signers) when newThreshold is omitted', async () => {
|
|
2115
|
+
mockPushResponse('remove_signer');
|
|
2116
|
+
|
|
2117
|
+
const multisig = createTestMultisig(config);
|
|
2118
|
+
await multisig.createRemoveSignerProposal('0x' + 'd'.repeat(64), { nonce: 1 });
|
|
2119
|
+
|
|
2120
|
+
expect(buildUpdateSignersTransactionRequest).toHaveBeenCalledWith(
|
|
2121
|
+
mockWebClient,
|
|
2122
|
+
2,
|
|
2123
|
+
expect.any(Array),
|
|
2124
|
+
{ signatureScheme: mockSigner.scheme },
|
|
2125
|
+
);
|
|
2126
|
+
});
|
|
2127
|
+
});
|
|
2128
|
+
|
|
2129
|
+
describe('legacy positional-caller guard (issue #387)', () => {
|
|
2130
|
+
const config = {
|
|
2131
|
+
threshold: 1,
|
|
2132
|
+
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
2133
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2134
|
+
};
|
|
2135
|
+
|
|
2136
|
+
it('rejects a legacy positional nonce where the options bag is expected', async () => {
|
|
2137
|
+
const multisig = createTestMultisig(config);
|
|
2138
|
+
|
|
2139
|
+
await expect(
|
|
2140
|
+
multisig.createP2idProposal('0xrecipient', '0xfaucet', 100n, 1 as any),
|
|
2141
|
+
).rejects.toThrow(/issue #387/);
|
|
2142
|
+
await expect(
|
|
2143
|
+
multisig.createConsumeNotesProposal(['0x1'], 1 as any),
|
|
2144
|
+
).rejects.toThrow(/issue #387/);
|
|
2145
|
+
await expect(
|
|
2146
|
+
multisig.createAddSignerProposal('0x' + 'e'.repeat(64), 1 as any),
|
|
2147
|
+
).rejects.toThrow(/issue #387/);
|
|
2148
|
+
await expect(
|
|
2149
|
+
multisig.createCustomProposal(new Uint8Array([1]), 'label', 1 as any),
|
|
2150
|
+
).rejects.toThrow(/issue #387/);
|
|
2151
|
+
});
|
|
2152
|
+
|
|
2153
|
+
it('rejects a legacy trailing argument after the options slot', async () => {
|
|
2154
|
+
const multisig = createTestMultisig(config);
|
|
2155
|
+
|
|
2156
|
+
// Pre-#387 pattern: createP2idProposal(r, f, amount, nonceHole, { noteType })
|
|
2157
|
+
await expect(
|
|
2158
|
+
(multisig.createP2idProposal as any)('0xrecipient', '0xfaucet', 100n, undefined, {
|
|
2159
|
+
noteType: 'private',
|
|
2160
|
+
}),
|
|
2161
|
+
).rejects.toThrow(/issue #387/);
|
|
2162
|
+
// Pre-#387 pattern: createAddSignerProposal(commitment, nonceHole, newThreshold)
|
|
2163
|
+
await expect(
|
|
2164
|
+
(multisig.createAddSignerProposal as any)('0x' + 'e'.repeat(64), undefined, 3),
|
|
2165
|
+
).rejects.toThrow(/issue #387/);
|
|
2166
|
+
});
|
|
2167
|
+
});
|
|
2168
|
+
|
|
1651
2169
|
describe('createSwitchGuardianProposal', () => {
|
|
1652
2170
|
it('should verify new endpoint commitment before creating proposal', async () => {
|
|
1653
2171
|
vi.mocked(executeForSummary).mockResolvedValue({
|
|
1654
|
-
|
|
2172
|
+
summary: {
|
|
2173
|
+
serialize: () => new Uint8Array([1, 2, 3]),
|
|
2174
|
+
},
|
|
2175
|
+
anchor: createMockChainAnchor(),
|
|
1655
2176
|
} as any);
|
|
1656
2177
|
|
|
1657
2178
|
const config = {
|
|
@@ -1700,7 +2221,10 @@ describe('Multisig', () => {
|
|
|
1700
2221
|
|
|
1701
2222
|
it('should reject switch proposal when endpoint commitment does not match', async () => {
|
|
1702
2223
|
vi.mocked(executeForSummary).mockResolvedValue({
|
|
1703
|
-
|
|
2224
|
+
summary: {
|
|
2225
|
+
serialize: () => new Uint8Array([1, 2, 3]),
|
|
2226
|
+
},
|
|
2227
|
+
anchor: createMockChainAnchor(),
|
|
1704
2228
|
} as any);
|
|
1705
2229
|
|
|
1706
2230
|
const config = {
|
|
@@ -1723,7 +2247,10 @@ describe('Multisig', () => {
|
|
|
1723
2247
|
|
|
1724
2248
|
it('should use the signer scheme when resolving new GUARDIAN commitments', async () => {
|
|
1725
2249
|
vi.mocked(executeForSummary).mockResolvedValue({
|
|
1726
|
-
|
|
2250
|
+
summary: {
|
|
2251
|
+
serialize: () => new Uint8Array([1, 2, 3]),
|
|
2252
|
+
},
|
|
2253
|
+
anchor: createMockChainAnchor(),
|
|
1727
2254
|
} as any);
|
|
1728
2255
|
|
|
1729
2256
|
const ecdsaSigner: Signer = {
|
|
@@ -1782,10 +2309,13 @@ describe('Multisig', () => {
|
|
|
1782
2309
|
describe('createUpdateProcedureThresholdProposal', () => {
|
|
1783
2310
|
it('should create procedure-threshold update proposals', async () => {
|
|
1784
2311
|
vi.mocked(executeForSummary).mockResolvedValue({
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
2312
|
+
summary: {
|
|
2313
|
+
toCommitment: () => ({
|
|
2314
|
+
toHex: () => '0x' + 'c'.repeat(64),
|
|
2315
|
+
}),
|
|
2316
|
+
serialize: () => new Uint8Array([1, 2, 3]),
|
|
2317
|
+
},
|
|
2318
|
+
anchor: createMockChainAnchor(),
|
|
1789
2319
|
} as any);
|
|
1790
2320
|
|
|
1791
2321
|
const config = {
|
|
@@ -1805,6 +2335,7 @@ describe('Multisig', () => {
|
|
|
1805
2335
|
signatures: [],
|
|
1806
2336
|
metadata: {
|
|
1807
2337
|
proposal_type: 'update_procedure_threshold',
|
|
2338
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
1808
2339
|
target_threshold: 1,
|
|
1809
2340
|
target_procedure: 'send_asset',
|
|
1810
2341
|
description: '',
|
|
@@ -1826,7 +2357,7 @@ describe('Multisig', () => {
|
|
|
1826
2357
|
}),
|
|
1827
2358
|
});
|
|
1828
2359
|
|
|
1829
|
-
const proposal = await multisig.createUpdateProcedureThresholdProposal('send_asset', 1, 1);
|
|
2360
|
+
const proposal = await multisig.createUpdateProcedureThresholdProposal('send_asset', 1, { nonce: 1 });
|
|
1830
2361
|
|
|
1831
2362
|
expect(buildUpdateProcedureThresholdTransactionRequest).toHaveBeenCalledWith(
|
|
1832
2363
|
mockWebClient,
|
|
@@ -1843,10 +2374,13 @@ describe('Multisig', () => {
|
|
|
1843
2374
|
|
|
1844
2375
|
it('passes the signer scheme to ECDSA procedure-threshold updates', async () => {
|
|
1845
2376
|
vi.mocked(executeForSummary).mockResolvedValue({
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
2377
|
+
summary: {
|
|
2378
|
+
toCommitment: () => ({
|
|
2379
|
+
toHex: () => '0x' + 'c'.repeat(64),
|
|
2380
|
+
}),
|
|
2381
|
+
serialize: () => new Uint8Array([1, 2, 3]),
|
|
2382
|
+
},
|
|
2383
|
+
anchor: createMockChainAnchor(),
|
|
1850
2384
|
} as any);
|
|
1851
2385
|
|
|
1852
2386
|
const ecdsaSigner: Signer = {
|
|
@@ -1873,6 +2407,7 @@ describe('Multisig', () => {
|
|
|
1873
2407
|
signatures: [],
|
|
1874
2408
|
metadata: {
|
|
1875
2409
|
proposal_type: 'update_procedure_threshold',
|
|
2410
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
1876
2411
|
target_threshold: 1,
|
|
1877
2412
|
target_procedure: 'send_asset',
|
|
1878
2413
|
description: '',
|
|
@@ -1894,7 +2429,7 @@ describe('Multisig', () => {
|
|
|
1894
2429
|
}),
|
|
1895
2430
|
});
|
|
1896
2431
|
|
|
1897
|
-
await multisig.createUpdateProcedureThresholdProposal('send_asset', 1, 1);
|
|
2432
|
+
await multisig.createUpdateProcedureThresholdProposal('send_asset', 1, { nonce: 1 });
|
|
1898
2433
|
|
|
1899
2434
|
expect(buildUpdateProcedureThresholdTransactionRequest).toHaveBeenCalledWith(
|
|
1900
2435
|
mockWebClient,
|
|
@@ -1942,6 +2477,7 @@ describe('Multisig', () => {
|
|
|
1942
2477
|
|
|
1943
2478
|
await multisig.createProposal(1, 'AQID', {
|
|
1944
2479
|
proposalType: 'add_signer',
|
|
2480
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
1945
2481
|
targetThreshold: 1,
|
|
1946
2482
|
targetSignerCommitments: ['0x' + 'a'.repeat(64)],
|
|
1947
2483
|
description: '',
|
|
@@ -1965,6 +2501,7 @@ describe('Multisig', () => {
|
|
|
1965
2501
|
...mockDelta.delta_payload,
|
|
1966
2502
|
metadata: {
|
|
1967
2503
|
proposal_type: 'add_signer',
|
|
2504
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
1968
2505
|
description: '',
|
|
1969
2506
|
target_threshold: 1,
|
|
1970
2507
|
signer_commitments: ['0x' + 'a'.repeat(64)],
|
|
@@ -2019,12 +2556,13 @@ describe('Multisig', () => {
|
|
|
2019
2556
|
|
|
2020
2557
|
await multisig.createProposal(1, 'AQID', {
|
|
2021
2558
|
proposalType: 'add_signer',
|
|
2559
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2022
2560
|
targetThreshold: 1,
|
|
2023
2561
|
targetSignerCommitments: ['0x' + 'a'.repeat(64)],
|
|
2024
2562
|
description: '',
|
|
2025
2563
|
});
|
|
2026
2564
|
|
|
2027
|
-
vi.mocked(
|
|
2565
|
+
vi.mocked(executeForSummaryAt).mockResolvedValueOnce({
|
|
2028
2566
|
toCommitment: () => ({
|
|
2029
2567
|
toHex: () => '0x' + 'f'.repeat(64),
|
|
2030
2568
|
}),
|
|
@@ -2058,6 +2596,7 @@ describe('Multisig', () => {
|
|
|
2058
2596
|
signatures: [],
|
|
2059
2597
|
metadata: {
|
|
2060
2598
|
proposal_type: 'add_signer',
|
|
2599
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2061
2600
|
description: '',
|
|
2062
2601
|
target_threshold: 1,
|
|
2063
2602
|
signer_commitments: [mockSigner.commitment],
|
|
@@ -2091,7 +2630,7 @@ describe('Multisig', () => {
|
|
|
2091
2630
|
|
|
2092
2631
|
const multisig = createTestMultisig(config);
|
|
2093
2632
|
|
|
2094
|
-
vi.mocked(
|
|
2633
|
+
vi.mocked(executeForSummaryAt).mockResolvedValueOnce({
|
|
2095
2634
|
toCommitment: () => ({
|
|
2096
2635
|
toHex: () => '0x' + 'f'.repeat(64),
|
|
2097
2636
|
}),
|
|
@@ -2107,6 +2646,7 @@ describe('Multisig', () => {
|
|
|
2107
2646
|
signatures: [],
|
|
2108
2647
|
metadata: {
|
|
2109
2648
|
proposalType: 'add_signer',
|
|
2649
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2110
2650
|
targetThreshold: 1,
|
|
2111
2651
|
targetSignerCommitments: ['0x' + 'a'.repeat(64)],
|
|
2112
2652
|
description: '',
|
|
@@ -2127,7 +2667,7 @@ describe('Multisig', () => {
|
|
|
2127
2667
|
|
|
2128
2668
|
const multisig = createTestMultisig(config);
|
|
2129
2669
|
|
|
2130
|
-
vi.mocked(
|
|
2670
|
+
vi.mocked(executeForSummaryAt).mockResolvedValueOnce({
|
|
2131
2671
|
toCommitment: () => ({
|
|
2132
2672
|
toHex: () => '0x' + 'c'.repeat(64),
|
|
2133
2673
|
}),
|
|
@@ -2142,6 +2682,7 @@ describe('Multisig', () => {
|
|
|
2142
2682
|
signatures: [],
|
|
2143
2683
|
metadata: {
|
|
2144
2684
|
proposalType: 'add_signer',
|
|
2685
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2145
2686
|
targetThreshold: 1,
|
|
2146
2687
|
targetSignerCommitments: ['0x' + 'a'.repeat(64)],
|
|
2147
2688
|
description: '',
|
|
@@ -2151,12 +2692,13 @@ describe('Multisig', () => {
|
|
|
2151
2692
|
|
|
2152
2693
|
proposal.metadata = {
|
|
2153
2694
|
proposalType: 'add_signer',
|
|
2695
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2154
2696
|
targetThreshold: 2,
|
|
2155
2697
|
targetSignerCommitments: ['0x' + 'a'.repeat(64)],
|
|
2156
2698
|
description: '',
|
|
2157
2699
|
};
|
|
2158
2700
|
|
|
2159
|
-
vi.mocked(
|
|
2701
|
+
vi.mocked(executeForSummaryAt).mockResolvedValueOnce({
|
|
2160
2702
|
toCommitment: () => ({
|
|
2161
2703
|
toHex: () => '0x' + 'f'.repeat(64),
|
|
2162
2704
|
}),
|
|
@@ -2188,6 +2730,7 @@ describe('Multisig', () => {
|
|
|
2188
2730
|
signatures: [],
|
|
2189
2731
|
metadata: {
|
|
2190
2732
|
proposal_type: 'add_signer',
|
|
2733
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2191
2734
|
description: '',
|
|
2192
2735
|
target_threshold: 1,
|
|
2193
2736
|
signer_commitments: ['0x' + 'a'.repeat(64)],
|
|
@@ -2243,6 +2786,7 @@ describe('Multisig', () => {
|
|
|
2243
2786
|
signatures: [],
|
|
2244
2787
|
metadata: {
|
|
2245
2788
|
proposal_type: 'change_threshold',
|
|
2789
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2246
2790
|
description: '',
|
|
2247
2791
|
target_threshold: 2,
|
|
2248
2792
|
signer_commitments: ['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64)],
|
|
@@ -2293,11 +2837,12 @@ describe('Multisig', () => {
|
|
|
2293
2837
|
ok: false,
|
|
2294
2838
|
status: 404,
|
|
2295
2839
|
statusText: 'Not Found',
|
|
2840
|
+
headers: new Headers(),
|
|
2296
2841
|
// Feature 009: only a conforming { code, message, meta } envelope is
|
|
2297
2842
|
// folded into the error message; raw text bodies are dropped.
|
|
2298
2843
|
text: async () =>
|
|
2299
2844
|
JSON.stringify({
|
|
2300
|
-
code: '
|
|
2845
|
+
code: 'proposal_not_found',
|
|
2301
2846
|
message: 'Proposal not found',
|
|
2302
2847
|
meta: { retryable: false },
|
|
2303
2848
|
}),
|
|
@@ -2332,6 +2877,7 @@ describe('Multisig', () => {
|
|
|
2332
2877
|
],
|
|
2333
2878
|
metadata: {
|
|
2334
2879
|
proposalType: 'add_signer' as const,
|
|
2880
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2335
2881
|
targetThreshold: 1,
|
|
2336
2882
|
targetSignerCommitments: ['0x' + 'a'.repeat(64)],
|
|
2337
2883
|
description: '',
|
|
@@ -2370,6 +2916,7 @@ describe('Multisig', () => {
|
|
|
2370
2916
|
],
|
|
2371
2917
|
metadata: {
|
|
2372
2918
|
proposalType: 'change_threshold',
|
|
2919
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2373
2920
|
targetThreshold: 1,
|
|
2374
2921
|
targetSignerCommitments: ['0x' + 'a'.repeat(64)],
|
|
2375
2922
|
description: '',
|
|
@@ -2415,6 +2962,7 @@ describe('Multisig', () => {
|
|
|
2415
2962
|
],
|
|
2416
2963
|
metadata: {
|
|
2417
2964
|
proposalType: 'change_threshold',
|
|
2965
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2418
2966
|
targetThreshold: 1,
|
|
2419
2967
|
targetSignerCommitments: ['0x' + 'a'.repeat(64)],
|
|
2420
2968
|
description: '',
|
|
@@ -2441,6 +2989,7 @@ describe('Multisig', () => {
|
|
|
2441
2989
|
signatures: [],
|
|
2442
2990
|
metadata: {
|
|
2443
2991
|
proposalType: 'add_signer' as const,
|
|
2992
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2444
2993
|
targetThreshold: 2,
|
|
2445
2994
|
targetSignerCommitments: ['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64)],
|
|
2446
2995
|
description: '',
|
|
@@ -2516,6 +3065,7 @@ describe('Multisig', () => {
|
|
|
2516
3065
|
],
|
|
2517
3066
|
metadata: {
|
|
2518
3067
|
proposalType: 'change_threshold',
|
|
3068
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2519
3069
|
targetThreshold: 1,
|
|
2520
3070
|
targetSignerCommitments: ['0x' + 'a'.repeat(64)],
|
|
2521
3071
|
description: '',
|
|
@@ -2533,6 +3083,7 @@ describe('Multisig', () => {
|
|
|
2533
3083
|
signatures: [],
|
|
2534
3084
|
metadata: {
|
|
2535
3085
|
proposal_type: 'change_threshold',
|
|
3086
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2536
3087
|
target_threshold: 1,
|
|
2537
3088
|
signer_commitments: ['0x' + 'a'.repeat(64)],
|
|
2538
3089
|
},
|
|
@@ -2575,17 +3126,19 @@ describe('Multisig', () => {
|
|
|
2575
3126
|
expect.anything(),
|
|
2576
3127
|
expect.anything(),
|
|
2577
3128
|
expect.anything(),
|
|
2578
|
-
cosignerPubkey,
|
|
2579
|
-
cosignerSignature,
|
|
2580
3129
|
);
|
|
2581
3130
|
expect(vi.mocked(buildSignatureAdviceEntry)).toHaveBeenNthCalledWith(
|
|
2582
3131
|
2,
|
|
2583
3132
|
expect.anything(),
|
|
2584
3133
|
expect.anything(),
|
|
2585
3134
|
expect.anything(),
|
|
2586
|
-
ackPubkey,
|
|
2587
|
-
ackSignature,
|
|
2588
3135
|
);
|
|
3136
|
+
// The advice payload now comes from the SDK, so the routing assertion is
|
|
3137
|
+
// the commitment each entry is keyed on: cosigner first, GUARDIAN ack
|
|
3138
|
+
// second. Swapping the two entries must not pass.
|
|
3139
|
+
const adviceCalls = vi.mocked(buildSignatureAdviceEntry).mock.calls;
|
|
3140
|
+
expect(adviceCalls[0][0].toHex()).toBe(config.signerCommitments[0]);
|
|
3141
|
+
expect(adviceCalls[1][0].toHex()).toBe(config.guardianCommitment);
|
|
2589
3142
|
expect(mockWebClient.executeTransaction).not.toHaveBeenCalled();
|
|
2590
3143
|
expect(mockWebClient.proveTransaction).not.toHaveBeenCalled();
|
|
2591
3144
|
expect(mockWebClient.submitProvenTransaction).not.toHaveBeenCalled();
|
|
@@ -2627,6 +3180,7 @@ describe('Multisig', () => {
|
|
|
2627
3180
|
],
|
|
2628
3181
|
metadata: {
|
|
2629
3182
|
proposalType: 'switch_guardian',
|
|
3183
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2630
3184
|
newGuardianPubkey,
|
|
2631
3185
|
newGuardianEndpoint: 'http://new-guardian.com',
|
|
2632
3186
|
description: '',
|
|
@@ -2680,6 +3234,7 @@ describe('Multisig', () => {
|
|
|
2680
3234
|
signatures: [],
|
|
2681
3235
|
metadata: {
|
|
2682
3236
|
proposal_type: 'add_signer',
|
|
3237
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2683
3238
|
description: '',
|
|
2684
3239
|
target_threshold: 2,
|
|
2685
3240
|
signer_commitments: ['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64)],
|
|
@@ -2722,7 +3277,7 @@ describe('Multisig', () => {
|
|
|
2722
3277
|
const multisig = createTestMultisig(config);
|
|
2723
3278
|
const proposalId = '0x' + 'c'.repeat(64);
|
|
2724
3279
|
|
|
2725
|
-
vi.mocked(
|
|
3280
|
+
vi.mocked(executeForSummaryAt).mockResolvedValueOnce({
|
|
2726
3281
|
toCommitment: () => ({
|
|
2727
3282
|
toHex: () => '0x' + 'd'.repeat(64),
|
|
2728
3283
|
}),
|
|
@@ -2743,6 +3298,7 @@ describe('Multisig', () => {
|
|
|
2743
3298
|
],
|
|
2744
3299
|
metadata: {
|
|
2745
3300
|
proposalType: 'change_threshold',
|
|
3301
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2746
3302
|
targetThreshold: 1,
|
|
2747
3303
|
targetSignerCommitments: ['0x' + 'a'.repeat(64)],
|
|
2748
3304
|
description: '',
|
|
@@ -2780,6 +3336,7 @@ describe('Multisig', () => {
|
|
|
2780
3336
|
],
|
|
2781
3337
|
metadata: {
|
|
2782
3338
|
proposalType: 'switch_guardian',
|
|
3339
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2783
3340
|
newGuardianPubkey: '0x' + '1'.repeat(64),
|
|
2784
3341
|
newGuardianEndpoint: 'http://new-guardian.com',
|
|
2785
3342
|
description: '',
|
|
@@ -2827,6 +3384,7 @@ describe('Multisig', () => {
|
|
|
2827
3384
|
],
|
|
2828
3385
|
metadata: {
|
|
2829
3386
|
proposalType: 'switch_guardian',
|
|
3387
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2830
3388
|
newGuardianPubkey: '0x' + '1'.repeat(64),
|
|
2831
3389
|
newGuardianEndpoint: 'http://new-guardian.com',
|
|
2832
3390
|
description: '',
|
|
@@ -2907,6 +3465,7 @@ describe('Multisig', () => {
|
|
|
2907
3465
|
],
|
|
2908
3466
|
metadata: {
|
|
2909
3467
|
proposalType: 'change_threshold',
|
|
3468
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2910
3469
|
targetThreshold: 1,
|
|
2911
3470
|
targetSignerCommitments: ['0x' + 'a'.repeat(64)],
|
|
2912
3471
|
description: '',
|
|
@@ -2924,6 +3483,7 @@ describe('Multisig', () => {
|
|
|
2924
3483
|
signatures: [],
|
|
2925
3484
|
metadata: {
|
|
2926
3485
|
proposal_type: 'change_threshold',
|
|
3486
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
2927
3487
|
target_threshold: 1,
|
|
2928
3488
|
signer_commitments: ['0x' + 'a'.repeat(64)],
|
|
2929
3489
|
},
|
|
@@ -2998,6 +3558,7 @@ describe('Multisig', () => {
|
|
|
2998
3558
|
],
|
|
2999
3559
|
metadata: {
|
|
3000
3560
|
proposalType: 'switch_guardian',
|
|
3561
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3001
3562
|
newGuardianPubkey: '0x' + '1'.repeat(64),
|
|
3002
3563
|
newGuardianEndpoint: 'http://new-guardian.com',
|
|
3003
3564
|
description: '',
|
|
@@ -3045,6 +3606,7 @@ describe('Multisig', () => {
|
|
|
3045
3606
|
signatures: [],
|
|
3046
3607
|
metadata: {
|
|
3047
3608
|
proposal_type: 'add_signer',
|
|
3609
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3048
3610
|
description: '',
|
|
3049
3611
|
target_threshold: 2,
|
|
3050
3612
|
signer_commitments: ['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64)],
|
|
@@ -3078,7 +3640,7 @@ describe('Multisig', () => {
|
|
|
3078
3640
|
).rejects.toThrow('not ready for execution');
|
|
3079
3641
|
});
|
|
3080
3642
|
|
|
3081
|
-
it('should fail when GUARDIAN ack signature is missing
|
|
3643
|
+
it('should fail when GUARDIAN ack signature is missing', async () => {
|
|
3082
3644
|
const config = {
|
|
3083
3645
|
threshold: 1,
|
|
3084
3646
|
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
@@ -3096,6 +3658,7 @@ describe('Multisig', () => {
|
|
|
3096
3658
|
signatures: [],
|
|
3097
3659
|
metadata: {
|
|
3098
3660
|
proposal_type: 'add_signer',
|
|
3661
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3099
3662
|
description: '',
|
|
3100
3663
|
target_threshold: 1,
|
|
3101
3664
|
signer_commitments: ['0x' + 'a'.repeat(64)],
|
|
@@ -3188,6 +3751,7 @@ describe('Multisig', () => {
|
|
|
3188
3751
|
],
|
|
3189
3752
|
metadata: {
|
|
3190
3753
|
proposalType: 'change_threshold',
|
|
3754
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3191
3755
|
targetThreshold: 1,
|
|
3192
3756
|
targetSignerCommitments: ['0x' + 'a'.repeat(64)],
|
|
3193
3757
|
description: '',
|
|
@@ -3205,6 +3769,7 @@ describe('Multisig', () => {
|
|
|
3205
3769
|
signatures: [],
|
|
3206
3770
|
metadata: {
|
|
3207
3771
|
proposal_type: 'change_threshold',
|
|
3772
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3208
3773
|
target_threshold: 1,
|
|
3209
3774
|
signer_commitments: ['0x' + 'a'.repeat(64)],
|
|
3210
3775
|
},
|
|
@@ -3258,17 +3823,19 @@ describe('Multisig', () => {
|
|
|
3258
3823
|
expect.anything(),
|
|
3259
3824
|
expect.anything(),
|
|
3260
3825
|
expect.anything(),
|
|
3261
|
-
cosignerPubkey,
|
|
3262
|
-
cosignerSignature,
|
|
3263
3826
|
);
|
|
3264
3827
|
expect(vi.mocked(buildSignatureAdviceEntry)).toHaveBeenNthCalledWith(
|
|
3265
3828
|
2,
|
|
3266
3829
|
expect.anything(),
|
|
3267
3830
|
expect.anything(),
|
|
3268
3831
|
expect.anything(),
|
|
3269
|
-
ackPubkey,
|
|
3270
|
-
ackSignature,
|
|
3271
3832
|
);
|
|
3833
|
+
// The advice payload now comes from the SDK, so the routing assertion is
|
|
3834
|
+
// the commitment each entry is keyed on: cosigner first, GUARDIAN ack
|
|
3835
|
+
// second. Swapping the two entries must not pass.
|
|
3836
|
+
const adviceCalls = vi.mocked(buildSignatureAdviceEntry).mock.calls;
|
|
3837
|
+
expect(adviceCalls[0][0].toHex()).toBe(config.signerCommitments[0]);
|
|
3838
|
+
expect(adviceCalls[1][0].toHex()).toBe(config.guardianCommitment);
|
|
3272
3839
|
});
|
|
3273
3840
|
|
|
3274
3841
|
it('should execute imported ECDSA proposals with scheme-aware advice', async () => {
|
|
@@ -3313,6 +3880,7 @@ describe('Multisig', () => {
|
|
|
3313
3880
|
],
|
|
3314
3881
|
metadata: {
|
|
3315
3882
|
proposalType: 'change_threshold',
|
|
3883
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3316
3884
|
targetThreshold: 1,
|
|
3317
3885
|
targetSignerCommitments: ['0x' + 'a'.repeat(64)],
|
|
3318
3886
|
description: '',
|
|
@@ -3331,6 +3899,7 @@ describe('Multisig', () => {
|
|
|
3331
3899
|
signatures: [],
|
|
3332
3900
|
metadata: {
|
|
3333
3901
|
proposal_type: 'change_threshold',
|
|
3902
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3334
3903
|
target_threshold: 1,
|
|
3335
3904
|
signer_commitments: ['0x' + 'a'.repeat(64)],
|
|
3336
3905
|
},
|
|
@@ -3374,17 +3943,19 @@ describe('Multisig', () => {
|
|
|
3374
3943
|
expect.anything(),
|
|
3375
3944
|
expect.anything(),
|
|
3376
3945
|
expect.anything(),
|
|
3377
|
-
cosignerPubkey,
|
|
3378
|
-
cosignerSignature,
|
|
3379
3946
|
);
|
|
3380
3947
|
expect(vi.mocked(buildSignatureAdviceEntry)).toHaveBeenNthCalledWith(
|
|
3381
3948
|
2,
|
|
3382
3949
|
expect.anything(),
|
|
3383
3950
|
expect.anything(),
|
|
3384
3951
|
expect.anything(),
|
|
3385
|
-
ackPubkey,
|
|
3386
|
-
ackSignature,
|
|
3387
3952
|
);
|
|
3953
|
+
// The advice payload now comes from the SDK, so the routing assertion is
|
|
3954
|
+
// the commitment each entry is keyed on: cosigner first, GUARDIAN ack
|
|
3955
|
+
// second. Swapping the two entries must not pass.
|
|
3956
|
+
const adviceCalls = vi.mocked(buildSignatureAdviceEntry).mock.calls;
|
|
3957
|
+
expect(adviceCalls[0][0].toHex()).toBe(config.signerCommitments[0]);
|
|
3958
|
+
expect(adviceCalls[1][0].toHex()).toBe(config.guardianCommitment);
|
|
3388
3959
|
});
|
|
3389
3960
|
|
|
3390
3961
|
it('should verify switch_guardian endpoint commitment before execution', async () => {
|
|
@@ -3413,6 +3984,7 @@ describe('Multisig', () => {
|
|
|
3413
3984
|
],
|
|
3414
3985
|
metadata: {
|
|
3415
3986
|
proposalType: 'switch_guardian',
|
|
3987
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3416
3988
|
newGuardianPubkey,
|
|
3417
3989
|
newGuardianEndpoint: 'http://new-guardian.com',
|
|
3418
3990
|
description: '',
|
|
@@ -3435,6 +4007,7 @@ describe('Multisig', () => {
|
|
|
3435
4007
|
signatures: [],
|
|
3436
4008
|
metadata: {
|
|
3437
4009
|
proposal_type: 'switch_guardian',
|
|
4010
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3438
4011
|
new_guardian_pubkey: newGuardianPubkey,
|
|
3439
4012
|
new_guardian_endpoint: 'http://new-guardian.com',
|
|
3440
4013
|
},
|
|
@@ -3497,6 +4070,7 @@ describe('Multisig', () => {
|
|
|
3497
4070
|
],
|
|
3498
4071
|
metadata: {
|
|
3499
4072
|
proposalType: 'switch_guardian',
|
|
4073
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3500
4074
|
newGuardianPubkey,
|
|
3501
4075
|
newGuardianEndpoint: 'http://new-guardian.com',
|
|
3502
4076
|
description: '',
|
|
@@ -3548,6 +4122,7 @@ describe('Multisig', () => {
|
|
|
3548
4122
|
],
|
|
3549
4123
|
metadata: {
|
|
3550
4124
|
proposalType: 'switch_guardian',
|
|
4125
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3551
4126
|
newGuardianPubkey: '0x' + '1'.repeat(64),
|
|
3552
4127
|
newGuardianEndpoint: 'http://new-guardian.com',
|
|
3553
4128
|
description: '',
|
|
@@ -3595,6 +4170,7 @@ describe('Multisig', () => {
|
|
|
3595
4170
|
],
|
|
3596
4171
|
metadata: {
|
|
3597
4172
|
proposalType: 'switch_guardian',
|
|
4173
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3598
4174
|
newGuardianPubkey: '0x' + '1'.repeat(64),
|
|
3599
4175
|
newGuardianEndpoint: 'http://new-guardian.com',
|
|
3600
4176
|
description: '',
|
|
@@ -3647,6 +4223,7 @@ describe('Multisig', () => {
|
|
|
3647
4223
|
],
|
|
3648
4224
|
metadata: {
|
|
3649
4225
|
proposalType: 'switch_guardian',
|
|
4226
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3650
4227
|
newGuardianPubkey: '0x' + '1'.repeat(64),
|
|
3651
4228
|
newGuardianEndpoint: 'http://new-guardian.com',
|
|
3652
4229
|
description: '',
|
|
@@ -3682,9 +4259,33 @@ describe('Multisig', () => {
|
|
|
3682
4259
|
.mockRejectedValueOnce(transient)
|
|
3683
4260
|
.mockResolvedValueOnce({});
|
|
3684
4261
|
|
|
4262
|
+
mockFetch.mockResolvedValueOnce({
|
|
4263
|
+
ok: true,
|
|
4264
|
+
json: async () => ({
|
|
4265
|
+
account_id: '0x' + 'a'.repeat(30),
|
|
4266
|
+
nonce: 1,
|
|
4267
|
+
prev_commitment: '0x' + 'b'.repeat(64),
|
|
4268
|
+
delta_payload: {
|
|
4269
|
+
tx_summary: { data: 'AQID' },
|
|
4270
|
+
signatures: [],
|
|
4271
|
+
metadata: {
|
|
4272
|
+
proposal_type: 'b2agg',
|
|
4273
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
4274
|
+
description: '',
|
|
4275
|
+
},
|
|
4276
|
+
},
|
|
4277
|
+
status: {
|
|
4278
|
+
status: 'pending',
|
|
4279
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
4280
|
+
proposer_id: '0x' + 'c'.repeat(64),
|
|
4281
|
+
cosigner_sigs: [],
|
|
4282
|
+
},
|
|
4283
|
+
}),
|
|
4284
|
+
});
|
|
4285
|
+
|
|
3685
4286
|
vi.useFakeTimers();
|
|
3686
4287
|
try {
|
|
3687
|
-
const submission = multisig.submitTransaction({} as never);
|
|
4288
|
+
const submission = multisig.submitTransaction('0x' + 'c'.repeat(64), {} as never);
|
|
3688
4289
|
await vi.runAllTimersAsync();
|
|
3689
4290
|
await submission;
|
|
3690
4291
|
} finally {
|
|
@@ -3714,6 +4315,7 @@ describe('Multisig', () => {
|
|
|
3714
4315
|
signatures: [],
|
|
3715
4316
|
metadata: {
|
|
3716
4317
|
proposal_type: proposalType,
|
|
4318
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3717
4319
|
description: '',
|
|
3718
4320
|
},
|
|
3719
4321
|
},
|
|
@@ -3747,6 +4349,7 @@ describe('Multisig', () => {
|
|
|
3747
4349
|
};
|
|
3748
4350
|
builtinDelta.delta_payload.metadata = {
|
|
3749
4351
|
proposal_type: 'change_threshold',
|
|
4352
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3750
4353
|
description: '',
|
|
3751
4354
|
target_threshold: 1,
|
|
3752
4355
|
signer_commitments: ['0x' + 'a'.repeat(64)],
|
|
@@ -3790,7 +4393,7 @@ describe('Multisig', () => {
|
|
|
3790
4393
|
|
|
3791
4394
|
// Signed commitment comes from TransactionSummary.deserialize -> 'c' * 64.
|
|
3792
4395
|
// Make the binding request derive a different commitment so the check fails.
|
|
3793
|
-
vi.mocked(
|
|
4396
|
+
vi.mocked(executeForSummaryAt).mockResolvedValueOnce({
|
|
3794
4397
|
toCommitment: () => ({
|
|
3795
4398
|
toHex: () => '0x' + '9'.repeat(64),
|
|
3796
4399
|
}),
|
|
@@ -3854,6 +4457,7 @@ describe('Multisig', () => {
|
|
|
3854
4457
|
signatures: [],
|
|
3855
4458
|
metadata: {
|
|
3856
4459
|
proposal_type: 'add_signer',
|
|
4460
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3857
4461
|
target_threshold: 2,
|
|
3858
4462
|
signer_commitments: ['0x1', '0x2'],
|
|
3859
4463
|
},
|
|
@@ -3876,6 +4480,7 @@ describe('Multisig', () => {
|
|
|
3876
4480
|
|
|
3877
4481
|
const proposal = await multisig.createProposal(1, 'AQID', {
|
|
3878
4482
|
proposalType: 'add_signer',
|
|
4483
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3879
4484
|
targetThreshold: 2,
|
|
3880
4485
|
targetSignerCommitments: ['0x1', '0x2'],
|
|
3881
4486
|
description: '',
|
|
@@ -3917,6 +4522,7 @@ describe('Multisig', () => {
|
|
|
3917
4522
|
signatures: [],
|
|
3918
4523
|
metadata: {
|
|
3919
4524
|
proposal_type: 'p2id',
|
|
4525
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3920
4526
|
recipient_id: '0xrecipient',
|
|
3921
4527
|
faucet_id: '0xfaucet',
|
|
3922
4528
|
amount: '100',
|
|
@@ -3962,6 +4568,7 @@ describe('Multisig', () => {
|
|
|
3962
4568
|
signatures: [],
|
|
3963
4569
|
metadata: {
|
|
3964
4570
|
proposal_type: 'add_signer',
|
|
4571
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3965
4572
|
target_threshold: 2,
|
|
3966
4573
|
signer_commitments: ['0x1', '0x2'],
|
|
3967
4574
|
description: '',
|
|
@@ -3985,6 +4592,7 @@ describe('Multisig', () => {
|
|
|
3985
4592
|
|
|
3986
4593
|
const proposal = await multisig.createProposal(1, 'AQID', {
|
|
3987
4594
|
proposalType: 'consume_notes',
|
|
4595
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
3988
4596
|
noteIds: ['0xnote1', '0xnote2'],
|
|
3989
4597
|
description: '',
|
|
3990
4598
|
});
|
|
@@ -4010,6 +4618,7 @@ describe('Multisig', () => {
|
|
|
4010
4618
|
signatures: [],
|
|
4011
4619
|
metadata: {
|
|
4012
4620
|
proposal_type: 'add_signer',
|
|
4621
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
4013
4622
|
target_threshold: 1,
|
|
4014
4623
|
signer_commitments: ['0x' + 'a'.repeat(64)],
|
|
4015
4624
|
description: '',
|
|
@@ -4033,6 +4642,7 @@ describe('Multisig', () => {
|
|
|
4033
4642
|
|
|
4034
4643
|
const proposal = await multisig.createProposal(1, 'AQID', {
|
|
4035
4644
|
proposalType: 'p2id',
|
|
4645
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
4036
4646
|
recipientId: '0xrecipient',
|
|
4037
4647
|
faucetId: '0xfaucet',
|
|
4038
4648
|
amount: '100',
|
|
@@ -4060,6 +4670,7 @@ describe('Multisig', () => {
|
|
|
4060
4670
|
signatures: [],
|
|
4061
4671
|
metadata: {
|
|
4062
4672
|
proposalType: 'add_signer',
|
|
4673
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
4063
4674
|
targetThreshold: 2,
|
|
4064
4675
|
targetSignerCommitments: ['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64)],
|
|
4065
4676
|
description: '',
|
|
@@ -4083,6 +4694,7 @@ describe('Multisig', () => {
|
|
|
4083
4694
|
|
|
4084
4695
|
const proposal = await multisig.createProposal(1, 'AQID', {
|
|
4085
4696
|
proposalType: 'switch_guardian',
|
|
4697
|
+
chainAnchor: MOCK_CHAIN_ANCHOR_B64,
|
|
4086
4698
|
newGuardianPubkey: '0xnewpubkey',
|
|
4087
4699
|
newGuardianEndpoint: 'http://new-guardian.com',
|
|
4088
4700
|
description: '',
|
|
@@ -4113,6 +4725,7 @@ describe('Multisig', () => {
|
|
|
4113
4725
|
signatures: [],
|
|
4114
4726
|
metadata: {
|
|
4115
4727
|
proposal_type: 'add_signer',
|
|
4728
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
4116
4729
|
target_threshold: 2,
|
|
4117
4730
|
signer_commitments: ['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64)],
|
|
4118
4731
|
description: '',
|
|
@@ -4149,6 +4762,7 @@ describe('Multisig', () => {
|
|
|
4149
4762
|
...mockProposalsPending[0].delta_payload,
|
|
4150
4763
|
metadata: {
|
|
4151
4764
|
proposal_type: 'add_signer',
|
|
4765
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
4152
4766
|
target_threshold: 2,
|
|
4153
4767
|
signer_commitments: ['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64)],
|
|
4154
4768
|
description: '',
|
|
@@ -4253,6 +4867,7 @@ describe('Multisig', () => {
|
|
|
4253
4867
|
signatures: [],
|
|
4254
4868
|
metadata: {
|
|
4255
4869
|
proposal_type: 'change_threshold',
|
|
4870
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
4256
4871
|
target_threshold: 3,
|
|
4257
4872
|
signer_commitments: ['0xa', '0xb', '0xc'],
|
|
4258
4873
|
salt: '0xlegacysalt',
|
|
@@ -4303,6 +4918,7 @@ describe('Multisig', () => {
|
|
|
4303
4918
|
signatures: [],
|
|
4304
4919
|
metadata: {
|
|
4305
4920
|
proposal_type: 'p2id',
|
|
4921
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
4306
4922
|
recipient_id: '0xrecipient',
|
|
4307
4923
|
faucet_id: '0xfaucet',
|
|
4308
4924
|
amount: '12345',
|
|
@@ -4359,6 +4975,7 @@ describe('Multisig', () => {
|
|
|
4359
4975
|
signatures: [],
|
|
4360
4976
|
metadata: {
|
|
4361
4977
|
proposal_type: 'switch_guardian',
|
|
4978
|
+
chain_anchor: MOCK_CHAIN_ANCHOR_B64,
|
|
4362
4979
|
new_guardian_pubkey: '0xnewpubkey',
|
|
4363
4980
|
new_guardian_endpoint: 'http://new-guardian.com',
|
|
4364
4981
|
salt: '0xsalt',
|