From 926ab91a0ca9fefe33c8edf79c1e182284858159 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Wed, 13 Nov 2024 19:51:14 +0530 Subject: [PATCH] refactor for miden 0.6 --- Cargo.toml | 15 +++---- src/accounts/accounts.rs | 78 ++++++++++++++++-------------------- src/accounts/tests.rs | 82 +++++++++++++++++++++----------------- src/cli.rs | 2 +- src/commands/new_oracle.rs | 25 ++++++------ src/commands/push_data.rs | 13 ++---- src/commands/read_data.rs | 21 ++++------ src/commands/sync.rs | 81 ++++++++++++++++++++++++++----------- src/sdk/mod.rs | 2 +- src/sdk/sdk.rs | 2 +- src/setup.rs | 23 ++++++----- 11 files changed, 185 insertions(+), 159 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2bcdbb4..fde1f3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,14 +8,15 @@ authors = ["Harsh Pratap Singh "] testing = ["miden-tx/testing"] [dependencies] -miden-client = { version = "0.5", features = ["concurrent", "testing", "sqlite", "tonic"] } -miden-crypto = { version = "0.10", default-features = false } -miden-lib = { version = "0.5", default-features = false } -miden-objects = { version = "0.5.1", default-features = false } -miden-tx = { version = "0.5", features = ["testing"] } -miden-cli = { version = "0.5" } +miden-client = { version = "0.6", features = ["concurrent", "testing", "sqlite", "tonic"] } +miden-crypto = { version = "0.12", default-features = false } +miden-lib = { version = "0.6", default-features = false } +miden-objects = { version = "0.6.1", default-features = false } +miden-tx = { version = "0.6", features = ["testing"] } +miden-air = { version = "0.11", default-features = false } +miden-cli = { version = "0.6" } -rusqlite = { version = "0.31", features = ["vtab", "array", "bundled"]} +rusqlite = { version = "0.32", features = ["vtab", "array", "bundled"]} rand = "0.8" tonic = { version = "0.12.3" } tokio = { version = "1.40.0", features = ["rt-multi-thread", "net", "macros"] } diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index 41bd6dd..c9f7a0e 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -1,7 +1,5 @@ use super::{data_to_word, public_key_to_string, word_to_data, word_to_masm, OracleData}; -use miden_client::{ - rpc::NodeRpcClient, store::Store, transactions::request::TransactionRequest, Client, -}; +use miden_client::{rpc::NodeRpcClient, store::Store, transactions::TransactionRequest, Client}; use miden_crypto::{ dsa::rpo_falcon512::{PublicKey, SecretKey}, rand::FeltRng, @@ -10,8 +8,8 @@ use miden_crypto::{ use miden_lib::{transaction::TransactionKernel, AuthScheme}; use miden_objects::{ accounts::{ - Account, AccountCode, AccountId, AccountStorage, AccountStorageType, AccountType, - AuthSecretKey, SlotItem, + Account, AccountBuilder, AccountCode, AccountComponent, AccountId, AccountStorage, + AccountStorageMode, AccountType, AuthSecretKey, StorageSlot, }, assembly::{Assembler, Library, LibraryNamespace, LibraryPath}, transaction::{TransactionArgs, TransactionScript}, @@ -23,6 +21,8 @@ use miden_tx::{ }; use rand::rngs::OsRng; use std::collections::BTreeMap; +use std::error::Error as StdError; +use std::fmt; use std::str::FromStr; use std::sync::Arc; use std::{ @@ -130,7 +130,7 @@ pub fn get_oracle_account( init_seed: [u8; 32], auth_scheme: AuthScheme, account_type: AccountType, - account_storage_type: AccountStorageType, + account_storage_type: AccountStorageMode, data_provider_public_key: PublicKey, ) -> Result<(Account, Word), AccountError> { let (auth_scheme_procedure, storage_slot_0_data): (&str, Word) = match auth_scheme { @@ -138,29 +138,24 @@ pub fn get_oracle_account( }; let assembler = TransactionKernel::assembler(); + let library = assembler.assemble_library([SOURCE_CODE]).unwrap(); - let oracle_account_code = AccountCode::compile(SOURCE_CODE, assembler).unwrap(); - - let account_storage = AccountStorage::new( + let component = AccountComponent::new( + library, vec![ - SlotItem::new_value(0, 0, storage_slot_0_data), - SlotItem::new_value(1, 0, data_provider_public_key.into()), + StorageSlot::Value(storage_slot_0_data), + StorageSlot::Value(data_provider_public_key.into()), ], - BTreeMap::new(), )?; - let account_seed = AccountId::get_account_seed( - init_seed, - account_type, - account_storage_type, - oracle_account_code.commitment(), - account_storage.root(), - )?; + let (account, seed) = AccountBuilder::new() + .init_seed(init_seed) + .account_type(account_type) + .storage_mode(account_storage_type) + .with_component(component) + .build()?; - Ok(( - Account::new(account_seed, oracle_account_code, account_storage)?, - account_seed, - )) + Ok((account, seed)) } /// Helper function to create a transaction script @@ -191,41 +186,36 @@ pub fn create_transaction_script( } /// Helper function to execute a transaction -async fn execute_transaction( - client: &mut Client, +async fn execute_transaction( + client: &mut Client, account_id: AccountId, tx_script: TransactionScript, -) -> Result> -where - N: NodeRpcClient, - R: FeltRng, - S: Store, - A: TransactionAuthenticator, -{ +) -> Result> { let tx_request = TransactionRequest::new(); let request = TransactionRequest::with_custom_script(tx_request, tx_script) - .map_err(|err| err.to_string())?; - let transaction_execution_result = client.new_transaction(account_id, request)?; + .map_err(|e| Box::new(e) as Box)?; + + let transaction_execution_result = client + .new_transaction(account_id, request) + .await + .map_err(|e| format!("Transaction execution failed: {}", e))?; + let transaction_id = transaction_execution_result.executed_transaction().id(); + client .submit_transaction(transaction_execution_result) - .await?; + .await + .map_err(|e| format!("Transaction submission failed: {}", e))?; Ok(transaction_id.to_string()) } -pub async fn push_data_to_oracle_account( - client: &mut Client, +pub async fn push_data_to_oracle_account( + client: &mut Client, account: Account, data: OracleData, data_provider_public_key: &PublicKey, -) -> Result<(), Box> -where - N: NodeRpcClient, - R: FeltRng, - S: Store, - A: TransactionAuthenticator, -{ +) -> Result<(), Box> { let word = data_to_word(&data); let push_tx_script_code = format!( diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index 0bebd75..c745ff1 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -17,27 +17,31 @@ use miden_objects::assembly::{Library, LibraryNamespace}; use miden_objects::{ accounts::{ account_id::testing::ACCOUNT_ID_REGULAR_ACCOUNT_IMMUTABLE_CODE_ON_CHAIN, Account, - AccountCode, AccountId, AccountStorage, AccountStorageType, SlotItem, + AccountCode, AccountComponent, AccountId, AccountStorage, AccountStorageMode, AccountType, + AuthSecretKey, StorageSlot, }, assets::AssetVault, crypto::utils::Serializable, transaction::{ExecutedTransaction, ProvenTransaction, TransactionArgs}, + AccountError, }; use miden_objects::{crypto::dsa::rpo_falcon512, ONE}; +use miden_tx::auth::BasicAuthenticator; use miden_tx::{ - testing::TransactionContextBuilder, ProvingOptions, TransactionExecutor, TransactionProver, - TransactionVerifier, TransactionVerifierError, + testing::TransactionContextBuilder, LocalTransactionProver, ProvingOptions, + TransactionExecutor, TransactionProver, TransactionVerifier, TransactionVerifierError, }; +use rand::rngs::StdRng; use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; -use std::{collections::BTreeMap, path::Path}; +use std::{collections::BTreeMap, path::Path, sync::Arc}; -#[test] -fn oracle_account_creation_and_pushing_data_to_read() { +#[tokio::test] +async fn oracle_account_creation_and_pushing_data_to_read() { let (oracle_pub_key, oracle_auth) = get_new_pk_and_authenticator(); let data_provider_private_key = SecretKey::new(); let data_provider_public_key = data_provider_private_key.public_key(); - let oracle_account = get_oracle_account(data_provider_public_key, oracle_pub_key); + let oracle_account = get_oracle_account(data_provider_public_key, oracle_pub_key).unwrap(); println!("Oracle account: {:?}", oracle_account.code().procedures()); @@ -51,8 +55,8 @@ fn oracle_account_creation_and_pushing_data_to_read() { let mut word = data_to_word(&oracle_data); word[0] = Felt::new(1); - let tx_context = TransactionContextBuilder::new(oracle_account.clone()).build(); - let executor = TransactionExecutor::new(tx_context.clone(), Some(oracle_auth.clone())); + let tx_context = Arc::new(TransactionContextBuilder::new(oracle_account.clone()).build()); + let executor = TransactionExecutor::new(tx_context, Some(Arc::new(oracle_auth))); let push_tx_script_code = format!( "{}", @@ -78,12 +82,15 @@ fn oracle_account_creation_and_pushing_data_to_read() { let txn_args = TransactionArgs::with_tx_script(push_tx_script); let executed_transaction = executor .execute_transaction(oracle_account.id(), 4, &[], txn_args) + .await .unwrap(); // check that now the account has the data stored in its storage at slot 2 println!("Account Delta: {:?}", executed_transaction.account_delta()); - assert!(prove_and_verify_transaction(executed_transaction.clone()).is_ok()); + assert!(prove_and_verify_transaction(executed_transaction.clone()) + .await + .is_ok()); // let read_tx_script_code = format!( // "{}", @@ -154,16 +161,7 @@ fn test_oracle_data_conversion() { // } // } -fn get_new_pk_and_authenticator() -> ( - Word, - std::rc::Rc>, -) { - use std::rc::Rc; - - use miden_objects::accounts::AuthSecretKey; - use miden_tx::auth::BasicAuthenticator; - use rand::rngs::StdRng; - +fn get_new_pk_and_authenticator() -> (Word, BasicAuthenticator) { let seed = [0_u8; 32]; let mut rng = ChaCha20Rng::from_seed(seed); @@ -173,18 +171,17 @@ fn get_new_pk_and_authenticator() -> ( let authenticator = BasicAuthenticator::::new(&[(pub_key, AuthSecretKey::RpoFalcon512(sec_key))]); - (pub_key, Rc::new(authenticator)) + (pub_key, authenticator) } -fn prove_and_verify_transaction( +async fn prove_and_verify_transaction( executed_transaction: ExecutedTransaction, ) -> Result<(), TransactionVerifierError> { let executed_transaction_id = executed_transaction.id(); - // Prove the transaction let proof_options = ProvingOptions::default(); - let prover = TransactionProver::new(proof_options); - let proven_transaction = prover.prove_transaction(executed_transaction).unwrap(); + let prover = LocalTransactionProver::new(proof_options); + let proven_transaction = prover.prove(executed_transaction.into()).await.unwrap(); assert_eq!(proven_transaction.id(), executed_transaction_id); @@ -198,7 +195,10 @@ fn prove_and_verify_transaction( verifier.verify(proven_transaction) } -fn get_oracle_account(data_provider_public_key: PublicKey, oracle_public_key: Word) -> Account { +fn get_oracle_account( + data_provider_public_key: PublicKey, + oracle_public_key: Word, +) -> Result { let account_owner_public_key = PublicKey::new(oracle_public_key); let oracle_account_id = AccountId::try_from(ACCOUNT_ID_REGULAR_ACCOUNT_IMMUTABLE_CODE_ON_CHAIN).unwrap(); @@ -260,22 +260,30 @@ fn get_oracle_account(data_provider_public_key: PublicKey, oracle_public_key: Wo end " ); - let oracle_account_code = AccountCode::compile(source_code, assembler).unwrap(); - let account_storage = AccountStorage::new( + let library = assembler.assemble_library([source_code]).unwrap(); + + let component = AccountComponent::new( + library, vec![ - SlotItem::new_value(0, 0, account_owner_public_key.into()), - SlotItem::new_value(1, 0, data_provider_public_key.into()), + StorageSlot::Value(account_owner_public_key.into()), + StorageSlot::Value(data_provider_public_key.into()), ], - BTreeMap::new(), - ) - .unwrap(); + )?; + + let oracle_account_code = + AccountCode::from_components(&[component], AccountType::RegularAccountImmutableCode)?; + + let account_storage = AccountStorage::new(vec![ + StorageSlot::Value(account_owner_public_key.into()), + StorageSlot::Value(data_provider_public_key.into()), + ])?; - Account::from_parts( + Ok(Account::from_parts( oracle_account_id, AssetVault::new(&[]).unwrap(), - account_storage.clone(), - oracle_account_code.clone(), + account_storage, + oracle_account_code, Felt::new(1), - ) + )) } diff --git a/src/cli.rs b/src/cli.rs index 46740ba..b89f325 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -33,7 +33,7 @@ pub struct Cli { impl Cli { pub async fn execute(&self) -> Result<(), String> { - let mut client = setup_client(); + let mut client = setup_client().await; match &self.action { Command::Sync(sync) => sync.execute(&mut client).await, diff --git a/src/commands/new_oracle.rs b/src/commands/new_oracle.rs index 9b59a86..825a891 100644 --- a/src/commands/new_oracle.rs +++ b/src/commands/new_oracle.rs @@ -4,7 +4,7 @@ use clap::{Parser, ValueEnum}; use miden_client::{rpc::NodeRpcClient, store::Store, Client, ClientError, Felt}; use miden_lib::{utils::hex_to_bytes, AuthScheme}; use miden_objects::{ - accounts::{Account, AccountId, AccountStorageType, AccountType, AuthSecretKey}, + accounts::{Account, AccountId, AccountStorageMode, AccountType, AuthSecretKey}, crypto::{ dsa::rpo_falcon512::{PublicKey, SecretKey}, rand::FeltRng, @@ -25,21 +25,18 @@ pub struct AccountCmd { pub trait OracleAccountCreation { async fn new_oracle_account( &mut self, - account_storage_type: AccountStorageType, + account_storage_type: AccountStorageMode, data_provider_public_key: PublicKey, ) -> Result<(Account, Word), ClientError>; } impl AccountCmd { - pub async fn execute( - &self, - client: &mut Client, - ) -> Result<(), String> + pub async fn execute(&self, client: &mut Client) -> Result<(), String> where - Client: OracleAccountCreation, + Client: OracleAccountCreation, { let (account, seed) = client - .new_oracle_account(AccountStorageType::OnChain, self.data_provider_public_key) + .new_oracle_account(AccountStorageMode::Public, self.data_provider_public_key) .await .map_err(|e| e.to_string())?; @@ -53,12 +50,10 @@ impl AccountCmd { } #[maybe_async] -impl OracleAccountCreation - for Client -{ +impl OracleAccountCreation for Client { async fn new_oracle_account( &mut self, - account_storage_type: AccountStorageType, + account_storage_type: AccountStorageMode, data_provider_public_key: PublicKey, ) -> Result<(Account, Word), ClientError> { let key_pair = SecretKey::with_rng(&mut self.rng()); @@ -78,7 +73,11 @@ impl Oracle data_provider_public_key, )?; - self.insert_account(&account, Some(seed), &AuthSecretKey::RpoFalcon512(key_pair))?; + maybe_await!(self.insert_account( + &account, + Some(seed), + &AuthSecretKey::RpoFalcon512(key_pair) + ))?; Ok((account, seed)) } } diff --git a/src/commands/push_data.rs b/src/commands/push_data.rs index 28ea38d..dfe002c 100644 --- a/src/commands/push_data.rs +++ b/src/commands/push_data.rs @@ -44,12 +44,9 @@ pub trait OracleDataPusher { } impl PushDataCmd { - pub async fn execute( - &self, - client: &mut Client, - ) -> Result<(), String> + pub async fn execute(&self, client: &mut Client) -> Result<(), String> where - Client: OracleDataPusher, + Client: OracleDataPusher, { let mut interval = tokio::time::interval(Duration::from_secs(10 * 60)); // 10 minutes @@ -89,16 +86,14 @@ impl PushDataCmd { } #[maybe_async] -impl OracleDataPusher - for Client -{ +impl OracleDataPusher for Client { async fn push_oracle_data( &mut self, data_provider_public_key: &PublicKey, account_id: &AccountId, data: OracleData, ) -> Result<(), ClientError> { - let (account, _) = self.get_account(*account_id)?; + let (account, _) = self.get_account(*account_id).await?; push_data_to_oracle_account(self, account, data, data_provider_public_key) .await .map_err(|e| { diff --git a/src/commands/read_data.rs b/src/commands/read_data.rs index 6ae0dc7..11008ea 100644 --- a/src/commands/read_data.rs +++ b/src/commands/read_data.rs @@ -1,9 +1,8 @@ use crate::accounts::OracleData; use crate::commands::account_id_parser; use clap::Parser; -use miden_client::{rpc::NodeRpcClient, store::Store, Client, ClientError}; +use miden_client::{Client, ClientError}; use miden_objects::{accounts::AccountId, crypto::rand::FeltRng}; -use miden_tx::auth::TransactionAuthenticator; use winter_maybe_async::maybe_async; #[derive(Debug, Clone, Parser)] @@ -22,16 +21,13 @@ pub trait OracleDataReader { &mut self, account_id: &AccountId, asset_pair: String, - ) -> Result, Box>; + ) -> Result, ClientError>; } impl ReadDataCmd { - pub async fn execute( - &self, - client: &mut Client, - ) -> Result<(), String> + pub async fn execute(&self, client: &mut Client) -> Result<(), String> where - Client: OracleDataReader, + Client: OracleDataReader, { let oracle_data_vector = client .read_oracle_data(&self.account_id, self.asset_pair.clone()) @@ -47,15 +43,14 @@ impl ReadDataCmd { } #[maybe_async] -impl OracleDataReader - for Client -{ +impl OracleDataReader for Client { async fn read_oracle_data( &mut self, account_id: &AccountId, asset_pair: String, - ) -> Result, Box> { - let (mut account, _) = self.get_account(*account_id)?; + ) -> Result, ClientError> { + let (mut account, _) = self.get_account(*account_id).await?; + // TODO: Implement actual data reading logic // let oracle_data = read_data_from_oracle_account(self, account, asset_pair).await?; // Ok(oracle_data.to_vector()) Ok(vec![0, 0, 0, 0]) diff --git a/src/commands/sync.rs b/src/commands/sync.rs index 61c4761..d5062a9 100644 --- a/src/commands/sync.rs +++ b/src/commands/sync.rs @@ -1,34 +1,69 @@ use clap::Parser; - -use miden_client::{ - auth::TransactionAuthenticator, crypto::FeltRng, rpc::NodeRpcClient, store::Store, Client, -}; +use miden_client::{crypto::FeltRng, sync::SyncSummary, Client}; +use std::fmt; #[derive(Debug, Clone, Parser)] #[clap(about = "Sync client state with the Miden Network")] pub struct SyncCmd {} +pub struct SyncSummaryDisplay<'a>(&'a SyncSummary); + +impl<'a> fmt::Display for SyncSummaryDisplay<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let summary = self.0; + writeln!(f, "State synced to block {}", summary.block_num)?; + + write!(f, "Received notes: [")?; + for (i, note) in summary.received_notes.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + write!(f, "{:?}", note)?; + } + writeln!(f, "]")?; + + write!(f, "Committed notes: [")?; + for (i, note) in summary.committed_notes.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + write!(f, "{:?}", note)?; + } + writeln!(f, "]")?; + + write!(f, "Consumed notes: [")?; + for (i, note) in summary.consumed_notes.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + write!(f, "{:?}", note)?; + } + writeln!(f, "]")?; + + write!(f, "Updated accounts: [")?; + for (i, account) in summary.updated_accounts.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + write!(f, "{:?}", account)?; + } + writeln!(f, "]")?; + + write!(f, "Committed transactions: [")?; + for (i, tx) in summary.committed_transactions.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + write!(f, "{:?}", tx)?; + } + writeln!(f, "]") + } +} + impl SyncCmd { - pub async fn execute( - &self, - client: &mut Client, - ) -> Result<(), String> { + pub async fn execute(&self, client: &mut Client) -> Result<(), String> { let new_details = client.sync_state().await?; - println!("State synced to block {}", new_details.block_num); - println!("New public notes: {}", new_details.new_notes); - println!( - "Tracked notes updated: {}", - new_details.new_inclusion_proofs - ); - println!("Tracked notes consumed: {}", new_details.new_nullifiers); - println!( - "Tracked accounts updated: {}", - new_details.updated_onchain_accounts - ); - println!( - "Commited transactions: {}", - new_details.commited_transactions - ); + println!("{}", SyncSummaryDisplay(&new_details)); println!("Sync successful."); Ok(()) } diff --git a/src/sdk/mod.rs b/src/sdk/mod.rs index 57da14d..54d8e7c 100644 --- a/src/sdk/mod.rs +++ b/src/sdk/mod.rs @@ -1,2 +1,2 @@ mod sdk; -pub use sdk::{get_pragma_prices, PragmaPrice, PragmaSDKError}; \ No newline at end of file +pub use sdk::{get_pragma_prices, PragmaPrice, PragmaSDKError}; diff --git a/src/sdk/sdk.rs b/src/sdk/sdk.rs index 72e3c92..a2713cb 100644 --- a/src/sdk/sdk.rs +++ b/src/sdk/sdk.rs @@ -87,4 +87,4 @@ pub async fn get_pragma_prices(pairs: Vec) -> Result, P Ok(prices) }) -} \ No newline at end of file +} diff --git a/src/setup.rs b/src/setup.rs index b1444af..261c8e3 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -1,37 +1,40 @@ +use miden_air::ProvingOptions; use miden_client::{ - auth::StoreAuthenticator, config::{Endpoint, RpcConfig}, crypto::RpoRandomCoin, rpc::TonicRpcClient, store::sqlite_store::{config::SqliteStoreConfig, SqliteStore}, + store::StoreAuthenticator, + transactions::LocalTransactionProver, Client, Felt, }; use rand::Rng; use std::rc::Rc; +use std::sync::Arc; // seting up Miden Client -pub fn setup_client() -> Client< - TonicRpcClient, - RpoRandomCoin, - SqliteStore, - StoreAuthenticator, -> { +pub async fn setup_client() -> Client { let store_config = SqliteStoreConfig::default(); - let store = Rc::new(SqliteStore::new(&store_config).unwrap()); + let store = Arc::new(SqliteStore::new(&store_config).await.unwrap()); let mut rng = rand::thread_rng(); let coin_seed: [u64; 4] = rng.gen(); let rng = RpoRandomCoin::new(coin_seed.map(Felt::new)); - let authenticator = StoreAuthenticator::new_with_rng(store.clone(), rng); + let authenticator = Arc::new(StoreAuthenticator::new_with_rng(store.clone(), rng)); let rpc_config = RpcConfig { endpoint: Endpoint::new("http".to_string(), "18.203.155.106".to_string(), 57291), timeout_ms: 10000, }; let in_debug_mode = true; + + // Create a dummy TransactionProver for now - you'll need to replace this with your actual prover + let tx_prover = Arc::new(LocalTransactionProver::new(ProvingOptions::default())); + Client::new( - TonicRpcClient::new(&rpc_config), + Box::new(TonicRpcClient::new(&rpc_config)), rng, store, authenticator, + tx_prover, in_debug_mode, ) }