1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
#![no_std]
#[macro_use]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
pub mod accounts;
pub mod config;
mod errors;
pub mod notes;
pub mod rpc;
pub mod store;
mod store_authenticator;
pub mod sync;
pub mod transactions;
#[cfg(test)]
pub mod mock;
#[cfg(test)]
pub mod tests;
// RE-EXPORTS
// ================================================================================================
pub mod assets {
pub use miden_objects::{
accounts::delta::{
AccountVaultDelta, FungibleAssetDelta, NonFungibleAssetDelta, NonFungibleDeltaAction,
},
assets::{Asset, AssetVault, FungibleAsset, NonFungibleAsset, TokenSymbol},
};
}
pub mod auth {
pub use miden_objects::accounts::AuthSecretKey;
pub use miden_tx::auth::TransactionAuthenticator;
pub use crate::store_authenticator::StoreAuthenticator;
}
pub mod blocks {
pub use miden_objects::BlockHeader;
}
pub mod crypto {
pub use miden_objects::{
crypto::{
merkle::{
InOrderIndex, LeafIndex, MerklePath, MmrDelta, MmrPeaks, MmrProof, SmtLeaf,
SmtProof,
},
rand::{FeltRng, RpoRandomCoin},
},
Digest,
};
}
pub use errors::{ClientError, IdPrefixFetchError};
pub use miden_objects::{Felt, StarkField, Word, ONE, ZERO};
pub mod utils {
pub use miden_tx::utils::{
bytes_to_hex_string, ByteReader, ByteWriter, Deserializable, DeserializationError,
Serializable,
};
}
#[cfg(feature = "testing")]
pub mod testing {
pub use miden_objects::accounts::account_id::testing::*;
}
use alloc::{rc::Rc, vec::Vec};
use miden_objects::crypto::rand::FeltRng;
use miden_tx::{auth::TransactionAuthenticator, TransactionExecutor};
use rpc::NodeRpcClient;
use store::{data_store::ClientDataStore, Store};
use tracing::info;
// MIDEN CLIENT
// ================================================================================================
/// A light client for connecting to the Miden rollup network.
///
/// Miden client is responsible for managing a set of accounts. Specifically, the client:
/// - Keeps track of the current and historical states of a set of accounts and related objects such
/// as notes and transactions.
/// - Connects to one or more Miden nodes to periodically sync with the current state of the
/// network.
/// - Executes, proves, and submits transactions to the network as directed by the user.
pub struct Client<N: NodeRpcClient, R: FeltRng, S: Store, A: TransactionAuthenticator> {
/// The client's store, which provides a way to write and read entities to provide persistence.
store: Rc<S>,
/// An instance of [FeltRng] which provides randomness tools for generating new keys,
/// serial numbers, etc.
rng: R,
/// An instance of [NodeRpcClient] which provides a way for the client to connect to the
/// Miden node.
rpc_api: N,
tx_executor: TransactionExecutor<ClientDataStore<S>, A>,
}
impl<N: NodeRpcClient, R: FeltRng, S: Store, A: TransactionAuthenticator> Client<N, R, S, A> {
// CONSTRUCTOR
// --------------------------------------------------------------------------------------------
/// Returns a new instance of [Client].
///
/// ## Arguments
///
/// - `api`: An instance of [NodeRpcClient] which provides a way for the client to connect to
/// the Miden node.
/// - `store`: An instance of [Store], which provides a way to write and read entities to
/// provide persistence.
/// - `executor_store`: An instance of [Store] that provides a way for [TransactionExecutor] to
/// retrieve relevant inputs at the moment of transaction execution. It should be the same
/// store as the one for `store`, but it doesn't have to be the **same instance**.
/// - `authenticator`: Defines the transaction authenticator that will be used by the
/// transaction executor whenever a signature is requested from within the VM.
/// - `in_debug_mode`: Instantiates the transaction executor (and in turn, its compiler) in
/// debug mode, which will enable debug logs for scripts compiled with this mode for easier
/// MASM debugging.
///
/// # Errors
///
/// Returns an error if the client could not be instantiated.
pub fn new(api: N, rng: R, store: Rc<S>, authenticator: A, in_debug_mode: bool) -> Self {
if in_debug_mode {
info!("Creating the Client in debug mode.");
}
let data_store = ClientDataStore::new(store.clone());
let authenticator = Some(Rc::new(authenticator));
let tx_executor =
TransactionExecutor::new(data_store, authenticator).with_debug_mode(in_debug_mode);
Self { store, rng, rpc_api: api, tx_executor }
}
/// Returns a reference to the client's random number generator. This can be used to generate
/// randomness for various purposes such as serial numbers, keys, etc.
pub fn rng(&mut self) -> &mut R {
&mut self.rng
}
// TEST HELPERS
// --------------------------------------------------------------------------------------------
#[cfg(any(test, feature = "testing"))]
pub fn rpc_api(&mut self) -> &mut N {
&mut self.rpc_api
}
// TODO: the idxdb feature access here is temporary and should be removed in the future once
// a good solution to the syncrhonous store access in the store authenticator is found.
// https://github.com/0xPolygonMiden/miden-base/issues/705
#[cfg(any(test, feature = "testing", feature = "idxdb"))]
pub fn store(&mut self) -> &S {
&self.store
}
#[cfg(any(test, feature = "testing"))]
#[winter_maybe_async::maybe_async]
pub fn get_block_headers(
&self,
block_numbers: &[u32],
) -> Result<Vec<(miden_objects::BlockHeader, bool)>, crate::ClientError> {
let result = winter_maybe_async::maybe_await!(self.store.get_block_headers(block_numbers))?;
Ok(result)
}
}