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://0xMiden.github.io/miden-docs/).
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::{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 pub use miden_protocol::assembly::diagnostics::Report;
152 pub use miden_protocol::assembly::diagnostics::reporting::PrintDiagnostic;
153 pub use miden_protocol::assembly::mast::MastNodeExt;
154 pub use miden_protocol::assembly::{
155 Assembler,
156 DefaultSourceManager,
157 Library,
158 Module,
159 ModuleKind,
160 Path,
161 };
162 pub use miden_standards::code_builder::CodeBuilder;
163}
164
165/// Provides types and utilities for working with assets within the Miden network.
166pub mod asset {
167 pub use miden_protocol::account::delta::{
168 AccountStorageDelta,
169 AccountVaultDelta,
170 FungibleAssetDelta,
171 NonFungibleAssetDelta,
172 NonFungibleDeltaAction,
173 };
174 pub use miden_protocol::account::{
175 AccountStorageHeader,
176 StorageMapWitness,
177 StorageSlotContent,
178 StorageSlotHeader,
179 };
180 pub use miden_protocol::asset::{
181 Asset,
182 AssetVault,
183 AssetVaultKey,
184 AssetWitness,
185 FungibleAsset,
186 NonFungibleAsset,
187 NonFungibleAssetDetails,
188 PartialVault,
189 TokenSymbol,
190 };
191}
192
193/// Provides authentication-related types and functionalities for the Miden
194/// network.
195pub mod auth {
196 pub use miden_protocol::account::auth::{
197 AuthScheme as AuthSchemeId,
198 AuthSecretKey,
199 PublicKey,
200 PublicKeyCommitment,
201 Signature,
202 };
203 pub use miden_standards::account::auth::{
204 AuthMultisig,
205 AuthMultisigConfig,
206 AuthSingleSig,
207 AuthSingleSigAcl,
208 AuthSingleSigAclConfig,
209 NoAuth,
210 };
211 pub use miden_tx::auth::{BasicAuthenticator, SigningInputs, TransactionAuthenticator};
212
213 pub use crate::account::component::AuthScheme;
214
215 pub const RPO_FALCON_SCHEME_ID: AuthSchemeId = AuthSchemeId::Falcon512Rpo;
216 pub const ECDSA_K256_KECCAK_SCHEME_ID: AuthSchemeId = AuthSchemeId::EcdsaK256Keccak;
217}
218
219/// Provides types for working with blocks within the Miden network.
220pub mod block {
221 pub use miden_protocol::block::{BlockHeader, BlockNumber};
222}
223
224/// Provides cryptographic types and utilities used within the Miden rollup
225/// network. It re-exports commonly used types and random number generators like `FeltRng` from
226/// the `miden_standards` crate.
227pub mod crypto {
228 pub mod rpo_falcon512 {
229 pub use miden_protocol::crypto::dsa::falcon512_rpo::{PublicKey, SecretKey, Signature};
230 }
231 pub use miden_protocol::crypto::hash::blake::{Blake3_160, Blake3Digest};
232 pub use miden_protocol::crypto::hash::rpo::Rpo256;
233 pub use miden_protocol::crypto::merkle::mmr::{
234 Forest,
235 InOrderIndex,
236 MmrDelta,
237 MmrPeaks,
238 MmrProof,
239 PartialMmr,
240 };
241 pub use miden_protocol::crypto::merkle::smt::{
242 LeafIndex,
243 SMT_DEPTH,
244 Smt,
245 SmtForest,
246 SmtLeaf,
247 SmtProof,
248 };
249 pub use miden_protocol::crypto::merkle::store::MerkleStore;
250 pub use miden_protocol::crypto::merkle::{
251 EmptySubtreeRoots,
252 MerkleError,
253 MerklePath,
254 MerkleTree,
255 NodeIndex,
256 SparseMerklePath,
257 };
258 pub use miden_protocol::crypto::rand::{FeltRng, RpoRandomCoin};
259}
260
261/// Provides types for working with addresses within the Miden network.
262pub mod address {
263 pub use miden_protocol::address::{
264 Address,
265 AddressId,
266 AddressInterface,
267 CustomNetworkId,
268 NetworkId,
269 RoutingParameters,
270 };
271}
272
273/// Provides types for working with the virtual machine within the Miden network.
274pub mod vm {
275 // TODO: Remove this re-export once miden-protocol exposes PackageKind/ProcedureExport.
276 pub use miden_mast_package::{PackageKind, ProcedureExport};
277 pub use miden_protocol::vm::{
278 AdviceInputs,
279 AdviceMap,
280 AttributeSet,
281 MastArtifact,
282 Package,
283 PackageExport,
284 PackageManifest,
285 Program,
286 QualifiedProcedureName,
287 Section,
288 SectionId,
289 };
290}
291
292pub use async_trait::async_trait;
293pub use errors::*;
294use miden_protocol::assembly::SourceManagerSync;
295pub use miden_protocol::{
296 EMPTY_WORD,
297 Felt,
298 MAX_TX_EXECUTION_CYCLES,
299 MIN_TX_EXECUTION_CYCLES,
300 ONE,
301 PrettyPrint,
302 StarkField,
303 Word,
304 ZERO,
305};
306pub use miden_remote_prover_client::RemoteTransactionProver;
307pub use miden_tx::ExecutionOptions;
308
309/// Provides test utilities for working with accounts and account IDs
310/// within the Miden network. This module is only available when the `testing` feature is
311/// enabled.
312#[cfg(feature = "testing")]
313pub mod testing {
314 pub use miden_protocol::testing::account_id;
315 pub use miden_standards::testing::note::NoteBuilder;
316 pub use miden_standards::testing::*;
317 pub use miden_testing::*;
318
319 pub use crate::test_utils::*;
320}
321
322use alloc::sync::Arc;
323
324use miden_protocol::crypto::rand::FeltRng;
325use miden_tx::auth::TransactionAuthenticator;
326use rand::RngCore;
327use rpc::NodeRpcClient;
328use store::Store;
329
330use crate::note_transport::NoteTransportClient;
331use crate::transaction::TransactionProver;
332
333// MIDEN CLIENT
334// ================================================================================================
335
336/// A light client for connecting to the Miden network.
337///
338/// Miden client is responsible for managing a set of accounts. Specifically, the client:
339/// - Keeps track of the current and historical states of a set of accounts and related objects such
340/// as notes and transactions.
341/// - Connects to a Miden node to periodically sync with the current state of the network.
342/// - Executes, proves, and submits transactions to the network as directed by the user.
343pub struct Client<AUTH> {
344 /// The client's store, which provides a way to write and read entities to provide persistence.
345 store: Arc<dyn Store>,
346 /// An instance of [`FeltRng`] which provides randomness tools for generating new keys,
347 /// serial numbers, etc.
348 rng: ClientRng,
349 /// An instance of [`NodeRpcClient`] which provides a way for the client to connect to the
350 /// Miden node.
351 rpc_api: Arc<dyn NodeRpcClient>,
352 /// An instance of a [`TransactionProver`] which will be the default prover for the
353 /// client.
354 tx_prover: Arc<dyn TransactionProver + Send + Sync>,
355 /// An instance of a [`TransactionAuthenticator`] which will be used by the transaction
356 /// executor whenever a signature is requested from within the VM.
357 authenticator: Option<Arc<AUTH>>,
358 /// Shared source manager used to retain MASM source information for assembled programs.
359 source_manager: Arc<dyn SourceManagerSync>,
360 /// Options that control the transaction executor's runtime behaviour (e.g. debug mode).
361 exec_options: ExecutionOptions,
362 /// Number of blocks after which pending transactions are considered stale and discarded.
363 tx_discard_delta: Option<u32>,
364 /// Maximum number of blocks the client can be behind the network for transactions and account
365 /// proofs to be considered valid.
366 max_block_number_delta: Option<u32>,
367 /// An instance of [`NoteTransportClient`] which provides a way for the client to connect to
368 /// the Miden Note Transport network.
369 note_transport_api: Option<Arc<dyn NoteTransportClient>>,
370}
371
372/// Constructors.
373impl<AUTH> Client<AUTH>
374where
375 AUTH: builder::BuilderAuthenticator,
376{
377 /// Returns a new [`ClientBuilder`](builder::ClientBuilder) for constructing a client.
378 ///
379 /// This is a convenience method equivalent to calling `ClientBuilder::new()`.
380 ///
381 /// # Example
382 ///
383 /// ```ignore
384 /// let client = Client::builder()
385 /// .rpc(rpc_client)
386 /// .store(store)
387 /// .authenticator(Arc::new(keystore))
388 /// .build()
389 /// .await?;
390 /// ```
391 pub fn builder() -> builder::ClientBuilder<AUTH> {
392 builder::ClientBuilder::new()
393 }
394}
395
396/// Access methods.
397impl<AUTH> Client<AUTH>
398where
399 AUTH: TransactionAuthenticator,
400{
401 /// Returns true if the client is in debug mode.
402 pub fn in_debug_mode(&self) -> bool {
403 self.exec_options.enable_debugging()
404 }
405
406 /// Returns an instance of the `CodeBuilder`
407 pub fn code_builder(&self) -> assembly::CodeBuilder {
408 assembly::CodeBuilder::with_source_manager(self.source_manager.clone())
409 }
410
411 /// Returns an instance of [`note::NoteScreener`] configured for this client.
412 pub fn note_screener(&self) -> note::NoteScreener<AUTH>
413 where
414 AUTH: Sync,
415 {
416 note::NoteScreener::new(self.store.clone(), self.authenticator.clone())
417 }
418
419 /// Returns a reference to the client's random number generator. This can be used to generate
420 /// randomness for various purposes such as serial numbers, keys, etc.
421 pub fn rng(&mut self) -> &mut ClientRng {
422 &mut self.rng
423 }
424
425 pub fn prover(&self) -> Arc<dyn TransactionProver + Send + Sync> {
426 self.tx_prover.clone()
427 }
428}
429
430impl<AUTH> Client<AUTH> {
431 // LIMITS
432 // --------------------------------------------------------------------------------------------
433
434 /// Checks if the note tag limit has been exceeded.
435 pub async fn check_note_tag_limit(&self) -> Result<(), ClientError> {
436 let limits = self.rpc_api.get_rpc_limits().await?;
437 if self.store.get_unique_note_tags().await?.len() >= limits.note_tags_limit as usize {
438 return Err(ClientError::NoteTagsLimitExceeded(limits.note_tags_limit));
439 }
440 Ok(())
441 }
442
443 /// Checks if the account limit has been exceeded.
444 pub async fn check_account_limit(&self) -> Result<(), ClientError> {
445 let limits = self.rpc_api.get_rpc_limits().await?;
446 if self.store.get_account_ids().await?.len() >= limits.account_ids_limit as usize {
447 return Err(ClientError::AccountsLimitExceeded(limits.account_ids_limit));
448 }
449 Ok(())
450 }
451
452 // TEST HELPERS
453 // --------------------------------------------------------------------------------------------
454
455 #[cfg(any(test, feature = "testing"))]
456 pub fn test_rpc_api(&mut self) -> &mut Arc<dyn NodeRpcClient> {
457 &mut self.rpc_api
458 }
459
460 #[cfg(any(test, feature = "testing"))]
461 pub fn test_store(&mut self) -> &mut Arc<dyn Store> {
462 &mut self.store
463 }
464}
465
466// CLIENT RNG
467// ================================================================================================
468
469// NOTE: The idea of having `ClientRng` is to enforce `Send` and `Sync` over `FeltRng`.
470// This allows `Client`` to be `Send` and `Sync`. There may be users that would want to use clients
471// with !Send/!Sync RNGs. For this we have two options:
472//
473// - We can make client generic over R (adds verbosity but is more flexible and maybe even correct)
474// - We can optionally (e.g., based on features/target) change `ClientRng` definition to not enforce
475// these bounds. (similar to TransactionAuthenticator)
476
477/// Marker trait for RNGs that can be shared across threads and used by the client.
478pub trait ClientFeltRng: FeltRng + Send + Sync {}
479impl<T> ClientFeltRng for T where T: FeltRng + Send + Sync {}
480
481/// Boxed RNG trait object used by the client.
482pub type ClientRngBox = Box<dyn ClientFeltRng>;
483
484/// A wrapper around a [`FeltRng`] that implements the [`RngCore`] trait.
485/// This allows the user to pass their own generic RNG so that it's used by the client.
486pub struct ClientRng(ClientRngBox);
487
488impl ClientRng {
489 pub fn new(rng: ClientRngBox) -> Self {
490 Self(rng)
491 }
492
493 pub fn inner_mut(&mut self) -> &mut ClientRngBox {
494 &mut self.0
495 }
496}
497
498impl RngCore for ClientRng {
499 fn next_u32(&mut self) -> u32 {
500 self.0.next_u32()
501 }
502
503 fn next_u64(&mut self) -> u64 {
504 self.0.next_u64()
505 }
506
507 fn fill_bytes(&mut self, dest: &mut [u8]) {
508 self.0.fill_bytes(dest);
509 }
510}
511
512impl FeltRng for ClientRng {
513 fn draw_element(&mut self) -> Felt {
514 self.0.draw_element()
515 }
516
517 fn draw_word(&mut self) -> Word {
518 self.0.draw_word()
519 }
520}
521
522/// Indicates whether the client is operating in debug mode.
523#[derive(Debug, Clone, Copy)]
524pub enum DebugMode {
525 Enabled,
526 Disabled,
527}
528
529impl From<DebugMode> for bool {
530 fn from(debug_mode: DebugMode) -> Self {
531 match debug_mode {
532 DebugMode::Enabled => true,
533 DebugMode::Disabled => false,
534 }
535 }
536}
537
538impl From<bool> for DebugMode {
539 fn from(debug_mode: bool) -> DebugMode {
540 if debug_mode {
541 DebugMode::Enabled
542 } else {
543 DebugMode::Disabled
544 }
545 }
546}
547
548#[cfg(test)]
549mod tests {
550 use super::Client;
551
552 fn assert_send_sync<T: Send + Sync>() {}
553
554 #[test]
555 fn client_is_send_sync() {
556 assert_send_sync::<Client<()>>();
557 }
558}