feat(rust-client): allow chain-anchored execution - #2421
Conversation
81b473b to
6a8bdfd
Compare
6a8bdfd to
70f571b
Compare
| 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); |
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
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).
Adds:
ChainAnchor: serializable(BlockHeader, PartialBlockchain)tuple identifying a reference block by commitment and verifiable against the signed summaryClient::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.