@openzeppelin/miden-multisig-client 0.13.0 → 0.13.2
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.d.ts +2 -0
- package/dist/account/builder.test.d.ts.map +1 -0
- package/dist/account/builder.test.js +115 -0
- package/dist/account/builder.test.js.map +1 -0
- 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 +6 -5
- package/dist/multisig/proposal/execution.d.ts.map +1 -1
- package/dist/multisig/proposal/execution.js +49 -27
- 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 +187 -46
- package/dist/multisig.d.ts.map +1 -1
- package/dist/multisig.js +650 -289
- 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 +8 -0
- package/dist/proposal/metadata.d.ts.map +1 -0
- package/dist/proposal/metadata.js +156 -0
- package/dist/proposal/metadata.js.map +1 -0
- 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/p2id.test.d.ts +2 -0
- package/dist/transaction/p2id.test.d.ts.map +1 -0
- package/dist/transaction/p2id.test.js +138 -0
- package/dist/transaction/p2id.test.js.map +1 -0
- package/dist/transaction/rpoRandomCoin.d.ts +7 -0
- package/dist/transaction/rpoRandomCoin.d.ts.map +1 -0
- package/dist/transaction/rpoRandomCoin.js +17 -0
- package/dist/transaction/rpoRandomCoin.js.map +1 -0
- package/dist/transaction/rpoRandomCoin.test.d.ts +2 -0
- package/dist/transaction/rpoRandomCoin.test.d.ts.map +1 -0
- package/dist/transaction/rpoRandomCoin.test.js +52 -0
- package/dist/transaction/rpoRandomCoin.test.js.map +1 -0
- 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 +102 -41
- 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 -365
- 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/signer.test.d.ts +0 -2
- package/dist/signer.test.d.ts.map +0 -1
- package/dist/signer.test.js +0 -117
- package/dist/signer.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/masm/psm.masm +0 -178
- package/masm/psm_ecdsa.masm +0 -179
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
# Multi-Signature ECDSA secp256k1 Authentication
|
|
1
|
+
# Multi-Signature ECDSA secp256k1 Authentication Core Library
|
|
2
2
|
#
|
|
3
|
-
# This
|
|
4
|
-
# ECDSA secp256k1 (k256/keccak) signatures instead of RPO Falcon 512.
|
|
5
|
-
# It integrates with the PSM component for optional PSM signature verification.
|
|
3
|
+
# This library provides the reusable multisig procedures used by account wrappers.
|
|
6
4
|
|
|
7
|
-
use miden::active_account
|
|
8
|
-
use miden::native_account
|
|
9
|
-
use miden::auth
|
|
10
|
-
use openzeppelin::psm_ecdsa
|
|
11
|
-
|
|
12
|
-
# Type definitions for v0.12 syntax
|
|
5
|
+
use miden::protocol::active_account
|
|
6
|
+
use miden::protocol::native_account
|
|
7
|
+
use miden::standards::auth
|
|
13
8
|
type BeWord = struct @bigendian { a: felt, b: felt, c: felt, d: felt }
|
|
14
9
|
|
|
15
10
|
# CONSTANTS
|
|
@@ -18,7 +13,7 @@ type BeWord = struct @bigendian { a: felt, b: felt, c: felt, d: felt }
|
|
|
18
13
|
# Auth Request Constants
|
|
19
14
|
|
|
20
15
|
# The event emitted when a signature is not found for a required signer.
|
|
21
|
-
const AUTH_UNAUTHORIZED_EVENT
|
|
16
|
+
const AUTH_UNAUTHORIZED_EVENT=event("miden::auth::unauthorized")
|
|
22
17
|
|
|
23
18
|
# Storage Layout Constants
|
|
24
19
|
#
|
|
@@ -33,29 +28,35 @@ const AUTH_UNAUTHORIZED_EVENT = event("miden::auth::unauthorized")
|
|
|
33
28
|
# number of approvers are stored as:
|
|
34
29
|
# [default_threshold, num_approvers, 0, 0].
|
|
35
30
|
# The threshold is guaranteed to be less than or equal to num_approvers.
|
|
36
|
-
const THRESHOLD_CONFIG_SLOT
|
|
31
|
+
const THRESHOLD_CONFIG_SLOT=word("openzeppelin::multisig::threshold_config")
|
|
37
32
|
|
|
38
33
|
# The slot in this component's storage layout where the public keys map is stored.
|
|
39
34
|
# Map entries: [key_index, 0, 0, 0] => APPROVER_PUBLIC_KEY
|
|
40
|
-
const PUBLIC_KEYS_MAP_SLOT
|
|
35
|
+
const PUBLIC_KEYS_MAP_SLOT=word("openzeppelin::multisig::signer_public_keys")
|
|
41
36
|
|
|
42
37
|
# The slot in this component's storage layout where executed transactions are stored.
|
|
43
38
|
# Map entries: transaction_message => [is_executed, 0, 0, 0]
|
|
44
|
-
const EXECUTED_TXS_SLOT
|
|
39
|
+
const EXECUTED_TXS_SLOT=word("openzeppelin::multisig::executed_transactions")
|
|
45
40
|
|
|
46
41
|
# The slot in this component's storage layout where procedure thresholds are stored.
|
|
47
42
|
# Map entries: PROC_ROOT => [proc_threshold, 0, 0, 0]
|
|
48
|
-
const PROC_THRESHOLD_ROOTS_SLOT
|
|
43
|
+
const PROC_THRESHOLD_ROOTS_SLOT=word("openzeppelin::multisig::procedure_thresholds")
|
|
49
44
|
|
|
50
45
|
# Executed Transaction Flag Constant
|
|
51
|
-
const IS_EXECUTED_FLAG
|
|
46
|
+
const IS_EXECUTED_FLAG=[1, 0, 0, 0]
|
|
52
47
|
|
|
53
48
|
# ERRORS
|
|
54
|
-
const ERR_TX_ALREADY_EXECUTED
|
|
49
|
+
const ERR_TX_ALREADY_EXECUTED="failed to approve multisig transaction as it was already executed"
|
|
50
|
+
|
|
51
|
+
const ERR_MALFORMED_MULTISIG_CONFIG="number of approvers must be equal to or greater than threshold"
|
|
52
|
+
|
|
53
|
+
const ERR_ZERO_IN_MULTISIG_CONFIG="number of approvers or threshold must not be zero"
|
|
54
|
+
|
|
55
|
+
const ERR_PROC_THRESHOLD_NOT_U32="procedure threshold must be a u32 value"
|
|
55
56
|
|
|
56
|
-
const
|
|
57
|
+
const ERR_NUM_APPROVERS_OR_PROC_THRESHOLD_NOT_U32="number of approvers and procedure threshold must be u32"
|
|
57
58
|
|
|
58
|
-
const
|
|
59
|
+
const ERR_PROC_THRESHOLD_EXCEEDS_NUM_APPROVERS="procedure threshold exceeds number of approvers"
|
|
59
60
|
|
|
60
61
|
# MULTISIG PROCEDURES
|
|
61
62
|
# =================================================================================================
|
|
@@ -67,21 +68,21 @@ const ERR_ZERO_IN_MULTISIG_CONFIG = "number of approvers or threshold must not b
|
|
|
67
68
|
#!
|
|
68
69
|
#! Panics if:
|
|
69
70
|
#! - the same transaction has already been executed
|
|
70
|
-
proc assert_new_tx(msg: BeWord)
|
|
71
|
+
pub proc assert_new_tx(msg: BeWord)
|
|
71
72
|
push.IS_EXECUTED_FLAG
|
|
72
73
|
# => [[0, 0, 0, is_executed], MSG]
|
|
73
74
|
|
|
74
75
|
swapw
|
|
75
76
|
# => [MSG, IS_EXECUTED_FLAG]
|
|
76
77
|
|
|
77
|
-
push.EXECUTED_TXS_SLOT
|
|
78
|
-
# => [
|
|
78
|
+
push.EXECUTED_TXS_SLOT[0..2]
|
|
79
|
+
# => [txs_slot_prefix, txs_slot_suffix, MSG, IS_EXECUTED_FLAG]
|
|
79
80
|
|
|
80
81
|
# Set the key value pair in the map to mark transaction as executed
|
|
81
82
|
exec.native_account::set_map_item
|
|
82
|
-
# => [
|
|
83
|
+
# => [[0, 0, 0, is_executed]]
|
|
83
84
|
|
|
84
|
-
|
|
85
|
+
drop drop drop
|
|
85
86
|
# => [is_executed]
|
|
86
87
|
|
|
87
88
|
assertz.err=ERR_TX_ALREADY_EXECUTED
|
|
@@ -120,13 +121,13 @@ proc cleanup_pubkey_mapping(init_num_of_approvers: u32, new_num_of_approvers: u3
|
|
|
120
121
|
padw swapw
|
|
121
122
|
# => [[0, 0, 0, i-1], EMPTY_WORD, i-1, new_num_of_approvers]
|
|
122
123
|
|
|
123
|
-
push.PUBLIC_KEYS_MAP_SLOT
|
|
124
|
-
# => [
|
|
124
|
+
push.PUBLIC_KEYS_MAP_SLOT[0..2]
|
|
125
|
+
# => [pub_key_slot_prefix, pub_key_slot_suffix, [0, 0, 0, i-1], EMPTY_WORD, i-1, new_num_of_approvers]
|
|
125
126
|
|
|
126
127
|
exec.native_account::set_map_item
|
|
127
|
-
# => [
|
|
128
|
+
# => [OLD_MAP_VALUE, i-1, new_num_of_approvers]
|
|
128
129
|
|
|
129
|
-
dropw
|
|
130
|
+
dropw
|
|
130
131
|
# => [i-1, new_num_of_approvers]
|
|
131
132
|
|
|
132
133
|
dup.1 dup.1
|
|
@@ -138,6 +139,85 @@ proc cleanup_pubkey_mapping(init_num_of_approvers: u32, new_num_of_approvers: u3
|
|
|
138
139
|
# => []
|
|
139
140
|
end
|
|
140
141
|
|
|
142
|
+
proc get_threshold_and_num_approvers
|
|
143
|
+
push.THRESHOLD_CONFIG_SLOT[0..2]
|
|
144
|
+
exec.active_account::get_initial_item
|
|
145
|
+
# => [0, 0, num_approvers, threshold]
|
|
146
|
+
|
|
147
|
+
drop drop
|
|
148
|
+
# => [num_approvers, threshold]
|
|
149
|
+
|
|
150
|
+
swap
|
|
151
|
+
# => [threshold, num_approvers]
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
proc assert_proc_thresholds_lte_num_approvers(num_approvers: u32)
|
|
155
|
+
exec.active_account::get_num_procedures
|
|
156
|
+
# => [num_procedures, num_approvers]
|
|
157
|
+
|
|
158
|
+
dup neq.0
|
|
159
|
+
# => [should_continue, num_procedures, num_approvers]
|
|
160
|
+
while.true
|
|
161
|
+
sub.1 dup
|
|
162
|
+
# => [proc_index, proc_index, num_approvers]
|
|
163
|
+
|
|
164
|
+
exec.active_account::get_procedure_root
|
|
165
|
+
# => [PROC_ROOT, proc_index, num_approvers]
|
|
166
|
+
|
|
167
|
+
push.PROC_THRESHOLD_ROOTS_SLOT[0..2]
|
|
168
|
+
# => [proc_roots_slot_prefix, proc_roots_slot_suffix, PROC_ROOT, proc_index, num_approvers]
|
|
169
|
+
|
|
170
|
+
exec.active_account::get_initial_map_item
|
|
171
|
+
# => [[0, 0, 0, proc_threshold], proc_index, num_approvers]
|
|
172
|
+
|
|
173
|
+
drop drop drop
|
|
174
|
+
# => [proc_threshold, proc_index, num_approvers]
|
|
175
|
+
|
|
176
|
+
dup.2
|
|
177
|
+
# => [num_approvers, proc_threshold, proc_index, num_approvers]
|
|
178
|
+
|
|
179
|
+
u32assert2.err=ERR_PROC_THRESHOLD_NOT_U32
|
|
180
|
+
u32gt assertz.err=ERR_PROC_THRESHOLD_EXCEEDS_NUM_APPROVERS
|
|
181
|
+
# => [proc_index, num_approvers]
|
|
182
|
+
|
|
183
|
+
dup neq.0
|
|
184
|
+
# => [should_continue, proc_index, num_approvers]
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
drop drop
|
|
188
|
+
# => []
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Internal storage helper used by the public `update_procedure_threshold`
|
|
192
|
+
# entrypoint after it receives direct stack arguments.
|
|
193
|
+
proc set_procedure_threshold(proc_threshold: u32, proc_root: BeWord)
|
|
194
|
+
exec.get_threshold_and_num_approvers
|
|
195
|
+
# => [threshold, num_approvers, proc_threshold, PROC_ROOT]
|
|
196
|
+
|
|
197
|
+
drop
|
|
198
|
+
# => [num_approvers, proc_threshold, PROC_ROOT]
|
|
199
|
+
|
|
200
|
+
dup.1 swap
|
|
201
|
+
# => [num_approvers, proc_threshold, proc_threshold, PROC_ROOT]
|
|
202
|
+
|
|
203
|
+
u32assert2.err=ERR_NUM_APPROVERS_OR_PROC_THRESHOLD_NOT_U32
|
|
204
|
+
u32gt assertz.err=ERR_PROC_THRESHOLD_EXCEEDS_NUM_APPROVERS
|
|
205
|
+
# => [proc_threshold, PROC_ROOT]
|
|
206
|
+
|
|
207
|
+
push.0.0.0
|
|
208
|
+
swapw
|
|
209
|
+
# => [PROC_ROOT, PROC_THRESHOLD_WORD]
|
|
210
|
+
|
|
211
|
+
push.PROC_THRESHOLD_ROOTS_SLOT[0..2]
|
|
212
|
+
# => [proc_roots_slot_prefix, proc_roots_slot_suffix, PROC_ROOT, PROC_THRESHOLD_WORD]
|
|
213
|
+
|
|
214
|
+
exec.native_account::set_map_item
|
|
215
|
+
# => [OLD_VALUE]
|
|
216
|
+
|
|
217
|
+
dropw
|
|
218
|
+
# => []
|
|
219
|
+
end
|
|
220
|
+
|
|
141
221
|
#! Update threshold config and add / remove approvers
|
|
142
222
|
#!
|
|
143
223
|
#! Inputs:
|
|
@@ -156,7 +236,8 @@ end
|
|
|
156
236
|
#! Locals:
|
|
157
237
|
#! 0: new_num_of_approvers
|
|
158
238
|
#! 1: init_num_of_approvers
|
|
159
|
-
|
|
239
|
+
@locals(2)
|
|
240
|
+
pub proc update_signers_and_threshold(multisig_config_hash: BeWord)
|
|
160
241
|
adv.push_mapval
|
|
161
242
|
# => [MULTISIG_CONFIG_HASH, pad(12)]
|
|
162
243
|
|
|
@@ -183,8 +264,14 @@ pub proc update_signers_and_threshold.2(multisig_config_hash: BeWord)
|
|
|
183
264
|
eq.0 assertz.err=ERR_ZERO_IN_MULTISIG_CONFIG
|
|
184
265
|
# => [MULTISIG_CONFIG, pad(12)]
|
|
185
266
|
|
|
186
|
-
|
|
187
|
-
# => [
|
|
267
|
+
loc_load.0
|
|
268
|
+
# => [num_approvers, MULTISIG_CONFIG, pad(12)]
|
|
269
|
+
|
|
270
|
+
exec.assert_proc_thresholds_lte_num_approvers
|
|
271
|
+
# => [MULTISIG_CONFIG, pad(12)]
|
|
272
|
+
|
|
273
|
+
push.THRESHOLD_CONFIG_SLOT[0..2]
|
|
274
|
+
# => [config_slot_prefix, config_slot_suffix, MULTISIG_CONFIG, pad(12)]
|
|
188
275
|
|
|
189
276
|
exec.native_account::set_item
|
|
190
277
|
# => [OLD_THRESHOLD_CONFIG, pad(12)]
|
|
@@ -210,13 +297,13 @@ pub proc update_signers_and_threshold.2(multisig_config_hash: BeWord)
|
|
|
210
297
|
swapw
|
|
211
298
|
# => [[0, 0, 0, i-1], PUB_KEY, i-1, pad(12)]
|
|
212
299
|
|
|
213
|
-
push.PUBLIC_KEYS_MAP_SLOT
|
|
214
|
-
# => [
|
|
300
|
+
push.PUBLIC_KEYS_MAP_SLOT[0..2]
|
|
301
|
+
# => [pub_key_slot_prefix, pub_key_slot_suffix, [0, 0, 0, i-1], PUB_KEY, i-1, pad(12)]
|
|
215
302
|
|
|
216
303
|
exec.native_account::set_map_item
|
|
217
|
-
# => [
|
|
304
|
+
# => [OLD_VALUE, i-1, pad(12)]
|
|
218
305
|
|
|
219
|
-
dropw
|
|
306
|
+
dropw
|
|
220
307
|
# => [i-1, pad(12)]
|
|
221
308
|
|
|
222
309
|
dup neq.0
|
|
@@ -237,13 +324,25 @@ pub proc update_signers_and_threshold.2(multisig_config_hash: BeWord)
|
|
|
237
324
|
# => [pad(12)]
|
|
238
325
|
end
|
|
239
326
|
|
|
327
|
+
#! Update or clear the threshold override for a specific procedure.
|
|
328
|
+
#!
|
|
329
|
+
#! Inputs:
|
|
330
|
+
#! Operand stack: [proc_threshold, PROC_ROOT]
|
|
331
|
+
#! Outputs:
|
|
332
|
+
#! Operand stack: []
|
|
333
|
+
#! Invocation: call
|
|
334
|
+
pub proc update_procedure_threshold(proc_threshold: u32, proc_root: BeWord)
|
|
335
|
+
exec.set_procedure_threshold
|
|
336
|
+
end
|
|
337
|
+
|
|
240
338
|
# Computes the effective transaction threshold based on called procedures and per-procedure
|
|
241
339
|
# overrides stored in PROC_THRESHOLD_ROOTS_SLOT. Falls back to default_threshold if no
|
|
242
340
|
# overrides apply.
|
|
243
341
|
#
|
|
244
342
|
#! Inputs: [default_threshold]
|
|
245
343
|
#! Outputs: [transaction_threshold]
|
|
246
|
-
|
|
344
|
+
@locals(1)
|
|
345
|
+
proc compute_transaction_threshold(default_threshold: u32) -> u32
|
|
247
346
|
# 1. initialize transaction_threshold = 0
|
|
248
347
|
# 2. iterate through all account procedures
|
|
249
348
|
# a. check if the procedure was called during the transaction
|
|
@@ -282,8 +381,8 @@ proc compute_transaction_threshold.1(default_threshold: u32) -> u32
|
|
|
282
381
|
if.true
|
|
283
382
|
# => [PROC_ROOT, num_procedures-1, transaction_threshold]
|
|
284
383
|
|
|
285
|
-
push.PROC_THRESHOLD_ROOTS_SLOT
|
|
286
|
-
# => [
|
|
384
|
+
push.PROC_THRESHOLD_ROOTS_SLOT[0..2]
|
|
385
|
+
# => [PROC_THRESHOLD_ROOTS_SLOT_prefix, PROC_THRESHOLD_ROOTS_SLOT_suffix, PROC_ROOT, num_procedures-1, transaction_threshold]
|
|
287
386
|
|
|
288
387
|
# 2b. get the override proc_threshold of that procedure
|
|
289
388
|
# if the procedure has no override threshold, the returned map item will be [0, 0, 0, 0]
|
|
@@ -333,8 +432,7 @@ end
|
|
|
333
432
|
#! 1. Computing the transaction summary message that needs to be signed
|
|
334
433
|
#! 2. Verifying ECDSA signatures from multiple required signers against their public keys
|
|
335
434
|
#! 3. Ensuring the minimum threshold of valid signatures is met
|
|
336
|
-
#! 4.
|
|
337
|
-
#! 5. Verifying PSM signature if PSM selector is enabled (via PSM component)
|
|
435
|
+
#! 4. Returning the transaction summary commitment for higher-level wrappers.
|
|
338
436
|
#!
|
|
339
437
|
#! Inputs:
|
|
340
438
|
#! Operand stack: [SALT]
|
|
@@ -344,7 +442,7 @@ end
|
|
|
344
442
|
#! h(PUB_KEY_n, MSG): SIG_n
|
|
345
443
|
#! }
|
|
346
444
|
#! Outputs:
|
|
347
|
-
#! Operand stack: []
|
|
445
|
+
#! Operand stack: [TX_SUMMARY_COMMITMENT]
|
|
348
446
|
#!
|
|
349
447
|
#! Where:
|
|
350
448
|
#! - SALT is a cryptographically random nonce that enables multiple concurrent
|
|
@@ -356,11 +454,11 @@ end
|
|
|
356
454
|
#!
|
|
357
455
|
#! Panics if:
|
|
358
456
|
#! - insufficient number of valid signatures (below threshold).
|
|
359
|
-
#! -
|
|
360
|
-
#! - PSM signature verification fails (if PSM is enabled).
|
|
457
|
+
#! - insufficient number of valid signatures (below threshold).
|
|
361
458
|
#!
|
|
362
|
-
#! Invocation:
|
|
363
|
-
|
|
459
|
+
#! Invocation: exec
|
|
460
|
+
@locals(1)
|
|
461
|
+
pub proc auth_tx(salt: BeWord) -> BeWord
|
|
364
462
|
exec.native_account::incr_nonce drop
|
|
365
463
|
# => [SALT]
|
|
366
464
|
|
|
@@ -379,8 +477,8 @@ pub proc auth_tx_ecdsa_multisig.1(salt: BeWord)
|
|
|
379
477
|
|
|
380
478
|
# ------ Verifying approver signatures ------
|
|
381
479
|
|
|
382
|
-
push.THRESHOLD_CONFIG_SLOT
|
|
383
|
-
# => [
|
|
480
|
+
push.THRESHOLD_CONFIG_SLOT[0..2]
|
|
481
|
+
# => [config_slot_prefix, config_slot_suffix, TX_SUMMARY_COMMITMENT]
|
|
384
482
|
|
|
385
483
|
exec.active_account::get_initial_item
|
|
386
484
|
# => [0, 0, num_of_approvers, default_threshold, TX_SUMMARY_COMMITMENT]
|
|
@@ -391,10 +489,10 @@ pub proc auth_tx_ecdsa_multisig.1(salt: BeWord)
|
|
|
391
489
|
swap movdn.5
|
|
392
490
|
# => [num_of_approvers, TX_SUMMARY_COMMITMENT, default_threshold]
|
|
393
491
|
|
|
394
|
-
push.PUBLIC_KEYS_MAP_SLOT
|
|
395
|
-
# => [
|
|
492
|
+
push.PUBLIC_KEYS_MAP_SLOT[0..2]
|
|
493
|
+
# => [pub_key_slot_prefix, pub_key_slot_suffix, num_of_approvers, TX_SUMMARY_COMMITMENT, default_threshold]
|
|
396
494
|
|
|
397
|
-
exec.::miden::auth::ecdsa_k256_keccak::verify_signatures
|
|
495
|
+
exec.::miden::standards::auth::ecdsa_k256_keccak::verify_signatures
|
|
398
496
|
# => [num_verified_signatures, TX_SUMMARY_COMMITMENT, default_threshold]
|
|
399
497
|
|
|
400
498
|
# ------ Checking threshold is >= num_verified_signatures ------
|
|
@@ -414,11 +512,5 @@ pub proc auth_tx_ecdsa_multisig.1(salt: BeWord)
|
|
|
414
512
|
push.0 assert.err="insufficient number of signatures"
|
|
415
513
|
end
|
|
416
514
|
|
|
417
|
-
# ------ Verifying PSM Signature ------
|
|
418
|
-
# => [TX_SUMMARY_COMMITMENT]
|
|
419
|
-
call.psm_ecdsa::verify_psm_signature
|
|
420
|
-
|
|
421
|
-
# ------ Writing executed transaction MSG to map ------
|
|
422
515
|
# => [TX_SUMMARY_COMMITMENT]
|
|
423
|
-
exec.assert_new_tx
|
|
424
516
|
end
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openzeppelin/miden-multisig-client",
|
|
3
|
-
"version": "0.13.
|
|
4
|
-
"description": "TypeScript SDK for Miden multisig accounts with
|
|
3
|
+
"version": "0.13.2",
|
|
4
|
+
"description": "TypeScript SDK for Miden multisig accounts with GUARDIAN integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -18,17 +18,19 @@
|
|
|
18
18
|
"masm"
|
|
19
19
|
],
|
|
20
20
|
"scripts": {
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
21
|
+
"generate:masm": "node ./scripts/generate-masm.mjs",
|
|
22
|
+
"build": "npm run generate:masm && tsc",
|
|
23
|
+
"dev": "npm run generate:masm && tsc --watch",
|
|
24
|
+
"typecheck": "npm run generate:masm && tsc --noEmit",
|
|
24
25
|
"clean": "rm -rf dist",
|
|
25
|
-
"test": "vitest run",
|
|
26
|
-
"test:watch": "vitest"
|
|
26
|
+
"test": "npm run generate:masm && vitest run",
|
|
27
|
+
"test:watch": "npm run generate:masm && vitest"
|
|
27
28
|
},
|
|
28
29
|
"dependencies": {
|
|
29
|
-
"@
|
|
30
|
+
"@noble/curves": "^1.9.7",
|
|
31
|
+
"@miden-sdk/miden-sdk": "0.13.0",
|
|
30
32
|
"@noble/hashes": "^2.0.1",
|
|
31
|
-
"@openzeppelin/
|
|
33
|
+
"@openzeppelin/guardian-client": "^0.13.2"
|
|
32
34
|
},
|
|
33
35
|
"devDependencies": {
|
|
34
36
|
"typescript": "^5.7.2",
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { createMultisigAccount } from './builder.js';
|
|
3
|
+
import {
|
|
4
|
+
MULTISIG_ECDSA_MASM,
|
|
5
|
+
MULTISIG_MASM,
|
|
6
|
+
GUARDIAN_ECDSA_MASM,
|
|
7
|
+
GUARDIAN_MASM,
|
|
8
|
+
} from './masm/auth.js';
|
|
9
|
+
import {
|
|
10
|
+
MULTISIG_GUARDIAN_ACCOUNT_COMPONENT_MASM,
|
|
11
|
+
MULTISIG_GUARDIAN_ECDSA_ACCOUNT_COMPONENT_MASM,
|
|
12
|
+
} from './masm/account-components/auth.js';
|
|
13
|
+
|
|
14
|
+
const {
|
|
15
|
+
buildMultisigStorageSlots,
|
|
16
|
+
buildGuardianStorageSlots,
|
|
17
|
+
withSupportsAllTypes,
|
|
18
|
+
compileComponent,
|
|
19
|
+
MockAccountBuilder,
|
|
20
|
+
} = vi.hoisted(() => {
|
|
21
|
+
const buildMultisigStorageSlots = vi.fn(() => ['multisig-slots']);
|
|
22
|
+
const buildGuardianStorageSlots = vi.fn(() => ['guardian-slots']);
|
|
23
|
+
const withSupportsAllTypes = vi.fn((component) => component);
|
|
24
|
+
const compileComponent = vi.fn((code, slots) => ({
|
|
25
|
+
code,
|
|
26
|
+
slots,
|
|
27
|
+
withSupportsAllTypes: () => withSupportsAllTypes({ code, slots }),
|
|
28
|
+
}));
|
|
29
|
+
|
|
30
|
+
class MockAccountBuilder {
|
|
31
|
+
accountType() {
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
storageMode() {
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
withAuthComponent() {
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
withComponent() {
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
withBasicWalletComponent() {
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
build() {
|
|
52
|
+
return {
|
|
53
|
+
account: { id: () => ({ toString: () => '0x' + 'a'.repeat(30) }) },
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
buildMultisigStorageSlots,
|
|
60
|
+
buildGuardianStorageSlots,
|
|
61
|
+
withSupportsAllTypes,
|
|
62
|
+
compileComponent,
|
|
63
|
+
MockAccountBuilder,
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
vi.mock('./storage.js', () => ({
|
|
68
|
+
buildMultisigStorageSlots,
|
|
69
|
+
buildGuardianStorageSlots,
|
|
70
|
+
}));
|
|
71
|
+
|
|
72
|
+
vi.mock('@miden-sdk/miden-sdk', () => ({
|
|
73
|
+
AccountBuilder: MockAccountBuilder,
|
|
74
|
+
AccountComponent: {
|
|
75
|
+
compile: compileComponent,
|
|
76
|
+
},
|
|
77
|
+
AccountType: {
|
|
78
|
+
RegularAccountUpdatableCode: 'regular',
|
|
79
|
+
},
|
|
80
|
+
AccountStorageMode: {
|
|
81
|
+
public: () => 'public',
|
|
82
|
+
private: () => 'private',
|
|
83
|
+
},
|
|
84
|
+
}));
|
|
85
|
+
|
|
86
|
+
describe('createMultisigAccount', () => {
|
|
87
|
+
beforeEach(() => {
|
|
88
|
+
vi.stubGlobal('crypto', {
|
|
89
|
+
getRandomValues(buffer: Uint8Array) {
|
|
90
|
+
return buffer;
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
buildMultisigStorageSlots.mockClear();
|
|
94
|
+
buildGuardianStorageSlots.mockClear();
|
|
95
|
+
withSupportsAllTypes.mockClear();
|
|
96
|
+
compileComponent.mockClear();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('uses Falcon MASM by default', async () => {
|
|
100
|
+
const authBuilder = {
|
|
101
|
+
buildLibrary: vi.fn((libraryPath, source) => ({ libraryPath, source })),
|
|
102
|
+
linkStaticLibrary: vi.fn(),
|
|
103
|
+
compileAccountComponentCode: vi.fn((source) => `auth:${source.slice(0, 16)}`),
|
|
104
|
+
};
|
|
105
|
+
const webClient = {
|
|
106
|
+
createCodeBuilder: vi.fn().mockReturnValue(authBuilder),
|
|
107
|
+
newAccount: vi.fn(),
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
await createMultisigAccount(webClient as never, {
|
|
111
|
+
threshold: 1,
|
|
112
|
+
signerCommitments: ['0x' + '1'.repeat(64)],
|
|
113
|
+
guardianCommitment: '0x' + '2'.repeat(64),
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
expect(authBuilder.buildLibrary).toHaveBeenNthCalledWith(
|
|
117
|
+
1,
|
|
118
|
+
'openzeppelin::auth::guardian',
|
|
119
|
+
GUARDIAN_MASM,
|
|
120
|
+
);
|
|
121
|
+
expect(authBuilder.buildLibrary).toHaveBeenNthCalledWith(
|
|
122
|
+
2,
|
|
123
|
+
'openzeppelin::auth::multisig',
|
|
124
|
+
MULTISIG_MASM,
|
|
125
|
+
);
|
|
126
|
+
expect(authBuilder.compileAccountComponentCode).toHaveBeenCalledWith(
|
|
127
|
+
MULTISIG_GUARDIAN_ACCOUNT_COMPONENT_MASM,
|
|
128
|
+
);
|
|
129
|
+
expect(webClient.newAccount).toHaveBeenCalledTimes(1);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('uses ECDSA MASM when requested', async () => {
|
|
133
|
+
const authBuilder = {
|
|
134
|
+
buildLibrary: vi.fn((libraryPath, source) => ({ libraryPath, source })),
|
|
135
|
+
linkStaticLibrary: vi.fn(),
|
|
136
|
+
compileAccountComponentCode: vi.fn((source) => `auth:${source.slice(0, 16)}`),
|
|
137
|
+
};
|
|
138
|
+
const webClient = {
|
|
139
|
+
createCodeBuilder: vi.fn().mockReturnValue(authBuilder),
|
|
140
|
+
newAccount: vi.fn(),
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
await createMultisigAccount(webClient as never, {
|
|
144
|
+
threshold: 1,
|
|
145
|
+
signerCommitments: ['0x' + '1'.repeat(64)],
|
|
146
|
+
guardianCommitment: '0x' + '2'.repeat(64),
|
|
147
|
+
signatureScheme: 'ecdsa',
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
expect(authBuilder.buildLibrary).toHaveBeenNthCalledWith(
|
|
151
|
+
1,
|
|
152
|
+
'openzeppelin::auth::guardian_ecdsa',
|
|
153
|
+
GUARDIAN_ECDSA_MASM,
|
|
154
|
+
);
|
|
155
|
+
expect(authBuilder.buildLibrary).toHaveBeenNthCalledWith(
|
|
156
|
+
2,
|
|
157
|
+
'openzeppelin::auth::multisig_ecdsa',
|
|
158
|
+
MULTISIG_ECDSA_MASM,
|
|
159
|
+
);
|
|
160
|
+
expect(authBuilder.compileAccountComponentCode).toHaveBeenCalledWith(
|
|
161
|
+
MULTISIG_GUARDIAN_ECDSA_ACCOUNT_COMPONENT_MASM,
|
|
162
|
+
);
|
|
163
|
+
expect(webClient.newAccount).toHaveBeenCalledTimes(1);
|
|
164
|
+
});
|
|
165
|
+
});
|