From 5f13c47831fbffe57bd2e5e35108797d8dda37ab Mon Sep 17 00:00:00 2001 From: Tomas Rodriguez Dala <43424983+tomyrd@users.noreply.github.com> Date: Mon, 30 Dec 2024 18:02:11 -0300 Subject: [PATCH] refactor: add client specific rpc functions (#616) * refactor: remove `NoteInclusionDetails` * feat: add `get_account_fpi_data` for rpc * feat: add `get_public_accounts` * feat: add `get_public_note_records` to rpc * refactor: various improvements * feat: add `get_block_header_with_proof` * feat: add `get_note_by_id` to rpc * refactor: rename rpc `NoteDetails` into `NodeNote` * chore: update CHANGELOG * chore: add doc comments * refactor: rename `NodeNote` to `NetworkNote` * refactor : remove `state_headers` from `FpiAccountData` * fix: doc types * review: address comments * chore: change node note to network note * chore: update cargo lock * doc: fix styling --- CHANGELOG.md | 1 + Cargo.lock | 84 +++++----- crates/rust-client/src/accounts.rs | 10 +- crates/rust-client/src/mock.rs | 19 +-- crates/rust-client/src/notes/import.rs | 32 ++-- crates/rust-client/src/rpc/domain/accounts.rs | 67 +++++++- crates/rust-client/src/rpc/domain/notes.rs | 48 ++---- crates/rust-client/src/rpc/errors.rs | 4 +- crates/rust-client/src/rpc/mod.rs | 146 +++++++++++++++++- .../rust-client/src/rpc/tonic_client/mod.rs | 18 +-- .../src/rpc/web_tonic_client/mod.rs | 12 +- .../rust-client/src/store/note_record/mod.rs | 3 +- .../src/store/sqlite_store/sync.rs | 4 +- .../src/store/web_store/sync/mod.rs | 4 +- crates/rust-client/src/sync/block_headers.rs | 5 +- crates/rust-client/src/sync/mod.rs | 100 ++++-------- crates/rust-client/src/transactions/mod.rs | 55 ++----- .../src/transactions/request/foreign.rs | 27 +--- 18 files changed, 356 insertions(+), 283 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e964069e6..1ae20cc4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ ### Changes +* Refactored RPC functions and structs to improve code quality (#616). * [BREAKING] Added support for new two `Felt` account ID (#639). * [BREAKING] Removed unnecessary methods from `Client` (#631). * [BREAKING] Use `thiserror` 2.0 to derive errors (#623). diff --git a/Cargo.lock b/Cargo.lock index ac6b63bab..9894d9d57 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -192,7 +192,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -203,7 +203,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -451,9 +451,9 @@ checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" -version = "1.2.6" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333" +checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" dependencies = [ "jobserver", "libc", @@ -541,7 +541,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -829,7 +829,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -1025,7 +1025,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -1519,7 +1519,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -1782,7 +1782,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax 0.8.5", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -2053,7 +2053,7 @@ dependencies = [ "supports-color", "supports-hyperlinks", "supports-unicode", - "syn 2.0.92", + "syn 2.0.91", "terminal_size 0.3.0", "textwrap", "trybuild", @@ -2068,7 +2068,7 @@ checksum = "1cc759f0a2947acae217a2f32f722105cacc57d17d5f93bc16362142943a4edd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -2143,7 +2143,7 @@ checksum = "0ee4176a0f2e7d29d2a8ee7e60b6deb14ce67a20e94c3e2c7275cdb8804e1862" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -2248,7 +2248,7 @@ checksum = "23c9b935fbe1d6cbd1dac857b54a688145e2d93f48db36010514d0f612d0ad67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -2369,7 +2369,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -2461,7 +2461,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -2693,7 +2693,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -2738,7 +2738,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -3059,7 +3059,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -3103,7 +3103,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", "version_check", "yansi", ] @@ -3149,7 +3149,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.92", + "syn 2.0.91", "tempfile", ] @@ -3163,7 +3163,7 @@ dependencies = [ "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -3505,9 +3505,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.19" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" @@ -3617,7 +3617,7 @@ checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -3833,7 +3833,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -3876,9 +3876,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.92" +version = "2.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ae51629bf965c5c098cc9e87908a3df5301051a9e087d6f9bef5c9771ed126" +checksum = "d53cbcb5a243bd33b7858b1d7f4aca2153490815872d86d955d6ea29f743c035" dependencies = [ "proc-macro2", "quote", @@ -3905,7 +3905,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -4031,7 +4031,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -4042,7 +4042,7 @@ checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -4132,7 +4132,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -4257,7 +4257,7 @@ dependencies = [ "prost-build", "prost-types", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -4402,7 +4402,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -4711,7 +4711,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", "wasm-bindgen-shared", ] @@ -4746,7 +4746,7 @@ checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4861,7 +4861,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -4872,7 +4872,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -5113,7 +5113,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be43529f43f70306437d2c2c9f9e2b3a4d39b42e86702d8d7577f2357ea32fa6" dependencies = [ "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -5210,7 +5210,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", "synstructure", ] @@ -5232,7 +5232,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] @@ -5252,7 +5252,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", "synstructure", ] @@ -5275,7 +5275,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.91", ] [[package]] diff --git a/crates/rust-client/src/accounts.rs b/crates/rust-client/src/accounts.rs index 71998d1b2..12dcce9c2 100644 --- a/crates/rust-client/src/accounts.rs +++ b/crates/rust-client/src/accounts.rs @@ -164,7 +164,7 @@ impl Client { /// Contains account changes to apply to the store. pub struct AccountUpdates { /// Updated public accounts. - updated_onchain_accounts: Vec, + updated_public_accounts: Vec, /// Node account hashes that don't match the tracked information. mismatched_offchain_accounts: Vec<(AccountId, Digest)>, } @@ -172,18 +172,18 @@ pub struct AccountUpdates { impl AccountUpdates { /// Creates a new instance of `AccountUpdates`. pub fn new( - updated_onchain_accounts: Vec, + updated_public_accounts: Vec, mismatched_offchain_accounts: Vec<(AccountId, Digest)>, ) -> Self { Self { - updated_onchain_accounts, + updated_public_accounts, mismatched_offchain_accounts, } } /// Returns the updated public accounts. - pub fn updated_onchain_accounts(&self) -> &[Account] { - &self.updated_onchain_accounts + pub fn updated_public_accounts(&self) -> &[Account] { + &self.updated_public_accounts } /// Returns the mismatched offchain accounts. diff --git a/crates/rust-client/src/mock.rs b/crates/rust-client/src/mock.rs index 040413cd4..32750e292 100644 --- a/crates/rust-client/src/mock.rs +++ b/crates/rust-client/src/mock.rs @@ -32,7 +32,7 @@ use crate::{ rpc::{ domain::{ accounts::{AccountDetails, AccountProofs}, - notes::{NoteDetails, NoteInclusionDetails, NoteSyncInfo}, + notes::{NetworkNote, NoteSyncInfo}, sync::StateSyncInfo, }, generated::{ @@ -257,26 +257,15 @@ impl NodeRpcClient for MockRpcApi { Ok((block.header(), mmr_proof)) } - async fn get_notes_by_id(&mut self, note_ids: &[NoteId]) -> Result, RpcError> { + async fn get_notes_by_id(&mut self, note_ids: &[NoteId]) -> Result, RpcError> { // assume all off-chain notes for now let hit_notes = note_ids.iter().filter_map(|id| self.notes.get(id)); let mut return_notes = vec![]; for note in hit_notes { - let inclusion_details = NoteInclusionDetails::new( - note.proof() - .expect("Note should have an inclusion proof") - .location() - .block_num(), - note.proof() - .expect("Note should have an inclusion proof") - .location() - .node_index_in_block(), - note.proof().expect("Note should have an inclusion proof").note_path().clone(), - ); - return_notes.push(NoteDetails::Private( + return_notes.push(NetworkNote::Private( note.id(), *note.note().metadata(), - inclusion_details, + note.proof().expect("Note should have an inclusion proof").clone(), )); } Ok(return_notes) diff --git a/crates/rust-client/src/notes/import.rs b/crates/rust-client/src/notes/import.rs index b1d2f35ea..76b6557a7 100644 --- a/crates/rust-client/src/notes/import.rs +++ b/crates/rust-client/src/notes/import.rs @@ -6,7 +6,7 @@ use miden_objects::{ }; use crate::{ - rpc::domain::notes::NoteDetails as RpcNoteDetails, + rpc::{domain::notes::NetworkNote, RpcError}, store::{input_note_states::ExpectedNoteState, InputNoteRecord, InputNoteState}, sync::NoteTagRecord, Client, ClientError, @@ -84,27 +84,17 @@ impl Client { previous_note: Option, id: NoteId, ) -> Result, ClientError> { - let mut chain_notes = self.rpc_api.get_notes_by_id(&[id]).await?; - if chain_notes.is_empty() { - return Err(ClientError::NoteNotFoundOnChain(id)); - } - - let note_details: RpcNoteDetails = - chain_notes.pop().expect("chain_notes should have at least one element"); - - let inclusion_details = note_details.inclusion_details(); + let network_note = self.rpc_api.get_note_by_id(id).await.map_err(|err| match err { + RpcError::NoteNotFound(note_id) => ClientError::NoteNotFoundOnChain(note_id), + err => ClientError::RpcError(err), + })?; - // Add the inclusion proof to the imported note - let inclusion_proof = NoteInclusionProof::new( - inclusion_details.block_num, - inclusion_details.note_index, - inclusion_details.merkle_path.clone(), - )?; + let inclusion_proof = network_note.inclusion_proof().clone(); match previous_note { Some(mut previous_note) => { if previous_note - .inclusion_proof_received(inclusion_proof, *note_details.metadata())? + .inclusion_proof_received(inclusion_proof, *network_note.metadata())? { self.store.remove_note_tag((&previous_note).try_into()?).await?; @@ -114,16 +104,16 @@ impl Client { } }, None => { - let node_note = match note_details { - RpcNoteDetails::Public(note, _) => note, - RpcNoteDetails::Private(..) => { + let network_note = match network_note { + NetworkNote::Public(note, _) => note, + NetworkNote::Private(..) => { return Err(ClientError::NoteImportError( "Incomplete imported note is private".to_string(), )) }, }; - self.import_note_record_by_proof(previous_note, node_note, inclusion_proof) + self.import_note_record_by_proof(previous_note, network_note, inclusion_proof) .await }, } diff --git a/crates/rust-client/src/rpc/domain/accounts.rs b/crates/rust-client/src/rpc/domain/accounts.rs index 1b22439d7..719835cf8 100644 --- a/crates/rust-client/src/rpc/domain/accounts.rs +++ b/crates/rust-client/src/rpc/domain/accounts.rs @@ -13,13 +13,16 @@ use miden_objects::{ use miden_tx::utils::{Deserializable, Serializable, ToHex}; use thiserror::Error; -use crate::rpc::{ - errors::RpcConversionError, - generated::{ - account::{AccountHeader as ProtoAccountHeader, AccountId as ProtoAccountId}, - responses::AccountStateHeader as ProtoAccountStateHeader, +use crate::{ + rpc::{ + errors::RpcConversionError, + generated::{ + account::{AccountHeader as ProtoAccountHeader, AccountId as ProtoAccountId}, + responses::AccountStateHeader as ProtoAccountStateHeader, + }, + RpcError, }, - RpcError, + transactions::ForeignAccountInputs, }; // ACCOUNT DETAILS @@ -272,6 +275,58 @@ impl AccountProof { } } +// FPI ACCOUNT DATA +// ================================================================================================ + +/// Represents the data needed to perform a Foreign Procedure Invocation (FPI) on an account. +pub struct FpiAccountData { + /// Account ID. + account_id: AccountId, + /// Authentication path from the `account_root` of the block header to the account. + merkle_path: MerklePath, + /// Account inputs needed to perform the FPI. + inputs: ForeignAccountInputs, +} + +impl FpiAccountData { + pub fn new( + account_id: AccountId, + merkle_path: MerklePath, + inputs: ForeignAccountInputs, + ) -> Self { + Self { account_id, merkle_path, inputs } + } + + pub fn account_id(&self) -> AccountId { + self.account_id + } + + pub fn merkle_path(&self) -> &MerklePath { + &self.merkle_path + } + + pub fn inputs(&self) -> &ForeignAccountInputs { + &self.inputs + } + + pub fn into_parts(self) -> (AccountId, MerklePath, ForeignAccountInputs) { + (self.account_id, self.merkle_path, self.inputs) + } +} + +impl TryFrom for FpiAccountData { + type Error = RpcError; + + fn try_from(value: AccountProof) -> Result { + let (account_id, merkle_proof, _, state_headers) = value.into_parts(); + if let Some(StateHeaders { account_header, storage_header, code }) = state_headers { + let inputs = ForeignAccountInputs::new(account_header, storage_header, code); + return Ok(FpiAccountData::new(account_id, merkle_proof, inputs)); + } + Err(RpcError::ExpectedDataMissing(String::from("AccountProof.StateHeaders"))) + } +} + // ERRORS // ================================================================================================ diff --git a/crates/rust-client/src/rpc/domain/notes.rs b/crates/rust-client/src/rpc/domain/notes.rs index cbe4def97..89c5c198a 100644 --- a/crates/rust-client/src/rpc/domain/notes.rs +++ b/crates/rust-client/src/rpc/domain/notes.rs @@ -2,7 +2,7 @@ use alloc::vec::Vec; use miden_objects::{ crypto::merkle::MerklePath, - notes::{Note, NoteExecutionHint, NoteId, NoteMetadata, NoteTag, NoteType}, + notes::{Note, NoteExecutionHint, NoteId, NoteInclusionProof, NoteMetadata, NoteTag, NoteType}, BlockHeader, Digest, Felt, }; @@ -161,59 +161,41 @@ impl CommittedNote { } } -/// Contains information related to the note inclusion, but not related to the block header -/// that contains the note. -pub struct NoteInclusionDetails { - /// Block number in which the note was included. - pub block_num: u32, - /// Index of the note in the block's note tree. - pub note_index: u16, - /// Merkle path to the note root of the block header. - pub merkle_path: MerklePath, -} - -impl NoteInclusionDetails { - /// Creates a new [NoteInclusionDetails]. - pub fn new(block_num: u32, note_index: u16, merkle_path: MerklePath) -> Self { - Self { block_num, note_index, merkle_path } - } -} - -// NOTE DETAILS +// NETWORK NOTE // ================================================================================================ /// Describes the possible responses from the `GetNotesById` endpoint for a single note. #[allow(clippy::large_enum_variant)] -pub enum NoteDetails { - /// Details for a private note only include its [NoteMetadata] and [NoteInclusionDetails]. +pub enum NetworkNote { + /// Details for a private note only include its [NoteMetadata] and [NoteInclusionProof]. /// Other details needed to consume the note are expected to be stored locally, off-chain. - Private(NoteId, NoteMetadata, NoteInclusionDetails), - /// Contains the full [Note] object alongside its [NoteInclusionDetails]. - Public(Note, NoteInclusionDetails), + Private(NoteId, NoteMetadata, NoteInclusionProof), + /// Contains the full [Note] object alongside its [NoteInclusionProof]. + Public(Note, NoteInclusionProof), } -impl NoteDetails { +impl NetworkNote { /// Returns the note's inclusion details. - pub fn inclusion_details(&self) -> &NoteInclusionDetails { + pub fn inclusion_proof(&self) -> &NoteInclusionProof { match self { - NoteDetails::Private(_, _, inclusion_details) => inclusion_details, - NoteDetails::Public(_, inclusion_details) => inclusion_details, + NetworkNote::Private(_, _, inclusion_proof) => inclusion_proof, + NetworkNote::Public(_, inclusion_proof) => inclusion_proof, } } /// Returns the note's metadata. pub fn metadata(&self) -> &NoteMetadata { match self { - NoteDetails::Private(_, metadata, _) => metadata, - NoteDetails::Public(note, _) => note.metadata(), + NetworkNote::Private(_, metadata, _) => metadata, + NetworkNote::Public(note, _) => note.metadata(), } } /// Returns the note's ID. pub fn id(&self) -> NoteId { match self { - NoteDetails::Private(id, ..) => *id, - NoteDetails::Public(note, _) => note.id(), + NetworkNote::Private(id, ..) => *id, + NetworkNote::Public(note, _) => note.id(), } } } diff --git a/crates/rust-client/src/rpc/errors.rs b/crates/rust-client/src/rpc/errors.rs index d6a85c2b8..4a2488f71 100644 --- a/crates/rust-client/src/rpc/errors.rs +++ b/crates/rust-client/src/rpc/errors.rs @@ -1,6 +1,6 @@ use alloc::string::{String, ToString}; -use miden_objects::{accounts::AccountId, utils::DeserializationError, NoteError}; +use miden_objects::{accounts::AccountId, notes::NoteId, utils::DeserializationError, NoteError}; use thiserror::Error; // RPC ERROR @@ -18,6 +18,8 @@ pub enum RpcError { ExpectedDataMissing(String), #[error("rpc api response is invalid: {0}")] InvalidResponse(String), + #[error("note with id {0} was not found")] + NoteNotFound(NoteId), #[error("rpc request failed for {0}: {1}")] RequestError(String, String), } diff --git a/crates/rust-client/src/rpc/mod.rs b/crates/rust-client/src/rpc/mod.rs index fa79ddb15..fa885b440 100644 --- a/crates/rust-client/src/rpc/mod.rs +++ b/crates/rust-client/src/rpc/mod.rs @@ -2,17 +2,22 @@ //! Remote Procedure Calls (RPC). It facilitates syncing with the network and submitting //! transactions. -use alloc::{boxed::Box, collections::BTreeSet, vec::Vec}; +use alloc::{ + boxed::Box, + collections::{BTreeMap, BTreeSet}, + string::String, + vec::Vec, +}; use core::fmt; use async_trait::async_trait; use domain::{ - accounts::{AccountDetails, AccountProofs}, - notes::{NoteDetails, NoteSyncInfo}, + accounts::{AccountDetails, AccountProof, AccountProofs, FpiAccountData}, + notes::{NetworkNote, NoteSyncInfo}, sync::StateSyncInfo, }; use miden_objects::{ - accounts::{AccountCode, AccountId}, + accounts::{Account, AccountCode, AccountHeader, AccountId}, crypto::merkle::MmrProof, notes::{NoteId, NoteTag, Nullifier}, transaction::ProvenTransaction, @@ -42,7 +47,11 @@ mod web_tonic_client; #[cfg(feature = "web-tonic")] pub use web_tonic_client::WebTonicRpcClient; -use crate::sync::get_nullifier_prefix; +use crate::{ + store::{input_note_states::UnverifiedNoteState, InputNoteRecord}, + sync::get_nullifier_prefix, + transactions::ForeignAccount, +}; // NODE RPC CLIENT TRAIT // ================================================================================================ @@ -78,7 +87,7 @@ pub trait NodeRpcClient { /// For any NoteType::Private note, the return data is only the /// [miden_objects::notes::NoteMetadata], whereas for NoteType::Onchain notes, the return /// data includes all details. - async fn get_notes_by_id(&mut self, note_ids: &[NoteId]) -> Result, RpcError>; + async fn get_notes_by_id(&mut self, note_ids: &[NoteId]) -> Result, RpcError>; /// Fetches info from the node necessary to perform a state sync using the /// `/SyncState` RPC endpoint. @@ -143,6 +152,131 @@ pub trait NodeRpcClient { Ok(nullifiers.iter().find(|(n, _)| n == nullifier).map(|(_, block_num)| *block_num)) } + + /// Fetches the account data needed to perform a Foreign Procedure Invocation (FPI) on the + /// specified foreign accounts. + /// + /// The `code_commitments` parameter is a list of known code hashes + /// to prevent unnecessary data fetching. Returns the block number and the FPI account data. If + /// one of the tracked accounts is not found in the node, the method will return an error. + /// The default implementation of this method uses [NodeRpcClient::get_account_proofs]. + async fn get_fpi_account_data( + &mut self, + foreign_accounts: BTreeSet, + known_account_code: Vec, + ) -> Result<(u32, Vec), RpcError> { + let account_ids = foreign_accounts.iter().map(|acc| acc.account_id()); + let (block_num, account_proofs) = self + .get_account_proofs(&account_ids.collect(), known_account_code, true) + .await?; + + let mut account_proofs: BTreeMap = + account_proofs.into_iter().map(|proof| (proof.account_id(), proof)).collect(); + + let mut headers = Vec::new(); + for foreign_account in foreign_accounts.into_iter() { + let fpi_account_data = match foreign_account { + ForeignAccount::Public(account_id) => { + let account_proof = account_proofs + .remove(&account_id) + .expect("Proof was requested and received"); + + account_proof.try_into()? + }, + ForeignAccount::Private(foreign_account_inputs) => { + let account_id = foreign_account_inputs.account_header().id(); + let proof = account_proofs + .remove(&account_id) + .expect("Proof was requested and received"); + + FpiAccountData::new(account_id, proof.into_parts().1, foreign_account_inputs) + }, + }; + + headers.push(fpi_account_data); + } + + Ok((block_num, headers)) + } + + /// Fetches public note-related data for a list of [NoteId] and builds [InputNoteRecord]s with + /// it. If a note is not found or it's private, it is ignored and will not be included in the + /// returned list. + /// + /// The default implementation of this method uses [NodeRpcClient::get_notes_by_id]. + async fn get_public_note_records( + &mut self, + note_ids: &[NoteId], + current_timestamp: Option, + ) -> Result, RpcError> { + let note_details = self.get_notes_by_id(note_ids).await?; + + let mut public_notes = vec![]; + for detail in note_details { + if let NetworkNote::Public(note, inclusion_proof) = detail { + let state = UnverifiedNoteState { + metadata: *note.metadata(), + inclusion_proof, + } + .into(); + let note = InputNoteRecord::new(note.into(), current_timestamp, state); + + public_notes.push(note); + } + } + + Ok(public_notes) + } + + /// Fetches the public accounts that have been updated since the last known state of the + /// accounts. + /// + /// The `local_accounts` parameter is a list of account headers that the client has + /// stored locally and that it wants to check for updates. If an account is private or didn't + /// change, it is ignored and will not be included in the returned list. + /// The default implementation of this method uses [NodeRpcClient::get_account_update]. + async fn get_updated_public_accounts( + &mut self, + local_accounts: &[&AccountHeader], + ) -> Result, RpcError> { + let mut public_accounts = vec![]; + + for local_account in local_accounts { + let response = self.get_account_update(local_account.id()).await?; + + if let AccountDetails::Public(account, _) = response { + // We should only return an account if it's newer, otherwise we ignore it + if account.nonce().as_int() > local_account.nonce().as_int() { + public_accounts.push(account); + } + } + } + + Ok(public_accounts) + } + + /// Given a block number, fetches the block header corresponding to that height from the node + /// along with the MMR proof. + /// + /// The default implementation of this method uses [NodeRpcClient::get_block_header_by_number]. + async fn get_block_header_with_proof( + &mut self, + block_num: u32, + ) -> Result<(BlockHeader, MmrProof), RpcError> { + let (header, proof) = self.get_block_header_by_number(Some(block_num), true).await?; + Ok((header, proof.ok_or(RpcError::ExpectedDataMissing(String::from("MmrProof")))?)) + } + + /// Fetches the note with the specified ID. + /// + /// The default implementation of this method uses [NodeRpcClient::get_notes_by_id]. + /// + /// Errors: + /// - [RpcError::NoteNotFound] if the note with the specified ID is not found. + async fn get_note_by_id(&mut self, note_id: NoteId) -> Result { + let notes = self.get_notes_by_id(&[note_id]).await?; + notes.into_iter().next().ok_or(RpcError::NoteNotFound(note_id)) + } } // RPC API ENDPOINT diff --git a/crates/rust-client/src/rpc/tonic_client/mod.rs b/crates/rust-client/src/rpc/tonic_client/mod.rs index be54f111a..fef744772 100644 --- a/crates/rust-client/src/rpc/tonic_client/mod.rs +++ b/crates/rust-client/src/rpc/tonic_client/mod.rs @@ -10,7 +10,7 @@ use async_trait::async_trait; use miden_objects::{ accounts::{Account, AccountCode, AccountId}, crypto::merkle::{MerklePath, MmrProof}, - notes::{Note, NoteId, NoteTag, Nullifier}, + notes::{Note, NoteId, NoteInclusionProof, NoteTag, Nullifier}, transaction::ProvenTransaction, utils::Deserializable, BlockHeader, Digest, @@ -22,7 +22,7 @@ use tracing::info; use super::{ domain::{ accounts::{AccountProof, AccountProofs, AccountUpdateSummary}, - notes::NoteInclusionDetails, + notes::NetworkNote, }, generated::{ requests::{ @@ -31,8 +31,8 @@ use super::{ }, rpc::api_client::ApiClient, }, - AccountDetails, Endpoint, NodeRpcClient, NodeRpcClientEndpoint, NoteDetails, NoteSyncInfo, - RpcError, StateSyncInfo, + AccountDetails, Endpoint, NodeRpcClient, NodeRpcClientEndpoint, NoteSyncInfo, RpcError, + StateSyncInfo, }; use crate::rpc::generated::requests::GetBlockHeaderByNumberRequest; @@ -144,7 +144,7 @@ impl NodeRpcClient for TonicRpcClient { Ok((block_header, mmr_proof)) } - async fn get_notes_by_id(&mut self, note_ids: &[NoteId]) -> Result, RpcError> { + async fn get_notes_by_id(&mut self, note_ids: &[NoteId]) -> Result, RpcError> { let request = GetNotesByIdRequest { note_ids: note_ids.iter().map(|id| id.inner().into()).collect(), }; @@ -165,7 +165,7 @@ impl NodeRpcClient for TonicRpcClient { .ok_or(RpcError::ExpectedDataMissing("Notes.MerklePath".into()))? .try_into()?; - NoteInclusionDetails::new(note.block_num, note.note_index as u16, merkle_path) + NoteInclusionProof::new(note.block_num, note.note_index as u16, merkle_path)? }; let note = match note.details { @@ -173,7 +173,7 @@ impl NodeRpcClient for TonicRpcClient { Some(details) => { let note = Note::read_from_bytes(&details)?; - NoteDetails::Public(note, inclusion_details) + NetworkNote::Public(note, inclusion_details) }, // Off-chain notes do not have details None => { @@ -187,7 +187,7 @@ impl NodeRpcClient for TonicRpcClient { .ok_or(RpcError::ExpectedDataMissing("Notes.NoteId".into()))? .try_into()?; - NoteDetails::Private(NoteId::from(note_id), note_metadata, inclusion_details) + NetworkNote::Private(NoteId::from(note_id), note_metadata, inclusion_details) }, }; response_notes.push(note) @@ -285,7 +285,7 @@ impl NodeRpcClient for TonicRpcClient { /// /// This function will return an error if: /// - /// - One of the requested Accounts isn't public, or isn't returned by the node. + /// - One of the requested Accounts isn't returned by the node. /// - There was an error sending the request to the node. /// - The answer had a `None` for one of the expected fields. /// - There is an error during storage deserialization. diff --git a/crates/rust-client/src/rpc/web_tonic_client/mod.rs b/crates/rust-client/src/rpc/web_tonic_client/mod.rs index a16825964..620c8735e 100644 --- a/crates/rust-client/src/rpc/web_tonic_client/mod.rs +++ b/crates/rust-client/src/rpc/web_tonic_client/mod.rs @@ -9,7 +9,7 @@ use async_trait::async_trait; use miden_objects::{ accounts::{Account, AccountCode, AccountId}, crypto::merkle::{MerklePath, MmrProof}, - notes::{Note, NoteId, NoteTag, Nullifier}, + notes::{Note, NoteId, NoteInclusionProof, NoteTag, Nullifier}, transaction::ProvenTransaction, utils::Deserializable, BlockHeader, Digest, @@ -20,7 +20,7 @@ use tonic_web_wasm_client::Client; use super::{ domain::{ accounts::{AccountDetails, AccountProof, AccountProofs, AccountUpdateSummary}, - notes::{NoteDetails, NoteInclusionDetails, NoteSyncInfo}, + notes::{NetworkNote, NoteSyncInfo}, sync::StateSyncInfo, }, generated::{ @@ -121,7 +121,7 @@ impl NodeRpcClient for WebTonicRpcClient { Ok((block_header, mmr_proof)) } - async fn get_notes_by_id(&mut self, note_ids: &[NoteId]) -> Result, RpcError> { + async fn get_notes_by_id(&mut self, note_ids: &[NoteId]) -> Result, RpcError> { let mut query_client = self.build_api_client(); let request = GetNotesByIdRequest { @@ -144,7 +144,7 @@ impl NodeRpcClient for WebTonicRpcClient { .ok_or(RpcError::ExpectedDataMissing("Notes.MerklePath".into()))? .try_into()?; - NoteInclusionDetails::new(note.block_num, note.note_index as u16, merkle_path) + NoteInclusionProof::new(note.block_num, note.note_index as u16, merkle_path)? }; let note = match note.details { @@ -152,7 +152,7 @@ impl NodeRpcClient for WebTonicRpcClient { Some(details) => { let note = Note::read_from_bytes(&details)?; - NoteDetails::Public(note, inclusion_details) + NetworkNote::Public(note, inclusion_details) }, // Off-chain notes do not have details None => { @@ -165,7 +165,7 @@ impl NodeRpcClient for WebTonicRpcClient { .ok_or(RpcError::ExpectedDataMissing("Notes.NoteId".into()))? .try_into()?; - NoteDetails::Private(NoteId::from(note_id), note_metadata, inclusion_details) + NetworkNote::Private(NoteId::from(note_id), note_metadata, inclusion_details) }, }; response_notes.push(note) diff --git a/crates/rust-client/src/store/note_record/mod.rs b/crates/rust-client/src/store/note_record/mod.rs index 78addbc77..81efce71a 100644 --- a/crates/rust-client/src/store/note_record/mod.rs +++ b/crates/rust-client/src/store/note_record/mod.rs @@ -27,8 +27,9 @@ pub use input_note_record::{InputNoteRecord, InputNoteState}; pub use output_note_record::{NoteExportType, OutputNoteRecord, OutputNoteState}; pub mod input_note_states { pub use super::input_note_record::{ - CommittedNoteState, ConsumedAuthenticatedLocalNoteState, ExpectedNoteState, + CommittedNoteState, ConsumedAuthenticatedLocalNoteState, ExpectedNoteState, InputNoteState, InvalidNoteState, ProcessingAuthenticatedNoteState, ProcessingUnauthenticatedNoteState, + UnverifiedNoteState, }; } diff --git a/crates/rust-client/src/store/sqlite_store/sync.rs b/crates/rust-client/src/store/sqlite_store/sync.rs index dab152f13..98af1ebc3 100644 --- a/crates/rust-client/src/store/sqlite_store/sync.rs +++ b/crates/rust-client/src/store/sqlite_store/sync.rs @@ -132,8 +132,8 @@ impl SqliteStore { // Marc transactions as discarded Self::mark_transactions_as_discarded(&tx, &discarded_transactions)?; - // Update onchain accounts on the db that have been updated onchain - for account in updated_accounts.updated_onchain_accounts() { + // Update public accounts on the db that have been updated onchain + for account in updated_accounts.updated_public_accounts() { update_account(&tx, account)?; } diff --git a/crates/rust-client/src/store/web_store/sync/mod.rs b/crates/rust-client/src/store/web_store/sync/mod.rs index b7a83aca4..0f4643ced 100644 --- a/crates/rust-client/src/store/web_store/sync/mod.rs +++ b/crates/rust-client/src/store/web_store/sync/mod.rs @@ -157,8 +157,8 @@ impl WebStore { .collect(); // TODO: LOP INTO idxdb_apply_state_sync call - // Update onchain accounts on the db that have been updated onchain - for account in updated_accounts.updated_onchain_accounts() { + // Update public accounts on the db that have been updated onchain + for account in updated_accounts.updated_public_accounts() { update_account(&account.clone()).await.unwrap(); } diff --git a/crates/rust-client/src/sync/block_headers.rs b/crates/rust-client/src/sync/block_headers.rs index 80051ff73..fdd550dd3 100644 --- a/crates/rust-client/src/sync/block_headers.rs +++ b/crates/rust-client/src/sync/block_headers.rs @@ -152,11 +152,8 @@ impl Client { let (block_header, _) = self.store.get_block_header_by_num(block_num).await?; return Ok(block_header); } - let (block_header, mmr_proof) = - self.rpc_api.get_block_header_by_number(Some(block_num), true).await?; + let (block_header, mmr_proof) = self.rpc_api.get_block_header_with_proof(block_num).await?; - let mmr_proof = mmr_proof - .expect("NodeRpcApi::get_block_header_by_number() should have returned an MMR proof"); // Trim merkle path to keep nodes relevant to our current PartialMmr since the node's MMR // might be of a forest arbitrarily higher let path_nodes = adjust_merkle_path_for_forest( diff --git a/crates/rust-client/src/sync/mod.rs b/crates/rust-client/src/sync/mod.rs index d59d209f0..7c2b394c5 100644 --- a/crates/rust-client/src/sync/mod.rs +++ b/crates/rust-client/src/sync/mod.rs @@ -17,19 +17,10 @@ use tracing::info; use crate::{ accounts::AccountUpdates, notes::NoteUpdates, - rpc::{ - domain::{ - accounts::AccountDetails, - notes::{CommittedNote, NoteDetails}, - nullifiers::NullifierUpdate, - transactions::TransactionUpdate, - }, - RpcError, - }, - store::{ - input_note_states::CommittedNoteState, InputNoteRecord, NoteFilter, OutputNoteRecord, - TransactionFilter, + rpc::domain::{ + notes::CommittedNote, nullifiers::NullifierUpdate, transactions::TransactionUpdate, }, + store::{InputNoteRecord, NoteFilter, OutputNoteRecord, TransactionFilter}, Client, ClientError, }; @@ -251,11 +242,11 @@ impl Client { let note_updates = committed_note_updates.combine_with(consumed_note_updates); - let (onchain_accounts, offchain_accounts): (Vec<_>, Vec<_>) = + let (public_accounts, offchain_accounts): (Vec<_>, Vec<_>) = accounts.into_iter().partition(|account_header| account_header.id().is_public()); - let updated_onchain_accounts = self - .get_updated_onchain_accounts(&response.account_hash_updates, &onchain_accounts) + let updated_public_accounts = self + .get_updated_public_accounts(&response.account_hash_updates, &public_accounts) .await?; let mismatched_offchain_accounts = self @@ -283,7 +274,7 @@ impl Client { note_updates.new_input_notes().iter().map(|n| n.id()).collect(), note_updates.committed_note_ids().into_iter().collect(), note_updates.consumed_note_ids().into_iter().collect(), - updated_onchain_accounts.iter().map(|acc| acc.id()).collect(), + updated_public_accounts.iter().map(|acc| acc.id()).collect(), mismatched_offchain_accounts.iter().map(|(acc_id, _)| *acc_id).collect(), transactions_to_commit.iter().map(|tx| tx.transaction_id).collect(), ); @@ -295,7 +286,7 @@ impl Client { new_mmr_peaks: new_peaks, new_authentication_nodes, updated_accounts: AccountUpdates::new( - updated_onchain_accounts, + updated_public_accounts, mismatched_offchain_accounts, ), block_has_relevant_notes: incoming_block_has_relevant_notes, @@ -522,38 +513,15 @@ impl Client { } info!("Getting note details for notes that are not being tracked."); - let notes_data = self.rpc_api.get_notes_by_id(query_notes).await?; - let mut return_notes = Vec::with_capacity(query_notes.len()); - for note_data in notes_data { - match note_data { - NoteDetails::Private(id, ..) => { - // TODO: Is there any benefit to not ignoring these? In any case we do not have - // the recipient which is mandatory right now. - info!("Note {} is private but the client is not tracking it, ignoring.", id); - }, - NoteDetails::Public(note, inclusion_proof) => { - info!("Retrieved details for Note ID {}.", note.id()); - let inclusion_proof = NoteInclusionProof::new( - block_header.block_num(), - inclusion_proof.note_index, - inclusion_proof.merkle_path, - ) - .map_err(ClientError::NoteError)?; - let metadata = *note.metadata(); - - return_notes.push(InputNoteRecord::new( - note.into(), - self.store.get_current_timestamp(), - CommittedNoteState { - metadata, - inclusion_proof, - block_note_root: block_header.note_root(), - } - .into(), - )) - }, - } + let mut return_notes = self + .rpc_api + .get_public_note_records(query_notes, self.store.get_current_timestamp()) + .await?; + + for note in return_notes.iter_mut() { + note.block_header_received(*block_header)?; } + Ok(return_notes) } @@ -579,35 +547,27 @@ impl Client { Ok(transactions) } - async fn get_updated_onchain_accounts( + async fn get_updated_public_accounts( &mut self, account_updates: &[(AccountId, Digest)], - current_onchain_accounts: &[AccountHeader], + current_public_accounts: &[AccountHeader], ) -> Result, ClientError> { - let mut accounts_to_update: Vec = Vec::new(); - for (remote_account_id, remote_account_hash) in account_updates { + let mut mismatched_public_accounts = vec![]; + + for (id, hash) in account_updates { // check if this updated account is tracked by the client - let current_account = current_onchain_accounts + if let Some(account) = current_public_accounts .iter() - .find(|acc| *remote_account_id == acc.id() && *remote_account_hash != acc.hash()); - - if let Some(tracked_account) = current_account { - info!("Public account hash difference detected for account with ID: {}. Fetching node for updates...", tracked_account.id()); - let account_details = self.rpc_api.get_account_update(tracked_account.id()).await?; - if let AccountDetails::Public(account, _) = account_details { - // We should only do the update if it's newer, otherwise we ignore it - if account.nonce().as_int() > tracked_account.nonce().as_int() { - accounts_to_update.push(account); - } - } else { - return Err(RpcError::AccountUpdateForPrivateAccountReceived( - account_details.account_id(), - ) - .into()); - } + .find(|acc| *id == acc.id() && *hash != acc.hash()) + { + mismatched_public_accounts.push(account); } } - Ok(accounts_to_update) + + self.rpc_api + .get_updated_public_accounts(&mismatched_public_accounts) + .await + .map_err(ClientError::RpcError) } /// Validates account hash updates and returns a vector with all the offchain account diff --git a/crates/rust-client/src/transactions/mod.rs b/crates/rust-client/src/transactions/mod.rs index d182e5994..7f71973aa 100644 --- a/crates/rust-client/src/transactions/mod.rs +++ b/crates/rust-client/src/transactions/mod.rs @@ -22,14 +22,13 @@ use miden_tx::TransactionExecutor; pub use miden_tx::{ LocalTransactionProver, ProvingOptions, TransactionProver, TransactionProverError, }; -use request::{ForeignAccount, ForeignAccountInputs}; +pub use request::{ForeignAccount, ForeignAccountInputs}; use script_builder::{AccountCapabilities, AccountInterface}; use tracing::info; use super::{Client, FeltRng}; use crate::{ notes::{NoteScreener, NoteUpdates}, - rpc::domain::accounts::AccountProof, store::{ input_note_states::ExpectedNoteState, InputNoteRecord, InputNoteState, NoteFilter, OutputNoteRecord, StoreError, TransactionFilter, @@ -743,48 +742,26 @@ impl Client { let account_ids = foreign_accounts.iter().map(|acc| acc.account_id()); let known_account_codes = - self.store.get_foreign_account_code(account_ids.clone().collect()).await?; + self.store.get_foreign_account_code(account_ids.collect()).await?; let known_account_codes: Vec = known_account_codes.into_values().collect(); - // Fetch account proofs - let (block_num, account_proofs) = self - .rpc_api - .get_account_proofs(&account_ids.collect(), known_account_codes, true) - .await?; - - let mut account_proofs: BTreeMap = - account_proofs.into_iter().map(|proof| (proof.account_id(), proof)).collect(); - - for foreign_account in foreign_accounts.into_iter() { - let (foreign_account_inputs, merkle_path) = match foreign_account { - ForeignAccount::Public(account_id) => { - let account_proof = account_proofs - .remove(&account_id) - .expect("Proof was requested and received"); - - let (foreign_account_inputs, merkle_path) = account_proof.try_into()?; + // Fetch FPI account data + let (block_num, fpi_data_vec) = + self.rpc_api.get_fpi_account_data(foreign_accounts, known_account_codes).await?; - // Update our foreign account code cache - self.store - .upsert_foreign_account_code( - account_id, - foreign_account_inputs.account_code().clone(), - ) - .await?; + for fpi_account_data in fpi_data_vec { + let (account_id, merkle_path, foreign_account_inputs) = fpi_account_data.into_parts(); - (foreign_account_inputs, merkle_path) - }, - ForeignAccount::Private(foreign_account_inputs) => { - let account_id = foreign_account_inputs.account_header().id(); - let proof = account_proofs - .remove(&account_id) - .expect("Proof was requested and received"); - let merkle_path = proof.merkle_proof(); - - (foreign_account_inputs, merkle_path.clone()) - }, - }; + if account_id.is_public() { + // Update our foreign account code cache + self.store + .upsert_foreign_account_code( + account_id, + foreign_account_inputs.account_code().clone(), + ) + .await?; + } extend_advice_inputs_for_account( tx_args, diff --git a/crates/rust-client/src/transactions/request/foreign.rs b/crates/rust-client/src/transactions/request/foreign.rs index be0eeee0c..776d4c748 100644 --- a/crates/rust-client/src/transactions/request/foreign.rs +++ b/crates/rust-client/src/transactions/request/foreign.rs @@ -2,14 +2,12 @@ use alloc::string::ToString; use core::cmp::Ordering; -use miden_objects::{ - accounts::{Account, AccountCode, AccountHeader, AccountId, AccountStorageHeader}, - crypto::merkle::MerklePath, +use miden_objects::accounts::{ + Account, AccountCode, AccountHeader, AccountId, AccountStorageHeader, }; use miden_tx::utils::{Deserializable, DeserializationError, Serializable}; use super::TransactionRequestError; -use crate::rpc::domain::accounts::{AccountProof, StateHeaders}; // FOREIGN ACCOUNT // ================================================================================================ @@ -20,8 +18,8 @@ pub enum ForeignAccount { /// Public account data will be retrieved from the network at execution time, based on the /// account id. Public(AccountId), - /// Private account data requires [ForeignAccountData] to be input. The proof of the account's - /// existence will be retrieved from the network at execution time. + /// Private account data requires [ForeignAccountInputs] to be input. The proof of the + /// account's existence will be retrieved from the network at execution time. Private(ForeignAccountInputs), } @@ -127,7 +125,7 @@ pub struct ForeignAccountInputs { } impl ForeignAccountInputs { - /// Creates a new [ForeignAccountData] + /// Creates a new [ForeignAccountInputs] pub fn new( account_header: AccountHeader, storage_header: AccountStorageHeader, @@ -155,7 +153,7 @@ impl ForeignAccountInputs { &self.account_code } - /// Consumes the [ForeignAccountData] and returns its parts. + /// Consumes the [ForeignAccountInputs] and returns its parts. pub fn into_parts(self) -> (AccountHeader, AccountStorageHeader, AccountCode) { (self.account_header, self.storage_header, self.account_code) } @@ -189,16 +187,3 @@ impl Deserializable for ForeignAccountInputs { Ok(ForeignAccountInputs::new(account_header, storage_header, account_code)) } } - -impl TryFrom for (ForeignAccountInputs, MerklePath) { - type Error = TransactionRequestError; - - fn try_from(value: AccountProof) -> Result { - let (_, merkle_proof, _, state_headers) = value.into_parts(); - if let Some(StateHeaders { account_header, storage_header, code }) = state_headers { - let inputs = ForeignAccountInputs::new(account_header, storage_header, code); - return Ok((inputs, merkle_proof)); - } - Err(TransactionRequestError::ForeignAccountDataMissing) - } -}