diff --git a/CHANGELOG.md b/CHANGELOG.md index f65d6f2dd..b083e083b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * [BREAKING] Merged `concurrent` feature with `std` (#974). * [BREAKING] Changed `TransactionRequest` to use expected output recipients instead of output notes (#976). * [BREAKING] Removed `TransactionExecutor` from `Client` and `NoteScreener` (#998). +* [BREAKING] Replace `FeltRng` trait object in `ClientBuilder` and `Client` with generic and remove `ClientRng` (#1015). ### Features diff --git a/bin/miden-cli/src/commands/new_account.rs b/bin/miden-cli/src/commands/new_account.rs index 88a7befd9..c3f302b24 100644 --- a/bin/miden-cli/src/commands/new_account.rs +++ b/bin/miden-cli/src/commands/new_account.rs @@ -20,7 +20,6 @@ use miden_lib::account::{auth::RpoFalcon512, wallets::BasicWallet}; use miden_objects::account::{ AccountComponent, AccountComponentTemplate, InitStorageData, StorageValueName, }; -use rand::RngCore; use crate::{ CLIENT_BINARY_NAME, CliKeyStore, commands::account::maybe_set_default_account, diff --git a/bin/miden-cli/tests/cli.rs b/bin/miden-cli/tests/cli.rs index 9d7127974..88288d503 100644 --- a/bin/miden-cli/tests/cli.rs +++ b/bin/miden-cli/tests/cli.rs @@ -762,7 +762,7 @@ async fn create_rust_client_with_store_path(store_path: &Path) -> (TestClient, C let mut rng = rand::rng(); let coin_seed: [u64; 4] = rng.random(); - let rng = Box::new(RpoRandomCoin::new(coin_seed.map(Felt::new))); + let rng = RpoRandomCoin::new(coin_seed.map(Felt::new)); let keystore = CliKeyStore::new(temp_dir()).unwrap(); diff --git a/crates/rust-client/src/builder.rs b/crates/rust-client/src/builder.rs index dfdc2f2c5..c48ad143e 100644 --- a/crates/rust-client/src/builder.rs +++ b/crates/rust-client/src/builder.rs @@ -2,7 +2,6 @@ use alloc::{ string::{String, ToString}, sync::Arc, }; -use std::boxed::Box; use miden_objects::{ Felt, MAX_TX_EXECUTION_CYCLES, MIN_TX_EXECUTION_CYCLES, @@ -46,13 +45,13 @@ enum AuthenticatorConfig { /// This builder allows you to configure the various components required by the client, such as the /// RPC endpoint, store, RNG, and keystore. It is generic over the keystore type. By default, it /// uses `FilesystemKeyStore`. -pub struct ClientBuilder { +pub struct ClientBuilder { /// An optional custom RPC client. If provided, this takes precedence over `rpc_endpoint`. rpc_api: Option>, /// An optional store provided by the user. store: Option>, - /// An optional RNG provided by the user. - rng: Option>, + /// RNG provided by the user. + rng: R, /// The store path to use when no store is directly provided via `with_store()`. #[cfg(feature = "sqlite")] store_path: String, @@ -70,10 +69,16 @@ pub struct ClientBuilder { impl Default for ClientBuilder { fn default() -> Self { + let rng = { + let mut seed_rng = rand::rng(); + let coin_seed: [u64; 4] = seed_rng.random(); + RpoRandomCoin::new(coin_seed.map(Felt::new)) + }; + Self { rpc_api: None, store: None, - rng: None, + rng, #[cfg(feature = "sqlite")] store_path: "store.sqlite3".to_string(), keystore: None, @@ -90,7 +95,9 @@ impl ClientBuilder { pub fn new() -> Self { Self::default() } +} +impl ClientBuilder { /// Enable or disable debug mode. #[must_use] pub fn in_debug_mode(mut self, debug: bool) -> Self { @@ -128,10 +135,10 @@ impl ClientBuilder { self } - /// Optionally provide a custom RNG. + /// Provide a custom RNG. #[must_use] - pub fn with_rng(mut self, rng: Box) -> Self { - self.rng = Some(rng); + pub fn with_rng(mut self, rng: R) -> Self { + self.rng = rng; self } @@ -177,7 +184,7 @@ impl ClientBuilder { /// - Returns an error if the store cannot be instantiated. /// - Returns an error if the keystore is not specified or fails to initialize. #[allow(clippy::unused_async, unused_mut)] - pub async fn build(mut self) -> Result { + pub async fn build(mut self) -> Result, ClientError> { // Determine the RPC client to use. let rpc_api: Arc = if let Some(client) = self.rpc_api { client @@ -206,15 +213,6 @@ impl ClientBuilder { )); }; - // Use the provided RNG, or create a default one. - let rng = if let Some(user_rng) = self.rng { - user_rng - } else { - let mut seed_rng = rand::rng(); - let coin_seed: [u64; 4] = seed_rng.random(); - Box::new(RpoRandomCoin::new(coin_seed.map(Felt::new))) - }; - // Initialize the authenticator. let authenticator = match self.keystore { Some(AuthenticatorConfig::Instance(authenticator)) => authenticator, @@ -233,7 +231,7 @@ impl ClientBuilder { Ok(Client::new( rpc_api, - rng, + self.rng, arc_store, authenticator, ExecutionOptions::new( diff --git a/crates/rust-client/src/lib.rs b/crates/rust-client/src/lib.rs index 21d8a23e9..77d0cff2c 100644 --- a/crates/rust-client/src/lib.rs +++ b/crates/rust-client/src/lib.rs @@ -87,7 +87,7 @@ //! let endpoint = Endpoint::new("https".into(), "localhost".into(), Some(57291)); //! let client: Client = Client::new( //! Arc::new(TonicRpcClient::new(&endpoint, 10_000)), -//! Box::new(rng), +//! rng, //! store, //! Arc::new(keystore), //! ExecutionOptions::new( @@ -112,7 +112,6 @@ #[macro_use] extern crate alloc; -use alloc::boxed::Box; #[cfg(feature = "std")] extern crate std; @@ -206,9 +205,8 @@ pub mod testing { use alloc::sync::Arc; -use miden_objects::crypto::rand::FeltRng; +use miden_objects::crypto::rand::{FeltRng, RpoRandomCoin}; use miden_tx::{LocalTransactionProver, auth::TransactionAuthenticator}; -use rand::RngCore; use rpc::NodeRpcClient; use store::Store; @@ -222,12 +220,12 @@ use store::Store; /// as notes and transactions. /// - Connects to a Miden node 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 { +pub struct Client { /// The client's store, which provides a way to write and read entities to provide persistence. store: Arc, /// An instance of [`FeltRng`] which provides randomness tools for generating new keys, /// serial numbers, etc. - rng: ClientRng, + rng: R, /// An instance of [`NodeRpcClient`] which provides a way for the client to connect to the /// Miden node. rpc_api: Arc, @@ -247,7 +245,7 @@ pub struct Client { } /// Construction and access methods. -impl Client { +impl Client { // CONSTRUCTOR // -------------------------------------------------------------------------------------------- @@ -275,7 +273,7 @@ impl Client { /// Returns an error if the client couldn't be instantiated. pub fn new( rpc_api: Arc, - rng: Box, + rng: R, store: Arc, authenticator: Arc, exec_options: ExecutionOptions, @@ -287,7 +285,7 @@ impl Client { Self { store, - rng: ClientRng::new(rng), + rng, rpc_api, tx_prover, authenticator, @@ -304,7 +302,7 @@ impl Client { /// 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 ClientRng { + pub fn rng(&mut self) -> &mut R { &mut self.rng } @@ -321,44 +319,3 @@ impl Client { &mut self.store } } - -// CLIENT RNG -// ================================================================================================ - -/// A wrapper around a [`FeltRng`] that implements the [`RngCore`] trait. -/// This allows the user to pass their own generic RNG so that it's used by the client. -pub struct ClientRng(Box); - -impl ClientRng { - pub fn new(rng: Box) -> Self { - Self(rng) - } - - pub fn inner_mut(&mut self) -> &mut Box { - &mut self.0 - } -} - -impl RngCore for ClientRng { - fn next_u32(&mut self) -> u32 { - self.0.next_u32() - } - - fn next_u64(&mut self) -> u64 { - self.0.next_u64() - } - - fn fill_bytes(&mut self, dest: &mut [u8]) { - self.0.fill_bytes(dest); - } -} - -impl FeltRng for ClientRng { - fn draw_element(&mut self) -> Felt { - self.0.draw_element() - } - - fn draw_word(&mut self) -> Word { - self.0.draw_word() - } -} diff --git a/crates/rust-client/src/test_utils/common.rs b/crates/rust-client/src/test_utils/common.rs index 8304ca8b1..586178dea 100644 --- a/crates/rust-client/src/test_utils/common.rs +++ b/crates/rust-client/src/test_utils/common.rs @@ -1,5 +1,4 @@ use std::{ - boxed::Box, env::temp_dir, fs::OpenOptions, io::Write, @@ -19,7 +18,7 @@ use miden_objects::{ note::{NoteId, NoteType}, transaction::{InputNote, OutputNote, TransactionId}, }; -use rand::{Rng, RngCore, rngs::StdRng}; +use rand::{Rng, rngs::StdRng}; use toml::Table; use uuid::Uuid; @@ -83,7 +82,7 @@ pub async fn create_test_client_builder() -> (ClientBuilder, TestClientKeyStore) let builder = ClientBuilder::new() .with_rpc(Arc::new(TonicRpcClient::new(&rpc_endpoint, rpc_timeout))) - .with_rng(Box::new(rng)) + .with_rng(rng) .with_store(store) .with_filesystem_keystore(auth_path.to_str().unwrap()) .in_debug_mode(true) diff --git a/crates/rust-client/src/tests.rs b/crates/rust-client/src/tests.rs index 563286f87..7a8496870 100644 --- a/crates/rust-client/src/tests.rs +++ b/crates/rust-client/src/tests.rs @@ -1,5 +1,5 @@ use alloc::vec::Vec; -use std::{boxed::Box, collections::BTreeSet, env::temp_dir, println, sync::Arc}; +use std::{collections::BTreeSet, env::temp_dir, println, sync::Arc}; // TESTS // ================================================================================================ @@ -39,7 +39,7 @@ use miden_tx::{ TransactionExecutorError, utils::{Deserializable, Serializable}, }; -use rand::{Rng, RngCore, rngs::StdRng}; +use rand::{Rng, rngs::StdRng}; use uuid::Uuid; use crate::{ @@ -93,7 +93,7 @@ pub async fn create_test_client_builder() -> (ClientBuilder, MockRpcApi, Filesys let builder = ClientBuilder::new() .with_rpc(arc_rpc_api) - .with_rng(Box::new(rng)) + .with_rng(rng) .with_store(store) .with_filesystem_keystore(keystore_path.to_str().unwrap()) .in_debug_mode(true) diff --git a/crates/rust-client/src/transaction/request/builder.rs b/crates/rust-client/src/transaction/request/builder.rs index 57f3d99c4..db38e5803 100644 --- a/crates/rust-client/src/transaction/request/builder.rs +++ b/crates/rust-client/src/transaction/request/builder.rs @@ -7,7 +7,10 @@ use miden_objects::{ account::AccountId, asset::{Asset, FungibleAsset}, block::BlockNumber, - crypto::merkle::{InnerNodeInfo, MerkleStore}, + crypto::{ + merkle::{InnerNodeInfo, MerkleStore}, + rand::FeltRng, + }, note::{Note, NoteDetails, NoteId, NoteRecipient, NoteTag, NoteType, PartialNote}, transaction::{OutputNote, TransactionScript}, vm::AdviceMap, @@ -17,7 +20,6 @@ use super::{ ForeignAccount, NoteArgs, TransactionRequest, TransactionRequestError, TransactionScriptTemplate, }; -use crate::ClientRng; // TRANSACTION REQUEST BUILDER // ================================================================================================ @@ -250,12 +252,12 @@ impl TransactionRequestBuilder { /// note. /// /// This function cannot be used with a previously set custom script. - pub fn build_mint_fungible_asset( + pub fn build_mint_fungible_asset( self, asset: FungibleAsset, target_id: AccountId, note_type: NoteType, - rng: &mut ClientRng, + rng: &mut R, ) -> Result { let created_note = create_p2id_note( asset.faucet_id(), @@ -281,12 +283,12 @@ impl TransactionRequestBuilder { /// note. /// /// This function cannot be used with a previously set custom script. - pub fn build_pay_to_id( + pub fn build_pay_to_id( self, payment_data: PaymentTransactionData, recall_height: Option, note_type: NoteType, - rng: &mut ClientRng, + rng: &mut R, ) -> Result { let PaymentTransactionData { assets, @@ -336,11 +338,11 @@ impl TransactionRequestBuilder { /// note. /// /// This function cannot be used with a previously set custom script. - pub fn build_swap( + pub fn build_swap( self, swap_data: &SwapTransactionData, note_type: NoteType, - rng: &mut ClientRng, + rng: &mut R, ) -> Result { // The created note is the one that we need as the output of the tx, the other one is the // one that we expect to receive and consume eventually. diff --git a/crates/web-client/package.json b/crates/web-client/package.json index d494fc215..7ebd80b13 100644 --- a/crates/web-client/package.json +++ b/crates/web-client/package.json @@ -1,6 +1,6 @@ { "name": "@demox-labs/miden-sdk", - "version": "0.10.0-next.4", + "version": "0.10.0-next.5", "description": "Miden Wasm SDK", "collaborators": [ "Miden", diff --git a/crates/web-client/src/lib.rs b/crates/web-client/src/lib.rs index c5fb6742a..4aa3d4e96 100644 --- a/crates/web-client/src/lib.rs +++ b/crates/web-client/src/lib.rs @@ -87,7 +87,7 @@ impl WebClient { self.inner = Some(Client::new( web_rpc_client, - Box::new(rng), + rng, web_store.clone(), Arc::new(keystore.clone()), ExecutionOptions::new( diff --git a/crates/web-client/src/new_account.rs b/crates/web-client/src/new_account.rs index 110d49fb7..9c714fa58 100644 --- a/crates/web-client/src/new_account.rs +++ b/crates/web-client/src/new_account.rs @@ -6,7 +6,6 @@ use miden_client::{ }; use miden_lib::account::{auth::RpoFalcon512, faucets::BasicFungibleFaucet}; use miden_objects::asset::TokenSymbol; -use rand::RngCore; use wasm_bindgen::prelude::*; use super::models::{ diff --git a/tests/src/network_transaction_tests.rs b/tests/src/network_transaction_tests.rs index 74559b4d0..4e801e9f1 100644 --- a/tests/src/network_transaction_tests.rs +++ b/tests/src/network_transaction_tests.rs @@ -19,7 +19,6 @@ use miden_objects::{ account::AccountComponent, assembly::{Assembler, DefaultSourceManager, Library, LibraryPath, Module, ModuleKind}, }; -use rand::RngCore; // HELPERS // ================================================================================================ diff --git a/tests/src/onchain_tests.rs b/tests/src/onchain_tests.rs index 69defda33..1ec94ccc3 100644 --- a/tests/src/onchain_tests.rs +++ b/tests/src/onchain_tests.rs @@ -11,7 +11,6 @@ use miden_objects::{ note::{NoteFile, NoteType}, transaction::InputNote, }; -use rand::RngCore; // TESTS // ================================================================================================