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