miden_client/
lib.rs

1//! A no_std-compatible client library for interacting with the Miden network.
2//!
3//! This crate provides a lightweight client that handles connections to the Miden node, manages
4//! accounts and their state, and facilitates executing, proving, and submitting transactions.
5//!
6//! For a protocol-level overview and guides for getting started, please visit the official
7//! [Miden docs](https://0xMiden.github.io/miden-docs/).
8//!
9//! ## Overview
10//!
11//! The library is organized into several key modules:
12//!
13//! - **Accounts:** Provides types for managing accounts. Once accounts are tracked by the client,
14//!   their state is updated with every transaction and validated during each sync.
15//!
16//! - **Notes:** Contains types and utilities for working with notes in the Miden client.
17//!
18//! - **RPC:** Facilitates communication with Miden node, exposing RPC methods for syncing state,
19//!   fetching block headers, and submitting transactions.
20//!
21//! - **Store:** Defines and implements the persistence layer for accounts, transactions, notes, and
22//!   other entities.
23//!
24//! - **Sync:** Provides functionality to synchronize the local state with the current state on the
25//!   Miden network.
26//!
27//! - **Transactions:** Offers capabilities to build, execute, prove, and submit transactions.
28//!
29//! Additionally, the crate re-exports several utility modules:
30//!
31//! - **Assets:** Types and utilities for working with assets.
32//! - **Auth:** Authentication-related types and functionalities.
33//! - **Blocks:** Types for handling block headers.
34//! - **Crypto:** Cryptographic types and utilities, including random number generators.
35//! - **Utils:** Miscellaneous utilities for serialization and common operations.
36//!
37//! The library is designed to work in both `no_std` and `std` environments and is
38//! configurable via Cargo features.
39//!
40//! ## Usage
41//!
42//! To use the Miden client library in your project, add it as a dependency in your `Cargo.toml`:
43//!
44//! ```toml
45//! [dependencies]
46//! miden-client = "0.10"
47//! ```
48//!
49//! ## Example
50//!
51//! Below is a brief example illustrating how to instantiate the client:
52//!
53//! ```rust
54//! use std::sync::Arc;
55//!
56//! use miden_client::{
57//!     Client, ExecutionOptions, Felt,
58//!     crypto::RpoRandomCoin,
59//!     keystore::FilesystemKeyStore,
60//!     rpc::{Endpoint, TonicRpcClient},
61//!     store::{Store, sqlite_store::SqliteStore},
62//! };
63//! use miden_objects::{MAX_TX_EXECUTION_CYCLES, MIN_TX_EXECUTION_CYCLES, crypto::rand::FeltRng};
64//! use rand::{Rng, rngs::StdRng};
65//!
66//! # pub async fn create_test_client() -> Result<(), Box<dyn std::error::Error>> {
67//! // Create the SQLite store from the client configuration.
68//! let sqlite_store = SqliteStore::new("path/to/store".try_into()?).await?;
69//! let store = Arc::new(sqlite_store);
70//!
71//! // Generate a random seed for the RpoRandomCoin.
72//! let mut rng = rand::rng();
73//! let coin_seed: [u64; 4] = rng.random();
74//!
75//! // Initialize the random coin using the generated seed.
76//! let rng = RpoRandomCoin::new(coin_seed.map(Felt::new));
77//! let keystore = FilesystemKeyStore::new("path/to/keys/directory".try_into()?)?;
78//!
79//! // Determine the number of blocks to consider a transaction stale.
80//! // 20 is simply an example value.
81//! let tx_graceful_blocks = Some(20);
82//! // Determine the maximum number of blocks that the client can be behind from the network.
83//! // 256 is simply an example value.
84//! let max_block_number_delta = Some(256);
85//!
86//! // Instantiate the client using a Tonic RPC client
87//! let endpoint = Endpoint::new("https".into(), "localhost".into(), Some(57291));
88//! let client: Client = Client::new(
89//!     Arc::new(TonicRpcClient::new(&endpoint, 10_000)),
90//!     Box::new(rng),
91//!     store,
92//!     Arc::new(keystore),
93//!     ExecutionOptions::new(
94//!         Some(MAX_TX_EXECUTION_CYCLES),
95//!         MIN_TX_EXECUTION_CYCLES,
96//!         false,
97//!         false, // Set to true for debug mode, if needed.
98//!     )
99//!     .unwrap(),
100//!     tx_graceful_blocks,
101//!     max_block_number_delta,
102//! );
103//!
104//! # Ok(())
105//! # }
106//! ```
107//!
108//! For additional usage details, configuration options, and examples, consult the documentation for
109//! each module.
110
111#![no_std]
112
113#[macro_use]
114extern crate alloc;
115use alloc::boxed::Box;
116
117#[cfg(feature = "std")]
118extern crate std;
119
120pub mod account;
121pub mod keystore;
122pub mod note;
123pub mod rpc;
124pub mod store;
125pub mod sync;
126pub mod transaction;
127
128#[cfg(feature = "std")]
129pub mod builder;
130
131#[cfg(feature = "testing")]
132mod test_utils;
133
134#[cfg(test)]
135pub mod tests;
136
137mod errors;
138
139// RE-EXPORTS
140// ================================================================================================
141
142/// Provides types and utilities for working with assets within the Miden network.
143pub mod asset {
144    pub use miden_objects::{
145        account::delta::{
146            AccountVaultDelta, FungibleAssetDelta, NonFungibleAssetDelta, NonFungibleDeltaAction,
147        },
148        asset::{Asset, AssetVault, FungibleAsset, NonFungibleAsset, TokenSymbol},
149    };
150}
151
152/// Provides authentication-related types and functionalities for the Miden
153/// network.
154pub mod auth {
155    pub use miden_lib::AuthScheme;
156    pub use miden_objects::account::AuthSecretKey;
157    pub use miden_tx::auth::{BasicAuthenticator, TransactionAuthenticator};
158}
159
160/// Provides types for working with blocks within the Miden network.
161pub mod block {
162    pub use miden_objects::block::BlockHeader;
163}
164
165/// Provides cryptographic types and utilities used within the Miden rollup
166/// network. It re-exports commonly used types and random number generators like `FeltRng` from
167/// the `miden_objects` crate.
168pub mod crypto {
169    pub use miden_objects::{
170        Digest,
171        crypto::{
172            dsa::rpo_falcon512::SecretKey,
173            merkle::{
174                InOrderIndex, LeafIndex, MerklePath, MmrDelta, MmrPeaks, MmrProof, SmtLeaf,
175                SmtProof,
176            },
177            rand::{FeltRng, RpoRandomCoin},
178        },
179    };
180}
181
182pub use errors::{AuthenticationError, ClientError, IdPrefixFetchError};
183pub use miden_objects::{Felt, ONE, StarkField, Word, ZERO};
184pub use miden_remote_prover_client::remote_prover::tx_prover::RemoteTransactionProver;
185pub use miden_tx::ExecutionOptions;
186
187/// Provides various utilities that are commonly used throughout the Miden
188/// client library.
189pub mod utils {
190    pub use miden_tx::utils::{
191        ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
192        bytes_to_hex_string,
193        sync::{LazyLock, RwLock, RwLockReadGuard, RwLockWriteGuard},
194    };
195}
196
197/// Provides test utilities for working with accounts and account IDs
198/// within the Miden network. This module is only available when the `testing` feature is
199/// enabled.
200#[cfg(feature = "testing")]
201pub mod testing {
202    pub use miden_objects::testing::*;
203
204    pub use crate::test_utils::*;
205}
206
207use alloc::sync::Arc;
208
209use miden_lib::utils::ScriptBuilder;
210use miden_objects::crypto::rand::FeltRng;
211use miden_tx::{LocalTransactionProver, auth::TransactionAuthenticator};
212use rand::RngCore;
213use rpc::NodeRpcClient;
214use store::Store;
215
216// MIDEN CLIENT
217// ================================================================================================
218
219/// A light client for connecting to the Miden network.
220///
221/// Miden client is responsible for managing a set of accounts. Specifically, the client:
222/// - Keeps track of the current and historical states of a set of accounts and related objects such
223///   as notes and transactions.
224/// - Connects to a Miden node to periodically sync with the current state of the network.
225/// - Executes, proves, and submits transactions to the network as directed by the user.
226pub struct Client {
227    /// The client's store, which provides a way to write and read entities to provide persistence.
228    store: Arc<dyn Store>,
229    /// An instance of [`FeltRng`] which provides randomness tools for generating new keys,
230    /// serial numbers, etc.
231    rng: ClientRng,
232    /// An instance of [`NodeRpcClient`] which provides a way for the client to connect to the
233    /// Miden node.
234    rpc_api: Arc<dyn NodeRpcClient + Send>,
235    /// An instance of a [`LocalTransactionProver`] which will be the default prover for the
236    /// client.
237    tx_prover: Arc<LocalTransactionProver>,
238    /// An instance of a [`TransactionAuthenticator`] which will be used by the transaction
239    /// executor whenever a signature is requested from within the VM.
240    authenticator: Option<Arc<dyn TransactionAuthenticator>>,
241    /// Options that control the transaction executor’s runtime behaviour (e.g. debug mode).
242    exec_options: ExecutionOptions,
243    /// The number of blocks that are considered old enough to discard pending transactions.
244    tx_graceful_blocks: Option<u32>,
245    /// Maximum number of blocks the client can be behind the network for transactions and account
246    /// proofs to be considered valid.
247    max_block_number_delta: Option<u32>,
248}
249
250/// Construction and access methods.
251impl Client {
252    // CONSTRUCTOR
253    // --------------------------------------------------------------------------------------------
254
255    /// Returns a new instance of [`Client`].
256    ///
257    /// ## Arguments
258    ///
259    /// - `api`: An instance of [`NodeRpcClient`] which provides a way for the client to connect to
260    ///   the Miden node.
261    /// - `rng`: An instance of [`FeltRng`] which provides randomness tools for generating new keys,
262    ///   serial numbers, etc. This can be any RNG that implements the [`FeltRng`] trait.
263    /// - `store`: An instance of [`Store`], which provides a way to write and read entities to
264    ///   provide persistence.
265    /// - `authenticator`: Defines the transaction authenticator that will be used by the
266    ///   transaction executor whenever a signature is requested from within the VM.
267    /// - `exec_options`: Options that control the transaction executor’s runtime behaviour (e.g.
268    ///   debug mode).
269    /// - `tx_graceful_blocks`: The number of blocks that are considered old enough to discard
270    ///   pending transactions.
271    /// - `max_block_number_delta`: Determines the maximum number of blocks that the client can be
272    ///   behind the network for transactions and account proofs to be considered valid.
273    ///
274    /// # Errors
275    ///
276    /// Returns an error if the client couldn't be instantiated.
277    pub fn new(
278        rpc_api: Arc<dyn NodeRpcClient + Send>,
279        rng: Box<dyn FeltRng>,
280        store: Arc<dyn Store>,
281        authenticator: Arc<dyn TransactionAuthenticator>,
282        exec_options: ExecutionOptions,
283        tx_graceful_blocks: Option<u32>,
284        max_block_number_delta: Option<u32>,
285    ) -> Self {
286        let authenticator = Some(authenticator);
287        let tx_prover = Arc::new(LocalTransactionProver::default());
288
289        Self {
290            store,
291            rng: ClientRng::new(rng),
292            rpc_api,
293            tx_prover,
294            authenticator,
295            exec_options,
296            tx_graceful_blocks,
297            max_block_number_delta,
298        }
299    }
300
301    /// Returns true if the client is in debug mode.
302    pub fn in_debug_mode(&self) -> bool {
303        self.exec_options.enable_debugging()
304    }
305
306    /// Returns an instance of the `ScriptBuilder`
307    pub fn script_builder(&self) -> ScriptBuilder {
308        ScriptBuilder::new(self.in_debug_mode())
309    }
310
311    /// Returns a reference to the client's random number generator. This can be used to generate
312    /// randomness for various purposes such as serial numbers, keys, etc.
313    pub fn rng(&mut self) -> &mut ClientRng {
314        &mut self.rng
315    }
316
317    // TEST HELPERS
318    // --------------------------------------------------------------------------------------------
319
320    #[cfg(any(test, feature = "testing"))]
321    pub fn test_rpc_api(&mut self) -> &mut Arc<dyn NodeRpcClient + Send> {
322        &mut self.rpc_api
323    }
324
325    #[cfg(any(test, feature = "testing"))]
326    pub fn test_store(&mut self) -> &mut Arc<dyn Store> {
327        &mut self.store
328    }
329}
330
331// CLIENT RNG
332// ================================================================================================
333
334/// A wrapper around a [`FeltRng`] that implements the [`RngCore`] trait.
335/// This allows the user to pass their own generic RNG so that it's used by the client.
336pub struct ClientRng(Box<dyn FeltRng>);
337
338impl ClientRng {
339    pub fn new(rng: Box<dyn FeltRng>) -> Self {
340        Self(rng)
341    }
342
343    pub fn inner_mut(&mut self) -> &mut Box<dyn FeltRng> {
344        &mut self.0
345    }
346}
347
348impl RngCore for ClientRng {
349    fn next_u32(&mut self) -> u32 {
350        self.0.next_u32()
351    }
352
353    fn next_u64(&mut self) -> u64 {
354        self.0.next_u64()
355    }
356
357    fn fill_bytes(&mut self, dest: &mut [u8]) {
358        self.0.fill_bytes(dest);
359    }
360}
361
362impl FeltRng for ClientRng {
363    fn draw_element(&mut self) -> Felt {
364        self.0.draw_element()
365    }
366
367    fn draw_word(&mut self) -> Word {
368        self.0.draw_word()
369    }
370}