@openzeppelin/miden-multisig-client 0.13.1 → 0.13.3
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 +98 -119
- package/dist/account/builder.d.ts +18 -0
- package/dist/account/builder.d.ts.map +1 -1
- package/dist/account/builder.js +59 -29
- package/dist/account/builder.js.map +1 -1
- package/dist/account/builder.test.js +108 -32
- package/dist/account/builder.test.js.map +1 -1
- package/dist/account/index.d.ts +1 -1
- package/dist/account/index.d.ts.map +1 -1
- package/dist/account/index.js +1 -1
- package/dist/account/index.js.map +1 -1
- package/dist/account/masm/account-components/auth.d.ts +5 -0
- package/dist/account/masm/account-components/auth.d.ts.map +1 -0
- package/dist/account/masm/account-components/auth.js +67 -0
- package/dist/account/masm/account-components/auth.js.map +1 -0
- package/dist/account/masm/auth.d.ts +5 -0
- package/dist/account/masm/auth.d.ts.map +1 -0
- package/dist/account/masm/auth.js +1395 -0
- package/dist/account/masm/auth.js.map +1 -0
- package/dist/account/masm/index.d.ts +3 -0
- package/dist/account/masm/index.d.ts.map +1 -0
- package/dist/account/masm/index.js +5 -0
- package/dist/account/masm/index.js.map +1 -0
- package/dist/account/masm.d.ts +1 -4
- package/dist/account/masm.d.ts.map +1 -1
- package/dist/account/masm.js +3 -1034
- package/dist/account/masm.js.map +1 -1
- package/dist/account/storage.d.ts +2 -2
- package/dist/account/storage.d.ts.map +1 -1
- package/dist/account/storage.js +18 -16
- package/dist/account/storage.js.map +1 -1
- package/dist/client.d.ts +67 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +73 -22
- package/dist/client.js.map +1 -1
- package/dist/client.test.js +31 -32
- package/dist/client.test.js.map +1 -1
- package/dist/index.d.ts +54 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +53 -9
- package/dist/index.js.map +1 -1
- package/dist/inspector.d.ts +32 -6
- package/dist/inspector.d.ts.map +1 -1
- package/dist/inspector.js +58 -23
- package/dist/inspector.js.map +1 -1
- package/dist/inspector.test.js +18 -18
- package/dist/inspector.test.js.map +1 -1
- package/dist/multisig/proposal/execution.d.ts +4 -4
- package/dist/multisig/proposal/execution.d.ts.map +1 -1
- package/dist/multisig/proposal/execution.js +42 -31
- package/dist/multisig/proposal/execution.js.map +1 -1
- package/dist/multisig/proposal/parser.d.ts +3 -3
- package/dist/multisig/proposal/parser.d.ts.map +1 -1
- package/dist/multisig/proposal/parser.js +23 -23
- package/dist/multisig/proposal/parser.js.map +1 -1
- package/dist/multisig/signing.d.ts +3 -3
- package/dist/multisig/signing.d.ts.map +1 -1
- package/dist/multisig/signing.js +3 -3
- package/dist/multisig/signing.js.map +1 -1
- package/dist/multisig.d.ts +188 -48
- package/dist/multisig.d.ts.map +1 -1
- package/dist/multisig.js +650 -308
- package/dist/multisig.js.map +1 -1
- package/dist/multisig.test.js +1680 -241
- package/dist/multisig.test.js.map +1 -1
- package/dist/procedures.d.ts +46 -24
- package/dist/procedures.d.ts.map +1 -1
- package/dist/procedures.js +46 -21
- package/dist/procedures.js.map +1 -1
- package/dist/proposal/factory.d.ts +18 -0
- package/dist/proposal/factory.d.ts.map +1 -0
- package/dist/proposal/factory.js +99 -0
- package/dist/proposal/factory.js.map +1 -0
- package/dist/proposal/metadata.d.ts +5 -12
- package/dist/proposal/metadata.d.ts.map +1 -1
- package/dist/proposal/metadata.js +118 -174
- package/dist/proposal/metadata.js.map +1 -1
- package/dist/proposal/signatures.d.ts +10 -0
- package/dist/proposal/signatures.d.ts.map +1 -0
- package/dist/proposal/signatures.js +54 -0
- package/dist/proposal/signatures.js.map +1 -0
- package/dist/signer.d.ts +2 -0
- package/dist/signer.d.ts.map +1 -1
- package/dist/signer.js +2 -0
- package/dist/signer.js.map +1 -1
- package/dist/signers/ecdsa.d.ts +3 -0
- package/dist/signers/ecdsa.d.ts.map +1 -1
- package/dist/signers/ecdsa.js +8 -4
- package/dist/signers/ecdsa.js.map +1 -1
- package/dist/signers/ecdsa.test.d.ts +2 -0
- package/dist/signers/ecdsa.test.d.ts.map +1 -0
- package/dist/signers/ecdsa.test.js +65 -0
- package/dist/signers/ecdsa.test.js.map +1 -0
- package/dist/signers/falcon.d.ts +3 -0
- package/dist/signers/falcon.d.ts.map +1 -1
- package/dist/signers/falcon.js +8 -4
- package/dist/signers/falcon.js.map +1 -1
- package/dist/signers/falcon.test.js +12 -0
- package/dist/signers/falcon.test.js.map +1 -1
- package/dist/signers/miden-wallet.d.ts +3 -1
- package/dist/signers/miden-wallet.d.ts.map +1 -1
- package/dist/signers/miden-wallet.js +11 -2
- package/dist/signers/miden-wallet.js.map +1 -1
- package/dist/signers/miden-wallet.test.js +26 -0
- package/dist/signers/miden-wallet.test.js.map +1 -1
- package/dist/signers/para.d.ts +3 -3
- package/dist/signers/para.d.ts.map +1 -1
- package/dist/signers/para.js +15 -6
- package/dist/signers/para.js.map +1 -1
- package/dist/signers/para.test.js +39 -0
- package/dist/signers/para.test.js.map +1 -1
- package/dist/transaction/consumeNotes.d.ts.map +1 -1
- package/dist/transaction/consumeNotes.js +1 -0
- package/dist/transaction/consumeNotes.js.map +1 -1
- package/dist/transaction/index.d.ts +2 -1
- package/dist/transaction/index.d.ts.map +1 -1
- package/dist/transaction/index.js +2 -1
- package/dist/transaction/index.js.map +1 -1
- package/dist/transaction/options.d.ts +1 -1
- package/dist/transaction/options.d.ts.map +1 -1
- package/dist/transaction/p2id.d.ts +1 -0
- package/dist/transaction/p2id.d.ts.map +1 -1
- package/dist/transaction/p2id.js +9 -3
- package/dist/transaction/p2id.js.map +1 -1
- package/dist/transaction/updateGuardian.d.ts +7 -0
- package/dist/transaction/updateGuardian.d.ts.map +1 -0
- package/dist/transaction/{updatePsm.js → updateGuardian.js} +15 -29
- package/dist/transaction/updateGuardian.js.map +1 -0
- package/dist/transaction/updateProcedureThreshold.d.ts +9 -0
- package/dist/transaction/updateProcedureThreshold.d.ts.map +1 -0
- package/dist/transaction/updateProcedureThreshold.js +55 -0
- package/dist/transaction/updateProcedureThreshold.js.map +1 -0
- package/dist/transaction/updateSigners.d.ts.map +1 -1
- package/dist/transaction/updateSigners.js +5 -23
- package/dist/transaction/updateSigners.js.map +1 -1
- package/dist/transaction.d.ts +2 -1
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +2 -1
- package/dist/transaction.js.map +1 -1
- package/dist/types/proposal.d.ts +32 -15
- package/dist/types/proposal.d.ts.map +1 -1
- package/dist/types.d.ts +24 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/digest.d.ts +5 -0
- package/dist/utils/digest.d.ts.map +1 -1
- package/dist/utils/digest.js +34 -1
- package/dist/utils/digest.js.map +1 -1
- package/dist/utils/digest.test.d.ts +2 -0
- package/dist/utils/digest.test.d.ts.map +1 -0
- package/dist/utils/digest.test.js +48 -0
- package/dist/utils/digest.test.js.map +1 -0
- package/dist/utils/signature.d.ts +3 -1
- package/dist/utils/signature.d.ts.map +1 -1
- package/dist/utils/signature.js +31 -6
- package/dist/utils/signature.js.map +1 -1
- package/dist/utils/word.test.js +1 -52
- package/dist/utils/word.test.js.map +1 -1
- package/masm/account_components/auth/multisig.masm +13 -0
- package/masm/account_components/auth/multisig_ecdsa.masm +13 -0
- package/masm/account_components/auth/multisig_guardian.masm +17 -0
- package/masm/account_components/auth/multisig_guardian_ecdsa.masm +17 -0
- package/masm/auth/guardian.masm +177 -0
- package/masm/auth/guardian_ecdsa.masm +178 -0
- package/masm/{multisig.masm → auth/multisig.masm} +149 -55
- package/masm/{multisig_ecdsa.masm → auth/multisig_ecdsa.masm} +148 -56
- package/package.json +11 -9
- package/src/account/builder.test.ts +165 -0
- package/src/account/builder.ts +71 -34
- package/src/account/index.ts +1 -1
- package/src/account/masm/account-components/auth.ts +70 -0
- package/src/account/masm/auth.ts +1398 -0
- package/src/account/masm/index.ts +5 -0
- package/src/account/masm.ts +3 -1040
- package/src/account/storage.ts +18 -16
- package/src/client.test.ts +31 -35
- package/src/client.ts +98 -26
- package/src/index.ts +84 -22
- package/src/inspector.test.ts +17 -17
- package/src/inspector.ts +63 -29
- package/src/multisig/proposal/execution.ts +66 -49
- package/src/multisig/proposal/parser.ts +26 -26
- package/src/multisig/signing.ts +4 -4
- package/src/multisig.test.ts +2097 -248
- package/src/multisig.ts +882 -388
- package/src/procedures.ts +50 -26
- package/src/proposal/factory.ts +171 -0
- package/src/proposal/metadata.ts +165 -0
- package/src/proposal/signatures.ts +68 -0
- package/src/signer.ts +2 -0
- package/src/signers/ecdsa.test.ts +80 -0
- package/src/signers/ecdsa.ts +15 -4
- package/src/signers/falcon.test.ts +19 -0
- package/src/signers/falcon.ts +16 -5
- package/src/signers/miden-wallet.test.ts +47 -0
- package/src/signers/miden-wallet.ts +18 -1
- package/src/signers/para.test.ts +57 -0
- package/src/signers/para.ts +26 -7
- package/src/transaction/consumeNotes.ts +1 -0
- package/src/transaction/index.ts +2 -2
- package/src/transaction/options.ts +1 -2
- package/src/transaction/p2id.test.ts +190 -0
- package/src/transaction/p2id.ts +11 -5
- package/src/transaction/rpoRandomCoin.test.ts +64 -0
- package/src/transaction/rpoRandomCoin.ts +24 -0
- package/src/transaction/{updatePsm.ts → updateGuardian.ts} +19 -32
- package/src/transaction/updateProcedureThreshold.ts +97 -0
- package/src/transaction/updateSigners.ts +12 -27
- package/src/transaction.ts +5 -3
- package/src/types/proposal.ts +43 -11
- package/src/types.ts +29 -11
- package/src/utils/digest.test.ts +55 -0
- package/src/utils/digest.ts +51 -1
- package/src/utils/signature.ts +47 -9
- package/src/utils/word.test.ts +1 -55
- package/dist/account.d.ts +0 -104
- package/dist/account.d.ts.map +0 -1
- package/dist/account.js +0 -136
- package/dist/account.js.map +0 -1
- package/dist/builder.d.ts +0 -54
- package/dist/builder.d.ts.map +0 -1
- package/dist/builder.js +0 -78
- package/dist/builder.js.map +0 -1
- package/dist/http.d.ts +0 -64
- package/dist/http.d.ts.map +0 -1
- package/dist/http.js +0 -162
- package/dist/http.js.map +0 -1
- package/dist/keystore.d.ts +0 -65
- package/dist/keystore.d.ts.map +0 -1
- package/dist/keystore.js +0 -121
- package/dist/keystore.js.map +0 -1
- package/dist/miden.d.ts +0 -9
- package/dist/miden.d.ts.map +0 -1
- package/dist/miden.js +0 -26
- package/dist/miden.js.map +0 -1
- package/dist/multisig/metadata.d.ts +0 -18
- package/dist/multisig/metadata.d.ts.map +0 -1
- package/dist/multisig/metadata.js +0 -100
- package/dist/multisig/metadata.js.map +0 -1
- package/dist/multisig/metadata.test.d.ts +0 -2
- package/dist/multisig/metadata.test.d.ts.map +0 -1
- package/dist/multisig/metadata.test.js +0 -323
- package/dist/multisig/metadata.test.js.map +0 -1
- package/dist/proposal/exported.d.ts +0 -12
- package/dist/proposal/exported.d.ts.map +0 -1
- package/dist/proposal/exported.js +0 -88
- package/dist/proposal/exported.js.map +0 -1
- package/dist/signer.test.d.ts +0 -2
- package/dist/signer.test.d.ts.map +0 -1
- package/dist/signer.test.js +0 -123
- package/dist/signer.test.js.map +0 -1
- package/dist/transaction/p2id.interop.test.d.ts +0 -2
- package/dist/transaction/p2id.interop.test.d.ts.map +0 -1
- package/dist/transaction/p2id.interop.test.js +0 -36
- package/dist/transaction/p2id.interop.test.js.map +0 -1
- package/dist/transaction/updatePsm.d.ts +0 -7
- package/dist/transaction/updatePsm.d.ts.map +0 -1
- package/dist/transaction/updatePsm.js.map +0 -1
- package/dist/transport/http.d.ts +0 -64
- package/dist/transport/http.d.ts.map +0 -1
- package/dist/transport/http.js +0 -162
- package/dist/transport/http.js.map +0 -1
- package/dist/transport/index.d.ts +0 -5
- package/dist/transport/index.d.ts.map +0 -1
- package/dist/transport/index.js +0 -5
- package/dist/transport/index.js.map +0 -1
- package/dist/utils/state-validation.d.ts +0 -5
- package/dist/utils/state-validation.d.ts.map +0 -1
- package/dist/utils/state-validation.js +0 -30
- package/dist/utils/state-validation.js.map +0 -1
- package/dist/utils/validation.d.ts +0 -6
- package/dist/utils/validation.d.ts.map +0 -1
- package/dist/utils/validation.js +0 -52
- package/dist/utils/validation.js.map +0 -1
- package/masm/psm.masm +0 -178
- package/masm/psm_ecdsa.masm +0 -179
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Felt,
|
|
3
|
+
FeltArray,
|
|
4
|
+
Rpo256,
|
|
5
|
+
TransactionRequest,
|
|
6
|
+
TransactionRequestBuilder,
|
|
7
|
+
TransactionScript,
|
|
8
|
+
WebClient,
|
|
9
|
+
Word,
|
|
10
|
+
Word as WordType,
|
|
11
|
+
} from '@miden-sdk/miden-sdk';
|
|
12
|
+
import {
|
|
13
|
+
MULTISIG_ECDSA_MASM,
|
|
14
|
+
MULTISIG_MASM,
|
|
15
|
+
} from '../account/masm/auth.js';
|
|
16
|
+
import { getProcedureRoot, type ProcedureName } from '../procedures.js';
|
|
17
|
+
import { normalizeHexWord } from '../utils/encoding.js';
|
|
18
|
+
import { randomWord } from '../utils/random.js';
|
|
19
|
+
import type { SignatureOptions } from './options.js';
|
|
20
|
+
import type { SignatureScheme } from '../types.js';
|
|
21
|
+
|
|
22
|
+
function buildProcedureThresholdAdvice(
|
|
23
|
+
procedure: ProcedureName,
|
|
24
|
+
threshold: number,
|
|
25
|
+
): { configHash: Word; payload: FeltArray } {
|
|
26
|
+
const procedureRoot = WordType.fromHex(normalizeHexWord(getProcedureRoot(procedure)));
|
|
27
|
+
const payload = new FeltArray([
|
|
28
|
+
...procedureRoot.toFelts(),
|
|
29
|
+
new Felt(BigInt(threshold)),
|
|
30
|
+
new Felt(0n),
|
|
31
|
+
new Felt(0n),
|
|
32
|
+
new Felt(0n),
|
|
33
|
+
]);
|
|
34
|
+
const configHash = Rpo256.hashElements(payload);
|
|
35
|
+
return { configHash, payload };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function buildUpdateProcedureThresholdScript(
|
|
39
|
+
webClient: WebClient,
|
|
40
|
+
procedure: ProcedureName,
|
|
41
|
+
threshold: number,
|
|
42
|
+
signatureScheme: SignatureScheme,
|
|
43
|
+
): TransactionScript {
|
|
44
|
+
const libBuilder = webClient.createCodeBuilder();
|
|
45
|
+
const multisigMasm = signatureScheme === 'ecdsa' ? MULTISIG_ECDSA_MASM : MULTISIG_MASM;
|
|
46
|
+
|
|
47
|
+
const multisigLib = libBuilder.buildLibrary('auth::multisig', multisigMasm);
|
|
48
|
+
libBuilder.linkDynamicLibrary(multisigLib);
|
|
49
|
+
const procedureRoot = normalizeHexWord(getProcedureRoot(procedure));
|
|
50
|
+
|
|
51
|
+
const scriptSource = `
|
|
52
|
+
use auth::multisig
|
|
53
|
+
|
|
54
|
+
begin
|
|
55
|
+
push.${procedureRoot}
|
|
56
|
+
push.${threshold}
|
|
57
|
+
call.multisig::update_procedure_threshold
|
|
58
|
+
dropw
|
|
59
|
+
drop
|
|
60
|
+
end
|
|
61
|
+
`;
|
|
62
|
+
|
|
63
|
+
return libBuilder.compileTxScript(scriptSource);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function buildUpdateProcedureThresholdTransactionRequest(
|
|
67
|
+
webClient: WebClient,
|
|
68
|
+
procedure: ProcedureName,
|
|
69
|
+
threshold: number,
|
|
70
|
+
options: SignatureOptions = {},
|
|
71
|
+
): Promise<{ request: TransactionRequest; salt: Word; configHash: Word }> {
|
|
72
|
+
const signatureScheme = options.signatureScheme ?? 'falcon';
|
|
73
|
+
const { configHash } = buildProcedureThresholdAdvice(procedure, threshold);
|
|
74
|
+
|
|
75
|
+
const script = buildUpdateProcedureThresholdScript(
|
|
76
|
+
webClient,
|
|
77
|
+
procedure,
|
|
78
|
+
threshold,
|
|
79
|
+
signatureScheme,
|
|
80
|
+
);
|
|
81
|
+
const authSaltHex = options.salt ? options.salt.toHex() : randomWord().toHex();
|
|
82
|
+
const authSalt = WordType.fromHex(normalizeHexWord(authSaltHex));
|
|
83
|
+
|
|
84
|
+
let txBuilder = new TransactionRequestBuilder();
|
|
85
|
+
txBuilder = txBuilder.withCustomScript(script);
|
|
86
|
+
txBuilder = txBuilder.withAuthArg(authSalt);
|
|
87
|
+
|
|
88
|
+
if (options.signatureAdviceMap) {
|
|
89
|
+
txBuilder = txBuilder.extendAdviceMap(options.signatureAdviceMap);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
request: txBuilder.build(),
|
|
94
|
+
salt: WordType.fromHex(normalizeHexWord(authSaltHex)),
|
|
95
|
+
configHash,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
@@ -10,10 +10,14 @@ import {
|
|
|
10
10
|
Word,
|
|
11
11
|
Word as WordType,
|
|
12
12
|
} from '@miden-sdk/miden-sdk';
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
MULTISIG_ECDSA_MASM,
|
|
15
|
+
MULTISIG_MASM,
|
|
16
|
+
} from '../account/masm/auth.js';
|
|
14
17
|
import { normalizeHexWord } from '../utils/encoding.js';
|
|
15
18
|
import { randomWord } from '../utils/random.js';
|
|
16
19
|
import type { SignatureOptions } from './options.js';
|
|
20
|
+
import type { SignatureScheme } from '../types.js';
|
|
17
21
|
|
|
18
22
|
function buildMultisigConfigAdvice(
|
|
19
23
|
threshold: number,
|
|
@@ -35,31 +39,14 @@ function buildMultisigConfigAdvice(
|
|
|
35
39
|
return { configHash, payload };
|
|
36
40
|
}
|
|
37
41
|
|
|
38
|
-
function
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const multisigLib = libBuilder.buildLibrary('auth::multisig', MULTISIG_MASM);
|
|
44
|
-
libBuilder.linkDynamicLibrary(multisigLib);
|
|
45
|
-
|
|
46
|
-
const scriptSource = `
|
|
47
|
-
use auth::multisig
|
|
48
|
-
|
|
49
|
-
begin
|
|
50
|
-
call.multisig::update_signers_and_threshold
|
|
51
|
-
end
|
|
52
|
-
`;
|
|
53
|
-
|
|
54
|
-
return libBuilder.compileTxScript(scriptSource);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function buildUpdateSignersEcdsaScript(webClient: WebClient): TransactionScript {
|
|
42
|
+
function buildUpdateSignersScript(
|
|
43
|
+
webClient: WebClient,
|
|
44
|
+
signatureScheme: SignatureScheme,
|
|
45
|
+
): TransactionScript {
|
|
58
46
|
const libBuilder = webClient.createCodeBuilder();
|
|
59
|
-
const
|
|
60
|
-
libBuilder.linkStaticLibrary(psmLib);
|
|
47
|
+
const multisigMasm = signatureScheme === 'ecdsa' ? MULTISIG_ECDSA_MASM : MULTISIG_MASM;
|
|
61
48
|
|
|
62
|
-
const multisigLib = libBuilder.buildLibrary('auth::multisig',
|
|
49
|
+
const multisigLib = libBuilder.buildLibrary('auth::multisig', multisigMasm);
|
|
63
50
|
libBuilder.linkDynamicLibrary(multisigLib);
|
|
64
51
|
|
|
65
52
|
const scriptSource = `
|
|
@@ -89,9 +76,7 @@ export async function buildUpdateSignersTransactionRequest(
|
|
|
89
76
|
const advice = new AdviceMap();
|
|
90
77
|
advice.insert(configHashForAdvice, payload);
|
|
91
78
|
|
|
92
|
-
const script = signatureScheme
|
|
93
|
-
? buildUpdateSignersEcdsaScript(webClient)
|
|
94
|
-
: buildUpdateSignersFalconScript(webClient);
|
|
79
|
+
const script = buildUpdateSignersScript(webClient, signatureScheme);
|
|
95
80
|
|
|
96
81
|
const authSaltHex = options.salt ? options.salt.toHex() : randomWord().toHex();
|
|
97
82
|
|
package/src/transaction.ts
CHANGED
|
@@ -6,9 +6,11 @@ export {
|
|
|
6
6
|
buildP2idTransactionRequest,
|
|
7
7
|
} from './transaction/p2id.js';
|
|
8
8
|
export {
|
|
9
|
-
|
|
10
|
-
} from './transaction/
|
|
9
|
+
buildUpdateGuardianTransactionRequest,
|
|
10
|
+
} from './transaction/updateGuardian.js';
|
|
11
|
+
export {
|
|
12
|
+
buildUpdateProcedureThresholdTransactionRequest,
|
|
13
|
+
} from './transaction/updateProcedureThreshold.js';
|
|
11
14
|
export {
|
|
12
15
|
buildUpdateSignersTransactionRequest,
|
|
13
16
|
} from './transaction/updateSigners.js';
|
|
14
|
-
|
package/src/types/proposal.ts
CHANGED
|
@@ -1,21 +1,32 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
ProposalSignature,
|
|
3
|
+
ProposalType as GuardianProposalType,
|
|
4
|
+
SignatureScheme,
|
|
5
|
+
} from '@openzeppelin/guardian-client';
|
|
6
|
+
import type { ProcedureName } from '../procedures.js';
|
|
7
|
+
|
|
8
|
+
export type ProposalType = Exclude<GuardianProposalType, 'custom'>;
|
|
9
|
+
|
|
10
|
+
export type ProposalStatus = 'pending' | 'ready' | 'finalized';
|
|
3
11
|
|
|
4
12
|
export type TransactionProposalStatus =
|
|
5
13
|
| { type: 'pending'; signaturesCollected: number; signaturesRequired: number; signers: string[] }
|
|
6
14
|
| { type: 'ready' }
|
|
7
15
|
| { type: 'finalized' };
|
|
8
16
|
|
|
9
|
-
export interface
|
|
17
|
+
export interface ProposalSignatureEntry {
|
|
10
18
|
signerId: string;
|
|
11
|
-
signature:
|
|
19
|
+
signature: ProposalSignature;
|
|
12
20
|
timestamp: string;
|
|
13
21
|
}
|
|
14
22
|
|
|
23
|
+
export type TransactionProposalSignature = ProposalSignatureEntry;
|
|
24
|
+
|
|
15
25
|
interface BaseProposalMetadata {
|
|
16
26
|
proposalType: ProposalType;
|
|
17
27
|
description: string;
|
|
18
28
|
saltHex?: string;
|
|
29
|
+
requiredSignatures?: number;
|
|
19
30
|
}
|
|
20
31
|
|
|
21
32
|
export interface UpdateSignersProposalMetadata extends BaseProposalMetadata {
|
|
@@ -24,14 +35,20 @@ export interface UpdateSignersProposalMetadata extends BaseProposalMetadata {
|
|
|
24
35
|
targetSignerCommitments: string[];
|
|
25
36
|
}
|
|
26
37
|
|
|
27
|
-
export interface
|
|
28
|
-
proposalType: '
|
|
29
|
-
|
|
30
|
-
|
|
38
|
+
export interface SwitchGuardianProposalMetadata extends BaseProposalMetadata {
|
|
39
|
+
proposalType: 'switch_guardian';
|
|
40
|
+
newGuardianPubkey: string;
|
|
41
|
+
newGuardianEndpoint?: string;
|
|
31
42
|
targetThreshold?: number;
|
|
32
43
|
targetSignerCommitments?: string[];
|
|
33
44
|
}
|
|
34
45
|
|
|
46
|
+
export interface UpdateProcedureThresholdProposalMetadata extends BaseProposalMetadata {
|
|
47
|
+
proposalType: 'update_procedure_threshold';
|
|
48
|
+
targetProcedure: ProcedureName;
|
|
49
|
+
targetThreshold: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
35
52
|
export interface ConsumeNotesProposalMetadata extends BaseProposalMetadata {
|
|
36
53
|
proposalType: 'consume_notes';
|
|
37
54
|
noteIds: string[];
|
|
@@ -50,11 +67,22 @@ export interface UnknownProposalMetadata extends BaseProposalMetadata {
|
|
|
50
67
|
|
|
51
68
|
export type ProposalMetadata =
|
|
52
69
|
| UpdateSignersProposalMetadata
|
|
53
|
-
|
|
|
70
|
+
| SwitchGuardianProposalMetadata
|
|
71
|
+
| UpdateProcedureThresholdProposalMetadata
|
|
54
72
|
| ConsumeNotesProposalMetadata
|
|
55
73
|
| P2IdProposalMetadata
|
|
56
74
|
| UnknownProposalMetadata;
|
|
57
75
|
|
|
76
|
+
export interface Proposal {
|
|
77
|
+
id: string;
|
|
78
|
+
accountId: string;
|
|
79
|
+
nonce: number;
|
|
80
|
+
status: ProposalStatus;
|
|
81
|
+
txSummary: string;
|
|
82
|
+
signatures: ProposalSignatureEntry[];
|
|
83
|
+
metadata: ProposalMetadata;
|
|
84
|
+
}
|
|
85
|
+
|
|
58
86
|
export interface TransactionProposal {
|
|
59
87
|
id: string;
|
|
60
88
|
commitment: string;
|
|
@@ -66,7 +94,7 @@ export interface TransactionProposal {
|
|
|
66
94
|
metadata: ProposalMetadata;
|
|
67
95
|
}
|
|
68
96
|
|
|
69
|
-
export interface
|
|
97
|
+
export interface ExportedProposal {
|
|
70
98
|
accountId: string;
|
|
71
99
|
nonce: number;
|
|
72
100
|
commitment: string;
|
|
@@ -74,11 +102,15 @@ export interface ExportedTransactionProposal {
|
|
|
74
102
|
signatures: Array<{
|
|
75
103
|
commitment: string;
|
|
76
104
|
signatureHex: string;
|
|
105
|
+
scheme?: SignatureScheme;
|
|
106
|
+
publicKey?: string;
|
|
77
107
|
timestamp?: string;
|
|
78
108
|
}>;
|
|
79
|
-
metadata
|
|
109
|
+
metadata: ProposalMetadata;
|
|
80
110
|
}
|
|
81
111
|
|
|
112
|
+
export type ExportedTransactionProposal = ExportedProposal;
|
|
113
|
+
|
|
82
114
|
export interface SignTransactionProposalParams {
|
|
83
115
|
commitment: string;
|
|
84
116
|
signature: string;
|
package/src/types.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Account } from '@miden-sdk/miden-sdk';
|
|
2
|
-
import type { SignatureScheme } from '@openzeppelin/
|
|
2
|
+
import type { SignatureScheme } from '@openzeppelin/guardian-client';
|
|
3
3
|
import type { ProcedureName } from './procedures.js';
|
|
4
|
-
import type { TransactionProposal } from './types/proposal.js';
|
|
5
4
|
import type { AccountState } from './multisig.js';
|
|
6
5
|
import type { DetectedMultisigConfig } from './inspector.js';
|
|
6
|
+
import type { TransactionProposal } from './types/proposal.js';
|
|
7
7
|
|
|
8
8
|
export type {
|
|
9
9
|
Signer,
|
|
@@ -23,16 +23,20 @@ export type {
|
|
|
23
23
|
DeltaProposalResponse,
|
|
24
24
|
ProposalsResponse,
|
|
25
25
|
SignProposalRequest,
|
|
26
|
-
} from '@openzeppelin/
|
|
26
|
+
} from '@openzeppelin/guardian-client';
|
|
27
27
|
|
|
28
28
|
export type {
|
|
29
|
-
|
|
30
|
-
TransactionProposalStatus,
|
|
31
|
-
TransactionProposalSignature,
|
|
29
|
+
ExportedProposal,
|
|
32
30
|
ExportedTransactionProposal,
|
|
33
|
-
|
|
31
|
+
Proposal,
|
|
34
32
|
ProposalMetadata,
|
|
33
|
+
ProposalSignatureEntry,
|
|
34
|
+
ProposalStatus,
|
|
35
35
|
ProposalType,
|
|
36
|
+
SignTransactionProposalParams,
|
|
37
|
+
TransactionProposal,
|
|
38
|
+
TransactionProposalSignature,
|
|
39
|
+
TransactionProposalStatus,
|
|
36
40
|
} from './types/proposal.js';
|
|
37
41
|
|
|
38
42
|
export interface SyncResult {
|
|
@@ -54,20 +58,33 @@ export interface MultisigAccountState {
|
|
|
54
58
|
cosignerCommitments: string[];
|
|
55
59
|
}
|
|
56
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Per-procedure threshold override.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const thresholds: ProcedureThreshold[] = [
|
|
67
|
+
* { procedure: 'receive_asset', threshold: 1 },
|
|
68
|
+
* { procedure: 'update_signers', threshold: 3 },
|
|
69
|
+
* ];
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
57
72
|
export interface ProcedureThreshold {
|
|
58
73
|
procedure: ProcedureName;
|
|
74
|
+
/** Threshold for this procedure (1 to numSigners) */
|
|
59
75
|
threshold: number;
|
|
60
76
|
}
|
|
61
77
|
|
|
62
78
|
export interface MultisigConfig {
|
|
63
79
|
threshold: number;
|
|
64
80
|
signerCommitments: string[];
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
81
|
+
guardianCommitment: string;
|
|
82
|
+
guardianPublicKey?: string;
|
|
83
|
+
guardianEnabled?: boolean;
|
|
68
84
|
storageMode?: 'private' | 'public';
|
|
69
85
|
procedureThresholds?: ProcedureThreshold[];
|
|
70
86
|
signatureScheme?: SignatureScheme;
|
|
87
|
+
seed?: Uint8Array
|
|
71
88
|
}
|
|
72
89
|
|
|
73
90
|
export interface CreateAccountResult {
|
|
@@ -78,7 +95,8 @@ export interface CreateAccountResult {
|
|
|
78
95
|
export type TransactionType =
|
|
79
96
|
| { type: 'p2id'; recipient: string; faucetId: string; amount: bigint }
|
|
80
97
|
| { type: 'consumeNotes'; noteIds: string[] }
|
|
81
|
-
| { type: 'updateSigners'; newThreshold: number; newSignerCommitments: string[] }
|
|
98
|
+
| { type: 'updateSigners'; newThreshold: number; newSignerCommitments: string[] }
|
|
99
|
+
| { type: 'updateProcedureThreshold'; procedure: ProcedureName; threshold: number };
|
|
82
100
|
|
|
83
101
|
export interface NoteAsset {
|
|
84
102
|
faucetId: string;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, expect, it, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { AuthDigest } from './digest.js';
|
|
3
|
+
|
|
4
|
+
vi.mock('@miden-sdk/miden-sdk', () => ({
|
|
5
|
+
AccountId: {
|
|
6
|
+
fromHex: vi.fn(() => ({
|
|
7
|
+
prefix: () => ({ label: 'prefix' }),
|
|
8
|
+
suffix: () => ({ label: 'suffix' }),
|
|
9
|
+
})),
|
|
10
|
+
},
|
|
11
|
+
Felt: vi.fn().mockImplementation((value: bigint) => ({ value })),
|
|
12
|
+
FeltArray: vi.fn().mockImplementation((elements: unknown[]) => elements),
|
|
13
|
+
Word: {
|
|
14
|
+
fromHex: vi.fn((hex: string) => ({
|
|
15
|
+
toHex: () => hex,
|
|
16
|
+
toFelts: () => [],
|
|
17
|
+
})),
|
|
18
|
+
},
|
|
19
|
+
Rpo256: {
|
|
20
|
+
hashElements: vi.fn().mockReturnValue({
|
|
21
|
+
toHex: () => '0x' + 'aa'.repeat(32),
|
|
22
|
+
toFelts: () => [],
|
|
23
|
+
}),
|
|
24
|
+
},
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
describe('AuthDigest', () => {
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
vi.clearAllMocks();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('uses the legacy 4-felt digest for account auth', async () => {
|
|
33
|
+
const { FeltArray, Rpo256 } = await import('@miden-sdk/miden-sdk');
|
|
34
|
+
|
|
35
|
+
AuthDigest.fromAccountIdWithTimestamp('0x' + 'ab'.repeat(15), 1700000000);
|
|
36
|
+
|
|
37
|
+
expect(FeltArray).toHaveBeenCalledWith([
|
|
38
|
+
{ label: 'prefix' },
|
|
39
|
+
{ label: 'suffix' },
|
|
40
|
+
{ value: 1700000000n },
|
|
41
|
+
{ value: 0n },
|
|
42
|
+
]);
|
|
43
|
+
expect(Rpo256.hashElements).toHaveBeenCalledTimes(1);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('includes the request payload hash for request-bound auth', async () => {
|
|
47
|
+
const { Rpo256 } = await import('@miden-sdk/miden-sdk');
|
|
48
|
+
|
|
49
|
+
AuthDigest.fromRequest('0x' + 'ab'.repeat(15), 1700000000, {
|
|
50
|
+
toBytes: () => new Uint8Array([1, 2, 3, 4]),
|
|
51
|
+
} as never);
|
|
52
|
+
|
|
53
|
+
expect(Rpo256.hashElements).toHaveBeenCalledTimes(2);
|
|
54
|
+
});
|
|
55
|
+
});
|
package/src/utils/digest.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RequestAuthPayload } from '@openzeppelin/guardian-client';
|
|
1
2
|
import { AccountId, Felt, FeltArray, Rpo256, Word } from '@miden-sdk/miden-sdk';
|
|
2
3
|
|
|
3
4
|
export class AuthDigest {
|
|
@@ -11,7 +12,35 @@ export class AuthDigest {
|
|
|
11
12
|
prefix,
|
|
12
13
|
suffix,
|
|
13
14
|
new Felt(BigInt(timestamp)),
|
|
14
|
-
new Felt(
|
|
15
|
+
new Felt(0n),
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
return Rpo256.hashElements(feltArray);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static fromRequest(accountId: string, timestamp: number, requestPayload: RequestAuthPayload): Word {
|
|
22
|
+
return AuthDigest.fromAccountIdTimestampAndPayloadWord(
|
|
23
|
+
accountId,
|
|
24
|
+
timestamp,
|
|
25
|
+
AuthDigest.payloadWordFromBytes(requestPayload.toBytes()),
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private static fromAccountIdTimestampAndPayloadWord(
|
|
30
|
+
accountId: string,
|
|
31
|
+
timestamp: number,
|
|
32
|
+
payloadWord: Word,
|
|
33
|
+
): Word {
|
|
34
|
+
const paddedHex = accountId.startsWith('0x') ? accountId : `0x${accountId}`;
|
|
35
|
+
const parsedAccountId = AccountId.fromHex(paddedHex);
|
|
36
|
+
const prefix = parsedAccountId.prefix();
|
|
37
|
+
const suffix = parsedAccountId.suffix();
|
|
38
|
+
|
|
39
|
+
const feltArray = new FeltArray([
|
|
40
|
+
prefix,
|
|
41
|
+
suffix,
|
|
42
|
+
new Felt(BigInt(timestamp)),
|
|
43
|
+
...payloadWord.toFelts(),
|
|
15
44
|
]);
|
|
16
45
|
|
|
17
46
|
return Rpo256.hashElements(feltArray);
|
|
@@ -22,4 +51,25 @@ export class AuthDigest {
|
|
|
22
51
|
const cleanHex = paddedHex.slice(2).padStart(64, '0');
|
|
23
52
|
return Word.fromHex(`0x${cleanHex}`);
|
|
24
53
|
}
|
|
54
|
+
|
|
55
|
+
private static emptyPayloadWord(): Word {
|
|
56
|
+
return Word.fromHex(`0x${'0'.repeat(64)}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private static payloadWordFromBytes(bytes: Uint8Array): Word {
|
|
60
|
+
if (bytes.length === 0) {
|
|
61
|
+
return AuthDigest.emptyPayloadWord();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const payloadElements: Felt[] = [];
|
|
65
|
+
for (let i = 0; i < bytes.length; i += 8) {
|
|
66
|
+
let packed = 0n;
|
|
67
|
+
for (let j = 0; j < 8 && i + j < bytes.length; j += 1) {
|
|
68
|
+
packed |= BigInt(bytes[i + j]) << (8n * BigInt(j));
|
|
69
|
+
}
|
|
70
|
+
payloadElements.push(new Felt(packed));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return Rpo256.hashElements(new FeltArray(payloadElements));
|
|
74
|
+
}
|
|
25
75
|
}
|
package/src/utils/signature.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { AdviceMap, Felt, FeltArray, Rpo256, Signature, Word } from '@miden-sdk/miden-sdk';
|
|
2
2
|
import * as midenSdk from '@miden-sdk/miden-sdk';
|
|
3
3
|
import { hexToBytes, normalizeHexWord } from './encoding.js';
|
|
4
|
-
import type { SignatureScheme } from '../types.js';
|
|
4
|
+
import type { ProposalSignatureEntry, SignatureScheme } from '../types.js';
|
|
5
5
|
|
|
6
|
-
export function signatureHexToBytes(
|
|
6
|
+
export function signatureHexToBytes(
|
|
7
|
+
hex: string,
|
|
8
|
+
scheme: SignatureScheme = 'falcon',
|
|
9
|
+
): Uint8Array {
|
|
7
10
|
const sigBytes = hexToBytes(hex);
|
|
8
11
|
const withPrefix = new Uint8Array(sigBytes.length + 1);
|
|
9
12
|
withPrefix[0] = scheme === 'ecdsa' ? 1 : 0;
|
|
@@ -15,7 +18,7 @@ function bytesToPackedU32Felts(bytes: Uint8Array): Felt[] {
|
|
|
15
18
|
const felts: Felt[] = [];
|
|
16
19
|
for (let i = 0; i < bytes.length; i += 4) {
|
|
17
20
|
let packed = 0;
|
|
18
|
-
for (let j = 0; j < 4 && i + j < bytes.length; j
|
|
21
|
+
for (let j = 0; j < 4 && i + j < bytes.length; j += 1) {
|
|
19
22
|
packed |= bytes[i + j] << (j * 8);
|
|
20
23
|
}
|
|
21
24
|
felts.push(new Felt(BigInt(packed >>> 0)));
|
|
@@ -87,7 +90,7 @@ export function verifyEcdsaCommitment(
|
|
|
87
90
|
const packedU32Values: number[] = [];
|
|
88
91
|
for (let i = 0; i < bytes.length; i += 4) {
|
|
89
92
|
let packed = 0;
|
|
90
|
-
for (let j = 0; j < 4 && i + j < bytes.length; j
|
|
93
|
+
for (let j = 0; j < 4 && i + j < bytes.length; j += 1) {
|
|
91
94
|
packed |= bytes[i + j] << (j * 8);
|
|
92
95
|
}
|
|
93
96
|
packedU32Values.push(packed >>> 0);
|
|
@@ -101,19 +104,22 @@ export function verifyEcdsaCommitment(
|
|
|
101
104
|
return {
|
|
102
105
|
match: computedHex === expectedNorm,
|
|
103
106
|
computedHex,
|
|
104
|
-
packedFelts: packedU32Values.map(
|
|
107
|
+
packedFelts: packedU32Values.map((value) => value.toString()),
|
|
105
108
|
};
|
|
106
|
-
} catch (
|
|
109
|
+
} catch (error) {
|
|
107
110
|
return {
|
|
108
111
|
match: false,
|
|
109
|
-
computedHex: `ERROR: ${
|
|
112
|
+
computedHex: `ERROR: ${error}`,
|
|
110
113
|
packedFelts: [],
|
|
111
|
-
error: String(
|
|
114
|
+
error: String(error),
|
|
112
115
|
};
|
|
113
116
|
}
|
|
114
117
|
}
|
|
115
118
|
|
|
116
|
-
export function mergeSignatureAdviceMaps(
|
|
119
|
+
export function mergeSignatureAdviceMaps(
|
|
120
|
+
advice: AdviceMap,
|
|
121
|
+
entries: Array<{ key: Word; values: Felt[] }>,
|
|
122
|
+
): AdviceMap {
|
|
117
123
|
for (const entry of entries) {
|
|
118
124
|
advice.insert(entry.key, new FeltArray(entry.values));
|
|
119
125
|
}
|
|
@@ -123,3 +129,35 @@ export function mergeSignatureAdviceMaps(advice: AdviceMap, entries: Array<{ key
|
|
|
123
129
|
export function toWord(hex: string): Word {
|
|
124
130
|
return Word.fromHex(normalizeHexWord(hex));
|
|
125
131
|
}
|
|
132
|
+
|
|
133
|
+
export function normalizeSignerCommitment(signerId: string): string {
|
|
134
|
+
const hex = signerId.startsWith('0x') || signerId.startsWith('0X')
|
|
135
|
+
? signerId.slice(2)
|
|
136
|
+
: signerId;
|
|
137
|
+
|
|
138
|
+
if (hex.length !== 64 || !/^[0-9a-fA-F]+$/.test(hex)) {
|
|
139
|
+
throw new Error(`expected signerId as 32-byte hex, got ${signerId}`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return normalizeHexWord(signerId);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function canonicalizeSignature(
|
|
146
|
+
signature: ProposalSignatureEntry,
|
|
147
|
+
signerCommitments: Set<string>,
|
|
148
|
+
): ProposalSignatureEntry {
|
|
149
|
+
try {
|
|
150
|
+
const signerId = normalizeSignerCommitment(signature.signerId);
|
|
151
|
+
if (!signerCommitments.has(signerId)) {
|
|
152
|
+
throw new Error(`signer ${signerId} is not part of this multisig`);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
...signature,
|
|
157
|
+
signerId,
|
|
158
|
+
};
|
|
159
|
+
} catch (error) {
|
|
160
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
161
|
+
throw new Error(message);
|
|
162
|
+
}
|
|
163
|
+
}
|
package/src/utils/word.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
-
import { wordElementToBigInt, wordToHex
|
|
2
|
+
import { wordElementToBigInt, wordToHex } from './word.js';
|
|
3
3
|
import { Word } from '@miden-sdk/miden-sdk';
|
|
4
4
|
|
|
5
5
|
// Mock the Miden SDK Word class
|
|
@@ -61,58 +61,4 @@ describe('word utilities', () => {
|
|
|
61
61
|
expect(hex).toBe(originalHex);
|
|
62
62
|
});
|
|
63
63
|
});
|
|
64
|
-
|
|
65
|
-
describe('wordToBytes', () => {
|
|
66
|
-
it('should convert a word with known felt values to LE bytes', () => {
|
|
67
|
-
const word = {
|
|
68
|
-
toFelts: () => [
|
|
69
|
-
{ asInt: () => 1n },
|
|
70
|
-
{ asInt: () => 2n },
|
|
71
|
-
{ asInt: () => 3n },
|
|
72
|
-
{ asInt: () => 4n },
|
|
73
|
-
],
|
|
74
|
-
};
|
|
75
|
-
const bytes = wordToBytes(word);
|
|
76
|
-
expect(bytes.length).toBe(32);
|
|
77
|
-
expect(bytes[0]).toBe(1);
|
|
78
|
-
expect(bytes[1]).toBe(0);
|
|
79
|
-
expect(bytes[8]).toBe(2);
|
|
80
|
-
expect(bytes[16]).toBe(3);
|
|
81
|
-
expect(bytes[24]).toBe(4);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('should encode felts in little-endian order', () => {
|
|
85
|
-
const word = {
|
|
86
|
-
toFelts: () => [
|
|
87
|
-
{ asInt: () => 0x0102030405060708n },
|
|
88
|
-
{ asInt: () => 0n },
|
|
89
|
-
{ asInt: () => 0n },
|
|
90
|
-
{ asInt: () => 0n },
|
|
91
|
-
],
|
|
92
|
-
};
|
|
93
|
-
const bytes = wordToBytes(word);
|
|
94
|
-
expect(bytes[0]).toBe(0x08);
|
|
95
|
-
expect(bytes[1]).toBe(0x07);
|
|
96
|
-
expect(bytes[2]).toBe(0x06);
|
|
97
|
-
expect(bytes[3]).toBe(0x05);
|
|
98
|
-
expect(bytes[4]).toBe(0x04);
|
|
99
|
-
expect(bytes[5]).toBe(0x03);
|
|
100
|
-
expect(bytes[6]).toBe(0x02);
|
|
101
|
-
expect(bytes[7]).toBe(0x01);
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it('should handle zero felts', () => {
|
|
105
|
-
const word = {
|
|
106
|
-
toFelts: () => [
|
|
107
|
-
{ asInt: () => 0n },
|
|
108
|
-
{ asInt: () => 0n },
|
|
109
|
-
{ asInt: () => 0n },
|
|
110
|
-
{ asInt: () => 0n },
|
|
111
|
-
],
|
|
112
|
-
};
|
|
113
|
-
const bytes = wordToBytes(word);
|
|
114
|
-
expect(bytes.length).toBe(32);
|
|
115
|
-
expect(bytes.every((b) => b === 0)).toBe(true);
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
64
|
});
|