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//! - **Assembly:** Types for working with Miden Assembly.
32//! - **Assets:** Types and utilities for working with assets.
33//! - **Auth:** Authentication-related types and functionalities.
34//! - **Blocks:** Types for handling block headers.
35//! - **Crypto:** Cryptographic types and utilities, including random number generators.
36//! - **Utils:** Miscellaneous utilities for serialization and common operations.
37//!
38//! The library is designed to work in both `no_std` and `std` environments and is
39//! configurable via Cargo features.
40//!
41//! ## Usage
42//!
43//! To use the Miden client library in your project, add it as a dependency in your `Cargo.toml`:
44//!
45//! ```toml
46//! [dependencies]
47//! miden-client = "0.10"
48//! ```
49//!
50//! ## Example
51//!
52//! Below is a brief example illustrating how to instantiate the client:
53//!
54//! ```rust
55//! use std::sync::Arc;
56//!
57//! use miden_client::crypto::RpoRandomCoin;
58//! use miden_client::keystore::FilesystemKeyStore;
59//! use miden_client::note_transport::NOTE_TRANSPORT_DEFAULT_ENDPOINT;
60//! use miden_client::note_transport::grpc::GrpcNoteTransportClient;
61//! use miden_client::rpc::{Endpoint, GrpcClient};
62//! use miden_client::store::Store;
63//! use miden_client::{Client, ExecutionOptions, Felt};
64//! use miden_client_sqlite_store::SqliteStore;
65//! use miden_objects::crypto::rand::FeltRng;
66//! use miden_objects::{MAX_TX_EXECUTION_CYCLES, MIN_TX_EXECUTION_CYCLES};
67//! use rand::Rng;
68//! use rand::rngs::StdRng;
69//!
70//! # pub async fn create_test_client() -> Result<(), Box<dyn std::error::Error>> {
71//! // Create the SQLite store from the client configuration.
72//! let sqlite_store = SqliteStore::new("path/to/store".try_into()?).await?;
73//! let store = Arc::new(sqlite_store);
74//!
75//! // Generate a random seed for the RpoRandomCoin.
76//! let mut rng = rand::rng();
77//! let coin_seed: [u64; 4] = rng.random();
78//!
79//! // Initialize the random coin using the generated seed.
80//! let rng = RpoRandomCoin::new(coin_seed.map(Felt::new).into());
81//! let keystore = FilesystemKeyStore::new("path/to/keys/directory".try_into()?)?;
82//!
83//! // Determine the number of blocks to consider a transaction stale.
84//! // 20 is simply an example value.
85//! let tx_graceful_blocks = Some(20);
86//! // Determine the maximum number of blocks that the client can be behind from the network.
87//! // 256 is simply an example value.
88//! let max_block_number_delta = Some(256);
89//!
90//! // Optionally, connect to the note transport network to exchange private notes.
91//! let note_transport_api =
92//!     GrpcNoteTransportClient::connect(NOTE_TRANSPORT_DEFAULT_ENDPOINT.to_string(), 10_000)
93//!         .await?;
94//!
95//! // Instantiate the client using a gRPC client
96//! let endpoint = Endpoint::new("https".into(), "localhost".into(), Some(57291));
97//! let client: Client<FilesystemKeyStore<StdRng>> = Client::new(
98//!     Arc::new(GrpcClient::new(&endpoint, 10_000)),
99//!     Box::new(rng),
100//!     store,
101//!     Some(Arc::new(keystore)), // or None if no authenticator is needed
102//!     ExecutionOptions::new(
103//!         Some(MAX_TX_EXECUTION_CYCLES),
104//!         MIN_TX_EXECUTION_CYCLES,
105//!         false,
106//!         false, // Set to true for debug mode, if needed.
107//!     )
108//!     .unwrap(),
109//!     tx_graceful_blocks,
110//!     max_block_number_delta,
111//!     Some(Arc::new(note_transport_api)),
112//! )
113//! .await
114//! .unwrap();
115//!
116//! # Ok(())
117//! # }
118//! ```
119//!
120//! For additional usage details, configuration options, and examples, consult the documentation for
121//! each module.
122
123#![no_std]
124
125#[macro_use]
126extern crate alloc;
127use alloc::boxed::Box;
128
129#[cfg(feature = "std")]
130extern crate std;
131
132pub mod account;
133pub mod keystore;
134pub mod note;
135pub mod note_transport;
136pub mod rpc;
137pub mod settings;
138pub mod store;
139pub mod sync;
140pub mod transaction;
141pub mod utils;
142
143#[cfg(feature = "std")]
144pub mod builder;
145
146#[cfg(feature = "testing")]
147mod test_utils;
148
149pub mod errors;
150
151// RE-EXPORTS
152// ================================================================================================
153
154pub mod notes {
155    pub use miden_objects::note::NoteFile;
156}
157
158/// Provides types and utilities for working with Miden Assembly.
159pub mod assembly {
160    pub use miden_objects::assembly::debuginfo::SourceManagerSync;
161    pub use miden_objects::assembly::diagnostics::Report;
162    pub use miden_objects::assembly::diagnostics::reporting::PrintDiagnostic;
163    pub use miden_objects::assembly::{
164        Assembler,
165        DefaultSourceManager,
166        Library,
167        LibraryPath,
168        Module,
169        ModuleKind,
170    };
171}
172
173/// Provides types and utilities for working with assets within the Miden network.
174pub mod asset {
175    pub use miden_objects::AssetError;
176    pub use miden_objects::account::delta::{
177        AccountStorageDelta,
178        AccountVaultDelta,
179        FungibleAssetDelta,
180        NonFungibleAssetDelta,
181        NonFungibleDeltaAction,
182    };
183    pub use miden_objects::asset::{
184        Asset,
185        AssetVault,
186        AssetWitness,
187        FungibleAsset,
188        NonFungibleAsset,
189        NonFungibleAssetDetails,
190        TokenSymbol,
191    };
192}
193
194/// Provides authentication-related types and functionalities for the Miden
195/// network.
196pub mod auth {
197    pub use miden_lib::AuthScheme;
198    pub use miden_lib::account::auth::{AuthRpoFalcon512, NoAuth};
199    pub use miden_objects::account::auth::{AuthSecretKey, PublicKeyCommitment, Signature};
200    pub use miden_tx::auth::{BasicAuthenticator, SigningInputs, TransactionAuthenticator};
201}
202
203/// Provides types for working with blocks within the Miden network.
204pub mod block {
205    pub use miden_objects::block::BlockHeader;
206}
207
208/// Provides cryptographic types and utilities used within the Miden rollup
209/// network. It re-exports commonly used types and random number generators like `FeltRng` from
210/// the `miden_objects` crate.
211pub mod crypto {
212    pub mod rpo_falcon512 {
213        pub use miden_objects::crypto::dsa::rpo_falcon512::{PublicKey, SecretKey, Signature};
214    }
215
216    pub use miden_objects::crypto::hash::blake::{Blake3_160, Blake3Digest};
217    pub use miden_objects::crypto::hash::rpo::Rpo256;
218    pub use miden_objects::crypto::merkle::{
219        Forest,
220        InOrderIndex,
221        LeafIndex,
222        MerklePath,
223        MerkleStore,
224        MerkleTree,
225        MmrDelta,
226        MmrPeaks,
227        MmrProof,
228        NodeIndex,
229        SMT_DEPTH,
230        SmtLeaf,
231        SmtProof,
232    };
233    pub use miden_objects::crypto::rand::{FeltRng, RpoRandomCoin};
234}
235
236/// Provides types for working with addresses within the Miden network.
237pub mod address {
238    pub use miden_objects::address::{
239        Address,
240        AddressId,
241        AddressInterface,
242        NetworkId,
243        RoutingParameters,
244    };
245}
246
247/// Provides types for working with the virtual machine within the Miden network.
248pub mod vm {
249    pub use miden_objects::vm::{
250        AdviceInputs,
251        AdviceMap,
252        AttributeSet,
253        MastArtifact,
254        Package,
255        PackageExport,
256        PackageManifest,
257        QualifiedProcedureName,
258        Section,
259        SectionId,
260    };
261}
262
263pub use async_trait::async_trait;
264pub use errors::*;
265use miden_objects::assembly::{DefaultSourceManager, SourceManagerSync};
266pub use miden_objects::{
267    EMPTY_WORD,
268    Felt,
269    MAX_TX_EXECUTION_CYCLES,
270    MIN_TX_EXECUTION_CYCLES,
271    ONE,
272    PrettyPrint,
273    StarkField,
274    Word,
275    ZERO,
276};
277pub use miden_remote_prover_client::remote_prover::tx_prover::RemoteTransactionProver;
278pub use miden_tx::ExecutionOptions;
279
280/// Provides test utilities for working with accounts and account IDs
281/// within the Miden network. This module is only available when the `testing` feature is
282/// enabled.
283#[cfg(feature = "testing")]
284pub mod testing {
285    pub use miden_lib::testing::note::NoteBuilder;
286    pub use miden_objects::testing::*;
287    pub use miden_testing::*;
288
289    pub use crate::test_utils::*;
290}
291
292use alloc::sync::Arc;
293
294pub use miden_lib::utils::{Deserializable, ScriptBuilder, Serializable, SliceReader};
295pub use miden_objects::block::BlockNumber;
296use miden_objects::crypto::rand::FeltRng;
297use miden_tx::LocalTransactionProver;
298use miden_tx::auth::TransactionAuthenticator;
299use rand::RngCore;
300use rpc::NodeRpcClient;
301use store::Store;
302
303use crate::note_transport::{NoteTransportClient, init_note_transport_cursor};
304use crate::transaction::TransactionProver;
305
306// MIDEN CLIENT
307// ================================================================================================
308
309/// A light client for connecting to the Miden network.
310///
311/// Miden client is responsible for managing a set of accounts. Specifically, the client:
312/// - Keeps track of the current and historical states of a set of accounts and related objects such
313///   as notes and transactions.
314/// - Connects to a Miden node to periodically sync with the current state of the network.
315/// - Executes, proves, and submits transactions to the network as directed by the user.
316pub struct Client<AUTH> {
317    /// The client's store, which provides a way to write and read entities to provide persistence.
318    store: Arc<dyn Store>,
319    /// An instance of [`FeltRng`] which provides randomness tools for generating new keys,
320    /// serial numbers, etc.
321    rng: ClientRng,
322    /// An instance of [`NodeRpcClient`] which provides a way for the client to connect to the
323    /// Miden node.
324    rpc_api: Arc<dyn NodeRpcClient>,
325    /// An instance of a [`LocalTransactionProver`] which will be the default prover for the
326    /// client.
327    tx_prover: Arc<LocalTransactionProver>,
328    /// An instance of a [`TransactionAuthenticator`] which will be used by the transaction
329    /// executor whenever a signature is requested from within the VM.
330    authenticator: Option<Arc<AUTH>>,
331    /// Shared source manager used to retain MASM source information for assembled programs.
332    source_manager: Arc<dyn SourceManagerSync>,
333    /// Options that control the transaction executor’s runtime behaviour (e.g. debug mode).
334    exec_options: ExecutionOptions,
335    /// The number of blocks that are considered old enough to discard pending transactions.
336    tx_graceful_blocks: Option<u32>,
337    /// Maximum number of blocks the client can be behind the network for transactions and account
338    /// proofs to be considered valid.
339    max_block_number_delta: Option<u32>,
340    /// An instance of [`NoteTransportClient`] which provides a way for the client to connect to
341    /// the Miden Note Transport network.
342    note_transport_api: Option<Arc<dyn NoteTransportClient>>,
343}
344
345/// Construction and access methods.
346impl<AUTH> Client<AUTH>
347where
348    AUTH: TransactionAuthenticator,
349{
350    // CONSTRUCTOR
351    // --------------------------------------------------------------------------------------------
352
353    /// Returns a new instance of [`Client`].
354    ///
355    /// ## Arguments
356    ///
357    /// - `rpc_api`: An instance of [`NodeRpcClient`] which provides a way for the client to connect
358    ///   to the Miden node.
359    /// - `rng`: An instance of [`FeltRng`] which provides randomness tools for generating new keys,
360    ///   serial numbers, etc. This can be any RNG that implements the [`FeltRng`] trait.
361    /// - `store`: An instance of [`Store`], which provides a way to write and read entities to
362    ///   provide persistence.
363    /// - `authenticator`: Defines the transaction authenticator that will be used by the
364    ///   transaction executor whenever a signature is requested from within the VM.
365    /// - `exec_options`: Options that control the transaction executor’s runtime behaviour (e.g.
366    ///   debug mode).
367    /// - `tx_graceful_blocks`: The number of blocks that are considered old enough to discard
368    ///   pending transactions.
369    /// - `max_block_number_delta`: Determines the maximum number of blocks that the client can be
370    ///   behind the network for transactions and account proofs to be considered valid.
371    /// - `note_transport_api`: An instance of [`NoteTransportClient`] which provides a way for the
372    ///   client to connect to the Miden Note Transport network.
373    ///
374    /// # Errors
375    ///
376    /// Returns an error if the client couldn't be instantiated.
377    pub async fn new(
378        rpc_api: Arc<dyn NodeRpcClient>,
379        rng: Box<dyn FeltRng>,
380        store: Arc<dyn Store>,
381        authenticator: Option<Arc<AUTH>>,
382        exec_options: ExecutionOptions,
383        tx_graceful_blocks: Option<u32>,
384        max_block_number_delta: Option<u32>,
385        note_transport_api: Option<Arc<dyn NoteTransportClient>>,
386    ) -> Result<Self, ClientError> {
387        let tx_prover = Arc::new(LocalTransactionProver::default());
388
389        if let Some((genesis, _)) = store.get_block_header_by_num(BlockNumber::GENESIS).await? {
390            // Set the genesis commitment in the RPC API client for future requests.
391            rpc_api.set_genesis_commitment(genesis.commitment()).await?;
392        }
393
394        if note_transport_api.is_some() {
395            // Initialize the note transport cursor
396            init_note_transport_cursor(store.clone()).await?;
397        }
398
399        let source_manager: Arc<dyn SourceManagerSync> = Arc::new(DefaultSourceManager::default());
400
401        Ok(Self {
402            store,
403            rng: ClientRng::new(rng),
404            rpc_api,
405            tx_prover,
406            authenticator,
407            source_manager,
408            exec_options,
409            tx_graceful_blocks,
410            max_block_number_delta,
411            note_transport_api,
412        })
413    }
414
415    /// Returns true if the client is in debug mode.
416    pub fn in_debug_mode(&self) -> bool {
417        self.exec_options.enable_debugging()
418    }
419
420    /// Returns an instance of the `ScriptBuilder`
421    pub fn script_builder(&self) -> ScriptBuilder {
422        ScriptBuilder::with_source_manager(self.source_manager.clone())
423    }
424
425    /// Returns a reference to the client's random number generator. This can be used to generate
426    /// randomness for various purposes such as serial numbers, keys, etc.
427    pub fn rng(&mut self) -> &mut ClientRng {
428        &mut self.rng
429    }
430
431    pub fn prover(&self) -> Arc<dyn TransactionProver + Send + Sync> {
432        self.tx_prover.clone()
433    }
434
435    // TEST HELPERS
436    // --------------------------------------------------------------------------------------------
437
438    #[cfg(any(test, feature = "testing"))]
439    pub fn test_rpc_api(&mut self) -> &mut Arc<dyn NodeRpcClient> {
440        &mut self.rpc_api
441    }
442
443    #[cfg(any(test, feature = "testing"))]
444    pub fn test_store(&mut self) -> &mut Arc<dyn Store> {
445        &mut self.store
446    }
447}
448
449// CLIENT RNG
450// ================================================================================================
451
452/// A wrapper around a [`FeltRng`] that implements the [`RngCore`] trait.
453/// This allows the user to pass their own generic RNG so that it's used by the client.
454pub struct ClientRng(Box<dyn FeltRng>);
455
456impl ClientRng {
457    pub fn new(rng: Box<dyn FeltRng>) -> Self {
458        Self(rng)
459    }
460
461    pub fn inner_mut(&mut self) -> &mut Box<dyn FeltRng> {
462        &mut self.0
463    }
464}
465
466impl RngCore for ClientRng {
467    fn next_u32(&mut self) -> u32 {
468        self.0.next_u32()
469    }
470
471    fn next_u64(&mut self) -> u64 {
472        self.0.next_u64()
473    }
474
475    fn fill_bytes(&mut self, dest: &mut [u8]) {
476        self.0.fill_bytes(dest);
477    }
478}
479
480impl FeltRng for ClientRng {
481    fn draw_element(&mut self) -> Felt {
482        self.0.draw_element()
483    }
484
485    fn draw_word(&mut self) -> Word {
486        self.0.draw_word()
487    }
488}
489
490/// Indicates whether the client is operating in debug mode.
491#[derive(Debug, Clone, Copy)]
492pub enum DebugMode {
493    Enabled,
494    Disabled,
495}
496
497impl From<DebugMode> for bool {
498    fn from(debug_mode: DebugMode) -> Self {
499        match debug_mode {
500            DebugMode::Enabled => true,
501            DebugMode::Disabled => false,
502        }
503    }
504}
505
506impl From<bool> for DebugMode {
507    fn from(debug_mode: bool) -> DebugMode {
508        if debug_mode {
509            DebugMode::Enabled
510        } else {
511            DebugMode::Disabled
512        }
513    }
514}