-
Notifications
You must be signed in to change notification settings - Fork 144
feat(standards): add AuthMultisigSmart
#2973
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
onurinanc
wants to merge
82
commits into
next
Choose a base branch
from
onur-auth-multisig-smart
base: next
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 61 commits
Commits
Show all changes
82 commits
Select commit
Hold shift + click to select a range
0bf1295
initial integration
onurinanc ae87735
update signer management to the current version
onurinanc a9ccc01
refactor common procedures
onurinanc 3553e86
refactor compute tx threshold
onurinanc 5f35fde
before the timelock guard
onurinanc dd915b5
add new tests
onurinanc d1890f7
rstest
onurinanc 7efc3bb
add tx expiration delta and timestamp and remove epoch
onurinanc 173cb2a
add modules
onurinanc fac9d7c
rename timelock controller
onurinanc 94deee4
rename guard -> controller
onurinanc 66a91a0
add get_price test stub
onurinanc 87f52cb
add tier validations and <= assertions
onurinanc bff4a6a
fix tier thresholds logic
onurinanc 8909f66
add procedure policies
onurinanc 95edc8e
refactor procedure_roots -> procedure_policies
onurinanc 1d7e0e8
move procedure_policies to multisig
onurinanc 4223de9
cleanup tests
onurinanc 145ad07
refactor AuthMultisigConfig
onurinanc 2c727d3
remove redundant tests
onurinanc f4d297b
cleanup
onurinanc c406cb6
integrate oracle
onurinanc 9758f58
refactor oracle
onurinanc a1afd25
merge
onurinanc 0e6d2e0
procedure_policies -> procedure_thresholds
onurinanc e95c470
Merge remote-tracking branch 'upstream/next' into onur-auth-multisig-…
onurinanc f933e48
refactor multisig smart
onurinanc 8db09b8
merge next
onurinanc a56f487
add next version of procedure policies
onurinanc 477ffe2
multisig next
onurinanc 413908b
fix proc
onurinanc 6a0c37e
fix
onurinanc 0564472
refactor multisig
onurinanc e242ed8
fix
onurinanc 18ec223
fix comments
onurinanc 76808aa
refactor
onurinanc a0170ba
cleanup multisig.masm
onurinanc 6639732
remove redundant tests
onurinanc 2087bec
refactor mock chain
onurinanc 301e14f
fmt
onurinanc ecc7c0e
change folder location
onurinanc a4c68d8
fix timelock_controller
onurinanc 7cd88e7
add masm documentation
onurinanc 2589218
simplify masm
onurinanc 636c32a
remove redundant helper
onurinanc e62526c
add finalize timelock helpers
onurinanc 08a253e
fix
onurinanc 8d82028
add timelock controller
onurinanc 004d34a
update spending limits
onurinanc 77cb6f8
resolve guardian conflicts
onurinanc 5dc1902
fmt
onurinanc ed2b1ca
remove locals
onurinanc 6e939e5
fix spending limit window
onurinanc 8a3a070
add masm conventions
onurinanc 589cb29
add untracked policy for get price
onurinanc 8ffeb0a
add documentation
onurinanc 9dad95b
initial merge basic and network accounts
onurinanc d817aa7
clippy
onurinanc 7d84b08
changelog
onurinanc df4dc5a
merge next
onurinanc b09c85f
refactor storage slots
onurinanc 449fcd6
Merge branch 'next' into merge-basic-network-faucets
onurinanc 7176fe4
apply review fixes
onurinanc adf50b1
Merge branch 'next' into merge-basic-network-faucets
onurinanc 8f3f2a2
apply review fixes
onurinanc 8b880de
Merge remote-tracking branch 'origin/merge-basic-network-faucets' int…
onurinanc b175c0c
merge next
onurinanc bf4a12d
fmt
onurinanc c270965
merge next
onurinanc 7b0e3fd
fix documentation
onurinanc e453e95
Merge pull request #2 from onurinanc/pr-2890
onurinanc 3692fc3
Merge branch '0xMiden:next' into next
onurinanc 8271ed4
Merge branch '0xMiden:next' into next
onurinanc 43d7ca3
merge
onurinanc 1dc15d6
Merge branch '0xMiden:next' into next
onurinanc 904ee12
migration
onurinanc 3834ade
add compositions
onurinanc be351e1
merge next
onurinanc aa24fed
clippy
onurinanc b21e888
Merge remote-tracking branch 'origin/next' into onur-auth-multisig-smart
onurinanc de4e418
merge next
onurinanc 472bf97
rename timelock controller -> delayed execution
onurinanc File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,8 @@ use miden::standards::auth::multisig | |
| use miden::standards::auth::multisig::APPROVER_PUBLIC_KEYS_SLOT | ||
| use miden::standards::auth::multisig::APPROVER_SCHEME_ID_SLOT | ||
| use miden::standards::auth::multisig::THRESHOLD_CONFIG_SLOT | ||
| use miden::standards::auth::multisig_smart::spending_limits | ||
| use miden::standards::auth::multisig_smart::timelock_controller | ||
| use miden::standards::auth::signature | ||
| use miden::standards::auth::tx_policy | ||
|
|
||
|
|
@@ -59,6 +61,8 @@ const ERR_INVALID_NOTE_RESTRICTIONS = "procedure policy note restrictions must b | |
|
|
||
| const ERR_INSUFFICIENT_SIGNATURES = "insufficient number of signatures" | ||
|
|
||
| const ERR_EXECUTE_PATH_MISMATCH = "execute path must match delay requirement" | ||
|
|
||
| # LOCAL ADDRESSES (set_procedure_policy) | ||
| # ================================================================================================= | ||
|
|
||
|
|
@@ -408,40 +412,35 @@ end | |
| #! Enforces the procedure-policy for the current transaction: | ||
| #! - asserts each called procedure supports the active execution mode, | ||
| #! - asserts the union of note restrictions against the transaction's input/output notes, | ||
| #! - returns the effective threshold required by the called procedure policies. | ||
| #! - returns the effective threshold required by the called procedure policies and | ||
| #! whether any policy required the delayed-execution mode. | ||
| #! | ||
| #! Always uses IMMEDIATE_EXECUTION_MODE; procedures whose policies require the delayed mode | ||
| #! panic via [`compute_called_proc_policy`] because this component has no timelock. | ||
| #! The active execution mode is read from [`timelock_controller::is_execute_path`]: when | ||
| #! the timelock controller's `PENDING_EXECUTE` slot is set this transaction is on the | ||
| #! delayed-execute path (mode = 1); otherwise it is on the immediate path (mode = 0). | ||
| #! | ||
| #! Inputs: [default_threshold] | ||
| #! Outputs: [policy_threshold] | ||
| #! Outputs: [policy_threshold, policy_requires_delay] | ||
| #! | ||
| #! Where: | ||
| #! - default_threshold is forwarded to [`compute_called_proc_policy`] as the per-procedure | ||
| #! contribution for any called procedure without an explicit policy. | ||
| #! - policy_requires_delay is 1 when any called procedure's policy explicitly requires the | ||
| #! delayed execution mode (used downstream to enforce [`ERR_EXECUTE_PATH_MISMATCH`]). | ||
| #! | ||
| #! Invocation: exec | ||
| #! | ||
| #! NOTE: This procedure is a temporary form. Once the TimelockedAccount feature lands, the | ||
| #! hardcoded IMMEDIATE_EXECUTION_MODE push will be replaced with a call to | ||
| #! `timelock_controller::execution_mode`, and the procedure will also expose | ||
| #! `policy_requires_delay` for downstream enforcement. | ||
| proc enforce_procedure_policy(default_threshold: u32) | ||
| push.IMMEDIATE_EXECUTION_MODE | ||
| exec.timelock_controller::is_execute_path | ||
| # => [execution_mode, default_threshold] | ||
|
|
||
| exec.compute_called_proc_policy | ||
| # => [policy_threshold, policy_requires_delay, note_restrictions] | ||
|
|
||
| # policy_requires_delay is always 0 on IMMEDIATE_EXECUTION_MODE; drop it. | ||
| swap drop | ||
| # => [policy_threshold, note_restrictions] | ||
|
|
||
| swap | ||
| # => [note_restrictions, policy_threshold] | ||
| movup.2 | ||
| # => [note_restrictions, policy_threshold, policy_requires_delay] | ||
|
|
||
| exec.enforce_note_restrictions | ||
| # => [policy_threshold] | ||
| # => [policy_threshold, policy_requires_delay] | ||
| end | ||
|
|
||
| #! Asserts that all configured smart per-procedure policies are valid for num_approvers. | ||
|
|
@@ -747,25 +746,41 @@ end | |
| #! Locals: | ||
| #! 0: policy_threshold | ||
| #! 1: default_threshold | ||
| #! 2: policy_requires_delay | ||
| #! 3: spending_threshold | ||
| #! 4: spending_requires_delay | ||
| #! 5: num_verified_signatures | ||
| #! | ||
| #! Flow: | ||
| #! 1. Compute spending policy (amount/tier-derived threshold + requires_delay flag). | ||
| #! 2. Build the tx summary commitment used for signing and timelock proposals. | ||
| #! 3. Enforce per-procedure policy (note restrictions + policy threshold + delay flag). | ||
| #! 4. Verify approver signatures. | ||
| #! 5. Combine the policy threshold with the spending threshold via `u32max`, fall back to | ||
| #! `default_threshold` when both are zero, and assert `num_verified_signatures` meets it. | ||
| #! 6. After signature verification, enforce that the active execute-path matches whether any | ||
| #! consumed policy (procedure or spending) required the delayed mode. Running this check | ||
| #! only after verification lets a caller still produce the TX_SUMMARY_COMMITMENT needed for | ||
| #! a propose/execute round-trip from an unauthorized dry-run. | ||
| #! 7. Finalize any pending timelock propose/cancel/execute slots against the verified sig count | ||
| #! and the union of `policy_requires_delay`/`spending_requires_delay`. | ||
| #! | ||
| #! Invocation: call | ||
| #! | ||
| #! NOTE: This procedure is a temporary form covering signer verification and | ||
| #! per-procedure policy enforcement. The following sections will be added: | ||
| #! - Spending Limits + Amount-Based Thresholds: a prologue that calls | ||
| #! `exec.spending_limits::compute_spending_policy` to derive a spending-derived threshold and | ||
| #! `spending_requires_delay` flag, and combines it via `u32max` with `policy_threshold` before | ||
| #! the final `compute_tx_threshold` fallback. | ||
| #! - TimelockedAccount: after signature verification, assert the execute-path vs. | ||
| #! `policy_requires_delay`/`spending_requires_delay` consistency (restoring | ||
| #! `ERR_EXECUTE_PATH_MISMATCH`), then call | ||
| #! `exec.timelock_controller::finalize_timelock_proposals` to advance any pending | ||
| #! propose/cancel/execute state. | ||
| @locals(2) | ||
| @locals(6) | ||
| pub proc auth_tx(salt: word) | ||
| exec.native_account::incr_nonce drop | ||
| # => [SALT] | ||
|
|
||
| # ------ Computing spending policy ------ | ||
| exec.spending_limits::compute_spending_policy | ||
| # => [spending_threshold, spending_requires_delay, SALT] | ||
|
|
||
| loc_store.3 | ||
| # => [spending_requires_delay, SALT] | ||
|
|
||
| loc_store.4 | ||
| # => [SALT] | ||
|
|
||
| # ------ Computing transaction summary ------ | ||
| exec.auth::create_tx_summary | ||
| # => [ACCOUNT_DELTA_COMMITMENT, INPUT_NOTES_COMMITMENT, OUTPUT_NOTES_COMMITMENT, SALT] | ||
|
|
@@ -787,9 +802,12 @@ pub proc auth_tx(salt: word) | |
|
|
||
| # ------ Enforcing procedure policy (consumes default_threshold) ------ | ||
| exec.enforce_procedure_policy | ||
| # => [policy_threshold, num_of_approvers, TX_SUMMARY_COMMITMENT] | ||
| # => [policy_threshold, policy_requires_delay, num_of_approvers, TX_SUMMARY_COMMITMENT] | ||
|
|
||
| loc_store.0 | ||
| # => [policy_requires_delay, num_of_approvers, TX_SUMMARY_COMMITMENT] | ||
|
|
||
| loc_store.2 | ||
| # => [num_of_approvers, TX_SUMMARY_COMMITMENT] | ||
|
|
||
| # ------ Verifying approver signatures ------ | ||
|
|
@@ -798,12 +816,22 @@ pub proc auth_tx(salt: word) | |
| exec.::miden::standards::auth::signature::verify_signatures | ||
| # => [num_verified_signatures, TX_SUMMARY_COMMITMENT] | ||
|
|
||
| dup loc_store.5 | ||
| # => [num_verified_signatures, TX_SUMMARY_COMMITMENT] | ||
|
|
||
| # ------ Computing final transaction threshold ------ | ||
| # If no non-auth procedure was called, `policy_threshold` is 0 and `compute_tx_threshold` | ||
| # falls back to `default_threshold`; otherwise it returns the policy max directly. | ||
| # The per-procedure pass (`compute_called_proc_policy`) has already folded `default_threshold` | ||
| # into every called procedure that lacked an explicit policy, so `policy_threshold` carries | ||
| # the procedure-side contribution. Spending limits add an independent amount-derived bound; | ||
| # combine the two via `u32max`. When both are zero (no called procedures and no spending), | ||
| # `compute_tx_threshold` falls back to `default_threshold`. | ||
| loc_load.0 | ||
| loc_load.3 u32max | ||
| # => [policy_or_spending_threshold, num_verified_signatures, TX_SUMMARY_COMMITMENT] | ||
|
|
||
| # compute_tx_threshold expects default_threshold on top, policy_threshold underneath. | ||
| loc_load.1 | ||
| # => [default_threshold, policy_threshold, num_verified_signatures, TX_SUMMARY_COMMITMENT] | ||
| # => [default_threshold, policy_or_spending_threshold, num_verified_signatures, TX_SUMMARY_COMMITMENT] | ||
|
|
||
| exec.compute_tx_threshold | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: We're computing part of the threshold inline here and part of it in |
||
| # => [transaction_threshold, num_verified_signatures, TX_SUMMARY_COMMITMENT] | ||
|
|
@@ -815,4 +843,35 @@ pub proc auth_tx(salt: word) | |
| emit.AUTH_UNAUTHORIZED_EVENT | ||
| push.0 assert.err=ERR_INSUFFICIENT_SIGNATURES | ||
| end | ||
|
|
||
| # ------ Enforcing execute-path consistency ------ | ||
| # If a *procedure* policy demands the delayed execution mode, the transaction must already be | ||
| # on the execute path (proposed earlier, now being executed). Spending limits use their own | ||
| # `requires_delay` flag to decide whether to advance timelock proposals (below) but do not | ||
| # by themselves veto an immediate-mode transaction — that distinction belongs to the policy | ||
| # layer and is consistent with the pre-foundation behavior we are preserving here. | ||
| loc_load.2 | ||
| # => [policy_requires_delay, TX_SUMMARY_COMMITMENT] | ||
|
|
||
| exec.timelock_controller::is_execute_path | ||
| # => [is_execute_path, policy_requires_delay, TX_SUMMARY_COMMITMENT] | ||
|
|
||
| # is_valid = NOT(policy_requires_delay) OR is_execute_path | ||
| swap not or | ||
| # => [is_valid_execute_path, TX_SUMMARY_COMMITMENT] | ||
|
|
||
| assert.err=ERR_EXECUTE_PATH_MISMATCH | ||
| # => [TX_SUMMARY_COMMITMENT] | ||
|
|
||
| # ------ Finalizing timelock proposals ------ | ||
| # The timelock controller consumes the union of policy- and spending-derived delay flags so | ||
| # that high-spending transactions still advance any pending propose/cancel/execute slots. | ||
| loc_load.2 loc_load.4 or | ||
| # => [requires_delay, TX_SUMMARY_COMMITMENT] | ||
|
|
||
| loc_load.5 | ||
| # => [num_verified_signatures, requires_delay, TX_SUMMARY_COMMITMENT] | ||
|
|
||
| exec.timelock_controller::finalize_timelock_proposals | ||
| # => [TX_SUMMARY_COMMITMENT] | ||
| end | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Afaict, transaction proposal and execution lives in timelock_controller because this relates to the idea of "delayed" execution, right? This connection doesn't click for me that much, so I wonder if we should rename this module. Maybe
miden::standards::auth::multisig_smart::delayed_execution?