Conversation
* refactor: address remaining #3204 comments (standards module moves) Carries the #3204 follow-up cleanup on top of the unified authenticator: - [BREAKING] move the `note_tag` MASM module to `miden::standards::note::note_tag` - [BREAKING] move the `note_creator` component to the `utils` namespace and the Rust `NoteCreator` type to `account::note_creator` - re-export `create_note` from the basic-wallet interface - standardize the panic-condition wording in the kernel/protocol MASM doc comments and update the affected import sites and docs The authenticator doc comments in api.masm / native_account.masm and the CHANGELOG entry are kept consistent with the flag-based tracking design from the parent commit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: small comment fixes * chore: re-trigger CI --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ency switch (#3520) * test(standards): pin the freeze-only actor asymmetry under RBAC * docs(standards): document the freeze-only actor pattern on Authority * changelog
* refactor: remove asset value from callback outputs * test: preserve callback value regression coverage * test: restore account callback value regression * Apply suggestions from code review * refactor: make callback wrappers consume inputs * docs: preserve callback changelog history --------- Co-authored-by: Philipp Gackstatter <18741416+PhilippGackstatter@users.noreply.github.com>
Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
Co-authored-by: UfukNode <208284577+UfukNode@users.noreply.github.com>
…dings (#3463) The security/code-reviewer agents sometimes clear a section with prose like "None. I specifically tried and failed to break the following:" followed by bullets documenting what was ruled out. `_count_blocking_findings` only recognized an exact `- None.` bullet as an absence marker, so those diligence bullets were counted as real findings, producing a false "N blocking finding(s)" verdict even though the reviewer intended CLEAN. Require a blocking section's first content line to open with "None"/"N/A" (bare, bolded, or with a period-terminated explanation on the same line, but not a real finding like "None of the callers..." - there's no "." or end-of-line right after "None" there); once matched, the rest of the section is ignored. A stray absence marker anywhere else only skips itself, so a real finding followed by a later "- None." isn't double-counted. This is fail-open for the narrow case of a "None." opener genuinely followed by real findings. Both prompts already require the response to open with a `BLOCK:`/`CLEAN:`/`APPROVE:` token (tolerant of markdown bold around it, and found by searching the preamble before the review body starts rather than strictly at byte 0 - a model occasionally writes a sentence or two before the token line even when told to lead with it, which happened for real during this change's own review); use it as a simple backstop - missing it is malformed output (blocks), and a self-reported BLOCK overrides a structured count of 0. A structured count still always wins over a self-reported CLEAN, so the agent can't talk its way past a real finding. Update both reviewer prompts: put the leading token directly into the Output Format template (as a placeholder, not a literal example that could get echoed as a real verdict) so it isn't just a trailing instruction the agent might drift from, align code-reviewer's verdict vocabulary with the token vocabulary (APPROVE/BLOCK instead of APPROVE/REQUEST CHANGES), and state the Empty Sections rule as one unambiguous sentence in both directions in both files. Co-authored-by: Claude (Opus) <noreply@anthropic.com>
…ezing role management (#3476) * fix(standards): prevent role delegation to a dead admin role from freezing role management * changelog * fix comment * remove redundant comments * apply suggestions
…es (#3501) * refactor(protocol): move shared input note helpers into private modules * chore: update changelog PR link * chore: address review comments * Apply suggestions from code review Co-authored-by: Marti <marcin.gorny.94@protonmail.com> --------- Co-authored-by: Marti <marti@miden.team> Co-authored-by: Marti <marcin.gorny.94@protonmail.com>
…oc to indexed-note path (#3542) The Panics doc for remove_asset_raw and remove_all_assets_raw stated unconditionally that calling outside the native account's context panics. That only holds for the indexed-note path (is_active_note is false); the active-note path used by active_note::remove_asset / remove_all_assets is exempt, per the kernel's own doc for the underlying procs (api.masm input_note_remove_asset / input_note_remove_all_assets). Co-authored-by: Claude (Opus) <noreply@anthropic.com>
* feat: track generic assets in `AccountVaultDelta` * chore: add changelog * chore: address review comments * chore: move changelog entry to 0.17
* feat(agglayer): configure priced fee policies at deployment * docs: document AggLayer constant fee policies * refactor(agglayer): add fee policy account builders * refactor(agglayer): streamline fee policy builders * test(agglayer): clarify fee manager names * refactor(agglayer): simplify testing helper imports * test(agglayer): cover bridge flows with fees enabled * refactor(tests): unify AggLayer fee policy setup * fix: address fee policy deployment review Make the fee policy manager a required argument of the AggLayer account builders instead of an optional setter whose absence panicked in `build()`, and expose the faucet's asset callback flag on the builder. The bridge-in claim-to-P2ID test regained the callback-enabled faucet it lost when it moved to the priced helper, and the bridge-out test keeps pinning all 32 bundled Solidity MTF vectors. * feat(agglayer): make deployed fee schedules repricable Both AggLayer network accounts install the ConstantFeeManager and allowlist CONSTANT_FEE_POLICY_CONFIG notes, so their ADMIN role can reprice a schedule that was otherwise frozen at deployment. The bridge sizes the sponsorship of every MINT and BURN note it creates from the faucet's schedule, so leaving the faucet frozen would stall bridging once the chain's verification base fee moved. The faucet moves from Authority::OwnerControlled to RbacControlled to make that reachable at all: with the bridge as its Ownable2Step owner, every authority-gated procedure was gated on a sender nothing can produce. Minting and burning are unaffected, since MintOwnerOnly and BurnOwnerOnly check the owner slot directly rather than going through Authority. The config note is scheduled free rather than at its benchmarked cost. Consuming one is the only route to set_note_fee, so pricing it would let the schedule put the note that repairs it out of reach. * docs(agglayer): specify fee schedule administration Documents what the fee policy work changed: the deployed schedules and how they are repriced, the faucet's move to RBAC and the resulting split between owner-gated minting and ADMIN-gated configuration, and the CONSTANT_FEE_POLICY_CONFIG note. Also records the operational consequence of a priced schedule that was previously undocumented: a note with a non-zero schedule entry can only be consumed alongside FEE_SPONSORSHIP notes covering it, regardless of the chain's own base fee, so every management note needs a sponsorship funded with it. Pins the faucet allowlist the way the bridge's already was, and covers repricing a paused bridge. * docs(agglayer): reword the SPEC term flagged by the spellchecker * chore: condense the AggLayer fee policy changelog entries * refactor(tests): deduplicate AggLayer fee-enabled test plumbing Adds a find_output_note helper for the six copies of the output-note-by-script-root predicate, returns Option<Note> from add_fee_sponsorship so the fee axis stops being threaded through if/else blocks, and uses the existing authenticated_input_notes iterator overload to restore the builder chains. The priced-account pin test now reuses build_managed_account instead of rebuilding the same two fixtures verbatim. * Update CHANGELOG.md Co-authored-by: zeapoz <zeapo@pm.me> * refactor(agglayer): return AccountBuilder from the account builder helpers Address review feedback on the deployment builder API: - drop the AggLayerBridgeAccountBuilder and AggLayerFaucetAccountBuilder wrappers; AggLayerBridge::account_builder and AggLayerFaucet::account_builder now return the underlying AccountBuilder directly - move the test-only helpers (zero_fee_policy_manager, faucet_account_builder, create_existing_agglayer_faucet) into miden_agglayer::testing * refactor(agglayer): rename the note-set accessors Address review feedback on the note-set naming: the former fee_policy_notes returned the full set of notes the account actually accepts, so it becomes allowed_notes, and the component-specific subsets become bridge_notes and faucet_notes. Record the rename in the changelog and move this PR's entries back under the unreleased v0.17.0 section, where the released v0.16.0 section had absorbed them during the merge from next. * refactor(agglayer): collapse the note-set accessors into allowed_notes AuthNetworkAccount::new already extends any allowlist it is given with the default network-account notes, so passing the full set to the builder is idempotent and the bridge_notes/faucet_notes split served no purpose. * refactor(agglayer): inline the account builders and drop the one-shot constructors AggLayerBridge::account_builder and AggLayerFaucet::account_builder now hold the building logic directly; the faucet builder takes the initial supply so test fixtures no longer need a separate pass-through, and the unused create_bridge_account / create_agglayer_faucet wrappers are gone. * docs(agglayer): explain the zero-priced fee config note and flag #2724 The zero schedule entry only forgoes enforced reimbursement: a voluntary sponsorship still funds a repricing transaction, and the pricer still computes the config note's real cost. Also document the price-then-allowlist ordering for new roots and mark the faucet ownership-rotation question as tracked by #2724. * test(agglayer): prove a sponsored repricing note reimburses the bridge * docs(agglayer): correct the faucet ownership claim - transfer is owner-gated The SPEC and builder docs claimed the faucet ADMIN can retarget the Ownable2Step owner. It cannot: transfer_ownership asserts the note sender is the current owner (the bridge), never consulting Authority, and the bridge has no flow that authors such a note. Rotation stays unreachable; #2724 tracks removing the dead procedures. * docs(agglayer): simplify the fee policy wording * docs(agglayer): note that a priced-in margin delays repricing * docs(agglayer): quantify the default pricing margin The default NetworkNotePricer margin is one extra verification cycle, roughly 6% of the fee, so a schedule built with it is not far from needing a reprice when the base fee rises. * docs(agglayer): document the bridge-faucet schedule coupling The bridge funds MINT/BURN sponsorships sized by the faucet's schedule and is reimbursed via its own CLAIM/B2AGG prices, so faucet repricing must be matched on the bridge. Nothing enforces this; it is an operator rule. * docs(agglayer): correct the schedule-coupling consequence A faucet entry repriced past the bridge's own CLAIM/B2AGG entry does not merely drain the vault: the AtMostCollectedFees assertion aborts every claim and bridge-out. Also document the bridge-first repricing order and that the bridge's CLAIM/B2AGG entries must never be zeroed. * docs(agglayer): state the schedule-coupling invariant instead of one order Bridge-first repricing is only safe upward; the invariant is that the bridge's CLAIM/B2AGG entries never sit below the faucet's MINT/BURN entries, so raise the bridge first and lower the faucet first. Zeroing the bridge entries halts claims outright rather than draining. * docs(agglayer): state the full schedule-coupling rule The solvency rule includes the bridge's own consumption fee, which is what NetworkNotePricer deploys, applies to every registered faucet, and holds during registration as well as repricing. Also note that raising an entry strands in-flight notes until a top-up sponsorship is added. * docs(agglayer): trim fee administration spec * fix(fees): price config notes without losing recovery * docs(fees): correct the repricing recovery story Drop the zero-reset claim and state the real sender-side constraint: standard auth components size a config note's sponsorship from the target's pre-transaction estimate (fee::pay_fee), so recovering from an excessively high entry requires fronting the previous fee, and an entry no sender can fund freezes fee administration. Also generalize the charged-the-new-value rule to every note of a repriced root and note that raising a fee leaves already-created notes under-sponsored until an extra FEE_SPONSORSHIP tops them up. * fix(agglayer): drop the unused allow_all burn policy from the faucet Registering BurnAllowAll as an allowed policy let the ADMIN role open burns in two steps under Authority::RbacControlled: widen the note allowlist with FAUCET_POLICY_CONFIG, then activate the registered policy. No AggLayer flow opens burns - bridge-out burns through the owner-gated receive_and_burn - so remove the registration and the redundant explicit component instead of documenting the escalation. The faucet code commitment changes. * chore: condense the AggLayer changelog, state the faucet ADMIN rotation limit One changelog entry for the whole PR. The SPEC trust model and the faucet builder docs now state that the faucet does not allowlist RBAC_CONFIG: its ADMIN cannot be rotated directly, and losing the key freezes the faucet's authority-gated configuration. * chore(agglayer): tidy the fee test fixtures and docs Use the mock chain's native fee faucet in the zero-fee fixture, record why the priced fixtures cannot move next to the zero-fee ones, drop a stale doc reference to a deleted scenario, and add the missing section header in fee_policy.rs. * test(agglayer): pin the output-note counts in the fee-enabled E2E cases find_output_note returns the first match by script root, so nothing pinned the total note count after the assertions were relaxed. Assert the exact per-case counts (feature note alone fee-free; plus the FEE_SPONSORSHIP and TX_FEE notes fee-enabled) so a stray extra note fails loudly. * docs(agglayer): note the inert FEE_SPONSORSHIP schedule entry Fee collection prices sponsorship notes at zero without consulting the policy, so the scheduled FEE_SPONSORSHIP entry is never read; it exists only to keep the schedule covering the whole allowlist. * docs(agglayer): tighten the fee administration and faucet ADMIN caveats The full mechanics live in the CONSTANT_FEE_POLICY_CONFIG note rustdoc; the SPEC states the outcomes and points there. * docs(fees): compress the config-note operational notes * docs(agglayer): rewrap the faucet allowlist doc paragraph * Update crates/miden-agglayer/src/lib.rs Co-authored-by: Marti <marti@miden.team> * Update crates/miden-agglayer/src/lib.rs Co-authored-by: Marti <marti@miden.team> * fix(fees): drop the sponsorship note from constant fee schedules A fee schedule maps a note script root to the price charged for consuming it. A FEE_SPONSORSHIP note funds those prices rather than carrying one, and fee collection never consults the policy for it: collect_sponsored_fees records a required fee of zero for a sponsorship input, and is_network_note keys off the NetworkAccountTarget attachment, which a sponsorship note never carries. Unifying the AggLayer note-set accessors pulled the root into the schedule as a side effect. Express the rule once as FeeSponsorshipNote::feature_notes and price only those. * docs(agglayer): disambiguate ADMIN and trim SPEC change narration Each faucet installs its own role set, so both accounts have a built-in ADMIN. State that once in the administration section and qualify the ambiguous uses. Drop the config-note text that narrated how pricing changed during review in favour of what the design does now. * docs(agglayer): restore the AuthNetworkAccount link definition The applied review suggestion removed the link-reference definition along with the paragraph above it, breaking cargo doc under -D warnings. * chore: trim the AggLayer changelog entry * docs(agglayer): say the bridge accepts three other standard notes * docs(agglayer): plainer wording in the allowlist and builder docs Say the bridge accepts three other standard notes rather than opting into standards notes, and allowed rather than sanctioned input notes. Reword the faucet's sponsorship-sizing note into two plain sentences. Drop the prose and inline comments restating that AuthNetworkAccount adds its own defaults, and the orphaned link definitions they leave behind. * docs(fees): simplify the config note's operational notes Drop the redundant RBAC comment in build.rs, which the component-order comment below it already covers. * docs(agglayer): drop the duplicate issue link from the trust model table * docs(agglayer): name the components the faucet shares with the bridge * chore: move the AggLayer entry to the v0.16.0 changelog section * refactor(tx): drop the AggLayer fee policy helpers from NetworkNotePricer Callers pass the account's allowed_notes to basic_constant_fee_policy_manager directly, keeping the pricer agnostic about account types. * refactor(agglayer): clean up bridge note pricing --------- Co-authored-by: zeapoz <zeapo@pm.me> Co-authored-by: Marti <marti@miden.team>
…3581) * feat(agglayer): configure priced fee policies at deployment * docs: document AggLayer constant fee policies * refactor(agglayer): add fee policy account builders * refactor(agglayer): streamline fee policy builders * test(agglayer): clarify fee manager names * refactor(agglayer): simplify testing helper imports * test(agglayer): cover bridge flows with fees enabled * refactor(tests): unify AggLayer fee policy setup * fix: address fee policy deployment review Make the fee policy manager a required argument of the AggLayer account builders instead of an optional setter whose absence panicked in `build()`, and expose the faucet's asset callback flag on the builder. The bridge-in claim-to-P2ID test regained the callback-enabled faucet it lost when it moved to the priced helper, and the bridge-out test keeps pinning all 32 bundled Solidity MTF vectors. * feat(agglayer): make deployed fee schedules repricable Both AggLayer network accounts install the ConstantFeeManager and allowlist CONSTANT_FEE_POLICY_CONFIG notes, so their ADMIN role can reprice a schedule that was otherwise frozen at deployment. The bridge sizes the sponsorship of every MINT and BURN note it creates from the faucet's schedule, so leaving the faucet frozen would stall bridging once the chain's verification base fee moved. The faucet moves from Authority::OwnerControlled to RbacControlled to make that reachable at all: with the bridge as its Ownable2Step owner, every authority-gated procedure was gated on a sender nothing can produce. Minting and burning are unaffected, since MintOwnerOnly and BurnOwnerOnly check the owner slot directly rather than going through Authority. The config note is scheduled free rather than at its benchmarked cost. Consuming one is the only route to set_note_fee, so pricing it would let the schedule put the note that repairs it out of reach. * docs(agglayer): specify fee schedule administration Documents what the fee policy work changed: the deployed schedules and how they are repriced, the faucet's move to RBAC and the resulting split between owner-gated minting and ADMIN-gated configuration, and the CONSTANT_FEE_POLICY_CONFIG note. Also records the operational consequence of a priced schedule that was previously undocumented: a note with a non-zero schedule entry can only be consumed alongside FEE_SPONSORSHIP notes covering it, regardless of the chain's own base fee, so every management note needs a sponsorship funded with it. Pins the faucet allowlist the way the bridge's already was, and covers repricing a paused bridge. * docs(agglayer): reword the SPEC term flagged by the spellchecker * chore: condense the AggLayer fee policy changelog entries * refactor(tests): deduplicate AggLayer fee-enabled test plumbing Adds a find_output_note helper for the six copies of the output-note-by-script-root predicate, returns Option<Note> from add_fee_sponsorship so the fee axis stops being threaded through if/else blocks, and uses the existing authenticated_input_notes iterator overload to restore the builder chains. The priced-account pin test now reuses build_managed_account instead of rebuilding the same two fixtures verbatim. * Update CHANGELOG.md * refactor(agglayer): return AccountBuilder from the account builder helpers Address review feedback on the deployment builder API: - drop the AggLayerBridgeAccountBuilder and AggLayerFaucetAccountBuilder wrappers; AggLayerBridge::account_builder and AggLayerFaucet::account_builder now return the underlying AccountBuilder directly - move the test-only helpers (zero_fee_policy_manager, faucet_account_builder, create_existing_agglayer_faucet) into miden_agglayer::testing * refactor(agglayer): rename the note-set accessors Address review feedback on the note-set naming: the former fee_policy_notes returned the full set of notes the account actually accepts, so it becomes allowed_notes, and the component-specific subsets become bridge_notes and faucet_notes. Record the rename in the changelog and move this PR's entries back under the unreleased v0.17.0 section, where the released v0.16.0 section had absorbed them during the merge from next. * refactor(agglayer): collapse the note-set accessors into allowed_notes AuthNetworkAccount::new already extends any allowlist it is given with the default network-account notes, so passing the full set to the builder is idempotent and the bridge_notes/faucet_notes split served no purpose. * refactor(agglayer): inline the account builders and drop the one-shot constructors AggLayerBridge::account_builder and AggLayerFaucet::account_builder now hold the building logic directly; the faucet builder takes the initial supply so test fixtures no longer need a separate pass-through, and the unused create_bridge_account / create_agglayer_faucet wrappers are gone. * docs(agglayer): explain the zero-priced fee config note and flag #2724 The zero schedule entry only forgoes enforced reimbursement: a voluntary sponsorship still funds a repricing transaction, and the pricer still computes the config note's real cost. Also document the price-then-allowlist ordering for new roots and mark the faucet ownership-rotation question as tracked by #2724. * test(agglayer): prove a sponsored repricing note reimburses the bridge * docs(agglayer): correct the faucet ownership claim - transfer is owner-gated The SPEC and builder docs claimed the faucet ADMIN can retarget the Ownable2Step owner. It cannot: transfer_ownership asserts the note sender is the current owner (the bridge), never consulting Authority, and the bridge has no flow that authors such a note. Rotation stays unreachable; #2724 tracks removing the dead procedures. * docs(agglayer): simplify the fee policy wording * docs(agglayer): note that a priced-in margin delays repricing * docs(agglayer): quantify the default pricing margin The default NetworkNotePricer margin is one extra verification cycle, roughly 6% of the fee, so a schedule built with it is not far from needing a reprice when the base fee rises. * docs(agglayer): document the bridge-faucet schedule coupling The bridge funds MINT/BURN sponsorships sized by the faucet's schedule and is reimbursed via its own CLAIM/B2AGG prices, so faucet repricing must be matched on the bridge. Nothing enforces this; it is an operator rule. * docs(agglayer): correct the schedule-coupling consequence A faucet entry repriced past the bridge's own CLAIM/B2AGG entry does not merely drain the vault: the AtMostCollectedFees assertion aborts every claim and bridge-out. Also document the bridge-first repricing order and that the bridge's CLAIM/B2AGG entries must never be zeroed. * docs(agglayer): state the schedule-coupling invariant instead of one order Bridge-first repricing is only safe upward; the invariant is that the bridge's CLAIM/B2AGG entries never sit below the faucet's MINT/BURN entries, so raise the bridge first and lower the faucet first. Zeroing the bridge entries halts claims outright rather than draining. * docs(agglayer): state the full schedule-coupling rule The solvency rule includes the bridge's own consumption fee, which is what NetworkNotePricer deploys, applies to every registered faucet, and holds during registration as well as repricing. Also note that raising an entry strands in-flight notes until a top-up sponsorship is added. * docs(agglayer): trim fee administration spec * fix(fees): price config notes without losing recovery * docs(fees): correct the repricing recovery story Drop the zero-reset claim and state the real sender-side constraint: standard auth components size a config note's sponsorship from the target's pre-transaction estimate (fee::pay_fee), so recovering from an excessively high entry requires fronting the previous fee, and an entry no sender can fund freezes fee administration. Also generalize the charged-the-new-value rule to every note of a repriced root and note that raising a fee leaves already-created notes under-sponsored until an extra FEE_SPONSORSHIP tops them up. * fix(agglayer): drop the unused allow_all burn policy from the faucet Registering BurnAllowAll as an allowed policy let the ADMIN role open burns in two steps under Authority::RbacControlled: widen the note allowlist with FAUCET_POLICY_CONFIG, then activate the registered policy. No AggLayer flow opens burns - bridge-out burns through the owner-gated receive_and_burn - so remove the registration and the redundant explicit component instead of documenting the escalation. The faucet code commitment changes. * chore: condense the AggLayer changelog, state the faucet ADMIN rotation limit One changelog entry for the whole PR. The SPEC trust model and the faucet builder docs now state that the faucet does not allowlist RBAC_CONFIG: its ADMIN cannot be rotated directly, and losing the key freezes the faucet's authority-gated configuration. * chore(agglayer): tidy the fee test fixtures and docs Use the mock chain's native fee faucet in the zero-fee fixture, record why the priced fixtures cannot move next to the zero-fee ones, drop a stale doc reference to a deleted scenario, and add the missing section header in fee_policy.rs. * test(agglayer): pin the output-note counts in the fee-enabled E2E cases find_output_note returns the first match by script root, so nothing pinned the total note count after the assertions were relaxed. Assert the exact per-case counts (feature note alone fee-free; plus the FEE_SPONSORSHIP and TX_FEE notes fee-enabled) so a stray extra note fails loudly. * docs(agglayer): note the inert FEE_SPONSORSHIP schedule entry Fee collection prices sponsorship notes at zero without consulting the policy, so the scheduled FEE_SPONSORSHIP entry is never read; it exists only to keep the schedule covering the whole allowlist. * docs(agglayer): tighten the fee administration and faucet ADMIN caveats The full mechanics live in the CONSTANT_FEE_POLICY_CONFIG note rustdoc; the SPEC states the outcomes and points there. * docs(fees): compress the config-note operational notes * docs(agglayer): rewrap the faucet allowlist doc paragraph * Update crates/miden-agglayer/src/lib.rs * Update crates/miden-agglayer/src/lib.rs * fix(fees): drop the sponsorship note from constant fee schedules A fee schedule maps a note script root to the price charged for consuming it. A FEE_SPONSORSHIP note funds those prices rather than carrying one, and fee collection never consults the policy for it: collect_sponsored_fees records a required fee of zero for a sponsorship input, and is_network_note keys off the NetworkAccountTarget attachment, which a sponsorship note never carries. Unifying the AggLayer note-set accessors pulled the root into the schedule as a side effect. Express the rule once as FeeSponsorshipNote::feature_notes and price only those. * docs(agglayer): disambiguate ADMIN and trim SPEC change narration Each faucet installs its own role set, so both accounts have a built-in ADMIN. State that once in the administration section and qualify the ambiguous uses. Drop the config-note text that narrated how pricing changed during review in favour of what the design does now. * docs(agglayer): restore the AuthNetworkAccount link definition The applied review suggestion removed the link-reference definition along with the paragraph above it, breaking cargo doc under -D warnings. * chore: trim the AggLayer changelog entry * docs(agglayer): say the bridge accepts three other standard notes * docs(agglayer): plainer wording in the allowlist and builder docs Say the bridge accepts three other standard notes rather than opting into standards notes, and allowed rather than sanctioned input notes. Reword the faucet's sponsorship-sizing note into two plain sentences. Drop the prose and inline comments restating that AuthNetworkAccount adds its own defaults, and the orphaned link definitions they leave behind. * docs(fees): simplify the config note's operational notes Drop the redundant RBAC comment in build.rs, which the component-order comment below it already covers. * docs(agglayer): drop the duplicate issue link from the trust model table * docs(agglayer): name the components the faucet shares with the bridge * chore: move the AggLayer entry to the v0.16.0 changelog section * refactor(tx): drop the AggLayer fee policy helpers from NetworkNotePricer Callers pass the account's allowed_notes to basic_constant_fee_policy_manager directly, keeping the pricer agnostic about account types. * refactor(agglayer): clean up bridge note pricing --------- Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com> Co-authored-by: zeapoz <zeapo@pm.me>
…3576) * chore: rename value_into_amount API for consistency * chore: add changelog * chore: structure the changelog
* fix(protocol): validate private note attachments * test(protocol): clarify attachment mismatch assertions * test(protocol): simplify mismatch assertions
* refactor(agglayer): construct fee policy managers internally * chore: link AggLayer changelog to follow-up PR * refactor(agglayer): inline fee policy manager construction
…a single constructor (#3548) * refactor(protocol): consolidate `MastForestScript` instantation into a single constructor * chore: update builder methods to use `mut self` --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* fix: assert procedure belongs to foreign account * chore: add changelog * Apply suggestions from code review Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com> --------- Co-authored-by: Marti <marti@miden.team> Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>
…es (#3500) * document AuthControlled in authority-gated config notes * changelog * apply suggestions --------- Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* feat: sort account procedures at construction * chore: add changelog * chore: address review comments * chore: bring back proc count validation in proc builder
…3567) * feat: validate proc uniqueness and sorting in tx kernel * chore: add changelog * chore: address review comments
* feat(miden-tx): let NetworkNotePricer take supplied note costs The pricer's cost lookup was hard-wired to the standard and agglayer tables, so an account with note families outside those tables — or with table-known script roots that measure differently on its own code — had to re-implement the pricing formula. The builder now accepts note_costs, a map consulted before the built-in tables, and the private test-only lookup hook is folded into it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: changelog entry for the pricer note-cost map Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(changelog): deduplicate the v0.16.0 section The changelog commit had inserted a second `## v0.16.0` header along with entries belonging to other PRs, splitting the release notes into two v0.16.0 sections. Keep the single existing section and add only this PR's `note_costs` entry to its Features list. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(miden-tx): let note costs be supplied individually or as an iterator Switch `note_costs` to a `#[builder(field)]` and expose `note_cost` (single entry) and `note_costs` (iterator) builder extensions, following the SwapNote builder pattern, so callers can set costs one at a time as well as in bulk. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude (Opus) <noreply@anthropic.com>
Bump the workspace version 0.16.0-rc.4 -> 0.16.0-rc.5 (workspace.package and the path-dependency pins), refresh Cargo.lock, and date the v0.16.0 changelog section. Co-authored-by: Claude (Opus) <noreply@anthropic.com>
…ture (#3617) * feat(agglayer): expose bridge storage readers outside the testing feature Production callers need these accessors to inspect GER registration, LET state, and hash chains without enabling the testing feature. Co-authored-by: Cursor <cursoragent@cursor.com> * chore: link the changelog entry to the pull request Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Claude (Opus) <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor: fee sponsorship note tryfrom * chore: changelog * fix: scope asset type * chore: simplify comment * chore: destructure inner struct * chore: simplify tests * chore: remove comment Co-authored-by: Marti <marti@miden.team> * chore: remove unnecessary comment Co-authored-by: Marti <marti@miden.team> --------- Co-authored-by: Marti <marti@miden.team>
* fix: reject multi-word PSWAP attachments in get_current_depth * changelog
* feat(protocol): add validated BatchAccountUpdate constructor * feat(protocol): add validated ProvenBatch constructor * feat(protocol): add validating constructor for BlockAccountUpdate * feat(protocol): add validated BlockBody constructor * feat(protocol): add BlockProof constructor * refactor(protocol): extract account detail validation * refactor(protocol): add explicit validator for BatchAccountUpdate and BlockAccountUpdate This allows ProvenBatch::new() and BlockBody::new() to avoid cloning account updates just to validate those. * fix(protocol): reject notes created and consumed in batch * fix(protocol): validate full-state block account updates * fix(protocol): validate merged batch account updates * refactor(protocol): restrict unchecked constructors * docs: add validated constructors changelog entry * fix: broken link in documentation * refactor: derive proven batch account update keys * fix(protocol): make validate methods non-public * fix(protocol): do not derive Default for BlockProof * fix(protocol): make ProvenBatch::new_unchecked() public * fix(protocol): validate transaction headers * fix(protocol): validate proven batch consistency * fix(protocol): suppress BlockProof default lint * fix(protocol/proven_batch): import instead of fully qualified type name * refactor(protocol/proven_batch): remove account update validation from constructor * fix(protocol): validate block body transaction notes * refactor(protocol): use storage patch builder in batch tests * fix(testing): keep private account state caller-owned * refactor(protocol/proven_batch): remove redundant checks from constructor * perf(protocol): avoid collecting batch account updates * fix(protocol): distinguish future note dependencies * refactor(protocol): add output note header accessor * refactor(protocol): trust validated block account updates * fix(protocol): report streamed account count as lower bound * docs(testing): clarify mock transaction account inputs * chore(protocol): add some newlines * refactor(protocol): remove constructor note aggregation * Update CHANGELOG.md Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com> --------- Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>
* fix(agglayer): allow faucet deregistration while paused * Update CHANGELOG.md Co-authored-by: zeapoz <zeapo@pm.me> --------- Co-authored-by: zeapoz <zeapo@pm.me>
* fix(standards): bound role symbol validation to a 4-bit exponent `role_symbol::validate_encoding` computed its `ALPHABET_LEN^(num_chars + 1)` upper bound with a bare `exp`, which the assembler lowers to a 64-row `EXPACC` sequence. Sixty-four bits do not pin down a field element: `e` and `e + Q` both fit, so a prover may decompose `e + Q`, pass the terminal-zero check, and land on `ALPHABET_LEN^(e + 1)` as the bound. That admits a role symbol carrying a character digit past the length it announces, which is exactly what the procedure exists to reject. The assertion above the exponentiation already caps `num_chars` at `MAX_LENGTH = 12`, so the exponent is at most 13 and four bits carry it. `exp.u4` commits exactly four rows, which makes the decomposition unique and costs 60 fewer cycles than the bare `exp`. Also covers the top of the bound's range: `ALPHABET_LEN^13 + 12` announces the longest encodable length while carrying a digit past it, so only the upper bound rejects it. The existing non-canonical cases are all caught by the length assertion instead, leaving the widest exponent untested. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bLUPBgD8T6Edt2141yrvQ * chore: point the changelog entry at this PR Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bLUPBgD8T6Edt2141yrvQ * chore: drop the explanatory comments from the diff The reasoning about the exponent width belongs in the PR description, not inline next to a one-token change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bLUPBgD8T6Edt2141yrvQ * chore: reword the changelog entry Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bLUPBgD8T6Edt2141yrvQ --------- Co-authored-by: Claude (Opus) <noreply@anthropic.com>
* fix(agglayer): preserve token registry ownership * test(agglayer): extract USDC fixtures * Update crates/miden-agglayer/asm/agglayer/bridge/bridge_config.masm Co-authored-by: Marti <marti@miden.team> * Update CHANGELOG.md Co-authored-by: Andrey Khmuro <andrey@polygon.technology> --------- Co-authored-by: Marti <marti@miden.team> Co-authored-by: Andrey Khmuro <andrey@polygon.technology>
* chore: bump Cargo version to 1.97 * chore: bump to 1.98 rather than 1.97 1.98 is the current stable (released 2026-08-20) and, like 1.97, carries the `cargo publish --workspace` deadlock fix from rust-lang/cargo#17071 that the release job needs. Going one release further adds the `chunks_exact_to_as_chunks` lint on top of the ones 1.97 reports, so `AccountStorageHeader::try_from_elements` and the attachment parser move to `as_chunks`. Both call sites already guard the length, so the behaviour is unchanged - and the array chunks make the fixed-width indexing that follows statically checked. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bLUPBgD8T6Edt2141yrvQ --------- Co-authored-by: Claude (Opus) <noreply@anthropic.com>
* fix(standards): assert the guardian is not an approver in the guarded multisig auth script * fix changelog entries * extract the approver public key read into a get_approver_pub_key helper Signed-off-by: onurinanc <e191322@metu.edu.tr> --------- Signed-off-by: onurinanc <e191322@metu.edu.tr> Co-authored-by: Marti <marti@miden.team>
* fix(standards): reject fee-only network account transactions * fix(standards): count output notes as network account actions * fix(standards): align network action check with kernel * fix(standards): preserve network sponsorship actions * fix(standards): preserve new network account nonce handling * refactor(standards): simplify network account effect check * chore(standards): rename network account helper section * Update CHANGELOG.md Co-authored-by: Andrey Khmuro <andrey@polygon.technology> * docs(standards): clarify network account auth docs --------- Co-authored-by: Andrey Khmuro <andrey@polygon.technology>
* chore: update Miden dependencies to 0.30.0 * fix: reject incomplete proofs before verification * chore: changelog * refactor: use upstream program executor * refactor: use advice stack iterator helper * refactor: simplify advice input updates * refactor: configure batch and block provers * fix: return transaction verification outcomes * fix: reject unsettled transaction proofs * fix: reject deferred batch deserialization * chore: deduplicate changelog * fix: use Poseidon2 prover defaults * fix: reject precompiles in batch and block proofs * chore: track precompile helper adoption * fix: name precompile proof errors * fix: validate proven proof states * fix: validate transaction precompile state
* fix(standards): bound the PSWAP lineage depth increment to u32 * fix(standards): validate the PSWAP attachment and drop the zero-depth assumption * test(standards): cover the PSWAP depth guards and relative lineage reconstruction * changelog * changelog * fix comments * fix comments
* fix(standards): reject non-public config notes * changelog * docs(standards): document the note type config note scripts accept * deduplicate comments * fix(standards): reject non-public config notes * fix comments * refactor(standards): move the config notes into note::config * docs(testing): trim the config note rejection test comments * changelog
* feat: add miden-objects crate with canonical Protobuf encodings * refactor(proto): reshuffle protobuf files * fix: add ExecutionProof wrapper * fix: add MastForest wrapper * fix: cargo shear * fix: extract generic PublicKey * fix: extract generic Signature * fix: remove redundant checks from conversion code * fix: fix conversion compile errors after rebase * chore: update CHANGELOG * fix: fix compile errors after rebase * chore: allow duplicate protobuf build dependencies * chore: remove schema tests * fix(objects): adapt conversions to validated constructors * refactor(objects): consolidate protobuf primitive types * test(objects): cover missing protobuf block numbers * refactor(objects): align protobuf messages with domain types * test(objects): cover block body conversion validation * fix(objects): make account conversions lossless * test(objects): cover invalid account nonce conversion * perf(account): expose ordered storage patch iteration * test(account): make storage patch order expectation explicit * fix(objects): address protobuf conversion clippy warnings * refactor(objects): align account witness protobuf with domain type * test(objects): decouple account witness error assertion * test(objects): remove redundant account witness fixture update * fix(objects): adapt block protobuf after rebase * feat(objects): version account header protobuf * feat(objects): version note metadata protobuf * feat(objects): version block header protobuf * feat(objects): add PartialSmt protobuf conversions * refactor(objects): clarify storage slot type conversion * refactor(objects): simplify protobuf decoding * fix(objects): complete protobuf type elision * test(objects): clarify invalid partial smt cases * refactor: clarify feature check package list * fix(objects): preserve note attachments error context * refactor(objects): clarify protobuf primitive variants * refactor(objects): structure protobuf asset identifiers * refactor(objects): align protobuf note transactions * fix(objects): remove redundant asset test clones * fix(objects): remove legacy protobuf asset schema * refactor(objects): add protobuf account versions * refactor(objects): flatten protobuf block version * refactor(objects): flatten protobuf note version * refactor(objects): add protobuf asset version * fix(objects): adapt partial SMT protobuf to miden-crypto 0.30 * fix(objects): update execution proof test fixtures * fix(objects): update partial SMT error assertions * style(objects): format partial SMT imports * fix(objects): preserve partial SMT depth boundaries * fix(objects): keep note type enum consistent with upstream type
* feat(protocol): expose transaction input protobuf parts * feat(objects): add account config protobufs * feat(objects): add transaction args protobufs * feat(objects): add transaction inputs protobuf * fix(protocol): satisfy transaction input lint * docs: add transaction inputs protobuf changelog * refactor(objects): clean up protobuf conversions * test(objects): clean up protobuf conversion tests * docs: correct transaction inputs changelog * fix: remove seen_ids in PartialVault::try_from_parts() * fix: invalid felt test * fix: use assert_matches! in tests * fix: clippy * Revert "fix: remove seen_ids in PartialVault::try_from_parts()" This reverts commit d934eb9. * fix(objects): update protobuf conversions for dependency changes * fix: VM upgrade compilation fixes --------- Co-authored-by: Codex (Opus) <noreply@anthropic.com>
* fix(standards): reject delay-only multisig procedure policies * changelog * fix comments --------- Co-authored-by: Marti <marti@miden.team>
* chore: keep MASM inline comments to what the code does Extends rule 6 of the masm-inline-comments skill: an inline comment is one line about what the next block does or which invariant it relies on, not design rationale, PR-review reasoning, or a justification of step ordering, which belong in the procedure's doc comment. Prompted by review on #3798, where such prose had to be trimmed by hand. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KkQzFtRjyDwQ7iVtRbsHsn * Apply suggestion from @zeapoz Co-authored-by: zeapoz <zeapo@pm.me> --------- Co-authored-by: Claude (Opus) <noreply@anthropic.com> Co-authored-by: zeapoz <zeapo@pm.me>
A reviewer rewrote the descriptions of the fee-stack port PRs, and later updates must build on those live bodies instead of re-amending the original drafts. The skill spells out the procedure: fetch the live text right before editing, treat every difference as a deliberate human edit, and make only targeted corrections that keep the person's structure and omissions. Claude-Session: https://claude.ai/code/session_01KkQzFtRjyDwQ7iVtRbsHsn Co-authored-by: Claude (Opus) <noreply@anthropic.com>
…#3748) * fix(standards): bound transfer policy dispatch to the reference block * test(standards): pin the dispatcher expiration limit on both transfer callbacks * docs(standards): describe the dispatcher expiration limit on transfer policies * changelog * remove redundant comments * test(standards): update transfer policy fixture callbacks * chore: update note cost tables --------- Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com> Co-authored-by: riemann <aleqvids@gmail.com>
* docs: clarify FPI expiration requirements * Update crates/miden-standards/asm/standards/expiration.masm * Update crates/miden-standards/src/account/policies/transfer/mod.rs Co-authored-by: Marti <marti@miden.team> * docs: address FPI expiration review comments --------- Co-authored-by: Marti <marti@miden.team>
* chore: update Miden VM dependencies to 0.32.0 * chore: use released Miden VM dependencies * chore: Changelog
#3808) * fix(standards): pin the fee payment to the native asset at par `fee::pay_fee` built the TX_FEE note from a caller-supplied conversion info word and paid `ceil(fee_amount * rate_num / rate_den)` of the named faucet's asset, checking neither the faucet nor the rate. Nothing downstream re-checks the fee note either - the transaction epilogue and the batch and block kernels contain no fee logic - so the authentication procedure is the only place the paid amount is decided, and any authorized transaction could move an arbitrary amount of an arbitrary fungible asset out of the vault as a fee. The conversion has nothing to convert: the computed fee is always denominated in the chain's single native fee asset (`ProtocolConfig`, verified against the reference block), and `verification_base_fee` is a per-network constant copied from the parent block, so there is no dynamic pricing either. Every production call site already commits `FeeConversionInfo::one_to_one`. `pay_fee` now asserts that the committed conversion info equals `native_conversion_info`, which pins the payment faucet and the rate together and makes the paid amount exactly the computed fee. `convert_amount` stays public and keeps its coverage, moved to direct invocation from a transaction script now that `pay_fee` only ever calls it at 1/1. Closes #3763. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0186Lb3N8KP4N75jFtWab3X6 * docs(standards): trim the fee comments Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0186Lb3N8KP4N75jFtWab3X6 * Apply batched suggestions from code review Co-authored-by: Marti <marcin.gorny.94@protonmail.com> --------- Co-authored-by: Claude (Opus) <noreply@anthropic.com> Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* let user fungible faucets hold the native fee asset * unit-test the user fungible faucet factories * prove a user faucet pays its own fee end to end * scope the network-faucet wallet note to steady state * drop the fee-asset tests and inline commentary * Apply suggestion from @mmagician --------- Co-authored-by: Marti <marti@miden.team>
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.17.0 release.