From faa782b982e49f51d5f1db11cc03857f2dbdb758 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Thu, 26 Dec 2024 11:38:00 +0200 Subject: [PATCH] fix: final subcenario version --- Cargo.lock | 2 + Cargo.toml | 1 + node_core/Cargo.toml | 1 + node_core/src/lib.rs | 296 ++++++++++++++++-------------- node_core/src/storage/mod.rs | 33 ++-- node_rpc/src/process.rs | 29 ++- node_rpc/src/types/rpc_structs.rs | 11 ++ 7 files changed, 218 insertions(+), 155 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c400d75..42d86f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,6 +145,7 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" dependencies = [ + "actix-macros", "futures-core", "tokio", ] @@ -2670,6 +2671,7 @@ name = "node_core" version = "0.1.0" dependencies = [ "accounts", + "actix-rt", "anyhow", "bincode", "elliptic-curve", diff --git a/Cargo.toml b/Cargo.toml index efb70ae..e04fca5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ serde_json = "1.0.81" actix = "0.13.0" actix-cors = "0.6.1" futures = "0.3" +actix-rt = "*" env_logger = "0.10" log = "0.4" diff --git a/node_core/Cargo.toml b/node_core/Cargo.toml index e26c723..61fcc28 100644 --- a/node_core/Cargo.toml +++ b/node_core/Cargo.toml @@ -21,6 +21,7 @@ tokio.workspace = true tempfile.workspace = true risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-1.2" } hex.workspace = true +actix-rt.workspace = true [dependencies.accounts] path = "../accounts" diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index baefad6..1d5455b 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -142,8 +142,13 @@ impl NodeCore { addr } - pub async fn mint_utxo_private(&self, acc: AccountAddress, amount: u128) -> Transaction { + pub async fn mint_utxo_private( + &self, + acc: AccountAddress, + amount: u128, + ) -> (Transaction, [u8; 32]) { let (utxo, receipt) = prove_mint_utxo(amount, acc); + let result_hash = utxo.hash; let acc_map_read_guard = self.storage.read().await; @@ -161,21 +166,24 @@ impl NodeCore { let comm = generate_commitments(&vec![utxo]); - TransactionPayload { - tx_kind: TxKind::Private, - execution_input: vec![], - execution_output: vec![], - utxo_commitments_spent_hashes: vec![], - utxo_commitments_created_hashes: comm - .into_iter() - .map(|hash_data| hash_data.try_into().unwrap()) - .collect(), - nullifier_created_hashes: vec![], - execution_proof_private: serde_json::to_string(&receipt).unwrap(), - encoded_data: vec![(encoded_data.0, encoded_data.1.to_vec())], - ephemeral_pub_key: eph_pub_key.to_vec(), - } - .into() + ( + TransactionPayload { + tx_kind: TxKind::Private, + execution_input: vec![], + execution_output: vec![], + utxo_commitments_spent_hashes: vec![], + utxo_commitments_created_hashes: comm + .into_iter() + .map(|hash_data| hash_data.try_into().unwrap()) + .collect(), + nullifier_created_hashes: vec![], + execution_proof_private: serde_json::to_string(&receipt).unwrap(), + encoded_data: vec![(encoded_data.0, encoded_data.1.to_vec())], + ephemeral_pub_key: eph_pub_key.to_vec(), + } + .into(), + result_hash, + ) } pub fn deposit_money_public(&self, acc: AccountAddress, amount: u128) -> Transaction { @@ -200,7 +208,7 @@ impl NodeCore { &self, utxo: UTXO, receivers: Vec<(u128, AccountAddress)>, - ) -> Transaction { + ) -> (Transaction, Vec<(AccountAddress, [u8; 32])>) { let acc_map_read_guard = self.storage.read().await; let accout = acc_map_read_guard.acc_map.get(&utxo.owner).unwrap(); @@ -222,6 +230,10 @@ impl NodeCore { ); let (resulting_utxos, receipt) = prove_send_utxo(utxo, receivers); + let utxo_hashes = resulting_utxos + .iter() + .map(|(utxo, addr)| (addr.clone(), utxo.hash)) + .collect(); let utxos: Vec = resulting_utxos .iter() @@ -249,21 +261,24 @@ impl NodeCore { let commitments = generate_commitments(&utxos); - TransactionPayload { - tx_kind: TxKind::Private, - execution_input: vec![], - execution_output: vec![], - utxo_commitments_spent_hashes: vec![commitment_in], - utxo_commitments_created_hashes: commitments - .into_iter() - .map(|hash_data| hash_data.try_into().unwrap()) - .collect(), - nullifier_created_hashes: vec![nullifier.try_into().unwrap()], - execution_proof_private: serde_json::to_string(&receipt).unwrap(), - encoded_data, - ephemeral_pub_key: eph_pub_key.to_vec(), - } - .into() + ( + TransactionPayload { + tx_kind: TxKind::Private, + execution_input: vec![], + execution_output: vec![], + utxo_commitments_spent_hashes: vec![commitment_in], + utxo_commitments_created_hashes: commitments + .into_iter() + .map(|hash_data| hash_data.try_into().unwrap()) + .collect(), + nullifier_created_hashes: vec![nullifier.try_into().unwrap()], + execution_proof_private: serde_json::to_string(&receipt).unwrap(), + encoded_data, + ephemeral_pub_key: eph_pub_key.to_vec(), + } + .into(), + utxo_hashes, + ) } pub async fn transfer_balance_shielded( @@ -271,7 +286,7 @@ impl NodeCore { acc: AccountAddress, balance: u64, receivers: Vec<(u128, AccountAddress)>, - ) -> Transaction { + ) -> (Transaction, Vec<(AccountAddress, [u8; 32])>) { let acc_map_read_guard = self.storage.read().await; let accout = acc_map_read_guard.acc_map.get(&acc).unwrap(); @@ -304,6 +319,10 @@ impl NodeCore { ); let (resulting_utxos, receipt) = prove_send_utxo_shielded(acc, balance as u128, receivers); + let utxo_hashes = resulting_utxos + .iter() + .map(|(utxo, addr)| (addr.clone(), utxo.hash)) + .collect(); let utxos: Vec = resulting_utxos .iter() @@ -331,27 +350,30 @@ impl NodeCore { let commitments = generate_commitments(&utxos); - TransactionPayload { - tx_kind: TxKind::Private, - execution_input: serde_json::to_vec(&ActionData::SendMoneyShieldedTx( - SendMoneyShieldedTx { - acc_sender: acc, - amount: balance as u128, - }, - )) - .unwrap(), - execution_output: vec![], - utxo_commitments_spent_hashes: vec![], - utxo_commitments_created_hashes: commitments - .into_iter() - .map(|hash_data| hash_data.try_into().unwrap()) - .collect(), - nullifier_created_hashes: vec![nullifier.try_into().unwrap()], - execution_proof_private: serde_json::to_string(&receipt).unwrap(), - encoded_data, - ephemeral_pub_key: eph_pub_key.to_vec(), - } - .into() + ( + TransactionPayload { + tx_kind: TxKind::Private, + execution_input: serde_json::to_vec(&ActionData::SendMoneyShieldedTx( + SendMoneyShieldedTx { + acc_sender: acc, + amount: balance as u128, + }, + )) + .unwrap(), + execution_output: vec![], + utxo_commitments_spent_hashes: vec![], + utxo_commitments_created_hashes: commitments + .into_iter() + .map(|hash_data| hash_data.try_into().unwrap()) + .collect(), + nullifier_created_hashes: vec![nullifier.try_into().unwrap()], + execution_proof_private: serde_json::to_string(&receipt).unwrap(), + encoded_data, + ephemeral_pub_key: eph_pub_key.to_vec(), + } + .into(), + utxo_hashes, + ) } pub async fn transfer_utxo_deshielded( @@ -379,14 +401,14 @@ impl NodeCore { .to_vec(), ); - let (resulting_utxos, receipt) = prove_send_utxo_deshielded(utxo, receivers); + let (resulting_balances, receipt) = prove_send_utxo_deshielded(utxo, receivers); TransactionPayload { tx_kind: TxKind::Private, execution_input: vec![], execution_output: serde_json::to_vec(&ActionData::SendMoneyDeshieldedTx( SendMoneyDeshieldedTx { - receiver_data: resulting_utxos, + receiver_data: resulting_balances, }, )) .unwrap(), @@ -404,11 +426,15 @@ impl NodeCore { &self, acc: AccountAddress, amount: u128, - ) -> Result { - Ok(self - .sequencer_client - .send_tx(self.mint_utxo_private(acc, amount).await) - .await?) + ) -> Result<(SendTxResponse, [u8; 32])> { + let point_before_prove = std::time::Instant::now(); + let (tx, utxo_hash) = self.mint_utxo_private(acc, amount).await; + let point_after_prove = std::time::Instant::now(); + + let timedelta = (point_after_prove - point_before_prove).as_millis(); + info!("Mint utxo proof spent {timedelta:?} milliseconds"); + + Ok((self.sequencer_client.send_tx(tx).await?, utxo_hash)) } pub async fn send_public_deposit( @@ -426,11 +452,15 @@ impl NodeCore { &self, utxo: UTXO, receivers: Vec<(u128, AccountAddress)>, - ) -> Result { - Ok(self - .sequencer_client - .send_tx(self.transfer_utxo_private(utxo, receivers).await) - .await?) + ) -> Result<(SendTxResponse, Vec<([u8; 32], [u8; 32])>)> { + let point_before_prove = std::time::Instant::now(); + let (tx, utxo_hashes) = self.transfer_utxo_private(utxo, receivers).await; + let point_after_prove = std::time::Instant::now(); + + let timedelta = (point_after_prove - point_before_prove).as_millis(); + info!("Send private utxo proof spent {timedelta:?} milliseconds"); + + Ok((self.sequencer_client.send_tx(tx).await?, utxo_hashes)) } pub async fn send_shielded_send_tx( @@ -438,11 +468,15 @@ impl NodeCore { acc: AccountAddress, amount: u64, receivers: Vec<(u128, AccountAddress)>, - ) -> Result { - Ok(self - .sequencer_client - .send_tx(self.transfer_balance_shielded(acc, amount, receivers).await) - .await?) + ) -> Result<(SendTxResponse, Vec<([u8; 32], [u8; 32])>)> { + let point_before_prove = std::time::Instant::now(); + let (tx, utxo_hashes) = self.transfer_balance_shielded(acc, amount, receivers).await; + let point_after_prove = std::time::Instant::now(); + + let timedelta = (point_after_prove - point_before_prove).as_millis(); + info!("Send balance shielded proof spent {timedelta:?} milliseconds"); + + Ok((self.sequencer_client.send_tx(tx).await?, utxo_hashes)) } pub async fn send_deshielded_send_tx( @@ -450,24 +484,23 @@ impl NodeCore { utxo: UTXO, receivers: Vec<(u128, AccountAddress)>, ) -> Result { - Ok(self - .sequencer_client - .send_tx(self.transfer_utxo_deshielded(utxo, receivers).await) - .await?) + let point_before_prove = std::time::Instant::now(); + let tx = self.transfer_utxo_deshielded(utxo, receivers).await; + let point_after_prove = std::time::Instant::now(); + + let timedelta = (point_after_prove - point_before_prove).as_millis(); + info!("Send deshielded utxo proof spent {timedelta:?} milliseconds"); + + Ok(self.sequencer_client.send_tx(tx).await?) } ///Mint utxo, make it public pub async fn subscenario_1(&mut self) { let acc_addr = self.create_new_account().await; - let resp = self.send_private_mint_tx(acc_addr, 100).await.unwrap(); + let (resp, new_utxo_hash) = self.send_private_mint_tx(acc_addr, 100).await.unwrap(); info!("Response for mint private is {resp:?}"); - let new_utxo_hash: [u8; 32] = hex::decode(resp.additional_data.unwrap()) - .unwrap() - .try_into() - .unwrap(); - info!("Awaiting new blocks"); tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; @@ -512,16 +545,13 @@ impl NodeCore { info!("New acconut public balance is {:?}", acc.balance); - let resp = self + let (resp, new_utxo_hashes) = self .send_shielded_send_tx(acc_addr, 100, vec![(100, acc_addr)]) .await .unwrap(); info!("Response for send shielded is {resp:?}"); - let new_utxo_hash: [u8; 32] = hex::decode(resp.additional_data.unwrap()) - .unwrap() - .try_into() - .unwrap(); + let new_utxo_hash = new_utxo_hashes[0].1; info!("Awaiting new blocks"); tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; @@ -545,14 +575,9 @@ impl NodeCore { let acc_addr = self.create_new_account().await; let acc_addr_rec = self.create_new_account().await; - let resp = self.send_private_mint_tx(acc_addr, 100).await.unwrap(); + let (resp, new_utxo_hash) = self.send_private_mint_tx(acc_addr, 100).await.unwrap(); info!("Response for mint private is {resp:?}"); - let new_utxo_hash: [u8; 32] = hex::decode(resp.additional_data.unwrap()) - .unwrap() - .try_into() - .unwrap(); - info!("Awaiting new blocks"); tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; @@ -568,16 +593,13 @@ impl NodeCore { .clone() }; - let resp = self + let (resp, new_utxo_hashes) = self .send_private_send_tx(new_utxo, vec![(100, acc_addr_rec)]) .await .unwrap(); info!("Response for send deshielded is {resp:?}"); - let new_utxo_hash: [u8; 32] = hex::decode(resp.additional_data.unwrap()) - .unwrap() - .try_into() - .unwrap(); + let new_utxo_hash = new_utxo_hashes[0].1; info!("Awaiting new blocks"); tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; @@ -613,16 +635,13 @@ impl NodeCore { info!("New acconut public balance is {:?}", acc.balance); - let resp = self + let (resp, new_utxo_hashes) = self .send_shielded_send_tx(acc_addr, 100, vec![(100, acc_addr_rec)]) .await .unwrap(); info!("Response for send shielded is {resp:?}"); - let new_utxo_hash: [u8; 32] = hex::decode(resp.additional_data.unwrap()) - .unwrap() - .try_into() - .unwrap(); + let new_utxo_hash = new_utxo_hashes[0].1; info!("Awaiting new blocks"); tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; @@ -642,46 +661,41 @@ impl NodeCore { info!("User {acc_addr_rec:?} received new utxo {new_utxo:?}"); } - ///Mint utxo, deshielded send it to another user - pub async fn subscenario_5(&mut self) { - let acc_addr = self.create_new_account().await; - let acc_addr_rec = self.create_new_account().await; - - let resp = self.send_private_mint_tx(acc_addr, 100).await.unwrap(); - info!("Response for mint private is {resp:?}"); - - let new_utxo_hash: [u8; 32] = hex::decode(resp.additional_data.unwrap()) + ///Mint utxo, deshielded send it to another user + pub async fn subscenario_5(&mut self) { + let acc_addr = self.create_new_account().await; + let acc_addr_rec = self.create_new_account().await; + + let (resp, new_utxo_hash) = self.send_private_mint_tx(acc_addr, 100).await.unwrap(); + info!("Response for mint private is {resp:?}"); + + info!("Awaiting new blocks"); + tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; + + let new_utxo = { + let mut write_guard = self.storage.write().await; + + let acc = write_guard.acc_map.get_mut(&acc_addr).unwrap(); + + acc.utxo_tree + .get_item(new_utxo_hash) .unwrap() - .try_into() - .unwrap(); - - info!("Awaiting new blocks"); - tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; - - let new_utxo = { - let mut write_guard = self.storage.write().await; - - let acc = write_guard.acc_map.get_mut(&acc_addr).unwrap(); - - acc.utxo_tree - .get_item(new_utxo_hash) - .unwrap() - .unwrap() - .clone() - }; - - let resp = self - .send_deshielded_send_tx(new_utxo, vec![(100, acc_addr_rec)]) - .await - .unwrap(); - info!("Response for send deshielded is {resp:?}"); - - info!("Awaiting new blocks"); - tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; + .unwrap() + .clone() + }; - let read_guard = self.storage.read().await; - let acc_rec = read_guard.acc_map.get(&acc_addr_rec).unwrap(); + let resp = self + .send_deshielded_send_tx(new_utxo, vec![(100, acc_addr_rec)]) + .await + .unwrap(); + info!("Response for send deshielded is {resp:?}"); - info!("New account public balance is {:?}", acc_rec.balance); - } + info!("Awaiting new blocks"); + tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; + + let read_guard = self.storage.read().await; + let acc_rec = read_guard.acc_map.get(&acc_addr_rec).unwrap(); + + info!("New account public balance is {:?}", acc_rec.balance); + } } diff --git a/node_core/src/storage/mod.rs b/node_core/src/storage/mod.rs index 3af3fe5..93abee2 100644 --- a/node_core/src/storage/mod.rs +++ b/node_core/src/storage/mod.rs @@ -70,8 +70,9 @@ impl NodeChainStore { .collect(), )?; - let slice_try: Result<[u8; 33],_> = tx.ephemeral_pub_key.clone().try_into(); - let eph_key_compressed = slice_try.and_then(|inner| Ok(::Repr::from(inner))); + let slice_try: Result<[u8; 33], _> = tx.ephemeral_pub_key.clone().try_into(); + let eph_key_compressed = + slice_try.and_then(|inner| Ok(::Repr::from(inner))); if let Ok(eph_key_compressed) = eph_key_compressed { let ephemeral_public_key_sender = AffinePoint::from_bytes(&eph_key_compressed); @@ -80,22 +81,28 @@ impl NodeChainStore { let ephemeral_public_key_sender = ephemeral_public_key_sender.unwrap(); for (ciphertext, nonce) in tx.encoded_data.clone() { + let slice = nonce.as_slice(); + let nonce = + accounts::key_management::constants_types::Nonce::clone_from_slice( + slice, + ); - let slice = nonce.as_slice(); - let nonce = accounts::key_management::constants_types::Nonce::clone_from_slice(slice); + for (acc_id, acc) in self.acc_map.iter_mut() { + let decoded_data_curr_acc = acc.decrypt_data( + ephemeral_public_key_sender, + ciphertext.clone(), + nonce, + ); - for (acc_id, acc) in self.acc_map.iter_mut() { - let decoded_data_curr_acc = - acc.decrypt_data(ephemeral_public_key_sender, ciphertext.clone(), nonce); - - let decoded_utxo_try = serde_json::from_slice::(&decoded_data_curr_acc); + let decoded_utxo_try = + serde_json::from_slice::(&decoded_data_curr_acc); - if let Ok(utxo) = decoded_utxo_try { - if &utxo.owner == acc_id { - acc.utxo_tree.insert_item(utxo)?; - } + if let Ok(utxo) = decoded_utxo_try { + if &utxo.owner == acc_id { + acc.utxo_tree.insert_item(utxo)?; } } + } } } } diff --git a/node_rpc/src/process.rs b/node_rpc/src/process.rs index af3a2a3..8622f60 100644 --- a/node_rpc/src/process.rs +++ b/node_rpc/src/process.rs @@ -11,7 +11,10 @@ use crate::{ rpc_error_responce_inverter, types::{ err_rpc::cast_seq_client_error_into_rpc_error, - rpc_structs::{RegisterAccountRequest, RegisterAccountResponse, SendTxRequest}, + rpc_structs::{ + ExecuteSubscenarioRequest, ExecuteSubscenarioResponse, RegisterAccountRequest, + RegisterAccountResponse, SendTxRequest, + }, }, }; @@ -34,6 +37,29 @@ impl JsonHandler { } } + async fn process_request_execute_subscenario(&self, request: Request) -> Result { + let req = ExecuteSubscenarioRequest::parse(Some(request.params))?; + + { + let mut store = self.node_chain_store.lock().await; + + match req.scenario_id { + 1 => store.subscenario_1().await, + 2 => store.subscenario_2().await, + 3 => store.subscenario_3().await, + 4 => store.subscenario_4().await, + 5 => store.subscenario_5().await, + _ => return Err(RpcErr(RpcError::invalid_params("Scenario id not found"))), + } + } + + let helperstruct = ExecuteSubscenarioResponse { + scenario_result: "success".to_string(), + }; + + respond(helperstruct) + } + async fn process_register_account(&self, request: Request) -> Result { let _req = RegisterAccountRequest::parse(Some(request.params))?; @@ -74,6 +100,7 @@ impl JsonHandler { match request.method.as_ref() { //Todo : Add handling of more JSON RPC methods "register_account" => self.process_register_account(request).await, + "execute_subscenario" => self.process_request_execute_subscenario(request).await, "send_tx" => self.process_send_tx(request).await, _ => Err(RpcErr(RpcError::method_not_found(request.method))), } diff --git a/node_rpc/src/types/rpc_structs.rs b/node_rpc/src/types/rpc_structs.rs index 201e518..ce1a43e 100644 --- a/node_rpc/src/types/rpc_structs.rs +++ b/node_rpc/src/types/rpc_structs.rs @@ -20,6 +20,11 @@ pub struct GetBlockDataRequest { pub block_id: u64, } +#[derive(Serialize, Deserialize, Debug)] +pub struct ExecuteSubscenarioRequest { + pub scenario_id: u64, +} + #[derive(Serialize, Deserialize, Debug)] pub struct GetGenesisIdRequest {} @@ -27,6 +32,7 @@ parse_request!(RegisterAccountRequest); parse_request!(SendTxRequest); parse_request!(GetBlockDataRequest); parse_request!(GetGenesisIdRequest); +parse_request!(ExecuteSubscenarioRequest); #[derive(Serialize, Deserialize, Debug)] pub struct HelloResponse { @@ -48,6 +54,11 @@ pub struct GetBlockDataResponse { pub block: Block, } +#[derive(Serialize, Deserialize, Debug)] +pub struct ExecuteSubscenarioResponse { + pub scenario_result: String, +} + #[derive(Serialize, Deserialize, Debug)] pub struct GetGenesisIdResponse { pub genesis_id: u64,