Skip to content

feat(rust-client): allow chain-anchored execution - #2421

Open
igamigo wants to merge 1 commit into
nextfrom
igamigo-chain-anchor-execution
Open

feat(rust-client): allow chain-anchored execution#2421
igamigo wants to merge 1 commit into
nextfrom
igamigo-chain-anchor-execution

Conversation

@igamigo

@igamigo igamigo commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Adds:

  • ChainAnchor: serializable (BlockHeader, PartialBlockchain) tuple identifying a reference block by commitment and verifiable against the signed summary
  • Client::execute_transaction_at(..., chain_anchor): executes at the anchor block instead of the current sync height, including pinned FPI proofs.
  • Client::chain_anchor_for_request(tx_req): captures an anchor at the current tip, including creation blocks for authenticated input notes.

In a guardian flow, the proposer can now include the anchor; cosigners and the executor verify the block commitment and re-execute at that anchor, so the same summary and signatures remain reproducible later.

@igamigo
igamigo force-pushed the igamigo-chain-anchor-execution branch 3 times, most recently from 81b473b to 6a8bdfd Compare August 19, 2026 19:22
@igamigo
igamigo force-pushed the igamigo-chain-anchor-execution branch from 6a8bdfd to 70f571b Compare August 19, 2026 21:08
@igamigo
igamigo marked this pull request as ready for review August 20, 2026 03:15

@Dominik1999 Dominik1999 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

2 questions

let data_store = ClientDataStore::new(self.store.clone(), self.rpc_api.clone());
let mut data_store = ClientDataStore::new(self.store.clone(), self.rpc_api.clone());
if let Some(anchor) = anchor {
data_store = data_store.with_chain_anchor(*anchor);

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.

Does anchored execution break when the request has ignore_invalid_input_notes set and the chain has advanced past the anchor.

This anchored data_store is later handed to get_valid_input_notes, whose NoteConsumptionChecker trial passes self.store.get_sync_height() as the reference block. Inside the anchored get_transaction_inputs, ref_block (sync height) ≠ anchor.block_num(), so the trial fails with ReferenceBlockMismatch.

The trial should run at anchor.block_num() when an anchor is present (or use a fresh non-anchored store, like NoteScreener::check_notes_consumability does). Neither of the new tests sets ignore_invalid_input_notes, so this path is currently untested.

// match the anchor; every other block in the set (input note creation blocks) must
// already be tracked by the anchor's partial blockchain.
if ref_block != anchor.block_num() {
return Err(DataStoreError::other(

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.

Both anchor errors here are flattened to strings via DataStoreError::other(err.to_string()), and the executor then wraps them as FetchTransactionInputsFailed — so the caller of execute_transaction_at always sees ClientError::TransactionExecutorError, never the ClientError::ChainAnchorError its rustdoc promises for the untracked-note case. A multisig caller that wants to react to BlockNotTracked (recapture a wider anchor) can only substring-match, which breaks the first time the wording changes.

Suggest preserving the typed error through DataStoreError (or, at minimum, fixing the execute_transaction_at error docs to say these surface as TransactionExecutorError).

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants