@openzeppelin/miden-multisig-client 0.17.0-rc.2 → 0.17.0
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 +172 -47
- package/dist/account/builder.d.ts +2 -2
- package/dist/account/builder.d.ts.map +1 -1
- package/dist/account/builder.js +49 -24
- package/dist/account/builder.js.map +1 -1
- package/dist/connectivity.d.ts +2 -0
- package/dist/connectivity.d.ts.map +1 -1
- package/dist/connectivity.js +7 -4
- package/dist/connectivity.js.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/multisig/authArgErrors.d.ts +59 -0
- package/dist/multisig/authArgErrors.d.ts.map +1 -0
- package/dist/multisig/authArgErrors.js +115 -0
- package/dist/multisig/authArgErrors.js.map +1 -0
- package/dist/multisig/helpers.d.ts +5 -0
- package/dist/multisig/helpers.d.ts.map +1 -1
- package/dist/multisig/helpers.js +7 -2
- package/dist/multisig/helpers.js.map +1 -1
- package/dist/multisig.d.ts +140 -0
- package/dist/multisig.d.ts.map +1 -1
- package/dist/multisig.js +419 -12
- package/dist/multisig.js.map +1 -1
- package/dist/procedures.d.ts +1 -1
- package/dist/procedures.js +1 -1
- package/dist/recovery/proposalNoteImport.d.ts +173 -0
- package/dist/recovery/proposalNoteImport.d.ts.map +1 -0
- package/dist/recovery/proposalNoteImport.js +411 -0
- package/dist/recovery/proposalNoteImport.js.map +1 -0
- package/dist/recovery/publicNoteBackfill.d.ts +168 -0
- package/dist/recovery/publicNoteBackfill.d.ts.map +1 -0
- package/dist/recovery/publicNoteBackfill.js +368 -0
- package/dist/recovery/publicNoteBackfill.js.map +1 -0
- package/dist/recovery/recoverNotes.d.ts +147 -0
- package/dist/recovery/recoverNotes.d.ts.map +1 -0
- package/dist/recovery/recoverNotes.js +163 -0
- package/dist/recovery/recoverNotes.js.map +1 -0
- package/dist/recovery/transportDrain.d.ts +124 -0
- package/dist/recovery/transportDrain.d.ts.map +1 -0
- package/dist/recovery/transportDrain.js +262 -0
- package/dist/recovery/transportDrain.js.map +1 -0
- package/dist/transaction/consumeNotes.d.ts.map +1 -1
- package/dist/transaction/consumeNotes.js +4 -1
- package/dist/transaction/consumeNotes.js.map +1 -1
- package/dist/transaction/p2id.d.ts.map +1 -1
- package/dist/transaction/p2id.js +4 -1
- package/dist/transaction/p2id.js.map +1 -1
- package/dist/transaction/summary.d.ts +10 -4
- package/dist/transaction/summary.d.ts.map +1 -1
- package/dist/transaction/summary.js +13 -7
- package/dist/transaction/summary.js.map +1 -1
- package/dist/transaction/updateGuardian.js +4 -1
- package/dist/transaction/updateGuardian.js.map +1 -1
- package/dist/transaction/updateProcedureThreshold.js +4 -1
- package/dist/transaction/updateProcedureThreshold.js.map +1 -1
- package/dist/transaction/updateSigners.js +4 -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/package.json +14 -10
- package/src/account/builder.ts +87 -35
- package/src/connectivity.ts +9 -4
- package/src/index.ts +34 -1
- package/src/multisig/authArgErrors.ts +138 -0
- package/src/multisig/helpers.ts +7 -2
- package/src/multisig.ts +513 -20
- package/src/procedures.ts +1 -1
- package/src/recovery/proposalNoteImport.ts +548 -0
- package/src/recovery/publicNoteBackfill.ts +502 -0
- package/src/recovery/recoverNotes.ts +288 -0
- package/src/recovery/transportDrain.ts +330 -0
- package/src/transaction/consumeNotes.ts +4 -1
- package/src/transaction/p2id.ts +4 -1
- package/src/transaction/summary.ts +13 -7
- package/src/transaction/updateGuardian.ts +4 -1
- package/src/transaction/updateProcedureThreshold.ts +4 -1
- package/src/transaction/updateSigners.ts +4 -1
- package/src/transaction.ts +1 -1
- package/dist/account/builder.test.d.ts +0 -2
- package/dist/account/builder.test.d.ts.map +0 -1
- package/dist/account/builder.test.js +0 -166
- package/dist/account/builder.test.js.map +0 -1
- package/dist/account/masm/account-components/auth.d.ts +0 -2
- package/dist/account/masm/account-components/auth.d.ts.map +0 -1
- package/dist/account/masm/account-components/auth.js +0 -46
- package/dist/account/masm/account-components/auth.js.map +0 -1
- package/dist/account/masm/index.d.ts +0 -2
- package/dist/account/masm/index.d.ts.map +0 -1
- package/dist/account/masm/index.js +0 -4
- package/dist/account/masm/index.js.map +0 -1
- package/dist/account/masm.d.ts +0 -2
- package/dist/account/masm.d.ts.map +0 -1
- package/dist/account/masm.js +0 -4
- package/dist/account/masm.js.map +0 -1
- package/dist/account/storage.test.d.ts +0 -2
- package/dist/account/storage.test.d.ts.map +0 -1
- package/dist/account/storage.test.js +0 -73
- package/dist/account/storage.test.js.map +0 -1
- package/dist/client.test.d.ts +0 -2
- package/dist/client.test.d.ts.map +0 -1
- package/dist/client.test.js +0 -380
- package/dist/client.test.js.map +0 -1
- package/dist/connectivity.test.d.ts +0 -2
- package/dist/connectivity.test.d.ts.map +0 -1
- package/dist/connectivity.test.js +0 -61
- package/dist/connectivity.test.js.map +0 -1
- package/dist/inspector.test.d.ts +0 -2
- package/dist/inspector.test.d.ts.map +0 -1
- package/dist/inspector.test.js +0 -425
- package/dist/inspector.test.js.map +0 -1
- package/dist/lookupAuth.test.d.ts +0 -2
- package/dist/lookupAuth.test.d.ts.map +0 -1
- package/dist/lookupAuth.test.js +0 -138
- package/dist/lookupAuth.test.js.map +0 -1
- package/dist/multisig/consumeNotesErrors.test.d.ts +0 -2
- package/dist/multisig/consumeNotesErrors.test.d.ts.map +0 -1
- package/dist/multisig/consumeNotesErrors.test.js +0 -28
- package/dist/multisig/consumeNotesErrors.test.js.map +0 -1
- package/dist/multisig/helpers.test.d.ts +0 -2
- package/dist/multisig/helpers.test.d.ts.map +0 -1
- package/dist/multisig/helpers.test.js +0 -94
- package/dist/multisig/helpers.test.js.map +0 -1
- package/dist/multisig.test.d.ts +0 -2
- package/dist/multisig.test.d.ts.map +0 -1
- package/dist/multisig.test.js +0 -4112
- package/dist/multisig.test.js.map +0 -1
- package/dist/proposal/factory.test.d.ts +0 -2
- package/dist/proposal/factory.test.d.ts.map +0 -1
- package/dist/proposal/factory.test.js +0 -32
- package/dist/proposal/factory.test.js.map +0 -1
- package/dist/proposal/metadata.test.d.ts +0 -2
- package/dist/proposal/metadata.test.d.ts.map +0 -1
- package/dist/proposal/metadata.test.js +0 -193
- package/dist/proposal/metadata.test.js.map +0 -1
- package/dist/prover/config.test.d.ts +0 -2
- package/dist/prover/config.test.d.ts.map +0 -1
- package/dist/prover/config.test.js +0 -54
- package/dist/prover/config.test.js.map +0 -1
- package/dist/prover/errors.test.d.ts +0 -2
- package/dist/prover/errors.test.d.ts.map +0 -1
- package/dist/prover/errors.test.js +0 -29
- package/dist/prover/errors.test.js.map +0 -1
- package/dist/prover/retry.test.d.ts +0 -2
- package/dist/prover/retry.test.d.ts.map +0 -1
- package/dist/prover/retry.test.js +0 -20
- package/dist/prover/retry.test.js.map +0 -1
- package/dist/prover/workflow.test.d.ts +0 -2
- package/dist/prover/workflow.test.d.ts.map +0 -1
- package/dist/prover/workflow.test.js +0 -105
- package/dist/prover/workflow.test.js.map +0 -1
- package/dist/raw-client.test.d.ts +0 -2
- package/dist/raw-client.test.d.ts.map +0 -1
- package/dist/raw-client.test.js +0 -111
- package/dist/raw-client.test.js.map +0 -1
- package/dist/rpc/config.test.d.ts +0 -2
- package/dist/rpc/config.test.d.ts.map +0 -1
- package/dist/rpc/config.test.js +0 -24
- package/dist/rpc/config.test.js.map +0 -1
- package/dist/rpc/errors.test.d.ts +0 -2
- package/dist/rpc/errors.test.d.ts.map +0 -1
- package/dist/rpc/errors.test.js +0 -34
- package/dist/rpc/errors.test.js.map +0 -1
- package/dist/rpc/retry.test.d.ts +0 -2
- package/dist/rpc/retry.test.d.ts.map +0 -1
- package/dist/rpc/retry.test.js +0 -98
- package/dist/rpc/retry.test.js.map +0 -1
- package/dist/signers/ecdsa.test.d.ts +0 -2
- package/dist/signers/ecdsa.test.d.ts.map +0 -1
- package/dist/signers/ecdsa.test.js +0 -88
- package/dist/signers/ecdsa.test.js.map +0 -1
- package/dist/signers/falcon.test.d.ts +0 -2
- package/dist/signers/falcon.test.d.ts.map +0 -1
- package/dist/signers/falcon.test.js +0 -161
- package/dist/signers/falcon.test.js.map +0 -1
- package/dist/signers/miden-wallet.ecdsa-recovery.test.d.ts +0 -2
- package/dist/signers/miden-wallet.ecdsa-recovery.test.d.ts.map +0 -1
- package/dist/signers/miden-wallet.ecdsa-recovery.test.js +0 -148
- package/dist/signers/miden-wallet.ecdsa-recovery.test.js.map +0 -1
- package/dist/signers/miden-wallet.test.d.ts +0 -2
- package/dist/signers/miden-wallet.test.d.ts.map +0 -1
- package/dist/signers/miden-wallet.test.js +0 -164
- package/dist/signers/miden-wallet.test.js.map +0 -1
- package/dist/signers/para.test.d.ts +0 -2
- package/dist/signers/para.test.d.ts.map +0 -1
- package/dist/signers/para.test.js +0 -146
- package/dist/signers/para.test.js.map +0 -1
- package/dist/transaction/index.d.ts +0 -8
- package/dist/transaction/index.d.ts.map +0 -1
- package/dist/transaction/index.js +0 -7
- package/dist/transaction/index.js.map +0 -1
- package/dist/transaction/p2id.test.d.ts +0 -2
- package/dist/transaction/p2id.test.d.ts.map +0 -1
- package/dist/transaction/p2id.test.js +0 -246
- package/dist/transaction/p2id.test.js.map +0 -1
- package/dist/transaction/rpoRandomCoin.test.d.ts +0 -2
- package/dist/transaction/rpoRandomCoin.test.d.ts.map +0 -1
- package/dist/transaction/rpoRandomCoin.test.js +0 -52
- package/dist/transaction/rpoRandomCoin.test.js.map +0 -1
- package/dist/transaction/summary.test.d.ts +0 -2
- package/dist/transaction/summary.test.d.ts.map +0 -1
- package/dist/transaction/summary.test.js +0 -26
- package/dist/transaction/summary.test.js.map +0 -1
- package/dist/transaction.test.d.ts +0 -2
- package/dist/transaction.test.d.ts.map +0 -1
- package/dist/transaction.test.js +0 -122
- package/dist/transaction.test.js.map +0 -1
- package/dist/types/proposal.test.d.ts +0 -2
- package/dist/types/proposal.test.d.ts.map +0 -1
- package/dist/types/proposal.test.js +0 -56
- package/dist/types/proposal.test.js.map +0 -1
- package/dist/utils/digest.test.d.ts +0 -2
- package/dist/utils/digest.test.d.ts.map +0 -1
- package/dist/utils/digest.test.js +0 -48
- package/dist/utils/digest.test.js.map +0 -1
- package/dist/utils/ecdsa.test.d.ts +0 -2
- package/dist/utils/ecdsa.test.d.ts.map +0 -1
- package/dist/utils/ecdsa.test.js +0 -131
- package/dist/utils/ecdsa.test.js.map +0 -1
- package/dist/utils/encoding.test.d.ts +0 -2
- package/dist/utils/encoding.test.d.ts.map +0 -1
- package/dist/utils/encoding.test.js +0 -185
- package/dist/utils/encoding.test.js.map +0 -1
- package/dist/utils/key.test.d.ts +0 -2
- package/dist/utils/key.test.d.ts.map +0 -1
- package/dist/utils/key.test.js +0 -82
- package/dist/utils/key.test.js.map +0 -1
- package/dist/utils/signature.test.d.ts +0 -2
- package/dist/utils/signature.test.d.ts.map +0 -1
- package/dist/utils/signature.test.js +0 -164
- package/dist/utils/signature.test.js.map +0 -1
- package/dist/utils/word.test.d.ts +0 -2
- package/dist/utils/word.test.d.ts.map +0 -1
- package/dist/utils/word.test.js +0 -54
- package/dist/utils/word.test.js.map +0 -1
- package/masm/account_components/auth/guarded_multisig.masm +0 -42
- package/src/account/builder.test.ts +0 -238
- package/src/account/masm/account-components/auth.ts +0 -46
- package/src/account/masm/index.ts +0 -4
- package/src/account/masm.ts +0 -4
- package/src/account/storage.test.ts +0 -90
- package/src/client.test.ts +0 -473
- package/src/connectivity.test.ts +0 -67
- package/src/inspector.test.ts +0 -542
- package/src/lookupAuth.test.ts +0 -185
- package/src/multisig/consumeNotesErrors.test.ts +0 -43
- package/src/multisig/helpers.test.ts +0 -114
- package/src/multisig.test.ts +0 -5008
- package/src/proposal/factory.test.ts +0 -40
- package/src/proposal/metadata.test.ts +0 -235
- package/src/prover/config.test.ts +0 -90
- package/src/prover/errors.test.ts +0 -61
- package/src/prover/retry.test.ts +0 -38
- package/src/prover/workflow.test.ts +0 -145
- package/src/raw-client.test.ts +0 -171
- package/src/rpc/config.test.ts +0 -45
- package/src/rpc/errors.test.ts +0 -69
- package/src/rpc/retry.test.ts +0 -144
- package/src/signers/ecdsa.test.ts +0 -111
- package/src/signers/falcon.test.ts +0 -197
- package/src/signers/miden-wallet.ecdsa-recovery.test.ts +0 -201
- package/src/signers/miden-wallet.test.ts +0 -206
- package/src/signers/para.test.ts +0 -186
- package/src/transaction/index.ts +0 -13
- package/src/transaction/p2id.test.ts +0 -371
- package/src/transaction/rpoRandomCoin.test.ts +0 -64
- package/src/transaction/summary.test.ts +0 -32
- package/src/transaction.test.ts +0 -142
- package/src/types/proposal.test.ts +0 -68
- package/src/utils/digest.test.ts +0 -55
- package/src/utils/ecdsa.test.ts +0 -164
- package/src/utils/encoding.test.ts +0 -233
- package/src/utils/key.test.ts +0 -91
- package/src/utils/signature.test.ts +0 -210
- package/src/utils/word.test.ts +0 -64
package/src/inspector.test.ts
DELETED
|
@@ -1,542 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { AccountInspector, assertCompleteDetectedConfig } from './inspector.js';
|
|
3
|
-
import type { DetectedMultisigConfig } from './inspector.js';
|
|
4
|
-
|
|
5
|
-
// Mock the Miden SDK
|
|
6
|
-
vi.mock('@miden-sdk/miden-sdk', () => {
|
|
7
|
-
const createMockWord = (values: bigint[]) => ({
|
|
8
|
-
toU64s: () => values,
|
|
9
|
-
toHex: () => '0x' + values.map(v => v.toString(16).padStart(16, '0')).join(''),
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
// Faithful to the real SDK's read semantics (verified against the wasm
|
|
13
|
-
// glue and miden-protocol): getItem returns undefined for an absent slot;
|
|
14
|
-
// getMapItem returns undefined only when the slot is absent or not a map,
|
|
15
|
-
// and the EMPTY word for a missing key in an existing map
|
|
16
|
-
// (StorageMap::get is unwrap_or_default). Neither throws for "not found".
|
|
17
|
-
const createMockStorage = (slots: Map<string, any>, maps: Map<string, Map<string, any>>) => ({
|
|
18
|
-
getItem: (slotName: string) => slots.get(slotName),
|
|
19
|
-
getMapItem: (slotName: string, key: any) => {
|
|
20
|
-
const map = maps.get(slotName);
|
|
21
|
-
if (!map) return undefined;
|
|
22
|
-
const keyStr = key.toU64s?.()[0]?.toString() ?? '0';
|
|
23
|
-
return map.get(keyStr) ?? createMockWord([0n, 0n, 0n, 0n]);
|
|
24
|
-
},
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
const createMockVault = (assets: Array<{ faucetId: string; amount: bigint }>) => ({
|
|
28
|
-
fungibleAssets: () => assets.map(a => ({
|
|
29
|
-
faucetId: () => ({ toString: () => a.faucetId }),
|
|
30
|
-
amount: () => a.amount,
|
|
31
|
-
})),
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
Account: {
|
|
36
|
-
deserialize: vi.fn((bytes: Uint8Array) => {
|
|
37
|
-
// Return different mocked accounts based on test scenario
|
|
38
|
-
// Default: 2-of-3 multisig with GUARDIAN enabled
|
|
39
|
-
const slot0 = createMockWord([2n, 3n, 0n, 0n]); // threshold=2, numSigners=3
|
|
40
|
-
|
|
41
|
-
const signerMap = new Map<string, any>();
|
|
42
|
-
signerMap.set('0', createMockWord([BigInt('0x1111111111111111'), BigInt('0x2222222222222222'), BigInt('0x3333333333333333'), BigInt('0x4444444444444444')]));
|
|
43
|
-
signerMap.set('1', createMockWord([BigInt('0x5555555555555555'), BigInt('0x6666666666666666'), BigInt('0x7777777777777777'), BigInt('0x8888888888888888')]));
|
|
44
|
-
signerMap.set('2', createMockWord([BigInt('0xaaaaaaaaaaaaaaaa'), BigInt('0xbbbbbbbbbbbbbbbb'), BigInt('0xcccccccccccccccc'), BigInt('0xdddddddddddddddd')]));
|
|
45
|
-
|
|
46
|
-
const guardianMap = new Map<string, any>();
|
|
47
|
-
guardianMap.set('0', createMockWord([BigInt('0xeeeeeeeeeeeeeeee'), BigInt('0xffffffffffffffff'), BigInt('0x0000000000000001'), BigInt('0x0000000000000002')]));
|
|
48
|
-
|
|
49
|
-
const slots = new Map<string, any>();
|
|
50
|
-
slots.set('miden::standards::auth::multisig::threshold_config', slot0);
|
|
51
|
-
|
|
52
|
-
const maps = new Map<string, Map<string, any>>();
|
|
53
|
-
maps.set('miden::standards::auth::multisig::approver_public_keys', signerMap);
|
|
54
|
-
maps.set('miden::standards::auth::guardian::pub_key', guardianMap);
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
storage: () => createMockStorage(slots, maps),
|
|
58
|
-
// The contract-version guard checks for the pinned auth procedure.
|
|
59
|
-
code: () => ({ hasProcedure: () => true }),
|
|
60
|
-
vault: () => createMockVault([
|
|
61
|
-
{ faucetId: '0xfaucet1', amount: 1000n },
|
|
62
|
-
{ faucetId: '0xfaucet2', amount: 500n },
|
|
63
|
-
]),
|
|
64
|
-
};
|
|
65
|
-
}),
|
|
66
|
-
},
|
|
67
|
-
Word: Object.assign(
|
|
68
|
-
vi.fn().mockImplementation((arr: BigUint64Array) => ({
|
|
69
|
-
toU64s: () => Array.from(arr),
|
|
70
|
-
toHex: () => '0x' + Array.from(arr).map(v => v.toString(16).padStart(16, '0')).join(''),
|
|
71
|
-
})),
|
|
72
|
-
{
|
|
73
|
-
fromHex: vi.fn((hex: string) => ({
|
|
74
|
-
toU64s: () => [0n, 0n, 0n, 0n],
|
|
75
|
-
toHex: () => hex,
|
|
76
|
-
})),
|
|
77
|
-
},
|
|
78
|
-
),
|
|
79
|
-
};
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
describe('AccountInspector', () => {
|
|
83
|
-
beforeEach(() => {
|
|
84
|
-
vi.clearAllMocks();
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
describe('fromBase64', () => {
|
|
88
|
-
it('deserializes account from base64 and extracts config', () => {
|
|
89
|
-
const base64 = btoa(String.fromCharCode(...new Uint8Array([1, 2, 3])));
|
|
90
|
-
const config = AccountInspector.fromBase64(base64);
|
|
91
|
-
|
|
92
|
-
expect(config.threshold).toBe(2);
|
|
93
|
-
expect(config.numSigners).toBe(3);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('extracts the GUARDIAN commitment', () => {
|
|
97
|
-
const base64 = btoa(String.fromCharCode(...new Uint8Array([1, 2, 3])));
|
|
98
|
-
const config = AccountInspector.fromBase64(base64);
|
|
99
|
-
|
|
100
|
-
expect(config.guardianCommitment).toMatch(/^0x[a-f0-9]+$/);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it('extracts signer commitments', () => {
|
|
104
|
-
const base64 = btoa(String.fromCharCode(...new Uint8Array([1, 2, 3])));
|
|
105
|
-
const config = AccountInspector.fromBase64(base64);
|
|
106
|
-
|
|
107
|
-
expect(config.signerCommitments).toHaveLength(3);
|
|
108
|
-
config.signerCommitments.forEach(commitment => {
|
|
109
|
-
expect(commitment).toMatch(/^0x[a-f0-9]+$/);
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('extracts vault balances', () => {
|
|
114
|
-
const base64 = btoa(String.fromCharCode(...new Uint8Array([1, 2, 3])));
|
|
115
|
-
const config = AccountInspector.fromBase64(base64);
|
|
116
|
-
|
|
117
|
-
expect(config.vaultBalances).toHaveLength(2);
|
|
118
|
-
expect(config.vaultBalances[0]).toEqual({ faucetId: '0xfaucet1', amount: 1000n });
|
|
119
|
-
expect(config.vaultBalances[1]).toEqual({ faucetId: '0xfaucet2', amount: 500n });
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
describe('fromAccount', () => {
|
|
124
|
-
it('extracts threshold from slot 0', async () => {
|
|
125
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
126
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
127
|
-
const config = AccountInspector.fromAccount(account);
|
|
128
|
-
|
|
129
|
-
expect(config.threshold).toBe(2);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it('extracts numSigners from slot 0', async () => {
|
|
133
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
134
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
135
|
-
const config = AccountInspector.fromAccount(account);
|
|
136
|
-
|
|
137
|
-
expect(config.numSigners).toBe(3);
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it('rejects accounts built from a different contract version', async () => {
|
|
141
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
142
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
143
|
-
// Same account shape, but its code lacks the pinned auth procedure —
|
|
144
|
-
// root-keyed reads against it would silently miss its stored overrides.
|
|
145
|
-
const foreign = {
|
|
146
|
-
...account,
|
|
147
|
-
code: () => ({ hasProcedure: () => false }),
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
expect(() => AccountInspector.fromAccount(foreign as never)).toThrow(
|
|
151
|
-
/unsupported contract version/,
|
|
152
|
-
);
|
|
153
|
-
});
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
describe('AccountInspector edge cases', () => {
|
|
158
|
-
beforeEach(() => {
|
|
159
|
-
vi.clearAllMocks();
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
it('returns a null GUARDIAN commitment when the guardian pub_key slot is absent', async () => {
|
|
163
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
164
|
-
|
|
165
|
-
// Override mock for this test: no guardian pub_key entry present.
|
|
166
|
-
vi.mocked(Account.deserialize).mockReturnValueOnce({
|
|
167
|
-
code: () => ({ hasProcedure: () => true }),
|
|
168
|
-
storage: () => ({
|
|
169
|
-
getItem: (slotName: string) => {
|
|
170
|
-
if (slotName === 'miden::standards::auth::multisig::threshold_config') return { toU64s: () => [1n, 1n, 0n, 0n] };
|
|
171
|
-
return { toU64s: () => [0n, 0n, 0n, 0n] };
|
|
172
|
-
},
|
|
173
|
-
getMapItem: (slotName: string, key: any) => {
|
|
174
|
-
if (slotName === 'miden::standards::auth::multisig::approver_public_keys' && key.toU64s?.()[0] === 0n) {
|
|
175
|
-
return {
|
|
176
|
-
toHex: () => '0x' + 'a'.repeat(64),
|
|
177
|
-
toU64s: () => [1n, 2n, 3n, 4n],
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
throw new Error('Not found');
|
|
181
|
-
},
|
|
182
|
-
}),
|
|
183
|
-
vault: () => ({
|
|
184
|
-
fungibleAssets: () => [],
|
|
185
|
-
}),
|
|
186
|
-
} as any);
|
|
187
|
-
|
|
188
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
189
|
-
const config = AccountInspector.fromAccount(account);
|
|
190
|
-
|
|
191
|
-
expect(config.guardianCommitment).toBeNull();
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it('handles account with empty vault', async () => {
|
|
195
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
196
|
-
|
|
197
|
-
vi.mocked(Account.deserialize).mockReturnValueOnce({
|
|
198
|
-
code: () => ({ hasProcedure: () => true }),
|
|
199
|
-
storage: () => ({
|
|
200
|
-
getItem: () => ({ toU64s: () => [1n, 1n, 0n, 0n] }),
|
|
201
|
-
getMapItem: () => {
|
|
202
|
-
throw new Error('Not found');
|
|
203
|
-
},
|
|
204
|
-
}),
|
|
205
|
-
vault: () => ({
|
|
206
|
-
fungibleAssets: () => [],
|
|
207
|
-
}),
|
|
208
|
-
} as any);
|
|
209
|
-
|
|
210
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
211
|
-
const config = AccountInspector.fromAccount(account);
|
|
212
|
-
|
|
213
|
-
expect(config.vaultBalances).toEqual([]);
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
it('handles missing signer map entries gracefully', async () => {
|
|
217
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
218
|
-
|
|
219
|
-
vi.mocked(Account.deserialize).mockReturnValueOnce({
|
|
220
|
-
code: () => ({ hasProcedure: () => true }),
|
|
221
|
-
storage: () => ({
|
|
222
|
-
getItem: (slotName: string) => {
|
|
223
|
-
if (slotName === 'miden::standards::auth::multisig::threshold_config') return { toU64s: () => [2n, 5n, 0n, 0n] }; // threshold=2, numSigners=5
|
|
224
|
-
return { toU64s: () => [0n, 0n, 0n, 0n] };
|
|
225
|
-
},
|
|
226
|
-
getMapItem: () => {
|
|
227
|
-
throw new Error('Map entry not found');
|
|
228
|
-
},
|
|
229
|
-
}),
|
|
230
|
-
vault: () => ({
|
|
231
|
-
fungibleAssets: () => [],
|
|
232
|
-
}),
|
|
233
|
-
} as any);
|
|
234
|
-
|
|
235
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
236
|
-
const config = AccountInspector.fromAccount(account);
|
|
237
|
-
|
|
238
|
-
// Should gracefully handle missing entries
|
|
239
|
-
expect(config.numSigners).toBe(5);
|
|
240
|
-
expect(config.signerCommitments).toEqual([]); // All entries missing
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it('handles vault access error gracefully', async () => {
|
|
244
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
245
|
-
|
|
246
|
-
vi.mocked(Account.deserialize).mockReturnValueOnce({
|
|
247
|
-
code: () => ({ hasProcedure: () => true }),
|
|
248
|
-
storage: () => ({
|
|
249
|
-
getItem: () => ({ toU64s: () => [1n, 1n, 0n, 0n] }),
|
|
250
|
-
getMapItem: () => {
|
|
251
|
-
throw new Error('Not found');
|
|
252
|
-
},
|
|
253
|
-
}),
|
|
254
|
-
vault: () => {
|
|
255
|
-
throw new Error('Vault access failed');
|
|
256
|
-
},
|
|
257
|
-
} as any);
|
|
258
|
-
|
|
259
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
260
|
-
const config = AccountInspector.fromAccount(account);
|
|
261
|
-
|
|
262
|
-
expect(config.vaultBalances).toEqual([]);
|
|
263
|
-
});
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
describe('AccountInspector.getSignerPublicKeyCommitments', () => {
|
|
267
|
-
beforeEach(() => {
|
|
268
|
-
vi.clearAllMocks();
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
it('returns all signer commitments ordered by signer index', async () => {
|
|
272
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
273
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
274
|
-
|
|
275
|
-
const commitments = AccountInspector.getSignerPublicKeyCommitments(account);
|
|
276
|
-
|
|
277
|
-
expect(commitments).toEqual([
|
|
278
|
-
'0x1111111111111111222222222222222233333333333333334444444444444444',
|
|
279
|
-
'0x5555555555555555666666666666666677777777777777778888888888888888',
|
|
280
|
-
'0xaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccdddddddddddddddd',
|
|
281
|
-
]);
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
it('rejects accounts built from a different contract version', async () => {
|
|
285
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
286
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
287
|
-
const foreign = {
|
|
288
|
-
...account,
|
|
289
|
-
code: () => ({ hasProcedure: () => false }),
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
expect(() => AccountInspector.getSignerPublicKeyCommitments(foreign as never)).toThrow(
|
|
293
|
-
/unsupported contract version/,
|
|
294
|
-
);
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
it('throws when a signer map entry is the empty word instead of truncating', async () => {
|
|
298
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
299
|
-
|
|
300
|
-
// Real SDK semantics: entries 0 and 1 exist, entries 2..4 come back as
|
|
301
|
-
// the empty word (StorageMap::get is unwrap_or_default) — NOT undefined
|
|
302
|
-
// and NOT a throw.
|
|
303
|
-
const entries = new Map<string, any>([
|
|
304
|
-
['0', { toU64s: () => [1n, 2n, 3n, 4n], toHex: () => '0x' + 'a'.repeat(64) }],
|
|
305
|
-
['1', { toU64s: () => [5n, 6n, 7n, 8n], toHex: () => '0x' + 'b'.repeat(64) }],
|
|
306
|
-
]);
|
|
307
|
-
vi.mocked(Account.deserialize).mockReturnValueOnce({
|
|
308
|
-
code: () => ({ hasProcedure: () => true }),
|
|
309
|
-
storage: () => ({
|
|
310
|
-
getItem: (slotName: string) => {
|
|
311
|
-
if (slotName === 'miden::standards::auth::multisig::threshold_config') return { toU64s: () => [2n, 5n, 0n, 0n] };
|
|
312
|
-
return undefined;
|
|
313
|
-
},
|
|
314
|
-
getMapItem: (slotName: string, key: any) => {
|
|
315
|
-
if (slotName !== 'miden::standards::auth::multisig::approver_public_keys') return undefined;
|
|
316
|
-
const keyStr = key.toU64s?.()[0]?.toString() ?? '0';
|
|
317
|
-
return entries.get(keyStr) ?? { toU64s: () => [0n, 0n, 0n, 0n] };
|
|
318
|
-
},
|
|
319
|
-
}),
|
|
320
|
-
} as any);
|
|
321
|
-
|
|
322
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
323
|
-
|
|
324
|
-
expect(() => AccountInspector.getSignerPublicKeyCommitments(account)).toThrow(
|
|
325
|
-
/missing signer public key at index 2/
|
|
326
|
-
);
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
it('throws when the signer map slot itself is absent', async () => {
|
|
330
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
331
|
-
|
|
332
|
-
vi.mocked(Account.deserialize).mockReturnValueOnce({
|
|
333
|
-
code: () => ({ hasProcedure: () => true }),
|
|
334
|
-
storage: () => ({
|
|
335
|
-
getItem: (slotName: string) => {
|
|
336
|
-
if (slotName === 'miden::standards::auth::multisig::threshold_config') return { toU64s: () => [2n, 3n, 0n, 0n] };
|
|
337
|
-
return undefined;
|
|
338
|
-
},
|
|
339
|
-
getMapItem: () => undefined,
|
|
340
|
-
}),
|
|
341
|
-
} as any);
|
|
342
|
-
|
|
343
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
344
|
-
|
|
345
|
-
expect(() => AccountInspector.getSignerPublicKeyCommitments(account)).toThrow(
|
|
346
|
-
/missing signer public key at index 0/
|
|
347
|
-
);
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
it('throws when the threshold config slot is absent', async () => {
|
|
351
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
352
|
-
|
|
353
|
-
vi.mocked(Account.deserialize).mockReturnValueOnce({
|
|
354
|
-
code: () => ({ hasProcedure: () => true }),
|
|
355
|
-
storage: () => ({
|
|
356
|
-
getItem: () => undefined,
|
|
357
|
-
getMapItem: () => undefined,
|
|
358
|
-
}),
|
|
359
|
-
} as any);
|
|
360
|
-
|
|
361
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
362
|
-
|
|
363
|
-
expect(() => AccountInspector.getSignerPublicKeyCommitments(account)).toThrow(
|
|
364
|
-
/not a guarded-multisig account/
|
|
365
|
-
);
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
it('throws when the threshold config reports zero signers', async () => {
|
|
369
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
370
|
-
|
|
371
|
-
vi.mocked(Account.deserialize).mockReturnValueOnce({
|
|
372
|
-
code: () => ({ hasProcedure: () => true }),
|
|
373
|
-
storage: () => ({
|
|
374
|
-
getItem: () => ({ toU64s: () => [0n, 0n, 0n, 0n] }),
|
|
375
|
-
getMapItem: () => undefined,
|
|
376
|
-
}),
|
|
377
|
-
} as any);
|
|
378
|
-
|
|
379
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
380
|
-
|
|
381
|
-
expect(() => AccountInspector.getSignerPublicKeyCommitments(account)).toThrow(
|
|
382
|
-
/zero signers/
|
|
383
|
-
);
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
// 2n ** 53n is the smallest count whose Number() conversion is no longer a
|
|
387
|
-
// safe integer (i++ would stop advancing without the ceiling guard).
|
|
388
|
-
it.each([4294967295n, 2n ** 53n])(
|
|
389
|
-
'throws on an absurd signer count (%s) instead of looping',
|
|
390
|
-
async (count) => {
|
|
391
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
392
|
-
|
|
393
|
-
vi.mocked(Account.deserialize).mockReturnValueOnce({
|
|
394
|
-
code: () => ({ hasProcedure: () => true }),
|
|
395
|
-
storage: () => ({
|
|
396
|
-
getItem: () => ({ toU64s: () => [2n, count, 0n, 0n] }),
|
|
397
|
-
getMapItem: () => ({ toU64s: () => [1n, 2n, 3n, 4n], toHex: () => '0x' + 'a'.repeat(64) }),
|
|
398
|
-
}),
|
|
399
|
-
} as any);
|
|
400
|
-
|
|
401
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
402
|
-
|
|
403
|
-
expect(() => AccountInspector.getSignerPublicKeyCommitments(account)).toThrow(
|
|
404
|
-
/sanity limit/
|
|
405
|
-
);
|
|
406
|
-
},
|
|
407
|
-
);
|
|
408
|
-
|
|
409
|
-
it('surfaces a descriptive error for an account from a different SDK copy', async () => {
|
|
410
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
411
|
-
|
|
412
|
-
// wasm-bindgen's _assertClass rejects Word instances from another
|
|
413
|
-
// bundled SDK copy with this exact message.
|
|
414
|
-
vi.mocked(Account.deserialize).mockReturnValueOnce({
|
|
415
|
-
code: () => ({ hasProcedure: () => true }),
|
|
416
|
-
storage: () => ({
|
|
417
|
-
getItem: (slotName: string) => {
|
|
418
|
-
if (slotName === 'miden::standards::auth::multisig::threshold_config') return { toU64s: () => [1n, 1n, 0n, 0n] };
|
|
419
|
-
return undefined;
|
|
420
|
-
},
|
|
421
|
-
getMapItem: () => {
|
|
422
|
-
throw new Error('expected instance of Word');
|
|
423
|
-
},
|
|
424
|
-
}),
|
|
425
|
-
} as any);
|
|
426
|
-
|
|
427
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
428
|
-
|
|
429
|
-
expect(() => AccountInspector.getSignerPublicKeyCommitments(account)).toThrow(
|
|
430
|
-
/different copy of @miden-sdk\/miden-sdk/
|
|
431
|
-
);
|
|
432
|
-
});
|
|
433
|
-
});
|
|
434
|
-
|
|
435
|
-
describe('AccountInspector.getGuardianPublicKeyCommitment', () => {
|
|
436
|
-
beforeEach(() => {
|
|
437
|
-
vi.clearAllMocks();
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
it('returns the guardian commitment', async () => {
|
|
441
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
442
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
443
|
-
|
|
444
|
-
const commitment = AccountInspector.getGuardianPublicKeyCommitment(account);
|
|
445
|
-
|
|
446
|
-
expect(commitment).toBe('0xeeeeeeeeeeeeeeeeffffffffffffffff00000000000000010000000000000002');
|
|
447
|
-
});
|
|
448
|
-
|
|
449
|
-
it('rejects accounts built from a different contract version', async () => {
|
|
450
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
451
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
452
|
-
const foreign = {
|
|
453
|
-
...account,
|
|
454
|
-
code: () => ({ hasProcedure: () => false }),
|
|
455
|
-
};
|
|
456
|
-
|
|
457
|
-
expect(() => AccountInspector.getGuardianPublicKeyCommitment(foreign as never)).toThrow(
|
|
458
|
-
/unsupported contract version/,
|
|
459
|
-
);
|
|
460
|
-
});
|
|
461
|
-
|
|
462
|
-
it('throws when the guardian key entry is the empty word', async () => {
|
|
463
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
464
|
-
|
|
465
|
-
vi.mocked(Account.deserialize).mockReturnValueOnce({
|
|
466
|
-
code: () => ({ hasProcedure: () => true }),
|
|
467
|
-
storage: () => ({
|
|
468
|
-
getItem: () => ({ toU64s: () => [1n, 1n, 0n, 0n] }),
|
|
469
|
-
getMapItem: () => ({ toU64s: () => [0n, 0n, 0n, 0n] }),
|
|
470
|
-
}),
|
|
471
|
-
} as any);
|
|
472
|
-
|
|
473
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
474
|
-
|
|
475
|
-
expect(() => AccountInspector.getGuardianPublicKeyCommitment(account)).toThrow(
|
|
476
|
-
/inconsistent account state/
|
|
477
|
-
);
|
|
478
|
-
});
|
|
479
|
-
|
|
480
|
-
it('propagates genuine storage read failures', async () => {
|
|
481
|
-
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
482
|
-
|
|
483
|
-
vi.mocked(Account.deserialize).mockReturnValueOnce({
|
|
484
|
-
code: () => ({ hasProcedure: () => true }),
|
|
485
|
-
storage: () => ({
|
|
486
|
-
getItem: () => ({ toU64s: () => [1n, 1n, 0n, 0n] }),
|
|
487
|
-
getMapItem: () => {
|
|
488
|
-
throw new Error('storage backend exploded');
|
|
489
|
-
},
|
|
490
|
-
}),
|
|
491
|
-
} as any);
|
|
492
|
-
|
|
493
|
-
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
494
|
-
|
|
495
|
-
expect(() => AccountInspector.getGuardianPublicKeyCommitment(account)).toThrow(
|
|
496
|
-
'storage backend exploded'
|
|
497
|
-
);
|
|
498
|
-
});
|
|
499
|
-
});
|
|
500
|
-
|
|
501
|
-
describe('assertCompleteDetectedConfig', () => {
|
|
502
|
-
const complete: DetectedMultisigConfig = {
|
|
503
|
-
threshold: 2,
|
|
504
|
-
numSigners: 2,
|
|
505
|
-
signerCommitments: ['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64)],
|
|
506
|
-
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
507
|
-
vaultBalances: [],
|
|
508
|
-
procedureThresholds: new Map(),
|
|
509
|
-
};
|
|
510
|
-
|
|
511
|
-
it('accepts a complete config', () => {
|
|
512
|
-
expect(() => assertCompleteDetectedConfig(complete)).not.toThrow();
|
|
513
|
-
});
|
|
514
|
-
|
|
515
|
-
it('rejects a signer set shorter than the reported count', () => {
|
|
516
|
-
expect(() =>
|
|
517
|
-
assertCompleteDetectedConfig({
|
|
518
|
-
...complete,
|
|
519
|
-
numSigners: 3,
|
|
520
|
-
}),
|
|
521
|
-
).toThrow(/incomplete signer set: storage reports 3 signers, read 2/);
|
|
522
|
-
});
|
|
523
|
-
|
|
524
|
-
it('rejects a zero signer count', () => {
|
|
525
|
-
expect(() =>
|
|
526
|
-
assertCompleteDetectedConfig({
|
|
527
|
-
...complete,
|
|
528
|
-
numSigners: 0,
|
|
529
|
-
signerCommitments: [],
|
|
530
|
-
}),
|
|
531
|
-
).toThrow(/incomplete signer set/);
|
|
532
|
-
});
|
|
533
|
-
|
|
534
|
-
it('rejects a missing guardian commitment', () => {
|
|
535
|
-
expect(() =>
|
|
536
|
-
assertCompleteDetectedConfig({
|
|
537
|
-
...complete,
|
|
538
|
-
guardianCommitment: null,
|
|
539
|
-
}),
|
|
540
|
-
).toThrow(/missing guardian commitment/);
|
|
541
|
-
});
|
|
542
|
-
});
|