@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.
Files changed (275) hide show
  1. package/README.md +98 -119
  2. package/dist/account/builder.d.ts +18 -0
  3. package/dist/account/builder.d.ts.map +1 -1
  4. package/dist/account/builder.js +59 -29
  5. package/dist/account/builder.js.map +1 -1
  6. package/dist/account/builder.test.js +108 -32
  7. package/dist/account/builder.test.js.map +1 -1
  8. package/dist/account/index.d.ts +1 -1
  9. package/dist/account/index.d.ts.map +1 -1
  10. package/dist/account/index.js +1 -1
  11. package/dist/account/index.js.map +1 -1
  12. package/dist/account/masm/account-components/auth.d.ts +5 -0
  13. package/dist/account/masm/account-components/auth.d.ts.map +1 -0
  14. package/dist/account/masm/account-components/auth.js +67 -0
  15. package/dist/account/masm/account-components/auth.js.map +1 -0
  16. package/dist/account/masm/auth.d.ts +5 -0
  17. package/dist/account/masm/auth.d.ts.map +1 -0
  18. package/dist/account/masm/auth.js +1395 -0
  19. package/dist/account/masm/auth.js.map +1 -0
  20. package/dist/account/masm/index.d.ts +3 -0
  21. package/dist/account/masm/index.d.ts.map +1 -0
  22. package/dist/account/masm/index.js +5 -0
  23. package/dist/account/masm/index.js.map +1 -0
  24. package/dist/account/masm.d.ts +1 -4
  25. package/dist/account/masm.d.ts.map +1 -1
  26. package/dist/account/masm.js +3 -1034
  27. package/dist/account/masm.js.map +1 -1
  28. package/dist/account/storage.d.ts +2 -2
  29. package/dist/account/storage.d.ts.map +1 -1
  30. package/dist/account/storage.js +18 -16
  31. package/dist/account/storage.js.map +1 -1
  32. package/dist/client.d.ts +67 -9
  33. package/dist/client.d.ts.map +1 -1
  34. package/dist/client.js +73 -22
  35. package/dist/client.js.map +1 -1
  36. package/dist/client.test.js +31 -32
  37. package/dist/client.test.js.map +1 -1
  38. package/dist/index.d.ts +54 -12
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +53 -9
  41. package/dist/index.js.map +1 -1
  42. package/dist/inspector.d.ts +32 -6
  43. package/dist/inspector.d.ts.map +1 -1
  44. package/dist/inspector.js +58 -23
  45. package/dist/inspector.js.map +1 -1
  46. package/dist/inspector.test.js +18 -18
  47. package/dist/inspector.test.js.map +1 -1
  48. package/dist/multisig/proposal/execution.d.ts +4 -4
  49. package/dist/multisig/proposal/execution.d.ts.map +1 -1
  50. package/dist/multisig/proposal/execution.js +42 -31
  51. package/dist/multisig/proposal/execution.js.map +1 -1
  52. package/dist/multisig/proposal/parser.d.ts +3 -3
  53. package/dist/multisig/proposal/parser.d.ts.map +1 -1
  54. package/dist/multisig/proposal/parser.js +23 -23
  55. package/dist/multisig/proposal/parser.js.map +1 -1
  56. package/dist/multisig/signing.d.ts +3 -3
  57. package/dist/multisig/signing.d.ts.map +1 -1
  58. package/dist/multisig/signing.js +3 -3
  59. package/dist/multisig/signing.js.map +1 -1
  60. package/dist/multisig.d.ts +188 -48
  61. package/dist/multisig.d.ts.map +1 -1
  62. package/dist/multisig.js +650 -308
  63. package/dist/multisig.js.map +1 -1
  64. package/dist/multisig.test.js +1680 -241
  65. package/dist/multisig.test.js.map +1 -1
  66. package/dist/procedures.d.ts +46 -24
  67. package/dist/procedures.d.ts.map +1 -1
  68. package/dist/procedures.js +46 -21
  69. package/dist/procedures.js.map +1 -1
  70. package/dist/proposal/factory.d.ts +18 -0
  71. package/dist/proposal/factory.d.ts.map +1 -0
  72. package/dist/proposal/factory.js +99 -0
  73. package/dist/proposal/factory.js.map +1 -0
  74. package/dist/proposal/metadata.d.ts +5 -12
  75. package/dist/proposal/metadata.d.ts.map +1 -1
  76. package/dist/proposal/metadata.js +118 -174
  77. package/dist/proposal/metadata.js.map +1 -1
  78. package/dist/proposal/signatures.d.ts +10 -0
  79. package/dist/proposal/signatures.d.ts.map +1 -0
  80. package/dist/proposal/signatures.js +54 -0
  81. package/dist/proposal/signatures.js.map +1 -0
  82. package/dist/signer.d.ts +2 -0
  83. package/dist/signer.d.ts.map +1 -1
  84. package/dist/signer.js +2 -0
  85. package/dist/signer.js.map +1 -1
  86. package/dist/signers/ecdsa.d.ts +3 -0
  87. package/dist/signers/ecdsa.d.ts.map +1 -1
  88. package/dist/signers/ecdsa.js +8 -4
  89. package/dist/signers/ecdsa.js.map +1 -1
  90. package/dist/signers/ecdsa.test.d.ts +2 -0
  91. package/dist/signers/ecdsa.test.d.ts.map +1 -0
  92. package/dist/signers/ecdsa.test.js +65 -0
  93. package/dist/signers/ecdsa.test.js.map +1 -0
  94. package/dist/signers/falcon.d.ts +3 -0
  95. package/dist/signers/falcon.d.ts.map +1 -1
  96. package/dist/signers/falcon.js +8 -4
  97. package/dist/signers/falcon.js.map +1 -1
  98. package/dist/signers/falcon.test.js +12 -0
  99. package/dist/signers/falcon.test.js.map +1 -1
  100. package/dist/signers/miden-wallet.d.ts +3 -1
  101. package/dist/signers/miden-wallet.d.ts.map +1 -1
  102. package/dist/signers/miden-wallet.js +11 -2
  103. package/dist/signers/miden-wallet.js.map +1 -1
  104. package/dist/signers/miden-wallet.test.js +26 -0
  105. package/dist/signers/miden-wallet.test.js.map +1 -1
  106. package/dist/signers/para.d.ts +3 -3
  107. package/dist/signers/para.d.ts.map +1 -1
  108. package/dist/signers/para.js +15 -6
  109. package/dist/signers/para.js.map +1 -1
  110. package/dist/signers/para.test.js +39 -0
  111. package/dist/signers/para.test.js.map +1 -1
  112. package/dist/transaction/consumeNotes.d.ts.map +1 -1
  113. package/dist/transaction/consumeNotes.js +1 -0
  114. package/dist/transaction/consumeNotes.js.map +1 -1
  115. package/dist/transaction/index.d.ts +2 -1
  116. package/dist/transaction/index.d.ts.map +1 -1
  117. package/dist/transaction/index.js +2 -1
  118. package/dist/transaction/index.js.map +1 -1
  119. package/dist/transaction/options.d.ts +1 -1
  120. package/dist/transaction/options.d.ts.map +1 -1
  121. package/dist/transaction/p2id.d.ts +1 -0
  122. package/dist/transaction/p2id.d.ts.map +1 -1
  123. package/dist/transaction/p2id.js +9 -3
  124. package/dist/transaction/p2id.js.map +1 -1
  125. package/dist/transaction/updateGuardian.d.ts +7 -0
  126. package/dist/transaction/updateGuardian.d.ts.map +1 -0
  127. package/dist/transaction/{updatePsm.js → updateGuardian.js} +15 -29
  128. package/dist/transaction/updateGuardian.js.map +1 -0
  129. package/dist/transaction/updateProcedureThreshold.d.ts +9 -0
  130. package/dist/transaction/updateProcedureThreshold.d.ts.map +1 -0
  131. package/dist/transaction/updateProcedureThreshold.js +55 -0
  132. package/dist/transaction/updateProcedureThreshold.js.map +1 -0
  133. package/dist/transaction/updateSigners.d.ts.map +1 -1
  134. package/dist/transaction/updateSigners.js +5 -23
  135. package/dist/transaction/updateSigners.js.map +1 -1
  136. package/dist/transaction.d.ts +2 -1
  137. package/dist/transaction.d.ts.map +1 -1
  138. package/dist/transaction.js +2 -1
  139. package/dist/transaction.js.map +1 -1
  140. package/dist/types/proposal.d.ts +32 -15
  141. package/dist/types/proposal.d.ts.map +1 -1
  142. package/dist/types.d.ts +24 -7
  143. package/dist/types.d.ts.map +1 -1
  144. package/dist/utils/digest.d.ts +5 -0
  145. package/dist/utils/digest.d.ts.map +1 -1
  146. package/dist/utils/digest.js +34 -1
  147. package/dist/utils/digest.js.map +1 -1
  148. package/dist/utils/digest.test.d.ts +2 -0
  149. package/dist/utils/digest.test.d.ts.map +1 -0
  150. package/dist/utils/digest.test.js +48 -0
  151. package/dist/utils/digest.test.js.map +1 -0
  152. package/dist/utils/signature.d.ts +3 -1
  153. package/dist/utils/signature.d.ts.map +1 -1
  154. package/dist/utils/signature.js +31 -6
  155. package/dist/utils/signature.js.map +1 -1
  156. package/dist/utils/word.test.js +1 -52
  157. package/dist/utils/word.test.js.map +1 -1
  158. package/masm/account_components/auth/multisig.masm +13 -0
  159. package/masm/account_components/auth/multisig_ecdsa.masm +13 -0
  160. package/masm/account_components/auth/multisig_guardian.masm +17 -0
  161. package/masm/account_components/auth/multisig_guardian_ecdsa.masm +17 -0
  162. package/masm/auth/guardian.masm +177 -0
  163. package/masm/auth/guardian_ecdsa.masm +178 -0
  164. package/masm/{multisig.masm → auth/multisig.masm} +149 -55
  165. package/masm/{multisig_ecdsa.masm → auth/multisig_ecdsa.masm} +148 -56
  166. package/package.json +11 -9
  167. package/src/account/builder.test.ts +165 -0
  168. package/src/account/builder.ts +71 -34
  169. package/src/account/index.ts +1 -1
  170. package/src/account/masm/account-components/auth.ts +70 -0
  171. package/src/account/masm/auth.ts +1398 -0
  172. package/src/account/masm/index.ts +5 -0
  173. package/src/account/masm.ts +3 -1040
  174. package/src/account/storage.ts +18 -16
  175. package/src/client.test.ts +31 -35
  176. package/src/client.ts +98 -26
  177. package/src/index.ts +84 -22
  178. package/src/inspector.test.ts +17 -17
  179. package/src/inspector.ts +63 -29
  180. package/src/multisig/proposal/execution.ts +66 -49
  181. package/src/multisig/proposal/parser.ts +26 -26
  182. package/src/multisig/signing.ts +4 -4
  183. package/src/multisig.test.ts +2097 -248
  184. package/src/multisig.ts +882 -388
  185. package/src/procedures.ts +50 -26
  186. package/src/proposal/factory.ts +171 -0
  187. package/src/proposal/metadata.ts +165 -0
  188. package/src/proposal/signatures.ts +68 -0
  189. package/src/signer.ts +2 -0
  190. package/src/signers/ecdsa.test.ts +80 -0
  191. package/src/signers/ecdsa.ts +15 -4
  192. package/src/signers/falcon.test.ts +19 -0
  193. package/src/signers/falcon.ts +16 -5
  194. package/src/signers/miden-wallet.test.ts +47 -0
  195. package/src/signers/miden-wallet.ts +18 -1
  196. package/src/signers/para.test.ts +57 -0
  197. package/src/signers/para.ts +26 -7
  198. package/src/transaction/consumeNotes.ts +1 -0
  199. package/src/transaction/index.ts +2 -2
  200. package/src/transaction/options.ts +1 -2
  201. package/src/transaction/p2id.test.ts +190 -0
  202. package/src/transaction/p2id.ts +11 -5
  203. package/src/transaction/rpoRandomCoin.test.ts +64 -0
  204. package/src/transaction/rpoRandomCoin.ts +24 -0
  205. package/src/transaction/{updatePsm.ts → updateGuardian.ts} +19 -32
  206. package/src/transaction/updateProcedureThreshold.ts +97 -0
  207. package/src/transaction/updateSigners.ts +12 -27
  208. package/src/transaction.ts +5 -3
  209. package/src/types/proposal.ts +43 -11
  210. package/src/types.ts +29 -11
  211. package/src/utils/digest.test.ts +55 -0
  212. package/src/utils/digest.ts +51 -1
  213. package/src/utils/signature.ts +47 -9
  214. package/src/utils/word.test.ts +1 -55
  215. package/dist/account.d.ts +0 -104
  216. package/dist/account.d.ts.map +0 -1
  217. package/dist/account.js +0 -136
  218. package/dist/account.js.map +0 -1
  219. package/dist/builder.d.ts +0 -54
  220. package/dist/builder.d.ts.map +0 -1
  221. package/dist/builder.js +0 -78
  222. package/dist/builder.js.map +0 -1
  223. package/dist/http.d.ts +0 -64
  224. package/dist/http.d.ts.map +0 -1
  225. package/dist/http.js +0 -162
  226. package/dist/http.js.map +0 -1
  227. package/dist/keystore.d.ts +0 -65
  228. package/dist/keystore.d.ts.map +0 -1
  229. package/dist/keystore.js +0 -121
  230. package/dist/keystore.js.map +0 -1
  231. package/dist/miden.d.ts +0 -9
  232. package/dist/miden.d.ts.map +0 -1
  233. package/dist/miden.js +0 -26
  234. package/dist/miden.js.map +0 -1
  235. package/dist/multisig/metadata.d.ts +0 -18
  236. package/dist/multisig/metadata.d.ts.map +0 -1
  237. package/dist/multisig/metadata.js +0 -100
  238. package/dist/multisig/metadata.js.map +0 -1
  239. package/dist/multisig/metadata.test.d.ts +0 -2
  240. package/dist/multisig/metadata.test.d.ts.map +0 -1
  241. package/dist/multisig/metadata.test.js +0 -323
  242. package/dist/multisig/metadata.test.js.map +0 -1
  243. package/dist/proposal/exported.d.ts +0 -12
  244. package/dist/proposal/exported.d.ts.map +0 -1
  245. package/dist/proposal/exported.js +0 -88
  246. package/dist/proposal/exported.js.map +0 -1
  247. package/dist/signer.test.d.ts +0 -2
  248. package/dist/signer.test.d.ts.map +0 -1
  249. package/dist/signer.test.js +0 -123
  250. package/dist/signer.test.js.map +0 -1
  251. package/dist/transaction/p2id.interop.test.d.ts +0 -2
  252. package/dist/transaction/p2id.interop.test.d.ts.map +0 -1
  253. package/dist/transaction/p2id.interop.test.js +0 -36
  254. package/dist/transaction/p2id.interop.test.js.map +0 -1
  255. package/dist/transaction/updatePsm.d.ts +0 -7
  256. package/dist/transaction/updatePsm.d.ts.map +0 -1
  257. package/dist/transaction/updatePsm.js.map +0 -1
  258. package/dist/transport/http.d.ts +0 -64
  259. package/dist/transport/http.d.ts.map +0 -1
  260. package/dist/transport/http.js +0 -162
  261. package/dist/transport/http.js.map +0 -1
  262. package/dist/transport/index.d.ts +0 -5
  263. package/dist/transport/index.d.ts.map +0 -1
  264. package/dist/transport/index.js +0 -5
  265. package/dist/transport/index.js.map +0 -1
  266. package/dist/utils/state-validation.d.ts +0 -5
  267. package/dist/utils/state-validation.d.ts.map +0 -1
  268. package/dist/utils/state-validation.js +0 -30
  269. package/dist/utils/state-validation.js.map +0 -1
  270. package/dist/utils/validation.d.ts +0 -6
  271. package/dist/utils/validation.d.ts.map +0 -1
  272. package/dist/utils/validation.js +0 -52
  273. package/dist/utils/validation.js.map +0 -1
  274. package/masm/psm.masm +0 -178
  275. package/masm/psm_ecdsa.masm +0 -179
@@ -1,15 +1,10 @@
1
- # Multi-Signature ECDSA secp256k1 Authentication Component
1
+ # Multi-Signature ECDSA secp256k1 Authentication Core Library
2
2
  #
3
- # This component provides multi-signature authentication for accounts using
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 = event("miden::auth::unauthorized")
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 = 0
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 = 1
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 = 2
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 = 3
43
+ const PROC_THRESHOLD_ROOTS_SLOT=word("openzeppelin::multisig::procedure_thresholds")
49
44
 
50
45
  # Executed Transaction Flag Constant
51
- const IS_EXECUTED_FLAG = [1, 0, 0, 0]
46
+ const IS_EXECUTED_FLAG=[1, 0, 0, 0]
52
47
 
53
48
  # ERRORS
54
- const ERR_TX_ALREADY_EXECUTED = "failed to approve multisig transaction as it was 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 ERR_MALFORMED_MULTISIG_CONFIG = "number of approvers must be equal to or greater than threshold"
57
+ const ERR_NUM_APPROVERS_OR_PROC_THRESHOLD_NOT_U32="number of approvers and procedure threshold must be u32"
57
58
 
58
- const ERR_ZERO_IN_MULTISIG_CONFIG = "number of approvers or threshold must not be zero"
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
- # => [index, MSG, IS_EXECUTED_FLAG]
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
- # => [OLD_MAP_ROOT, [0, 0, 0, is_executed]]
83
+ # => [[0, 0, 0, is_executed]]
83
84
 
84
- dropw drop drop drop
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
- # => [pub_key_slot_idx, [0, 0, 0, i-1], EMPTY_WORD, i-1, new_num_of_approvers]
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
- # => [OLD_MAP_ROOT, OLD_MAP_VALUE, i-1, new_num_of_approvers]
128
+ # => [OLD_MAP_VALUE, i-1, new_num_of_approvers]
128
129
 
129
- dropw 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
- pub proc update_signers_and_threshold.2(multisig_config_hash: BeWord)
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
- push.THRESHOLD_CONFIG_SLOT
187
- # => [slot, MULTISIG_CONFIG, pad(12)]
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
- # => [pub_key_slot_idx, [0, 0, 0, i-1], PUB_KEY, i-1, pad(12)]
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
- # => [OLD_MAP_ROOT, OLD_MAP_VALUE, i-1, pad(12)]
304
+ # => [OLD_VALUE, i-1, pad(12)]
218
305
 
219
- dropw 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
- proc compute_transaction_threshold.1(default_threshold: u32) -> u32
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
- # => [PROC_THRESHOLD_ROOTS_SLOT, PROC_ROOT, num_procedures-1, transaction_threshold]
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. Implementing replay protection by tracking executed transactions
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
- #! - the same transaction has already been executed (replay protection).
360
- #! - PSM signature verification fails (if PSM is enabled).
457
+ #! - insufficient number of valid signatures (below threshold).
361
458
  #!
362
- #! Invocation: call
363
- pub proc auth_tx_ecdsa_multisig.1(salt: BeWord)
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
- # => [index, TX_SUMMARY_COMMITMENT]
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
- # => [pub_key_slot_idx, num_of_approvers, TX_SUMMARY_COMMITMENT, default_threshold]
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.1",
4
- "description": "TypeScript SDK for Miden multisig accounts with PSM integration",
3
+ "version": "0.13.3",
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
- "build": "tsc",
22
- "dev": "tsc --watch",
23
- "typecheck": "tsc --noEmit",
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
- "@miden-sdk/miden-sdk": "^0.13.0",
30
+ "@noble/curves": "^1.9.7",
31
+ "@miden-sdk/miden-sdk": "0.13.0",
30
32
  "@noble/hashes": "^2.0.1",
31
- "@openzeppelin/psm-client": "^0.13.1"
33
+ "@openzeppelin/guardian-client": "^0.13.3"
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
+ });