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 [Miden
9//! 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//! - **`AggLayer`:** Bridge account components, note constructors, and Ethereum-compatible helper
40//! types from the Miden `AggLayer` protocol crate.
41//!
42//! The library is designed to work in both `no_std` and `std` environments and is configurable via
43//! Cargo features.
44//!
45//! ## Usage
46//!
47//! To use the Miden client library in your project, add it as a dependency in your `Cargo.toml`:
48//!
49//! ```toml
50//! [dependencies]
51//! miden-client = "0.10"
52//! ```
53//!
54//! ## Example
55//!
56//! Below is a brief example illustrating how to instantiate the client using `ClientBuilder`:
57//!
58//! ```rust,ignore
59//! use std::sync::Arc;
60//!
61//! use miden_client::builder::ClientBuilder;
62//! use miden_client::keystore::FilesystemKeyStore;
63//! use miden_client::rpc::{Endpoint, GrpcClient, VerifyingRpcClient};
64//! use miden_client_sqlite_store::SqliteStore;
65//!
66//! # pub async fn create_test_client() -> Result<(), Box<dyn std::error::Error>> {
67//! // Create the SQLite store.
68//! let sqlite_store = SqliteStore::new("path/to/store".try_into()?).await?;
69//! let store = Arc::new(sqlite_store);
70//!
71//! // Create the keystore for transaction signing.
72//! let keystore = FilesystemKeyStore::new("path/to/keys/directory".try_into()?)?;
73//!
74//! // Create the RPC client.
75//! let endpoint = Endpoint::new("https".into(), "localhost".into(), Some(57291));
76//!
77//! // Instantiate the client using the builder.
78//! let client = ClientBuilder::new()
79//! .rpc(Arc::new(VerifyingRpcClient::new(GrpcClient::new(&endpoint, 10_000))))
80//! .store(store)
81//! .authenticator(Arc::new(keystore))
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 protocol_config;
125pub mod pswap;
126#[cfg(feature = "tonic")]
127pub mod remote_prover;
128pub mod rpc;
129pub mod settings;
130pub mod store;
131pub mod sync;
132pub mod transaction;
133pub mod utils;
134
135pub mod builder;
136pub mod rng;
137
138#[cfg(feature = "testing")]
139mod test_utils;
140
141pub mod errors;
142
143pub use miden_protocol::utils::serde::{Deserializable, Serializable, SliceReader};
144
145// RE-EXPORTS
146// ================================================================================================
147
148/// Provides `AggLayer` bridge components, note constructors, and helper types.
149pub mod agglayer {
150 pub use miden_agglayer::*;
151 pub use miden_standards::interop::eth::{
152 AddressConversionError,
153 EthAddress,
154 EthAmount,
155 EthAmountError,
156 EthEmbeddedAccountId,
157 };
158}
159
160/// Provides types and utilities for working with Miden Assembly.
161pub mod assembly {
162 pub use miden_protocol::MastForest;
163 pub use miden_protocol::assembly::debuginfo::SourceManagerSync;
164 #[cfg(feature = "std")]
165 pub use miden_protocol::assembly::debuginfo::{SourceManagerExt, Uri};
166 pub use miden_protocol::assembly::diagnostics::Report;
167 pub use miden_protocol::assembly::diagnostics::reporting::PrintDiagnostic;
168 pub use miden_protocol::assembly::mast::MastNodeExt;
169 pub use miden_protocol::assembly::{Assembler, DefaultSourceManager, Module, ModuleKind, Path};
170 pub use miden_standards::code_builder::CodeBuilder;
171}
172
173/// Provides types and utilities for working with assets within the Miden network.
174pub mod asset {
175 pub use miden_protocol::account::delta::AccountVaultDelta;
176 pub use miden_protocol::account::{
177 AccountStorageHeader,
178 AssetCallbackFlag,
179 StorageMapWitness,
180 StorageSlotContent,
181 StorageSlotHeader,
182 };
183 pub use miden_protocol::asset::{
184 Asset,
185 AssetAmount,
186 AssetCallbacks,
187 AssetComposition,
188 AssetId,
189 AssetVault,
190 AssetWitness,
191 FungibleAsset,
192 NonFungibleAsset,
193 NonFungibleAssetDetails,
194 PartialVault,
195 TokenSymbol,
196 };
197}
198
199/// Provides authentication-related types and functionalities for the Miden network.
200pub mod auth {
201 pub use miden_protocol::account::auth::{
202 AuthScheme as AuthSchemeId,
203 AuthSecretKey,
204 PublicKey,
205 PublicKeyCommitment,
206 Signature,
207 };
208 pub use miden_standards::account::auth::{
209 Approver,
210 ApproverSet,
211 AuthGuardedMultisig,
212 AuthGuardedMultisigConfig,
213 AuthMultisig,
214 AuthMultisigConfig,
215 AuthMultisigSmart,
216 AuthMultisigSmartConfig,
217 AuthSingleSig,
218 GuardianConfig,
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::account_tree::AccountWitness;
232 pub use miden_protocol::block::{BlockHeader, BlockNumber, FeeParameters, ValidatorConfig};
233}
234
235/// Provides cryptographic types and utilities used within the Miden rollup network. It re-exports
236/// commonly used types and random number generators like `FeltRng` from the `miden_standards`
237/// crate.
238pub mod crypto {
239 pub mod ecdsa_k256_keccak {
240 pub use miden_protocol::crypto::dsa::ecdsa_k256_keccak::{
241 PublicKey,
242 Signature,
243 SigningKey,
244 };
245 }
246 pub mod eddsa_25519_sha512 {
247 pub use miden_protocol::crypto::dsa::eddsa_25519_sha512::{KeyExchangeKey, PublicKey};
248 }
249 pub mod rpo_falcon512 {
250 pub use miden_protocol::crypto::dsa::falcon512_poseidon2::{
251 PublicKey,
252 SecretKey,
253 Signature,
254 };
255 }
256 pub use miden_protocol::crypto::hash::blake::Blake3Digest;
257 pub use miden_protocol::crypto::hash::poseidon2::Poseidon2;
258 pub use miden_protocol::crypto::hash::rpo::Rpo256;
259 pub use miden_protocol::crypto::merkle::mmr::{
260 Forest,
261 InOrderIndex,
262 MmrDelta,
263 MmrPeaks,
264 MmrProof,
265 PartialMmr,
266 };
267 // Forest backend types are re-exported for downstream stores.
268 pub use miden_protocol::crypto::merkle::smt::{
269 Backend,
270 BackendReader,
271 ForestInMemoryBackend,
272 LeafIndex,
273 SMT_DEPTH,
274 Smt,
275 SmtLeaf,
276 SmtProof,
277 VersionId,
278 };
279 pub use miden_protocol::crypto::merkle::store::MerkleStore;
280 pub use miden_protocol::crypto::merkle::{
281 EmptySubtreeRoots,
282 MerkleError,
283 MerklePath,
284 MerkleTree,
285 NodeIndex,
286 SparseMerklePath,
287 };
288 pub use miden_protocol::crypto::rand::FeltRng;
289}
290
291/// Provides types for working with addresses within the Miden network.
292pub mod address {
293 pub use miden_protocol::address::{
294 Address,
295 AddressId,
296 AddressInterface,
297 CustomNetworkId,
298 NetworkId,
299 RoutingParameters,
300 };
301}
302
303/// Provides types for working with the virtual machine within the Miden network.
304pub mod vm {
305 pub use miden_assembly_syntax::ast::types::signatures as typed;
306 pub use miden_processor::ExecutionError;
307 pub use miden_processor::mast::error_code_from_msg;
308 pub use miden_processor::operation::OperationError;
309 pub use miden_protocol::vm::{
310 AdviceInputs,
311 AdviceMap,
312 AttributeSet,
313 MIN_STACK_DEPTH,
314 Package,
315 PackageExport,
316 PackageManifest,
317 ProcedureExport,
318 Program,
319 QualifiedProcedureName,
320 Section,
321 SectionId,
322 TargetType,
323 };
324}
325
326pub use async_trait::async_trait;
327pub use errors::*;
328use miden_protocol::assembly::SourceManagerSync;
329pub use miden_protocol::{
330 EMPTY_WORD,
331 Felt,
332 MAX_TX_EXECUTION_CYCLES,
333 MIN_TX_EXECUTION_CYCLES,
334 ONE,
335 PrettyPrint,
336 WORD_SIZE,
337 Word,
338 ZERO,
339};
340pub use miden_tx::{ExecutionOptions, NetworkNotePricer, NotePricingError};
341#[cfg(feature = "tonic")]
342pub use remote_prover::RemoteTransactionProver;
343
344/// Provides test utilities for working with accounts and account IDs within the Miden network. This
345/// module is only available when the `testing` feature is enabled.
346#[cfg(feature = "testing")]
347pub mod testing {
348 pub use miden_protocol::testing::account_id;
349 /// Raw access to `miden-standards` testing modules for items not curated by `miden-client`.
350 pub use miden_standards::testing as standards;
351 pub use miden_standards::testing::note::NoteBuilder;
352 pub use miden_testing::*;
353 /// The data store the executor reads from, the MAST forest store trait it also serves, and the
354 /// MAST store that [`ClientDataStore::mast_store`] returns. Exposed here so that tests can
355 /// exercise them on their own, without going through a transaction or a note screening pass.
356 pub use miden_tx::{DataStore, MastForestStore, TransactionMastStore};
357
358 pub use crate::store::data_store::ClientDataStore;
359 pub use crate::test_utils::*;
360}
361
362use alloc::sync::Arc;
363use alloc::vec::Vec;
364use core::convert::Infallible;
365
366use miden_protocol::block::BlockNumber;
367use miden_protocol::crypto::merkle::mmr::PartialMmr;
368use miden_protocol::crypto::rand::FeltRng;
369use miden_tx::auth::TransactionAuthenticator;
370use rand::{CryptoRng, TryCryptoRng, TryRng};
371use rpc::NodeRpcClient;
372use store::Store;
373
374use crate::note_transport::NoteTransportClient;
375use crate::transaction::TransactionProver;
376
377// MIDEN CLIENT
378// ================================================================================================
379
380/// A light client for connecting to the Miden network.
381///
382/// Miden client is responsible for managing a set of accounts. Specifically, the client:
383/// - Keeps track of the current and historical states of a set of accounts and related objects such
384/// as notes and transactions.
385/// - Connects to a Miden node to periodically sync with the current state of the network.
386/// - Executes, proves, and submits transactions to the network as directed by the user.
387pub struct Client<AUTH> {
388 /// The client's store, which provides a way to write and read entities to provide persistence.
389 store: Arc<dyn Store>,
390 /// An instance of [`FeltRng`] which provides randomness tools for generating new keys, serial
391 /// numbers, etc.
392 rng: ClientRng,
393 /// An instance of [`NodeRpcClient`] which provides a way for the client to connect to the Miden
394 /// node.
395 rpc_api: Arc<dyn NodeRpcClient>,
396 /// An instance of a [`TransactionProver`] which will be the default prover for the client.
397 tx_prover: Arc<dyn TransactionProver + Send + Sync>,
398 /// An instance of a [`TransactionAuthenticator`] which will be used by the transaction executor
399 /// whenever a signature is requested from within the VM.
400 authenticator: Option<Arc<AUTH>>,
401 /// Shared source manager used to retain MASM source information for assembled programs.
402 source_manager: Arc<dyn SourceManagerSync>,
403 /// Options that control the transaction executor's runtime behaviour (e.g. cycle limits).
404 exec_options: ExecutionOptions,
405 /// Number of blocks after which pending transactions are considered stale and discarded.
406 tx_discard_delta: Option<u32>,
407 /// Number of synced blocks between automatic irrelevant-block pruning runs.
408 irrelevant_block_prune_interval: Option<u32>,
409 /// Sync height at which the last automatic irrelevant-block prune completed.
410 last_irrelevant_block_prune_sync_height: Option<BlockNumber>,
411 /// Maximum number of blocks the client can be behind the network for transactions and account
412 /// proofs to be considered valid.
413 max_block_number_delta: Option<u32>,
414 /// An instance of [`NoteTransportClient`] which provides a way for the client to connect to the
415 /// Miden Note Transport network.
416 note_transport_api: Option<Arc<dyn NoteTransportClient>>,
417 /// Whether the client should cache the current Partial MMR in memory.
418 cache_partial_mmr_in_memory: bool,
419 /// Cached [`PartialMmr`] for the chain's MMR. Lazily built from the store and kept in sync
420 /// across sync/prune operations. `None` forces a rebuild on next access.
421 partial_mmr: Option<CachedPartialMmr>,
422 /// Observers fired by `apply_transaction`. See [`Client::with_transaction_observer`].
423 transaction_observers: Vec<Arc<dyn transaction::TransactionObserver>>,
424}
425
426/// Cached [`PartialMmr`] with a two-part freshness fingerprint:
427///
428/// - `store_peaks_hash`: peaks at the current sync height - guards against chain/height drift.
429/// - `tracked_blocks_hash`: hash of the store's tracked block numbers - guards against drift
430/// between store-tracked and cache-tracked blocks. Required because a same-height update can mark
431/// an existing block relevant without changing peaks; pruning the cached MMR while it's missing
432/// such a block would over-delete auth nodes that the store still needs.
433///
434/// The cached MMR includes the sync-height block as a tracked leaf; the store persists the peaks
435/// committed by that block's header, i.e. the peaks over the chain *before* that block was added,
436/// so the two states are offset by one leaf.
437pub(crate) struct CachedPartialMmr {
438 pub(crate) store_peaks_hash: Word,
439 pub(crate) tracked_blocks_hash: Word,
440 pub(crate) mmr: PartialMmr,
441}
442
443/// Constructors.
444impl<AUTH> Client<AUTH>
445where
446 AUTH: builder::BuilderAuthenticator,
447{
448 /// Returns a new [`ClientBuilder`](builder::ClientBuilder) for constructing a client.
449 ///
450 /// This is a convenience method equivalent to calling `ClientBuilder::new()`.
451 ///
452 /// # Example
453 ///
454 /// ```ignore
455 /// let client = Client::builder()
456 /// .rpc(rpc_client)
457 /// .store(store)
458 /// .authenticator(Arc::new(keystore))
459 /// .build()
460 /// .await?;
461 /// ```
462 pub fn builder() -> builder::ClientBuilder<AUTH> {
463 builder::ClientBuilder::new()
464 }
465}
466
467/// Access methods.
468impl<AUTH> Client<AUTH>
469where
470 AUTH: TransactionAuthenticator,
471{
472 /// Returns an instance of the `CodeBuilder`
473 pub fn code_builder(&self) -> assembly::CodeBuilder {
474 assembly::CodeBuilder::with_source_manager(self.source_manager.clone())
475 }
476
477 /// Returns an instance of [`note::NoteScreener`] configured for this client.
478 pub fn note_screener(&self) -> note::NoteScreener {
479 note::NoteScreener::new(self.store.clone(), self.rpc_api.clone())
480 }
481
482 /// Returns a reference to the client's random number generator. This can be used to generate
483 /// randomness for various purposes such as serial numbers, keys, etc.
484 pub fn rng(&mut self) -> &mut ClientRng {
485 &mut self.rng
486 }
487
488 pub fn prover(&self) -> Arc<dyn TransactionProver + Send + Sync> {
489 self.tx_prover.clone()
490 }
491
492 pub fn authenticator(&self) -> Option<&Arc<AUTH>> {
493 self.authenticator.as_ref()
494 }
495
496 /// Returns the shared source manager used to retain MASM source information for assembled
497 /// programs.
498 pub fn source_manager(&self) -> Arc<dyn SourceManagerSync> {
499 self.source_manager.clone()
500 }
501}
502
503impl<AUTH> Client<AUTH> {
504 /// Returns the identifier of the underlying store (e.g. `IndexedDB` database name, `SQLite`
505 /// file path).
506 pub fn store_identifier(&self) -> &str {
507 self.store.identifier()
508 }
509
510 /// Registers a [`transaction::TransactionObserver`]. Per-observer failures are logged.
511 pub fn with_transaction_observer(
512 &mut self,
513 observer: Arc<dyn transaction::TransactionObserver>,
514 ) {
515 self.transaction_observers.push(observer);
516 }
517
518 /// Returns the network ID of the node the client is connected to.
519 pub async fn network_id(&self) -> Result<address::NetworkId, ClientError> {
520 Ok(self.rpc_api.get_network_id().await?)
521 }
522
523 // TEST HELPERS
524 // --------------------------------------------------------------------------------------------
525
526 #[cfg(any(test, feature = "testing"))]
527 pub fn test_rpc_api(&mut self) -> &mut Arc<dyn NodeRpcClient> {
528 &mut self.rpc_api
529 }
530
531 #[cfg(any(test, feature = "testing"))]
532 pub fn test_store(&mut self) -> &mut Arc<dyn Store> {
533 &mut self.store
534 }
535
536 #[cfg(any(test, feature = "testing"))]
537 pub fn test_has_cached_partial_mmr(&self) -> bool {
538 self.partial_mmr.is_some()
539 }
540}
541
542// CLIENT RNG
543// ================================================================================================
544
545// NOTE: The idea of having `ClientRng` is to enforce `Send` and `Sync` over `FeltRng`. This allows
546// `Client`` to be `Send` and `Sync`. There may be users that would want to use clients with
547// !Send/!Sync RNGs. For this we have two options:
548//
549// - We can make client generic over R (adds verbosity but is more flexible and maybe even correct)
550// - We can optionally (e.g., based on features/target) change `ClientRng` definition to not enforce
551// these bounds. (similar to TransactionAuthenticator)
552
553/// Marker trait for RNGs that can be shared across threads and used by the client.
554pub trait ClientCryptoRng: CryptoRng + Send + Sync {}
555impl<T> ClientCryptoRng for T where T: CryptoRng + Send + Sync {}
556
557/// Boxed RNG trait object used by the client.
558pub type ClientRngBox = Box<dyn ClientCryptoRng>;
559
560/// A wrapper around a [`CryptoRng`] that implements the [`TryRng`] and [`FeltRng`] traits. This
561/// allows the user to pass their own generic RNG so that it's used by the client.
562pub struct ClientRng(ClientRngBox);
563
564impl ClientRng {
565 pub(crate) fn new(rng: ClientRngBox) -> Self {
566 Self(rng)
567 }
568
569 #[cfg(feature = "testing")]
570 pub fn inner_mut(&mut self) -> &mut ClientRngBox {
571 &mut self.0
572 }
573}
574
575impl TryRng for ClientRng {
576 type Error = Infallible;
577
578 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
579 Ok(self.0.next_u32())
580 }
581
582 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
583 Ok(self.0.next_u64())
584 }
585
586 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
587 self.0.fill_bytes(dest);
588 Ok(())
589 }
590}
591
592// Holds because the inner generator is a `CryptoRng` and the delegation above is infallible.
593impl TryCryptoRng for ClientRng {}
594
595impl FeltRng for ClientRng {
596 fn draw_element(&mut self) -> Felt {
597 rng::draw_felt(&mut self.0)
598 }
599
600 fn draw_word(&mut self) -> Word {
601 rng::draw_word(&mut self.0)
602 }
603}
604
605#[cfg(test)]
606mod tests {
607 use super::Client;
608
609 fn assert_send_sync<T: Send + Sync>() {}
610
611 #[test]
612 fn client_is_send_sync() {
613 assert_send_sync::<Client<()>>();
614 }
615}