Skip to content

feat: canonical expiration transaction script in miden-standards#3051

Merged
partylikeits1983 merged 6 commits into
nextfrom
partylikeits1983-claude/canonical-expiration-tx-script
Jun 12, 2026
Merged

feat: canonical expiration transaction script in miden-standards#3051
partylikeits1983 merged 6 commits into
nextfrom
partylikeits1983-claude/canonical-expiration-tx-script

Conversation

@partylikeits1983

@partylikeits1983 partylikeits1983 commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Closes #3050. Follow-up to #3028, which added the network-account tx-script allowlist mechanism and explicitly left "defining a frozen canonical expiration script" to a follow-up.

This PR targets next.

What

Adds miden_standards::transaction::ExpirationTransactionScript:

  • ExpirationTransactionScript::new(delta: NonZeroU16) - the typed script for a given expiration delta.
  • ExpirationTransactionScript::into_parts() -> (TransactionScript, Word) - the compiled script paired with the matching TX_SCRIPT_ARGS so the two cannot be decoupled.
  • ExpirationTransactionScript::script_root() -> TransactionScriptRoot - the single allowlistable root, shared by every delta.

The script is the args-driven form:

use miden::protocol::tx

begin
    exec.tx::update_expiration_block_delta
    drop drop drop
end

At tx-script entry the operand stack holds [TX_SCRIPT_ARGS, ..], so the top element is the delta; update_expiration_block_delta consumes it and the remaining three argument elements are dropped. into_parts() returns TX_SCRIPT_ARGS = [delta, 0, 0, 0] alongside the script.

Why args-driven (one root for all deltas)

Reading the delta from TX_SCRIPT_ARGS instead of baking it in means a single MAST root accepts any delta, so every network-account creator can pin the same shared root. This is safe to allowlist on an open network account even though the submitter controls the argument: the kernel only ever lets the expiration delta be tightened, never extended, so the worst a caller can do is make their own transaction expire sooner (see the type docs added in #3028).

Validation

  • New example test (scripts/expiration.rs): attaches the script via into_parts() and asserts the tx-args-supplied delta is applied.
  • The miden-testing test_auth_network_account_accepts_allowlisted_tx_script_with_caller_args rstest cases (deltas 10 / 30 / u16::MAX) now allowlist and execute this standard script via script_root(), replacing their local copy - exercising the canonical root end to end.

Branch / release

Targets next. Depends on TransactionScriptRoot and the tx-script allowlist from #3028 / #3049, which are present on next.

Follow-ups (not in this PR)

  • AggLayer bridge/faucet accounts allowlist ExpirationTransactionScript::script_root().
  • Node ntx-builder re-enables its expiration script using this standard script (passing the delta via TX_SCRIPT_ARGS) and the counter-account deploy allowlists the root - see node#2205.

partylikeits1983 pushed a commit that referenced this pull request Jun 5, 2026
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread crates/miden-testing/tests/scripts/expiration.rs Outdated
@partylikeits1983 partylikeits1983 marked this pull request as ready for review June 5, 2026 21:38
partylikeits1983 pushed a commit that referenced this pull request Jun 6, 2026
Resolves the merge of origin/next into the canonical expiration tx script
branch. The 7 textual conflicts (Cargo.lock, Cargo.toml, batch/mod.rs,
kernel_tests batch mod + proposed_batch, test_active_note, agglayer
bridge_out) were stale copies the PR never touched and take next's version.

CHANGELOG.md auto-merged into a broken state (duplicated v0.16.0 entries and
a stale v0.15.2 heading), so it was rebuilt from next's copy with the three
PR entries (#3028 allowlist, #3028 TransactionScriptRoot, #3051 expiration
script) folded into the v0.16.0 Changes list.
@partylikeits1983 partylikeits1983 marked this pull request as draft June 8, 2026 16:07
@partylikeits1983 partylikeits1983 force-pushed the partylikeits1983-claude/canonical-expiration-tx-script branch from 3a5817b to 0e1ff1b Compare June 10, 2026 01:27
@partylikeits1983 partylikeits1983 changed the base branch from main to next June 10, 2026 01:29
@partylikeits1983 partylikeits1983 self-assigned this Jun 10, 2026
@partylikeits1983 partylikeits1983 force-pushed the partylikeits1983-claude/canonical-expiration-tx-script branch from 0e1ff1b to 2e98caf Compare June 10, 2026 02:40
@partylikeits1983 partylikeits1983 marked this pull request as ready for review June 10, 2026 02:51

@PhilippGackstatter PhilippGackstatter left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I'd just move the script to a different location.

Comment thread crates/miden-standards/src/lib.rs Outdated
Comment thread crates/miden-standards/src/transaction.rs Outdated
Comment thread crates/miden-standards/src/tx_script/expiration_script.rs

@mmagician mmagician left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approved with verbosity nits

Comment thread crates/miden-standards/src/tx_script/expiration_script.rs
Comment thread CHANGELOG.md Outdated
partylikeits1983 and others added 3 commits June 10, 2026 14:21
Adds a canonical expiration transaction script to miden-standards via
transaction::ExpirationTransactionScript. The script reads the expiration
delta from TX_SCRIPT_ARGS, so a single allowlistable root
(ExpirationTransactionScript::script_root) covers any delta - enabling
network accounts to set their expiration under the root allowlist
introduced in #3028.
Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>
Address review feedback on PR #3051:
- Move the type from src/transaction.rs to src/tx_script/expiration_script.rs,
  alongside SendNotesTransactionScript (the tx_script module added in #3055).
- Trim the repeated delta-independence wording, keeping it once on the type doc.
- Shorten the CHANGELOG entry and move it under v0.16.0.
@partylikeits1983 partylikeits1983 force-pushed the partylikeits1983-claude/canonical-expiration-tx-script branch from ae70892 to e979bcf Compare June 10, 2026 18:34

@bobbinth bobbinth left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thank you! I left a couple of minor comments inline.

Also, this should be retargeted into main, right?

Comment thread crates/miden-standards/src/tx_script/expiration_script.rs
Comment thread crates/miden-standards/src/tx_script/expiration_script.rs
Comment thread crates/miden-standards/src/tx_script/expiration_script.rs Outdated
@partylikeits1983

Copy link
Copy Markdown
Contributor Author

@bobbinth, actually I think I was wrong to assume that this would be easy to rebase back to main. The reason why is because after I addressed @PhilippGackstatter's comment here, this refactor depends on #3055. Doing a cherry pick of #3055 into main would cause a bunch of merge conflicts since that PR did a large refactor of account/interface 😭

Maybe we need to bring main back up to state with next? Or if its not too critical maybe we just wait for this to be available in the next release? Wdyt?

Address Bobbin's review on PR #3051 plus pre-push security review:
- Document that the kernel's update_expiration_block_delta only accepts a
  delta in 1..=0xFFFF (failing with ERR_TX_INVALID_EXPIRATION_DELTA otherwise),
  and that the NonZeroU16 constructor guarantees that range.
- Reword "submitted network transaction" to "submitted transaction" since the
  script works with any transaction.
- Correct the allowlist-safety rationale: a standalone single call lets an
  arbitrary submitter pick any delta up to 0xFFFF (not just tighten an existing
  window), so safety rests on the delta only bounding the submitter's own
  transaction validity window - it cannot touch account nonce, state, or assets -
  and being hard-capped at 0xFFFF blocks. Mirrored fix in the network_account test.
@bobbinth

Copy link
Copy Markdown
Contributor

Or if its not too critical maybe we just wait for this to be available in the next release? Wdyt?

Yeah, the assumption was that merging this into main is trivial. If that's not the case, then it's fine to merge into next.

Address review feedback: clarify that ExpirationTransactionScript cannot
trigger a host panic. The NonZeroU16 delta always yields an in-range
TX_SCRIPT_ARGS; a hand-crafted out-of-range argument makes the kernel
reject the transaction with ERR_TX_INVALID_EXPIRATION_DELTA. Adds a
'Panics if' section to the script doc comment and a note on tx_script_args.
@partylikeits1983 partylikeits1983 added this pull request to the merge queue Jun 12, 2026
Merged via the queue into next with commit 142fe90 Jun 12, 2026
20 checks passed
@partylikeits1983 partylikeits1983 deleted the partylikeits1983-claude/canonical-expiration-tx-script branch June 12, 2026 19:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a canonical expiration-delta transaction script to the standard library

5 participants