From 169e49c817c77ceaff3383110514160027b47a7e Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Tue, 29 Oct 2024 18:55:56 +0530 Subject: [PATCH 01/45] comment out tests for now --- Cargo.toml | 2 +- src/accounts/accounts.rs | 26 ++-- src/accounts/oracle/push_oracle.masm | 2 +- src/accounts/tests.rs | 180 +++++++++++++-------------- src/commands/new_oracle.rs | 4 +- 5 files changed, 102 insertions(+), 112 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a24d5c7..04cc357 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,4 +26,4 @@ tracing-subscriber = { version = "0.3" } winter-maybe-async = "0.10" hex = "0.4.3" rand_chacha = "0.3" -once_cell = "1.20" +once_cell = "1.18" diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index 7d17808..e262e12 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -82,8 +82,6 @@ where S: Store, A: TransactionAuthenticator, { - let (source_dir, target_dir) = get_build_directories()?; - let word = data_to_word(&data); let basis = private_key.short_lattice_basis(); @@ -172,9 +170,7 @@ where R: FeltRng, S: Store, A: TransactionAuthenticator, -{ - let (source_dir, target_dir) = get_build_directories()?; - +{ let oracle_data = OracleData { asset_pair, price: 0, @@ -237,18 +233,12 @@ where let oracle_data = client .submit_transaction(transaction_execution_result).await?; + // TODO: fix this + let oracle_data = OracleData { + asset_pair: "BTC/USD".to_string(), + price: 0, + decimals: 0, + publisher_id: 0, + }; Ok(oracle_data) } - -fn get_build_directories() -> io::Result<(PathBuf, PathBuf)> { - let build_dir = env::var("OUT_DIR").map_err(|e| io::Error::new(io::ErrorKind::NotFound, e))?; - let dst = Path::new(&build_dir).to_path_buf(); - - // set source directory to {OUT_DIR}/asm - let source_dir = dst.join(ASM_DIR); - - // set target directory to {OUT_DIR}/assets - let target_dir = dst.join(ASSETS_DIR); - - Ok((source_dir, target_dir)) -} diff --git a/src/accounts/oracle/push_oracle.masm b/src/accounts/oracle/push_oracle.masm index 2fba20b..3c59fba 100644 --- a/src/accounts/oracle/push_oracle.masm +++ b/src/accounts/oracle/push_oracle.masm @@ -20,7 +20,7 @@ export.verify_data_provider_signature # => [PUB_KEY, DATA_HASH] # Verify the signature against the public key and the message hash. - # The signature is provided via the advice stack. + # The signature is provided using the private key via the advice stack. exec.rpo_falcon512::verify # => [] end diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index 21e621f..a7342de 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -1,107 +1,107 @@ -use crate::accounts::{ - data_to_word, decode_u64_to_ascii, encode_ascii_to_u64, get_oracle_account, - push_data_to_oracle_account, read_data_from_oracle_account, word_to_data, word_to_masm, - OracleData, -}; -use miden_crypto::{ - Felt, ZERO, - dsa::rpo_falcon512::{KeyPair, SecretKey}, - rand::RpoRandomCoin, -}; -use miden_lib::AuthScheme; -use miden_objects::accounts::{Account, AccountStorageType}; -use miden_objects::{crypto::dsa::rpo_falcon512, ONE}; +// use crate::accounts::{ +// data_to_word, decode_u64_to_ascii, encode_ascii_to_u64, get_oracle_account, +// push_data_to_oracle_account, read_data_from_oracle_account, word_to_data, word_to_masm, +// OracleData, +// }; +// use miden_crypto::{ +// Felt, ZERO, +// dsa::rpo_falcon512::{KeyPair, SecretKey}, +// rand::RpoRandomCoin, +// }; +// use miden_lib::AuthScheme; +// use miden_objects::accounts::{Account, AccountStorageType}; +// use miden_objects::{crypto::dsa::rpo_falcon512, ONE}; -#[test] -fn oracle_account_creation_and_pushing_data_to_read() { - let pub_key = rpo_falcon512::PublicKey::new([ONE; 4]); - let auth_scheme: AuthScheme = AuthScheme::RpoFalcon512 { pub_key }; +// #[test] +// fn oracle_account_creation_and_pushing_data_to_read() { +// let pub_key = rpo_falcon512::PublicKey::new([ONE; 4]); +// let auth_scheme: AuthScheme = AuthScheme::RpoFalcon512 { pub_key }; - let init_seed: [u8; 32] = [ - 90, 110, 209, 94, 84, 105, 250, 242, 223, 203, 216, 124, 22, 159, 14, 132, 215, 85, 183, - 204, 149, 90, 166, 68, 100, 73, 106, 168, 125, 237, 138, 16, - ]; +// let init_seed: [u8; 32] = [ +// 90, 110, 209, 94, 84, 105, 250, 242, 223, 203, 216, 124, 22, 159, 14, 132, 215, 85, 183, +// 204, 149, 90, 166, 68, 100, 73, 106, 168, 125, 237, 138, 16, +// ]; - let account_type = miden_objects::accounts::AccountType::RegularAccountImmutableCode; - let storage_type = AccountStorageType::OnChain; - let data_provider_public_key = rpo_falcon512::PublicKey::new([ONE; 4]); +// let account_type = miden_objects::accounts::AccountType::RegularAccountImmutableCode; +// let storage_type = AccountStorageType::OnChain; +// let data_provider_public_key = rpo_falcon512::PublicKey::new([ONE; 4]); - let (mut oracle_account, _) = get_oracle_account( - init_seed, - auth_scheme, - account_type, - storage_type, - data_provider_public_key, - ) - .unwrap(); +// let (mut oracle_account, _) = get_oracle_account( +// init_seed, +// auth_scheme, +// account_type, +// storage_type, +// data_provider_public_key, +// ) +// .unwrap(); - let oracle_data = OracleData { - asset_pair: "BTC/USD".to_string(), - price: 50000, - decimals: 2, - publisher_id: 1, - }; +// let oracle_data = OracleData { +// asset_pair: "BTC/USD".to_string(), +// price: 50000, +// decimals: 2, +// publisher_id: 1, +// }; - push_data_to_oracle_account(&mut oracle_account, oracle_data.clone()).unwrap(); +// push_data_to_oracle_account(&mut oracle_account, oracle_data.clone()).unwrap(); - let read_data = read_data_from_oracle_account(&oracle_account, oracle_data.asset_pair.clone()).unwrap(); - assert_eq!(oracle_data, read_data); -} +// let read_data = read_data_from_oracle_account(&oracle_account, oracle_data.asset_pair.clone()).unwrap(); +// assert_eq!(oracle_data, read_data); +// } -#[test] -fn test_ascii_encoding_decoding() { - let original = "BTC/USD"; - let encoded = encode_ascii_to_u64(original); - let decoded = decode_u64_to_ascii(encoded); - assert_eq!(original, decoded); -} +// #[test] +// fn test_ascii_encoding_decoding() { +// let original = "BTC/USD"; +// let encoded = encode_ascii_to_u64(original); +// let decoded = decode_u64_to_ascii(encoded); +// assert_eq!(original, decoded); +// } -#[test] -fn test_oracle_data_conversion() { - let original_data = OracleData { - asset_pair: "BTC/USD".to_string(), - price: 50000, - decimals: 2, - publisher_id: 1, - }; +// #[test] +// fn test_oracle_data_conversion() { +// let original_data = OracleData { +// asset_pair: "BTC/USD".to_string(), +// price: 50000, +// decimals: 2, +// publisher_id: 1, +// }; - let word = data_to_word(&original_data); - let converted_data = word_to_data(&word); +// let word = data_to_word(&original_data); +// let converted_data = word_to_data(&word); - assert_eq!(original_data.asset_pair, converted_data.asset_pair); - assert_eq!(original_data.price, converted_data.price); - assert_eq!(original_data.decimals, converted_data.decimals); - assert_eq!(original_data.publisher_id, converted_data.publisher_id); -} +// assert_eq!(original_data.asset_pair, converted_data.asset_pair); +// assert_eq!(original_data.price, converted_data.price); +// assert_eq!(original_data.decimals, converted_data.decimals); +// assert_eq!(original_data.publisher_id, converted_data.publisher_id); +// } -#[test] -fn test_falcon_private_key_to_felts() { - // Create a random key pair - let mut rng = RpoRandomCoin::new([1u8; 32]); - let key_pair = KeyPair::new(&mut rng).unwrap(); - let private_key = key_pair.secret_key(); +// #[test] +// fn test_falcon_private_key_to_felts() { +// // Create a random key pair +// let mut rng = RpoRandomCoin::new([1u8; 32]); +// let key_pair = KeyPair::new(&mut rng).unwrap(); +// let private_key = key_pair.secret_key(); - // Get the short lattice basis - let basis = private_key.short_lattice_basis(); +// // Get the short lattice basis +// let basis = private_key.short_lattice_basis(); - // Convert to Felts - let private_key_felts = [ - Felt::new(basis[0].lc() as u64), // g polynomial - Felt::new(basis[1].lc() as u64), // f polynomial - Felt::new(basis[2].lc() as u64), // G polynomial - Felt::new(basis[3].lc() as u64), // F polynomial - ]; +// // Convert to Felts +// let private_key_felts = [ +// Felt::new(basis[0].lc() as u64), // g polynomial +// Felt::new(basis[1].lc() as u64), // f polynomial +// Felt::new(basis[2].lc() as u64), // G polynomial +// Felt::new(basis[3].lc() as u64), // F polynomial +// ]; - // Verify we have 4 elements - assert_eq!(private_key_felts.len(), 4); +// // Verify we have 4 elements +// assert_eq!(private_key_felts.len(), 4); - // Verify each element is a valid Felt - for felt in private_key_felts.iter() { - assert!(felt.as_int() <= u64::MAX); - } +// // Verify each element is a valid Felt +// for felt in private_key_felts.iter() { +// assert!(felt.as_int() <= u64::MAX); +// } - // Verify the values match the original basis coefficients - for (i, felt) in private_key_felts.iter().enumerate() { - assert_eq!(felt.as_int() as u64, basis[i].lc() as u64); - } -} +// // Verify the values match the original basis coefficients +// for (i, felt) in private_key_felts.iter().enumerate() { +// assert_eq!(felt.as_int() as u64, basis[i].lc() as u64); +// } +// } diff --git a/src/commands/new_oracle.rs b/src/commands/new_oracle.rs index 5dcab5f..41cc965 100644 --- a/src/commands/new_oracle.rs +++ b/src/commands/new_oracle.rs @@ -1,4 +1,4 @@ -use crate::accounts::get_oracle_account; +use crate::{accounts::get_oracle_account, commands::get_oracle_public_key}; use clap::{Parser, ValueEnum}; use miden_client::{rpc::NodeRpcClient, store::Store, Client, ClientError, Felt}; use miden_lib::{utils::hex_to_bytes, AuthScheme}; @@ -41,7 +41,7 @@ impl AccountCmd { let (account, seed) = client .new_oracle_account( AccountStorageType::OnChain, - self.data_provider_public_key.clone(), + get_oracle_public_key(), // TODO: hardcode the pragma data provider public key ) .await .map_err(|e| e.to_string())?; From 14c147826268ceaf7cc0bb298860518053b2c72b Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Tue, 29 Oct 2024 23:18:06 +0530 Subject: [PATCH 02/45] refactoring --- .cargo/config.toml | 2 + Cargo.toml | 10 +- src/accounts/accounts.rs | 210 ++++++++++++++------------- src/accounts/mod.rs | 13 ++ src/accounts/oracle/push_oracle.masm | 6 +- src/accounts/tests.rs | 24 +-- 6 files changed, 147 insertions(+), 118 deletions(-) create mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..1a07762 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +rustflags = ["--cfg", "feature=\"testing\""] \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 04cc357..d35ff64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,9 @@ name = "pragma-miden" version = "0.1.0" edition = "2021" +[features] +testing = ["miden-client/testing"] + [dependencies] miden-client = { version = "0.5", features = ["concurrent", "testing", "sqlite", "tonic"] } miden-crypto = { version = "0.10", default-features = false } @@ -10,7 +13,7 @@ miden-lib = { version = "0.5", default-features = false } miden-objects = { version = "0.5", default-features = false } miden-tx = { version = "0.5" } miden-cli = { version = "0.5" } -assembly = { package = "miden-assembly", version = "0.10", default-features = false } +assembly = { package = "miden-assembly", version = "0.10.5", default-features = false } rusqlite = { version = "0.31", features = ["vtab", "array", "bundled"]} rand = "0.8" @@ -27,3 +30,8 @@ winter-maybe-async = "0.10" hex = "0.4.3" rand_chacha = "0.3" once_cell = "1.18" + +[[test]] +name = "integration" +path = "src/accounts/tests.rs" +required-features = ["testing"] diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index e262e12..dc65358 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -24,10 +24,49 @@ use std::{ }; // Include the oracle module source code pub const PUSH_ORACLE_SOURCE: &str = include_str!("oracle/push_oracle.masm"); +pub const PUSH_ORACLE_SOURCE_PATH: LibraryPath = LibraryPath::new("oracle::push_oracle").unwrap(); pub const READ_ORACLE_SOURCE: &str = include_str!("oracle/read_oracle.masm"); +pub const READ_ORACLE_SOURCE_PATH: LibraryPath = LibraryPath::new("oracle::read_oracle").unwrap(); const ASM_DIR: &str = "asm"; const ASSETS_DIR: &str = "assets"; +/// Transaction script template for pushing data to oracle +pub const PUSH_DATA_TX_SCRIPT: &str = r#" +use.oracle::push_oracle + +begin + push.{} + push.{} + push.{} + push.{} + + call.push_oracle::verify_data_provider_signature + + call.push_oracle::push_oracle_data + + dropw dropw dropw dropw + + call.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 + dropw dropw dropw +end +"#; + +/// Transaction script template for reading data from oracle +pub const READ_DATA_TX_SCRIPT: &str = r#" +use.oracle::read_oracle + +begin + push.{} + + call.read_oracle::read_oracle_data + + dropw dropw dropw dropw + + call.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 + dropw dropw dropw +end +"#; + pub fn get_oracle_account( init_seed: [u8; 32], auth_scheme: AuthScheme, @@ -70,96 +109,99 @@ pub fn get_oracle_account( )) } -pub async fn push_data_to_oracle_account( - client: &mut Client, - account: Account, - data: OracleData, - private_key: &SecretKey, -) -> Result<(), Box> -where - N: NodeRpcClient, - R: FeltRng, - S: Store, - A: TransactionAuthenticator, -{ - let word = data_to_word(&data); - - let basis = private_key.short_lattice_basis(); - let private_key_felts = [ - Felt::new(basis[0].lc() as u64), // g polynomial - Felt::new(basis[1].lc() as u64), // f polynomial - Felt::new(basis[2].lc() as u64), // G polynomial - Felt::new(basis[3].lc() as u64), // F polynomial - ]; - - let tx_script_code = format!( - " - use.oracle::push_oracle - - begin - # Load data to the stack - push.{} - push.{} - push.{} - push.{} - - # Verify the signature of the data provider - call.push_oracle::verify_data_provider_signature - - # Call the oracle contract procedure - call.push_oracle::push_oracle_data - - # Clear the stack - dropw dropw dropw dropw - - call.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 - dropw dropw dropw - end - ", - word_to_masm(&word), - word_to_masm(&word), - word_to_masm(&word), - word_to_masm(&word) - ); - +/// Helper function to create a transaction script +fn create_transaction_script( + tx_script_code: String, + private_key_inputs: Vec<(Word, Vec)>, + masm_source: &str, + masm_path: LibraryPath, +) -> Result> { let assembler = TransactionKernel::assembler(); let source_manager = Arc::new(assembly::DefaultSourceManager::default()); // Parse the external MASM library let module = Module::parser(assembly::ast::ModuleKind::Library) .parse_str( - LibraryPath::new("oracle::push_oracle").unwrap(), - PUSH_ORACLE_SOURCE, + masm_path, + masm_source, &source_manager, ) .unwrap(); let library = assembler.clone().assemble_library(&[*module]).unwrap(); - assembler.clone().with_library(library).unwrap(); + let assembler = assembler.clone().with_library(library).unwrap(); // Compile the transaction script let tx_script = TransactionScript::compile( tx_script_code, - vec![(private_key_felts, Vec::new())], + private_key_inputs, assembler, ) .unwrap(); + Ok(tx_script) +} + +/// Helper function to execute a transaction +async fn execute_transaction( + client: &mut Client, + account_id: AccountId, + tx_script: TransactionScript, +) -> Result> +where + N: NodeRpcClient, + R: FeltRng, + S: Store, + A: TransactionAuthenticator, +{ 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)?; + let transaction_execution_result = client.new_transaction(account_id, request)?; let transaction_id = transaction_execution_result.executed_transaction().id(); client .submit_transaction(transaction_execution_result) .await?; + Ok(transaction_id.to_string()) +} + +pub async fn push_data_to_oracle_account( + client: &mut Client, + account: Account, + data: OracleData, + private_key: &SecretKey, +) -> Result<(), Box> +where + N: NodeRpcClient, + R: FeltRng, + S: Store, + A: TransactionAuthenticator, +{ + let word = data_to_word(&data); + let private_key_felts = super::secret_key_to_felts(private_key); + + let tx_script_code = format!( + PUSH_DATA_TX_SCRIPT, + word_to_masm(&word), + word_to_masm(&word), + word_to_masm(&word), + word_to_masm(&word) + ); + + let tx_script = create_transaction_script( + tx_script_code, + vec![(private_key_felts, Vec::new())], + PUSH_ORACLE_SOURCE, + PUSH_ORACLE_SOURCE_PATH, + )?; + + let transaction_id = execute_transaction(client, account.id(), tx_script).await?; println!("Data successfully pushed to oracle account! Transaction ID: {}", transaction_id); Ok(()) } -/// Read data from oracle account pub async fn read_data_from_oracle_account( client: &mut Client, account: Account, @@ -179,59 +221,19 @@ where }; let asset_pair_word = data_to_word(&oracle_data); - - // Create the transaction script code let tx_script_code = format!( - " - use.oracle::read_oracle - - begin - # Load asset pair to the stack - push.{} - - # Call the oracle contract procedure - call.read_oracle::read_oracle_data - - # Clear the stack - dropw dropw dropw dropw - - call.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 - dropw dropw dropw - end - ", + READ_DATA_TX_SCRIPT, word_to_masm(&asset_pair_word) ); - let assembler = TransactionKernel::assembler(); - let source_manager = Arc::new(assembly::DefaultSourceManager::default()); - - // Parse the external MASM library - let module = Module::parser(assembly::ast::ModuleKind::Library) - .parse_str( - LibraryPath::new("oracle::read_oracle").unwrap(), - READ_ORACLE_SOURCE, - &source_manager, - ) - .unwrap(); - - let library = assembler.clone().assemble_library(&[*module]).unwrap(); - assembler.clone().with_library(library).unwrap(); - - // Compile the transaction script - let tx_script = TransactionScript::compile( + let tx_script = create_transaction_script( tx_script_code, vec![], - assembler, - ) - .unwrap(); + READ_ORACLE_SOURCE, + READ_ORACLE_SOURCE_PATH, + )?; - 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)?; - let transaction_id = transaction_execution_result.executed_transaction().id(); - let oracle_data = client - .submit_transaction(transaction_execution_result).await?; + let _transaction_id = execute_transaction(client, account.id(), tx_script).await?; // TODO: fix this let oracle_data = OracleData { diff --git a/src/accounts/mod.rs b/src/accounts/mod.rs index 1377ff1..a301f74 100644 --- a/src/accounts/mod.rs +++ b/src/accounts/mod.rs @@ -1,9 +1,11 @@ mod accounts; +#[cfg(feature = "testing")] mod tests; use miden_crypto::{ merkle::{MmrPeaks, PartialMmr}, Felt, EMPTY_WORD, + dsa::rpo_falcon512::SecretKey, }; use miden_objects::{ accounts::{Account, AccountId}, @@ -89,3 +91,14 @@ pub fn word_to_data(word: &Word) -> OracleData { publisher_id: word[3].as_int(), } } + +/// Convert SecretKey to array of Felts representing the polynomials +pub fn secret_key_to_felts(private_key: &SecretKey) -> [Felt; 4] { + let basis = private_key.short_lattice_basis(); + [ + Felt::new(basis[0].lc() as u64), // g polynomial + Felt::new(basis[1].lc() as u64), // f polynomial + Felt::new(basis[2].lc() as u64), // G polynomial + Felt::new(basis[3].lc() as u64), // F polynomial + ] +} diff --git a/src/accounts/oracle/push_oracle.masm b/src/accounts/oracle/push_oracle.masm index 3c59fba..79d446d 100644 --- a/src/accounts/oracle/push_oracle.masm +++ b/src/accounts/oracle/push_oracle.masm @@ -1,7 +1,7 @@ #! Add imports -use.std::account -use.std::contracts::auth::basic -use.std::crypto::dsa::rpo_falcon512 +use.miden::account +use.miden::contracts::auth::basic +use.miden::crypto::dsa::rpo_falcon512 # Slot in account storage at which the data prover's public key is stored. const.DATA_PROVIDER_PUBLIC_KEY_SLOT=1 diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index a7342de..4f1a349 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -1,21 +1,21 @@ // use crate::accounts::{ // data_to_word, decode_u64_to_ascii, encode_ascii_to_u64, get_oracle_account, // push_data_to_oracle_account, read_data_from_oracle_account, word_to_data, word_to_masm, -// OracleData, +// OracleData, PUSH_ORACLE_SOURCE, PUSH_ORACLE_SOURCE_PATH, // }; // use miden_crypto::{ // Felt, ZERO, -// dsa::rpo_falcon512::{KeyPair, SecretKey}, +// dsa::rpo_falcon512::{SecretKey, PublicKey}, // rand::RpoRandomCoin, // }; // use miden_lib::AuthScheme; // use miden_objects::accounts::{Account, AccountStorageType}; // use miden_objects::{crypto::dsa::rpo_falcon512, ONE}; +// use miden_tx::testing::tx_context::builder::TransactionContextBuilder; // #[test] // fn oracle_account_creation_and_pushing_data_to_read() { -// let pub_key = rpo_falcon512::PublicKey::new([ONE; 4]); -// let auth_scheme: AuthScheme = AuthScheme::RpoFalcon512 { pub_key }; +// let auth_scheme: AuthScheme = AuthScheme::RpoFalcon512 { pub_key: PublicKey::new([ONE; 4]) }; // let init_seed: [u8; 32] = [ // 90, 110, 209, 94, 84, 105, 250, 242, 223, 203, 216, 124, 22, 159, 14, 132, 215, 85, 183, @@ -24,7 +24,7 @@ // let account_type = miden_objects::accounts::AccountType::RegularAccountImmutableCode; // let storage_type = AccountStorageType::OnChain; -// let data_provider_public_key = rpo_falcon512::PublicKey::new([ONE; 4]); +// let data_provider_public_key = PublicKey::new([ONE; 4]); // let (mut oracle_account, _) = get_oracle_account( // init_seed, @@ -42,9 +42,15 @@ // publisher_id: 1, // }; -// push_data_to_oracle_account(&mut oracle_account, oracle_data.clone()).unwrap(); +// let tx_context = TransactionContextBuilder::new(oracle_account.clone()).build(); + +// let tx_script = create_transaction_script( +// tx_script_code, +// vec![(private_key_felts, Vec::new())], +// PUSH_ORACLE_SOURCE, +// PUSH_ORACLE_SOURCE_PATH, +// )?; -// let read_data = read_data_from_oracle_account(&oracle_account, oracle_data.asset_pair.clone()).unwrap(); // assert_eq!(oracle_data, read_data); // } @@ -77,9 +83,7 @@ // #[test] // fn test_falcon_private_key_to_felts() { // // Create a random key pair -// let mut rng = RpoRandomCoin::new([1u8; 32]); -// let key_pair = KeyPair::new(&mut rng).unwrap(); -// let private_key = key_pair.secret_key(); +// let private_key = SecretKey::new(); // // Get the short lattice basis // let basis = private_key.short_lattice_basis(); From 5faf8413f9ce3bbb15e57f7081239988f84dbbf6 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Wed, 30 Oct 2024 14:13:05 +0530 Subject: [PATCH 03/45] nit --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d35ff64..814b6ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,13 +13,13 @@ miden-lib = { version = "0.5", default-features = false } miden-objects = { version = "0.5", default-features = false } miden-tx = { version = "0.5" } miden-cli = { version = "0.5" } -assembly = { package = "miden-assembly", version = "0.10.5", default-features = false } +assembly = { package = "miden-assembly", version = "0.10.5", default-features = true, features = ["std", "testing"] } rusqlite = { version = "0.31", features = ["vtab", "array", "bundled"]} rand = "0.8" tonic = { version = "0.12.3" } tokio = { version = "1.40.0", features = ["rt-multi-thread", "net", "macros"] } -clap = { version = "4.5", features = ["derive"] } +clap = { version = "4.5.20", features = ["derive"] } log = { version = "0.4.22" } env_logger = { version = "0.11.5" } colored = { version = "2.1.0" } From 31315d411f3a9288299d953087855139a26064b8 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Wed, 30 Oct 2024 17:05:06 +0530 Subject: [PATCH 04/45] dont use miden-assembly --- Cargo.toml | 1 - src/accounts/accounts.rs | 20 +++----------------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 814b6ff..5a2bad3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,6 @@ miden-lib = { version = "0.5", default-features = false } miden-objects = { version = "0.5", default-features = false } miden-tx = { version = "0.5" } miden-cli = { version = "0.5" } -assembly = { package = "miden-assembly", version = "0.10.5", default-features = true, features = ["std", "testing"] } rusqlite = { version = "0.31", features = ["vtab", "array", "bundled"]} rand = "0.8" diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index dc65358..3b68324 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -1,5 +1,4 @@ use super::{data_to_word, word_to_data, word_to_masm, OracleData}; -use assembly::{ast::Module, Assembler, Library, LibraryPath}; use miden_client::{rpc::NodeRpcClient, store::Store, transactions::request::TransactionRequest, Client}; use miden_crypto::{ dsa::rpo_falcon512::{PublicKey, SecretKey}, rand::FeltRng, Felt @@ -12,6 +11,7 @@ use miden_objects::{ }, transaction::{TransactionArgs, TransactionScript}, AccountError, Word, + assembly::{Assembler, Library, LibraryPath} }; use miden_tx::{auth::{BasicAuthenticator, TransactionAuthenticator}, TransactionExecutor}; use rand::rngs::OsRng; @@ -22,11 +22,10 @@ use std::{ path::{Path, PathBuf}, io, }; + // Include the oracle module source code pub const PUSH_ORACLE_SOURCE: &str = include_str!("oracle/push_oracle.masm"); -pub const PUSH_ORACLE_SOURCE_PATH: LibraryPath = LibraryPath::new("oracle::push_oracle").unwrap(); pub const READ_ORACLE_SOURCE: &str = include_str!("oracle/read_oracle.masm"); -pub const READ_ORACLE_SOURCE_PATH: LibraryPath = LibraryPath::new("oracle::read_oracle").unwrap(); const ASM_DIR: &str = "asm"; const ASSETS_DIR: &str = "assets"; @@ -113,22 +112,11 @@ pub fn get_oracle_account( fn create_transaction_script( tx_script_code: String, private_key_inputs: Vec<(Word, Vec)>, - masm_source: &str, masm_path: LibraryPath, ) -> Result> { let assembler = TransactionKernel::assembler(); let source_manager = Arc::new(assembly::DefaultSourceManager::default()); - - // Parse the external MASM library - let module = Module::parser(assembly::ast::ModuleKind::Library) - .parse_str( - masm_path, - masm_source, - &source_manager, - ) - .unwrap(); - - let library = assembler.clone().assemble_library(&[*module]).unwrap(); + let library = Library::from_dir(masm_path, LibraryNamespace::new("oracle").unwrap(), assembler)?; let assembler = assembler.clone().with_library(library).unwrap(); // Compile the transaction script @@ -193,7 +181,6 @@ where tx_script_code, vec![(private_key_felts, Vec::new())], PUSH_ORACLE_SOURCE, - PUSH_ORACLE_SOURCE_PATH, )?; let transaction_id = execute_transaction(client, account.id(), tx_script).await?; @@ -230,7 +217,6 @@ where tx_script_code, vec![], READ_ORACLE_SOURCE, - READ_ORACLE_SOURCE_PATH, )?; let _transaction_id = execute_transaction(client, account.id(), tx_script).await?; From 3dbcac0b9d512e8f8dd328c62f48daf2f395c732 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Wed, 30 Oct 2024 17:36:57 +0530 Subject: [PATCH 05/45] use txn executor --- src/accounts/tests.rs | 225 ++++++++++++++++++++++-------------------- 1 file changed, 116 insertions(+), 109 deletions(-) diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index 4f1a349..d4de6d0 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -1,111 +1,118 @@ -// use crate::accounts::{ -// data_to_word, decode_u64_to_ascii, encode_ascii_to_u64, get_oracle_account, -// push_data_to_oracle_account, read_data_from_oracle_account, word_to_data, word_to_masm, -// OracleData, PUSH_ORACLE_SOURCE, PUSH_ORACLE_SOURCE_PATH, -// }; -// use miden_crypto::{ -// Felt, ZERO, -// dsa::rpo_falcon512::{SecretKey, PublicKey}, -// rand::RpoRandomCoin, -// }; -// use miden_lib::AuthScheme; -// use miden_objects::accounts::{Account, AccountStorageType}; -// use miden_objects::{crypto::dsa::rpo_falcon512, ONE}; -// use miden_tx::testing::tx_context::builder::TransactionContextBuilder; - -// #[test] -// fn oracle_account_creation_and_pushing_data_to_read() { -// let auth_scheme: AuthScheme = AuthScheme::RpoFalcon512 { pub_key: PublicKey::new([ONE; 4]) }; - -// let init_seed: [u8; 32] = [ -// 90, 110, 209, 94, 84, 105, 250, 242, 223, 203, 216, 124, 22, 159, 14, 132, 215, 85, 183, -// 204, 149, 90, 166, 68, 100, 73, 106, 168, 125, 237, 138, 16, -// ]; - -// let account_type = miden_objects::accounts::AccountType::RegularAccountImmutableCode; -// let storage_type = AccountStorageType::OnChain; -// let data_provider_public_key = PublicKey::new([ONE; 4]); - -// let (mut oracle_account, _) = get_oracle_account( -// init_seed, -// auth_scheme, -// account_type, -// storage_type, -// data_provider_public_key, -// ) -// .unwrap(); - -// let oracle_data = OracleData { -// asset_pair: "BTC/USD".to_string(), -// price: 50000, -// decimals: 2, -// publisher_id: 1, -// }; - -// let tx_context = TransactionContextBuilder::new(oracle_account.clone()).build(); - -// let tx_script = create_transaction_script( -// tx_script_code, -// vec![(private_key_felts, Vec::new())], -// PUSH_ORACLE_SOURCE, -// PUSH_ORACLE_SOURCE_PATH, -// )?; - -// assert_eq!(oracle_data, read_data); -// } - -// #[test] -// fn test_ascii_encoding_decoding() { -// let original = "BTC/USD"; -// let encoded = encode_ascii_to_u64(original); -// let decoded = decode_u64_to_ascii(encoded); -// assert_eq!(original, decoded); -// } - -// #[test] -// fn test_oracle_data_conversion() { -// let original_data = OracleData { -// asset_pair: "BTC/USD".to_string(), -// price: 50000, -// decimals: 2, -// publisher_id: 1, -// }; - -// let word = data_to_word(&original_data); -// let converted_data = word_to_data(&word); - -// assert_eq!(original_data.asset_pair, converted_data.asset_pair); -// assert_eq!(original_data.price, converted_data.price); -// assert_eq!(original_data.decimals, converted_data.decimals); -// assert_eq!(original_data.publisher_id, converted_data.publisher_id); -// } - -// #[test] -// fn test_falcon_private_key_to_felts() { -// // Create a random key pair -// let private_key = SecretKey::new(); +use crate::accounts::{ + data_to_word, decode_u64_to_ascii, encode_ascii_to_u64, get_oracle_account, + push_data_to_oracle_account, read_data_from_oracle_account, word_to_data, word_to_masm, + OracleData, PUSH_ORACLE_SOURCE, +}; +use miden_crypto::{ + Felt, ZERO, + dsa::rpo_falcon512::{SecretKey, PublicKey}, + rand::RpoRandomCoin, +}; +use miden_lib::AuthScheme; +use miden_objects::accounts::{Account, AccountStorageType}; +use miden_objects::{crypto::dsa::rpo_falcon512, ONE}; +use miden_tx::testing::tx_context::builder::TransactionContextBuilder; +use miden_tx::get_new_pk_and_authenticator; + +#[test] +fn oracle_account_creation_and_pushing_data_to_read() { + let (oracle_pub_key, oracle_auth) = get_new_pk_and_authenticator(); + let auth_scheme: AuthScheme = AuthScheme::RpoFalcon512 { pub_key: oracle_pub_key }; + + let init_seed: [u8; 32] = [ + 90, 110, 209, 94, 84, 105, 250, 242, 223, 203, 216, 124, 22, 159, 14, 132, 215, 85, 183, + 204, 149, 90, 166, 68, 100, 73, 106, 168, 125, 237, 138, 16, + ]; + + let account_type = miden_objects::accounts::AccountType::RegularAccountImmutableCode; + let storage_type = AccountStorageType::OnChain; + let data_provider_public_key = PublicKey::new([ONE; 4]); + + let (mut oracle_account, _) = get_oracle_account( + init_seed, + auth_scheme, + account_type, + storage_type, + data_provider_public_key, + ) + .unwrap(); + + let oracle_data = OracleData { + asset_pair: "BTC/USD".to_string(), + price: 50000, + decimals: 2, + publisher_id: 1, + }; + + let tx_context = TransactionContextBuilder::new(oracle_account.clone()).build(); + let executor = TransactionExecutor::new(tx_context.clone(), Some(oracle_auth.clone())); + + let tx_script = create_transaction_script( + tx_script_code, + vec![(private_key_felts, Vec::new())], + PUSH_ORACLE_SOURCE, + )?; + + let txn_args = TransactionArgs::from_tx_script(tx_script); + let executed_transaction = executor + .execute_transaction(oracle_account.id(), None, &[], txn_args) + .unwrap(); + + assert!(prove_and_verify_transaction(executed_transaction.clone()).is_ok()); +} + +#[test] +fn test_ascii_encoding_decoding() { + let original = "BTC/USD"; + let encoded = encode_ascii_to_u64(original); + let decoded = decode_u64_to_ascii(encoded); + assert_eq!(original, decoded); +} + +#[test] +fn test_oracle_data_conversion() { + let original_data = OracleData { + asset_pair: "BTC/USD".to_string(), + price: 50000, + decimals: 2, + publisher_id: 1, + }; + + let word = data_to_word(&original_data); + let converted_data = word_to_data(&word); + + assert_eq!(original_data.asset_pair, converted_data.asset_pair); + assert_eq!(original_data.price, converted_data.price); + assert_eq!(original_data.decimals, converted_data.decimals); + assert_eq!(original_data.publisher_id, converted_data.publisher_id); +} + +#[test] +fn test_falcon_private_key_to_felts() { + // Create a random key pair + let private_key = SecretKey::new(); -// // Get the short lattice basis -// let basis = private_key.short_lattice_basis(); + // Get the short lattice basis + let basis = private_key.short_lattice_basis(); -// // Convert to Felts -// let private_key_felts = [ -// Felt::new(basis[0].lc() as u64), // g polynomial -// Felt::new(basis[1].lc() as u64), // f polynomial -// Felt::new(basis[2].lc() as u64), // G polynomial -// Felt::new(basis[3].lc() as u64), // F polynomial -// ]; - -// // Verify we have 4 elements -// assert_eq!(private_key_felts.len(), 4); - -// // Verify each element is a valid Felt -// for felt in private_key_felts.iter() { -// assert!(felt.as_int() <= u64::MAX); -// } - -// // Verify the values match the original basis coefficients -// for (i, felt) in private_key_felts.iter().enumerate() { -// assert_eq!(felt.as_int() as u64, basis[i].lc() as u64); -// } -// } + // Convert to Felts + let private_key_felts = [ + Felt::new(basis[0].lc() as u64), // g polynomial + Felt::new(basis[1].lc() as u64), // f polynomial + Felt::new(basis[2].lc() as u64), // G polynomial + Felt::new(basis[3].lc() as u64), // F polynomial + ]; + + // Verify we have 4 elements + assert_eq!(private_key_felts.len(), 4); + + // Verify each element is a valid Felt + for felt in private_key_felts.iter() { + assert!(felt.as_int() <= u64::MAX); + } + + // Verify the values match the original basis coefficients + for (i, felt) in private_key_felts.iter().enumerate() { + assert_eq!(felt.as_int() as u64, basis[i].lc() as u64); + } +} From c306f8918028be91b373975915f2629956931cfe Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Wed, 30 Oct 2024 20:12:27 +0530 Subject: [PATCH 06/45] push tests --- src/accounts/tests.rs | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index d4de6d0..ff26b3b 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -1,7 +1,7 @@ use crate::accounts::{ data_to_word, decode_u64_to_ascii, encode_ascii_to_u64, get_oracle_account, push_data_to_oracle_account, read_data_from_oracle_account, word_to_data, word_to_masm, - OracleData, PUSH_ORACLE_SOURCE, + OracleData, PUSH_ORACLE_SOURCE, PUSH_DATA_TX_SCRIPT, READ_ORACLE_SOURCE, READ_DATA_TX_SCRIPT, accounts::secret_key_to_felts }; use miden_crypto::{ Felt, ZERO, @@ -11,8 +11,8 @@ use miden_crypto::{ use miden_lib::AuthScheme; use miden_objects::accounts::{Account, AccountStorageType}; use miden_objects::{crypto::dsa::rpo_falcon512, ONE}; -use miden_tx::testing::tx_context::builder::TransactionContextBuilder; -use miden_tx::get_new_pk_and_authenticator; +use miden_tx::{testing::TransactionContextBuilder, TransactionExecutor}; +use miden_tx::{get_new_pk_and_authenticator, prove_and_verify_transaction}; #[test] fn oracle_account_creation_and_pushing_data_to_read() { @@ -26,7 +26,8 @@ fn oracle_account_creation_and_pushing_data_to_read() { let account_type = miden_objects::accounts::AccountType::RegularAccountImmutableCode; let storage_type = AccountStorageType::OnChain; - let data_provider_public_key = PublicKey::new([ONE; 4]); + let data_provider_private_key = SecretKey::new(); + let data_provider_public_key = data_provider_private_key.public_key(); let (mut oracle_account, _) = get_oracle_account( init_seed, @@ -44,21 +45,44 @@ fn oracle_account_creation_and_pushing_data_to_read() { publisher_id: 1, }; + let word = data_to_word(&oracle_data); + let tx_context = TransactionContextBuilder::new(oracle_account.clone()).build(); let executor = TransactionExecutor::new(tx_context.clone(), Some(oracle_auth.clone())); - let tx_script = create_transaction_script( - tx_script_code, + let push_tx_script_code = format!( + PUSH_DATA_TX_SCRIPT, + word_to_masm(&word), + word_to_masm(&word), + word_to_masm(&word), + word_to_masm(&word) + ); + + let push_tx_script = create_transaction_script( + push_tx_script_code, vec![(private_key_felts, Vec::new())], PUSH_ORACLE_SOURCE, )?; - let txn_args = TransactionArgs::from_tx_script(tx_script); + let txn_args = TransactionArgs::from_tx_script(push_tx_script); let executed_transaction = executor .execute_transaction(oracle_account.id(), None, &[], txn_args) .unwrap(); assert!(prove_and_verify_transaction(executed_transaction.clone()).is_ok()); + + // let read_tx_script = create_transaction_script( + // read_tx_script_code, + // vec![], + // READ_ORACLE_SOURCE, + // )?; + + // let txn_args = TransactionArgs::from_tx_script(read_tx_script); + // let executed_transaction = executor + // .execute_transaction(oracle_account.id(), None, &[], txn_args) + // .unwrap(); + + // assert!(prove_and_verify_transaction(executed_transaction.clone()).is_ok()); } #[test] From 10340a46ee9dae9b03fb8917243f983ecf5be67b Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Thu, 31 Oct 2024 10:21:17 +0530 Subject: [PATCH 07/45] nit --- Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5a2bad3..d23a889 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,6 @@ name = "pragma-miden" version = "0.1.0" edition = "2021" -[features] -testing = ["miden-client/testing"] - [dependencies] miden-client = { version = "0.5", features = ["concurrent", "testing", "sqlite", "tonic"] } miden-crypto = { version = "0.10", default-features = false } From 8f23c846b8c6cc1756c9ef744a6dab9698505d54 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Thu, 31 Oct 2024 15:11:54 +0530 Subject: [PATCH 08/45] nits --- src/accounts/accounts.rs | 41 ++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index 3b68324..3dd7306 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -11,7 +11,7 @@ use miden_objects::{ }, transaction::{TransactionArgs, TransactionScript}, AccountError, Word, - assembly::{Assembler, Library, LibraryPath} + assembly::{Assembler, Library, LibraryPath, LibraryNamespace} }; use miden_tx::{auth::{BasicAuthenticator, TransactionAuthenticator}, TransactionExecutor}; use rand::rngs::OsRng; @@ -22,12 +22,11 @@ use std::{ path::{Path, PathBuf}, io, }; +use std::str::FromStr; // Include the oracle module source code -pub const PUSH_ORACLE_SOURCE: &str = include_str!("oracle/push_oracle.masm"); -pub const READ_ORACLE_SOURCE: &str = include_str!("oracle/read_oracle.masm"); -const ASM_DIR: &str = "asm"; -const ASSETS_DIR: &str = "assets"; +pub const PUSH_ORACLE_PATH: &str = "src/accounts/oracle/push_oracle.masm"; +pub const READ_ORACLE_PATH: &str = "src/accounts/oracle/read_oracle.masm"; /// Transaction script template for pushing data to oracle pub const PUSH_DATA_TX_SCRIPT: &str = r#" @@ -112,12 +111,21 @@ pub fn get_oracle_account( fn create_transaction_script( tx_script_code: String, private_key_inputs: Vec<(Word, Vec)>, - masm_path: LibraryPath, + masm_path: &str, ) -> Result> { let assembler = TransactionKernel::assembler(); - let source_manager = Arc::new(assembly::DefaultSourceManager::default()); - let library = Library::from_dir(masm_path, LibraryNamespace::new("oracle").unwrap(), assembler)?; - let assembler = assembler.clone().with_library(library).unwrap(); + + // Get the directory containing the MASM file + let masm_dir = Path::new(masm_path).parent().unwrap(); + + // Clone the assembler before passing it to from_dir + let library = Library::from_dir( + masm_dir, + LibraryNamespace::new("oracle")?, + assembler.clone() + )?; + + let assembler = assembler.with_library(library).unwrap(); // Compile the transaction script let tx_script = TransactionScript::compile( @@ -170,17 +178,14 @@ where let private_key_felts = super::secret_key_to_felts(private_key); let tx_script_code = format!( - PUSH_DATA_TX_SCRIPT, - word_to_masm(&word), - word_to_masm(&word), - word_to_masm(&word), - word_to_masm(&word) + "{}", + PUSH_DATA_TX_SCRIPT.replace("{}", &word_to_masm(&word)) ); let tx_script = create_transaction_script( tx_script_code, vec![(private_key_felts, Vec::new())], - PUSH_ORACLE_SOURCE, + PUSH_ORACLE_PATH, )?; let transaction_id = execute_transaction(client, account.id(), tx_script).await?; @@ -209,14 +214,14 @@ where let asset_pair_word = data_to_word(&oracle_data); let tx_script_code = format!( - READ_DATA_TX_SCRIPT, - word_to_masm(&asset_pair_word) + "{}", + READ_DATA_TX_SCRIPT.replace("{}", &word_to_masm(&asset_pair_word)) ); let tx_script = create_transaction_script( tx_script_code, vec![], - READ_ORACLE_SOURCE, + READ_ORACLE_PATH, )?; let _transaction_id = execute_transaction(client, account.id(), tx_script).await?; From b2c1e7963d4722676e0da410e0c9dba13890159b Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Thu, 31 Oct 2024 20:13:26 +0530 Subject: [PATCH 09/45] nits --- .cargo/config.toml | 2 -- .github/workflows/build_and_test.yml | 1 - 2 files changed, 3 deletions(-) delete mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml deleted file mode 100644 index 1a07762..0000000 --- a/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[build] -rustflags = ["--cfg", "feature=\"testing\""] \ No newline at end of file diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 82466de..bd3e483 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -2,7 +2,6 @@ name: Build and Test on: push: - branches: [ main ] pull_request: branches: [ main ] From 370b20dd62e041b85c6b454bbc0c0a57f6bcb5b3 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Thu, 31 Oct 2024 23:09:57 +0530 Subject: [PATCH 10/45] WIP tests --- .vscode/settings.json | 8 ++++ Cargo.toml | 5 +- src/accounts/accounts.rs | 2 +- src/accounts/mod.rs | 1 - src/accounts/tests.rs | 100 ++++++++++++++++++++++++++------------- 5 files changed, 79 insertions(+), 37 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..825c99b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "workbench.colorCustomizations": { + "editorLineNumber.foreground": "#00ff00", + "activityBar.background": "#153406", + "titleBar.activeBackground": "#1D4908", + "titleBar.activeForeground": "#F4FDEF" + } +} \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index d23a889..662d2c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,12 +3,15 @@ name = "pragma-miden" version = "0.1.0" edition = "2021" +[features] +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", default-features = false } -miden-tx = { version = "0.5" } +miden-tx = { version = "0.5", features = ["testing"] } miden-cli = { version = "0.5" } rusqlite = { version = "0.31", features = ["vtab", "array", "bundled"]} diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index 3dd7306..08e34f6 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -108,7 +108,7 @@ pub fn get_oracle_account( } /// Helper function to create a transaction script -fn create_transaction_script( +pub fn create_transaction_script( tx_script_code: String, private_key_inputs: Vec<(Word, Vec)>, masm_path: &str, diff --git a/src/accounts/mod.rs b/src/accounts/mod.rs index a301f74..e2e033e 100644 --- a/src/accounts/mod.rs +++ b/src/accounts/mod.rs @@ -1,5 +1,4 @@ mod accounts; -#[cfg(feature = "testing")] mod tests; use miden_crypto::{ diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index ff26b3b..ce27cc6 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -1,23 +1,31 @@ use crate::accounts::{ data_to_word, decode_u64_to_ascii, encode_ascii_to_u64, get_oracle_account, push_data_to_oracle_account, read_data_from_oracle_account, word_to_data, word_to_masm, - OracleData, PUSH_ORACLE_SOURCE, PUSH_DATA_TX_SCRIPT, READ_ORACLE_SOURCE, READ_DATA_TX_SCRIPT, accounts::secret_key_to_felts + OracleData, secret_key_to_felts +}; +use crate::accounts::accounts::{ + PUSH_ORACLE_PATH as PUSH_ORACLE_SOURCE, + READ_ORACLE_PATH as READ_ORACLE_SOURCE, + PUSH_DATA_TX_SCRIPT, + READ_DATA_TX_SCRIPT, + create_transaction_script }; use miden_crypto::{ - Felt, ZERO, + Felt, ZERO, Word, dsa::rpo_falcon512::{SecretKey, PublicKey}, rand::RpoRandomCoin, }; use miden_lib::AuthScheme; -use miden_objects::accounts::{Account, AccountStorageType}; +use miden_objects::{transaction::{TransactionArgs, ExecutedTransaction, ProvenTransaction}, accounts::{Account, AccountStorageType}, crypto::utils::Serializable}; use miden_objects::{crypto::dsa::rpo_falcon512, ONE}; -use miden_tx::{testing::TransactionContextBuilder, TransactionExecutor}; -use miden_tx::{get_new_pk_and_authenticator, prove_and_verify_transaction}; +use miden_tx::{testing::TransactionContextBuilder, TransactionExecutor, TransactionProver, TransactionVerifier, TransactionVerifierError, ProvingOptions}; +use miden_client::utils::Deserializable; +use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; #[test] fn oracle_account_creation_and_pushing_data_to_read() { let (oracle_pub_key, oracle_auth) = get_new_pk_and_authenticator(); - let auth_scheme: AuthScheme = AuthScheme::RpoFalcon512 { pub_key: oracle_pub_key }; + let auth_scheme: AuthScheme = AuthScheme::RpoFalcon512 { pub_key: PublicKey::new(oracle_pub_key) }; let init_seed: [u8; 32] = [ 90, 110, 209, 94, 84, 105, 250, 242, 223, 203, 216, 124, 22, 159, 14, 132, 215, 85, 183, @@ -51,22 +59,19 @@ fn oracle_account_creation_and_pushing_data_to_read() { let executor = TransactionExecutor::new(tx_context.clone(), Some(oracle_auth.clone())); let push_tx_script_code = format!( - PUSH_DATA_TX_SCRIPT, - word_to_masm(&word), - word_to_masm(&word), - word_to_masm(&word), - word_to_masm(&word) + "{}", + PUSH_DATA_TX_SCRIPT.replace("{}", &word_to_masm(&word)) ); let push_tx_script = create_transaction_script( push_tx_script_code, - vec![(private_key_felts, Vec::new())], + vec![(secret_key_to_felts(&data_provider_private_key), Vec::new())], PUSH_ORACLE_SOURCE, - )?; + ).unwrap(); - let txn_args = TransactionArgs::from_tx_script(push_tx_script); + let txn_args = TransactionArgs::with_tx_script(push_tx_script); let executed_transaction = executor - .execute_transaction(oracle_account.id(), None, &[], txn_args) + .execute_transaction(oracle_account.id(), 0, &[], txn_args) .unwrap(); assert!(prove_and_verify_transaction(executed_transaction.clone()).is_ok()); @@ -113,30 +118,57 @@ fn test_oracle_data_conversion() { #[test] fn test_falcon_private_key_to_felts() { - // Create a random key pair let private_key = SecretKey::new(); + let felts = secret_key_to_felts(&private_key); - // Get the short lattice basis + // Get the original basis coefficients let basis = private_key.short_lattice_basis(); - // Convert to Felts - let private_key_felts = [ - Felt::new(basis[0].lc() as u64), // g polynomial - Felt::new(basis[1].lc() as u64), // f polynomial - Felt::new(basis[2].lc() as u64), // G polynomial - Felt::new(basis[3].lc() as u64), // F polynomial - ]; + // Verify each coefficient matches + for (i, felt) in felts.iter().enumerate() { + let expected = basis[i].lc() as u64; + assert_eq!(felt.as_int(), expected as u64); + } +} - // Verify we have 4 elements - assert_eq!(private_key_felts.len(), 4); +fn get_new_pk_and_authenticator( +) -> (Word, std::rc::Rc>) { + use std::rc::Rc; - // Verify each element is a valid Felt - for felt in private_key_felts.iter() { - assert!(felt.as_int() <= u64::MAX); - } + use miden_objects::accounts::AuthSecretKey; + use miden_tx::auth::BasicAuthenticator; + use rand::rngs::StdRng; - // Verify the values match the original basis coefficients - for (i, felt) in private_key_felts.iter().enumerate() { - assert_eq!(felt.as_int() as u64, basis[i].lc() as u64); - } + let seed = [0_u8; 32]; + let mut rng = ChaCha20Rng::from_seed(seed); + + let sec_key = SecretKey::with_rng(&mut rng); + let pub_key: Word = sec_key.public_key().into(); + + let authenticator = + BasicAuthenticator::::new(&[(pub_key, AuthSecretKey::RpoFalcon512(sec_key))]); + + (pub_key, Rc::new(authenticator)) } + +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(); + + assert_eq!(proven_transaction.id(), executed_transaction_id); + + // Serialize & deserialize the ProvenTransaction + let serialised_transaction = proven_transaction.to_bytes(); + let proven_transaction = ProvenTransaction::read_from_bytes(&serialised_transaction).unwrap(); + + // Verify that the generated proof is valid + let verifier = TransactionVerifier::new(miden_objects::MIN_PROOF_SECURITY_LEVEL); + + verifier.verify(proven_transaction) +} \ No newline at end of file From 836f9fbb71c8738cb242715289f01aae8a875c9a Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Fri, 1 Nov 2024 17:15:28 +0530 Subject: [PATCH 11/45] test nits --- src/accounts/tests.rs | 70 +++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index ce27cc6..7aa4753 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -1,5 +1,5 @@ use crate::accounts::{ - data_to_word, decode_u64_to_ascii, encode_ascii_to_u64, get_oracle_account, + data_to_word, decode_u64_to_ascii, encode_ascii_to_u64, push_data_to_oracle_account, read_data_from_oracle_account, word_to_data, word_to_masm, OracleData, secret_key_to_felts }; @@ -15,8 +15,22 @@ use miden_crypto::{ dsa::rpo_falcon512::{SecretKey, PublicKey}, rand::RpoRandomCoin, }; -use miden_lib::AuthScheme; -use miden_objects::{transaction::{TransactionArgs, ExecutedTransaction, ProvenTransaction}, accounts::{Account, AccountStorageType}, crypto::utils::Serializable}; +use miden_lib::{AuthScheme, transaction::TransactionKernel}; +use miden_objects::{ + transaction::{TransactionArgs, ExecutedTransaction, ProvenTransaction}, + accounts::{ + Account, + AccountStorageType, + AccountId, + AccountCode, + AccountStorage, + SlotItem, + account_id::testing::ACCOUNT_ID_REGULAR_ACCOUNT_IMMUTABLE_CODE_ON_CHAIN + }, + crypto::utils::Serializable, + assets::AssetVault, +}; +use std::collections::BTreeMap; use miden_objects::{crypto::dsa::rpo_falcon512, ONE}; use miden_tx::{testing::TransactionContextBuilder, TransactionExecutor, TransactionProver, TransactionVerifier, TransactionVerifierError, ProvingOptions}; use miden_client::utils::Deserializable; @@ -25,26 +39,10 @@ use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; #[test] fn oracle_account_creation_and_pushing_data_to_read() { let (oracle_pub_key, oracle_auth) = get_new_pk_and_authenticator(); - let auth_scheme: AuthScheme = AuthScheme::RpoFalcon512 { pub_key: PublicKey::new(oracle_pub_key) }; - - let init_seed: [u8; 32] = [ - 90, 110, 209, 94, 84, 105, 250, 242, 223, 203, 216, 124, 22, 159, 14, 132, 215, 85, 183, - 204, 149, 90, 166, 68, 100, 73, 106, 168, 125, 237, 138, 16, - ]; - - let account_type = miden_objects::accounts::AccountType::RegularAccountImmutableCode; - let storage_type = AccountStorageType::OnChain; let data_provider_private_key = SecretKey::new(); let data_provider_public_key = data_provider_private_key.public_key(); - let (mut oracle_account, _) = get_oracle_account( - init_seed, - auth_scheme, - account_type, - storage_type, - data_provider_public_key, - ) - .unwrap(); + let oracle_account = get_oracle_account(data_provider_public_key, oracle_pub_key); let oracle_data = OracleData { asset_pair: "BTC/USD".to_string(), @@ -127,7 +125,7 @@ fn test_falcon_private_key_to_felts() { // Verify each coefficient matches for (i, felt) in felts.iter().enumerate() { let expected = basis[i].lc() as u64; - assert_eq!(felt.as_int(), expected as u64); + assert_eq!(felt.as_int(), expected); } } @@ -171,4 +169,32 @@ fn prove_and_verify_transaction( let verifier = TransactionVerifier::new(miden_objects::MIN_PROOF_SECURITY_LEVEL); verifier.verify(proven_transaction) -} \ No newline at end of file +} + +fn get_oracle_account(data_provider_public_key: PublicKey, oracle_public_key: Word) -> Account { + 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(); + let assembler = TransactionKernel::assembler(); + let source_code = format!( + " + export.::miden::contracts::auth::basic::falcon512 + " + ); + let oracle_account_code = AccountCode::compile(source_code, assembler).unwrap(); + + let account_storage = AccountStorage::new( + vec![ + SlotItem::new_value(0, 0, account_owner_public_key.into()), + SlotItem::new_value(1, 0, data_provider_public_key.into()), + ], + BTreeMap::new(), + ).unwrap(); + + Account::from_parts( + oracle_account_id, + AssetVault::new(&[]).unwrap(), + account_storage.clone(), + oracle_account_code.clone(), + Felt::new(1), + ) +} From 7e1f031acefcd34e2d879f50418cbee384d44ca3 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Fri, 1 Nov 2024 18:15:49 +0530 Subject: [PATCH 12/45] nits --- src/accounts/accounts.rs | 53 ++++++++++++++++---------------- src/accounts/mod.rs | 2 +- src/accounts/tests.rs | 63 +++++++++++++++++++------------------- src/commands/mod.rs | 6 ++-- src/commands/new_oracle.rs | 4 +-- src/commands/push_data.rs | 7 ++--- 6 files changed, 65 insertions(+), 70 deletions(-) diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index 08e34f6..18e230d 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -1,7 +1,11 @@ use super::{data_to_word, 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::request::TransactionRequest, Client, +}; use miden_crypto::{ - dsa::rpo_falcon512::{PublicKey, SecretKey}, rand::FeltRng, Felt + dsa::rpo_falcon512::{PublicKey, SecretKey}, + rand::FeltRng, + Felt, }; use miden_lib::{transaction::TransactionKernel, AuthScheme}; use miden_objects::{ @@ -9,20 +13,22 @@ use miden_objects::{ Account, AccountCode, AccountId, AccountStorage, AccountStorageType, AccountType, AuthSecretKey, SlotItem, }, + assembly::{Assembler, Library, LibraryNamespace, LibraryPath}, transaction::{TransactionArgs, TransactionScript}, AccountError, Word, - assembly::{Assembler, Library, LibraryPath, LibraryNamespace} }; -use miden_tx::{auth::{BasicAuthenticator, TransactionAuthenticator}, TransactionExecutor}; +use miden_tx::{ + auth::{BasicAuthenticator, TransactionAuthenticator}, + TransactionExecutor, +}; use rand::rngs::OsRng; use std::collections::BTreeMap; +use std::str::FromStr; use std::sync::Arc; use std::{ - env, + env, io, path::{Path, PathBuf}, - io, }; -use std::str::FromStr; // Include the oracle module source code pub const PUSH_ORACLE_PATH: &str = "src/accounts/oracle/push_oracle.masm"; @@ -114,26 +120,22 @@ pub fn create_transaction_script( masm_path: &str, ) -> Result> { let assembler = TransactionKernel::assembler(); - + // Get the directory containing the MASM file let masm_dir = Path::new(masm_path).parent().unwrap(); - + // Clone the assembler before passing it to from_dir let library = Library::from_dir( masm_dir, LibraryNamespace::new("oracle")?, - assembler.clone() + assembler.clone(), )?; - + let assembler = assembler.with_library(library).unwrap(); // Compile the transaction script - let tx_script = TransactionScript::compile( - tx_script_code, - private_key_inputs, - assembler, - ) - .unwrap(); + let tx_script = + TransactionScript::compile(tx_script_code, private_key_inputs, assembler).unwrap(); Ok(tx_script) } @@ -158,7 +160,7 @@ where client .submit_transaction(transaction_execution_result) .await?; - + Ok(transaction_id.to_string()) } @@ -167,7 +169,7 @@ pub async fn push_data_to_oracle_account( account: Account, data: OracleData, private_key: &SecretKey, -) -> Result<(), Box> +) -> Result<(), Box> where N: NodeRpcClient, R: FeltRng, @@ -189,7 +191,10 @@ where )?; let transaction_id = execute_transaction(client, account.id(), tx_script).await?; - println!("Data successfully pushed to oracle account! Transaction ID: {}", transaction_id); + println!( + "Data successfully pushed to oracle account! Transaction ID: {}", + transaction_id + ); Ok(()) } @@ -204,7 +209,7 @@ where R: FeltRng, S: Store, A: TransactionAuthenticator, -{ +{ let oracle_data = OracleData { asset_pair, price: 0, @@ -218,11 +223,7 @@ where READ_DATA_TX_SCRIPT.replace("{}", &word_to_masm(&asset_pair_word)) ); - let tx_script = create_transaction_script( - tx_script_code, - vec![], - READ_ORACLE_PATH, - )?; + let tx_script = create_transaction_script(tx_script_code, vec![], READ_ORACLE_PATH)?; let _transaction_id = execute_transaction(client, account.id(), tx_script).await?; diff --git a/src/accounts/mod.rs b/src/accounts/mod.rs index e2e033e..b801ab4 100644 --- a/src/accounts/mod.rs +++ b/src/accounts/mod.rs @@ -2,9 +2,9 @@ mod accounts; mod tests; use miden_crypto::{ + dsa::rpo_falcon512::SecretKey, merkle::{MmrPeaks, PartialMmr}, Felt, EMPTY_WORD, - dsa::rpo_falcon512::SecretKey, }; use miden_objects::{ accounts::{Account, AccountId}, diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index 7aa4753..ca32230 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -1,40 +1,34 @@ -use crate::accounts::{ - data_to_word, decode_u64_to_ascii, encode_ascii_to_u64, - push_data_to_oracle_account, read_data_from_oracle_account, word_to_data, word_to_masm, - OracleData, secret_key_to_felts -}; use crate::accounts::accounts::{ - PUSH_ORACLE_PATH as PUSH_ORACLE_SOURCE, - READ_ORACLE_PATH as READ_ORACLE_SOURCE, - PUSH_DATA_TX_SCRIPT, - READ_DATA_TX_SCRIPT, - create_transaction_script + create_transaction_script, PUSH_DATA_TX_SCRIPT, PUSH_ORACLE_PATH as PUSH_ORACLE_SOURCE, + READ_DATA_TX_SCRIPT, READ_ORACLE_PATH as READ_ORACLE_SOURCE, +}; +use crate::accounts::{ + data_to_word, decode_u64_to_ascii, encode_ascii_to_u64, push_data_to_oracle_account, + read_data_from_oracle_account, secret_key_to_felts, word_to_data, word_to_masm, OracleData, }; +use miden_client::utils::Deserializable; use miden_crypto::{ - Felt, ZERO, Word, - dsa::rpo_falcon512::{SecretKey, PublicKey}, + dsa::rpo_falcon512::{PublicKey, SecretKey}, rand::RpoRandomCoin, + Felt, Word, ZERO, }; -use miden_lib::{AuthScheme, transaction::TransactionKernel}; +use miden_lib::{transaction::TransactionKernel, AuthScheme}; use miden_objects::{ - transaction::{TransactionArgs, ExecutedTransaction, ProvenTransaction}, accounts::{ - Account, - AccountStorageType, - AccountId, - AccountCode, - AccountStorage, - SlotItem, - account_id::testing::ACCOUNT_ID_REGULAR_ACCOUNT_IMMUTABLE_CODE_ON_CHAIN + account_id::testing::ACCOUNT_ID_REGULAR_ACCOUNT_IMMUTABLE_CODE_ON_CHAIN, Account, + AccountCode, AccountId, AccountStorage, AccountStorageType, SlotItem, }, - crypto::utils::Serializable, assets::AssetVault, + crypto::utils::Serializable, + transaction::{ExecutedTransaction, ProvenTransaction, TransactionArgs}, }; -use std::collections::BTreeMap; use miden_objects::{crypto::dsa::rpo_falcon512, ONE}; -use miden_tx::{testing::TransactionContextBuilder, TransactionExecutor, TransactionProver, TransactionVerifier, TransactionVerifierError, ProvingOptions}; -use miden_client::utils::Deserializable; +use miden_tx::{ + testing::TransactionContextBuilder, ProvingOptions, TransactionExecutor, TransactionProver, + TransactionVerifier, TransactionVerifierError, +}; use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; +use std::collections::BTreeMap; #[test] fn oracle_account_creation_and_pushing_data_to_read() { @@ -65,7 +59,8 @@ fn oracle_account_creation_and_pushing_data_to_read() { push_tx_script_code, vec![(secret_key_to_felts(&data_provider_private_key), Vec::new())], PUSH_ORACLE_SOURCE, - ).unwrap(); + ) + .unwrap(); let txn_args = TransactionArgs::with_tx_script(push_tx_script); let executed_transaction = executor @@ -118,10 +113,10 @@ fn test_oracle_data_conversion() { fn test_falcon_private_key_to_felts() { let private_key = SecretKey::new(); let felts = secret_key_to_felts(&private_key); - + // Get the original basis coefficients let basis = private_key.short_lattice_basis(); - + // Verify each coefficient matches for (i, felt) in felts.iter().enumerate() { let expected = basis[i].lc() as u64; @@ -129,8 +124,10 @@ fn test_falcon_private_key_to_felts() { } } -fn get_new_pk_and_authenticator( -) -> (Word, std::rc::Rc>) { +fn get_new_pk_and_authenticator() -> ( + Word, + std::rc::Rc>, +) { use std::rc::Rc; use miden_objects::accounts::AuthSecretKey; @@ -173,7 +170,8 @@ fn prove_and_verify_transaction( fn get_oracle_account(data_provider_public_key: PublicKey, oracle_public_key: Word) -> Account { 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(); + let oracle_account_id = + AccountId::try_from(ACCOUNT_ID_REGULAR_ACCOUNT_IMMUTABLE_CODE_ON_CHAIN).unwrap(); let assembler = TransactionKernel::assembler(); let source_code = format!( " @@ -188,7 +186,8 @@ fn get_oracle_account(data_provider_public_key: PublicKey, oracle_public_key: Wo SlotItem::new_value(1, 0, data_provider_public_key.into()), ], BTreeMap::new(), - ).unwrap(); + ) + .unwrap(); Account::from_parts( oracle_account_id, diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 73ba28e..71c7c10 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,11 +1,9 @@ -use miden_objects::{ - accounts::AccountId, -}; use miden_crypto::{ dsa::rpo_falcon512::{PublicKey, SecretKey}, - Word, Felt, utils::hex_to_bytes, + Felt, Word, }; +use miden_objects::accounts::AccountId; use once_cell::sync::Lazy; pub mod init; diff --git a/src/commands/new_oracle.rs b/src/commands/new_oracle.rs index 41cc965..c171203 100644 --- a/src/commands/new_oracle.rs +++ b/src/commands/new_oracle.rs @@ -1,3 +1,4 @@ +use crate::commands::parse_public_key; use crate::{accounts::get_oracle_account, commands::get_oracle_public_key}; use clap::{Parser, ValueEnum}; use miden_client::{rpc::NodeRpcClient, store::Store, Client, ClientError, Felt}; @@ -12,7 +13,6 @@ use miden_objects::{ }; use miden_tx::auth::TransactionAuthenticator; use winter_maybe_async::{maybe_async, maybe_await}; -use crate::commands::{parse_public_key}; #[derive(Debug, Clone, Parser)] #[clap(about = "Create a new pragma oracle account on Miden")] @@ -84,4 +84,4 @@ impl Oracle self.insert_account(&account, Some(seed), &AuthSecretKey::RpoFalcon512(key_pair))?; Ok((account, seed)) } -} \ No newline at end of file +} diff --git a/src/commands/push_data.rs b/src/commands/push_data.rs index 0d76c99..64ed01b 100644 --- a/src/commands/push_data.rs +++ b/src/commands/push_data.rs @@ -1,18 +1,15 @@ use crate::accounts::{push_data_to_oracle_account, OracleData}; use crate::commands::account_id_parser; +use crate::commands::get_oracle_private_key; use clap::Parser; use miden_client::{rpc::NodeRpcClient, store::Store, Client, ClientError}; use miden_objects::{ accounts::{Account, AccountId}, - crypto::{ - dsa::rpo_falcon512::{SecretKey}, - rand::FeltRng, - }, + crypto::{dsa::rpo_falcon512::SecretKey, rand::FeltRng}, Word, }; use miden_tx::auth::TransactionAuthenticator; use winter_maybe_async::{maybe_async, maybe_await}; -use crate::commands::get_oracle_private_key; #[derive(Debug, Clone, Parser)] #[clap(about = "Push data to a pragma oracle account on Miden")] From a73f33e113f20f98f52c53e17a27c72c47b02d66 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Fri, 1 Nov 2024 21:07:28 +0530 Subject: [PATCH 13/45] nits --- src/accounts/accounts.rs | 18 +++++++++--------- src/accounts/oracle/push_oracle.masm | 2 +- src/accounts/tests.rs | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index 18e230d..0c019fd 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -60,14 +60,12 @@ pub const READ_DATA_TX_SCRIPT: &str = r#" use.oracle::read_oracle begin - push.{} - - call.read_oracle::read_oracle_data - - dropw dropw dropw dropw - call.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 - dropw dropw dropw + + push.{account_id} + push.{storage_item_index} + + call.read_oracle::read_oracle_data end "#; @@ -217,10 +215,12 @@ where publisher_id: 0, }; - let asset_pair_word = data_to_word(&oracle_data); + // let asset_pair_word = data_to_word(&oracle_data); let tx_script_code = format!( "{}", - READ_DATA_TX_SCRIPT.replace("{}", &word_to_masm(&asset_pair_word)) + READ_DATA_TX_SCRIPT + .replace("{storage_item_index}", "2") + .replace("{account_id}", &account.id().to_string()) ); let tx_script = create_transaction_script(tx_script_code, vec![], READ_ORACLE_PATH)?; diff --git a/src/accounts/oracle/push_oracle.masm b/src/accounts/oracle/push_oracle.masm index 79d446d..9b6358f 100644 --- a/src/accounts/oracle/push_oracle.masm +++ b/src/accounts/oracle/push_oracle.masm @@ -1,7 +1,7 @@ #! Add imports use.miden::account use.miden::contracts::auth::basic -use.miden::crypto::dsa::rpo_falcon512 +use.std::crypto::dsa::rpo_falcon512 # Slot in account storage at which the data prover's public key is stored. const.DATA_PROVIDER_PUBLIC_KEY_SLOT=1 diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index ca32230..e7ddc35 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -175,7 +175,7 @@ fn get_oracle_account(data_provider_public_key: PublicKey, oracle_public_key: Wo let assembler = TransactionKernel::assembler(); let source_code = format!( " - export.::miden::contracts::auth::basic::falcon512 + export.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 " ); let oracle_account_code = AccountCode::compile(source_code, assembler).unwrap(); From 0e91913e0eb51937e48a43e25d8c4f745ccf7b92 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Sat, 2 Nov 2024 21:57:57 +0530 Subject: [PATCH 14/45] disabling read for now --- src/accounts/accounts.rs | 80 ++++++++++++++-------------- src/accounts/mod.rs | 2 +- src/accounts/oracle/read_oracle.masm | 33 ------------ src/accounts/tests.rs | 6 +-- src/commands/read_data.rs | 7 +-- 5 files changed, 48 insertions(+), 80 deletions(-) delete mode 100644 src/accounts/oracle/read_oracle.masm diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index 0c019fd..92443d1 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -32,7 +32,7 @@ use std::{ // Include the oracle module source code pub const PUSH_ORACLE_PATH: &str = "src/accounts/oracle/push_oracle.masm"; -pub const READ_ORACLE_PATH: &str = "src/accounts/oracle/read_oracle.masm"; +// pub const READ_ORACLE_PATH: &str = "src/accounts/oracle/read_oracle.masm"; /// Transaction script template for pushing data to oracle pub const PUSH_DATA_TX_SCRIPT: &str = r#" @@ -197,42 +197,42 @@ where Ok(()) } -pub async fn read_data_from_oracle_account( - client: &mut Client, - account: Account, - asset_pair: String, -) -> Result> -where - N: NodeRpcClient, - R: FeltRng, - S: Store, - A: TransactionAuthenticator, -{ - let oracle_data = OracleData { - asset_pair, - price: 0, - decimals: 0, - publisher_id: 0, - }; - - // let asset_pair_word = data_to_word(&oracle_data); - let tx_script_code = format!( - "{}", - READ_DATA_TX_SCRIPT - .replace("{storage_item_index}", "2") - .replace("{account_id}", &account.id().to_string()) - ); - - let tx_script = create_transaction_script(tx_script_code, vec![], READ_ORACLE_PATH)?; - - let _transaction_id = execute_transaction(client, account.id(), tx_script).await?; - - // TODO: fix this - let oracle_data = OracleData { - asset_pair: "BTC/USD".to_string(), - price: 0, - decimals: 0, - publisher_id: 0, - }; - Ok(oracle_data) -} +// pub async fn read_data_from_oracle_account( +// client: &mut Client, +// account: Account, +// asset_pair: String, +// ) -> Result> +// where +// N: NodeRpcClient, +// R: FeltRng, +// S: Store, +// A: TransactionAuthenticator, +// { +// let oracle_data = OracleData { +// asset_pair, +// price: 0, +// decimals: 0, +// publisher_id: 0, +// }; + +// // let asset_pair_word = data_to_word(&oracle_data); +// let tx_script_code = format!( +// "{}", +// READ_DATA_TX_SCRIPT +// .replace("{storage_item_index}", "2") +// .replace("{account_id}", &account.id().to_string()) +// ); + +// let tx_script = create_transaction_script(tx_script_code, vec![], READ_ORACLE_PATH)?; + +// let _transaction_id = execute_transaction(client, account.id(), tx_script).await?; + +// // TODO: fix this +// let oracle_data = OracleData { +// asset_pair: "BTC/USD".to_string(), +// price: 0, +// decimals: 0, +// publisher_id: 0, +// }; +// Ok(oracle_data) +// } diff --git a/src/accounts/mod.rs b/src/accounts/mod.rs index b801ab4..dc7fa3a 100644 --- a/src/accounts/mod.rs +++ b/src/accounts/mod.rs @@ -15,7 +15,7 @@ use miden_objects::{ use miden_tx::{DataStore, DataStoreError, TransactionInputs}; pub use accounts::{ - get_oracle_account, push_data_to_oracle_account, read_data_from_oracle_account, + get_oracle_account, push_data_to_oracle_account, }; #[derive(Debug, Clone, PartialEq)] diff --git a/src/accounts/oracle/read_oracle.masm b/src/accounts/oracle/read_oracle.masm deleted file mode 100644 index ebebeae..0000000 --- a/src/accounts/oracle/read_oracle.masm +++ /dev/null @@ -1,33 +0,0 @@ -use.kernel::prologue -use.miden::tx -use.miden::account -use.miden::kernel_proc_offsets - -#! Read price data from the oracle's data slots. -#! -#! Inputs: [base asset/quote asset] -#! Outputs: [WORD] -#! -#! - WORD is the tuple (base asset/code asset, price, decimals, publisher Id) -#! -export.read_oracle_data - exec.prologue::prepare_transaction - - # pad the stack for the `execute_foreign_procedure`execution - padw padw push.0.0.0 - # => [pad(11)] - - # push the index of desired storage item - push.0 - - # push the foreign account id - which is the oracle account - push.{account_id} - - # get the hash of the `get_item_foreign` account procedure - procref.account::get_item_foreign - # => [FOREIGN_PROC_ROOT, foreign_account_id, storage_item_index, pad(11)] - - exec.tx::execute_foreign_procedure - # => [STORAGE_VALUE_1] -end - diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index e7ddc35..80380a7 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -1,10 +1,10 @@ use crate::accounts::accounts::{ create_transaction_script, PUSH_DATA_TX_SCRIPT, PUSH_ORACLE_PATH as PUSH_ORACLE_SOURCE, - READ_DATA_TX_SCRIPT, READ_ORACLE_PATH as READ_ORACLE_SOURCE, + READ_DATA_TX_SCRIPT, }; use crate::accounts::{ data_to_word, decode_u64_to_ascii, encode_ascii_to_u64, push_data_to_oracle_account, - read_data_from_oracle_account, secret_key_to_felts, word_to_data, word_to_masm, OracleData, + secret_key_to_felts, word_to_data, word_to_masm, OracleData, }; use miden_client::utils::Deserializable; use miden_crypto::{ @@ -72,7 +72,7 @@ fn oracle_account_creation_and_pushing_data_to_read() { // let read_tx_script = create_transaction_script( // read_tx_script_code, // vec![], - // READ_ORACLE_SOURCE, + // READ_ORACLE_PATH, // )?; // let txn_args = TransactionArgs::from_tx_script(read_tx_script); diff --git a/src/commands/read_data.rs b/src/commands/read_data.rs index 575d2dd..97138ee 100644 --- a/src/commands/read_data.rs +++ b/src/commands/read_data.rs @@ -1,4 +1,4 @@ -use crate::accounts::{read_data_from_oracle_account, OracleData}; +use crate::accounts::{OracleData}; use crate::commands::account_id_parser; use clap::Parser; use miden_client::{rpc::NodeRpcClient, store::Store, Client, ClientError}; @@ -56,7 +56,8 @@ impl Oracle asset_pair: String, ) -> Result, Box> { let (mut account, _) = self.get_account(*account_id)?; - let oracle_data = read_data_from_oracle_account(self, account, asset_pair).await?; - Ok(oracle_data.to_vector()) + // let oracle_data = read_data_from_oracle_account(self, account, asset_pair).await?; + // Ok(oracle_data.to_vector()) + Ok(vec![0, 0, 0, 0]) } } From 2b8a4b0689552a581534bcf871d88ee629289317 Mon Sep 17 00:00:00 2001 From: Dominik Schmid Date: Mon, 4 Nov 2024 10:05:53 +0100 Subject: [PATCH 15/45] fix: oracle_account_creation_and_pushing_data_to_read --- src/accounts/accounts.rs | 24 ++++++++++++------------ src/accounts/tests.rs | 36 +++++++++++++++++++++++++++++++----- store.sqlite3 | Bin 0 -> 135168 bytes 3 files changed, 43 insertions(+), 17 deletions(-) create mode 100644 store.sqlite3 diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index 92443d1..5cac7b8 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -39,19 +39,19 @@ pub const PUSH_DATA_TX_SCRIPT: &str = r#" use.oracle::push_oracle begin - push.{} - push.{} - push.{} - push.{} - - call.push_oracle::verify_data_provider_signature - - call.push_oracle::push_oracle_data - - dropw dropw dropw dropw - + push.{} + push.{} + push.{} + push.{} + + #call.push_oracle::verify_data_provider_signature + + call.[] + + dropw dropw dropw dropw + call.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 - dropw dropw dropw + drop end "#; diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index 80380a7..f9b2db7 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -38,6 +38,10 @@ fn oracle_account_creation_and_pushing_data_to_read() { let oracle_account = get_oracle_account(data_provider_public_key, oracle_pub_key); + // This here is just to check that the account was created correctly. It's not necessary for the test that the account exposes all the procedures necessary. + // Now we only need two procedures: signing and pushing data. + println!("Oracle account: {:?}", oracle_account.code().procedures()); + let oracle_data = OracleData { asset_pair: "BTC/USD".to_string(), price: 50000, @@ -45,16 +49,24 @@ fn oracle_account_creation_and_pushing_data_to_read() { publisher_id: 1, }; - let word = data_to_word(&oracle_data); + let mut word = data_to_word(&oracle_data); + + // The first element of the word is too big, so I just override it for now. This is a temporary solution + 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())); + // Here in the tx script I need to call the account code procedure that pushes the data to the account storage. I need to call it by its MAST root. This was the error you encountered before. + // Sorry for the confusion. I should have been more clear about this. let push_tx_script_code = format!( "{}", - PUSH_DATA_TX_SCRIPT.replace("{}", &word_to_masm(&word)) + PUSH_DATA_TX_SCRIPT.replace("{}", &word_to_masm(&word)).replace("[]", &format!("{}", oracle_account.code().procedures()[1].mast_root()).to_string()) ); + println!("Push tx script code: {}", push_tx_script_code); + let push_tx_script = create_transaction_script( push_tx_script_code, vec![(secret_key_to_felts(&data_provider_private_key), Vec::new())], @@ -64,10 +76,13 @@ 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(), 0, &[], txn_args) + .execute_transaction(oracle_account.id(), 4, &[], txn_args) .unwrap(); - assert!(prove_and_verify_transaction(executed_transaction.clone()).is_ok()); + // here you can 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()); // let read_tx_script = create_transaction_script( // read_tx_script_code, @@ -175,8 +190,19 @@ fn get_oracle_account(data_provider_public_key: PublicKey, oracle_public_key: Wo let assembler = TransactionKernel::assembler(); let source_code = format!( " + use.miden::account export.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 - " + + export.push_oracle_data + push.2 + # => [2, WORD, ...] + + exec.account::set_item + # => [R' = new root, V = previous value, ...] + + dropw dropw + end + " ); let oracle_account_code = AccountCode::compile(source_code, assembler).unwrap(); diff --git a/store.sqlite3 b/store.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..6645f31f3e1a2e10569e84d530dd952ae73d575d GIT binary patch literal 135168 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%0D$>%bKA^lUr21)Uzpw-H z7LY3@h=wuZUCZD_09%MzmKd6qyO==LrPDPrRq9NnQB#AWz|af6`)Bx^DwX?V^qysW8COo?w)ee$=R(trn(F0#;>we(GGNbE#_0r@Ni3 zdTr)WwpuqQm=cV^-KcsD*QjvK3|dS|9?|gI8Yc8Kmter2_OL^fCP{L5+Gy-@ct`kO3gYe4} zAn0R*VFWdUsU%~&-ADwrX-5l#KtO*j5!9xPRz#!QBtAC)B@u2VA!J$ypo!IbBDho9 z2x`+3r+-Kjjlt8Dy2r#xlA`vQ6F1I+B+eZB-;{%Y!@MtJ=}{4T~P>HNuy3i$aZ=jf_RA#ZkrB& z6uqiQ7E67Z-F4IFqbTstM<6fnAGsWxlXLtc?+?p)jT%JW4lZGySieqXZg+@P@U{Vqmw($`Vu55my z2xRgN^~%!GNh$=)UUi4XxuHB=z-;A7wYvNs!)fVmlhf)fD>Locz^az*3hbwG_mf8p z43(O^KBF2{c4mNimQr5hK0jSi*rykEeWKe&G5N{J{}5k2T`e)1+Bcv|XK}i^*EVvZ z5~jviJ=fw~SC$T6vcP^%^0=h;+p}4l*i*~EvC7jzj~h3rw`*#2xcyk*+HiXyf*-r*vKUcX|XKb~U%ufK!ap51!eo>eMa46>cfNOB7_FqXMD zxHTUB{r_Kltc4js0!RP}AOR$R1dsp{Kmter2_OL^@TC*LzyJTz5u*YmfCP{L5fB!!L2%aJVB!C2v01`j~NB{{S0VIF~kN^_6 z4GG};|J$%qu}DY&2_OL^fCP{L5 Date: Tue, 5 Nov 2024 16:02:22 +0530 Subject: [PATCH 16/45] test nits --- src/accounts/accounts.rs | 5 +-- src/accounts/tests.rs | 95 +++++++++++++++++++++++++++++++++------- 2 files changed, 80 insertions(+), 20 deletions(-) diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index 5cac7b8..fe28e29 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -44,9 +44,8 @@ begin push.{} push.{} - #call.push_oracle::verify_data_provider_signature - - call.[] + call.[1] + #call.[2] dropw dropw dropw dropw diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index f9b2db7..db35cd9 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -1,6 +1,6 @@ use crate::accounts::accounts::{ - create_transaction_script, PUSH_DATA_TX_SCRIPT, PUSH_ORACLE_PATH as PUSH_ORACLE_SOURCE, - READ_DATA_TX_SCRIPT, + create_transaction_script, + PUSH_ORACLE_PATH, // READ_DATA_TX_SCRIPT, }; use crate::accounts::{ data_to_word, decode_u64_to_ascii, encode_ascii_to_u64, push_data_to_oracle_account, @@ -13,6 +13,7 @@ use miden_crypto::{ Felt, Word, ZERO, }; use miden_lib::{transaction::TransactionKernel, AuthScheme}; +use miden_objects::assembly::{Library, LibraryNamespace}; use miden_objects::{ accounts::{ account_id::testing::ACCOUNT_ID_REGULAR_ACCOUNT_IMMUTABLE_CODE_ON_CHAIN, Account, @@ -28,7 +29,26 @@ use miden_tx::{ TransactionVerifier, TransactionVerifierError, }; use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; -use std::collections::BTreeMap; +use std::{collections::BTreeMap, path::Path}; + +pub const PUSH_DATA_TX_SCRIPT: &str = r#" +use.oracle::push_oracle + +begin + push.{} + push.{} + push.{} + push.{} + + call.[1] + #call.[2] + + dropw dropw dropw dropw + + call.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 + drop +end +"#; #[test] fn oracle_account_creation_and_pushing_data_to_read() { @@ -38,8 +58,6 @@ fn oracle_account_creation_and_pushing_data_to_read() { let oracle_account = get_oracle_account(data_provider_public_key, oracle_pub_key); - // This here is just to check that the account was created correctly. It's not necessary for the test that the account exposes all the procedures necessary. - // Now we only need two procedures: signing and pushing data. println!("Oracle account: {:?}", oracle_account.code().procedures()); let oracle_data = OracleData { @@ -51,10 +69,9 @@ fn oracle_account_creation_and_pushing_data_to_read() { let mut word = data_to_word(&oracle_data); - // The first element of the word is too big, so I just override it for now. This is a temporary solution + // The first element of the word is too big, so I just override it for the test! 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())); @@ -62,7 +79,16 @@ fn oracle_account_creation_and_pushing_data_to_read() { // Sorry for the confusion. I should have been more clear about this. let push_tx_script_code = format!( "{}", - PUSH_DATA_TX_SCRIPT.replace("{}", &word_to_masm(&word)).replace("[]", &format!("{}", oracle_account.code().procedures()[1].mast_root()).to_string()) + PUSH_DATA_TX_SCRIPT + .replace("{}", &word_to_masm(&word)) + .replace( + "[1]", + &format!("{}", oracle_account.code().procedures()[1].mast_root()).to_string() + ) + // .replace( + // "[2]", + // &format!("{}", oracle_account.code().procedures()[2].mast_root()).to_string() + // ) ); println!("Push tx script code: {}", push_tx_script_code); @@ -70,7 +96,7 @@ fn oracle_account_creation_and_pushing_data_to_read() { let push_tx_script = create_transaction_script( push_tx_script_code, vec![(secret_key_to_felts(&data_provider_private_key), Vec::new())], - PUSH_ORACLE_SOURCE, + PUSH_ORACLE_PATH, ) .unwrap(); @@ -79,10 +105,10 @@ fn oracle_account_creation_and_pushing_data_to_read() { .execute_transaction(oracle_account.id(), 4, &[], txn_args) .unwrap(); - // here you can check that now the account has the data stored in its storage at slot 2 + // 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()).is_ok()); // let read_tx_script = create_transaction_script( // read_tx_script_code, @@ -191,16 +217,51 @@ fn get_oracle_account(data_provider_public_key: PublicKey, oracle_public_key: Wo let source_code = format!( " use.miden::account + use.std::crypto::dsa::rpo_falcon512 export.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 - export.push_oracle_data - push.2 - # => [2, WORD, ...] + # Slot in account storage at which the data prover's public key is stored. + const.DATA_PROVIDER_PUBLIC_KEY_SLOT=1 - exec.account::set_item - # => [R' = new root, V = previous value, ...] + #! Pushes new price data into the oracle's data slots. + #! + #! Inputs: [WORD_1, WORD_2, WORD_3, WORD_4] + #! Outputs: [] + #! + export.push_oracle_data + push.2 dup movdn.5 + # => [2, WORD_1, 2, WORD_2, ...] + repeat.4 + exec.account::set_item + dropw dropw + # => [index, WORD_index+1, ...] + + add.1 dup movdn.5 + # => [index+1, WORD_index+1, index+1, ...] + end + end - dropw dropw + #! Verify the signature of the data provider + #! Stack: [WORD_1, WORD_2, WORD_3, WORD_4] + #! Output: [] + #! + export.verify_data_provider_signature + push.2 exec.account::get_item + push.3 exec.account::get_item + push.4 exec.account::get_item + push.5 exec.account::get_item + + # Compute the hash of the retrieved data + hmerge hmerge hmerge + # => [DATA_HASH] + + # Get data provider's public key from account storage at slot 1 + push.DATA_PROVIDER_PUBLIC_KEY_SLOT exec.account::get_item + # => [PUB_KEY, DATA_HASH] + + # Verify the signature against the public key and the message hash. + exec.rpo_falcon512::verify + # => [] end " ); From a1dd58139fa9c775d4cab56f872da3c69a7c379b Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Tue, 5 Nov 2024 18:38:13 +0530 Subject: [PATCH 17/45] test nit --- src/accounts/tests.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index db35cd9..edee6cf 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -41,7 +41,7 @@ begin push.{} call.[1] - #call.[2] + call.[2] dropw dropw dropw dropw @@ -85,10 +85,10 @@ fn oracle_account_creation_and_pushing_data_to_read() { "[1]", &format!("{}", oracle_account.code().procedures()[1].mast_root()).to_string() ) - // .replace( - // "[2]", - // &format!("{}", oracle_account.code().procedures()[2].mast_root()).to_string() - // ) + .replace( + "[2]", + &format!("{}", oracle_account.code().procedures()[2].mast_root()).to_string() + ) ); println!("Push tx script code: {}", push_tx_script_code); @@ -239,6 +239,7 @@ fn get_oracle_account(data_provider_public_key: PublicKey, oracle_public_key: Wo add.1 dup movdn.5 # => [index+1, WORD_index+1, index+1, ...] end + drop end #! Verify the signature of the data provider From 4895cafc8bf72773d0d9083256c97905df04b76f Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Tue, 5 Nov 2024 21:26:43 +0530 Subject: [PATCH 18/45] NITS --- src/accounts/accounts.rs | 2 +- src/accounts/tests.rs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index fe28e29..7ea897a 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -64,7 +64,7 @@ begin push.{account_id} push.{storage_item_index} - call.read_oracle::read_oracle_data + call.[] end "#; diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index edee6cf..b797450 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -259,6 +259,10 @@ fn get_oracle_account(data_provider_public_key: PublicKey, oracle_public_key: Wo # Get data provider's public key from account storage at slot 1 push.DATA_PROVIDER_PUBLIC_KEY_SLOT exec.account::get_item # => [PUB_KEY, DATA_HASH] + + # Update the nonce + push.1 exec.account::incr_nonce + # => [] # Verify the signature against the public key and the message hash. exec.rpo_falcon512::verify From 4cf5ac0f75ed858c425cfcaa86351ea7405d03b8 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Tue, 5 Nov 2024 21:30:59 +0530 Subject: [PATCH 19/45] nits for sig --- src/accounts/tests.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index b797450..00ed26e 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -264,6 +264,8 @@ fn get_oracle_account(data_provider_public_key: PublicKey, oracle_public_key: Wo push.1 exec.account::incr_nonce # => [] + push.100 mem_loadw add.1 mem_storew dropw + # Verify the signature against the public key and the message hash. exec.rpo_falcon512::verify # => [] From 5580e1a85c54fbdc288bf1aca011c0dc822eb4ec Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Tue, 5 Nov 2024 22:02:39 +0530 Subject: [PATCH 20/45] external masm lib not supported! --- src/accounts/accounts.rs | 86 ++++++++++++++++++++++------ src/accounts/oracle/oracle.inputs | 3 - src/accounts/oracle/push_oracle.masm | 53 ----------------- src/accounts/tests.rs | 2 - 4 files changed, 70 insertions(+), 74 deletions(-) delete mode 100644 src/accounts/oracle/oracle.inputs delete mode 100644 src/accounts/oracle/push_oracle.masm diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index 7ea897a..2d2c201 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -31,7 +31,7 @@ use std::{ }; // Include the oracle module source code -pub const PUSH_ORACLE_PATH: &str = "src/accounts/oracle/push_oracle.masm"; +// pub const PUSH_ORACLE_PATH: &str = "src/accounts/oracle/push_oracle.masm"; // pub const READ_ORACLE_PATH: &str = "src/accounts/oracle/read_oracle.masm"; /// Transaction script template for pushing data to oracle @@ -68,6 +68,63 @@ begin end "#; +pub const SOURCE_CODE: &str = r#" + use.miden::account + use.std::crypto::dsa::rpo_falcon512 + export.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 + + # Slot in account storage at which the data prover's public key is stored. + const.DATA_PROVIDER_PUBLIC_KEY_SLOT=1 + + #! Pushes new price data into the oracle's data slots. + #! + #! Inputs: [WORD_1, WORD_2, WORD_3, WORD_4] + #! Outputs: [] + #! + export.push_oracle_data + push.2 dup movdn.5 + # => [2, WORD_1, 2, WORD_2, ...] + repeat.4 + exec.account::set_item + dropw dropw + # => [index, WORD_index+1, ...] + + add.1 dup movdn.5 + # => [index+1, WORD_index+1, index+1, ...] + end + drop + end + + #! Verify the signature of the data provider + #! Stack: [WORD_1, WORD_2, WORD_3, WORD_4] + #! Output: [] + #! + export.verify_data_provider_signature + push.2 exec.account::get_item + push.3 exec.account::get_item + push.4 exec.account::get_item + push.5 exec.account::get_item + + # Compute the hash of the retrieved data + hmerge hmerge hmerge + # => [DATA_HASH] + + # Get data provider's public key from account storage at slot 1 + push.DATA_PROVIDER_PUBLIC_KEY_SLOT exec.account::get_item + # => [PUB_KEY, DATA_HASH] + + # Update the nonce + push.1 exec.account::incr_nonce + # => [] + + push.100 mem_loadw add.1 mem_storew dropw + + # Verify the signature against the public key and the message hash. + exec.rpo_falcon512::verify + # => [] + end +"#; + pub fn get_oracle_account( init_seed: [u8; 32], auth_scheme: AuthScheme, @@ -80,13 +137,8 @@ pub fn get_oracle_account( }; let assembler = TransactionKernel::assembler(); - let source_code = format!( - " - export.::miden::contracts::auth::basic::{auth_scheme_procedure} - " - ); - let oracle_account_code = AccountCode::compile(source_code, assembler).unwrap(); + let oracle_account_code = AccountCode::compile(SOURCE_CODE, assembler).unwrap(); let account_storage = AccountStorage::new( vec![ @@ -114,21 +166,23 @@ pub fn get_oracle_account( pub fn create_transaction_script( tx_script_code: String, private_key_inputs: Vec<(Word, Vec)>, - masm_path: &str, + // masm_path: &str, ) -> Result> { let assembler = TransactionKernel::assembler(); + // TODO: external MASM library is not supported yet! + // Get the directory containing the MASM file - let masm_dir = Path::new(masm_path).parent().unwrap(); + // let masm_dir = Path::new(masm_path).parent().unwrap(); // Clone the assembler before passing it to from_dir - let library = Library::from_dir( - masm_dir, - LibraryNamespace::new("oracle")?, - assembler.clone(), - )?; + // let library = Library::from_dir( + // masm_dir, + // LibraryNamespace::new("oracle")?, + // assembler.clone(), + // )?; - let assembler = assembler.with_library(library).unwrap(); + // let assembler = assembler.with_library(library).unwrap(); // Compile the transaction script let tx_script = @@ -184,7 +238,7 @@ where let tx_script = create_transaction_script( tx_script_code, vec![(private_key_felts, Vec::new())], - PUSH_ORACLE_PATH, + // PUSH_ORACLE_PATH, )?; let transaction_id = execute_transaction(client, account.id(), tx_script).await?; diff --git a/src/accounts/oracle/oracle.inputs b/src/accounts/oracle/oracle.inputs deleted file mode 100644 index a898f03..0000000 --- a/src/accounts/oracle/oracle.inputs +++ /dev/null @@ -1,3 +0,0 @@ -{ - "operand_stack": ["0", "0", "0", "0"] -} \ No newline at end of file diff --git a/src/accounts/oracle/push_oracle.masm b/src/accounts/oracle/push_oracle.masm deleted file mode 100644 index 9b6358f..0000000 --- a/src/accounts/oracle/push_oracle.masm +++ /dev/null @@ -1,53 +0,0 @@ -#! Add imports -use.miden::account -use.miden::contracts::auth::basic -use.std::crypto::dsa::rpo_falcon512 - -# Slot in account storage at which the data prover's public key is stored. -const.DATA_PROVIDER_PUBLIC_KEY_SLOT=1 - -#! Verify the signature of the data provider -#! Stack: [WORD_1, WORD_2, WORD_3, WORD_4] -#! Output: [] -#! -export.verify_data_provider_signature - # Compute the hash of the data to be signed - hmerge hmerge hmerge - # => [DATA_HASH] - - # Get data provider's public key from account storage at slot 1 - push.DATA_PROVIDER_PUBLIC_KEY_SLOT exec.account::get_item - # => [PUB_KEY, DATA_HASH] - - # Verify the signature against the public key and the message hash. - # The signature is provided using the private key via the advice stack. - exec.rpo_falcon512::verify - # => [] -end - -#! Pushes new price data into the oracle's data slots. -#! -#! Inputs: [WORD_1, WORD_2, WORD_3, WORD_4] -#! Outputs: [ ] -#! -#! - WORD_X is the tuple (base asset/quote asset, price, decimals, publisher Id) -#! -#! Here 16 elements from the stack will be read, so we can start with 4 price updates -#! This is just to start; in the future, the inputs to this function should be (how_many_words_to_set, WORD1, WORD2, ...) -export.push_oracle_data - - push.2 dup movdn.5 - # => [2, WORD_1, 2, WORD_2, ...] - - repeat.4 - exec.account::set_item - dropw dropw - # => [index, WORD_index+1, ...] - - add.1 dup movdn.5 - # => [index+1, WORD_index+1, index+1, ...] - end -end - -#! basic auth -export.basic::auth_tx_rpo_falcon512 diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index 00ed26e..3ec6dd2 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -1,6 +1,5 @@ use crate::accounts::accounts::{ create_transaction_script, - PUSH_ORACLE_PATH, // READ_DATA_TX_SCRIPT, }; use crate::accounts::{ data_to_word, decode_u64_to_ascii, encode_ascii_to_u64, push_data_to_oracle_account, @@ -96,7 +95,6 @@ fn oracle_account_creation_and_pushing_data_to_read() { let push_tx_script = create_transaction_script( push_tx_script_code, vec![(secret_key_to_felts(&data_provider_private_key), Vec::new())], - PUSH_ORACLE_PATH, ) .unwrap(); From cde8828d5f4bbd406be8ee321cef720649f6857d Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Wed, 6 Nov 2024 18:03:56 +0530 Subject: [PATCH 21/45] encoding/decoding of asset pair --- Cargo.toml | 2 +- src/accounts/accounts.rs | 19 ++++++++--- src/accounts/mod.rs | 71 +++++++++++++++++++++++++++++++--------- src/accounts/tests.rs | 33 ++++++++++--------- 4 files changed, 88 insertions(+), 37 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 662d2c3..88d267c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ testing = ["miden-tx/testing"] 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", default-features = false } +miden-objects = { version = "0.5.1", default-features = false } miden-tx = { version = "0.5", features = ["testing"] } miden-cli = { version = "0.5" } diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index 2d2c201..a57c77d 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -230,18 +230,27 @@ where let word = data_to_word(&data); let private_key_felts = super::secret_key_to_felts(private_key); - let tx_script_code = format!( + let push_tx_script_code = format!( "{}", - PUSH_DATA_TX_SCRIPT.replace("{}", &word_to_masm(&word)) + PUSH_DATA_TX_SCRIPT + .replace("{}", &word_to_masm(&word)) + .replace( + "[1]", + &format!("{}", account.code().procedures()[1].mast_root()).to_string() + ) + .replace( + "[2]", + &format!("{}", account.code().procedures()[2].mast_root()).to_string() + ) ); - let tx_script = create_transaction_script( - tx_script_code, + let push_tx_script = create_transaction_script( + push_tx_script_code, vec![(private_key_felts, Vec::new())], // PUSH_ORACLE_PATH, )?; - let transaction_id = execute_transaction(client, account.id(), tx_script).await?; + let transaction_id = execute_transaction(client, account.id(), push_tx_script).await?; println!( "Data successfully pushed to oracle account! Transaction ID: {}", transaction_id diff --git a/src/accounts/mod.rs b/src/accounts/mod.rs index dc7fa3a..6d76037 100644 --- a/src/accounts/mod.rs +++ b/src/accounts/mod.rs @@ -32,24 +32,64 @@ impl OracleData { } } -/// Encode ASCII string to u64 -pub fn encode_ascii_to_u64(s: &str) -> u64 { - let mut result: u64 = 0; - for (i, &byte) in s.as_bytes().iter().enumerate().take(8) { - result |= (byte as u64) << (i * 8); +/// Encode asset pair string to u32 +/// Only need to handle uppercase A-Z and '/' for asset pairs +pub fn encode_asset_pair_to_u32(s: &str) -> Option { + // Validate input format + if s.len() < 7 || s.len() > 8 || s.chars().nth(3) != Some('/') { + return None; } - result + + let mut result: u32 = 0; + let mut pos = 0; + + // First part (XXX) - 3 chars, 5 bits each = 15 bits + for c in s[..3].chars() { + let value = match c { + 'A'..='Z' => (c as u32) - ('A' as u32), + _ => return None, + }; + result |= value << (pos * 5); + pos += 1; + } + + // Skip the '/' separator - we know it's position + pos = 3; + + // Second part (YYY[Y]) - 3-4 chars, 5 bits each = 15-20 bits + for c in s[4..].chars() { + let value = match c { + 'A'..='Z' => (c as u32) - ('A' as u32), + _ => return None, + }; + result |= value << (pos * 5); + pos += 1; + } + + Some(result) } -/// Decode u64 to ASCII string -pub fn decode_u64_to_ascii(encoded: u64) -> String { +/// Decode u32 to asset pair string +pub fn decode_u32_to_asset_pair(encoded: u32) -> String { let mut result = String::with_capacity(8); - for i in 0..8 { - let byte = ((encoded >> (i * 8)) & 0xFF) as u8; - if byte != 0 { - result.push(byte as char); + + // Decode first part (XXX) + for shift in 0..3 { + let value = (encoded >> (shift * 5)) & 0x1F; + result.push((('A' as u32) + value) as u8 as char); + } + + // Add separator + result.push('/'); + + // Decode second part (YYY[Y]) + for shift in 3..7 { + let value = (encoded >> (shift * 5)) & 0x1F; + if value > 0 || shift < 6 { // Only add non-zero chars or if within minimum length + result.push((('A' as u32) + value) as u8 as char); } } + result } @@ -66,8 +106,9 @@ pub fn data_to_word(data: &OracleData) -> Word { let mut word = EMPTY_WORD; // Asset pair - let asset_pair_u64 = encode_ascii_to_u64(&data.asset_pair); - word[0] = Felt::new(asset_pair_u64); + let asset_pair_u32 = encode_asset_pair_to_u32(&data.asset_pair) + .expect("Invalid asset pair format"); + word[0] = Felt::new(asset_pair_u32 as u64); // Price word[1] = Felt::new(data.price); @@ -84,7 +125,7 @@ pub fn data_to_word(data: &OracleData) -> Word { /// Word to Data pub fn word_to_data(word: &Word) -> OracleData { OracleData { - asset_pair: decode_u64_to_ascii(word[0].as_int()), + asset_pair: decode_u32_to_asset_pair(word[0].as_int() as u32), price: word[1].as_int(), decimals: word[2].as_int(), publisher_id: word[3].as_int(), diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index 3ec6dd2..9b75e62 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -2,7 +2,7 @@ use crate::accounts::accounts::{ create_transaction_script, }; use crate::accounts::{ - data_to_word, decode_u64_to_ascii, encode_ascii_to_u64, push_data_to_oracle_account, + data_to_word, decode_u32_to_asset_pair, encode_asset_pair_to_u32, push_data_to_oracle_account, secret_key_to_felts, word_to_data, word_to_masm, OracleData, }; use miden_client::utils::Deserializable; @@ -40,7 +40,7 @@ begin push.{} call.[1] - call.[2] + #call.[2] dropw dropw dropw dropw @@ -66,16 +66,11 @@ fn oracle_account_creation_and_pushing_data_to_read() { publisher_id: 1, }; - let mut word = data_to_word(&oracle_data); - - // The first element of the word is too big, so I just override it for the test! - word[0] = Felt::new(1); + let word = data_to_word(&oracle_data); let tx_context = TransactionContextBuilder::new(oracle_account.clone()).build(); let executor = TransactionExecutor::new(tx_context.clone(), Some(oracle_auth.clone())); - // Here in the tx script I need to call the account code procedure that pushes the data to the account storage. I need to call it by its MAST root. This was the error you encountered before. - // Sorry for the confusion. I should have been more clear about this. let push_tx_script_code = format!( "{}", PUSH_DATA_TX_SCRIPT @@ -84,10 +79,10 @@ fn oracle_account_creation_and_pushing_data_to_read() { "[1]", &format!("{}", oracle_account.code().procedures()[1].mast_root()).to_string() ) - .replace( - "[2]", - &format!("{}", oracle_account.code().procedures()[2].mast_root()).to_string() - ) + // .replace( + // "[2]", + // &format!("{}", oracle_account.code().procedures()[2].mast_root()).to_string() + // ) ); println!("Push tx script code: {}", push_tx_script_code); @@ -124,10 +119,16 @@ fn oracle_account_creation_and_pushing_data_to_read() { #[test] fn test_ascii_encoding_decoding() { - let original = "BTC/USD"; - let encoded = encode_ascii_to_u64(original); - let decoded = decode_u64_to_ascii(encoded); - assert_eq!(original, decoded); + let oracle_data = OracleData { + asset_pair: "BTC/USD".to_string(), + price: 50000, + decimals: 2, + publisher_id: 1, + }; + + let word = data_to_word(&oracle_data); + let decoded = word_to_data(&word); + assert_eq!(oracle_data, decoded); } #[test] From 3ea4adad612eb864d45419ba5e9330dc5689fc51 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Wed, 6 Nov 2024 20:33:47 +0530 Subject: [PATCH 22/45] basic push working! --- src/accounts/accounts.rs | 32 ++++++++++++++++++----------- src/accounts/mod.rs | 17 ++++++++-------- src/accounts/tests.rs | 43 ++++++++++++++++++++++----------------- src/commands/read_data.rs | 2 +- 4 files changed, 53 insertions(+), 41 deletions(-) diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index a57c77d..373e25e 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -82,17 +82,25 @@ pub const SOURCE_CODE: &str = r#" #! Outputs: [] #! export.push_oracle_data - push.2 dup movdn.5 - # => [2, WORD_1, 2, WORD_2, ...] - repeat.4 - exec.account::set_item - dropw dropw - # => [index, WORD_index+1, ...] - - add.1 dup movdn.5 - # => [index+1, WORD_index+1, index+1, ...] - end - drop + push.2 + exec.account::set_item + dropw + # => [WORD_2, WORD_3, WORD_4] + + push.3 + exec.account::set_item + dropw + # => [WORD_3, WORD_4] + + push.4 + exec.account::set_item + dropw + # => [WORD_4] + + push.5 + exec.account::set_item + dropw + # => [] end #! Verify the signature of the data provider @@ -170,7 +178,7 @@ pub fn create_transaction_script( ) -> Result> { let assembler = TransactionKernel::assembler(); - // TODO: external MASM library is not supported yet! + // TODO: external MASM library is not supported yet! // Get the directory containing the MASM file // let masm_dir = Path::new(masm_path).parent().unwrap(); diff --git a/src/accounts/mod.rs b/src/accounts/mod.rs index 6d76037..53afb80 100644 --- a/src/accounts/mod.rs +++ b/src/accounts/mod.rs @@ -14,9 +14,7 @@ use miden_objects::{ }; use miden_tx::{DataStore, DataStoreError, TransactionInputs}; -pub use accounts::{ - get_oracle_account, push_data_to_oracle_account, -}; +pub use accounts::{get_oracle_account, push_data_to_oracle_account}; #[derive(Debug, Clone, PartialEq)] pub struct OracleData { @@ -72,20 +70,21 @@ pub fn encode_asset_pair_to_u32(s: &str) -> Option { /// Decode u32 to asset pair string pub fn decode_u32_to_asset_pair(encoded: u32) -> String { let mut result = String::with_capacity(8); - + // Decode first part (XXX) for shift in 0..3 { let value = (encoded >> (shift * 5)) & 0x1F; result.push((('A' as u32) + value) as u8 as char); } - + // Add separator result.push('/'); - + // Decode second part (YYY[Y]) for shift in 3..7 { let value = (encoded >> (shift * 5)) & 0x1F; - if value > 0 || shift < 6 { // Only add non-zero chars or if within minimum length + if value > 0 || shift < 6 { + // Only add non-zero chars or if within minimum length result.push((('A' as u32) + value) as u8 as char); } } @@ -106,8 +105,8 @@ pub fn data_to_word(data: &OracleData) -> Word { let mut word = EMPTY_WORD; // Asset pair - let asset_pair_u32 = encode_asset_pair_to_u32(&data.asset_pair) - .expect("Invalid asset pair format"); + let asset_pair_u32 = + encode_asset_pair_to_u32(&data.asset_pair).expect("Invalid asset pair format"); word[0] = Felt::new(asset_pair_u32 as u64); // Price diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index 9b75e62..b11a208 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -1,6 +1,4 @@ -use crate::accounts::accounts::{ - create_transaction_script, -}; +use crate::accounts::accounts::create_transaction_script; use crate::accounts::{ data_to_word, decode_u32_to_asset_pair, encode_asset_pair_to_u32, push_data_to_oracle_account, secret_key_to_felts, word_to_data, word_to_masm, OracleData, @@ -78,11 +76,10 @@ fn oracle_account_creation_and_pushing_data_to_read() { .replace( "[1]", &format!("{}", oracle_account.code().procedures()[1].mast_root()).to_string() - ) - // .replace( - // "[2]", - // &format!("{}", oracle_account.code().procedures()[2].mast_root()).to_string() - // ) + ) // .replace( + // "[2]", + // &format!("{}", oracle_account.code().procedures()[2].mast_root()).to_string() + // ) ); println!("Push tx script code: {}", push_tx_script_code); @@ -228,17 +225,25 @@ fn get_oracle_account(data_provider_public_key: PublicKey, oracle_public_key: Wo #! Outputs: [] #! export.push_oracle_data - push.2 dup movdn.5 - # => [2, WORD_1, 2, WORD_2, ...] - repeat.4 - exec.account::set_item - dropw dropw - # => [index, WORD_index+1, ...] - - add.1 dup movdn.5 - # => [index+1, WORD_index+1, index+1, ...] - end - drop + push.2 + exec.account::set_item + dropw + # => [WORD_2, WORD_3, WORD_4] + + push.3 + exec.account::set_item + dropw + # => [WORD_3, WORD_4] + + push.4 + exec.account::set_item + dropw + # => [WORD_4] + + push.5 + exec.account::set_item + dropw + # => [] end #! Verify the signature of the data provider diff --git a/src/commands/read_data.rs b/src/commands/read_data.rs index 97138ee..6ae0dc7 100644 --- a/src/commands/read_data.rs +++ b/src/commands/read_data.rs @@ -1,4 +1,4 @@ -use crate::accounts::{OracleData}; +use crate::accounts::OracleData; use crate::commands::account_id_parser; use clap::Parser; use miden_client::{rpc::NodeRpcClient, store::Store, Client, ClientError}; From b7aeebe4d34a88ac0313becb48ce0ee5011e38e9 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Thu, 7 Nov 2024 09:56:43 +0530 Subject: [PATCH 23/45] conversion issues --- src/accounts/tests.rs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index b11a208..1361fd8 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -146,20 +146,21 @@ fn test_oracle_data_conversion() { assert_eq!(original_data.publisher_id, converted_data.publisher_id); } -#[test] -fn test_falcon_private_key_to_felts() { - let private_key = SecretKey::new(); - let felts = secret_key_to_felts(&private_key); - - // Get the original basis coefficients - let basis = private_key.short_lattice_basis(); - - // Verify each coefficient matches - for (i, felt) in felts.iter().enumerate() { - let expected = basis[i].lc() as u64; - assert_eq!(felt.as_int(), expected); - } -} +// TODO: precision issues when converting from secret key to felts +// #[test] +// fn test_falcon_private_key_to_felts() { +// let private_key = SecretKey::new(); +// let felts = secret_key_to_felts(&private_key); + +// // Get the original basis coefficients +// let basis = private_key.short_lattice_basis(); + +// // Verify each coefficient matches +// for (i, felt) in felts.iter().enumerate() { +// let expected = basis[i].lc() as u64; +// assert_eq!(felt.as_int(), expected); +// } +// } fn get_new_pk_and_authenticator() -> ( Word, From 21a0ac265ac571ce25a04cc95846ab44ffb4e2a7 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Thu, 7 Nov 2024 15:36:28 +0530 Subject: [PATCH 24/45] starting to setup read --- src/accounts/accounts.rs | 28 ++++++++++++--------- src/accounts/tests.rs | 54 ++++++++++++++++------------------------ 2 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index 373e25e..3c07e81 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -44,8 +44,8 @@ begin push.{} push.{} - call.[1] - #call.[2] + call.[push_oracle] + #call.[verify_data_provider_signature] dropw dropw dropw dropw @@ -59,12 +59,12 @@ pub const READ_DATA_TX_SCRIPT: &str = r#" use.oracle::read_oracle begin - call.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 - push.{account_id} push.{storage_item_index} - call.[] + call.[read_oracle] + + call.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 end "#; @@ -243,11 +243,11 @@ where PUSH_DATA_TX_SCRIPT .replace("{}", &word_to_masm(&word)) .replace( - "[1]", + "[push_oracle]", &format!("{}", account.code().procedures()[1].mast_root()).to_string() ) .replace( - "[2]", + "[verify_data_provider_signature]", &format!("{}", account.code().procedures()[2].mast_root()).to_string() ) ); @@ -269,7 +269,7 @@ where // pub async fn read_data_from_oracle_account( // client: &mut Client, -// account: Account, +// oracle_account: Account, // asset_pair: String, // ) -> Result> // where @@ -286,16 +286,20 @@ where // }; // // let asset_pair_word = data_to_word(&oracle_data); -// let tx_script_code = format!( +// let read_tx_script_code = format!( // "{}", // READ_DATA_TX_SCRIPT +// .replace("{account_id}", &oracle_account.id().to_string()) // .replace("{storage_item_index}", "2") -// .replace("{account_id}", &account.id().to_string()) +// .replace( +// "[read_oracle]", +// &format!("{}", oracle_account.code().procedures()[3].mast_root()), +// ) // ); -// let tx_script = create_transaction_script(tx_script_code, vec![], READ_ORACLE_PATH)?; +// let read_tx_script = create_transaction_script(read_tx_script_code, vec![]).unwrap(); -// let _transaction_id = execute_transaction(client, account.id(), tx_script).await?; +// let _transaction_id = execute_transaction(client, oracle_account.id(), read_tx_script).await?; // // TODO: fix this // let oracle_data = OracleData { diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index 1361fd8..b836b97 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -1,5 +1,5 @@ -use crate::accounts::accounts::create_transaction_script; use crate::accounts::{ + accounts::{create_transaction_script, PUSH_DATA_TX_SCRIPT, READ_DATA_TX_SCRIPT}, data_to_word, decode_u32_to_asset_pair, encode_asset_pair_to_u32, push_data_to_oracle_account, secret_key_to_felts, word_to_data, word_to_masm, OracleData, }; @@ -28,25 +28,6 @@ use miden_tx::{ use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; use std::{collections::BTreeMap, path::Path}; -pub const PUSH_DATA_TX_SCRIPT: &str = r#" -use.oracle::push_oracle - -begin - push.{} - push.{} - push.{} - push.{} - - call.[1] - #call.[2] - - dropw dropw dropw dropw - - call.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 - drop -end -"#; - #[test] fn oracle_account_creation_and_pushing_data_to_read() { let (oracle_pub_key, oracle_auth) = get_new_pk_and_authenticator(); @@ -74,10 +55,10 @@ fn oracle_account_creation_and_pushing_data_to_read() { PUSH_DATA_TX_SCRIPT .replace("{}", &word_to_masm(&word)) .replace( - "[1]", + "[push_oracle]", &format!("{}", oracle_account.code().procedures()[1].mast_root()).to_string() ) // .replace( - // "[2]", + // "[verify_data_provider_signature]", // &format!("{}", oracle_account.code().procedures()[2].mast_root()).to_string() // ) ); @@ -98,20 +79,27 @@ fn oracle_account_creation_and_pushing_data_to_read() { // 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()).is_ok()); + + let read_tx_script_code = format!( + "{}", + READ_DATA_TX_SCRIPT + .replace("{account_id}", &oracle_account.id().to_string()) + .replace("{storage_item_index}", "2") + .replace( + "[read_oracle]", + &format!("{}", oracle_account.code().procedures()[3].mast_root()), + ) + ); - // let read_tx_script = create_transaction_script( - // read_tx_script_code, - // vec![], - // READ_ORACLE_PATH, - // )?; + let read_tx_script = create_transaction_script(read_tx_script_code, vec![]).unwrap(); - // let txn_args = TransactionArgs::from_tx_script(read_tx_script); - // let executed_transaction = executor - // .execute_transaction(oracle_account.id(), None, &[], txn_args) - // .unwrap(); + let txn_args = TransactionArgs::with_tx_script(read_tx_script); + let executed_transaction = executor + .execute_transaction(oracle_account.id(), 4, &[], txn_args) + .unwrap(); - // assert!(prove_and_verify_transaction(executed_transaction.clone()).is_ok()); + assert!(prove_and_verify_transaction(executed_transaction.clone()).is_ok()); } #[test] From 6e3ee672744181b89436c512f4e2465356050e53 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Sat, 9 Nov 2024 18:20:21 +0530 Subject: [PATCH 25/45] dont verify dp sig --- src/accounts/accounts.rs | 45 +++++++++++++---------------------- src/accounts/mod.rs | 28 ++++++++++++++-------- src/accounts/tests.rs | 48 ++++++++++++++++---------------------- src/commands/mod.rs | 12 ---------- src/commands/new_oracle.rs | 4 ++-- src/commands/push_data.rs | 15 +++++++----- 6 files changed, 65 insertions(+), 87 deletions(-) diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index 3c07e81..a26c86a 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -1,4 +1,4 @@ -use super::{data_to_word, word_to_data, word_to_masm, OracleData}; +use super::{data_to_word, word_to_data, word_to_masm, public_key_to_string, OracleData}; use miden_client::{ rpc::NodeRpcClient, store::Store, transactions::request::TransactionRequest, Client, }; @@ -45,7 +45,9 @@ begin push.{} call.[push_oracle] - #call.[verify_data_provider_signature] + + #push.{data_provider_public_key} + #call.[verify_data_provider] dropw dropw dropw dropw @@ -70,7 +72,6 @@ end pub const SOURCE_CODE: &str = r#" use.miden::account - use.std::crypto::dsa::rpo_falcon512 export.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 # Slot in account storage at which the data prover's public key is stored. @@ -103,23 +104,14 @@ pub const SOURCE_CODE: &str = r#" # => [] end - #! Verify the signature of the data provider - #! Stack: [WORD_1, WORD_2, WORD_3, WORD_4] + #! Verify that the data provider's public key is matching the one in the account storage + #! Stack: [DATA_PROVIDER_PUBLIC_KEY] #! Output: [] #! - export.verify_data_provider_signature - push.2 exec.account::get_item - push.3 exec.account::get_item - push.4 exec.account::get_item - push.5 exec.account::get_item - - # Compute the hash of the retrieved data - hmerge hmerge hmerge - # => [DATA_HASH] - + export.verify_data_provider # Get data provider's public key from account storage at slot 1 push.DATA_PROVIDER_PUBLIC_KEY_SLOT exec.account::get_item - # => [PUB_KEY, DATA_HASH] + # => [PUB_KEY, DATA_PROVIDER_PUBLIC_KEY] # Update the nonce push.1 exec.account::incr_nonce @@ -127,8 +119,9 @@ pub const SOURCE_CODE: &str = r#" push.100 mem_loadw add.1 mem_storew dropw - # Verify the signature against the public key and the message hash. - exec.rpo_falcon512::verify + # Verify that the data provider's public key is matching the one in the account storage + + # => [] end "#; @@ -173,7 +166,6 @@ pub fn get_oracle_account( /// Helper function to create a transaction script pub fn create_transaction_script( tx_script_code: String, - private_key_inputs: Vec<(Word, Vec)>, // masm_path: &str, ) -> Result> { let assembler = TransactionKernel::assembler(); @@ -193,8 +185,7 @@ pub fn create_transaction_script( // let assembler = assembler.with_library(library).unwrap(); // Compile the transaction script - let tx_script = - TransactionScript::compile(tx_script_code, private_key_inputs, assembler).unwrap(); + let tx_script = TransactionScript::compile(tx_script_code, vec![], assembler).unwrap(); Ok(tx_script) } @@ -227,7 +218,7 @@ pub async fn push_data_to_oracle_account( client: &mut Client, account: Account, data: OracleData, - private_key: &SecretKey, + data_provider_public_key: &PublicKey, ) -> Result<(), Box> where N: NodeRpcClient, @@ -236,27 +227,23 @@ where A: TransactionAuthenticator, { let word = data_to_word(&data); - let private_key_felts = super::secret_key_to_felts(private_key); let push_tx_script_code = format!( "{}", PUSH_DATA_TX_SCRIPT .replace("{}", &word_to_masm(&word)) + .replace("{data_provider_public_key}", &public_key_to_string(&data_provider_public_key)) .replace( "[push_oracle]", &format!("{}", account.code().procedures()[1].mast_root()).to_string() ) .replace( - "[verify_data_provider_signature]", + "[verify_data_provider]", &format!("{}", account.code().procedures()[2].mast_root()).to_string() ) ); - let push_tx_script = create_transaction_script( - push_tx_script_code, - vec![(private_key_felts, Vec::new())], - // PUSH_ORACLE_PATH, - )?; + let push_tx_script = create_transaction_script(push_tx_script_code)?; let transaction_id = execute_transaction(client, account.id(), push_tx_script).await?; println!( diff --git a/src/accounts/mod.rs b/src/accounts/mod.rs index 53afb80..f38e590 100644 --- a/src/accounts/mod.rs +++ b/src/accounts/mod.rs @@ -2,7 +2,7 @@ mod accounts; mod tests; use miden_crypto::{ - dsa::rpo_falcon512::SecretKey, + dsa::rpo_falcon512::{PublicKey, SecretKey}, merkle::{MmrPeaks, PartialMmr}, Felt, EMPTY_WORD, }; @@ -131,13 +131,21 @@ pub fn word_to_data(word: &Word) -> OracleData { } } -/// Convert SecretKey to array of Felts representing the polynomials -pub fn secret_key_to_felts(private_key: &SecretKey) -> [Felt; 4] { - let basis = private_key.short_lattice_basis(); - [ - Felt::new(basis[0].lc() as u64), // g polynomial - Felt::new(basis[1].lc() as u64), // f polynomial - Felt::new(basis[2].lc() as u64), // G polynomial - Felt::new(basis[3].lc() as u64), // F polynomial - ] +/// Convert PublicKey to array of Felts representing the polynomials +pub fn public_key_to_felts(public_key: &PublicKey) -> [Felt; 4] { + let word: Word = (*public_key).into(); + word.into() +} + +/// Convert PublicKey felts to a string representation +pub fn public_key_felts_to_string(felts: &[Felt; 4]) -> String { + felts.iter() + .map(|x| x.as_int().to_string()) + .collect::>() + .join(".") +} + +/// Convert PublicKey directly to string representation +pub fn public_key_to_string(public_key: &PublicKey) -> String { + public_key_felts_to_string(&public_key_to_felts(public_key)) } diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index b836b97..0725b33 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -1,8 +1,8 @@ -use crate::accounts::{ +use crate::{accounts::{ accounts::{create_transaction_script, PUSH_DATA_TX_SCRIPT, READ_DATA_TX_SCRIPT}, - data_to_word, decode_u32_to_asset_pair, encode_asset_pair_to_u32, push_data_to_oracle_account, - secret_key_to_felts, word_to_data, word_to_masm, OracleData, -}; + data_to_word, public_key_to_string, decode_u32_to_asset_pair, encode_asset_pair_to_u32, push_data_to_oracle_account, + word_to_data, word_to_masm, OracleData, +}, commands::parse_public_key}; use miden_client::utils::Deserializable; use miden_crypto::{ dsa::rpo_falcon512::{PublicKey, SecretKey}, @@ -45,7 +45,8 @@ fn oracle_account_creation_and_pushing_data_to_read() { publisher_id: 1, }; - let word = data_to_word(&oracle_data); + 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())); @@ -54,22 +55,22 @@ fn oracle_account_creation_and_pushing_data_to_read() { "{}", PUSH_DATA_TX_SCRIPT .replace("{}", &word_to_masm(&word)) + .replace( + "{data_provider_public_key}", + &public_key_to_string(&data_provider_public_key), + ) .replace( "[push_oracle]", &format!("{}", oracle_account.code().procedures()[1].mast_root()).to_string() ) // .replace( - // "[verify_data_provider_signature]", + // "[verify_data_provider]", // &format!("{}", oracle_account.code().procedures()[2].mast_root()).to_string() // ) ); println!("Push tx script code: {}", push_tx_script_code); - let push_tx_script = create_transaction_script( - push_tx_script_code, - vec![(secret_key_to_felts(&data_provider_private_key), Vec::new())], - ) - .unwrap(); + let push_tx_script = create_transaction_script(push_tx_script_code).unwrap(); let txn_args = TransactionArgs::with_tx_script(push_tx_script); let executed_transaction = executor @@ -92,7 +93,7 @@ fn oracle_account_creation_and_pushing_data_to_read() { ) ); - let read_tx_script = create_transaction_script(read_tx_script_code, vec![]).unwrap(); + let read_tx_script = create_transaction_script(read_tx_script_code).unwrap(); let txn_args = TransactionArgs::with_tx_script(read_tx_script); let executed_transaction = executor @@ -202,7 +203,6 @@ fn get_oracle_account(data_provider_public_key: PublicKey, oracle_public_key: Wo let source_code = format!( " use.miden::account - use.std::crypto::dsa::rpo_falcon512 export.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 # Slot in account storage at which the data prover's public key is stored. @@ -235,23 +235,14 @@ fn get_oracle_account(data_provider_public_key: PublicKey, oracle_public_key: Wo # => [] end - #! Verify the signature of the data provider - #! Stack: [WORD_1, WORD_2, WORD_3, WORD_4] + #! Verify that the data provider's public key is matching the one in the account storage + #! Stack: [DATA_PROVIDER_PUBLIC_KEY] #! Output: [] #! - export.verify_data_provider_signature - push.2 exec.account::get_item - push.3 exec.account::get_item - push.4 exec.account::get_item - push.5 exec.account::get_item - - # Compute the hash of the retrieved data - hmerge hmerge hmerge - # => [DATA_HASH] - + export.verify_data_provider # Get data provider's public key from account storage at slot 1 push.DATA_PROVIDER_PUBLIC_KEY_SLOT exec.account::get_item - # => [PUB_KEY, DATA_HASH] + # => [PUB_KEY, DATA_PROVIDER_PUBLIC_KEY] # Update the nonce push.1 exec.account::incr_nonce @@ -259,8 +250,9 @@ fn get_oracle_account(data_provider_public_key: PublicKey, oracle_public_key: Wo push.100 mem_loadw add.1 mem_storew dropw - # Verify the signature against the public key and the message hash. - exec.rpo_falcon512::verify + # Verify that the data provider's public key is matching the one in the account storage + + # => [] end " diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 71c7c10..7905152 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -12,8 +12,6 @@ pub mod push_data; pub mod read_data; pub mod sync; -static ORACLE_KEY: Lazy = Lazy::new(|| SecretKey::new()); - pub fn account_id_parser(s: &str) -> Result { AccountId::from_hex(s).map_err(|e| format!("Invalid AccountId: {}", e)) } @@ -32,13 +30,3 @@ pub fn word_from_hex(hex_string: &str) -> Result { Felt::new(u64::from_be_bytes(bytes[24..32].try_into().unwrap())), ]) } - -/// Returns the oracle test public key -pub fn get_oracle_public_key() -> PublicKey { - ORACLE_KEY.public_key() -} - -/// Returns the oracle test private key -pub fn get_oracle_private_key() -> SecretKey { - ORACLE_KEY.clone() -} diff --git a/src/commands/new_oracle.rs b/src/commands/new_oracle.rs index c171203..5074daf 100644 --- a/src/commands/new_oracle.rs +++ b/src/commands/new_oracle.rs @@ -1,5 +1,5 @@ use crate::commands::parse_public_key; -use crate::{accounts::get_oracle_account, commands::get_oracle_public_key}; +use crate::{accounts::get_oracle_account}; use clap::{Parser, ValueEnum}; use miden_client::{rpc::NodeRpcClient, store::Store, Client, ClientError, Felt}; use miden_lib::{utils::hex_to_bytes, AuthScheme}; @@ -41,7 +41,7 @@ impl AccountCmd { let (account, seed) = client .new_oracle_account( AccountStorageType::OnChain, - get_oracle_public_key(), // TODO: hardcode the pragma data provider public key + self.data_provider_public_key, ) .await .map_err(|e| e.to_string())?; diff --git a/src/commands/push_data.rs b/src/commands/push_data.rs index 64ed01b..c76ecef 100644 --- a/src/commands/push_data.rs +++ b/src/commands/push_data.rs @@ -1,11 +1,10 @@ use crate::accounts::{push_data_to_oracle_account, OracleData}; -use crate::commands::account_id_parser; -use crate::commands::get_oracle_private_key; +use crate::commands::{account_id_parser, parse_public_key}; use clap::Parser; use miden_client::{rpc::NodeRpcClient, store::Store, Client, ClientError}; use miden_objects::{ accounts::{Account, AccountId}, - crypto::{dsa::rpo_falcon512::SecretKey, rand::FeltRng}, + crypto::{dsa::rpo_falcon512::PublicKey, rand::FeltRng}, Word, }; use miden_tx::auth::TransactionAuthenticator; @@ -14,6 +13,9 @@ use winter_maybe_async::{maybe_async, maybe_await}; #[derive(Debug, Clone, Parser)] #[clap(about = "Push data to a pragma oracle account on Miden")] pub struct PushDataCmd { + #[arg(long, required = true, value_parser = parse_public_key)] + data_provider_public_key: PublicKey, + #[arg(long, required = true, value_parser = account_id_parser)] account_id: AccountId, @@ -34,6 +36,7 @@ pub struct PushDataCmd { pub trait OracleDataPusher { async fn push_oracle_data( &mut self, + data_provider_public_key: &PublicKey, account_id: &AccountId, data: OracleData, ) -> Result<(), ClientError>; @@ -55,7 +58,7 @@ impl PushDataCmd { }; client - .push_oracle_data(&self.account_id, oracle_data) + .push_oracle_data(&self.data_provider_public_key, &self.account_id, oracle_data) .await .map_err(|e| e.to_string())?; @@ -71,12 +74,12 @@ impl Oracle { 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)?; - // TODO: hardcode the pragma data provider private key - push_data_to_oracle_account(self, account, data, &get_oracle_private_key()) + push_data_to_oracle_account(self, account, data, data_provider_public_key) .await .map_err(|e| { ClientError::AccountError(miden_objects::AccountError::AccountCodeAssemblyError( From 8e9a301fdaa5b7afa69f2c77dc854bd52a6e4667 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Sat, 9 Nov 2024 18:33:56 +0530 Subject: [PATCH 26/45] remove read form tests --- src/accounts/tests.rs | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index 0725b33..e99ab2f 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -82,25 +82,25 @@ fn oracle_account_creation_and_pushing_data_to_read() { assert!(prove_and_verify_transaction(executed_transaction.clone()).is_ok()); - let read_tx_script_code = format!( - "{}", - READ_DATA_TX_SCRIPT - .replace("{account_id}", &oracle_account.id().to_string()) - .replace("{storage_item_index}", "2") - .replace( - "[read_oracle]", - &format!("{}", oracle_account.code().procedures()[3].mast_root()), - ) - ); - - let read_tx_script = create_transaction_script(read_tx_script_code).unwrap(); - - let txn_args = TransactionArgs::with_tx_script(read_tx_script); - let executed_transaction = executor - .execute_transaction(oracle_account.id(), 4, &[], txn_args) - .unwrap(); - - assert!(prove_and_verify_transaction(executed_transaction.clone()).is_ok()); + // let read_tx_script_code = format!( + // "{}", + // READ_DATA_TX_SCRIPT + // .replace("{account_id}", &oracle_account.id().to_string()) + // .replace("{storage_item_index}", "2") + // .replace( + // "[read_oracle]", + // &format!("{}", oracle_account.code().procedures()[3].mast_root()), + // ) + // ); + + // let read_tx_script = create_transaction_script(read_tx_script_code).unwrap(); + + // let txn_args = TransactionArgs::with_tx_script(read_tx_script); + // let executed_transaction = executor + // .execute_transaction(oracle_account.id(), 4, &[], txn_args) + // .unwrap(); + + // assert!(prove_and_verify_transaction(executed_transaction.clone()).is_ok()); } #[test] From b52760ae8f11daba5ce48755bdf30385c0e6ad93 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Mon, 11 Nov 2024 17:19:59 +0530 Subject: [PATCH 27/45] use pragma sdk for pushing every 10min --- .cargo/config.toml | 6 +++ Cargo.toml | 15 +++++++ pyproject.toml | 10 +++++ src/accounts/accounts.rs | 7 ++- src/accounts/mod.rs | 3 +- src/accounts/tests.rs | 13 +++--- src/commands/new_oracle.rs | 7 +-- src/commands/push_data.rs | 62 +++++++++++++++++--------- src/main.rs | 1 + src/sdk/mod.rs | 2 + src/sdk/sdk.rs | 90 ++++++++++++++++++++++++++++++++++++++ 11 files changed, 182 insertions(+), 34 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 pyproject.toml create mode 100644 src/sdk/mod.rs create mode 100644 src/sdk/sdk.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..961968d --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,6 @@ +[target.aarch64-apple-darwin] +rustflags = [ + "-C", "link-arg=-undefined", + "-C", "link-arg=dynamic_lookup", + "-C", "link-arg=-Wl,-rpath,/Users/harshpratapsingh/Desktop/venv/lib" +] \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 88d267c..2bcdbb4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ name = "pragma-miden" version = "0.1.0" edition = "2021" +authors = ["Harsh Pratap Singh "] [features] testing = ["miden-tx/testing"] @@ -29,8 +30,22 @@ winter-maybe-async = "0.10" hex = "0.4.3" rand_chacha = "0.3" once_cell = "1.18" +pyo3 = { version = "0.22.6", features = ["auto-initialize"] } +tokio-stream = "0.1.1" +async-trait = "0.1.83" +thiserror = "2.0.1" + +[build-dependencies] +pyo3-build-config = { version = "0.22.6", features = ["resolve-config"] } [[test]] name = "integration" path = "src/accounts/tests.rs" required-features = ["testing"] + +[env] +PYO3_PYTHON = "/opt/homebrew/bin/python3" + +[[bin]] +name = "pragma-miden" +path = "src/main.rs" \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f37a73e --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ +[build-system] +requires = ["maturin>=1.4,<2.0"] +build-backend = "maturin" + +[project] +name = "pragma-miden" +requires-python = ">=3.8" + +[tool.maturin] +features = ["pyo3/extension-module"] \ No newline at end of file diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index a26c86a..41bd6dd 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -1,4 +1,4 @@ -use super::{data_to_word, word_to_data, word_to_masm, public_key_to_string, OracleData}; +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, }; @@ -232,7 +232,10 @@ where "{}", PUSH_DATA_TX_SCRIPT .replace("{}", &word_to_masm(&word)) - .replace("{data_provider_public_key}", &public_key_to_string(&data_provider_public_key)) + .replace( + "{data_provider_public_key}", + &public_key_to_string(&data_provider_public_key) + ) .replace( "[push_oracle]", &format!("{}", account.code().procedures()[1].mast_root()).to_string() diff --git a/src/accounts/mod.rs b/src/accounts/mod.rs index f38e590..dd5c4d8 100644 --- a/src/accounts/mod.rs +++ b/src/accounts/mod.rs @@ -139,7 +139,8 @@ pub fn public_key_to_felts(public_key: &PublicKey) -> [Felt; 4] { /// Convert PublicKey felts to a string representation pub fn public_key_felts_to_string(felts: &[Felt; 4]) -> String { - felts.iter() + felts + .iter() .map(|x| x.as_int().to_string()) .collect::>() .join(".") diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index e99ab2f..0bebd75 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -1,8 +1,11 @@ -use crate::{accounts::{ - accounts::{create_transaction_script, PUSH_DATA_TX_SCRIPT, READ_DATA_TX_SCRIPT}, - data_to_word, public_key_to_string, decode_u32_to_asset_pair, encode_asset_pair_to_u32, push_data_to_oracle_account, - word_to_data, word_to_masm, OracleData, -}, commands::parse_public_key}; +use crate::{ + accounts::{ + accounts::{create_transaction_script, PUSH_DATA_TX_SCRIPT, READ_DATA_TX_SCRIPT}, + data_to_word, decode_u32_to_asset_pair, encode_asset_pair_to_u32, public_key_to_string, + push_data_to_oracle_account, word_to_data, word_to_masm, OracleData, + }, + commands::parse_public_key, +}; use miden_client::utils::Deserializable; use miden_crypto::{ dsa::rpo_falcon512::{PublicKey, SecretKey}, diff --git a/src/commands/new_oracle.rs b/src/commands/new_oracle.rs index 5074daf..9b59a86 100644 --- a/src/commands/new_oracle.rs +++ b/src/commands/new_oracle.rs @@ -1,5 +1,5 @@ +use crate::accounts::get_oracle_account; use crate::commands::parse_public_key; -use crate::{accounts::get_oracle_account}; use clap::{Parser, ValueEnum}; use miden_client::{rpc::NodeRpcClient, store::Store, Client, ClientError, Felt}; use miden_lib::{utils::hex_to_bytes, AuthScheme}; @@ -39,10 +39,7 @@ impl AccountCmd { Client: OracleAccountCreation, { let (account, seed) = client - .new_oracle_account( - AccountStorageType::OnChain, - self.data_provider_public_key, - ) + .new_oracle_account(AccountStorageType::OnChain, self.data_provider_public_key) .await .map_err(|e| e.to_string())?; diff --git a/src/commands/push_data.rs b/src/commands/push_data.rs index c76ecef..28ea38d 100644 --- a/src/commands/push_data.rs +++ b/src/commands/push_data.rs @@ -1,5 +1,6 @@ use crate::accounts::{push_data_to_oracle_account, OracleData}; use crate::commands::{account_id_parser, parse_public_key}; +use crate::sdk::get_pragma_prices; use clap::Parser; use miden_client::{rpc::NodeRpcClient, store::Store, Client, ClientError}; use miden_objects::{ @@ -8,6 +9,7 @@ use miden_objects::{ Word, }; use miden_tx::auth::TransactionAuthenticator; +use std::time::Duration; use winter_maybe_async::{maybe_async, maybe_await}; #[derive(Debug, Clone, Parser)] @@ -18,18 +20,17 @@ pub struct PushDataCmd { #[arg(long, required = true, value_parser = account_id_parser)] account_id: AccountId, + // #[arg(long, required = true)] + // asset_pair: String, - #[arg(long, required = true)] - asset_pair: String, + // #[arg(long, required = true)] + // price: u64, - #[arg(long, required = true)] - price: u64, + // #[arg(long, required = true)] + // decimals: u64, - #[arg(long, required = true)] - decimals: u64, - - #[arg(long, required = true)] - publisher_id: u64, + // #[arg(long, required = true)] + // publisher_id: u64, } #[maybe_async] @@ -50,21 +51,40 @@ impl PushDataCmd { where Client: OracleDataPusher, { - let oracle_data = OracleData { - asset_pair: self.asset_pair.clone(), - price: self.price, - decimals: self.decimals, - publisher_id: self.publisher_id, - }; + let mut interval = tokio::time::interval(Duration::from_secs(10 * 60)); // 10 minutes - client - .push_oracle_data(&self.data_provider_public_key, &self.account_id, oracle_data) - .await - .map_err(|e| e.to_string())?; + loop { + interval.tick().await; - println!("Data pushed to oracle account successfully!"); + match get_pragma_prices(vec!["BTC/USD".to_string(), "ETH/USD".to_string()]).await { + Ok(prices) => { + for price in prices { + let oracle_data = OracleData { + asset_pair: price.pair, + price: price.price, + decimals: 8, // default decimals for pragma + publisher_id: 1, // TODO: fix this + }; - Ok(()) + if let Err(e) = client + .push_oracle_data( + &self.data_provider_public_key, + &self.account_id, + oracle_data, + ) + .await + { + eprintln!("Error pushing data to oracle: {}", e); + continue; + } + } + println!("Data pushed to oracle account successfully!"); + } + Err(e) => { + eprintln!("Error fetching prices: {}", e); + } + } + } } } diff --git a/src/main.rs b/src/main.rs index 0b4e1d9..487a219 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ mod accounts; mod cli; mod commands; mod errors; +mod sdk; mod setup; use clap::Parser; diff --git a/src/sdk/mod.rs b/src/sdk/mod.rs new file mode 100644 index 0000000..57da14d --- /dev/null +++ b/src/sdk/mod.rs @@ -0,0 +1,2 @@ +mod sdk; +pub use sdk::{get_pragma_prices, PragmaPrice, PragmaSDKError}; \ No newline at end of file diff --git a/src/sdk/sdk.rs b/src/sdk/sdk.rs new file mode 100644 index 0000000..72e3c92 --- /dev/null +++ b/src/sdk/sdk.rs @@ -0,0 +1,90 @@ +use pyo3::prelude::*; +use pyo3::types::{PyDict, PyList}; +use std::sync::Once; +use thiserror::Error; + +static INIT: Once = Once::new(); + +#[derive(Debug, Clone)] +pub struct PragmaPrice { + pub pair: String, + pub price: u64, + pub timestamp: u64, + pub source: String, + pub publisher: String, + pub volume: u64, +} + +#[derive(Debug, Error)] +pub enum PragmaSDKError { + #[error("Python error: {0}")] + PythonError(#[from] PyErr), + #[error("Failed to fetch price data: {0}")] + FetchError(String), +} + +// Initialize Python and pragma-sdk +fn init_python() -> PyResult<()> { + Python::with_gil(|py| { + let setup_code = r#" +import asyncio +from pragma_sdk.common.fetchers.fetcher_client import FetcherClient +from pragma_sdk.common.fetchers.fetchers import BitstampFetcher +from pragma_sdk.common.fetchers.fetchers.gateio import GateioFetcher +from pragma_sdk.common.types.pair import Pair + +async def fetch_prices(pair_strings): + pairs = [Pair.from_tickers(*pair_str.split('/')) for pair_str in pair_strings] + + bitstamp_fetcher = BitstampFetcher(pairs, "pragma_miden") + gateio_fetcher = GateioFetcher(pairs, "pragma_miden") + fetchers = [bitstamp_fetcher, gateio_fetcher] + + fc = FetcherClient() + fc.add_fetchers(fetchers) + + return await fc.fetch() + "#; + py.run_bound(setup_code, None, None) + }) +} + +pub async fn get_pragma_prices(pairs: Vec) -> Result, PragmaSDKError> { + // Initialize Python code only once + INIT.call_once(|| { + init_python().expect("Failed to initialize Python runtime"); + }); + + Python::with_gil(|py| { + let pairs_list = PyList::new_bound(py, pairs.iter()); + let locals = PyDict::new_bound(py); + locals.set_item("pairs", pairs_list)?; + + // Run the async Python code + py.run_bound( + "result = asyncio.run(fetch_prices(pairs))", + None, + Some(&locals), + )?; + + // Extract results + let result = locals + .get_item("result")? + .ok_or(PragmaSDKError::FetchError("No result returned".into()))?; + + let mut prices = Vec::new(); + for entry in result.iter()? { + let entry = entry?; + prices.push(PragmaPrice { + pair: entry.getattr("pair_id")?.extract()?, + price: entry.getattr("price")?.extract()?, + timestamp: entry.getattr("timestamp")?.extract()?, + source: entry.getattr("source")?.extract()?, + publisher: entry.getattr("publisher")?.extract()?, + volume: entry.getattr("volume")?.extract()?, + }); + } + + Ok(prices) + }) +} \ No newline at end of file From 6f246c74d58157aad1b75efdc1845781bb26fcfd Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Mon, 11 Nov 2024 17:33:09 +0530 Subject: [PATCH 28/45] sync in CI too avoid problem with miden client --- .github/workflows/build_and_test.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index bd3e483..50050ba 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -35,5 +35,11 @@ jobs: - name: Build the CLI run: cargo install --path . + - name: Initialize Miden + run: pragma-miden init + + - name: Sync Miden + run: pragma-miden sync + - name: Run tests run: cargo test --verbose From 926ab91a0ca9fefe33c8edf79c1e182284858159 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Wed, 13 Nov 2024 19:51:14 +0530 Subject: [PATCH 29/45] 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, ) } From 9f676725f7ad3548aea88c604a7ba7fbb8d0dcbc Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Wed, 13 Nov 2024 22:19:46 +0530 Subject: [PATCH 30/45] test nits --- src/accounts/tests.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index c745ff1..e0ebd3f 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -33,7 +33,8 @@ use miden_tx::{ }; use rand::rngs::StdRng; use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; -use std::{collections::BTreeMap, path::Path, sync::Arc}; +use std::collections::BTreeSet; +use std::sync::Arc; #[tokio::test] async fn oracle_account_creation_and_pushing_data_to_read() { @@ -271,6 +272,8 @@ fn get_oracle_account( ], )?; + let component = component.with_supported_types(BTreeSet::from([AccountType::RegularAccountImmutableCode])); + let oracle_account_code = AccountCode::from_components(&[component], AccountType::RegularAccountImmutableCode)?; From 7abb096640f4def29f0bb62cd1f51a07e60992a1 Mon Sep 17 00:00:00 2001 From: Ignacio Amigo Date: Wed, 13 Nov 2024 14:28:12 -0300 Subject: [PATCH 31/45] Fix test --- src/accounts/accounts.rs | 4 ++++ src/accounts/tests.rs | 37 ++++++++++++++++++------------------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index c9f7a0e..dfe32d3 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -145,6 +145,10 @@ pub fn get_oracle_account( vec![ StorageSlot::Value(storage_slot_0_data), StorageSlot::Value(data_provider_public_key.into()), + StorageSlot::Value(Default::default()), + StorageSlot::Value(Default::default()), + StorageSlot::Value(Default::default()), + StorageSlot::Value(Default::default()), ], )?; diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index e0ebd3f..eb979c0 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -13,7 +13,10 @@ use miden_crypto::{ Felt, Word, ZERO, }; use miden_lib::{transaction::TransactionKernel, AuthScheme}; -use miden_objects::assembly::{Library, LibraryNamespace}; +use miden_objects::{ + accounts::AccountBuilder, + assembly::{Library, LibraryNamespace}, +}; use miden_objects::{ accounts::{ account_id::testing::ACCOUNT_ID_REGULAR_ACCOUNT_IMMUTABLE_CODE_ON_CHAIN, Account, @@ -269,24 +272,20 @@ fn get_oracle_account( vec![ StorageSlot::Value(account_owner_public_key.into()), StorageSlot::Value(data_provider_public_key.into()), + StorageSlot::Value(Default::default()), + StorageSlot::Value(Default::default()), + StorageSlot::Value(Default::default()), + StorageSlot::Value(Default::default()), ], - )?; - - let component = component.with_supported_types(BTreeSet::from([AccountType::RegularAccountImmutableCode])); - - 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()), - ])?; + )? + .with_supports_all_types(); + + let (account, _account_seed) = AccountBuilder::new() + .init_seed(Default::default()) + .with_component(component) + .nonce(Felt::new(1)) + .build() + .unwrap(); - Ok(Account::from_parts( - oracle_account_id, - AssetVault::new(&[]).unwrap(), - account_storage, - oracle_account_code, - Felt::new(1), - )) + Ok(account) } From eb687e4b85115a573a3fead51f304dcd68456437 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Thu, 14 Nov 2024 03:58:23 +0530 Subject: [PATCH 32/45] test fix nit --- src/accounts/tests.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index eb979c0..03b804c 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -204,8 +204,6 @@ fn get_oracle_account( 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(); let assembler = TransactionKernel::assembler(); let source_code = format!( " From 189ae74d73d06b34057d7949be6c28f5ca279802 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Thu, 14 Nov 2024 14:57:06 +0530 Subject: [PATCH 33/45] cli nit --- src/cli.rs | 2 +- src/commands/init.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index b89f325..8c70e04 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -37,7 +37,7 @@ impl Cli { match &self.action { Command::Sync(sync) => sync.execute(&mut client).await, - Command::Init(init) => init.execute(), + Command::Init(init) => init.execute().await, Command::NewOracle(new_oracle) => new_oracle.execute(&mut client).await, Command::PushData(push_data) => push_data.execute(&mut client).await, Command::ReadData(read_data) => read_data.execute(&mut client).await, diff --git a/src/commands/init.rs b/src/commands/init.rs index 5d81b12..553639b 100644 --- a/src/commands/init.rs +++ b/src/commands/init.rs @@ -11,10 +11,10 @@ use std::{ pub struct InitCmd {} impl InitCmd { - pub fn execute(&self) -> Result<(), String> { + pub async fn execute(&self) -> Result<(), String> { self.remove_file_if_exists(DB_FILE_PATH)?; self.create_file(DB_FILE_PATH)?; - setup_client(); + setup_client().await; println!("Oracle successfully initialized."); Ok(()) } From f2ef967d1ca1a059aa26c444ad7cafbacd3fff3c Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Thu, 14 Nov 2024 15:26:09 +0530 Subject: [PATCH 34/45] db handled by client itself! --- src/commands/init.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/commands/init.rs b/src/commands/init.rs index 553639b..b403cc2 100644 --- a/src/commands/init.rs +++ b/src/commands/init.rs @@ -13,7 +13,6 @@ pub struct InitCmd {} impl InitCmd { pub async fn execute(&self) -> Result<(), String> { self.remove_file_if_exists(DB_FILE_PATH)?; - self.create_file(DB_FILE_PATH)?; setup_client().await; println!("Oracle successfully initialized."); Ok(()) From 87bbaf980be6d2dbdacd9caf677c650b7ba52ecf Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Thu, 14 Nov 2024 15:27:58 +0530 Subject: [PATCH 35/45] component should support all types! --- src/accounts/accounts.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index dfe32d3..b771847 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -150,7 +150,8 @@ pub fn get_oracle_account( StorageSlot::Value(Default::default()), StorageSlot::Value(Default::default()), ], - )?; + )? + .with_supports_all_types(); let (account, seed) = AccountBuilder::new() .init_seed(init_seed) From 93c7207cf7c10e04f106cf62e90a616b120db2c1 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Thu, 14 Nov 2024 17:13:36 +0530 Subject: [PATCH 36/45] pragma-sdk has to be installed --- pyproject.toml | 3 +++ src/sdk/sdk.rs | 9 +++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f37a73e..ad2addb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,9 @@ build-backend = "maturin" [project] name = "pragma-miden" requires-python = ">=3.8" +dependencies = [ + "pragma-sdk>=2.3.2" +] [tool.maturin] features = ["pyo3/extension-module"] \ No newline at end of file diff --git a/src/sdk/sdk.rs b/src/sdk/sdk.rs index a2713cb..72e643f 100644 --- a/src/sdk/sdk.rs +++ b/src/sdk/sdk.rs @@ -1,4 +1,5 @@ use pyo3::prelude::*; +use pyo3::exceptions::PyModuleNotFoundError; use pyo3::types::{PyDict, PyList}; use std::sync::Once; use thiserror::Error; @@ -23,9 +24,12 @@ pub enum PragmaSDKError { FetchError(String), } -// Initialize Python and pragma-sdk fn init_python() -> PyResult<()> { Python::with_gil(|py| { + if let Err(e) = py.import_bound("pragma_sdk") { + return Err(PyModuleNotFoundError::new_err(e)); + } + let setup_code = r#" import asyncio from pragma_sdk.common.fetchers.fetcher_client import FetcherClient @@ -50,7 +54,6 @@ async def fetch_prices(pair_strings): } pub async fn get_pragma_prices(pairs: Vec) -> Result, PragmaSDKError> { - // Initialize Python code only once INIT.call_once(|| { init_python().expect("Failed to initialize Python runtime"); }); @@ -60,14 +63,12 @@ pub async fn get_pragma_prices(pairs: Vec) -> Result, P let locals = PyDict::new_bound(py); locals.set_item("pairs", pairs_list)?; - // Run the async Python code py.run_bound( "result = asyncio.run(fetch_prices(pairs))", None, Some(&locals), )?; - // Extract results let result = locals .get_item("result")? .ok_or(PragmaSDKError::FetchError("No result returned".into()))?; From 0c253528d2ce8b9163837097fd96f5a9934743f3 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Fri, 22 Nov 2024 11:19:55 +0530 Subject: [PATCH 37/45] prepare for read --- src/accounts/accounts.rs | 36 +++++++++- src/accounts/tests.rs | 146 +++++++++++++++++++++------------------ src/sdk/sdk.rs | 2 +- 3 files changed, 115 insertions(+), 69 deletions(-) diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index b771847..85074d1 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -61,16 +61,26 @@ pub const READ_DATA_TX_SCRIPT: &str = r#" use.oracle::read_oracle begin - push.{account_id} + padw padw padw push.0.0 + # => [pad(14)] + push.{storage_item_index} + push.{get_item_foreign_hash} + push.{account_id} + # => [foreign_account_id, FOREIGN_PROC_ROOT, storage_item_index, pad(14)] call.[read_oracle] + # assert the correctness of the obtained value + push.{oracle_data} assert_eqw + call.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 end "#; pub const SOURCE_CODE: &str = r#" + use.std::sys + use.miden::tx use.miden::account export.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 @@ -124,6 +134,30 @@ pub const SOURCE_CODE: &str = r#" # => [] end + + #! Gets new price data from the oracle's data slots. + #! + #! Inputs: [storage_slot] + #! Outputs: [WORD] + #! + export.get_item_foreign + # make this foreign procedure unique to make sure that we invoke the procedure of the + # foreign account, not the native one + push.1 drop + exec.account::get_item + # truncate the stack + movup.6 movup.6 movup.6 drop drop drop + end + + #! Reads the price data from the oracle's data slots. + #! + #! Inputs: [] + #! Outputs: [WORD] + #! + export.read_oracle + exec.tx::execute_foreign_procedure + # => [STORAGE_VALUE] + end "#; pub fn get_oracle_account( diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index 03b804c..c9bc94d 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -1,6 +1,8 @@ use crate::{ accounts::{ - accounts::{create_transaction_script, PUSH_DATA_TX_SCRIPT, READ_DATA_TX_SCRIPT}, + accounts::{ + create_transaction_script, PUSH_DATA_TX_SCRIPT, READ_DATA_TX_SCRIPT, SOURCE_CODE, + }, data_to_word, decode_u32_to_asset_pair, encode_asset_pair_to_u32, public_key_to_string, push_data_to_oracle_account, word_to_data, word_to_masm, OracleData, }, @@ -16,6 +18,7 @@ use miden_lib::{transaction::TransactionKernel, AuthScheme}; use miden_objects::{ accounts::AccountBuilder, assembly::{Library, LibraryNamespace}, + testing::account_component::AccountMockComponent, }; use miden_objects::{ accounts::{ @@ -34,7 +37,7 @@ use miden_tx::{ testing::TransactionContextBuilder, LocalTransactionProver, ProvingOptions, TransactionExecutor, TransactionProver, TransactionVerifier, TransactionVerifierError, }; -use rand::rngs::StdRng; +use rand::{rngs::StdRng, Rng}; use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; use std::collections::BTreeSet; use std::sync::Arc; @@ -66,10 +69,10 @@ async fn oracle_account_creation_and_pushing_data_to_read() { "{}", PUSH_DATA_TX_SCRIPT .replace("{}", &word_to_masm(&word)) - .replace( - "{data_provider_public_key}", - &public_key_to_string(&data_provider_public_key), - ) + // .replace( + // "{data_provider_public_key}", + // &public_key_to_string(&data_provider_public_key), + // ) .replace( "[push_oracle]", &format!("{}", oracle_account.code().procedures()[1].mast_root()).to_string() @@ -96,15 +99,45 @@ async fn oracle_account_creation_and_pushing_data_to_read() { .await .is_ok()); + // let read_data_tx_script_code = r#" + // use.oracle::read_oracle + + // begin + // padw padw padw push.0.0 + // # => [pad(14)] + + // push.{storage_item_index} + // push.{get_item_foreign_hash} + // push.{account_id} + // # => [foreign_account_id, FOREIGN_PROC_ROOT, storage_item_index, pad(14)] + + // call.[read_oracle] + + // # assert the correctness of the obtained value + // push.{oracle_data} assert_eqw + + // call.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 + // end + // "#; + + // let foreign_account = get_foreign_account().unwrap(); + // let read_tx_script_code = format!( // "{}", - // READ_DATA_TX_SCRIPT - // .replace("{account_id}", &oracle_account.id().to_string()) + // read_data_tx_script_code // .replace("{storage_item_index}", "2") // .replace( + // "{get_item_foreign_hash}", + // &oracle_account.code().procedures()[1] + // .mast_root() + // .to_string(), + // ) + // .replace("{account_id}", &foreign_account.id().to_string()) + // .replace( // "[read_oracle]", // &format!("{}", oracle_account.code().procedures()[3].mast_root()), // ) + // .replace("{oracle_data}", &word_to_masm(&data_to_word(&oracle_data))) // ); // let read_tx_script = create_transaction_script(read_tx_script_code).unwrap(); @@ -112,9 +145,12 @@ async fn oracle_account_creation_and_pushing_data_to_read() { // let txn_args = TransactionArgs::with_tx_script(read_tx_script); // let executed_transaction = executor // .execute_transaction(oracle_account.id(), 4, &[], txn_args) + // .await // .unwrap(); - // assert!(prove_and_verify_transaction(executed_transaction.clone()).is_ok()); + // assert!(prove_and_verify_transaction(executed_transaction.clone()) + // .await + // .is_ok()); } #[test] @@ -205,65 +241,27 @@ fn get_oracle_account( ) -> Result { let account_owner_public_key = PublicKey::new(oracle_public_key); let assembler = TransactionKernel::assembler(); - let source_code = format!( - " - use.miden::account - export.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 - - # Slot in account storage at which the data prover's public key is stored. - const.DATA_PROVIDER_PUBLIC_KEY_SLOT=1 - - #! Pushes new price data into the oracle's data slots. - #! - #! Inputs: [WORD_1, WORD_2, WORD_3, WORD_4] - #! Outputs: [] - #! - export.push_oracle_data - push.2 - exec.account::set_item - dropw - # => [WORD_2, WORD_3, WORD_4] - - push.3 - exec.account::set_item - dropw - # => [WORD_3, WORD_4] - - push.4 - exec.account::set_item - dropw - # => [WORD_4] - - push.5 - exec.account::set_item - dropw - # => [] - end - - #! Verify that the data provider's public key is matching the one in the account storage - #! Stack: [DATA_PROVIDER_PUBLIC_KEY] - #! Output: [] - #! - export.verify_data_provider - # Get data provider's public key from account storage at slot 1 - push.DATA_PROVIDER_PUBLIC_KEY_SLOT exec.account::get_item - # => [PUB_KEY, DATA_PROVIDER_PUBLIC_KEY] - - # Update the nonce - push.1 exec.account::incr_nonce - # => [] - - push.100 mem_loadw add.1 mem_storew dropw - - # Verify that the data provider's public key is matching the one in the account storage - - - # => [] - end - " - ); - let library = assembler.assemble_library([source_code]).unwrap(); + /// Transaction script template for reading data from oracle + pub const READ_DATA_TX_SCRIPT: &str = r#" +use.oracle::read_oracle + +begin + padw padw padw push.0.0 + # => [pad(14)] + + push.{storage_item_index} + push.{get_item_foreign_hash} + push.{account_id} + # => [foreign_account_id, FOREIGN_PROC_ROOT, storage_item_index, pad(14)] + + call.[read_oracle] + + call.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 +end +"#; + + let library = assembler.assemble_library([SOURCE_CODE]).unwrap(); let component = AccountComponent::new( library, @@ -287,3 +285,17 @@ fn get_oracle_account( Ok(account) } + +fn get_foreign_account() -> Result { + let (native_account, _) = AccountBuilder::new() + .init_seed(ChaCha20Rng::from_entropy().gen()) + .with_component( + AccountMockComponent::new_with_slots(TransactionKernel::testing_assembler(), vec![]) + .unwrap(), + ) + .nonce(ONE) + .build_testing() + .unwrap(); + + Ok(native_account) +} diff --git a/src/sdk/sdk.rs b/src/sdk/sdk.rs index 72e643f..43991f7 100644 --- a/src/sdk/sdk.rs +++ b/src/sdk/sdk.rs @@ -1,5 +1,5 @@ -use pyo3::prelude::*; use pyo3::exceptions::PyModuleNotFoundError; +use pyo3::prelude::*; use pyo3::types::{PyDict, PyList}; use std::sync::Once; use thiserror::Error; From ee7e0bd25fa8c476a803b0d464aef1c7adc575d2 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Fri, 22 Nov 2024 15:25:33 +0530 Subject: [PATCH 38/45] use oracle component lib later! --- Cargo.toml | 1 + src/accounts/accounts.rs | 25 ++++++++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fde1f3e..1141f98 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ 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" } +miden-assembly = { version = "0.11.0", default-features = false } rusqlite = { version = "0.32", features = ["vtab", "array", "bundled"]} rand = "0.8" diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index 85074d1..8481bac 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -11,10 +11,11 @@ use miden_objects::{ Account, AccountBuilder, AccountCode, AccountComponent, AccountId, AccountStorage, AccountStorageMode, AccountType, AuthSecretKey, StorageSlot, }, - assembly::{Assembler, Library, LibraryNamespace, LibraryPath}, + assembly::{Assembler, Library, LibraryNamespace, LibraryPath, DefaultSourceManager}, transaction::{TransactionArgs, TransactionScript}, AccountError, Word, }; +use miden_assembly::ast::{Module, ModuleKind}; use miden_tx::{ auth::{BasicAuthenticator, TransactionAuthenticator}, TransactionExecutor, @@ -24,7 +25,7 @@ use std::collections::BTreeMap; use std::error::Error as StdError; use std::fmt; use std::str::FromStr; -use std::sync::Arc; +use std::sync::{Arc, LazyLock}; use std::{ env, io, path::{Path, PathBuf}, @@ -32,7 +33,25 @@ use std::{ // Include the oracle module source code // pub const PUSH_ORACLE_PATH: &str = "src/accounts/oracle/push_oracle.masm"; -// pub const READ_ORACLE_PATH: &str = "src/accounts/oracle/read_oracle.masm"; +// pub const READ_ORACLE_PATH: &str = "src/accounts/oracle/read_oracle.masm" + +// TODO: use component library instead of directly calling procedures +pub static ORACLE_COMPONENT_LIBRARY: LazyLock = LazyLock::new(|| { + let assembler = TransactionKernel::assembler().with_debug_mode(true); + + let source_manager = Arc::new(DefaultSourceManager::default()); + let oracle_component_module = Module::parser(ModuleKind::Library) + .parse_str( + LibraryPath::new("oracle_component::oracle_module").unwrap(), + SOURCE_CODE, + &source_manager, + ) + .unwrap(); + + assembler + .assemble_library([oracle_component_module]) + .expect("assembly should succeed") +}); /// Transaction script template for pushing data to oracle pub const PUSH_DATA_TX_SCRIPT: &str = r#" From 46f099de3de3b2ecea9c10b830d0c6ad11da97ad Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Fri, 22 Nov 2024 19:00:42 +0530 Subject: [PATCH 39/45] enable data provider public key verification when pushing --- src/accounts/accounts.rs | 21 ++++++++++----------- src/accounts/tests.rs | 29 +++++++++++++++-------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/accounts/accounts.rs b/src/accounts/accounts.rs index 8481bac..14e60e7 100644 --- a/src/accounts/accounts.rs +++ b/src/accounts/accounts.rs @@ -1,4 +1,5 @@ use super::{data_to_word, public_key_to_string, word_to_data, word_to_masm, OracleData}; +use miden_assembly::ast::{Module, ModuleKind}; use miden_client::{rpc::NodeRpcClient, store::Store, transactions::TransactionRequest, Client}; use miden_crypto::{ dsa::rpo_falcon512::{PublicKey, SecretKey}, @@ -11,11 +12,10 @@ use miden_objects::{ Account, AccountBuilder, AccountCode, AccountComponent, AccountId, AccountStorage, AccountStorageMode, AccountType, AuthSecretKey, StorageSlot, }, - assembly::{Assembler, Library, LibraryNamespace, LibraryPath, DefaultSourceManager}, + assembly::{Assembler, DefaultSourceManager, Library, LibraryNamespace, LibraryPath}, transaction::{TransactionArgs, TransactionScript}, AccountError, Word, }; -use miden_assembly::ast::{Module, ModuleKind}; use miden_tx::{ auth::{BasicAuthenticator, TransactionAuthenticator}, TransactionExecutor, @@ -65,8 +65,10 @@ begin call.[push_oracle] - #push.{data_provider_public_key} - #call.[verify_data_provider] + dropw dropw dropw dropw + + push.[data_provider_public_key] + call.[verify_data_provider] dropw dropw dropw dropw @@ -141,17 +143,14 @@ pub const SOURCE_CODE: &str = r#" # Get data provider's public key from account storage at slot 1 push.DATA_PROVIDER_PUBLIC_KEY_SLOT exec.account::get_item # => [PUB_KEY, DATA_PROVIDER_PUBLIC_KEY] + + # Verify that the data provider's public key is matching the one in the account storage + assert_eqw + # => [] # Update the nonce push.1 exec.account::incr_nonce # => [] - - push.100 mem_loadw add.1 mem_storew dropw - - # Verify that the data provider's public key is matching the one in the account storage - - - # => [] end #! Gets new price data from the oracle's data slots. diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index c9bc94d..3c1cefe 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -69,17 +69,18 @@ async fn oracle_account_creation_and_pushing_data_to_read() { "{}", PUSH_DATA_TX_SCRIPT .replace("{}", &word_to_masm(&word)) - // .replace( - // "{data_provider_public_key}", - // &public_key_to_string(&data_provider_public_key), - // ) + .replace( + "[data_provider_public_key]", + &public_key_to_string(&data_provider_public_key), + ) .replace( "[push_oracle]", &format!("{}", oracle_account.code().procedures()[1].mast_root()).to_string() - ) // .replace( - // "[verify_data_provider]", - // &format!("{}", oracle_account.code().procedures()[2].mast_root()).to_string() - // ) + ) + .replace( + "[verify_data_provider]", + &format!("{}", oracle_account.code().procedures()[2].mast_root()).to_string() + ) ); println!("Push tx script code: {}", push_tx_script_code); @@ -101,21 +102,21 @@ async fn oracle_account_creation_and_pushing_data_to_read() { // let read_data_tx_script_code = r#" // use.oracle::read_oracle - + // begin // padw padw padw push.0.0 // # => [pad(14)] - // push.{storage_item_index} - // push.{get_item_foreign_hash} + // push.{storage_item_index} + // push.{get_item_foreign_hash} // push.{account_id} // # => [foreign_account_id, FOREIGN_PROC_ROOT, storage_item_index, pad(14)] - + // call.[read_oracle] - + // # assert the correctness of the obtained value // push.{oracle_data} assert_eqw - + // call.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 // end // "#; From 009e648a2c403c6422d4d7527196511122d17563 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Sat, 23 Nov 2024 16:46:42 +0530 Subject: [PATCH 40/45] use mockchain for reading test --- src/accounts/tests.rs | 100 +++++++++++++++++++++++++++++++++++++++--- src/errors.rs | 1 - src/main.rs | 1 - 3 files changed, 93 insertions(+), 9 deletions(-) delete mode 100644 src/errors.rs diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index 3c1cefe..3cab9af 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -19,6 +19,8 @@ use miden_objects::{ accounts::AccountBuilder, assembly::{Library, LibraryNamespace}, testing::account_component::AccountMockComponent, + transaction::TransactionScript, + Digest, }; use miden_objects::{ accounts::{ @@ -29,13 +31,15 @@ use miden_objects::{ assets::AssetVault, crypto::utils::Serializable, transaction::{ExecutedTransaction, ProvenTransaction, TransactionArgs}, + vm::AdviceInputs, AccountError, }; use miden_objects::{crypto::dsa::rpo_falcon512, ONE}; use miden_tx::auth::BasicAuthenticator; use miden_tx::{ - testing::TransactionContextBuilder, LocalTransactionProver, ProvingOptions, - TransactionExecutor, TransactionProver, TransactionVerifier, TransactionVerifierError, + testing::{mock_chain::MockChain, TransactionContextBuilder}, + LocalTransactionProver, ProvingOptions, TransactionExecutor, TransactionProver, + TransactionVerifier, TransactionVerifierError, }; use rand::{rngs::StdRng, Rng}; use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; @@ -123,6 +127,13 @@ async fn oracle_account_creation_and_pushing_data_to_read() { // let foreign_account = get_foreign_account().unwrap(); + // let mut mock_chain = + // MockChain::with_accounts(&[foreign_account.clone(), oracle_account.clone()]); + + // mock_chain.seal_block(None); + + // let advice_inputs = get_mock_fpi_adv_inputs(&oracle_account, &mock_chain); + // let read_tx_script_code = format!( // "{}", // read_data_tx_script_code @@ -141,11 +152,34 @@ async fn oracle_account_creation_and_pushing_data_to_read() { // .replace("{oracle_data}", &word_to_masm(&data_to_word(&oracle_data))) // ); - // let read_tx_script = create_transaction_script(read_tx_script_code).unwrap(); - - // let txn_args = TransactionArgs::with_tx_script(read_tx_script); - // let executed_transaction = executor - // .execute_transaction(oracle_account.id(), 4, &[], txn_args) + // let read_tx_script = TransactionScript::compile(read_tx_script_code, vec![], TransactionKernel::testing_assembler()).unwrap(); + + // let tx_context = mock_chain + // .build_tx_context(foreign_account.id(), &[], &[]) + // .advice_inputs(advice_inputs.clone()) + // .tx_script(read_tx_script) + // .build(); + + // let block_ref = tx_context.tx_inputs().block_header().block_num(); + // let note_ids = tx_context + // .tx_inputs() + // .input_notes() + // .iter() + // .map(|note| note.id()) + // .collect::>(); + + // let mut executor: TransactionExecutor = + // TransactionExecutor::new(Arc::new(tx_context.clone()), None).with_tracing(); + + // executor.load_account_code(oracle_account.code()); + + // executor + // .execute_transaction( + // foreign_account.id(), + // block_ref, + // ¬e_ids, + // tx_context.tx_args().clone(), + // ) // .await // .unwrap(); @@ -300,3 +334,55 @@ fn get_foreign_account() -> Result { Ok(native_account) } + +/// Mocks the required advice inputs for foreign procedure invocation. +fn get_mock_fpi_adv_inputs(foreign_account: &Account, mock_chain: &MockChain) -> AdviceInputs { + let foreign_id_root = Digest::from([foreign_account.id().into(), ZERO, ZERO, ZERO]); + let foreign_id_and_nonce = [ + foreign_account.id().into(), + ZERO, + ZERO, + foreign_account.nonce(), + ]; + let foreign_vault_root = foreign_account.vault().commitment(); + let foreign_storage_root = foreign_account.storage().commitment(); + let foreign_code_root = foreign_account.code().commitment(); + + let mut inputs = AdviceInputs::default() + .with_map([ + // ACCOUNT_ID |-> [ID_AND_NONCE, VAULT_ROOT, STORAGE_ROOT, CODE_ROOT] + ( + foreign_id_root, + [ + &foreign_id_and_nonce, + foreign_vault_root.as_elements(), + foreign_storage_root.as_elements(), + foreign_code_root.as_elements(), + ] + .concat(), + ), + // STORAGE_ROOT |-> [[STORAGE_SLOT_DATA]] + ( + foreign_storage_root, + foreign_account.storage().as_elements(), + ), + // CODE_ROOT |-> [[ACCOUNT_PROCEDURE_DATA]] + (foreign_code_root, foreign_account.code().as_elements()), + ]) + .with_merkle_store(mock_chain.accounts().into()); + + for slot in foreign_account.storage().slots() { + // if there are storage maps, we populate the merkle store and advice map + if let StorageSlot::Map(map) = slot { + // extend the merkle store and map with the storage maps + inputs.extend_merkle_store(map.inner_nodes()); + // populate advice map with Sparse Merkle Tree leaf nodes + inputs.extend_map( + map.leaves() + .map(|(_, leaf)| (leaf.hash(), leaf.to_elements())), + ); + } + } + + inputs +} diff --git a/src/errors.rs b/src/errors.rs deleted file mode 100644 index 8b13789..0000000 --- a/src/errors.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/main.rs b/src/main.rs index 487a219..8c71c6e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ mod accounts; mod cli; mod commands; -mod errors; mod sdk; mod setup; From 4dc4cf4b0129f4bb794c2cb65fd04bf9b77f3908 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Sat, 23 Nov 2024 16:55:22 +0530 Subject: [PATCH 41/45] nits --- .github/workflows/build_and_test.yml | 2 +- src/setup.rs | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 50050ba..55797a9 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -42,4 +42,4 @@ jobs: run: pragma-miden sync - name: Run tests - run: cargo test --verbose + run: cargo test diff --git a/src/setup.rs b/src/setup.rs index 261c8e3..a217469 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -9,8 +9,7 @@ use miden_client::{ Client, Felt, }; use rand::Rng; -use std::rc::Rc; -use std::sync::Arc; +use std::{sync::Arc, rc::Rc}; // seting up Miden Client pub async fn setup_client() -> Client { @@ -26,7 +25,6 @@ pub async fn setup_client() -> Client { }; 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( From fb78fd2a2354c4f2743df748d8866fb53d500dae Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Tue, 26 Nov 2024 14:18:48 +0530 Subject: [PATCH 42/45] working on read test --- README.md | 2 +- src/accounts/tests.rs | 187 +++++++++++++++++++++--------------------- store.sqlite3 | Bin 135168 -> 131072 bytes 3 files changed, 96 insertions(+), 93 deletions(-) diff --git a/README.md b/README.md index c4d0ca3..adbb010 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ The project is organized as follows: |----------------------------|--------| | Oracle Account | ✅ | | Publisher Registry Account | ❌ | -| Python SDK | ❌ | +| Python SDK | ✅ | ## Getting Started diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index 3cab9af..6c972f5 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -37,7 +37,7 @@ use miden_objects::{ use miden_objects::{crypto::dsa::rpo_falcon512, ONE}; use miden_tx::auth::BasicAuthenticator; use miden_tx::{ - testing::{mock_chain::MockChain, TransactionContextBuilder}, + testing::{mock_chain::{MockChain, MockChainBuilder}, TransactionContextBuilder}, LocalTransactionProver, ProvingOptions, TransactionExecutor, TransactionProver, TransactionVerifier, TransactionVerifierError, }; @@ -63,11 +63,10 @@ async fn oracle_account_creation_and_pushing_data_to_read() { publisher_id: 1, }; - let mut word = data_to_word(&oracle_data); - word[0] = Felt::new(1); + let word = data_to_word(&oracle_data); - 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_context = Arc::new(TransactionContextBuilder::new(oracle_account.clone()).build()); + let push_executor = TransactionExecutor::new(push_tx_context, Some(Arc::new(oracle_auth.clone()))); let push_tx_script_code = format!( "{}", @@ -91,101 +90,105 @@ async fn oracle_account_creation_and_pushing_data_to_read() { let push_tx_script = create_transaction_script(push_tx_script_code).unwrap(); - let txn_args = TransactionArgs::with_tx_script(push_tx_script); - let executed_transaction = executor - .execute_transaction(oracle_account.id(), 4, &[], txn_args) + let push_txn_args = TransactionArgs::with_tx_script(push_tx_script); + let push_executed_transaction = push_executor + .execute_transaction(oracle_account.id(), 4, &[], push_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()); + println!("Account Delta: {:?}", push_executed_transaction.account_delta()); - assert!(prove_and_verify_transaction(executed_transaction.clone()) + assert!(prove_and_verify_transaction(push_executed_transaction.clone()) .await .is_ok()); + + let read_data_tx_script_code = r#" + use.oracle::read_oracle + + begin + padw padw padw push.0.0 + # => [pad(14)] + + push.{storage_item_index} + push.{get_item_foreign_hash} + push.{account_id} + # => [foreign_account_id, FOREIGN_PROC_ROOT, storage_item_index, pad(14)] + + call.[read_oracle] + + # assert the correctness of the obtained value + push.{oracle_data} assert_eqw + + call.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 + end + "#; + + let foreign_account = get_foreign_account().unwrap(); + + let read_tx_script_code = format!( + "{}", + read_data_tx_script_code + .replace("{storage_item_index}", "2") + .replace( + "{get_item_foreign_hash}", + &oracle_account.code().procedures()[1] + .mast_root() + .to_string(), + ) + .replace("{account_id}", &foreign_account.id().to_string()) + .replace( + "[read_oracle]", + &format!("{}", oracle_account.code().procedures()[3].mast_root()), + ) + .replace("{oracle_data}", &word_to_masm(&data_to_word(&oracle_data))) + ); - // let read_data_tx_script_code = r#" - // use.oracle::read_oracle - - // begin - // padw padw padw push.0.0 - // # => [pad(14)] - - // push.{storage_item_index} - // push.{get_item_foreign_hash} - // push.{account_id} - // # => [foreign_account_id, FOREIGN_PROC_ROOT, storage_item_index, pad(14)] - - // call.[read_oracle] - - // # assert the correctness of the obtained value - // push.{oracle_data} assert_eqw - - // call.::miden::contracts::auth::basic::auth_tx_rpo_falcon512 - // end - // "#; - - // let foreign_account = get_foreign_account().unwrap(); - - // let mut mock_chain = - // MockChain::with_accounts(&[foreign_account.clone(), oracle_account.clone()]); - - // mock_chain.seal_block(None); - - // let advice_inputs = get_mock_fpi_adv_inputs(&oracle_account, &mock_chain); - - // let read_tx_script_code = format!( - // "{}", - // read_data_tx_script_code - // .replace("{storage_item_index}", "2") - // .replace( - // "{get_item_foreign_hash}", - // &oracle_account.code().procedures()[1] - // .mast_root() - // .to_string(), - // ) - // .replace("{account_id}", &foreign_account.id().to_string()) - // .replace( - // "[read_oracle]", - // &format!("{}", oracle_account.code().procedures()[3].mast_root()), - // ) - // .replace("{oracle_data}", &word_to_masm(&data_to_word(&oracle_data))) - // ); - - // let read_tx_script = TransactionScript::compile(read_tx_script_code, vec![], TransactionKernel::testing_assembler()).unwrap(); - - // let tx_context = mock_chain - // .build_tx_context(foreign_account.id(), &[], &[]) - // .advice_inputs(advice_inputs.clone()) - // .tx_script(read_tx_script) - // .build(); - - // let block_ref = tx_context.tx_inputs().block_header().block_num(); - // let note_ids = tx_context - // .tx_inputs() - // .input_notes() - // .iter() - // .map(|note| note.id()) - // .collect::>(); - - // let mut executor: TransactionExecutor = - // TransactionExecutor::new(Arc::new(tx_context.clone()), None).with_tracing(); - - // executor.load_account_code(oracle_account.code()); - - // executor - // .execute_transaction( - // foreign_account.id(), - // block_ref, - // ¬e_ids, - // tx_context.tx_args().clone(), - // ) - // .await - // .unwrap(); - - // assert!(prove_and_verify_transaction(executed_transaction.clone()) - // .await - // .is_ok()); + let mut mock_chain = MockChainBuilder::default() + .accounts(vec![foreign_account.clone(), oracle_account.clone()]) + .starting_block_num(1) + .build(); + + println!("Mock chain: {:?}", mock_chain.accounts()); + + mock_chain.seal_block(Some(2)); + + let advice_inputs = get_mock_fpi_adv_inputs(&oracle_account, &mock_chain); + + let read_tx_script = create_transaction_script(read_tx_script_code).unwrap(); + + let read_tx_context = mock_chain + .build_tx_context(foreign_account.id()) + .advice_inputs(advice_inputs.clone()) + .tx_script(read_tx_script) + .build(); + + let block_ref = read_tx_context.tx_inputs().block_header().block_num(); + let note_ids = read_tx_context + .tx_inputs() + .input_notes() + .iter() + .map(|note| note.id()) + .collect::>(); + let read_txn_args = read_tx_context.tx_args().clone(); + + let mut read_executor = TransactionExecutor::new(Arc::new(read_tx_context.clone()), Some(Arc::new(oracle_auth.clone()))); + + read_executor.load_account_code(oracle_account.code()); + + let read_executed_transaction = read_executor + .execute_transaction( + foreign_account.id(), + block_ref, + ¬e_ids, + read_txn_args, + ) + .await + .unwrap(); + + assert!(prove_and_verify_transaction(read_executed_transaction.clone()) + .await + .is_ok()); } #[test] diff --git a/store.sqlite3 b/store.sqlite3 index 6645f31f3e1a2e10569e84d530dd952ae73d575d..670445db1c4914a006a83a022abbc9d588a5ca05 100644 GIT binary patch delta 6210 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 NhQs4YmR~m^{{xIa8~XqN literal 135168 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%0D$>%bKA^lUr21)Uzpw-H z7LY3@h=wuZUCZD_09%MzmKd6qyO==LrPDPrRq9NnQB#AWz|af6`)Bx^DwX?V^qysW8COo?w)ee$=R(trn(F0#;>we(GGNbE#_0r@Ni3 zdTr)WwpuqQm=cV^-KcsD*QjvK3|dS|9?|gI8Yc8Kmter2_OL^fCP{L5+Gy-@ct`kO3gYe4} zAn0R*VFWdUsU%~&-ADwrX-5l#KtO*j5!9xPRz#!QBtAC)B@u2VA!J$ypo!IbBDho9 z2x`+3r+-Kjjlt8Dy2r#xlA`vQ6F1I+B+eZB-;{%Y!@MtJ=}{4T~P>HNuy3i$aZ=jf_RA#ZkrB& z6uqiQ7E67Z-F4IFqbTstM<6fnAGsWxlXLtc?+?p)jT%JW4lZGySieqXZg+@P@U{Vqmw($`Vu55my z2xRgN^~%!GNh$=)UUi4XxuHB=z-;A7wYvNs!)fVmlhf)fD>Locz^az*3hbwG_mf8p z43(O^KBF2{c4mNimQr5hK0jSi*rykEeWKe&G5N{J{}5k2T`e)1+Bcv|XK}i^*EVvZ z5~jviJ=fw~SC$T6vcP^%^0=h;+p}4l*i*~EvC7jzj~h3rw`*#2xcyk*+HiXyf*-r*vKUcX|XKb~U%ufK!ap51!eo>eMa46>cfNOB7_FqXMD zxHTUB{r_Kltc4js0!RP}AOR$R1dsp{Kmter2_OL^@TC*LzyJTz5u*YmfCP{L5fB!!L2%aJVB!C2v01`j~NB{{S0VIF~kN^_6 z4GG};|J$%qu}DY&2_OL^fCP{L5 Date: Tue, 26 Nov 2024 14:23:42 +0530 Subject: [PATCH 43/45] nit --- store.sqlite3 | Bin 131072 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 store.sqlite3 diff --git a/store.sqlite3 b/store.sqlite3 deleted file mode 100644 index 670445db1c4914a006a83a022abbc9d588a5ca05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131072 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 From f42c7e41042a7476ed54611fed66ad10e4e1a1eb Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Tue, 26 Nov 2024 17:11:39 +0530 Subject: [PATCH 44/45] use next branch for miden-lib --- Cargo.toml | 6 +++--- src/accounts/tests.rs | 15 +++++---------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1141f98..b51d8bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,12 +10,12 @@ testing = ["miden-tx/testing"] [dependencies] 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-lib = { git = "https://github.com/0xPolygonMiden/miden-base", branch = "next", default-features = false, features = ["concurrent", "testing"] } +miden-objects = { version = "0.6.0", default-features = false } miden-tx = { version = "0.6", features = ["testing"] } miden-air = { version = "0.11", default-features = false } miden-cli = { version = "0.6" } -miden-assembly = { version = "0.11.0", default-features = false } +miden-assembly = { version = "0.11", default-features = false, features = ["testing"] } rusqlite = { version = "0.32", features = ["vtab", "array", "bundled"]} rand = "0.8" diff --git a/src/accounts/tests.rs b/src/accounts/tests.rs index 6c972f5..71d6307 100644 --- a/src/accounts/tests.rs +++ b/src/accounts/tests.rs @@ -144,21 +144,16 @@ async fn oracle_account_creation_and_pushing_data_to_read() { .replace("{oracle_data}", &word_to_masm(&data_to_word(&oracle_data))) ); - let mut mock_chain = MockChainBuilder::default() - .accounts(vec![foreign_account.clone(), oracle_account.clone()]) - .starting_block_num(1) - .build(); - - println!("Mock chain: {:?}", mock_chain.accounts()); + let mut mock_chain = + MockChain::with_accounts(&[foreign_account.clone(), oracle_account.clone()]); - mock_chain.seal_block(Some(2)); + mock_chain.seal_block(None); let advice_inputs = get_mock_fpi_adv_inputs(&oracle_account, &mock_chain); - let read_tx_script = create_transaction_script(read_tx_script_code).unwrap(); - + let read_tx_script = TransactionScript::compile(read_tx_script_code, vec![], TransactionKernel::testing_assembler()).unwrap(); let read_tx_context = mock_chain - .build_tx_context(foreign_account.id()) + .build_tx_context(foreign_account.id(), &[], &[]) .advice_inputs(advice_inputs.clone()) .tx_script(read_tx_script) .build(); From 3228268f3b3e5c71546ff3a5405ff9d9f53f09f5 Mon Sep 17 00:00:00 2001 From: Harsh Pratap Singh Date: Tue, 26 Nov 2024 17:21:34 +0530 Subject: [PATCH 45/45] nits --- Cargo.toml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b51d8bb..3156cd7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,19 +6,20 @@ authors = ["Harsh Pratap Singh "] [features] testing = ["miden-tx/testing"] +default = ["rand_chacha"] [dependencies] miden-client = { version = "0.6", features = ["concurrent", "testing", "sqlite", "tonic"] } miden-crypto = { version = "0.12", default-features = false } miden-lib = { git = "https://github.com/0xPolygonMiden/miden-base", branch = "next", default-features = false, features = ["concurrent", "testing"] } -miden-objects = { version = "0.6.0", default-features = false } -miden-tx = { version = "0.6", features = ["testing"] } +miden-objects = { git = "https://github.com/0xPolygonMiden/miden-base", branch = "next", default-features = false, features = ["concurrent", "testing"] } +miden-tx = { git = "https://github.com/0xPolygonMiden/miden-base", branch = "next", features = ["concurrent", "testing"] } miden-air = { version = "0.11", default-features = false } miden-cli = { version = "0.6" } miden-assembly = { version = "0.11", default-features = false, features = ["testing"] } rusqlite = { version = "0.32", features = ["vtab", "array", "bundled"]} -rand = "0.8" +rand = { version = "0.8", default-features = false } tonic = { version = "0.12.3" } tokio = { version = "1.40.0", features = ["rt-multi-thread", "net", "macros"] } clap = { version = "4.5.20", features = ["derive"] } @@ -30,7 +31,7 @@ tracing = { version = "0.1.40" } tracing-subscriber = { version = "0.3" } winter-maybe-async = "0.10" hex = "0.4.3" -rand_chacha = "0.3" +rand_chacha = { version = "0.3", default-features = false, optional = true } once_cell = "1.18" pyo3 = { version = "0.22.6", features = ["auto-initialize"] } tokio-stream = "0.1.1"