Skip to main content

miden_client/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2
3//! A no_std-compatible client library for interacting with the Miden network.
4//!
5//! This crate provides a lightweight client that handles connections to the Miden node, manages
6//! accounts and their state, and facilitates executing, proving, and submitting transactions.
7//!
8//! For a protocol-level overview and guides for getting started, please visit the official
9//! [Miden docs](https://docs.miden.xyz/).
10//!
11//! ## Overview
12//!
13//! The library is organized into several key modules:
14//!
15//! - **Accounts:** Provides types for managing accounts. Once accounts are tracked by the client,
16//!   their state is updated with every transaction and validated during each sync.
17//!
18//! - **Notes:** Contains types and utilities for working with notes in the Miden client.
19//!
20//! - **RPC:** Facilitates communication with Miden node, exposing RPC methods for syncing state,
21//!   fetching block headers, and submitting transactions.
22//!
23//! - **Store:** Defines and implements the persistence layer for accounts, transactions, notes, and
24//!   other entities.
25//!
26//! - **Sync:** Provides functionality to synchronize the local state with the current state on the
27//!   Miden network.
28//!
29//! - **Transactions:** Offers capabilities to build, execute, prove, and submit transactions.
30//!
31//! Additionally, the crate re-exports several utility modules:
32//!
33//! - **Assembly:** Types for working with Miden Assembly.
34//! - **Assets:** Types and utilities for working with assets.
35//! - **Auth:** Authentication-related types and functionalities.
36//! - **Blocks:** Types for handling block headers.
37//! - **Crypto:** Cryptographic types and utilities, including random number generators.
38//! - **Utils:** Miscellaneous utilities for serialization and common operations.
39//!
40//! The library is designed to work in both `no_std` and `std` environments and is
41//! configurable via Cargo features.
42//!
43//! ## Usage
44//!
45//! To use the Miden client library in your project, add it as a dependency in your `Cargo.toml`:
46//!
47//! ```toml
48//! [dependencies]
49//! miden-client = "0.10"
50//! ```
51//!
52//! ## Example
53//!
54//! Below is a brief example illustrating how to instantiate the client using `ClientBuilder`:
55//!
56//! ```rust,ignore
57//! use std::sync::Arc;
58//!
59//! use miden_client::DebugMode;
60//! use miden_client::builder::ClientBuilder;
61//! use miden_client::keystore::FilesystemKeyStore;
62//! use miden_client::rpc::{Endpoint, GrpcClient};
63//! use miden_client_sqlite_store::SqliteStore;
64//!
65//! # pub async fn create_test_client() -> Result<(), Box<dyn std::error::Error>> {
66//! // Create the SQLite store.
67//! let sqlite_store = SqliteStore::new("path/to/store".try_into()?).await?;
68//! let store = Arc::new(sqlite_store);
69//!
70//! // Create the keystore for transaction signing.
71//! let keystore = FilesystemKeyStore::new("path/to/keys/directory".try_into()?)?;
72//!
73//! // Create the RPC client.
74//! let endpoint = Endpoint::new("https".into(), "localhost".into(), Some(57291));
75//!
76//! // Instantiate the client using the builder.
77//! let client = ClientBuilder::new()
78//!     .rpc(Arc::new(GrpcClient::new(&endpoint, 10_000)))
79//!     .store(store)
80//!     .authenticator(Arc::new(keystore))
81//!     .in_debug_mode(DebugMode::Disabled)
82//!     .build()
83//!     .await?;
84//!
85//! # Ok(())
86//! # }
87//! ```
88//!
89//! For network-specific defaults, use the convenience constructors:
90//!
91//! ```ignore
92//! // For testnet (includes remote prover and note transport)
93//! let client = ClientBuilder::for_testnet()
94//!     .store(store)
95//!     .authenticator(Arc::new(keystore))
96//!     .build()
97//!     .await?;
98//!
99//! // For local development
100//! let client = ClientBuilder::for_localhost()
101//!     .store(store)
102//!     .authenticator(Arc::new(keystore))
103//!     .build()
104//!     .await?;
105//! ```
106//!
107//! For additional usage details, configuration options, and examples, consult the documentation for
108//! each module.
109
110#![no_std]
111
112#[macro_use]
113extern crate alloc;
114use alloc::boxed::Box;
115
116#[cfg(feature = "std")]
117extern crate std;
118
119pub mod account;
120pub mod grpc_support;
121pub mod keystore;
122pub mod note;
123pub mod note_transport;
124pub mod rpc;
125pub mod settings;
126pub mod store;
127pub mod sync;
128pub mod transaction;
129pub mod utils;
130
131pub mod builder;
132
133#[cfg(feature = "testing")]
134mod test_utils;
135
136pub mod errors;
137
138pub use miden_protocol::utils::serde::{Deserializable, Serializable, SliceReader};
139
140// RE-EXPORTS
141// ================================================================================================
142
143pub mod notes {
144    pub use miden_protocol::note::NoteFile;
145}
146
147/// Provides types and utilities for working with Miden Assembly.
148pub mod assembly {
149    pub use miden_protocol::MastForest;
150    pub use miden_protocol::assembly::debuginfo::SourceManagerSync;
151    #[cfg(feature = "std")]
152    pub use miden_protocol::assembly::debuginfo::{SourceManagerExt, Uri};
153    pub use miden_protocol::assembly::diagnostics::Report;
154    pub use miden_protocol::assembly::diagnostics::reporting::PrintDiagnostic;
155    pub use miden_protocol::assembly::mast::MastNodeExt;
156    pub use miden_protocol::assembly::{
157        Assembler,
158        DefaultSourceManager,
159        Library,
160        Module,
161        ModuleKind,
162        Path,
163    };
164    pub use miden_standards::code_builder::CodeBuilder;
165}
166
167/// Provides types and utilities for working with assets within the Miden network.
168pub mod asset {
169    pub use miden_protocol::account::delta::{
170        AccountStorageDelta,
171        AccountVaultDelta,
172        FungibleAssetDelta,
173        NonFungibleAssetDelta,
174        NonFungibleDeltaAction,
175        StorageMapDelta,
176        StorageSlotDelta,
177    };
178    pub use miden_protocol::account::{
179        AccountStorageHeader,
180        StorageMapWitness,
181        StorageSlotContent,
182        StorageSlotHeader,
183    };
184    pub use miden_protocol::asset::{
185        Asset,
186        AssetAmount,
187        AssetCallbackFlag,
188        AssetCallbacks,
189        AssetComposition,
190        AssetId,
191        AssetVault,
192        AssetVaultKey,
193        AssetWitness,
194        FungibleAsset,
195        NonFungibleAsset,
196        NonFungibleAssetDetails,
197        PartialVault,
198        TokenSymbol,
199    };
200}
201
202/// Provides authentication-related types and functionalities for the Miden
203/// network.
204pub mod auth {
205    pub use miden_protocol::account::auth::{
206        AuthScheme as AuthSchemeId,
207        AuthSecretKey,
208        PublicKey,
209        PublicKeyCommitment,
210        Signature,
211    };
212    pub use miden_standards::AuthMethod;
213    pub use miden_standards::account::auth::{
214        AuthMultisig,
215        AuthMultisigConfig,
216        AuthSingleSig,
217        AuthSingleSigAcl,
218        AuthSingleSigAclConfig,
219        NoAuth,
220    };
221    pub use miden_tx::auth::{BasicAuthenticator, SigningInputs, TransactionAuthenticator};
222
223    pub use crate::account::component::AuthScheme;
224
225    pub const RPO_FALCON_SCHEME_ID: AuthSchemeId = AuthSchemeId::Falcon512Poseidon2;
226    pub const ECDSA_K256_KECCAK_SCHEME_ID: AuthSchemeId = AuthSchemeId::EcdsaK256Keccak;
227}
228
229/// Provides types for working with blocks within the Miden network.
230pub mod block {
231    pub use miden_protocol::block::{BlockHeader, BlockNumber};
232}
233
234/// Provides cryptographic types and utilities used within the Miden rollup
235/// network. It re-exports commonly used types and random number generators like `FeltRng` from
236/// the `miden_standards` crate.
237pub mod crypto {
238    pub mod rpo_falcon512 {
239        pub use miden_protocol::crypto::dsa::falcon512_poseidon2::{
240            PublicKey,
241            SecretKey,
242            Signature,
243        };
244    }
245    pub use miden_protocol::crypto::hash::blake::Blake3Digest;
246    pub use miden_protocol::crypto::hash::poseidon2::Poseidon2;
247    pub use miden_protocol::crypto::hash::rpo::Rpo256;
248    pub use miden_protocol::crypto::merkle::mmr::{
249        Forest,
250        InOrderIndex,
251        MmrDelta,
252        MmrPeaks,
253        MmrProof,
254        PartialMmr,
255    };
256    pub use miden_protocol::crypto::merkle::smt::{
257        LeafIndex,
258        SMT_DEPTH,
259        Smt,
260        SmtForest,
261        SmtLeaf,
262        SmtProof,
263    };
264    pub use miden_protocol::crypto::merkle::store::MerkleStore;
265    pub use miden_protocol::crypto::merkle::{
266        EmptySubtreeRoots,
267        MerkleError,
268        MerklePath,
269        MerkleTree,
270        NodeIndex,
271        SparseMerklePath,
272    };
273    pub use miden_protocol::crypto::rand::{FeltRng, RandomCoin};
274}
275
276/// Provides types for working with addresses within the Miden network.
277pub mod address {
278    pub use miden_protocol::address::{
279        Address,
280        AddressId,
281        AddressInterface,
282        CustomNetworkId,
283        NetworkId,
284        RoutingParameters,
285    };
286}
287
288/// Provides types for working with the virtual machine within the Miden network.
289pub mod vm {
290    pub use miden_protocol::vm::{
291        AdviceInputs,
292        AdviceMap,
293        AttributeSet,
294        MIN_STACK_DEPTH,
295        Package,
296        PackageExport,
297        PackageManifest,
298        ProcedureExport,
299        Program,
300        QualifiedProcedureName,
301        Section,
302        SectionId,
303        TargetType,
304    };
305}
306
307pub use async_trait::async_trait;
308pub use errors::*;
309use miden_protocol::assembly::SourceManagerSync;
310pub use miden_protocol::{
311    EMPTY_WORD,
312    Felt,
313    MAX_TX_EXECUTION_CYCLES,
314    MIN_TX_EXECUTION_CYCLES,
315    ONE,
316    PrettyPrint,
317    WORD_SIZE,
318    Word,
319    ZERO,
320};
321pub use miden_remote_prover_client::RemoteTransactionProver;
322pub use miden_tx::ExecutionOptions;
323
324/// Provides test utilities for working with accounts and account IDs
325/// within the Miden network. This module is only available when the `testing` feature is
326/// enabled.
327#[cfg(feature = "testing")]
328pub mod testing {
329    pub use miden_protocol::testing::account_id;
330    /// Raw access to `miden-standards` testing modules for items not curated by
331    /// `miden-client`.
332    pub use miden_standards::testing as standards;
333    pub use miden_standards::testing::note::NoteBuilder;
334    pub use miden_testing::*;
335
336    pub use crate::test_utils::*;
337}
338
339use alloc::sync::Arc;
340
341use miden_protocol::block::BlockNumber;
342use miden_protocol::crypto::merkle::mmr::PartialMmr;
343use miden_protocol::crypto::rand::FeltRng;
344use miden_tx::auth::TransactionAuthenticator;
345use rand::RngCore;
346use rpc::NodeRpcClient;
347use store::Store;
348
349use crate::note_transport::NoteTransportClient;
350use crate::transaction::TransactionProver;
351
352// MIDEN CLIENT
353// ================================================================================================
354
355/// A light client for connecting to the Miden network.
356///
357/// Miden client is responsible for managing a set of accounts. Specifically, the client:
358/// - Keeps track of the current and historical states of a set of accounts and related objects such
359///   as notes and transactions.
360/// - Connects to a Miden node to periodically sync with the current state of the network.
361/// - Executes, proves, and submits transactions to the network as directed by the user.
362pub struct Client<AUTH> {
363    /// The client's store, which provides a way to write and read entities to provide persistence.
364    store: Arc<dyn Store>,
365    /// An instance of [`FeltRng`] which provides randomness tools for generating new keys,
366    /// serial numbers, etc.
367    rng: ClientRng,
368    /// An instance of [`NodeRpcClient`] which provides a way for the client to connect to the
369    /// Miden node.
370    rpc_api: Arc<dyn NodeRpcClient>,
371    /// An instance of a [`TransactionProver`] which will be the default prover for the
372    /// client.
373    tx_prover: Arc<dyn TransactionProver + Send + Sync>,
374    /// An instance of a [`TransactionAuthenticator`] which will be used by the transaction
375    /// executor whenever a signature is requested from within the VM.
376    authenticator: Option<Arc<AUTH>>,
377    /// Shared source manager used to retain MASM source information for assembled programs.
378    source_manager: Arc<dyn SourceManagerSync>,
379    /// Options that control the transaction executor's runtime behaviour (e.g. debug mode).
380    exec_options: ExecutionOptions,
381    /// Number of blocks after which pending transactions are considered stale and discarded.
382    tx_discard_delta: Option<u32>,
383    /// Number of synced blocks between automatic irrelevant-block pruning runs.
384    irrelevant_block_prune_interval: Option<u32>,
385    /// Sync height at which the last automatic irrelevant-block prune completed.
386    last_irrelevant_block_prune_sync_height: Option<BlockNumber>,
387    /// Maximum number of blocks the client can be behind the network for transactions and account
388    /// proofs to be considered valid.
389    max_block_number_delta: Option<u32>,
390    /// An instance of [`NoteTransportClient`] which provides a way for the client to connect to
391    /// the Miden Note Transport network.
392    note_transport_api: Option<Arc<dyn NoteTransportClient>>,
393    /// Whether the client should cache the current Partial MMR in memory.
394    cache_partial_mmr_in_memory: bool,
395    /// Cached [`PartialMmr`] for the chain's MMR. Lazily built from the store and kept in sync
396    /// across sync/prune operations. `None` forces a rebuild on next access.
397    partial_mmr: Option<CachedPartialMmr>,
398}
399
400/// Cached [`PartialMmr`] with a two-part freshness fingerprint:
401///
402/// - `store_peaks_hash`: peaks at the current sync height - guards against chain/height drift.
403/// - `tracked_blocks_hash`: hash of the store's tracked block numbers - guards against drift
404///   between store-tracked and cache-tracked blocks. Required because a same-height update can mark
405///   an existing block relevant without changing peaks; pruning the cached MMR while it's missing
406///   such a block would over-delete auth nodes that the store still needs.
407///
408/// The cached MMR includes the sync-height block as a tracked leaf; the store persists the
409/// peaks committed by that block's header, i.e. the peaks over the chain *before* that block
410/// was added, so the two states are offset by one leaf.
411pub(crate) struct CachedPartialMmr {
412    pub(crate) store_peaks_hash: Word,
413    pub(crate) tracked_blocks_hash: Word,
414    pub(crate) mmr: PartialMmr,
415}
416
417/// Constructors.
418impl<AUTH> Client<AUTH>
419where
420    AUTH: builder::BuilderAuthenticator,
421{
422    /// Returns a new [`ClientBuilder`](builder::ClientBuilder) for constructing a client.
423    ///
424    /// This is a convenience method equivalent to calling `ClientBuilder::new()`.
425    ///
426    /// # Example
427    ///
428    /// ```ignore
429    /// let client = Client::builder()
430    ///     .rpc(rpc_client)
431    ///     .store(store)
432    ///     .authenticator(Arc::new(keystore))
433    ///     .build()
434    ///     .await?;
435    /// ```
436    pub fn builder() -> builder::ClientBuilder<AUTH> {
437        builder::ClientBuilder::new()
438    }
439}
440
441/// Access methods.
442impl<AUTH> Client<AUTH>
443where
444    AUTH: TransactionAuthenticator,
445{
446    /// Returns true if the client is in debug mode.
447    pub fn in_debug_mode(&self) -> bool {
448        self.exec_options.enable_debugging()
449    }
450
451    /// Returns an instance of the `CodeBuilder`
452    pub fn code_builder(&self) -> assembly::CodeBuilder {
453        assembly::CodeBuilder::with_source_manager(self.source_manager.clone())
454    }
455
456    /// Returns an instance of [`note::NoteScreener`] configured for this client.
457    pub fn note_screener(&self) -> note::NoteScreener {
458        note::NoteScreener::new(self.store.clone(), self.rpc_api.clone())
459    }
460
461    /// Returns a reference to the client's random number generator. This can be used to generate
462    /// randomness for various purposes such as serial numbers, keys, etc.
463    pub fn rng(&mut self) -> &mut ClientRng {
464        &mut self.rng
465    }
466
467    pub fn prover(&self) -> Arc<dyn TransactionProver + Send + Sync> {
468        self.tx_prover.clone()
469    }
470
471    pub fn authenticator(&self) -> Option<&Arc<AUTH>> {
472        self.authenticator.as_ref()
473    }
474
475    /// Returns the shared source manager used to retain MASM source information for assembled
476    /// programs.
477    pub fn source_manager(&self) -> Arc<dyn SourceManagerSync> {
478        self.source_manager.clone()
479    }
480}
481
482impl<AUTH> Client<AUTH> {
483    /// Returns the identifier of the underlying store (e.g. `IndexedDB` database name, `SQLite`
484    /// file path).
485    pub fn store_identifier(&self) -> &str {
486        self.store.identifier()
487    }
488
489    /// Returns the network ID of the node the client is connected to.
490    pub async fn network_id(&self) -> Result<address::NetworkId, ClientError> {
491        Ok(self.rpc_api.get_network_id().await?)
492    }
493
494    // TEST HELPERS
495    // --------------------------------------------------------------------------------------------
496
497    #[cfg(any(test, feature = "testing"))]
498    pub fn test_rpc_api(&mut self) -> &mut Arc<dyn NodeRpcClient> {
499        &mut self.rpc_api
500    }
501
502    #[cfg(any(test, feature = "testing"))]
503    pub fn test_store(&mut self) -> &mut Arc<dyn Store> {
504        &mut self.store
505    }
506
507    #[cfg(any(test, feature = "testing"))]
508    pub fn test_has_cached_partial_mmr(&self) -> bool {
509        self.partial_mmr.is_some()
510    }
511}
512
513// CLIENT RNG
514// ================================================================================================
515
516// NOTE: The idea of having `ClientRng` is to enforce `Send` and `Sync` over `FeltRng`.
517// This allows `Client`` to be `Send` and `Sync`. There may be users that would want to use clients
518// with !Send/!Sync RNGs. For this we have two options:
519//
520// - We can make client generic over R (adds verbosity but is more flexible and maybe even correct)
521// - We can optionally (e.g., based on features/target) change `ClientRng` definition to not enforce
522//   these bounds. (similar to TransactionAuthenticator)
523
524/// Marker trait for RNGs that can be shared across threads and used by the client.
525pub trait ClientFeltRng: FeltRng + Send + Sync {}
526impl<T> ClientFeltRng for T where T: FeltRng + Send + Sync {}
527
528/// Boxed RNG trait object used by the client.
529pub type ClientRngBox = Box<dyn ClientFeltRng>;
530
531/// A wrapper around a [`FeltRng`] that implements the [`RngCore`] trait.
532/// This allows the user to pass their own generic RNG so that it's used by the client.
533pub struct ClientRng(ClientRngBox);
534
535impl ClientRng {
536    pub fn new(rng: ClientRngBox) -> Self {
537        Self(rng)
538    }
539
540    pub fn inner_mut(&mut self) -> &mut ClientRngBox {
541        &mut self.0
542    }
543}
544
545impl RngCore for ClientRng {
546    fn next_u32(&mut self) -> u32 {
547        self.0.next_u32()
548    }
549
550    fn next_u64(&mut self) -> u64 {
551        self.0.next_u64()
552    }
553
554    fn fill_bytes(&mut self, dest: &mut [u8]) {
555        self.0.fill_bytes(dest);
556    }
557}
558
559impl FeltRng for ClientRng {
560    fn draw_element(&mut self) -> Felt {
561        self.0.draw_element()
562    }
563
564    fn draw_word(&mut self) -> Word {
565        self.0.draw_word()
566    }
567}
568
569/// Indicates whether the client is operating in debug mode.
570#[derive(Debug, Clone, Copy)]
571pub enum DebugMode {
572    Enabled,
573    Disabled,
574}
575
576impl From<DebugMode> for bool {
577    fn from(debug_mode: DebugMode) -> Self {
578        match debug_mode {
579            DebugMode::Enabled => true,
580            DebugMode::Disabled => false,
581        }
582    }
583}
584
585impl From<bool> for DebugMode {
586    fn from(debug_mode: bool) -> DebugMode {
587        if debug_mode {
588            DebugMode::Enabled
589        } else {
590            DebugMode::Disabled
591        }
592    }
593}
594
595#[cfg(test)]
596mod tests {
597    use super::Client;
598
599    fn assert_send_sync<T: Send + Sync>() {}
600
601    #[test]
602    fn client_is_send_sync() {
603        assert_send_sync::<Client<()>>();
604    }
605}