diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index 8e36dc5..63bbbc1 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -2,24 +2,18 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use accounts::account_core::{address::AccountAddress, Account}; use anyhow::Result; -use block_store::NodeBlockStore; use common::{ block::Block, - execution_input::PublicNativeTokenSend, merkle_tree_public::merkle_tree::{PublicTransactionMerkleTree, UTXOCommitmentsMerkleTree}, nullifier::UTXONullifier, - utxo_commitment::UTXOCommitment, }; -use k256::AffinePoint; -use log::{info, warn}; use sc_core::public_context::PublicSCContext; use serde::{Deserialize, Serialize}; -use utxo::utxo_core::UTXO; -use crate::{config::NodeConfig, ActionData}; +use crate::config::NodeConfig; pub mod accounts_store; -pub mod block_store; +//pub mod block_store; #[derive(Deserialize, Serialize)] pub struct AccMap { @@ -49,7 +43,6 @@ impl From for HashMap<[u8; 32], Account> { pub struct NodeChainStore { pub acc_map: HashMap, - pub block_store: NodeBlockStore, pub nullifier_store: HashSet, pub utxo_commitments_store: UTXOCommitmentsMerkleTree, pub pub_tx_store: PublicTransactionMerkleTree, @@ -58,30 +51,15 @@ pub struct NodeChainStore { impl NodeChainStore { pub fn new(config: NodeConfig, genesis_block: Block) -> Result<(Self, u64)> { - let mut acc_map = HashMap::new(); - let mut nullifier_store = HashSet::new(); - let mut utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]); - let mut pub_tx_store = PublicTransactionMerkleTree::new(vec![]); - let mut block_id = genesis_block.block_id; - - //Sequencer should panic if unable to open db, - //as fixing this issue may require actions non-native to program scope - let block_store = - NodeBlockStore::open_db_with_genesis(&config.home.join("rocksdb"), Some(genesis_block)) - .unwrap(); - - if let Ok(temp_block_id) = block_store.get_snapshot_block_id() { - utxo_commitments_store = block_store.get_snapshot_commitment()?; - nullifier_store = block_store.get_snapshot_nullifier()?; - acc_map = block_store.get_snapshot_account()?; - pub_tx_store = block_store.get_snapshot_transaction()?; - block_id = temp_block_id; - } + let acc_map = HashMap::new(); + let nullifier_store = HashSet::new(); + let utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]); + let pub_tx_store = PublicTransactionMerkleTree::new(vec![]); + let block_id = genesis_block.block_id; Ok(( Self { acc_map, - block_store, nullifier_store, utxo_commitments_store, pub_tx_store, @@ -91,184 +69,6 @@ impl NodeChainStore { )) } - pub fn new_after_restart(config: NodeConfig, genesis_block: Block) -> Result<(Self, u64)> { - let mut acc_map = HashMap::new(); - let mut nullifier_store = HashSet::new(); - let mut utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]); - let mut pub_tx_store = PublicTransactionMerkleTree::new(vec![]); - let mut block_id = genesis_block.block_id; - - //Sequencer should panic if unable to open db, - //as fixing this issue may require actions non-native to program scope - let block_store = NodeBlockStore::open_db_reload(&config.home.join("rocksdb")).unwrap(); - - if let Ok(temp_block_id) = block_store.get_snapshot_block_id() { - utxo_commitments_store = block_store.get_snapshot_commitment()?; - nullifier_store = block_store.get_snapshot_nullifier()?; - acc_map = block_store.get_snapshot_account()?; - pub_tx_store = block_store.get_snapshot_transaction()?; - block_id = temp_block_id; - } - - Ok(( - Self { - acc_map, - block_store, - nullifier_store, - utxo_commitments_store, - pub_tx_store, - node_config: config, - }, - block_id, - )) - } - - pub fn dissect_insert_block(&mut self, block: Block) -> Result<()> { - let block_id = block.block_id; - - for tx in &block.transactions { - if !tx.body().execution_input.is_empty() { - let public_action = - serde_json::from_slice::(&tx.body().execution_input); - - if let Ok(public_action) = public_action { - match public_action { - ActionData::MintMoneyPublicTx(action) => { - let acc_mut = self.acc_map.get_mut(&action.acc); - - if let Some(acc_mut) = acc_mut { - acc_mut.balance += action.amount as u64; - } - } - ActionData::SendMoneyDeshieldedTx(action) => { - for (balance, acc_addr) in action.receiver_data { - let acc_mut = self.acc_map.get_mut(&acc_addr); - - if let Some(acc_mut) = acc_mut { - acc_mut.balance += balance as u64; - } - } - } - ActionData::SendMoneyShieldedTx(action) => { - let acc_mut = self.acc_map.get_mut(&action.acc_sender); - - if let Some(acc_mut) = acc_mut { - acc_mut.balance = - acc_mut.balance.saturating_sub(action.amount as u64); - } - } - _ => {} - } - } else { - let native_transfer = - serde_json::from_slice::(&tx.body().execution_input); - - if let Ok(transfer) = native_transfer { - if let Some(acc_sender) = self.acc_map.get_mut(&transfer.from) { - //Can panic, we depend on sequencer maintaining chain consistency here - acc_sender.balance -= transfer.balance_to_move; - - if let Some(acc_rec) = self.acc_map.get_mut(&transfer.to) { - acc_rec.balance += transfer.balance_to_move; - } - } - } - } - } - - self.utxo_commitments_store.add_tx_multiple( - tx.body() - .utxo_commitments_created_hashes - .clone() - .into_iter() - .map(|hash| UTXOCommitment { hash }) - .collect(), - ); - - for nullifier in tx.body().nullifier_created_hashes.iter() { - self.nullifier_store.insert(UTXONullifier { - utxo_hash: *nullifier, - }); - } - - if !tx.body().encoded_data.is_empty() { - let ephemeral_public_key_sender = - serde_json::from_slice::(&tx.body().ephemeral_pub_key)?; - - for (ciphertext, nonce, tag) in tx.body().encoded_data.clone() { - 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() { - if hex::decode(acc_id).unwrap()[0] == tag { - let decoded_data_curr_acc = acc.decrypt_data( - ephemeral_public_key_sender, - ciphertext.clone(), - nonce, - ); - if let Ok(decoded_data_curr_acc) = 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.utxos.insert(utxo.hash, utxo); - } - } - } - } - } - } - } - - self.pub_tx_store.add_tx(tx); - } - - self.block_store.put_block_at_id(block)?; - - //Snapshot - if block_id.is_multiple_of(self.node_config.shapshot_frequency_in_blocks) { - //Serializing all important data structures - - //If we fail serialization, it is not the reason to stop running - //Logging on warn level in this cases - let acc_map: AccMap = self.acc_map.clone().into(); - - if let Ok(accounts_ser) = serde_json::to_vec(&acc_map).inspect_err(|err| { - warn!("Failed to serialize accounts data {err:#?}"); - }) { - if let Ok(comm_ser) = - serde_json::to_vec(&self.utxo_commitments_store).inspect_err(|err| { - warn!("Failed to serialize commitments {err:#?}"); - }) - { - if let Ok(txs_ser) = serde_json::to_vec(&self.pub_tx_store).inspect_err(|err| { - warn!("Failed to serialize transactions {err:#?}"); - }) { - if let Ok(nullifiers_ser) = serde_json::to_vec(&self.nullifier_store) - .inspect_err(|err| { - warn!("Failed to serialize nullifiers {err:#?}"); - }) - { - let snapshot_trace = self.block_store.put_snapshot_at_block_id( - block_id, - accounts_ser, - comm_ser, - txs_ser, - nullifiers_ser, - ); - - info!( - "Snapshot executed at {block_id:?} with results {snapshot_trace:#?}" - ); - } - } - } - } - } - - Ok(()) - } - pub fn produce_context(&self, caller: AccountAddress) -> PublicSCContext { let mut account_masks = BTreeMap::new(); @@ -298,7 +98,6 @@ mod tests { use crate::config::GasConfig; use accounts::account_core::Account; use common::block::{Block, Data}; - use common::merkle_tree_public::TreeHashType; use common::transaction::{SignaturePrivateKey, Transaction, TransactionBody, TxKind}; use secp256k1_zkp::Tweak; use std::path::PathBuf; @@ -489,6 +288,7 @@ mod tests { } } + //ToDo: Continue refactor fn create_dummy_transaction( nullifier_created_hashes: Vec<[u8; 32]>, utxo_commitments_spent_hashes: Vec<[u8; 32]>, @@ -515,6 +315,7 @@ mod tests { Transaction::new(body, SignaturePrivateKey::random(&mut rng)) } + //ToDo: Continue refactor fn create_sample_block(block_id: u64, prev_block_id: u64) -> Block { Block { block_id, @@ -551,10 +352,6 @@ mod tests { } } - fn generate_dummy_utxo(address: TreeHashType, amount: u128) -> UTXO { - UTXO::new(address, vec![], amount, false) - } - #[test] fn test_new_initializes_correctly() { let temp_dir = tempdir().unwrap(); @@ -574,59 +371,4 @@ mod tests { [0; 32] ); } - - #[test] - fn test_new_recovers_from_snapshot() { - let temp_dir = tempdir().unwrap(); - let path = temp_dir.path().to_path_buf(); - - let config = create_sample_node_config(path); - - let nullifier_secret_const = - "261d61d294ac4bdc24f91b6f490efa263757a4a95f65871cd4f16b2ea23c3b5d"; - std::env::set_var("NULLIFIER_SECRET_CONST", nullifier_secret_const); - - let viewing_secret_const = - "6117af750b30d7a296672ec3b3b25d3489beca3cfe5770fa39f275cec395d5ce"; - std::env::set_var("VIEWING_SECRET_CONST", viewing_secret_const); - - let genesis_block = create_genesis_block(); - - // Initialize once to create DB and store fake snapshot - { - let (mut store, _) = - NodeChainStore::new(config.clone(), genesis_block.clone()).unwrap(); - - // Insert state - let mut account = Account::new(); - account - .add_new_utxo_outputs(vec![generate_dummy_utxo(account.address, 100)]) - .unwrap(); - store.acc_map.insert(account.address, account); - store.nullifier_store.insert(UTXONullifier { - utxo_hash: [2u8; 32], - }); - store - .utxo_commitments_store - .add_tx_multiple(vec![UTXOCommitment { hash: [3u8; 32] }]); - store.pub_tx_store.add_tx(&create_dummy_transaction( - vec![[9; 32]], - vec![[7; 32]], - vec![[8; 32]], - )); - - // Put block snapshot to trigger snapshot recovery on next load - let dummy_block = create_sample_block(1, 0); - - store.dissect_insert_block(dummy_block).unwrap(); - } - - // Now reload and verify snapshot is used - let (recovered_store, block_id) = - NodeChainStore::new_after_restart(config.clone(), genesis_block).unwrap(); - - assert_eq!(block_id, 1); - assert_eq!(recovered_store.acc_map.len(), 1); - assert!(recovered_store.utxo_commitments_store.get_root().is_some()); - } } diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index f613dbb..1c70a11 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -1,44 +1,30 @@ -use std::sync::{ - atomic::{AtomicU64, Ordering}, - Arc, -}; +use std::sync::{atomic::AtomicU64, Arc}; use common::{ execution_input::PublicNativeTokenSend, transaction::Transaction, ExecutionFailureKind, }; -use accounts::{ - account_core::{address::AccountAddress, Account}, - key_management::ephemeral_key_holder::EphemeralKeyHolder, -}; +use accounts::account_core::{address::AccountAddress, Account}; use anyhow::Result; use chain_storage::NodeChainStore; -use common::transaction::{TransactionBody, TxKind}; +use common::transaction::TransactionBody; use config::NodeConfig; use log::info; -use sc_core::proofs_circuits::{ - generate_commitments, generate_nullifiers, generate_nullifiers_se, pedersen_commitment_vec, -}; +use sc_core::proofs_circuits::{generate_commitments, pedersen_commitment_vec}; use sequencer_client::{json::SendTxResponse, SequencerClient}; use serde::{Deserialize, Serialize}; use storage::sc_db_utils::DataBlobChangeVariant; -use tokio::{sync::RwLock, task::JoinHandle}; +use tokio::sync::RwLock; use utxo::utxo_core::UTXO; -use zkvm::{ - gas_calculator::GasCalculator, prove_mint_utxo, prove_mint_utxo_multiple_assets, - prove_send_utxo, prove_send_utxo_deshielded, prove_send_utxo_multiple_assets_one_receiver, - prove_send_utxo_shielded, -}; +use zkvm::gas_calculator::GasCalculator; pub const BLOCK_GEN_DELAY_SECS: u64 = 20; pub mod chain_storage; pub mod config; -///Module, which includes pre start setup helperfunctions -pub mod pre_start; pub mod sequencer_client; -fn vec_u8_to_vec_u64(bytes: Vec) -> Vec { +pub fn vec_u8_to_vec_u64(bytes: Vec) -> Vec { // Pad with zeros to make sure it's a multiple of 8 let mut padded = bytes.clone(); while !padded.len().is_multiple_of(8) { @@ -89,7 +75,6 @@ pub struct NodeCore { pub storage: Arc>, pub curr_height: Arc, pub node_config: NodeConfig, - pub db_updater_handle: JoinHandle>, pub sequencer_client: Arc, pub gas_calculator: GasCalculator, } @@ -103,68 +88,18 @@ impl NodeCore { let genesis_block = client.get_block(genesis_id.genesis_id).await?.block; - let (mut storage, mut chain_height) = NodeChainStore::new(config.clone(), genesis_block)?; + let (mut storage, chain_height) = NodeChainStore::new(config.clone(), genesis_block)?; for acc in config.clone().initial_accounts { storage.acc_map.insert(acc.address, acc); } - pre_start::setup_empty_sc_states(&storage).await?; - - //Chain update loop - loop { - let next_block = chain_height + 1; - - if let Ok(block) = client.get_block(next_block).await { - storage.dissect_insert_block(block.block)?; - info!("Preprocessed block with id {next_block:?}"); - } else { - break; - } - - chain_height += 1; - } - let wrapped_storage = Arc::new(RwLock::new(storage)); let chain_height_wrapped = Arc::new(AtomicU64::new(chain_height)); - let wrapped_storage_thread = wrapped_storage.clone(); - let wrapped_chain_height_thread = chain_height_wrapped.clone(); - let client_thread = client.clone(); - - let updater_handle = tokio::spawn(async move { - loop { - let next_block = wrapped_chain_height_thread.load(Ordering::Relaxed) + 1; - - if let Ok(block) = client_thread.get_block(next_block).await { - { - let mut storage_guard = wrapped_storage_thread.write().await; - - let block_insertion_result = - storage_guard.dissect_insert_block(block.block); - - if block_insertion_result.is_err() { - info!("Block insertion failed due to {block_insertion_result:?}"); - - block_insertion_result?; - } - info!("Processed block with id {next_block:?}"); - } - - wrapped_chain_height_thread.store(next_block, Ordering::Relaxed); - } else { - tokio::time::sleep(std::time::Duration::from_secs( - config.seq_poll_timeout_secs, - )) - .await; - } - } - }); - Ok(Self { storage: wrapped_storage, curr_height: chain_height_wrapped, node_config: config.clone(), - db_updater_handle: updater_handle, sequencer_client: client.clone(), gas_calculator: GasCalculator::from(config.gas_config), }) @@ -193,760 +128,6 @@ impl NodeCore { addr } - pub async fn mint_utxo_private( - &self, - acc: AccountAddress, - amount: u128, - ) -> Result<(Transaction, [u8; 32]), ExecutionFailureKind> { - let (utxo, receipt) = prove_mint_utxo(amount, acc)?; - let result_hash = utxo.hash; - - let acc_map_read_guard = self.storage.read().await; - - let account = acc_map_read_guard.acc_map.get(&acc).unwrap(); - - let ephm_key_holder = EphemeralKeyHolder::new_os_random(); - ephm_key_holder.log(); - - let eph_pub_key = - serde_json::to_vec(&ephm_key_holder.generate_ephemeral_public_key()).unwrap(); - - let encoded_data = Account::encrypt_data( - &ephm_key_holder, - account.key_holder.viewing_public_key, - &serde_json::to_vec(&utxo).unwrap(), - ); - - let tag = account.make_tag(); - - let comm = generate_commitments(&[utxo]); - - let mint_utxo_addr_bytes: Vec = zkvm::test_methods::MINT_UTXO_ID - .iter() - .flat_map(|num| num.to_le_bytes()) - .collect(); - let sc_addr = hex::encode(mint_utxo_addr_bytes); - - //Sc does not change its state - let state_changes: Vec = vec![]; - let new_len = 0; - let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len); - - let sc_state = acc_map_read_guard - .block_store - .get_sc_sc_state(&sc_addr) - .map_err(ExecutionFailureKind::db_error)?; - - let mut vec_values_u64: Vec> = sc_state - .into_iter() - .map(|slice| vec_u8_to_vec_u64(slice.to_vec())) - .collect(); - - let context = acc_map_read_guard.produce_context(account.address); - - //Will not panic, as PublicScContext is serializable - let context_public_info: Vec = context.produce_u64_list_from_context().unwrap(); - vec_values_u64.push(context_public_info); - - let vec_public_info: Vec = vec_values_u64.into_iter().flatten().collect(); - - let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); - let transaction_body = TransactionBody { - 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: sc_core::transaction_payloads_tools::encode_receipt(receipt) - .unwrap(), - encoded_data: vec![(encoded_data.0, encoded_data.1.to_vec(), tag)], - ephemeral_pub_key: eph_pub_key.to_vec(), - commitment, - tweak, - secret_r, - sc_addr, - state_changes, - }; - let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); - - Ok(( - Transaction::new(transaction_body, key_to_sign_transaction), - result_hash, - )) - } - - pub async fn mint_utxo_multiple_assets_private( - &self, - acc: AccountAddress, - amount: u128, - number_of_assets: usize, - ) -> Result<(Transaction, Vec<[u8; 32]>), ExecutionFailureKind> { - let (utxos, receipt) = prove_mint_utxo_multiple_assets(amount, number_of_assets, acc)?; - let result_hashes = utxos.iter().map(|utxo| utxo.hash).collect(); - - let acc_map_read_guard = self.storage.read().await; - - let account = acc_map_read_guard.acc_map.get(&acc).unwrap(); - - let ephm_key_holder = EphemeralKeyHolder::new_os_random(); - ephm_key_holder.log(); - - let eph_pub_key = - serde_json::to_vec(&ephm_key_holder.generate_ephemeral_public_key()).unwrap(); - - let encoded_data = utxos - .iter() - .map(|utxo| { - ( - Account::encrypt_data( - &ephm_key_holder, - account.key_holder.viewing_public_key, - &serde_json::to_vec(&utxo).unwrap(), - ), - account.make_tag(), - ) - }) - .map(|((ciphertext, nonce), tag)| (ciphertext, nonce.to_vec(), tag)) - .collect(); - - let comm = generate_commitments(&utxos); - - let mint_multiple_utxo_addr_bytes: Vec = - zkvm::test_methods::MINT_UTXO_MULTIPLE_ASSETS_ID - .iter() - .flat_map(|num| num.to_le_bytes()) - .collect(); - let sc_addr = hex::encode(mint_multiple_utxo_addr_bytes); - - //Sc does not change its state - let state_changes: Vec = vec![]; - let new_len = 0; - let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len); - - let sc_state = acc_map_read_guard - .block_store - .get_sc_sc_state(&sc_addr) - .map_err(ExecutionFailureKind::db_error)?; - - let mut vec_values_u64: Vec> = sc_state - .into_iter() - .map(|slice| vec_u8_to_vec_u64(slice.to_vec())) - .collect(); - - let context = acc_map_read_guard.produce_context(account.address); - - //Will not panic, as PublicScContext is serializable - let context_public_info: Vec = context.produce_u64_list_from_context().unwrap(); - vec_values_u64.push(context_public_info); - - let vec_public_info: Vec = vec_values_u64.into_iter().flatten().collect(); - - let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); - - let transaction_body = TransactionBody { - 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: sc_core::transaction_payloads_tools::encode_receipt(receipt) - .unwrap(), - encoded_data, - ephemeral_pub_key: eph_pub_key.to_vec(), - commitment, - tweak, - secret_r, - sc_addr, - state_changes, - }; - let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); - - Ok(( - Transaction::new(transaction_body, key_to_sign_transaction), - result_hashes, - )) - } - - pub async fn transfer_utxo_private( - &self, - utxo: UTXO, - commitment_in: [u8; 32], - receivers: Vec<(u128, AccountAddress)>, - ) -> Result<(Transaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { - let acc_map_read_guard = self.storage.read().await; - - let account = acc_map_read_guard.acc_map.get(&utxo.owner).unwrap(); - - let nullifier = generate_nullifiers( - &utxo, - &account - .key_holder - .utxo_secret_key_holder - .nullifier_secret_key - .to_bytes(), - ); - - let (resulting_utxos, receipt) = prove_send_utxo(utxo, receivers)?; - let utxo_hashes = resulting_utxos - .iter() - .map(|(utxo, addr)| (*addr, utxo.hash)) - .collect(); - - let utxos: Vec = resulting_utxos - .iter() - .map(|(utxo, _)| utxo.clone()) - .collect(); - - let ephm_key_holder = EphemeralKeyHolder::new_os_random(); - ephm_key_holder.log(); - - let eph_pub_key = - serde_json::to_vec(&ephm_key_holder.generate_ephemeral_public_key()).unwrap(); - - let encoded_data: Vec<(Vec, Vec, u8)> = utxos - .iter() - .map(|utxo_enc| { - let accout_enc = acc_map_read_guard.acc_map.get(&utxo_enc.owner).unwrap(); - - let (ciphertext, nonce) = Account::encrypt_data( - &ephm_key_holder, - accout_enc.key_holder.viewing_public_key, - &serde_json::to_vec(&utxo_enc).unwrap(), - ); - - let tag = accout_enc.make_tag(); - - (ciphertext, nonce.to_vec(), tag) - }) - .collect(); - - let commitments = generate_commitments(&utxos); - - let send_utxo_addr_bytes: Vec = zkvm::test_methods::SEND_UTXO_ID - .iter() - .flat_map(|num| num.to_le_bytes()) - .collect(); - let sc_addr = hex::encode(send_utxo_addr_bytes); - - //Sc does not change its state - let state_changes: Vec = vec![]; - let new_len = 0; - let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len); - - let sc_state = acc_map_read_guard - .block_store - .get_sc_sc_state(&sc_addr) - .map_err(ExecutionFailureKind::db_error)?; - - let mut vec_values_u64: Vec> = sc_state - .into_iter() - .map(|slice| vec_u8_to_vec_u64(slice.to_vec())) - .collect(); - - let context = acc_map_read_guard.produce_context(account.address); - - //Will not panic, as PublicScContext is serializable - let context_public_info: Vec = context.produce_u64_list_from_context().unwrap(); - vec_values_u64.push(context_public_info); - - let vec_public_info: Vec = vec_values_u64.into_iter().flatten().collect(); - - let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); - - let transaction_body = TransactionBody { - 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: sc_core::transaction_payloads_tools::encode_receipt(receipt) - .unwrap(), - encoded_data, - ephemeral_pub_key: eph_pub_key.to_vec(), - commitment, - tweak, - secret_r, - sc_addr, - state_changes, - }; - - let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); - - Ok(( - Transaction::new(transaction_body, key_to_sign_transaction), - utxo_hashes, - )) - } - - pub async fn transfer_utxo_multiple_assets_private( - &self, - utxos: Vec, - commitments_in: Vec<[u8; 32]>, - number_to_send: usize, - receiver: AccountAddress, - ) -> Result<(Transaction, Vec<[u8; 32]>, Vec<[u8; 32]>), ExecutionFailureKind> { - let acc_map_read_guard = self.storage.read().await; - - let account = acc_map_read_guard.acc_map.get(&utxos[0].owner).unwrap(); - - let nsk = account - .key_holder - .utxo_secret_key_holder - .nullifier_secret_key - .to_bytes() - .to_vec(); - - let nullifiers = utxos - .iter() - .map(|utxo| generate_nullifiers(utxo, &nsk)) - .map(|vecc| vecc.try_into().unwrap()) - .collect(); - - let (resulting_utxos_receiver, resulting_utxos_not_spent, receipt) = - prove_send_utxo_multiple_assets_one_receiver(utxos, number_to_send, receiver)?; - - let utxo_hashes_receiver = resulting_utxos_receiver - .iter() - .map(|utxo| utxo.hash) - .collect(); - - let utxo_hashes_not_spent = resulting_utxos_not_spent - .iter() - .map(|utxo| utxo.hash) - .collect(); - - let ephm_key_holder = EphemeralKeyHolder::new_os_random(); - ephm_key_holder.log(); - - let eph_pub_key = - serde_json::to_vec(&ephm_key_holder.generate_ephemeral_public_key()).unwrap(); - - let mut encoded_data: Vec<(Vec, Vec, u8)> = resulting_utxos_receiver - .iter() - .map(|utxo_enc| { - let accout_enc = acc_map_read_guard.acc_map.get(&utxo_enc.owner).unwrap(); - - let (ciphertext, nonce) = Account::encrypt_data( - &ephm_key_holder, - accout_enc.key_holder.viewing_public_key, - &serde_json::to_vec(&utxo_enc).unwrap(), - ); - - let tag = accout_enc.make_tag(); - - (ciphertext, nonce.to_vec(), tag) - }) - .collect(); - - let encoded_data_1: Vec<(Vec, Vec, u8)> = resulting_utxos_not_spent - .iter() - .map(|utxo_enc| { - let accout_enc = acc_map_read_guard.acc_map.get(&utxo_enc.owner).unwrap(); - - let (ciphertext, nonce) = Account::encrypt_data( - &ephm_key_holder, - accout_enc.key_holder.viewing_public_key, - &serde_json::to_vec(&utxo_enc).unwrap(), - ); - - let tag = accout_enc.make_tag(); - - (ciphertext, nonce.to_vec(), tag) - }) - .collect(); - - encoded_data.extend(encoded_data_1); - - let mut commitments = generate_commitments(&resulting_utxos_receiver); - let commitments_1 = generate_commitments(&resulting_utxos_not_spent); - - commitments.extend(commitments_1); - - let send_multiple_utxo_addr_bytes: Vec = - zkvm::test_methods::SEND_UTXO_MULTIPLE_ASSETS_ID - .iter() - .flat_map(|num| num.to_le_bytes()) - .collect(); - let sc_addr = hex::encode(send_multiple_utxo_addr_bytes); - - //Sc does not change its state - let state_changes: Vec = vec![]; - let new_len = 0; - let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len); - - let sc_state = acc_map_read_guard - .block_store - .get_sc_sc_state(&sc_addr) - .map_err(ExecutionFailureKind::db_error)?; - - let mut vec_values_u64: Vec> = sc_state - .into_iter() - .map(|slice| vec_u8_to_vec_u64(slice.to_vec())) - .collect(); - - let context = acc_map_read_guard.produce_context(account.address); - - //Will not panic, as PublicScContext is serializable - let context_public_info: Vec = context.produce_u64_list_from_context().unwrap(); - vec_values_u64.push(context_public_info); - - let vec_public_info: Vec = vec_values_u64.into_iter().flatten().collect(); - - let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); - - let transaction_body = TransactionBody { - tx_kind: TxKind::Private, - execution_input: vec![], - execution_output: vec![], - utxo_commitments_spent_hashes: commitments_in, - utxo_commitments_created_hashes: commitments - .into_iter() - .map(|hash_data| hash_data.try_into().unwrap()) - .collect(), - nullifier_created_hashes: nullifiers, - execution_proof_private: sc_core::transaction_payloads_tools::encode_receipt(receipt) - .unwrap(), - encoded_data, - ephemeral_pub_key: eph_pub_key.to_vec(), - commitment, - tweak, - secret_r, - sc_addr, - state_changes, - }; - - let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); - - Ok(( - Transaction::new(transaction_body, key_to_sign_transaction), - utxo_hashes_receiver, - utxo_hashes_not_spent, - )) - } - - pub async fn transfer_balance_shielded( - &self, - acc: AccountAddress, - balance: u64, - receivers: Vec<(u128, AccountAddress)>, - ) -> Result<(Transaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { - let acc_map_read_guard = self.storage.read().await; - - let account = acc_map_read_guard.acc_map.get(&acc).unwrap(); - - // TODO: add to transaction structure and do the check. Research has to update the scheme as well. - let commitment = sc_core::transaction_payloads_tools::generate_secret_random_commitment( - balance, account, - ) - .unwrap(); - - let nullifier = generate_nullifiers_se( - &commitment, - &account - .key_holder - .utxo_secret_key_holder - .nullifier_secret_key - .to_bytes(), - ); - - let (resulting_utxos, receipt) = prove_send_utxo_shielded(acc, balance as u128, receivers)?; - let utxo_hashes = resulting_utxos - .iter() - .map(|(utxo, addr)| (*addr, utxo.hash)) - .collect(); - - let utxos: Vec = resulting_utxos - .iter() - .map(|(utxo, _)| utxo.clone()) - .collect(); - - let ephm_key_holder = EphemeralKeyHolder::new_os_random(); - ephm_key_holder.log(); - - let eph_pub_key = - serde_json::to_vec(&ephm_key_holder.generate_ephemeral_public_key()).unwrap(); - - let encoded_data: Vec<(Vec, Vec, u8)> = utxos - .iter() - .map(|utxo_enc| { - let accout_enc = acc_map_read_guard.acc_map.get(&utxo_enc.owner).unwrap(); - - let (ciphertext, nonce) = Account::encrypt_data( - &ephm_key_holder, - accout_enc.key_holder.viewing_public_key, - &serde_json::to_vec(&utxo_enc).unwrap(), - ); - - let tag = accout_enc.make_tag(); - - (ciphertext, nonce.to_vec(), tag) - }) - .collect(); - - let commitments = generate_commitments(&utxos); - - let mint_utxo_addr_bytes: Vec = zkvm::test_methods::SEND_UTXO_ID - .iter() - .flat_map(|num| num.to_le_bytes()) - .collect(); - let sc_addr = hex::encode(mint_utxo_addr_bytes); - - //Sc does not change its state - let state_changes: Vec = vec![]; - let new_len = 0; - let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len); - - let sc_state = acc_map_read_guard - .block_store - .get_sc_sc_state(&sc_addr) - .map_err(ExecutionFailureKind::db_error)?; - - let mut vec_values_u64: Vec> = sc_state - .into_iter() - .map(|slice| vec_u8_to_vec_u64(slice.to_vec())) - .collect(); - - let context = acc_map_read_guard.produce_context(account.address); - - //Will not panic, as PublicScContext is serializable - let context_public_info: Vec = context.produce_u64_list_from_context().unwrap(); - vec_values_u64.push(context_public_info); - - let vec_public_info: Vec = vec_values_u64.into_iter().flatten().collect(); - - let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); - - let transaction_body = TransactionBody { - tx_kind: TxKind::Shielded, - 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: sc_core::transaction_payloads_tools::encode_receipt(receipt) - .unwrap(), - encoded_data, - ephemeral_pub_key: eph_pub_key.to_vec(), - commitment, - tweak, - secret_r, - sc_addr, - state_changes, - }; - - let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); - - Ok(( - Transaction::new(transaction_body, key_to_sign_transaction), - utxo_hashes, - )) - } - - pub async fn transfer_utxo_deshielded( - &self, - utxo: UTXO, - comm_gen_hash: [u8; 32], - receivers: Vec<(u128, AccountAddress)>, - ) -> Result { - let acc_map_read_guard = self.storage.read().await; - - let commitment_in = acc_map_read_guard - .utxo_commitments_store - .get_tx(comm_gen_hash) - .unwrap() - .hash; - - let account = acc_map_read_guard.acc_map.get(&utxo.owner).unwrap(); - - let nullifier = generate_nullifiers( - &utxo, - &account - .key_holder - .utxo_secret_key_holder - .nullifier_secret_key - .to_bytes(), - ); - - let (resulting_balances, receipt) = prove_send_utxo_deshielded(utxo, receivers)?; - - let send_utxo_addr_bytes: Vec = zkvm::test_methods::SEND_UTXO_ID - .iter() - .flat_map(|num| num.to_le_bytes()) - .collect(); - let sc_addr = hex::encode(send_utxo_addr_bytes); - - //Sc does not change its state - let state_changes: Vec = vec![]; - let new_len = 0; - let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len); - - let sc_state = acc_map_read_guard - .block_store - .get_sc_sc_state(&sc_addr) - .map_err(ExecutionFailureKind::db_error)?; - - let mut vec_values_u64: Vec> = sc_state - .into_iter() - .map(|slice| vec_u8_to_vec_u64(slice.to_vec())) - .collect(); - - let context = acc_map_read_guard.produce_context(account.address); - - //Will not panic, as PublicScContext is serializable - let context_public_info: Vec = context.produce_u64_list_from_context().unwrap(); - vec_values_u64.push(context_public_info); - - let vec_public_info: Vec = vec_values_u64.into_iter().flatten().collect(); - - let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); - - let transaction_body = TransactionBody { - tx_kind: TxKind::Deshielded, - execution_input: serde_json::to_vec(&ActionData::SendMoneyDeshieldedTx( - SendMoneyDeshieldedTx { - receiver_data: resulting_balances, - }, - )) - .unwrap(), - execution_output: vec![], - utxo_commitments_spent_hashes: vec![commitment_in], - utxo_commitments_created_hashes: vec![], - nullifier_created_hashes: vec![nullifier.try_into().unwrap()], - execution_proof_private: sc_core::transaction_payloads_tools::encode_receipt(receipt) - .unwrap(), - encoded_data: vec![], - ephemeral_pub_key: vec![], - commitment, - tweak, - secret_r, - sc_addr, - state_changes, - }; - - let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); - - Ok(Transaction::new(transaction_body, key_to_sign_transaction)) - } - - pub async fn send_private_mint_tx( - &self, - acc: AccountAddress, - amount: u128, - ) -> Result<(SendTxResponse, [u8; 32], [u8; 32]), ExecutionFailureKind> { - //Considering proof time, needs to be done before proof - let tx_roots = self.get_roots().await; - - let point_before_prove = std::time::Instant::now(); - let (tx, utxo_hash) = self.mint_utxo_private(acc, amount).await?; - tx.body().log(); - let point_after_prove = std::time::Instant::now(); - - let commitment_generated_hash = tx.body().utxo_commitments_created_hashes[0]; - - let timedelta = (point_after_prove - point_before_prove).as_millis(); - info!("Mint utxo proof spent {timedelta:?} milliseconds"); - - Ok(( - self.sequencer_client.send_tx(tx, tx_roots).await?, - utxo_hash, - commitment_generated_hash, - )) - } - - pub async fn send_private_mint_multiple_assets_tx( - &self, - acc: AccountAddress, - amount: u128, - number_of_assets: usize, - ) -> Result<(SendTxResponse, Vec<[u8; 32]>, Vec<[u8; 32]>), ExecutionFailureKind> { - //Considering proof time, needs to be done before proof - let tx_roots = self.get_roots().await; - - let point_before_prove = std::time::Instant::now(); - let (tx, utxo_hashes) = self - .mint_utxo_multiple_assets_private(acc, amount, number_of_assets) - .await?; - tx.body().log(); - let point_after_prove = std::time::Instant::now(); - - let commitment_generated_hashes = tx.body().utxo_commitments_created_hashes.clone(); - - let timedelta = (point_after_prove - point_before_prove).as_millis(); - info!("Mint utxo proof spent {timedelta:?} milliseconds"); - - Ok(( - self.sequencer_client.send_tx(tx, tx_roots).await?, - utxo_hashes, - commitment_generated_hashes, - )) - } - - // pub async fn send_public_deposit( - // &self, - // acc: AccountAddress, - // amount: u128, - // ) -> Result { - // //Considering proof time, needs to be done before proof - // let tx_roots = self.get_roots().await; - // - // let public_context = { - // let read_guard = self.storage.read().await; - // - // read_guard.produce_context(acc) - // }; - // - // let (tweak, secret_r, commitment) = pedersen_commitment_vec( - // //Will not panic, as public context is serializable - // public_context.produce_u64_list_from_context().unwrap(), - // ); - // - // let sc_addr = hex::encode([0; 32]); - // - // //Sc does not change its state - // let state_changes: Vec = vec![]; - // let new_len = 0; - // let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len); - // - // let tx: TransactionBody = - // sc_core::transaction_payloads_tools::create_public_transaction_payload( - // serde_json::to_vec(&ActionData::MintMoneyPublicTx(MintMoneyPublicTx { - // acc, - // amount, - // })) - // .unwrap(), - // commitment, - // tweak, - // secret_r, - // sc_addr, - // state_changes, - // ) - // .into(); - // tx.log(); - // - // Ok(self.sequencer_client.send_tx(tx, tx_roots).await?) - // } - pub async fn send_public_native_token_transfer( &self, from: AccountAddress, @@ -1010,732 +191,6 @@ impl NodeCore { } } } - - pub async fn send_private_send_tx( - &self, - utxo: UTXO, - comm_hash: [u8; 32], - receivers: Vec<(u128, AccountAddress)>, - ) -> Result<(SendTxResponse, Vec<([u8; 32], [u8; 32])>), ExecutionFailureKind> { - //Considering proof time, needs to be done before proof - let tx_roots = self.get_roots().await; - - let point_before_prove = std::time::Instant::now(); - let (tx, utxo_hashes) = self - .transfer_utxo_private(utxo, comm_hash, receivers) - .await?; - tx.body().log(); - 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, tx_roots).await?, - utxo_hashes, - )) - } - - pub async fn send_private_multiple_assets_send_tx( - &self, - utxos: Vec, - comm_hashes: Vec<[u8; 32]>, - number_to_send: usize, - receiver: AccountAddress, - ) -> Result<(SendTxResponse, Vec<[u8; 32]>, Vec<[u8; 32]>), ExecutionFailureKind> { - //Considering proof time, needs to be done before proof - let tx_roots = self.get_roots().await; - - let point_before_prove = std::time::Instant::now(); - let (tx, utxo_hashes_received, utxo_hashes_not_spent) = self - .transfer_utxo_multiple_assets_private(utxos, comm_hashes, number_to_send, receiver) - .await?; - tx.body().log(); - 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, tx_roots).await?, - utxo_hashes_received, - utxo_hashes_not_spent, - )) - } - - pub async fn send_shielded_send_tx( - &self, - acc: AccountAddress, - amount: u64, - receivers: Vec<(u128, AccountAddress)>, - ) -> Result<(SendTxResponse, Vec<([u8; 32], [u8; 32])>), ExecutionFailureKind> { - //Considering proof time, needs to be done before proof - let tx_roots = self.get_roots().await; - - let point_before_prove = std::time::Instant::now(); - let (tx, utxo_hashes) = self - .transfer_balance_shielded(acc, amount, receivers) - .await?; - tx.body().log(); - 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, tx_roots).await?, - utxo_hashes, - )) - } - - pub async fn send_deshielded_send_tx( - &self, - utxo: UTXO, - comm_gen_hash: [u8; 32], - receivers: Vec<(u128, AccountAddress)>, - ) -> Result { - //Considering proof time, needs to be done before proof - let tx_roots = self.get_roots().await; - - let point_before_prove = std::time::Instant::now(); - let tx = self - .transfer_utxo_deshielded(utxo, comm_gen_hash, receivers) - .await?; - tx.body().log(); - 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, tx_roots).await?) - } - - pub async fn operate_account_mint_private( - &mut self, - acc_addr: AccountAddress, - amount: u128, - ) -> Result<(UTXO, [u8; 32]), ExecutionFailureKind> { - let (resp, new_utxo_hash, comm_gen_hash) = - self.send_private_mint_tx(acc_addr, amount).await?; - 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.utxos.get(&new_utxo_hash).unwrap().clone() - }; - - new_utxo.log(); - info!( - "Account address is {:?} ,new utxo owner address is {:?}", - hex::encode(acc_addr), - hex::encode(new_utxo.owner) - ); - info!( - "Account {:?} got new utxo with amount {amount:?}", - hex::encode(acc_addr) - ); - - Ok((new_utxo, comm_gen_hash)) - } - - pub async fn operate_account_mint_multiple_assets_private( - &mut self, - acc_addr: AccountAddress, - amount: u128, - number_of_assets: usize, - ) -> Result<(Vec, Vec<[u8; 32]>), ExecutionFailureKind> { - let (resp, new_utxo_hashes, comm_gen_hashes) = self - .send_private_mint_multiple_assets_tx(acc_addr, amount, number_of_assets) - .await?; - info!("Response for mint multiple assets private is {resp:?}"); - - info!("Awaiting new blocks"); - tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; - - let new_utxos = { - let mut write_guard = self.storage.write().await; - - new_utxo_hashes - .into_iter() - .map(|new_utxo_hash| { - let acc = write_guard.acc_map.get_mut(&acc_addr).unwrap(); - - let new_utxo = acc.utxos.get(&new_utxo_hash).unwrap().clone(); - - new_utxo.log(); - info!( - "Account address is {:?} ,new utxo owner address is {:?}", - hex::encode(acc_addr), - hex::encode(new_utxo.owner) - ); - info!( - "Account {:?} got new utxo with amount {amount:?} and asset {:?}", - hex::encode(acc_addr), - new_utxo.asset - ); - - new_utxo - }) - .collect() - }; - - Ok((new_utxos, comm_gen_hashes)) - } - - pub async fn operate_account_send_deshielded_one_receiver( - &mut self, - acc_addr_rec: AccountAddress, - utxo: UTXO, - comm_gen_hash: [u8; 32], - ) -> Result<(), ExecutionFailureKind> { - let amount = utxo.amount; - - let old_balance = { - let acc_map_read_guard = self.storage.read().await; - - let acc = acc_map_read_guard.acc_map.get(&acc_addr_rec).unwrap(); - - acc.balance - }; - - info!( - "Balance of receiver {:?} now is {old_balance:?}", - hex::encode(acc_addr_rec) - ); - - let resp = self - .send_deshielded_send_tx(utxo, comm_gen_hash, vec![(amount, acc_addr_rec)]) - .await?; - info!("Response for send deshielded is {resp:?}"); - - info!("Awaiting new blocks"); - tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; - - let new_balance = { - let acc_map_read_guard = self.storage.read().await; - - let acc = acc_map_read_guard.acc_map.get(&acc_addr_rec).unwrap(); - - acc.balance - }; - - info!( - "Balance of receiver {:?} now is {:?}, delta is {:?}", - hex::encode(acc_addr_rec), - new_balance, - new_balance - old_balance - ); - - Ok(()) - } - - // pub async fn operate_account_deposit_public( - // &mut self, - // acc_addr: AccountAddress, - // amount: u128, - // ) -> Result<(), ExecutionFailureKind> { - // let old_balance = { - // let acc_map_read_guard = self.storage.read().await; - // - // let acc = acc_map_read_guard.acc_map.get(&acc_addr).unwrap(); - // - // acc.balance - // }; - // - // info!( - // "Balance of {:?} now is {old_balance:?}", - // hex::encode(acc_addr) - // ); - // - // let resp = self.send_public_deposit(acc_addr, amount).await?; - // info!("Response for public deposit is {resp:?}"); - // - // info!("Awaiting new blocks"); - // tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; - // - // let new_balance = { - // let acc_map_read_guard = self.storage.read().await; - // - // let acc = acc_map_read_guard.acc_map.get(&acc_addr).unwrap(); - // - // acc.balance - // }; - // - // info!( - // "Balance of {:?} now is {new_balance:?}, delta is {:?}", - // hex::encode(acc_addr), - // new_balance - old_balance - // ); - // - // Ok(()) - // } - - pub async fn operate_account_send_shielded_one_receiver( - &mut self, - acc_addr_sender: AccountAddress, - acc_addr_rec: AccountAddress, - amount: u128, - ) -> Result { - let (resp, new_utxo_hashes) = self - .send_shielded_send_tx(acc_addr_sender, amount as u64, vec![(amount, acc_addr_rec)]) - .await?; - info!("Response for send shielded is {resp:?}"); - - 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; - - let new_utxo = { - let mut write_guard = self.storage.write().await; - - let acc = write_guard.acc_map.get_mut(&acc_addr_rec).unwrap(); - acc.log(); - - acc.utxos.get(&new_utxo_hash).unwrap().clone() - }; - new_utxo.log(); - info!( - "Account address is {:?} ,new utxo owner address is {:?}", - hex::encode(acc_addr_rec), - hex::encode(new_utxo.owner) - ); - info!( - "Account {:?} got new utxo with amount {amount:?}", - hex::encode(acc_addr_rec) - ); - - Ok(new_utxo) - } - - pub async fn operate_account_send_private_one_receiver( - &mut self, - acc_addr_rec: AccountAddress, - utxo: UTXO, - comm_gen_hash: [u8; 32], - ) -> Result { - let amount = utxo.amount; - - let (resp, new_utxo_hashes) = self - .send_private_send_tx(utxo, comm_gen_hash, vec![(amount, acc_addr_rec)]) - .await?; - info!("Response for send private is {resp:?}"); - - 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; - - let new_utxo = { - let mut write_guard = self.storage.write().await; - - let acc = write_guard.acc_map.get_mut(&acc_addr_rec).unwrap(); - acc.log(); - - acc.utxos.get(&new_utxo_hash).unwrap().clone() - }; - new_utxo.log(); - info!( - "Account address is {:?} ,new utxo owner address is {:?}", - hex::encode(acc_addr_rec), - hex::encode(new_utxo.owner) - ); - info!( - "Account {:?} got new utxo with amount {:?}", - hex::encode(acc_addr_rec), - new_utxo.amount - ); - - Ok(new_utxo) - } - - pub async fn operate_account_send_private_multiple_assets_one_receiver( - &mut self, - acc_addr: AccountAddress, - acc_addr_rec: AccountAddress, - utxos: Vec, - comm_gen_hashes: Vec<[u8; 32]>, - number_to_send: usize, - ) -> Result<(), ExecutionFailureKind> { - let (resp, new_utxo_hashes_rec, new_utxo_hashes_not_sp) = self - .send_private_multiple_assets_send_tx( - utxos, - comm_gen_hashes, - number_to_send, - acc_addr_rec, - ) - .await?; - info!("Response for send private multiple assets is {resp:?}"); - - info!("Awaiting new blocks"); - tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; - - { - let mut write_guard = self.storage.write().await; - - for new_utxo_hash in new_utxo_hashes_rec { - let acc = write_guard.acc_map.get_mut(&acc_addr_rec).unwrap(); - acc.log(); - - let new_utxo = acc.utxos.get(&new_utxo_hash).unwrap().clone(); - - new_utxo.log(); - info!( - "Account address is {:?} ,new utxo owner address is {:?}", - hex::encode(acc_addr_rec), - hex::encode(new_utxo.owner) - ); - info!( - "Account {:?} got new utxo with amount {:?} and asset {:?}", - hex::encode(acc_addr_rec), - new_utxo.amount, - new_utxo.asset, - ); - } - - for new_utxo_hash in new_utxo_hashes_not_sp { - let acc = write_guard.acc_map.get_mut(&acc_addr).unwrap(); - acc.log(); - - let new_utxo = acc.utxos.get(&new_utxo_hash).unwrap().clone(); - - new_utxo.log(); - info!( - "Account address is {:?} ,new utxo owner address is {:?}", - hex::encode(acc_addr), - hex::encode(new_utxo.owner) - ); - info!( - "Account {:?} got new utxo with amount {:?} and asset {:?}", - hex::encode(acc_addr), - new_utxo.amount, - new_utxo.asset, - ); - } - } - - Ok(()) - } - - pub async fn split_utxo( - &self, - utxo: UTXO, - commitment_in: [u8; 32], - receivers: Vec<(u128, AccountAddress)>, - visibility_list: [bool; 3], - ) -> Result<(Transaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> { - let acc_map_read_guard = self.storage.read().await; - - let account = acc_map_read_guard.acc_map.get(&utxo.owner).unwrap(); - - let nullifier = generate_nullifiers( - &utxo, - &account - .key_holder - .utxo_secret_key_holder - .nullifier_secret_key - .to_bytes(), - ); - - let (resulting_utxos, receipt) = prove_send_utxo(utxo, receivers)?; - let utxo_hashes = resulting_utxos - .iter() - .map(|(utxo, addr)| (*addr, utxo.hash)) - .collect(); - - let utxos: Vec = resulting_utxos - .iter() - .map(|(utxo, _)| utxo.clone()) - .collect(); - - let ephm_key_holder = EphemeralKeyHolder::new_os_random(); - ephm_key_holder.log(); - - let eph_pub_key = - serde_json::to_vec(&ephm_key_holder.generate_ephemeral_public_key()).unwrap(); - - let encoded_data: Vec<(Vec, Vec, u8)> = utxos - .iter() - .map(|utxo_enc| { - let accout_enc = acc_map_read_guard.acc_map.get(&utxo_enc.owner).unwrap(); - - let (ciphertext, nonce) = Account::encrypt_data( - &ephm_key_holder, - accout_enc.key_holder.viewing_public_key, - &serde_json::to_vec(&utxo_enc).unwrap(), - ); - - let tag = accout_enc.make_tag(); - - (ciphertext, nonce.to_vec(), tag) - }) - .collect(); - - let commitments = generate_commitments(&utxos); - - let publication = ActionData::UTXOPublication(UTXOPublication { - utxos: utxos - .iter() - .enumerate() - .filter_map(|(id, item)| { - if visibility_list[id] { - Some(item.clone()) - } else { - None - } - }) - .collect(), - }); - - let send_utxo_addr_bytes: Vec = zkvm::test_methods::SEND_UTXO_ID - .iter() - .flat_map(|num| num.to_le_bytes()) - .collect(); - let sc_addr = hex::encode(send_utxo_addr_bytes); - - //Sc does not change its state - let state_changes: Vec = vec![]; - let new_len = 0; - let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len); - - let sc_state = acc_map_read_guard - .block_store - .get_sc_sc_state(&sc_addr) - .map_err(ExecutionFailureKind::db_error)?; - - let mut vec_values_u64: Vec> = sc_state - .into_iter() - .map(|slice| vec_u8_to_vec_u64(slice.to_vec())) - .collect(); - - let context = acc_map_read_guard.produce_context(account.address); - - //Will not panic, as PublicScContext is serializable - let context_public_info: Vec = context.produce_u64_list_from_context().unwrap(); - vec_values_u64.push(context_public_info); - - let vec_public_info: Vec = vec_values_u64.into_iter().flatten().collect(); - - let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info); - - let transaction_body = TransactionBody { - tx_kind: TxKind::Shielded, - execution_input: vec![], - execution_output: serde_json::to_vec(&publication).unwrap(), - utxo_commitments_spent_hashes: vec![commitment_in], - utxo_commitments_created_hashes: commitments - .clone() - .into_iter() - .map(|hash_data| hash_data.try_into().unwrap()) - .collect(), - nullifier_created_hashes: vec![nullifier.try_into().unwrap()], - execution_proof_private: sc_core::transaction_payloads_tools::encode_receipt(receipt) - .unwrap(), - encoded_data, - ephemeral_pub_key: eph_pub_key.to_vec(), - commitment, - tweak, - secret_r, - sc_addr, - state_changes, - }; - let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key(); - - Ok(( - Transaction::new(transaction_body, key_to_sign_transaction), - utxo_hashes, - )) - } - - pub async fn send_split_tx( - &self, - utxo: UTXO, - comm_hash: [u8; 32], - receivers: Vec<(u128, AccountAddress)>, - visibility_list: [bool; 3], - ) -> Result<(SendTxResponse, Vec<([u8; 32], [u8; 32])>, Vec<[u8; 32]>), ExecutionFailureKind> - { - //Considering proof time, needs to be done before proof - let tx_roots = self.get_roots().await; - - let point_before_prove = std::time::Instant::now(); - let (tx, utxo_hashes) = self - .split_utxo(utxo, comm_hash, receivers, visibility_list) - .await?; - tx.body().log(); - 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"); - - let commitments = tx.body().utxo_commitments_created_hashes.clone(); - - Ok(( - self.sequencer_client.send_tx(tx, tx_roots).await?, - utxo_hashes, - commitments, - )) - } - - pub async fn operate_account_send_split_utxo( - &mut self, - addrs_receivers: [AccountAddress; 3], - utxo: UTXO, - comm_gen_hash: [u8; 32], - visibility_list: [bool; 3], - ) -> Result<(Vec, Vec<[u8; 32]>), ExecutionFailureKind> { - let (resp, new_utxo_hashes, commitments_hashes) = self - .send_split_tx( - utxo.clone(), - comm_gen_hash, - addrs_receivers.map(|addr| (utxo.amount / 3, addr)).to_vec(), - visibility_list, - ) - .await?; - info!("Response for send shielded is {resp:?}"); - - info!("Awaiting new blocks"); - tokio::time::sleep(std::time::Duration::from_secs(BLOCK_GEN_DELAY_SECS)).await; - - let new_utxos: Vec = { - let mut write_guard = self.storage.write().await; - - new_utxo_hashes - .into_iter() - .map(|(acc_addr_rec, new_utxo_hash)| { - let acc = write_guard.acc_map.get_mut(&acc_addr_rec).unwrap(); - - let new_utxo = acc.utxos.get(&new_utxo_hash).unwrap().clone(); - new_utxo.log(); - - info!( - "Account address is {:?} ,new utxo owner address is {:?}", - hex::encode(acc_addr_rec), - hex::encode(new_utxo.owner) - ); - info!( - "Account {:?} got new utxo with amount {:?}", - hex::encode(acc_addr_rec), - new_utxo.amount - ); - - new_utxo - }) - .collect() - }; - - Ok((new_utxos, commitments_hashes)) - } - - ///Mint utxo, make it public - pub async fn subscenario_1(&mut self) -> Result<(), ExecutionFailureKind> { - let acc_addr = self.create_new_account().await; - - let (new_utxo, comm_gen_hash) = self.operate_account_mint_private(acc_addr, 100).await?; - - self.operate_account_send_deshielded_one_receiver(acc_addr, new_utxo, comm_gen_hash) - .await?; - - Ok(()) - } - - ///Mint utxo, privately send it to another user - pub async fn subscenario_2(&mut self) -> Result<(), ExecutionFailureKind> { - let acc_addr = self.create_new_account().await; - let acc_addr_rec = self.create_new_account().await; - - let (new_utxo, comm_gen_hash) = self.operate_account_mint_private(acc_addr, 100).await?; - - self.operate_account_send_private_one_receiver(acc_addr_rec, new_utxo, comm_gen_hash) - .await?; - - Ok(()) - } - - ///Mint utxo, deshielded send it to another user - pub async fn subscenario_3(&mut self) -> Result<(), ExecutionFailureKind> { - let acc_addr = self.create_new_account().await; - let acc_addr_rec = self.create_new_account().await; - - let (new_utxo, comm_gen_hash) = self.operate_account_mint_private(acc_addr, 100).await?; - - self.operate_account_send_deshielded_one_receiver(acc_addr_rec, new_utxo, comm_gen_hash) - .await?; - - Ok(()) - } - - ///First complex scenario. - /// Creating accounts A, B, C, D. - /// Minting UTXO for A, splitting it between B, C, D. - /// Variable `visibility_list` decides, which of actions will be visible on blockchain. - /// Variable `publication index` decides, who of B, C or D moves its UTXO into public state. - pub async fn scenario_1( - &mut self, - visibility_list: [bool; 3], - publication_index: usize, - ) -> Result<(), ExecutionFailureKind> { - let acc_addr_sender = self.create_new_account().await; - - let acc_addr_rec_1 = self.create_new_account().await; - let acc_addr_rec_2 = self.create_new_account().await; - let acc_addr_rec_3 = self.create_new_account().await; - - let addrs_receivers = [acc_addr_rec_1, acc_addr_rec_2, acc_addr_rec_3]; - - let (new_utxo, comm_gen_hash) = self - .operate_account_mint_private(acc_addr_sender, 99) - .await?; - - let (new_utxos, comm_gen_hashes) = self - .operate_account_send_split_utxo( - addrs_receivers, - new_utxo, - comm_gen_hash, - visibility_list, - ) - .await?; - - self.operate_account_send_deshielded_one_receiver( - addrs_receivers[publication_index], - new_utxos[publication_index].clone(), - comm_gen_hashes[publication_index], - ) - .await?; - - Ok(()) - } - - ///Mint number of different assets with same amount for account - pub async fn scenario_2( - &mut self, - number_of_assets: usize, - number_to_send: usize, - ) -> Result<(), ExecutionFailureKind> { - let acc_addr_sender = self.create_new_account().await; - let acc_addr_receiver = self.create_new_account().await; - - let (utxos, comm_gen_hashes) = self - .operate_account_mint_multiple_assets_private(acc_addr_sender, 100, number_of_assets) - .await?; - - self.operate_account_send_private_multiple_assets_one_receiver( - acc_addr_sender, - acc_addr_receiver, - utxos, - comm_gen_hashes, - number_to_send, - ) - .await?; - - Ok(()) - } } pub fn generate_commitments_helper(input_utxos: &[UTXO]) -> Vec<[u8; 32]> { diff --git a/node_core/src/pre_start.rs b/node_core/src/pre_start.rs deleted file mode 100644 index e79dafc..0000000 --- a/node_core/src/pre_start.rs +++ /dev/null @@ -1,71 +0,0 @@ -use anyhow::Result; -use log::info; - -use crate::chain_storage::NodeChainStore; - -///Addres of public fund transfer account, as no such binary exists for zkVM -pub const PUBLIC_DEPOSIT_ID: [u8; 32] = [0; 32]; - -///Setups public states of default smart conracts as empty -pub async fn setup_empty_sc_states(node: &NodeChainStore) -> Result<()> { - info!("Filling up public states of default smart contracts"); - - let empty_state = vec![]; - - let public_deposit_addr = hex::encode(PUBLIC_DEPOSIT_ID); - node.block_store.put_sc_sc_state( - &public_deposit_addr, - empty_state.len(), - empty_state.clone(), - )?; - info!("Public transfer state set"); - - let mint_utxo_addr_bytes: Vec = zkvm::test_methods::MINT_UTXO_ID - .iter() - .flat_map(|num| num.to_le_bytes()) - .collect(); - let mint_utxo_addr = hex::encode(mint_utxo_addr_bytes); - node.block_store - .put_sc_sc_state(&mint_utxo_addr, empty_state.len(), empty_state.clone())?; - info!("Mint UTXO state set"); - - let single_utxo_transfer_addr_bytes: Vec = zkvm::test_methods::SEND_UTXO_ID - .iter() - .flat_map(|num| num.to_le_bytes()) - .collect(); - let single_utxo_transfer_addr = hex::encode(single_utxo_transfer_addr_bytes); - node.block_store.put_sc_sc_state( - &single_utxo_transfer_addr, - empty_state.len(), - empty_state.clone(), - )?; - info!("Single UTXO transfer state set"); - - let mint_utxo_multiple_assets_addr_bytes: Vec = - zkvm::test_methods::MINT_UTXO_MULTIPLE_ASSETS_ID - .iter() - .flat_map(|num| num.to_le_bytes()) - .collect(); - let mint_utxo_multiple_assets_addr = hex::encode(mint_utxo_multiple_assets_addr_bytes); - node.block_store.put_sc_sc_state( - &mint_utxo_multiple_assets_addr, - empty_state.len(), - empty_state.clone(), - )?; - info!("Mint UTXO multiple assets state set"); - - let multiple_assets_utxo_transfer_addr_bytes: Vec = - zkvm::test_methods::SEND_UTXO_MULTIPLE_ASSETS_ID - .iter() - .flat_map(|num| num.to_le_bytes()) - .collect(); - let multiple_assets_utxo_transfer_addr = hex::encode(multiple_assets_utxo_transfer_addr_bytes); - node.block_store.put_sc_sc_state( - &multiple_assets_utxo_transfer_addr, - empty_state.len(), - empty_state.clone(), - )?; - info!("Multiple_assets UTXO transfer state set"); - - Ok(()) -} diff --git a/node_rpc/src/process.rs b/node_rpc/src/process.rs index 29ac787..4546639 100644 --- a/node_rpc/src/process.rs +++ b/node_rpc/src/process.rs @@ -1,7 +1,6 @@ use std::sync::atomic::Ordering; use actix_web::Error as HttpError; -use node_core::generate_commitments_helper; use serde_json::Value; use common::rpc_primitives::{ @@ -11,25 +10,12 @@ use common::rpc_primitives::{ }; use common::transaction::ActionData; -use common::rpc_primitives::requests::{ - GetBlockDataRequest, GetBlockDataResponse, GetLastBlockRequest, GetLastBlockResponse, -}; +use common::rpc_primitives::requests::{GetLastBlockRequest, GetLastBlockResponse}; -use crate::types::{ - err_rpc::cast_common_execution_error_into_rpc_error, - rpc_structs::{ - CreateAccountRequest, CreateAccountResponse, ExecuteScenarioMultipleSendRequest, - ExecuteScenarioMultipleSendResponse, ExecuteScenarioSplitRequest, - ExecuteScenarioSplitResponse, ExecuteSubscenarioRequest, ExecuteSubscenarioResponse, - ShowAccountPublicBalanceRequest, ShowAccountPublicBalanceResponse, ShowAccountUTXORequest, - ShowAccountUTXOResponse, ShowTransactionRequest, ShowTransactionResponse, - UTXOShortEssentialStruct, WriteMintPrivateUTXOMultipleAssetsRequest, - WriteMintPrivateUTXOMultipleAssetsResponse, WriteMintPrivateUTXORequest, - WriteMintPrivateUTXOResponse, WriteSendDeshieldedBalanceRequest, - WriteSendDeshieldedUTXOResponse, WriteSendPrivateUTXORequest, WriteSendPrivateUTXOResponse, - WriteSendShieldedUTXORequest, WriteSendShieldedUTXOResponse, WriteSendSplitUTXOResponse, - WriteSplitUTXORequest, - }, +use crate::types::rpc_structs::{ + CreateAccountRequest, CreateAccountResponse, ShowAccountPublicBalanceRequest, + ShowAccountPublicBalanceResponse, ShowAccountUTXORequest, ShowAccountUTXOResponse, + ShowTransactionRequest, ShowTransactionResponse, }; pub const CREATE_ACCOUNT: &str = "create_account"; @@ -71,80 +57,6 @@ 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 - .map_err(cast_common_execution_error_into_rpc_error)?, - 2 => store - .subscenario_2() - .await - .map_err(cast_common_execution_error_into_rpc_error)?, - 3 => store - .subscenario_3() - .await - .map_err(cast_common_execution_error_into_rpc_error)?, - _ => return Err(RpcErr(RpcError::invalid_params("Scenario id not found"))), - } - } - - let helperstruct = ExecuteSubscenarioResponse { - scenario_result: SUCCESS.to_string(), - }; - - respond(helperstruct) - } - - async fn process_request_execute_scenario_split( - &self, - request: Request, - ) -> Result { - let req = ExecuteScenarioSplitRequest::parse(Some(request.params))?; - - { - let mut store = self.node_chain_store.lock().await; - - store - .scenario_1(req.visibility_list, req.publication_index) - .await - .map_err(cast_common_execution_error_into_rpc_error)?; - } - - let helperstruct = ExecuteScenarioSplitResponse { - scenario_result: SUCCESS.to_string(), - }; - - respond(helperstruct) - } - - async fn process_request_execute_scenario_multiple_send( - &self, - request: Request, - ) -> Result { - let req = ExecuteScenarioMultipleSendRequest::parse(Some(request.params))?; - - { - let mut store = self.node_chain_store.lock().await; - - store - .scenario_2(req.number_of_assets, req.number_to_send) - .await - .map_err(cast_common_execution_error_into_rpc_error)?; - } - - let helperstruct = ExecuteScenarioMultipleSendResponse { - scenario_result: SUCCESS.to_string(), - }; - - respond(helperstruct) - } - async fn process_create_account(&self, request: Request) -> Result { let _req = CreateAccountRequest::parse(Some(request.params))?; @@ -161,24 +73,6 @@ impl JsonHandler { respond(helperstruct) } - async fn process_get_block_data(&self, request: Request) -> Result { - let req = GetBlockDataRequest::parse(Some(request.params))?; - - let block = { - let guard = self.node_chain_store.lock().await; - - { - let read_guard = guard.storage.read().await; - - read_guard.block_store.get_block_at_id(req.block_id)? - } - }; - - let helperstruct = GetBlockDataResponse { block }; - - respond(helperstruct) - } - async fn process_get_last_block(&self, request: Request) -> Result { let _req = GetLastBlockRequest::parse(Some(request.params))?; @@ -349,406 +243,14 @@ impl JsonHandler { respond(helperstruct) } - pub async fn process_write_mint_utxo(&self, request: Request) -> Result { - let req = WriteMintPrivateUTXORequest::parse(Some(request.params))?; - - let acc_addr_hex_dec = hex::decode(req.account_addr.clone()).map_err(|_| { - RpcError::parse_error("Failed to decode account address from hex string".to_string()) - })?; - - let acc_addr: [u8; 32] = acc_addr_hex_dec.try_into().map_err(|_| { - RpcError::parse_error("Failed to parse account address from bytes".to_string()) - })?; - - let (utxo, commitment_hash) = { - let mut cover_guard = self.node_chain_store.lock().await; - - cover_guard - .operate_account_mint_private(acc_addr, req.amount as u128) - .await - .map_err(cast_common_execution_error_into_rpc_error)? - }; - - let helperstruct = WriteMintPrivateUTXOResponse { - status: SUCCESS.to_string(), - utxo: UTXOShortEssentialStruct { - hash: hex::encode(utxo.hash), - commitment_hash: hex::encode(commitment_hash), - asset: utxo.asset, - }, - }; - - respond(helperstruct) - } - - pub async fn process_write_mint_utxo_multiple_assets( - &self, - request: Request, - ) -> Result { - let req = WriteMintPrivateUTXOMultipleAssetsRequest::parse(Some(request.params))?; - - let acc_addr_hex_dec = hex::decode(req.account_addr.clone()).map_err(|_| { - RpcError::parse_error("Failed to decode account address from hex string".to_string()) - })?; - - let acc_addr: [u8; 32] = acc_addr_hex_dec.try_into().map_err(|_| { - RpcError::parse_error("Failed to parse account address from bytes".to_string()) - })?; - - let (utxos, commitment_hashes) = { - let mut cover_guard = self.node_chain_store.lock().await; - - cover_guard - .operate_account_mint_multiple_assets_private( - acc_addr, - req.amount as u128, - req.num_of_assets, - ) - .await - .map_err(cast_common_execution_error_into_rpc_error)? - }; - - let helperstruct = WriteMintPrivateUTXOMultipleAssetsResponse { - status: SUCCESS.to_string(), - utxos: utxos - .into_iter() - .zip(commitment_hashes) - .map(|(utxo, comm_hash)| UTXOShortEssentialStruct { - hash: hex::encode(utxo.hash), - commitment_hash: hex::encode(comm_hash), - asset: utxo.asset, - }) - .collect(), - }; - - respond(helperstruct) - } - - pub async fn process_write_send_private_utxo(&self, request: Request) -> Result { - let req = WriteSendPrivateUTXORequest::parse(Some(request.params))?; - - let acc_addr_hex_dec_sender = - hex::decode(req.account_addr_sender.clone()).map_err(|_| { - RpcError::parse_error( - "Failed to decode account address from hex string".to_string(), - ) - })?; - - let acc_addr_sender: [u8; 32] = acc_addr_hex_dec_sender.try_into().map_err(|_| { - RpcError::parse_error("Failed to parse account address from bytes".to_string()) - })?; - - let acc_addr_hex_dec = hex::decode(req.account_addr_receiver.clone()).map_err(|_| { - RpcError::parse_error("Failed to decode account address from hex string".to_string()) - })?; - - let acc_addr: [u8; 32] = acc_addr_hex_dec.try_into().map_err(|_| { - RpcError::parse_error("Failed to parse account address from bytes".to_string()) - })?; - - let utxo_hash_hex_dec = hex::decode(req.utxo_hash.clone()).map_err(|_| { - RpcError::parse_error("Failed to decode utxo hash from hex string".to_string()) - })?; - - let utxo_hash: [u8; 32] = utxo_hash_hex_dec.try_into().map_err(|_| { - RpcError::parse_error("Failed to parse utxo hash from bytes".to_string()) - })?; - - let comm_hash_hex_dec = hex::decode(req.utxo_commitment.clone()).map_err(|_| { - RpcError::parse_error("Failed to decode commitment hash from hex string".to_string()) - })?; - - let comm_hash: [u8; 32] = comm_hash_hex_dec.try_into().map_err(|_| { - RpcError::parse_error("Failed to parse commitment hash from bytes".to_string()) - })?; - - let new_utxo_rec = { - let mut cover_guard = self.node_chain_store.lock().await; - - let utxo_to_send = { - let mut under_guard = cover_guard.storage.write().await; - - let acc = under_guard - .acc_map - .get_mut(&acc_addr_sender) - .ok_or(RpcError::new_internal_error(None, ACCOUNT_NOT_FOUND))?; - - acc.utxos - .get(&utxo_hash) - .ok_or(RpcError::new_internal_error( - None, - "UTXO does not exist in tree", - ))? - .clone() - }; - - cover_guard - .operate_account_send_private_one_receiver(acc_addr, utxo_to_send, comm_hash) - .await - .map_err(cast_common_execution_error_into_rpc_error)? - }; - - let helperstruct = WriteSendPrivateUTXOResponse { - status: SUCCESS.to_string(), - utxo_result: UTXOShortEssentialStruct { - hash: hex::encode(new_utxo_rec.hash), - asset: new_utxo_rec.asset.clone(), - commitment_hash: hex::encode(generate_commitments_helper(&[new_utxo_rec])[0]), - }, - }; - - respond(helperstruct) - } - - pub async fn process_write_send_shielded_utxo( - &self, - request: Request, - ) -> Result { - let req = WriteSendShieldedUTXORequest::parse(Some(request.params))?; - - let acc_addr_hex_dec_sender = - hex::decode(req.account_addr_sender.clone()).map_err(|_| { - RpcError::parse_error( - "Failed to decode account address sender from hex string".to_string(), - ) - })?; - - let acc_addr_sender: [u8; 32] = acc_addr_hex_dec_sender.try_into().map_err(|_| { - RpcError::parse_error("Failed to parse account address sender from bytes".to_string()) - })?; - - let acc_addr_hex_dec_rec = - hex::decode(req.account_addr_receiver.clone()).map_err(|_| { - RpcError::parse_error( - "Failed to decode account address receiver from hex string".to_string(), - ) - })?; - - let acc_addr_rec: [u8; 32] = acc_addr_hex_dec_rec.try_into().map_err(|_| { - RpcError::parse_error("Failed to parse account address receiver from bytes".to_string()) - })?; - - let new_utxo_rec = { - let mut cover_guard = self.node_chain_store.lock().await; - - cover_guard - .operate_account_send_shielded_one_receiver( - acc_addr_sender, - acc_addr_rec, - req.amount as u128, - ) - .await - .map_err(cast_common_execution_error_into_rpc_error)? - }; - - let helperstruct = WriteSendShieldedUTXOResponse { - status: SUCCESS.to_string(), - utxo_result: UTXOShortEssentialStruct { - hash: hex::encode(new_utxo_rec.hash), - asset: new_utxo_rec.asset.clone(), - commitment_hash: hex::encode(generate_commitments_helper(&[new_utxo_rec])[0]), - }, - }; - - respond(helperstruct) - } - - pub async fn process_write_send_deshielded_utxo( - &self, - request: Request, - ) -> Result { - let req = WriteSendDeshieldedBalanceRequest::parse(Some(request.params))?; - - let acc_addr_hex_dec_sender = - hex::decode(req.account_addr_sender.clone()).map_err(|_| { - RpcError::parse_error( - "Failed to decode account address from hex string".to_string(), - ) - })?; - - let acc_addr_sender: [u8; 32] = acc_addr_hex_dec_sender.try_into().map_err(|_| { - RpcError::parse_error("Failed to parse account address from bytes".to_string()) - })?; - - let acc_addr_hex_dec = hex::decode(req.account_addr_receiver.clone()).map_err(|_| { - RpcError::parse_error("Failed to decode account address from hex string".to_string()) - })?; - - let acc_addr: [u8; 32] = acc_addr_hex_dec.try_into().map_err(|_| { - RpcError::parse_error("Failed to parse account address from bytes".to_string()) - })?; - - let utxo_hash_hex_dec = hex::decode(req.utxo_hash.clone()).map_err(|_| { - RpcError::parse_error("Failed to decode utxo hash from hex string".to_string()) - })?; - - let utxo_hash: [u8; 32] = utxo_hash_hex_dec.try_into().map_err(|_| { - RpcError::parse_error("Failed to parse utxo hash from bytes".to_string()) - })?; - - let comm_hash_hex_dec = hex::decode(req.utxo_commitment.clone()).map_err(|_| { - RpcError::parse_error("Failed to decode commitment hash from hex string".to_string()) - })?; - - let comm_hash: [u8; 32] = comm_hash_hex_dec.try_into().map_err(|_| { - RpcError::parse_error("Failed to parse commitment hash from bytes".to_string()) - })?; - - { - let mut cover_guard = self.node_chain_store.lock().await; - - let utxo_to_send = { - let mut under_guard = cover_guard.storage.write().await; - - let acc = under_guard - .acc_map - .get_mut(&acc_addr_sender) - .ok_or(RpcError::new_internal_error(None, ACCOUNT_NOT_FOUND))?; - - acc.utxos - .get(&utxo_hash) - .ok_or(RpcError::new_internal_error( - None, - "UTXO does not exist in tree", - ))? - .clone() - }; - - cover_guard - .operate_account_send_deshielded_one_receiver(acc_addr, utxo_to_send, comm_hash) - .await - .map_err(cast_common_execution_error_into_rpc_error)? - }; - - let helperstruct = WriteSendDeshieldedUTXOResponse { - status: SUCCESS.to_string(), - }; - - respond(helperstruct) - } - - pub async fn process_write_send_split_utxo(&self, request: Request) -> Result { - let req = WriteSplitUTXORequest::parse(Some(request.params))?; - - let acc_addr_hex_dec_sender = - hex::decode(req.account_addr_sender.clone()).map_err(|_| { - RpcError::parse_error( - "Failed to decode account address from hex string".to_string(), - ) - })?; - - let acc_addr_sender: [u8; 32] = acc_addr_hex_dec_sender.try_into().map_err(|_| { - RpcError::parse_error("Failed to parse account address from bytes".to_string()) - })?; - - let acc_addresses = { - let mut res_addrs = vec![]; - - for item in req.account_addr_receivers { - let hex_dec_item = hex::decode(item).map_err(|_| { - RpcError::parse_error( - "Failed to decode account address from hex string".to_string(), - ) - })?; - - let dec_item = hex_dec_item.try_into().map_err(|_| { - RpcError::parse_error( - "Failed to decode account address from hex string".to_string(), - ) - })?; - - res_addrs.push(dec_item); - } - - res_addrs.try_into().unwrap() - }; - - let utxo_hash_hex_dec = hex::decode(req.utxo_hash.clone()).map_err(|_| { - RpcError::parse_error("Failed to decode utxo hash from hex string".to_string()) - })?; - - let utxo_hash: [u8; 32] = utxo_hash_hex_dec.try_into().map_err(|_| { - RpcError::parse_error("Failed to parse utxo hash from bytes".to_string()) - })?; - - let comm_hash_hex_dec = hex::decode(req.utxo_commitment.clone()).map_err(|_| { - RpcError::parse_error("Failed to decode commitment hash from hex string".to_string()) - })?; - - let comm_hash: [u8; 32] = comm_hash_hex_dec.try_into().map_err(|_| { - RpcError::parse_error("Failed to parse commitment hash from bytes".to_string()) - })?; - - let (new_utxos, commitment_hashes) = { - let mut cover_guard = self.node_chain_store.lock().await; - - let utxo_to_send = { - let mut under_guard = cover_guard.storage.write().await; - - let acc = under_guard - .acc_map - .get_mut(&acc_addr_sender) - .ok_or(RpcError::new_internal_error(None, ACCOUNT_NOT_FOUND))?; - - acc.utxos - .get(&utxo_hash) - .ok_or(RpcError::new_internal_error( - None, - "UTXO does not exist in tree", - ))? - .clone() - }; - - cover_guard - .operate_account_send_split_utxo( - acc_addresses, - utxo_to_send, - comm_hash, - req.visibility_list, - ) - .await - .map_err(cast_common_execution_error_into_rpc_error)? - }; - - let helperstruct = WriteSendSplitUTXOResponse { - status: SUCCESS.to_string(), - utxo_results: new_utxos - .into_iter() - .zip(commitment_hashes) - .map(|(utxo, comm_hash)| UTXOShortEssentialStruct { - hash: hex::encode(utxo.hash), - commitment_hash: hex::encode(comm_hash), - asset: utxo.asset, - }) - .collect(), - }; - - respond(helperstruct) - } - pub async fn process_request_internal(&self, request: Request) -> Result { match request.method.as_ref() { //Todo : Add handling of more JSON RPC methods CREATE_ACCOUNT => self.process_create_account(request).await, - EXECUTE_SUBSCENARIO => self.process_request_execute_subscenario(request).await, - GET_BLOCK => self.process_get_block_data(request).await, GET_LAST_BLOCK => self.process_get_last_block(request).await, - EXECUTE_SCENARIO_SPLIT => self.process_request_execute_scenario_split(request).await, - EXECUTE_SCENARIO_MULTIPLE_SEND => { - self.process_request_execute_scenario_multiple_send(request) - .await - } SHOW_ACCOUNT_PUBLIC_BALANCE => self.process_show_account_public_balance(request).await, SHOW_ACCOUNT_UTXO => self.process_show_account_utxo_request(request).await, SHOW_TRANSACTION => self.process_show_transaction(request).await, - WRITE_MINT_UTXO => self.process_write_mint_utxo(request).await, - WRITE_MINT_UTXO_MULTIPLE_ASSETS => { - self.process_write_mint_utxo_multiple_assets(request).await - } - WRITE_SEND_UTXO_PRIVATE => self.process_write_send_private_utxo(request).await, - WRITE_SEND_UTXO_SHIELDED => self.process_write_send_shielded_utxo(request).await, - WRITE_SEND_UTXO_DESHIELDED => self.process_write_send_deshielded_utxo(request).await, - WRITE_SPLIT_UTXO => self.process_write_send_split_utxo(request).await, _ => Err(RpcErr(RpcError::method_not_found(request.method))), } }