@openzeppelin/miden-multisig-client 0.14.8 → 0.14.9
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 +47 -0
- package/dist/multisig/proposal/execution.js +3 -2
- package/dist/multisig/proposal/execution.js.map +1 -1
- package/dist/multisig.d.ts +28 -5
- package/dist/multisig.d.ts.map +1 -1
- package/dist/multisig.js +173 -5
- package/dist/multisig.js.map +1 -1
- package/dist/multisig.test.js +110 -0
- package/dist/multisig.test.js.map +1 -1
- package/dist/proposal/metadata.d.ts.map +1 -1
- package/dist/proposal/metadata.js +14 -5
- package/dist/proposal/metadata.js.map +1 -1
- package/dist/proposal/metadata.test.js +44 -0
- package/dist/proposal/metadata.test.js.map +1 -1
- package/dist/types/proposal.d.ts +16 -5
- package/dist/types/proposal.d.ts.map +1 -1
- package/dist/types/proposal.js.map +1 -1
- package/package.json +2 -2
- package/src/multisig.test.ts +139 -0
- package/src/multisig.ts +260 -5
- package/src/proposal/metadata.test.ts +53 -1
- package/src/proposal/metadata.ts +15 -6
- package/src/types/proposal.ts +24 -9
- package/src/multisig/proposal/execution.ts +0 -385
- package/src/multisig/proposal/parser.ts +0 -191
package/dist/multisig.test.js
CHANGED
|
@@ -37,6 +37,9 @@ vi.mock('@miden-sdk/miden-sdk', () => ({
|
|
|
37
37
|
toPreparedSignature: () => [1, 2, 3],
|
|
38
38
|
}),
|
|
39
39
|
},
|
|
40
|
+
TransactionRequest: {
|
|
41
|
+
deserialize: vi.fn().mockReturnValue({}),
|
|
42
|
+
},
|
|
40
43
|
AdviceMap: vi.fn().mockImplementation(() => ({
|
|
41
44
|
insert: vi.fn(),
|
|
42
45
|
})),
|
|
@@ -2534,6 +2537,113 @@ describe('Multisig', () => {
|
|
|
2534
2537
|
await expect(multisig.executeProposal(proposalId)).rejects.toThrow('Duplicate advice-map key detected');
|
|
2535
2538
|
});
|
|
2536
2539
|
});
|
|
2540
|
+
describe('prepareCustomExecution', () => {
|
|
2541
|
+
const requestBytes = new Uint8Array([9, 8, 7]);
|
|
2542
|
+
function customDelta(proposalType, cosignerSigs) {
|
|
2543
|
+
return {
|
|
2544
|
+
account_id: '0x' + 'a'.repeat(30),
|
|
2545
|
+
nonce: 1,
|
|
2546
|
+
prev_commitment: '0x' + 'b'.repeat(64),
|
|
2547
|
+
delta_payload: {
|
|
2548
|
+
tx_summary: { data: 'AQID' },
|
|
2549
|
+
signatures: [],
|
|
2550
|
+
metadata: {
|
|
2551
|
+
proposal_type: proposalType,
|
|
2552
|
+
description: '',
|
|
2553
|
+
},
|
|
2554
|
+
},
|
|
2555
|
+
status: {
|
|
2556
|
+
status: 'pending',
|
|
2557
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
2558
|
+
proposer_id: '0x' + 'c'.repeat(64),
|
|
2559
|
+
cosigner_sigs: cosignerSigs,
|
|
2560
|
+
},
|
|
2561
|
+
};
|
|
2562
|
+
}
|
|
2563
|
+
function falconSig(signerId) {
|
|
2564
|
+
return {
|
|
2565
|
+
signer_id: signerId,
|
|
2566
|
+
signature: { scheme: 'falcon', signature: '0x' + 'e'.repeat(128) },
|
|
2567
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
2568
|
+
};
|
|
2569
|
+
}
|
|
2570
|
+
it('rejects a built-in proposal type', async () => {
|
|
2571
|
+
const config = {
|
|
2572
|
+
threshold: 1,
|
|
2573
|
+
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
2574
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2575
|
+
};
|
|
2576
|
+
const multisig = new Multisig(mockAccount, config, guardian, mockSigner, mockWebClient);
|
|
2577
|
+
const builtinDelta = {
|
|
2578
|
+
...customDelta('change_threshold', [falconSig('0x' + 'a'.repeat(64))]),
|
|
2579
|
+
};
|
|
2580
|
+
builtinDelta.delta_payload.metadata = {
|
|
2581
|
+
proposal_type: 'change_threshold',
|
|
2582
|
+
description: '',
|
|
2583
|
+
target_threshold: 1,
|
|
2584
|
+
signer_commitments: ['0x' + 'a'.repeat(64)],
|
|
2585
|
+
};
|
|
2586
|
+
mockFetch.mockResolvedValueOnce({
|
|
2587
|
+
ok: true,
|
|
2588
|
+
json: async () => builtinDelta,
|
|
2589
|
+
});
|
|
2590
|
+
await expect(multisig.prepareCustomExecution('0x' + 'c'.repeat(64), requestBytes)).rejects.toThrow('prepareCustomExecution is only for custom proposals');
|
|
2591
|
+
});
|
|
2592
|
+
it('rejects a proposal that is below its signature threshold', async () => {
|
|
2593
|
+
const config = {
|
|
2594
|
+
threshold: 2,
|
|
2595
|
+
signerCommitments: ['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64)],
|
|
2596
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2597
|
+
};
|
|
2598
|
+
const multisig = new Multisig(mockAccount, config, guardian, mockSigner, mockWebClient);
|
|
2599
|
+
mockFetch.mockResolvedValueOnce({
|
|
2600
|
+
ok: true,
|
|
2601
|
+
json: async () => customDelta('b2agg', [falconSig('0x' + 'a'.repeat(64))]),
|
|
2602
|
+
});
|
|
2603
|
+
await expect(multisig.prepareCustomExecution('0x' + 'c'.repeat(64), requestBytes)).rejects.toThrow('have 1 of 2 required signatures');
|
|
2604
|
+
});
|
|
2605
|
+
it('rejects when the rebuilt request does not reproduce the signed commitment', async () => {
|
|
2606
|
+
const config = {
|
|
2607
|
+
threshold: 1,
|
|
2608
|
+
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
2609
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2610
|
+
};
|
|
2611
|
+
const multisig = new Multisig(mockAccount, config, guardian, mockSigner, mockWebClient);
|
|
2612
|
+
// Signed commitment comes from TransactionSummary.deserialize -> 'c' * 64.
|
|
2613
|
+
// Make the binding request derive a different commitment so the check fails.
|
|
2614
|
+
vi.mocked(executeForSummary).mockResolvedValueOnce({
|
|
2615
|
+
toCommitment: () => ({
|
|
2616
|
+
toHex: () => '0x' + '9'.repeat(64),
|
|
2617
|
+
}),
|
|
2618
|
+
serialize: () => new Uint8Array([1, 2, 3]),
|
|
2619
|
+
});
|
|
2620
|
+
mockFetch.mockResolvedValueOnce({
|
|
2621
|
+
ok: true,
|
|
2622
|
+
json: async () => customDelta('b2agg', [falconSig('0x' + 'a'.repeat(64))]),
|
|
2623
|
+
});
|
|
2624
|
+
await expect(multisig.prepareCustomExecution('0x' + 'c'.repeat(64), requestBytes)).rejects.toThrow('Custom proposal binding mismatch');
|
|
2625
|
+
});
|
|
2626
|
+
it('fails when GUARDIAN does not return an acknowledgment signature', async () => {
|
|
2627
|
+
const config = {
|
|
2628
|
+
threshold: 1,
|
|
2629
|
+
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
2630
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
2631
|
+
};
|
|
2632
|
+
const multisig = new Multisig(mockAccount, config, guardian, mockSigner, mockWebClient);
|
|
2633
|
+
const ready = customDelta('b2agg', [falconSig('0x' + 'a'.repeat(64))]);
|
|
2634
|
+
// getDeltaProposal
|
|
2635
|
+
mockFetch.mockResolvedValueOnce({
|
|
2636
|
+
ok: true,
|
|
2637
|
+
json: async () => ready,
|
|
2638
|
+
});
|
|
2639
|
+
// pushDelta returns no ack_sig
|
|
2640
|
+
mockFetch.mockResolvedValueOnce({
|
|
2641
|
+
ok: true,
|
|
2642
|
+
json: async () => ({ ...ready, ack_sig: null }),
|
|
2643
|
+
});
|
|
2644
|
+
await expect(multisig.prepareCustomExecution('0x' + 'c'.repeat(64), requestBytes)).rejects.toThrow('GUARDIAN did not return acknowledgment signature');
|
|
2645
|
+
});
|
|
2646
|
+
});
|
|
2537
2647
|
describe('proposal metadata preservation', () => {
|
|
2538
2648
|
it('should preserve local metadata when syncing proposals', async () => {
|
|
2539
2649
|
const config = {
|