feat: canonical expiration transaction script in miden-standards#3051
Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
3a5817b to
0e1ff1b
Compare
0e1ff1b to
2e98caf
Compare
PhilippGackstatter
left a comment
There was a problem hiding this comment.
Looks good. I'd just move the script to a different location.
mmagician
left a comment
There was a problem hiding this comment.
approved with verbosity nits
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.
ae70892 to
e979bcf
Compare
bobbinth
left a comment
There was a problem hiding this comment.
Looks good! Thank you! I left a couple of minor comments inline.
Also, this should be retargeted into main, right?
|
@bobbinth, actually I think I was wrong to assume that this would be easy to rebase back to Maybe we need to bring |
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.
Yeah, the assumption was that merging this into |
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.
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 matchingTX_SCRIPT_ARGSso the two cannot be decoupled.ExpirationTransactionScript::script_root() -> TransactionScriptRoot- the single allowlistable root, shared by every delta.The script is the args-driven form:
At tx-script entry the operand stack holds
[TX_SCRIPT_ARGS, ..], so the top element is the delta;update_expiration_block_deltaconsumes it and the remaining three argument elements are dropped.into_parts()returnsTX_SCRIPT_ARGS = [delta, 0, 0, 0]alongside the script.Why args-driven (one root for all deltas)
Reading the delta from
TX_SCRIPT_ARGSinstead 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
scripts/expiration.rs): attaches the script viainto_parts()and asserts the tx-args-supplied delta is applied.miden-testingtest_auth_network_account_accepts_allowlisted_tx_script_with_caller_argsrstest cases (deltas 10 / 30 / u16::MAX) now allowlist and execute this standard script viascript_root(), replacing their local copy - exercising the canonical root end to end.Branch / release
Targets
next. Depends onTransactionScriptRootand the tx-script allowlist from #3028 / #3049, which are present onnext.Follow-ups (not in this PR)
ExpirationTransactionScript::script_root().TX_SCRIPT_ARGS) and the counter-account deploy allowlists the root - see node#2205.