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