Conversation
#3116) * change assert_sender_has_role from call to exec * changelog --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
…3121) * add zero root check for active mint and burn policy * changelog --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* fix policy getters * changelog --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* chore: remove `AccountDelta::merge` * chore: remove `AccountVaultDelta::merge` * chore: remove tests using `Account::apply_delta` * chore: remove `Account::apply_delta` * chore: replace `apply_delta` in delta -> account conversion * chore: Remove AssetVault::apply_delta * chore: add changelog * chore: make added_assets and removed_assets non-testing --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
…3118) * add FUNGIBLE_ASSET_MAX_AMOUNT to set_max_supply * changelog --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* feat(testing): introduce TestTransactionBuilder * Simplify TestTransactionBuilder doc comment * fix: lint check
* feat(standards): add P2idNote bon builder, require at least one asset Replace the `P2idNote` marker type and its `P2idNote::create` factory with a `P2idNote` struct built via a `bon` typestate builder (`P2idNote::builder()`): - `.sender()`, `.target()`, and a serial number (`.serial_number()` or `.generate_serial_number(rng)`) are required; `.note_type()` defaults to private and attachments are optional. - `.asset()`/`.assets()` and `.attachment()`/`.attachments()` append items. - P2ID notes must now carry at least one asset, enforced in `new()` via the new `NoteError::MissingAsset`. - `From<P2idNote> for Note` converts infallibly. Migrate all `P2idNote::create` call sites to the builder. Incidental 0-asset P2ID notes in kernel tests move to P2ANY (which legitimately carries no assets), preserving the 0-asset coverage. Part of #2283 * docs(standards): address P2ID builder review comments - Drop the builder usage description from `P2idNote::new` docs; the typestate builder is self-documenting. - Trim redundant tails from the builder extension method docs. - Remove the "Use P2ANY ..." rationalization comments across the kernel tests and the P2ANY reference in the `setup_test` doc comment. - Assert the note type against `NoteType::default()` instead of a hardcoded `NoteType::Private` in the minimal-builder test. - Add a `compile_fail` doctest showing `.serial_number()` and `.generate_serial_number()` are mutually exclusive at compile time. * docs(standards): drop the dual-serial compile_fail doctest Per review feedback, remove the `compile_fail` doctest (and its explanation) on `generate_serial_number`; the typestate already enforces that the serial number cannot be set twice. * fix(standards): address #3126 review feedback - Use `NoteError::other` instead of adding a dedicated `MissingAsset` variant to the protocol crate; the "at least one asset" rule is a standards concern. - Remove the hand-rolled `create_p2id_note_exact` helper and inline the builder (with `.serial_number()`) at all 9 call sites. - Drop the low-value `builder_generates_serial_number` and `into_note_preserves_assets` tests; exercise `generate_serial_number` inside `builder_accumulates_assets` instead. - Remove the 5 duplicate CHANGELOG entries the rebase re-inserted. * fix(testing): remove unused `Word` import Left over from removing `create_p2id_note_exact`; clippy (-D warnings) flagged it.
* feat(standards): add P2ideNote bon builder, require at least one asset Replace the `P2ideNote` marker type and its `P2ideNote::create` factory with a `P2ideNote` struct built via a `bon` typestate builder (`P2ideNote::builder()`): - `.sender()`, `.target()`, and a serial number (`.serial_number()` or `.generate_serial_number(rng)`) are required; `.note_type()` defaults to private, and `.reclaim_height()`, `.timelock_height()`, and attachments are optional. - `.asset()`/`.assets()` and `.attachment()`/`.attachments()` append items. - P2IDE notes must now carry at least one asset, enforced in `new()` via the new `NoteError::MissingAsset`. - `From<P2ideNote> for Note` converts infallibly. Migrate the `P2ideNote::create` call sites to the builder. Part of #2283 * docs(standards): address P2IDE builder review comments - Drop the builder usage description from `P2ideNote::new` docs; the typestate builder is self-documenting. - Trim redundant tails from the builder extension method docs. - Assert the note type against `NoteType::default()` instead of a hardcoded `NoteType::Private` in the minimal-builder test. - Add a `compile_fail` doctest showing `.serial_number()` and `.generate_serial_number()` are mutually exclusive at compile time. * docs(standards): drop dual-serial doctest, restore P2ideNote doc Per review feedback: - Remove the `compile_fail` doctest (and its explanation) on `generate_serial_number`; the typestate already enforces that the serial number cannot be set twice. - Roll back the `P2ideNote` struct documentation to its original wording. * fix(standards): address P2IDE builder review feedback - Use `NoteError::other` instead of adding a dedicated `MissingAsset` variant to the protocol crate; the "at least one asset" rule is a standards concern. - Drop the low-value `builder_generates_serial_number` and `into_note_preserves_assets` tests; exercise `generate_serial_number` inside `builder_accumulates_assets` instead. - Remove the 5 duplicate CHANGELOG entries the rebase re-inserted. * test(standards): tighten the empty-assets assertions for P2ID and P2IDE Use `assert_matches!` to also check the error message in the empty-assets builder test, applied to both the P2ID and P2IDE modules, per review feedback.
* Use TestTransactionBuilder in miden-testing * Deleting methods from tx context builder as per comments
…3065) * flip AuthSingleSigAcl to exempt-list semantics Replace the previous trigger-list ACL with an exempt-list ACL: every called account procedure requires a signature by default, and only procedures listed in the exempt map are allowed to execute without authentication. This removes a footgun where forgetting to register a new setter in the trigger list silently left it permissionless, and lets us drop the `allow_unauthorized_output_notes` and `allow_unauthorized_input_notes` configuration flags. Under the new model the input/output note checks become implicit: any side-effecting note consumption goes through an account procedure call, so the procedure check covers it. - MASM: rewrite `auth_tx_acl` to iterate account procedures (skipping index 0, the auth proc itself), check `was_procedure_called`, and look up each called proc in the exempt map. Mirrors the structure of `multisig::compute_transaction_threshold`. - Storage layout: rename `trigger_procedure_roots` slot to `exempt_procedure_roots`, keyed by procedure root with `[1, 0, 0, 0]` presence marker. Drop the now-unused `config` slot. - Faucet factory: `AuthControlled + SingleSig` now uses an empty exempt list, so every authority-gated setter requires a signature including the burn/receive path that previously rode in unsigned. - Test helper `Auth::Acl` and integration tests flipped to the new semantics, with added invariant coverage for the empty-exempt-list default and for transactions that mix exempt and non-exempt calls. Part of #2964. * docs: changelog entry for AuthSingleSigAcl exempt-list flip Part of #2964. * address pre-push review findings - Validate exempt_procedures uniqueness in AuthSingleSigAcl::new so a caller passing duplicate procedure roots receives an AccountError instead of panicking inside StorageMap::with_entries. Add a unit test that exercises the rejection path. - Refresh the stale "Safe to unwrap because we know that the map keys are unique" comment to reference the validation source. Correct the pre-existing # Panics doc on `new` (it returns Result for the length check, never panics). - Reword the integration-test assertion message that read as contradictory next to nonce_delta == 0. - Note in the CHANGELOG that the no-signature hot path now iterates every account procedure (two kernel calls each), so it costs more than the old trigger-list iteration that was bounded by the trigger count. * restore explicit input/output note auth checks Security review caught a real auth bypass: deleting the explicit `tx::get_num_output_notes` / `tx::get_num_input_notes` gates relied on `was_procedure_called` being set for every side-effecting procedure, but the kernel only flags procedures that touch account-restricted APIs. `output_note_create` and `output_note_add_asset` do *not* trip that flag (only `assert_native_account`), so any account procedure that emits notes without also moving assets through the vault would have executed unsigned. Asset-bearing flows stay safe because vault add/remove is tracked, but the "note checks are implicit" claim was false for asset-less note emission. This restores the issue's original three-invariant design: 1. Any kernel-detected called procedure not on the exempt list forces `auth_required`. 2. Any output note creation forces `auth_required` unconditionally (this is the gap that `was_procedure_called` cannot close). 3. Any input note consumption forces `auth_required` unless an exempt procedure was detected as called during the transaction (the consumption is then vouched for by the exempt call). The MASM now tracks `any_exempt_called` via a local across the procedure loop so the input-note gate can distinguish vouched consumption from raw consumption. The Rust module doc, the on-type "procedure detection" callout, and the CHANGELOG entry are updated to state precisely which gaps `was_procedure_called` leaves and why the explicit note checks remain. A new integration test `test_acl_exempt_detected_procedure_succeeds_without_auth` exercises the positive exempt-map lookup with a kernel-detected procedure (`get_item`) so a regression that inverted the marker would be caught. * test: cover the unconditional output-note auth gate Code review flagged that the new condition 2 ("any output note created → auth_required, unconditionally") had no regression coverage. Adding a test where the procedure that emits the note (BasicWallet's move_asset_to_note) is on the exempt list, so condition 1 is satisfied and the only thing forcing authentication is the output-note check itself. Without an authenticator the tx must fail with MissingAuthenticator. * clarify transaction-wide input-note vouching and harden mixed test Security review caught a documentation mismatch: the prior wording ("vouched for by an exempt procedure") read as per-note vouching, but `ANY_EXEMPT_CALLED_LOC` is a transaction-wide flag — a single detected exempt call lifts the input-note signature requirement for every input note in the same transaction, not only the notes that procedure handled. Asset exfil is still blocked by the unconditional output-note gate, but exempting any detected procedure relaxes input-note auth transaction-wide, which integrators should know. - Rewrite condition 3 in the Rust doc to state the global scope explicitly, with a usage guidance line. - Mirror the clarification in the MASM `ANY_EXEMPT_CALLED_LOC` rationale. - Add a SECURITY-CRITICAL invariant comment on the unconditional output-note `or` (the line is the only barrier against an exempt procedure emitting notes via `output_note_create`). - Update the CHANGELOG bullet with the same global-scope wording. Also addressing a code review nit: `test_acl_mixed_exempt_and_protected_requires_auth` previously exempted `account_procedure_1` (undetected), so the test never actually exercised the "detected-exempt alongside detected-non-exempt" branch. Switch to exempting `get_item` and calling both `get_item` + `set_item` so a regression that let a detected exempt call suppress the non-exempt auth requirement would be caught. * isolate input-note auth gate and surface vouching warning at config site - Add `test_acl_input_note_consumption_requires_auth_without_exempt`: empty exempt list, no tx script, consume the mock note → expect MissingAuthenticator. Without this, the input-note branch of the MASM `and or` could be deleted and no test would fail (every other no-auth note test also calls a non-exempt detected procedure that trips condition 1 first). - Sharpen the cost note in the CHANGELOG to mention the per-detected- call map lookup (was undercounted as "two kernel calls each"). - Add a pointer on `AuthSingleSigAclConfig::with_exempt_procedures` warning about the transaction-wide scope of condition 3, so callers see it at the configuration site, not only on the type. * review nits: expand faucet exempt-map probe and fix doc comment - auth_scheme_slot_schema: switch `//` to `///` so the doc renders consistently with the sibling slot-schema accessors. - faucet_contract_creation: probe the full former trigger set (mint_and_send + 4 metadata setters + 4 policy setters + pause + unpause) for absence from the exempt map, rather than only three representative roots. A regression that put any of these back into the exempt map will now surface here. * review nits: cover MAX_NUM_PROCEDURES path and inline BTreeSet import - Add `test_singlesig_acl_rejects_exempt_list_above_account_limit` so the two error paths in `AuthSingleSigAcl::new` (duplicates and over-limit) have symmetric coverage. - Move `alloc::collections::BTreeSet` to a top-of-file `use` to match the surrounding import style (`alloc::vec::Vec` is already imported this way). * style: replace em dashes with simple dashes per project convention * docs: consolidate auth-logic into two conditions Restructure the three-condition auth description into two: condition 1 combines the per-procedure check and the input-note vouching clause (they are logically coupled and condition 1 already handles the non-exempt-called half through the exempt-list lookup), and explicitly spells out that input-note consumption with no procedures called at all still requires authentication. Condition 2 (output notes) stays unconditional and is unchanged. Apply the same restructuring to the MASM docstring, the CHANGELOG entry, and the cross-references in the `with_exempt_procedures` setter and the procedure-detection note. The implementation is unchanged - this is purely a docs revision. The transaction-wide vouching behavior remains as-is pending further discussion on whether to introduce a separate per-note-vouching opt-in. * docs: roll back to three conditions, sharpen input-note check Restructure the auth-logic description into three conditions, matching the issue's original spec but with a sharper wording for the input-note check: 1. A kernel-detected non-exempt procedure was called. 2. An input note was consumed AND no procedure was detected as called at all. 3. Any output note was created (unconditional). Conditions 1 and 2 are logically equivalent in outcome to the previous formulation ("input consumed AND no exempt called"), because condition 1 already catches the non-exempt-called case. Stating condition 2 as "no procedure called at all" makes the easy-to-miss case (input consumed but no account procedure invoked) explicit. Update the MASM to literally match the new wording: track ANY_PROC_CALLED_LOC (set to 1 whenever was_procedure_called returns true) instead of ANY_EXEMPT_CALLED_LOC. The flag-update site simplifies from a load-or-store to an idempotent `push.1 loc_store`. All 16 integration tests and 4 unit tests still pass without modification, confirming the outcome equivalence. Apply the same restructuring to the Rust type doc, the with_exempt_procedures setter, the procedure-detection note, and the CHANGELOG entry. Update two test docstring cross-references to use the new condition numbering. The footgun warning about transaction-wide vouching remains in place. * optimize auth_tx_acl loop and drop "input-note" hyphenation Tighten the procedure-iteration loop: instead of iterating num_procedures-1 down to 0 and gating the body on `dup neq.0` to skip the auth procedure at index 0, iterate down to 1 directly. The initial guard becomes `dup neq.1` (don't enter the loop if num_procedures == 1, i.e. only the auth procedure is installed) and the continuation check also becomes `dup neq.1`. This removes the inner `if.true ... end` block that was gating every iteration, saving a few cycles per procedure on the no-signature hot path while preserving the index-0 skip property (the auth procedure is guaranteed at index 0 by the account-code builder, so by never decrementing below 1 we never touch it). Replace "input-note" with "input note" in the comments and docs of files this branch introduced or modified. * docs: shorten ANY_PROC_CALLED_LOC comment and use named rule references Shrink the doc comment on `ANY_PROC_CALLED_LOC` to four lines explaining the flag's role: it tracks "any procedure detected as called" and gates the input note check on whether at least one procedure ran, with a note that non-exempt detected calls already force authentication via the per-procedure check inside the loop. Replace every numbered authentication-condition reference ("condition 1", "condition 2", "condition 3") in the type doc, MASM docstring, CHANGELOG entry, `with_exempt_procedures` setter, the procedure- detection note, and the integration test docstrings with named rules: "non-exempt proc was called", "input note was consumed, but no proc was called", and "output note was created". Numbered references couple prose to a particular ordering and are fragile under future doc reshuffles; named references are stable. * address PR review comments - MASM: trim the slot comment on EXEMPT_PROCEDURE_ROOTS_SLOT to two lines; drop the "most easily missed" trailing sentence and the output-note explanation from the auth_tx_acl docstring; remove the redundant multi-line explanation above the input note check (the docstring already covers the same ground). - Faucet factory: shorten the AuthControlled + SingleSig comment by dropping the historical reference to allow_unauthorized_input_notes. - Errors: add a typed `AccountError::DuplicateExemptProcedure(_)` variant carrying the offending procedure root, and replace the duplicate-check `AccountError::other` call with it. The check now short-circuits in a single forward pass that identifies which root was duplicated. - Tests: hoist the per-function `use` block in `test_acl_output_note_creation_requires_auth_even_when_caller_exempt` up to the top of the file, alongside the other module-level imports; rewrite the explicit `TransactionScript::from(...)` cast to a typed binding plus `.into()`. - CHANGELOG: rewrite the entry to fit in under 400 characters by deferring the full auth-logic description to the type doc. * docs: drop quoted-phrase rule references in favor of short descriptions Convert "non-exempt proc was called", "input note was consumed, but no proc was called", and "output note was created" from literal quoted labels (used everywhere the rules are referenced) into natural prose descriptions: "the non-exempt proc check", "the input note check", and "the output note check". The enumeration in the type doc and MASM docstring is now numbered 1./2./3. with descriptive bullet bodies, and all references in the surrounding prose, the `with_exempt_procedures` setter, the procedure-detection note, and the integration test docstrings use the short forms. * address remaining PR review comments - MASM: drop the SECURITY-CRITICAL comment block above the unconditional output-note `or`. The section header on the line above already names the invariant and the reviewer considered the explanation redundant. - singlesig_acl.rs: remove the per-setter warning on `with_exempt_procedures` (already covered by the type doc), shorten the transaction-wide-vouching paragraph to its first sentence, drop the "auth runs after the rest of the transaction" paragraph, and compress the "Important Note on Procedure Detection" section into eight lines while preserving the practical guidance. - CHANGELOG: shorten the entry to a single sentence and switch the reference from #2964 (issue) to #3065 (this PR), per project convention. * address remaining PR review comments - MASM: apply the requested commentary edits in `auth_tx_acl` (add a Locals section header on the procedure, reword the section header for the iteration block, clarify the initialization comments for the any_proc_called flag and auth_required, restate the loop comment as a single line, rewrite the post-was_called marker comment to mention the input note check it gates, shorten the exempt-map lookup comment, and tighten the post-loop stack annotation). - AuthSingleSigAclConfig: switch `exempt_procedures` from `Vec<AccountProcedureRoot>` to `BTreeSet<AccountProcedureRoot>`. Uniqueness is now enforced by the type, so the runtime duplicate check in `AuthSingleSigAcl::new` and the `DuplicateExemptProcedure` variant on `AccountError` (along with the corresponding unit test) are dropped. The "safety" comment on the now-trivially-infallible `StorageMap::with_entries(...).unwrap()` is removed, and the surrounding storage-slot comment is reworded per the reviewer's suggestion. - Update the `Auth::Acl` mock-chain helper variant and every integration test call site to use `BTreeSet::from([...])`. - Trim the doc comment on the procedure-detection note and rewrite the `# Panics`-style block on `AuthSingleSigAcl::new` as a bullet list under "Returns an error if". - Faucet construction test: apply the wording suggestion on the empty-exempt-map probe comment. * reflow inline comments to <=100 cols and remove stray breaks - Faucet construction test: rejoin the "Probe the full" / "former trigger set" fragments back into a single sentence; the PR-suggested comment had been pasted with a stray mid-clause newline. - MASM auth_tx_acl: - shorten the procedure-iteration section header so it fits in 100 columns, - trim the "no authentication required by default" comment by one word so it fits, - wrap the loop-direction comment over two lines, - reflow the `was_called` marker comment block onto sentence boundaries (the previous break landed mid-clause after "Setting to 1"), and - wrap the exempt-map lookup comment so the marker value sits on its own line. * simplify auth_tx_acl: drop input/output note checks Per Philipp's review (#3065 (comment)), the input note vouching rule and the unconditional output note rule are redundant for the funds-out concern. Any procedure that moves assets out of the account vault must call `account_remove_asset` (or equivalent), which is kernel-tracked, so an exfiltrating procedure always shows up in the per-procedure check unless the author has explicitly exempted it. The transaction kernel epilogue separately enforces asset conservation across the whole transaction (input_vault == output_vault, see ERR_EPILOGUE_TOTAL_NUMBER_OF_ASSETS_MUST_STAY_THE_SAME at epilogue.masm:439), so an output note cannot smuggle in assets that weren't taken from the vault or an input note. This collapses the auth logic to a single condition: "a non-exempt detected procedure was called". The benefits: - The MASM drops `ANY_PROC_CALLED_LOC`, the `@locals(1)` annotation, the flag-set inside the loop, and the entire post-loop input/output note block. - `use miden::protocol::tx` is no longer needed. - The type doc collapses from a three-condition list with a transaction-wide-vouching footgun warning to a two-paragraph description plus the unchanged procedure-detection caveat. - Two integration tests (test_acl_output_note_creation_requires_auth_even_when_caller_exempt and test_acl_input_note_consumption_requires_auth_without_exempt) are removed because they exercise rules that no longer exist; the remaining seven tests still cover the procedure-based path (empty/exempt/mixed/protected, key rotation, initial-state read). The faucet's `AuthControlled + SingleSig` factory ships an empty exempt list, so its behavior is unchanged: every authority-gated setter still requires a signature. * address remaining PR review comments - MASM auth_tx_acl docstring: shorten the security argument per the reviewer's wording. The first sentence states the auth rule directly; the second explains that asset removal goes through a kernel-tracked procedure, so funds-out is gated unless every procedure in that path is explicitly exempted. - MASM post-loop stack annotation: label the literal `1` as `i = 1` so a reader does not have to derive that this is the loop counter at its final value. - Rust type doc: drop the trailing sentence about the epilogue's asset conservation check; the kernel-tracked `account_remove_asset` explanation in the preceding sentence carries the same argument more directly. * address Philipp's remaining PR review comments - testing/faucet.rs: per Philipp's note that exempting `receive_and_burn` preserves the old "BURN note runs unsigned" behavior, seed `user_faucet_single_sig_acl` with an exempt set containing `FungibleFaucet::receive_and_burn_root()`. Every other authority-gated procedure (mint_and_send, the metadata setters, the policy setters, pause/unpause) still requires a signature. - tests/auth/singlesig_acl.rs: address the three test cleanups Philipp flagged. Inline the temporary `tx_context_*_with_auth` bindings into a single build + execute + await chain. Factor the canonical `mock::account::get_item` and `mock::account::set_item` tx scripts into `compile_call_get_item_script` / `compile_call_set_item_script` helpers (the get_item script was duplicated across three tests). Replace `.expect(...)` on test results with `?` so the failure message preserves the source error. Also finishes the `TestSetup` refactor the user had started: rewrites every test body to destructure the helper output, and drops the unused proc-root fields from the struct. - New `test_acl_burn_note_against_user_faucet_runs_without_signature`: builds a public fungible faucet account using `user_faucet_single_sig_acl` (which now carries `receive_and_burn` in its exempt set), creates a BURN note targeted at the faucet, and verifies the consumption transaction executes without an authenticator. Direct evidence that the exempt-set choice in `user_faucet_single_sig_acl` matches Philipp's intent. * docs: fix doc lint --------- Co-authored-by: Claude (Opus) <noreply@anthropic.com> Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* feat(standards): replace BurnNote::create with a bon builder Convert the `BurnNote` marker type into a struct built via a `bon` typestate builder (`BurnNote::builder()`), mirroring `P2idNote`. A `BurnNote` converts into a `Note` via `Note::from`. Migrate the faucet burn-note test sites. Part of #2283. * refactor(standards): model BurnNote as carrying a single Asset Address review: store the burned asset as Asset instead of NoteAssets, take #[builder(into)] asset, expose an asset() getter, and build the NoteAssets in the Note conversion (one asset can't exceed the limit). Use NoteStorage::default() for the empty storage. * test(testing): migrate singlesig_acl burn note to the BurnNote builder The next merge brought in tests/auth/singlesig_acl.rs, which still called the removed BurnNote::create. Port it to BurnNote::builder() and drop the now-unused NoteAttachments import.
* rework SWAP to support public payback notes Public payback notes were unrecoverable from on-chain data: the previous SWAP precomputed the payback recipient off-line and embedded only the resulting hash, so the consuming script had no preimage to register with the advice provider. Build the payback P2ID recipient at consume time from data available in SWAP storage so the on-chain script can call p2id::new (which also registers the recipient preimage in the advice map): - Embed the creator account ID in storage (hybrid embed, mirroring PSWAP) so the consumer reads it directly instead of going through active_note::get_sender. - Derive the payback serial as swap_serial[0] + 1. - Derive the payback tag from the creator account ID prefix via note_tag::create_account_target. Storage shrinks from 14 to 11 items: the precomputed recipient and tag are no longer stored. The Rust constructor sets creator_id = sender by convention. * simplify swap.masm comments * refactor(standards): hide private SWAP payback recipient Branch SWAP MASM on payback note type so private paybacks store an opaque precomputed recipient digest (and tag) instead of the creator id. Public paybacks keep the creator id in plaintext since the consumer needs it to reconstruct the recipient via p2id::new. The unified 16-felt storage asserts zero on the slots unused by each branch, making the privacy guarantee structural rather than convention-based. * fix(standards): clippy and rustfmt in swap.rs * docs: refresh SWAP storage description in note.md * docs(swap): explain why creator id is stored explicitly * rename SWAP creator id field to payback target id * docs(swap): consolidate per-mode payback docs Centralize the rationale for the SwapPayback::Private vs Public storage shape on the enum itself and drop the repeated explanations from SwapNote::create, SwapNoteStorage, and the constructors. Also remove a stale comment from swap.masm. * style(standards): rustfmt swap.rs * test(standards): adapt dummy_target_id to new AccountId::dummy signature * feat(standards): re-export SwapPayback from note module * Apply suggestion from @partylikeits1983 Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com> * docs(swap): clarify payback target defaults to sender * refactor(swap): store payback target account ID as [suffix, prefix] Swap the public payback target limbs so the suffix occupies slot [14] and the prefix slot [15], matching the [suffix, prefix] account ID convention used elsewhere (e.g. P2ID storage). Updates the MASM storage constants and layout comment, the Rust From/TryFrom conversions, and the storage doc table. Purely a layout convention change; the on-chain payback recipient is unaffected, as verified by the public-payback integration tests. * refactor(swap): avoid single-letter closure bindings in TryFrom Rename the |e| and |f| closure parameters in the SwapNoteStorage TryFrom impl to |err| and |felt| for readability. * test(swap): fold try_from round-trip into the storage round-trip tests Merge the standalone swap_note_storage_try_from_round_trip_public/private tests into the two round-trip tests, which now also parse the serialized NoteStorage back via TryFrom and assert equality with the original. * test(swap): assert exact error in dirty-slot rejection tests Replace the loose is_err() checks in the SwapNoteStorage dirty-slot tests with assert_matches! on NoteError::Other guarded by the exact error message, so the tests keep verifying the intended validation after refactors. * docs(swap): clarify payback target load-order comment Reword the public-payback comment to explain that loading prefix then suffix leaves the stack as [suffix, prefix], matching p2id::new's [target_id_suffix, target_id_prefix, ...] inputs (the previous wording read as if the signature were prefix-first). * replace apply_delta with apply_patch --------- Co-authored-by: Marti <marti@miden.team> Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>
* chore: replace delta error for patch error * docs: add changelog entry
* extend wallet APIs with multisig and guarded multisig * changelog * add Approver struct * add documentation for withholding issue * add Approver struct * apply suggestions --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* feat(standards): replace MintNote::create with a bon builder Convert the `MintNote` marker type into a struct built via a `bon` typestate builder (`MintNote::builder()`), mirroring `P2idNote`. A `MintNote` converts into a `Note` via `Note::from` and keeps the faucet-id/asset-faucet match check via `NoteError::other`. Migrate the faucet mint-note test sites. Part of #2283. * Update crates/miden-standards/src/note/mint.rs Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com> * refactor(standards): derive MintNote faucet_id from storage Address review: drop the faucet_id builder param and derive it from the embedded MintNoteStorage asset, removing the mismatch error condition. Remove the now-dead builder_rejects_mismatched_faucet test and inline its storage helper into the remaining test. Update the mint call sites in faucet.rs. * style(standards): collapse Note::with_attachments to satisfy nightly rustfmt --------- Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>
* add multisig options to fungible faucet * changelog * chore: minor fixes --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com> Co-authored-by: Bobbin Threadbare <bobbinth@protonmail.com>
…protocol` (#3122) * refactor: Add attachments to NoteFile * chore: comments * chore: move to standards * chore: comments * refactor: remove attachments --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
…#3073) * perf: avoid double-hashing the asset vault key in fungible add/remove Hash the raw asset vault key once at the start of each asset vault modifier and have peek_asset/get_asset accept the already-hashed key, removing one poseidon2 hash per fungible asset add/remove (including the fee-removing path in the epilogue). The set_asset helper becomes a bare smt::set wrapper and is removed. Worst-case post-compute_fee cycles drop from 863 to 843; VAULT_KEY_HASH_CYCLES is re-measured from 50 to 30 (same 45-cycle margin). Closes #3059 * chore: add changelog entry for #3073 * refactor: keep asset vault key hashing internal to the vault Address review feedback: hashing stays inside the asset_vault module so callers don't have to think about it. - get_asset is unchanged: it takes a raw ASSET_KEY and hashes internally. - hash_asset_key stays private. - peek_asset takes the pre-hashed ASSET_KEY_HASH; add_fungible_asset and remove_fungible_asset hash the key once at the start and reuse it for both the peek and the set, eliminating the double hash. - the now-redundant set_asset wrapper is replaced by a direct smt::set. --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
) The note doc's Inputs section was renamed to Storage (### Storage), but three reference links still pointed at note#inputs, which docs.miden.xyz flags as a broken anchor on ingest. Repoint them to note#storage: - protocol_library.md: get_storage / get_storage_info - transaction.md: P2ID note storage link Closes #3158.
…3157) * refactor: update AuthRequest event to carry either signature or tx summary * chore: update changelog
…ts (#3123) * feat: Introduce create, update, remove storage patches * chore: add `AccountStoragePatchBuilder` * chore: replace mutators on storage patch with builder * chore: test all slot merge permutations * chore: normalize empty words in created map * chore: add changelog * chore: optimize StorageMapPatchEntries serialization * chore: compact empty words to `None` in value patch serialization * chore: reject duplicate entries in map patch * chore: add note on no-op-ness of map update variant * chore: split storage patch into modules * feat: allow re-creating existing slot * feat: allow removing non-existent slot * feat: document merge behavior * feat: ensure num storage patches is within limits * feat: remove no-op storage patches after merge * chore: revert allowing removing non-existent slot * chore: remove outdated error condition * chore: remove `set_init_map_item` * chore: use `expect` in patch construction
* feat: update kernel to commit to patch operation * chore: add changelog * chore: make map trailer description clearer * chore: remove unnecessary delta computation in epilogue
* implement nft faucet * changelog * apply suggestions * apply suggestions * lint * remove max supply from NFTs * remove redundant comments * add nft modify assertion * apply suggestions
* feat: reject full state deltas with storage updates * chore: replace storage patch test helpers with more targeted ones * feat: define full state as only create ops * chore: add changelog
* feat(standards): treat PSWAP requested amount as a minimum Previously the PSWAP note reverted when the total fill (account_fill + note_fill) exceeded the requested amount. This makes `requested` a minimum rather than an exact cap: an over-fill is accepted and treated as a full take. - Payout divisor is `denom = max(total_fill, requested)`, so an over-fill divides by the fill itself and pays out the whole offered side. - No remainder note is created on a full or over-fill: the partial-fill check is `total_in < total_requested` (was `!=`). - The creator banks the surplus requested tokens via the P2ID payback, which carries the full fill amount. - Removes the `ERR_PSWAP_FILL_EXCEEDS_REQUESTED` cap. MASM and Rust mirror each other (denom selection, no-remainder-on-overfill, payout read from on-chain attachments). Removing the cap also removes accidental-overpay protection: a filler who over-pays gets no refund and no extra offered tokens, so callers must compute the intended fill amount. Tests: single-sided over-fill payback round-trip, mixed account+note over-fill with rounding-dust attribution, a calculate_offered_for_requested over-fill unit case; the fill-exceeds-requested error case is removed. * refactor(standards): clarify PSWAP over-fill, address review comments - Extract a `max` helper proc; `execute_pswap` calls `exec.max` instead of the inline lt/if-else to pick `denominator = max(fill, requested)`. - Rename `CALC_DENOM`/`EXEC_AMT_DENOM` to `*_DENOMINATOR`, matching the Rust mirror and spelling out the abbreviation. - Rewrite the `execute_pswap` doc with the two fill cases stated explicitly, and note that two-sided over-fill rounding dust (<=1 token) is absorbed by the cross-swap counterparty, never minted or stranded. - Drop the redundant inline `is_partial` annotation. - Test: assert the consumer takes the whole offered side on a single-sided over-fill (per CodeRabbit). No behaviour change: the max extraction is behaviour-equivalent. 10 standards unit + 69 pswap integration tests pass; fmt clean. * refactor(standards): rename divisor to fill_reference, tidy comments Address review feedback on PR #9: - Rename the payout divisor `full_fill_amount` -> `fill_reference` across the MASM (CALC_/EXEC_AMT_ constants) and the Rust mirror. - MASM: drop single/two-sided wording in the execute_pswap doc (use account_fill/ note_fill); trim the inline `fill_reference = max(...)` comment that duplicated the proc doc. - Tests: shrink the combined-fill rstest doc and de-hardcode the per-case numbers in its body comments. * docs: add CHANGELOG entry for PSWAP requested-as-minimum * Update crates/miden-testing/tests/scripts/pswap.rs Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com> * refactor(standards): address review feedback on PR #3148 - MASM `max`: branchless `cdrop` instead of an if/else branch. - Rename the requested-amount locals to `min_requested`/`min_requested_amount` and align the divisor comments to make clear it is a minimum, not an exact target. - Combined-fill test: Alice/Bob are now bare AccountIds (not funded wallets), and the rstest fill params are named after their source (`charlie_fill`/`bob_fill`). * refactor(standards): use min_requested consistently for the runtime minimum Follow-up to the review-feedback commit: rename the runtime requested-minimum references (the MASM `EXEC_AMT_REQUESTED` local + its comments, `execute_full_fill`'s local, and the remaining doc lines) to `min_requested`. Storage field/accessors, raw storage slots, the account/note fill legs, and `remaining_requested` keep the `requested` name. Pure rename — recipients/digests unchanged (tests pass). * refactor(standards)!: rename PSWAP requested -> min_requested everywhere Rename every `requested` reference in the PSWAP module to `min_requested` to make clear the amount is a minimum: the public `PswapNoteStorage` field/accessors/builder (`requested_asset` -> `min_requested_asset`, `requested_asset_amount` -> `min_requested_asset_amount`, `requested_faucet_id` -> `min_requested_faucet_id`), `calculate_offered_for_requested` -> `calculate_offered_for_min_requested`, the MASM storage/exec/P2ID constants, and all comments/docs. Behaviour-preserving: names do not affect the assembled MAST or the positional storage serialization (recipients/digests unchanged; 9 standards unit + 69 pswap integration tests pass). BREAKING for downstream callers of the renamed public API (miden-client, web-sdk). * Narrow PSWAP rename to the public asset/amount accessors Revert the over-broad min_requested sweep and keep the rename to exactly the public-facing amount: PswapNoteStorage::requested_asset -> min_requested_asset and requested_asset_amount -> min_requested_amount. requested_faucet_id is left unchanged, and the MASM/internal naming returns to its prior form. * Use bare account IDs for creator-only accounts in PSWAP tests Accounts that only supply a PSWAP creator/sender AccountId were built as full wallets via add_existing_wallet_with_assets, carrying an unused vault balance that implied the offered asset came from the creator's vault (it comes from the note). Replace them with AccountIdBuilder::new() .build_with_seed(..), matching the existing combined-fill test. Accounts that consume a transaction, source fill assets from their vault, or have their vault asserted stay full wallets. * Rename PSWAP storage amount slot to min_requested_amount The storage-layout doc and the slot const used requested_amount while the amount is the requested minimum (the Rust accessor is min_requested_amount). Rename the doc entry and REQUESTED_AMOUNT_ITEM -> MIN_REQUESTED_AMOUNT_ITEM; the faucet/callbacks slots stay requested_* (matching requested_faucet_id). --------- Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>
* add code inspection account component * changelog * namespace
* feat: migrate protocol crate to miden-project * chore: comments * review: rename `miden::protocol_utils` * review: address comments on MASM imports and constants * review: declare miden-core dep in the manifest * chore: format toml * review: rename projects * review: provide miden-core through `InMemoryPackageRegistry` * review: use `package.write_masp_file` convenience * review: do not use Result on `build_assembler` * review: expose Package for `ProtocolLib` * review: expose Package for `TransactionKernel` * feat: comments * feat: explicit miden-core versioning * feat: explicit linkage on project file * feat: remove `shared_modules` and move `account_id` to `protocol-utils` * feat: split `miden-tx-kernel` and `miden-tx-kernel-core` (#3149) * feat: split miden-kernel-tx and miden-kernel-tx-core * chore: remove miden-project dep; lint * fix: test * review: small changes on comments * review: miden-core version and comment * review: rename `protocol_utils` * review: move masm source code to `src` dir * review: changelog breaking marker
* read allowlist via get_initial_map_item * changelog * read tx script allowlist via get_initial_map_item --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
…key and signature (#3178) * add documentation for ecdsa * changelog --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
…SigAcl` refactor (#3180) * remove all_authority_gated_setter_roots after AuthSingleSigAcl refactor * changelog --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
…notes (#3447) * feat(agglayer): enable on-chain bridge role rotation via RBAC action notes Wraps up the role-transfer mechanism for the bridge's administrative roles. PR #3130 moved the bridge to the miden-standards RBAC stack but left rotation unexercisable on-chain: the bridge's AuthNetworkAccount allowlist rejected the role-management note. - Add RbacActionNote::script_root() to AggLayerBridge::allowed_notes(), making grant_role / revoke_role / set_role_admin / renounce_role reachable on the bridge. The fee-schedule entry derives from the allowlist automatically; the allowlist is component storage, so BRIDGE_CODE_COMMITMENT is unaffected. - Add a create_existing_bridge_account_with_admin_and_roles fixture and an agglayer rbac_rotation test suite covering: grant-then-use, revoke-then-fail, unauthorized grant, ADMIN rotation, the last-admin-renounce lockout hazard, and an allowlist pin test. - Document role rotation in SPEC.md section 2.5 (with the rotation ordering, last-admin, and target-binding caveats), add the RBAC_ACTION note as section 4.7, and resolve the stale rotation TODOs. Closes #2706 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(agglayer): single bridge test fixture with explicit admin Merge create_existing_bridge_account_with_admin_and_roles into create_existing_bridge_account_with_roles: the fixture now always takes the ADMIN member explicitly, and callers that do not exercise rotation pass the dummy admin themselves. Addresses review feedback on the duplicate constructors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(agglayer): drop historical framing and fix the ADMIN-decommission recipe Document only present behavior in SPEC section 2.5, per review feedback. Also correct the recipe for bounding ADMIN authority: each delegate admin role must be populated and made self-administering, in committed steps, before ADMIN is emptied - otherwise the delegate roles freeze under the then-empty ADMIN role. Pinned by the new self_administered_delegate_survives_admin_removal test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: move generic RBAC rotation guidance from the agglayer SPEC to the component docs SPEC section 2.5 now keeps only the bridge-specific consequences of on-chain role management and points to the miden-standards docs for the generic hazards: the RoleBasedAccessControl rustdoc gains the corrected, strictly ordered ADMIN-decommission recipe (with its no-quorum residual risk), and the RbacActionNote rustdoc gains the note-model security considerations (ordering, unexpiring pending notes, no target binding). Addresses review feedback that most of this content belongs in the RBAC documentation rather than the agglayer spec. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: shorten the RBAC rotation guidance Cut the RoleBasedAccessControl decommission paragraph, the RbacConfigNote security considerations, and the SPEC 2.5 caveat list down to their essentials. While shortening, correct two claims for the post-#3434 reality: the builder now attaches NetworkAccountTarget by default, and the auto-allowlisted NETWORK_ACCOUNT_CONFIG note reaches ADMIN-defaulted procedures - so the bridge's ADMIN role must never be emptied (it would forfeit the post-deployment configuration channel), and the SPEC now says so instead of describing decommissioning as viable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(agglayer): trim the bridge fixture doc comment Addresses review feedback. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(standards): drop the target-binding caveat from the RbacConfigNote docs Target binding will be enforced by the note script itself (tracked separately), so the caveat is not worth documenting. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(agglayer): drop the target-binding caveat from SPEC section 2.5 Note target binding is tracked in a separate issue; the section 4.7 permissions table keeps the factual consumer row. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(agglayer): drop rotation tests already covered by the generic RBAC suite Keep only the bridge-specific wiring tests: grant-then-use and revoke-then-fail (RBAC_CONFIG through the bridge allowlist, fee schedule, and update_ger gating) plus the allowlist pin. Admin rotation, delegation exclusivity, and last-admin removal are component semantics covered in tests/scripts/rbac/. Three properties the generic suite did not yet cover move there instead of being dropped: an unauthorized-sender RBAC_CONFIG note is rejected, a note targeting another account is consumable (the assertion that inverts once target binding lands), and a self-administered role stays manageable after ADMIN renounces (set_role_admin(X, X)). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(agglayer): share the bridge setup helper across test suites Extract the duplicated setup_bridge helpers from remove_ger.rs and rbac_rotation.rs into test_utils (BridgeSetup + setup_bridge), seeding a chain-resident admin wallet so both suites - and future ones - can use the same fixture. Addresses review feedback on re-using test helpers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(agglayer): pin paused-bridge rotation and the effective note allowlist Post-merge follow-ups: a test pinning that RBAC_CONFIG notes stay consumable while the bridge is paused (the emergency-recovery path SPEC section 2.5 documents), an extension of the allowlist pin to the effective on-account set including the AuthNetworkAccount auto-added entries, and two wording fixes (NETWORK_ACCOUNT_CONFIG also dispatches fee-policy updates; the bench dummy admin covers all ADMIN-gated operations). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(agglayer): assert the pause actually took effect during paused rotation Promote is_bridge_paused into test_utils, assert the pause state before and after the paused-bridge rotation, and pin the bridge's tx-script allowlist alongside the note allowlist. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Apply suggestions from code review Co-authored-by: Marti <marcin.gorny.94@protonmail.com> --------- Co-authored-by: Claude (Opus) <noreply@anthropic.com>
* refactor(standards): remove the AuthSingleSigAcl auth component Its exempt-procedure-list mechanism let fee-charging accounts be drained: anyone could call an exempt procedure without a signature, but the account still paid the transaction fee. The team decided to remove the component rather than fix it now (see issue discussion). The plain AuthSingleSig component (every call requires a signature) remains available and now backs the "singlesig user faucet" factories. Closes #3360 * fix: revert unnecessary comment change in BurnNote conversion Per review feedback: the struct-level doc comment already covers the network-execution caveat; the internal conversion comment didn't need the same rewording. --------- Co-authored-by: Claude (Opus) <noreply@anthropic.com>
* fix: restrict indexed input note asset removal * refactor: share indexed input note removal guard * test: make malicious input note theft regression explicit * fix: require native account context for indexed input note asset removal The account-origin check resolves the caller against the *active* account, so the gate alone was bypassable: a malicious note script could route the indexed removal through an attacker-controlled foreign account via FPI, where that foreign account is active and vouches for its own procedures. The full #3445 drain still worked end to end against a standard wallet. Add exec.memory::assert_native_account to the guard, which closes that path while leaving the one legitimate by-index caller intact (the fee manager collects sponsorship note assets from the native account's auth procedure). Tests: a note-script-via-FPI regression test, and an explicit test that transaction scripts are rejected too - the latter pins a behavior change that was previously only implied by a deleted test. --------- Co-authored-by: Claude (Opus) <noreply@anthropic.com> Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* feat: add miden-build-utils crate * feat: remove copy_directory helper * feat: more build-utils * feat: remove TransactionScript and NoteScript constructor from Program * feat: remove unused helpers * feat: refactors * revert: remove Program constructors * chore: changelog * chore: remove leftover changes * refactor: assemble utils * review: move regex into LazyLock * fix: cargo shear * review: address comments * review: address remaining comments * fix: changelog merge * feat: add publish logic to read masp file from OUT_DIR * refactor: inline code --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* refactor min burn amount comment * changelog * Update CHANGELOG.md Co-authored-by: zeapoz <zeapo@pm.me> --------- Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com> Co-authored-by: zeapoz <zeapo@pm.me>
* feat: assemble `ExpirationTransactionScript` on build-time * feat: move script to library procedure inside the standards package * chore: changelog * feat: add `SendNotesTransactionScript` to standards package * chore: changelog * feat: add tx_script() accessor * chore: comments * chore: tests * chore: fmt * feat: factor out common masm code * feat: comments; masm signatures * feat: add tests * review: address comments * review: address nits and tests * feat: address more comments * review: address comments * chore: update comments * review: make common module private * review: improve comments * review: validate asset composition * review: add `add_existing_non_fungible_faucet` to mockchain builder helper * review: remove `validate_note_records` costly validation * review: keep note idx and read ptr on stack * review: add cross-check with asset composition to pick script --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* chore: fix fresh build * change version to rc1 * regenerate cost tables --------- Co-authored-by: Marti <marti@miden.team>
…3471) * fix(tx): gate only signature production outside the auth procedure * changelog * fix in_auth_procedure: bool comment * remove auth request probe component
* chore: reject unbounded signatures in tx event * chore: add changelog * chore: use multiple assertions * fix: changelog entry
… note (#3469) * fix pswap.masm * add regression tests * test: cover a pswap note-fill payback created behind a remainder note * rename tests * changelog * clean tests * simplify tests * Update crates/miden-testing/tests/scripts/pswap.rs --------- Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>
The v0.16.0-rc.1 release aborted mid-publish with: 403 Forbidden: Trusted Publishing tokens do not support creating new crates. Publish the crate manually, first `miden-protocol-build-utils` was added to the workspace and had never been published, and crates.io does not let an OIDC token create a new crate name. `cargo publish --dry-run` never contacts the registry to reserve a name, so nothing caught this until the tagged release had already been cut. Add scripts/check-crates-published.sh, which enumerates publishable workspace members via `cargo metadata` and checks each name against the crates.io sparse index. It runs in the publish job, ahead of the token mint - the check needs no credential, and a slow registry would otherwise eat into the token's short lifetime. A release that would abort partway now stops before publishing anything, with an error naming the manual-claim and Trusted Publishing setup needed to fix it. The remediation is explicit that the claim must happen at a version strictly below the upcoming release, from a placeholder outside this workspace. Claiming the name at the version about to be released is what turned this incident's retry into "crate miden-protocol-build-utils@0.16.0-rc.1 already exists on crates.io index", and publishing from the workspace would need --allow-dirty, which bakes untracked files into a permanently public artifact. Scope is narrow and stated in the header: a hit proves the name is registered by someone, not that we own it, that Trusted Publishing is configured, or that the release version is free. Those still surface only at publish time, and the success message says so rather than reading as "the release will succeed". `cargo metadata` and the jq filter are captured into a variable rather than read through a process substitution, so a failed or truncated read cannot yield a partial crate list that silently passes. An unverifiable crate refuses to guess rather than passing. All eight publishable members currently resolve on the index, so this is safe to land as-is. Co-authored-by: Claude (Opus) <noreply@anthropic.com>
`cargo publish --workspace` verifies each member against a temporary local registry under target/package/tmp-registry, and cargo unpacks that registry's crates into ~/.cargo/registry/src keyed only by name and version. Extraction is skipped whenever the target directory already has a `.cargo-ok` marker, so a stale unpack is reused without ever being compared to the tarball. The registry cache key hashes only Cargo.lock, so a release branch and `next` sitting at the same version share it. The v0.16.0-rc.2 publish restored a cache saved minutes earlier by a `next` dry-run and verified the release branch's miden-tx against `next`'s miden-protocol, which failed with a missing-method error on a rename that had not been cherry-picked over. The clearing step already existed but was gated to dry-run mode. Drop the gate. Co-authored-by: Claude (Opus) <noreply@anthropic.com>
* fix missing invocation comments * changelog
* feat: unify account-origin authenticators in api.masm Merge the tracking and non-tracking `authenticate_*` procedures in the transaction kernel into a single `authenticate_account_origin` / `account::authenticate_procedure`, and gate `account_upgrade` with it (closing the follow-up noted in the issue). A kernel procedure call is tracked (via the was_called flag) only when the active account is native and the account's authentication procedure is not currently executing. The "auth in progress" condition is keyed on a new epilogue-controlled kernel-memory flag (set around the auth dyncall in `execute_auth_procedure`), NOT on the caller being the auth procedure (index 0). Keying on the flag rather than the caller index is required for safety: the epilogue's replay guard (ERR_EPILOGUE_AUTH_PROCEDURE_CALLED_FROM_WRONG_CONTEXT) detects an auth procedure invoked from user code by checking that was_called[0] is still 0 before it runs the auth procedure. That detection relies on the auth procedure's own kernel calls being tracked. An index-based exemption would suppress that tracking whenever the auth procedure runs - including when a note/tx script invokes it during the main phase - defeating the guard for any auth component that does not unconditionally increment the nonce (e.g. no_auth, network_account). The flag is only set during the epilogue's auth window, so a main-phase invocation is still tracked and the guard still fires. Since read-only introspection procedures are now tracked in the native context, this changes their was_procedure_called results; `account_upgrade` now panics when not invoked from the account context. Tests: - test_authenticate_procedure_conditional_tracking: tracking is suppressed while the auth-in-progress flag is set and applied otherwise. - test_non_incrementing_auth_procedure_called_from_wrong_context: an auth procedure that makes a gated call but never increments the nonce, invoked from a tx script, still trips the epilogue replay guard (fails under an index-based exemption, passes with the flag). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: address review comments - add a positive kernel test that successfully calls `native_account::upgrade` through an account procedure (mock account now exposes `upgrade`), alongside the negative wrong-context test - trim the verbose doc comments on the epilogue auth-in-progress flag, `authenticate_procedure`, `assert_auth_procedure`, and the epilogue guard back to concise versions - reword the `was_procedure_called` docs (kernel and protocol wrapper) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor: update doc comments and CHANGELOG, add a new skill file * test: address review comments on auth tests - merge `test_non_incrementing_auth_procedure_called_from_wrong_context` into `test_auth_procedure_called_from_wrong_context` via `rstest`, parameterizing the auth-proc body (incrementing vs non-incrementing) - replace the flag-toggling `test_authenticate_procedure_conditional_tracking` with a realistic end-to-end test: a procedure called from a tx script is tracked, one called from the auth procedure is not, both asserted in the auth procedure Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: small doc comment fix --------- Co-authored-by: Claude (Opus) <noreply@anthropic.com>
* state the NFT asset value model as a convention, not a guarantee * changelog --------- Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>
* fix: enforce asset-value preservation at the callback boundary * docs: link the asset-callback changelog entry to the issue * test: document what actually enforces callback value preservation Order the moved amounts as 200 then 100 to match the scenario described in issue #3442, and record that the executor's host-side note reconciliation already rejects this transaction today: `NOTE_BEFORE_ADD_ASSET_EVENT` is emitted before the callback runs, so the host keeps the pre-callback amounts and its output-notes commitment disagrees with the kernel's. That reconciliation is not proof-enforced, which is why the test asserts on the kernel error rather than on the commitment mismatch. * test: cover the account path of the callback value-preservation check Add a negative test where on_before_asset_added_to_account rewrites the added amount so that offsetting rewrites keep the aggregate vault totals intact. On this path there is no host-side backstop at all: ACCOUNT_VAULT_BEFORE_ADD_ASSET_EVENT is emitted after the callback with the processed value, so without the callback-boundary assertion the transaction would succeed end-to-end. Also note in the asset docs that the kernel enforces the existing requirement that the processed value equals the input value. * refactor: make callback stack overwrite explicit * fix: address callback value preservation review --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* chore: update miden-vm dependencies to v0.29 Bumps the `miden-vm` and `miden-crypto` workspace dependencies from v0.25 / v0.28.1 to v0.29, along with the `miden-core` version declared in the `miden-project.toml` MASM manifests, and adapts to the upstream API changes: - `CoreLibrary` now bundles a separate `miden-precompiles` package. Both the build-time package registries and the `TransactionMastStore` seed the pair via `CoreLibrary::packages()`; without the precompiles forest, dynamic calls into Falcon/Keccak wrappers fail to resolve at execution time. - The advice stack moved behind the typed `AdviceStack` API: `AdviceInputs`' stack field is private, `AdviceInputs::into_parts` returns three components, and `AdviceMutation::extend_stack` became `extend_advice_stack`. - `Kernel` was renamed to `KernelDescriptor`, `Package::to_kernel` to `to_kernel_descriptor`, and `Package::module_infos` to `module_descriptors`. - `miden_verifier::verify` now takes an `ExecutionClaim` and verifies bundled precompile proofs itself, replacing `verify_with_precompiles`. - `miden_core_lib::handlers::keccak256::KeccakPreimage` is gone; the agglayer tests compute digests through a local `keccak256_felts` helper. The ECDSA k256 encoded signature is now 32 felts (was 33). Falcon verification moved into a precompile, which cuts hasher rows dramatically, so the note consumption cost tables, `bench-tx.json`, and the committed trace-shape brackets are regenerated. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * chore: revert claude settings changes * chore: clean up advice provider instantiations * chore: minor rename * chore: address review comments * chore: fix core library loading --------- Co-authored-by: Claude (Opus) <noreply@anthropic.com>
…3495) * refactor(standards): drop `components` prefix from `NAME` constants * chore: add changelog --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
… depth (#3470) * fix(standards): return the call-invoked getters at the required stack depth * changelog * apply suggestions --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* feat(standards): add the MinBurnAmountConfig note * test(testing): cover the MinBurnAmountConfig note * changelog * address review comments
* feat(standards): seed RBAC delegated admins at construction Replace `RoleBasedAccessControl::new` with a `bon` builder over `RoleSeed`s. A seed carries a role's members and its delegated admin, so the role config word is seeded as `[member_count, admin_role_symbol, 0, 0]` instead of always leaving the admin unset. Exclusive delegation is therefore established at account creation rather than through a sequence of on-chain `set_role_admin` calls during which `ADMIN` still administers the role. The builder's `build()` rejects duplicate role seeds, seeds that carry neither members nor a delegated admin, member counts exceeding `u32::MAX`, and seeds whose effective admin chain never reaches a populated role, which would leave the role permanently unmanageable. The last check covers the default admin too: seeding an operational role without seeding `ADMIN` freezes it just as a dead explicit delegation does, since `ADMIN` administers itself. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * chore: rename RoleSeed to RoleConfig * chore: simplified BridgeRoles * chore: minor renaming --------- Co-authored-by: Claude (Opus) <noreply@anthropic.com> Co-authored-by: Bobbin Threadbare <bobbinth@protonmail.com> Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
…3508) * feat(protocol): add native_account::is_issuer_of * fix(standards): exempt the issuing faucet from its own transfer list * test(standards): cover the issuer exemption in the transfer list suites * changelog * refactor(standards): inline the issuer check into the transfer policies * test(standards): drive the transfer-policy mint tests through MintNote * docs: move the changelog entry into the v0.16.0 section
bobbinth
marked this pull request as ready for review
August 7, 2026 00:41
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
This is a tracking PR for v0.16.0 release.