Skip to content

docs: clarify FPI expiration requirements - #3795

Open
partylikeits1983 wants to merge 4 commits into
nextfrom
docs/fpi-expiration-requirements
Open

docs: clarify FPI expiration requirements#3795
partylikeits1983 wants to merge 4 commits into
nextfrom
docs/fpi-expiration-requirements

Conversation

@partylikeits1983

Copy link
Copy Markdown
Contributor

Summary

  • add a dedicated transaction docs section explaining that FPI reads foreign state at the transaction reference block
  • document that FPI-callable procedures and asset callbacks reading mutable security state must set tx::update_expiration_block_delta
  • add the same guidance to asset callback docs, account component docs, and token policy docs

Closes #3480

@partylikeits1983
partylikeits1983 marked this pull request as draft September 2, 2026 13:09
Comment thread crates/miden-standards/asm/standards/expiration.masm Outdated
@partylikeits1983 partylikeits1983 added no changelog This PR does not require an entry in the `CHANGELOG.md` file documentation Improvements or additions to documentation labels Sep 2, 2026
@partylikeits1983 partylikeits1983 self-assigned this Sep 2, 2026
@partylikeits1983
partylikeits1983 marked this pull request as ready for review September 2, 2026 13:40
Comment thread crates/miden-standards/src/account/policies/transfer/mod.rs Outdated
Comment thread docs/src/account/components.md Outdated
Comment on lines +27 to +30
Account component procedures can become part of an account's public interface and can be called
from note scripts, transaction scripts, and foreign accounts through FPI. If such a procedure reads
mutable security state, it must call `tx::update_expiration_block_delta` in the execution path that
reads that state.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Claude has a tendency to introduce newlines to .md files, but IMO (and keeping in line with our current .md files) we should not artificially split lines here.
May be worth adding a skill that we don't need to respect the 100-char (or whatever) limit in .mds

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

true about claude, but this is not claude :)

Comment thread docs/src/account/components.md Outdated
Comment on lines +34 to +36
stale reads can change an authorization or pricing decision. The component owns the recency bound:
callers can choose an old reference block, so callers cannot be trusted to set the expiration
policy for the component.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The component owns the recency bound

I'd rather align the language with the terminology we already have, e.g. instead of "recency bound" we'd stick with the "expiration delta", or similar.

Also, "component owns" is not very clear - I think this is meant to say it defines or sets the expiration delta.

Comment on lines +36 to +37
//! staleness limit. Policies that only read immutable data, or for which stale data is acceptable,
//! do not need an expiration delta.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'd align the language here, as we mix between:

  • don't need
  • may omit

Comment thread docs/src/asset.md Outdated
Comment on lines +195 to +207
Asset callbacks execute against the issuing faucet through FPI. Any callback or callback-dispatched
policy that reads mutable security state must call `tx::update_expiration_block_delta` in the
execution path that reads that state. This includes checks against blocklists, allowlists, pause
flags, active policy roots, oracle values, risk parameters, or similar state.

Without an expiration delta, a prover can choose an older reference block where the callback state
allowed the transfer. The expiration delta bounds how stale that reference block may be when the
transaction is included. Standards components that need the common limit can use
`miden::standards::expiration::apply_default`; custom callbacks can call
`tx::update_expiration_block_delta` directly with a tighter limit.

Callbacks that only inspect immutable data, or for which stale data is acceptable, do not need to
set an expiration delta.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Parts of this read repetitive - I'd rather have the expiration deltas explained in on shared place (here or could also be in components.md) and maybe very briefly mention in the other doc location, but include a reference like:
"for more info see X"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

makes sense on the "for more info see X". I do think a bit of repetition is good since this is super important to not miss.

will trim

Comment thread docs/src/protocol_library.md Outdated
Comment on lines +198 to +211
`execute_foreign_procedure` reads the foreign account's state at the transaction reference block,
which is chosen by the executor. The foreign account commitment is not a transaction public input
and is not revalidated against the foreign account's current on-chain state at inclusion, so a
foreign read may be outdated.

Any FPI-callable procedure that reads mutable security state must call
`tx::update_expiration_block_delta` in the execution path that reads that state. This includes
asset callbacks and procedures that read blocklists, allowlists, pause flags, role maps, active
policy roots, oracle values, risk parameters, or other mutable data where stale reads can change an
authorization or pricing decision.

The call is the foreign account's responsibility because the caller controls which valid reference
block is used for proving. Procedures may omit the call only when they read immutable data or stale
data is acceptable.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

again repetition

Comment thread docs/src/transaction.md Outdated
Comment on lines +62 to +70
Note scripts and transaction scripts can read state from foreign accounts by calling public
account procedures through foreign procedure invocation (FPI). FPI authenticates the foreign
account state against the transaction reference block. It does not prove that the foreign account
state is current when the transaction is included in a block.

The executor chooses the transaction reference block. If no expiration delta is set, a transaction
can be proved against an old canonical block where mutable foreign state still allowed the action.
For example, a prover could choose a block from before an account was added to a blocklist, before
an account was removed from an allowlist, or before an oracle value or active policy root changed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Again parts feel repetitive

#!
#! Where:
#! - block_height_delta is the desired expiration time delta (1 to 0xFFFF).
#! - block_height_delta is the desired expiration delta (1 to 0xFFFF).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

let's avoid using HEX values in user-facing docs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation no changelog This PR does not require an entry in the `CHANGELOG.md` file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make FPI expiration requirements obvious in the docs

2 participants