From cde9f0a5c889f0203331f409869c9a835f168852 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Thu, 15 May 2025 11:38:37 +0300 Subject: [PATCH 1/8] feat: sparse trees preparation for serialization --- accounts/src/account_core/mod.rs | 38 ++++-- common/src/nullifier_sparse_merkle_tree.rs | 129 +++++++++++++++++---- node_core/src/chain_storage/mod.rs | 26 ++++- node_core/src/executions/de.rs | 15 ++- node_core/src/executions/private_exec.rs | 15 ++- node_core/src/executions/se.rs | 15 ++- sc_core/src/proofs_circuits.rs | 15 ++- sequencer_core/src/lib.rs | 22 +++- utxo/src/utxo_tree.rs | 113 ++++++++++++++---- 9 files changed, 314 insertions(+), 74 deletions(-) diff --git a/accounts/src/account_core/mod.rs b/accounts/src/account_core/mod.rs index 2d3417c..afa0197 100644 --- a/accounts/src/account_core/mod.rs +++ b/accounts/src/account_core/mod.rs @@ -7,7 +7,7 @@ use log::info; use serde::Serialize; use utxo::{ utxo_core::{UTXOPayload, UTXO}, - utxo_tree::UTXOSparseMerkleTree, + utxo_tree::{UTXOSparseMerkleTree, UTXOTreeInput}, }; use crate::key_management::{ @@ -100,7 +100,7 @@ impl Account { Ok(()) } - pub fn add_new_utxo_outputs(&mut self, utxos: Vec) -> Result<()> { + pub fn add_new_utxo_outputs(&mut self, utxos: Vec) -> Result<()> { Ok(self.utxo_tree.insert_items(utxos)?) } @@ -113,6 +113,9 @@ impl Account { asset: Asset, amount: u128, privacy_flag: bool, + utxo_id: u64, + tx_id: u64, + block_id: u64, ) -> Result<()> { let payload_with_asset = UTXOPayload { owner: self.address, @@ -123,7 +126,14 @@ impl Account { let asset_utxo = UTXO::create_utxo_from_payload(payload_with_asset)?; - self.utxo_tree.insert_item(asset_utxo)?; + let input_utxo = UTXOTreeInput { + utxo_id, + tx_id, + block_id, + utxo: asset_utxo, + }; + + self.utxo_tree.insert_item(input_utxo)?; Ok(()) } @@ -163,14 +173,24 @@ mod tests { UTXONullifier::default() } - fn generate_dummy_utxo(address: TreeHashType, amount: u128) -> anyhow::Result { + fn generate_dummy_utxo( + address: TreeHashType, + amount: u128, + utxo_id: u64, + ) -> anyhow::Result { let payload = UTXOPayload { owner: address, asset: vec![], amount, privacy_flag: false, }; - UTXO::create_utxo_from_payload(payload) + let utxo = UTXO::create_utxo_from_payload(payload); + utxo.map(|utxo| UTXOTreeInput { + utxo_id, + tx_id: 1, + block_id: 1, + utxo, + }) } #[test] @@ -184,7 +204,7 @@ mod tests { #[test] fn test_mark_spent_utxo() { let mut account = Account::new(); - let utxo = generate_dummy_utxo(account.address, 100).unwrap(); + let utxo = generate_dummy_utxo(account.address, 100, 1).unwrap(); account.add_new_utxo_outputs(vec![utxo]).unwrap(); let mut utxo_nullifier_map = HashMap::new(); @@ -199,8 +219,8 @@ mod tests { #[test] fn test_add_new_utxo_outputs() { let mut account = Account::new(); - let utxo1 = generate_dummy_utxo(account.address, 100).unwrap(); - let utxo2 = generate_dummy_utxo(account.address, 200).unwrap(); + let utxo1 = generate_dummy_utxo(account.address, 100, 1).unwrap(); + let utxo2 = generate_dummy_utxo(account.address, 200, 2).unwrap(); let result = account.add_new_utxo_outputs(vec![utxo1.clone(), utxo2.clone()]); @@ -222,7 +242,7 @@ mod tests { let asset = "dummy_asset"; let amount = 1000u128; - let result = account.add_asset(asset, amount, false); + let result = account.add_asset(asset, amount, false, 1, 1, 1); assert!(result.is_ok()); assert_eq!(account.utxo_tree.store.len(), 1); diff --git a/common/src/nullifier_sparse_merkle_tree.rs b/common/src/nullifier_sparse_merkle_tree.rs index 282fccc..c6707a7 100644 --- a/common/src/nullifier_sparse_merkle_tree.rs +++ b/common/src/nullifier_sparse_merkle_tree.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeMap; + use monotree::database::MemoryDB; use monotree::hasher::Blake3; use monotree::{Hasher, Monotree, Proof}; @@ -5,10 +7,31 @@ use monotree::{Hasher, Monotree, Proof}; use crate::merkle_tree_public::TreeHashType; use crate::nullifier::UTXONullifier; +#[derive(Debug, Clone)] +pub struct NullifierTreeInput { + pub nullifier_id: u64, + pub tx_id: u64, + pub block_id: u64, + pub nullifier: UTXONullifier, +} + +#[derive(Debug, Clone)] +pub struct TreeTxWithNullifierId { + pub id: u64, + pub nullifiers: BTreeMap, +} + +#[derive(Debug, Clone)] +pub struct TreeBlockWithTxId { + pub id: u64, + pub txs: BTreeMap, +} + pub struct NullifierSparseMerkleTree { pub curr_root: Option, pub tree: Monotree, pub hasher: Blake3, + pub leafs: BTreeMap, } impl NullifierSparseMerkleTree { @@ -17,30 +40,71 @@ impl NullifierSparseMerkleTree { curr_root: None, tree: Monotree::default(), hasher: Blake3::new(), + leafs: BTreeMap::new(), } } - pub fn insert_item(&mut self, nullifier: UTXONullifier) -> Result<(), monotree::Errors> { + pub fn modify_leavs_with_nullifier_input(&mut self, tree_nullifier: NullifierTreeInput) { + self.leafs + .entry(tree_nullifier.block_id) + .and_modify(|tree_block| { + tree_block + .txs + .entry(tree_nullifier.tx_id) + .and_modify(|tree_tx| { + tree_tx + .nullifiers + .insert(tree_nullifier.nullifier_id, tree_nullifier.nullifier); + }) + .or_insert(TreeTxWithNullifierId { + id: tree_nullifier.tx_id, + nullifiers: BTreeMap::new(), + }); + }) + .or_insert(TreeBlockWithTxId { + id: tree_nullifier.block_id, + txs: BTreeMap::new(), + }); + } + + pub fn insert_item( + &mut self, + tree_nullifier: NullifierTreeInput, + ) -> Result<(), monotree::Errors> { let root = self.curr_root.as_ref(); - let new_root = self - .tree - .insert(root, &nullifier.utxo_hash, &nullifier.utxo_hash)?; + let new_root = self.tree.insert( + root, + &tree_nullifier.nullifier.utxo_hash, + &tree_nullifier.nullifier.utxo_hash, + )?; self.curr_root = new_root; + self.modify_leavs_with_nullifier_input(tree_nullifier); + Ok(()) } - pub fn insert_items(&mut self, nullifiers: Vec) -> Result<(), monotree::Errors> { + pub fn insert_items( + &mut self, + tree_nullifiers: Vec, + ) -> Result<(), monotree::Errors> { let root = self.curr_root.as_ref(); - let hashes: Vec = nullifiers.iter().map(|nu| nu.utxo_hash).collect(); + let hashes: Vec = tree_nullifiers + .iter() + .map(|nu| nu.nullifier.utxo_hash) + .collect(); let new_root = self.tree.inserts(root, &hashes, &hashes)?; self.curr_root = new_root; + for tree_nullifier in tree_nullifiers { + self.modify_leavs_with_nullifier_input(tree_nullifier); + } + Ok(()) } @@ -130,6 +194,20 @@ mod tests { UTXONullifier { utxo_hash: hash } } + fn create_nullifier_input( + hash: TreeHashType, + nullifier_id: u64, + tx_id: u64, + block_id: u64, + ) -> NullifierTreeInput { + NullifierTreeInput { + nullifier_id, + tx_id, + block_id, + nullifier: create_nullifier(hash), + } + } + #[test] fn test_new_tree_initialization() { let tree = NullifierSparseMerkleTree::new(); @@ -139,9 +217,9 @@ mod tests { #[test] fn test_insert_single_item() { let mut tree = NullifierSparseMerkleTree::new(); - let nullifier = create_nullifier([1u8; 32]); // Sample 32-byte hash + let tree_nullifier = create_nullifier_input([1u8; 32], 1, 1, 1); // Sample 32-byte hash - let result = tree.insert_item(nullifier); + let result = tree.insert_item(tree_nullifier); assert!(result.is_ok()); assert!(tree.curr_root.is_some()); } @@ -149,13 +227,13 @@ mod tests { #[test] fn test_insert_multiple_items() { let mut tree = NullifierSparseMerkleTree::new(); - let nullifiers = vec![ - create_nullifier([1u8; 32]), - create_nullifier([2u8; 32]), - create_nullifier([3u8; 32]), + let tree_nullifiers = vec![ + create_nullifier_input([1u8; 32], 1, 1, 1), + create_nullifier_input([2u8; 32], 2, 1, 1), + create_nullifier_input([3u8; 32], 3, 1, 1), ]; - let result = tree.insert_items(nullifiers); + let result = tree.insert_items(tree_nullifiers); assert!(result.is_ok()); assert!(tree.curr_root.is_some()); } @@ -163,9 +241,9 @@ mod tests { #[test] fn test_search_item_inclusion() { let mut tree = NullifierSparseMerkleTree::new(); - let nullifier = create_nullifier([1u8; 32]); + let tree_nullifier = create_nullifier_input([1u8; 32], 1, 1, 1); - tree.insert_item(nullifier.clone()).unwrap(); + tree.insert_item(tree_nullifier.clone()).unwrap(); let result = tree.search_item_inclusion([1u8; 32]); assert!(result.is_ok()); @@ -179,13 +257,13 @@ mod tests { #[test] fn test_search_multiple_item_inclusions() { let mut tree = NullifierSparseMerkleTree::new(); - let nullifiers = vec![ - create_nullifier([1u8; 32]), - create_nullifier([2u8; 32]), - create_nullifier([3u8; 32]), + let tree_nullifiers = vec![ + create_nullifier_input([1u8; 32], 1, 1, 1), + create_nullifier_input([2u8; 32], 2, 1, 1), + create_nullifier_input([3u8; 32], 3, 1, 1), ]; - tree.insert_items(nullifiers).unwrap(); + tree.insert_items(tree_nullifiers).unwrap(); let search_hashes = vec![[1u8; 32], [2u8; 32], [99u8; 32]]; let result = tree.search_item_inclusions(&search_hashes); @@ -224,9 +302,9 @@ mod tests { #[test] fn test_insert_and_get_proof_of_existing_item() { let mut tree = NullifierSparseMerkleTree::new(); - let nullifier = create_nullifier([1u8; 32]); + let tree_nullifier = create_nullifier_input([1u8; 32], 1, 1, 1); - tree.insert_item(nullifier.clone()).unwrap(); + tree.insert_item(tree_nullifier.clone()).unwrap(); let proof_result = tree.get_non_membership_proof([1u8; 32]); assert!(proof_result.is_err()); @@ -235,9 +313,12 @@ mod tests { #[test] fn test_insert_and_get_proofs_of_existing_items() { let mut tree = NullifierSparseMerkleTree::new(); - let nullifiers = vec![create_nullifier([1u8; 32]), create_nullifier([2u8; 32])]; + let tree_nullifiers = vec![ + create_nullifier_input([1u8; 32], 1, 1, 1), + create_nullifier_input([2u8; 32], 2, 1, 1), + ]; - tree.insert_items(nullifiers).unwrap(); + tree.insert_items(tree_nullifiers).unwrap(); let proof_result = tree.get_non_membership_proofs(&[[1u8; 32], [2u8; 32]]); assert!(proof_result.is_err()); diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index f8bcf4e..3500c41 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -10,12 +10,12 @@ use common::{ block::Block, merkle_tree_public::merkle_tree::{PublicTransactionMerkleTree, UTXOCommitmentsMerkleTree}, nullifier::UTXONullifier, - nullifier_sparse_merkle_tree::NullifierSparseMerkleTree, + nullifier_sparse_merkle_tree::{NullifierSparseMerkleTree, NullifierTreeInput}, utxo_commitment::UTXOCommitment, }; use k256::AffinePoint; use public_context::PublicSCContext; -use utxo::utxo_core::UTXO; +use utxo::{utxo_core::UTXO, utxo_tree::UTXOTreeInput}; use crate::ActionData; @@ -54,7 +54,7 @@ impl NodeChainStore { } pub fn dissect_insert_block(&mut self, block: Block) -> Result<()> { - for tx in &block.transactions { + for (tx_id, tx) in block.transactions.iter().enumerate() { if !tx.execution_input.is_empty() { let public_action = serde_json::from_slice::(&tx.execution_input); @@ -101,7 +101,13 @@ impl NodeChainStore { tx.nullifier_created_hashes .clone() .into_iter() - .map(|hash| UTXONullifier { utxo_hash: hash }) + .enumerate() + .map(|(idx, hash)| NullifierTreeInput { + nullifier_id: idx as u64, + tx_id: tx_id as u64, + block_id: block.block_id, + nullifier: UTXONullifier { utxo_hash: hash }, + }) .collect(), )?; @@ -109,7 +115,9 @@ impl NodeChainStore { let ephemeral_public_key_sender = serde_json::from_slice::(&tx.ephemeral_pub_key)?; - for (ciphertext, nonce, tag) in tx.encoded_data.clone() { + for (utxo_id, (ciphertext, nonce, tag)) in + tx.encoded_data.clone().into_iter().enumerate() + { let slice = nonce.as_slice(); let nonce = accounts::key_management::constants_types::Nonce::clone_from_slice(slice); @@ -125,7 +133,13 @@ impl NodeChainStore { 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)?; + let input_utxo = UTXOTreeInput { + utxo_id: utxo_id as u64, + tx_id: tx_id as u64, + block_id: block.block_id, + utxo, + }; + acc.utxo_tree.insert_item(input_utxo)?; } } } diff --git a/node_core/src/executions/de.rs b/node_core/src/executions/de.rs index f73ba85..ddc5e81 100644 --- a/node_core/src/executions/de.rs +++ b/node_core/src/executions/de.rs @@ -1,4 +1,7 @@ +use std::collections::BTreeMap; + use bincode; +use common::nullifier_sparse_merkle_tree::NullifierTreeInput; use common::{ commitment::Commitment, commitments_sparse_merkle_tree::CommitmentsSparseMerkleTree, nullifier::UTXONullifier, nullifier_sparse_merkle_tree::NullifierSparseMerkleTree, @@ -106,15 +109,25 @@ pub fn validate_nullifiers_proof( root_nullifier: [u8; 32], nullifiers_proof: &[[u8; 32]], ) -> bool { + //There is no need for storage, so ids can be default there + let id = 1; + let mut nsmt = NullifierSparseMerkleTree { curr_root: Option::Some(root_nullifier), tree: Monotree::default(), hasher: Blake3::new(), + leafs: BTreeMap::new(), }; let nullifiers: Vec<_> = nullifiers_proof .into_iter() - .map(|n_p| UTXONullifier { utxo_hash: *n_p }) + .enumerate() + .map(|(idx, n_p)| NullifierTreeInput { + nullifier_id: idx as u64, + tx_id: id, + block_id: id, + nullifier: UTXONullifier { utxo_hash: *n_p }, + }) .collect(); nsmt.insert_items(nullifiers).unwrap(); diff --git a/node_core/src/executions/private_exec.rs b/node_core/src/executions/private_exec.rs index 2e06c86..e3d55a1 100644 --- a/node_core/src/executions/private_exec.rs +++ b/node_core/src/executions/private_exec.rs @@ -1,4 +1,7 @@ +use std::collections::BTreeMap; + use bincode; +use common::nullifier_sparse_merkle_tree::NullifierTreeInput; use common::{ commitment::Commitment, commitments_sparse_merkle_tree::CommitmentsSparseMerkleTree, nullifier::UTXONullifier, nullifier_sparse_merkle_tree::NullifierSparseMerkleTree, @@ -79,15 +82,25 @@ pub fn validate_nullifiers_proof( root_nullifier: [u8; 32], nullifiers_proof: &[[u8; 32]], ) -> bool { + //There is no need for storage, so ids can be default there + let id = 1; + let mut nsmt = NullifierSparseMerkleTree { curr_root: Option::Some(root_nullifier), tree: Monotree::default(), hasher: Blake3::new(), + leafs: BTreeMap::new(), }; let nullifiers: Vec<_> = nullifiers_proof .into_iter() - .map(|n_p| UTXONullifier { utxo_hash: *n_p }) + .enumerate() + .map(|(idx, n_p)| NullifierTreeInput { + nullifier_id: idx as u64, + tx_id: id, + block_id: id, + nullifier: UTXONullifier { utxo_hash: *n_p }, + }) .collect(); nsmt.insert_items(nullifiers).unwrap(); diff --git a/node_core/src/executions/se.rs b/node_core/src/executions/se.rs index d37fee5..f9123c2 100644 --- a/node_core/src/executions/se.rs +++ b/node_core/src/executions/se.rs @@ -1,4 +1,7 @@ +use std::collections::BTreeMap; + use bincode; +use common::nullifier_sparse_merkle_tree::NullifierTreeInput; use common::{ commitment::Commitment, commitments_sparse_merkle_tree::CommitmentsSparseMerkleTree, nullifier::UTXONullifier, nullifier_sparse_merkle_tree::NullifierSparseMerkleTree, @@ -108,15 +111,25 @@ pub fn validate_nullifiers_proof( root_nullifier: [u8; 32], nullifiers_proof: &[[u8; 32]], ) -> bool { + //There is no need for storage, so ids can be default there + let id = 1; + let mut nsmt = NullifierSparseMerkleTree { curr_root: Option::Some(root_nullifier), tree: Monotree::default(), hasher: Blake3::new(), + leafs: BTreeMap::new(), }; let nullifiers: Vec<_> = nullifiers_proof .into_iter() - .map(|n_p| UTXONullifier { utxo_hash: *n_p }) + .enumerate() + .map(|(idx, n_p)| NullifierTreeInput { + nullifier_id: idx as u64, + tx_id: id, + block_id: id, + nullifier: UTXONullifier { utxo_hash: *n_p }, + }) .collect(); nsmt.insert_items(nullifiers).unwrap(); diff --git a/sc_core/src/proofs_circuits.rs b/sc_core/src/proofs_circuits.rs index 2072e55..3574ec4 100644 --- a/sc_core/src/proofs_circuits.rs +++ b/sc_core/src/proofs_circuits.rs @@ -1,4 +1,7 @@ +use std::collections::BTreeMap; + use bincode; +use common::nullifier_sparse_merkle_tree::NullifierTreeInput; use common::{ commitment::Commitment, commitments_sparse_merkle_tree::CommitmentsSparseMerkleTree, nullifier::UTXONullifier, nullifier_sparse_merkle_tree::NullifierSparseMerkleTree, @@ -81,15 +84,25 @@ pub fn validate_nullifiers_proof( root_nullifier: [u8; 32], nullifiers_proof: &[[u8; 32]], ) -> bool { + //There is no need for storage, so ids can be default there + let id = 1; + let mut nsmt = NullifierSparseMerkleTree { curr_root: Option::Some(root_nullifier), tree: Monotree::default(), hasher: Blake3::new(), + leafs: BTreeMap::new(), }; let nullifiers: Vec<_> = nullifiers_proof .into_iter() - .map(|n_p| UTXONullifier { utxo_hash: *n_p }) + .enumerate() + .map(|(idx, n_p)| NullifierTreeInput { + nullifier_id: idx as u64, + tx_id: id, + block_id: id, + nullifier: UTXONullifier { utxo_hash: *n_p }, + }) .collect(); nsmt.insert_items(nullifiers).unwrap(); diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index d073ffb..647af9b 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -5,6 +5,7 @@ use common::{ block::{Block, HashableBlockData}, merkle_tree_public::TreeHashType, nullifier::UTXONullifier, + nullifier_sparse_merkle_tree::NullifierTreeInput, transaction::{Transaction, TxKind}, utxo_commitment::UTXOCommitment, }; @@ -185,6 +186,8 @@ impl SequencerCore { fn execute_check_transaction_on_state( &mut self, tx: TransactionMempool, + tx_id: u64, + block_id: u64, ) -> Result<(), TransactionMalformationErrorKind> { let Transaction { hash, @@ -199,11 +202,16 @@ impl SequencerCore { .add_tx(UTXOCommitment { hash: *utxo_comm }); } - for nullifier in nullifier_created_hashes { + for (idx, nullifier) in nullifier_created_hashes.iter().enumerate() { self.store .nullifier_store - .insert_item(UTXONullifier { - utxo_hash: *nullifier, + .insert_item(NullifierTreeInput { + nullifier_id: idx as u64, + tx_id, + block_id, + nullifier: UTXONullifier { + utxo_hash: *nullifier, + }, }) .map_err(|err| TransactionMalformationErrorKind::FailedToInsert { tx: hash, @@ -225,12 +233,14 @@ impl SequencerCore { ///Produces new block from transactions in mempool pub fn produce_new_block_with_mempool_transactions(&mut self) -> Result { + let new_block_height = self.chain_height + 1; + let transactions = self .mempool .pop_size(self.sequencer_config.max_num_tx_in_block); - for tx in transactions.clone() { - self.execute_check_transaction_on_state(tx)?; + for (idx, tx) in transactions.clone().into_iter().enumerate() { + self.execute_check_transaction_on_state(tx, idx as u64, new_block_height)?; } let prev_block_hash = self @@ -240,7 +250,7 @@ impl SequencerCore { .hash; let hashable_data = HashableBlockData { - block_id: self.chain_height + 1, + block_id: new_block_height, prev_block_id: self.chain_height, transactions: transactions.into_iter().map(|tx_mem| tx_mem.tx).collect(), data: vec![], diff --git a/utxo/src/utxo_tree.rs b/utxo/src/utxo_tree.rs index 3c0c603..cc84dd9 100644 --- a/utxo/src/utxo_tree.rs +++ b/utxo/src/utxo_tree.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use common::merkle_tree_public::TreeHashType; use monotree::database::MemoryDB; @@ -7,11 +7,32 @@ use monotree::{Hasher, Monotree, Proof}; use crate::utxo_core::UTXO; +#[derive(Debug, Clone)] +pub struct UTXOTreeInput { + pub utxo_id: u64, + pub tx_id: u64, + pub block_id: u64, + pub utxo: UTXO, +} + +#[derive(Debug, Clone)] +pub struct TreeTxWithUTXOId { + pub id: u64, + pub utxos: BTreeMap, +} + +#[derive(Debug, Clone)] +pub struct TreeBlockWithTxId { + pub id: u64, + pub txs: BTreeMap, +} + pub struct UTXOSparseMerkleTree { pub curr_root: Option, pub tree: Monotree, pub hasher: Blake3, pub store: HashMap, + pub leafs: BTreeMap, } impl UTXOSparseMerkleTree { @@ -21,30 +42,58 @@ impl UTXOSparseMerkleTree { tree: Monotree::default(), hasher: Blake3::new(), store: HashMap::new(), + leafs: BTreeMap::new(), } } - pub fn insert_item(&mut self, utxo: UTXO) -> Result<(), monotree::Errors> { + pub fn modify_leavs_with_nullifier_input(&mut self, tree_utxo: UTXOTreeInput) { + self.leafs + .entry(tree_utxo.block_id) + .and_modify(|tree_block| { + tree_block + .txs + .entry(tree_utxo.tx_id) + .and_modify(|tree_tx| { + tree_tx.utxos.insert(tree_utxo.utxo_id, tree_utxo.utxo); + }) + .or_insert(TreeTxWithUTXOId { + id: tree_utxo.tx_id, + utxos: BTreeMap::new(), + }); + }) + .or_insert(TreeBlockWithTxId { + id: tree_utxo.block_id, + txs: BTreeMap::new(), + }); + } + + pub fn insert_item(&mut self, tree_utxo: UTXOTreeInput) -> Result<(), monotree::Errors> { let root = self.curr_root.as_ref(); - let new_root = self.tree.insert(root, &utxo.hash, &utxo.hash)?; - - self.store.insert(utxo.hash, utxo); + let new_root = self + .tree + .insert(root, &tree_utxo.utxo.hash, &tree_utxo.utxo.hash)?; self.curr_root = new_root; + self.store + .insert(tree_utxo.utxo.hash, tree_utxo.utxo.clone()); + self.modify_leavs_with_nullifier_input(tree_utxo); + Ok(()) } - pub fn insert_items(&mut self, utxos: Vec) -> Result<(), monotree::Errors> { + pub fn insert_items(&mut self, tree_utxos: Vec) -> Result<(), monotree::Errors> { let root = self.curr_root.as_ref(); - let hashes: Vec = utxos.iter().map(|item| item.hash).collect(); + let hashes: Vec = tree_utxos.iter().map(|item| item.utxo.hash).collect(); let new_root = self.tree.inserts(root, &hashes, &hashes)?; - for utxo in utxos { - self.store.insert(utxo.hash, utxo); + for tree_utxo in tree_utxos { + self.store + .insert(tree_utxo.utxo.hash, tree_utxo.utxo.clone()); + self.modify_leavs_with_nullifier_input(tree_utxo); } self.curr_root = new_root; @@ -80,17 +129,31 @@ mod tests { use super::*; use crate::utxo_core::{UTXOPayload, UTXO}; - fn sample_utxo_payload() -> UTXOPayload { + fn sample_utxo_payload(amount: u128) -> UTXOPayload { UTXOPayload { owner: AccountId::default(), asset: vec![1, 2, 3], - amount: 10, + amount, privacy_flag: false, } } - fn sample_utxo() -> anyhow::Result { - UTXO::create_utxo_from_payload(sample_utxo_payload()) + fn sample_utxo(amount: u128) -> anyhow::Result { + UTXO::create_utxo_from_payload(sample_utxo_payload(amount)) + } + + fn sample_utxo_input( + utxo_id: u64, + tx_id: u64, + block_id: u64, + amount: u128, + ) -> anyhow::Result { + sample_utxo(amount).map(|utxo| UTXOTreeInput { + utxo_id, + tx_id, + block_id, + utxo, + }) } #[test] @@ -103,7 +166,7 @@ mod tests { #[test] fn test_insert_item() { let mut smt = UTXOSparseMerkleTree::new(); - let utxo = sample_utxo().unwrap(); + let utxo = sample_utxo_input(1, 1, 1, 10).unwrap(); let result = smt.insert_item(utxo.clone()); @@ -111,7 +174,7 @@ mod tests { assert!(result.is_ok()); // Test UTXO is now stored in the tree - assert_eq!(smt.store.get(&utxo.hash).unwrap().hash, utxo.hash); + assert_eq!(smt.store.get(&utxo.utxo.hash).unwrap().hash, utxo.utxo.hash); // Test curr_root is updated assert!(smt.curr_root.is_some()); @@ -120,8 +183,8 @@ mod tests { #[test] fn test_insert_items() { let mut smt = UTXOSparseMerkleTree::new(); - let utxo1 = sample_utxo().unwrap(); - let utxo2 = sample_utxo().unwrap(); + let utxo1 = sample_utxo_input(1, 1, 1, 10).unwrap(); + let utxo2 = sample_utxo_input(2, 1, 1, 11).unwrap(); let result = smt.insert_items(vec![utxo1.clone(), utxo2.clone()]); @@ -129,8 +192,8 @@ mod tests { assert!(result.is_ok()); // Test UTXOs are now stored in the tree - assert!(smt.store.get(&utxo1.hash).is_some()); - assert!(smt.store.get(&utxo2.hash).is_some()); + assert!(smt.store.get(&utxo1.utxo.hash).is_some()); + assert!(smt.store.get(&utxo2.utxo.hash).is_some()); // Test curr_root is updated assert!(smt.curr_root.is_some()); @@ -139,20 +202,20 @@ mod tests { #[test] fn test_get_item_exists() { let mut smt = UTXOSparseMerkleTree::new(); - let utxo = sample_utxo().unwrap(); + let utxo = sample_utxo_input(1, 1, 1, 10).unwrap(); smt.insert_item(utxo.clone()).unwrap(); // Test that the UTXO can be retrieved by hash - let retrieved_utxo = smt.get_item(utxo.hash).unwrap(); + let retrieved_utxo = smt.get_item(utxo.utxo.hash).unwrap(); assert!(retrieved_utxo.is_some()); - assert_eq!(retrieved_utxo.unwrap().hash, utxo.hash); + assert_eq!(retrieved_utxo.unwrap().hash, utxo.utxo.hash); } #[test] fn test_get_item_not_exists() { let mut smt = UTXOSparseMerkleTree::new(); - let utxo = sample_utxo().unwrap(); + let utxo = sample_utxo_input(1, 1, 1, 10).unwrap(); // Insert one UTXO and try to fetch a different hash smt.insert_item(utxo).unwrap(); @@ -167,12 +230,12 @@ mod tests { #[test] fn test_get_membership_proof() { let mut smt = UTXOSparseMerkleTree::new(); - let utxo = sample_utxo().unwrap(); + let utxo = sample_utxo_input(1, 1, 1, 10).unwrap(); smt.insert_item(utxo.clone()).unwrap(); // Fetch membership proof for the inserted UTXO - let proof = smt.get_membership_proof(utxo.hash).unwrap(); + let proof = smt.get_membership_proof(utxo.utxo.hash).unwrap(); // Test proof is generated successfully assert!(proof.is_some()); From 00fe02c1d102918fb679efc74f4c7e1017ce99d6 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Wed, 21 May 2025 08:34:03 +0300 Subject: [PATCH 2/8] fix: merge updates --- accounts/src/account_core/mod.rs | 25 ++++++------------------- node_core/src/chain_storage/mod.rs | 6 ++---- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/accounts/src/account_core/mod.rs b/accounts/src/account_core/mod.rs index 813f6fc..d5f5e90 100644 --- a/accounts/src/account_core/mod.rs +++ b/accounts/src/account_core/mod.rs @@ -116,9 +116,6 @@ impl Account { asset: Asset, amount: u128, privacy_flag: bool, - utxo_id: u64, - tx_id: u64, - block_id: u64, ) -> Result<()> { let payload_with_asset = UTXOPayload { owner: self.address, @@ -169,24 +166,14 @@ mod tests { UTXONullifier::default() } - fn generate_dummy_utxo( - address: TreeHashType, - amount: u128, - utxo_id: u64, - ) -> anyhow::Result { + fn generate_dummy_utxo(address: TreeHashType, amount: u128) -> anyhow::Result { let payload = UTXOPayload { owner: address, asset: vec![], amount, privacy_flag: false, }; - let utxo = UTXO::create_utxo_from_payload(payload); - utxo.map(|utxo| UTXOTreeInput { - utxo_id, - tx_id: 1, - block_id: 1, - utxo, - }) + UTXO::create_utxo_from_payload(payload) } #[test] @@ -200,7 +187,7 @@ mod tests { #[test] fn test_mark_spent_utxo() { let mut account = Account::new(); - let utxo = generate_dummy_utxo(account.address, 100, 1).unwrap(); + let utxo = generate_dummy_utxo(account.address, 100).unwrap(); account.add_new_utxo_outputs(vec![utxo]).unwrap(); let mut utxo_nullifier_map = HashMap::new(); @@ -214,8 +201,8 @@ mod tests { #[test] fn test_add_new_utxo_outputs() { let mut account = Account::new(); - let utxo1 = generate_dummy_utxo(account.address, 100, 1).unwrap(); - let utxo2 = generate_dummy_utxo(account.address, 200, 2).unwrap(); + let utxo1 = generate_dummy_utxo(account.address, 100).unwrap(); + let utxo2 = generate_dummy_utxo(account.address, 200).unwrap(); let result = account.add_new_utxo_outputs(vec![utxo1.clone(), utxo2.clone()]); @@ -237,7 +224,7 @@ mod tests { let asset = "dummy_asset"; let amount = 1000u128; - let result = account.add_asset(asset, amount, false, 1, 1, 1); + let result = account.add_asset(asset, amount, false); assert!(result.is_ok()); assert_eq!(account.utxos.len(), 1); diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index c4eef13..90c9cb1 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -15,7 +15,7 @@ use common::{ }; use k256::AffinePoint; use public_context::PublicSCContext; -use utxo::{utxo_core::UTXO, utxo_tree::UTXOTreeInput}; +use utxo::utxo_core::UTXO; use crate::ActionData; @@ -115,9 +115,7 @@ impl NodeChainStore { let ephemeral_public_key_sender = serde_json::from_slice::(&tx.ephemeral_pub_key)?; - for (utxo_id, (ciphertext, nonce, tag)) in - tx.encoded_data.clone().into_iter().enumerate() - { + for (ciphertext, nonce, tag) in tx.encoded_data.clone() { let slice = nonce.as_slice(); let nonce = accounts::key_management::constants_types::Nonce::clone_from_slice(slice); From 00297db3ab1a080fe45cb0926e71e74f70acf233 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Thu, 22 May 2025 00:13:17 +0300 Subject: [PATCH 3/8] feat: indexed tree migration 1 --- Cargo.lock | 504 +++++---------------- Cargo.toml | 2 +- common/Cargo.toml | 2 +- common/src/indexed_merkle_tree.rs | 248 ++++++++++ common/src/lib.rs | 5 +- common/src/nullifier_sparse_merkle_tree.rs | 326 ------------- node_core/Cargo.toml | 2 +- node_core/src/chain_storage/mod.rs | 23 +- node_core/src/executions/de.rs | 50 +- node_core/src/executions/private_exec.rs | 50 +- node_core/src/executions/se.rs | 50 +- node_core/src/lib.rs | 2 +- node_rpc/src/types/err_rpc.rs | 1 - sc_core/Cargo.toml | 2 +- sc_core/src/proofs_circuits.rs | 66 +-- sequencer_core/src/lib.rs | 18 +- sequencer_core/src/sequencer_store/mod.rs | 6 +- utxo/Cargo.toml | 2 +- 18 files changed, 433 insertions(+), 926 deletions(-) create mode 100644 common/src/indexed_merkle_tree.rs delete mode 100644 common/src/nullifier_sparse_merkle_tree.rs diff --git a/Cargo.lock b/Cargo.lock index 8c84dec..b294ce1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,7 +18,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "sha2 0.10.8", + "sha2", "utxo", ] @@ -132,7 +132,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" dependencies = [ "bytestring", - "cfg-if 1.0.0", + "cfg-if", "http 0.2.12", "regex", "regex-lite", @@ -204,7 +204,7 @@ dependencies = [ "ahash 0.7.8", "bytes", "bytestring", - "cfg-if 1.0.0", + "cfg-if", "derive_more 0.99.19", "encoding_rs", "futures-core", @@ -284,7 +284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ "crypto-common", - "generic-array 0.14.7", + "generic-array", ] [[package]] @@ -293,7 +293,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cipher", "cpufeatures", ] @@ -309,15 +309,9 @@ dependencies = [ "cipher", "ctr", "ghash", - "subtle 2.6.1", + "subtle", ] -[[package]] -name = "ahash" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" - [[package]] name = "ahash" version = "0.7.8" @@ -335,7 +329,7 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", "version_check", "zerocopy 0.7.35", @@ -411,10 +405,10 @@ dependencies = [ "ark-std", "blake2", "derivative", - "digest 0.10.7", + "digest", "fnv", "merlin", - "sha2 0.10.8", + "sha2", ] [[package]] @@ -459,13 +453,13 @@ dependencies = [ "ark-ff-macros", "ark-serialize", "ark-std", - "arrayvec 0.7.6", - "digest 0.10.7", + "arrayvec", + "digest", "educe", "itertools 0.13.0", "num-bigint 0.4.6", "num-traits", - "paste 1.0.15", + "paste", "zeroize", ] @@ -559,8 +553,8 @@ checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" dependencies = [ "ark-serialize-derive", "ark-std", - "arrayvec 0.7.6", - "digest 0.10.7", + "arrayvec", + "digest", "num-bigint 0.4.6", ] @@ -603,27 +597,6 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - -[[package]] -name = "arrayvec" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -dependencies = [ - "nodrop", -] - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "arrayvec" version = "0.7.6" @@ -669,7 +642,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line 0.24.2", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object 0.36.7", @@ -773,32 +746,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "blake2-rfc" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -dependencies = [ - "arrayvec 0.4.12", - "constant_time_eq", -] - -[[package]] -name = "blake3" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "667d945f23cefed0b5f973af35c4bc3319caa6776fbda270e4897d8504afa8e4" -dependencies = [ - "arrayref", - "arrayvec 0.5.2", - "cc", - "cfg-if 0.1.10", - "constant_time_eq", - "crypto-mac", - "digest 0.8.1", + "digest", ] [[package]] @@ -807,34 +755,24 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array 0.12.4", -] - [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array 0.14.7", + "generic-array", ] [[package]] -name = "block-padding" -version = "0.1.5" +name = "bls12_381" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +checksum = "d7bc6d6292be3a19e6379786dac800f551e5865a5bb51ebbe3064ab80433f403" dependencies = [ - "byte-tools", + "ff", + "rand_core 0.6.4", + "subtle", ] [[package]] @@ -878,12 +816,6 @@ version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - [[package]] name = "bytemuck" version = "1.22.0" @@ -990,12 +922,6 @@ dependencies = [ "nom", ] -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -1081,15 +1007,15 @@ dependencies = [ "anyhow", "elliptic-curve", "hex", + "indexed-merkle-tree", "log", - "monotree", "reqwest 0.11.27", "risc0-zkvm", "rs_merkle", "secp256k1-zkp", "serde", "serde_json", - "sha2 0.10.8", + "sha2", "thiserror 1.0.69", ] @@ -1112,12 +1038,6 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - [[package]] name = "convert_case" version = "0.4.0" @@ -1157,7 +1077,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1175,7 +1095,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1224,9 +1144,9 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array 0.14.7", + "generic-array", "rand_core 0.6.4", - "subtle 2.6.1", + "subtle", "zeroize", ] @@ -1236,21 +1156,11 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.7", + "generic-array", "rand_core 0.6.4", "typenum", ] -[[package]] -name = "crypto-mac" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" -dependencies = [ - "generic-array 0.12.4", - "subtle 1.0.0", -] - [[package]] name = "ctr" version = "0.9.2" @@ -1447,25 +1357,16 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", -] - [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", + "block-buffer", "const-oid", "crypto-common", - "subtle 2.6.1", + "subtle", ] [[package]] @@ -1527,7 +1428,7 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ac1e888d6830712d565b2f3a974be3200be9296bc1b03db8251a4cbf18a4a34" dependencies = [ - "digest 0.10.7", + "digest", "futures", "rand 0.8.5", "reqwest 0.12.15", @@ -1552,7 +1453,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", - "digest 0.10.7", + "digest", "elliptic-curve", "rfc6979", "serdect", @@ -1592,15 +1493,15 @@ checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", - "digest 0.10.7", + "digest", "ff", - "generic-array 0.14.7", + "generic-array", "group", "pkcs8", "rand_core 0.6.4", "sec1", "serdect", - "subtle 2.6.1", + "subtle", "zeroize", ] @@ -1622,7 +1523,7 @@ version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1704,12 +1605,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - [[package]] name = "fallible-iterator" version = "0.3.0" @@ -1732,7 +1627,7 @@ dependencies = [ "byteorder", "ff_derive", "rand_core 0.6.4", - "subtle 2.6.1", + "subtle", ] [[package]] @@ -1927,15 +1822,6 @@ dependencies = [ "slab", ] -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -1947,24 +1833,13 @@ dependencies = [ "zeroize", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", @@ -1977,7 +1852,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "libc", "r-efi", @@ -1991,7 +1866,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" dependencies = [ - "opaque-debug 0.3.1", + "opaque-debug", "polyval", ] @@ -2034,7 +1909,7 @@ checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", "rand_core 0.6.4", - "subtle 2.6.1", + "subtle", ] [[package]] @@ -2065,16 +1940,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "hashbrown" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96282e96bfcd3da0d3aa9938bedf1e50df3269b6db08b4876d2da0bb1a0841cf" -dependencies = [ - "ahash 0.3.8", - "autocfg", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -2170,7 +2035,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] @@ -2501,6 +2366,23 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee796ad498c8d9a1d68e477df8f754ed784ef875de1414ebdaf169f70a6a784" +[[package]] +name = "indexed-merkle-tree" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86e7e0a70243eb602dba292003d26682c23cff528c5b3c06c002d242a26d865" +dependencies = [ + "anyhow", + "bls12_381", + "borsh", + "hex", + "num", + "num-bigint 0.4.6", + "num-traits", + "serde", + "sha2", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -2527,7 +2409,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ - "generic-array 0.14.7", + "generic-array", ] [[package]] @@ -2624,12 +2506,12 @@ version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "ecdsa", "elliptic-curve", "once_cell", "serdect", - "sha2 0.10.8", + "sha2", "signature", ] @@ -2698,7 +2580,7 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "windows-targets 0.52.6", ] @@ -2970,7 +2852,7 @@ dependencies = [ "foreign-types 0.5.0", "log", "objc", - "paste 1.0.15", + "paste", ] [[package]] @@ -3012,25 +2894,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "monotree" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6724f66abef26ea20981177c87a500f2416a420d96daf50c5d96d97a10892d5f" -dependencies = [ - "blake2-rfc", - "blake3", - "digest 0.8.1", - "hashbrown 0.7.2", - "hex", - "num", - "paste 0.1.18", - "rand 0.7.3", - "scopeguard", - "sha2 0.8.2", - "sha3", -] - [[package]] name = "native-tls" version = "0.2.14" @@ -3055,7 +2918,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841" dependencies = [ "matrixmultiply", - "num-complex 0.4.6", + "num-complex", "num-integer", "num-traits", "portable-atomic", @@ -3093,9 +2956,9 @@ dependencies = [ "elliptic-curve", "env_logger", "hex", + "indexed-merkle-tree", "k256", "log", - "monotree", "rand 0.8.5", "reqwest 0.11.27", "risc0-zkvm", @@ -3103,7 +2966,7 @@ dependencies = [ "secp256k1-zkp", "serde", "serde_json", - "sha2 0.10.8", + "sha2", "storage", "tempfile", "thiserror 1.0.69", @@ -3164,12 +3027,6 @@ dependencies = [ "zkvm", ] -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - [[package]] name = "nom" version = "7.1.3" @@ -3182,29 +3039,18 @@ dependencies = [ [[package]] name = "num" -version = "0.2.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ - "num-bigint 0.2.6", - "num-complex 0.2.4", + "num-bigint 0.4.6", + "num-complex", "num-integer", "num-iter", "num-rational", "num-traits", ] -[[package]] -name = "num-bigint" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-bigint" version = "0.3.3" @@ -3226,16 +3072,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-complex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" -dependencies = [ - "autocfg", - "num-traits", -] - [[package]] name = "num-complex" version = "0.4.6" @@ -3284,12 +3120,11 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.2.4" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", - "num-bigint 0.2.6", + "num-bigint 0.4.6", "num-integer", "num-traits", ] @@ -3348,12 +3183,6 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - [[package]] name = "opaque-debug" version = "0.3.1" @@ -3367,7 +3196,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" dependencies = [ "bitflags 2.9.0", - "cfg-if 1.0.0", + "cfg-if", "foreign-types 0.3.2", "libc", "once_cell", @@ -3432,38 +3261,19 @@ version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall", "smallvec", "windows-targets 0.52.6", ] -[[package]] -name = "paste" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" -dependencies = [ - "paste-impl", - "proc-macro-hack", -] - [[package]] name = "paste" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "paste-impl" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" -dependencies = [ - "proc-macro-hack", -] - [[package]] name = "peeking_take_while" version = "0.1.2" @@ -3510,9 +3320,9 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", - "opaque-debug 0.3.1", + "opaque-debug", "universal-hash", ] @@ -3602,12 +3412,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - [[package]] name = "proc-macro2" version = "1.0.94" @@ -3648,7 +3452,7 @@ checksum = "fa9dae7b05c02ec1a6bc9bcf20d8bc64a7dcbf57934107902a872014899b741f" dependencies = [ "anyhow", "byteorder", - "cfg-if 1.0.0", + "cfg-if", "itertools 0.10.5", "once_cell", "parking_lot", @@ -3729,19 +3533,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - [[package]] name = "rand" version = "0.8.5" @@ -3764,16 +3555,6 @@ dependencies = [ "zerocopy 0.8.24", ] -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - [[package]] name = "rand_chacha" version = "0.3.1" @@ -3794,15 +3575,6 @@ dependencies = [ "rand_core 0.9.3", ] -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - [[package]] name = "rand_core" version = "0.6.4" @@ -3821,15 +3593,6 @@ dependencies = [ "getrandom 0.3.2", ] -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - [[package]] name = "rawpointer" version = "0.2.1" @@ -4004,7 +3767,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ "hmac", - "subtle 2.6.1", + "subtle", ] [[package]] @@ -4014,7 +3777,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", - "cfg-if 1.0.0", + "cfg-if", "getrandom 0.2.15", "libc", "untrusted", @@ -4078,7 +3841,7 @@ dependencies = [ "glob", "hex", "rayon", - "sha2 0.10.8", + "sha2", "tempfile", ] @@ -4089,9 +3852,9 @@ source = "git+https://github.com/risc0/risc0.git?branch=release-2.0#fdd54f961b84 dependencies = [ "anyhow", "bytemuck", - "cfg-if 1.0.0", + "cfg-if", "keccak", - "paste 1.0.15", + "paste", "rayon", "risc0-binfmt", "risc0-circuit-keccak-sys", @@ -4125,7 +3888,7 @@ source = "git+https://github.com/risc0/risc0.git?branch=release-2.0#fdd54f961b84 dependencies = [ "anyhow", "bytemuck", - "cfg-if 1.0.0", + "cfg-if", "cust", "downloader", "hex", @@ -4138,7 +3901,7 @@ dependencies = [ "risc0-sys", "risc0-zkp", "serde", - "sha2 0.10.8", + "sha2", "tracing", "zip", ] @@ -4165,13 +3928,13 @@ dependencies = [ "bit-vec", "bytemuck", "byteorder", - "cfg-if 1.0.0", + "cfg-if", "derive_more 2.0.1", "enum-map", "malachite", "num-derive", "num-traits", - "paste 1.0.15", + "paste", "postcard", "rand 0.8.5", "rayon", @@ -4266,16 +4029,16 @@ dependencies = [ "blake2", "borsh", "bytemuck", - "cfg-if 1.0.0", + "cfg-if", "cust", - "digest 0.10.7", + "digest", "ff", "hex", "hex-literal", "metal", "ndarray", "parking_lot", - "paste 1.0.15", + "paste", "rand 0.8.5", "rand_core 0.6.4", "rayon", @@ -4283,7 +4046,7 @@ dependencies = [ "risc0-sys", "risc0-zkvm-platform", "serde", - "sha2 0.10.8", + "sha2", "stability", "tracing", ] @@ -4327,7 +4090,7 @@ dependencies = [ "rzup", "semver", "serde", - "sha2 0.10.8", + "sha2", "stability", "tempfile", "tracing", @@ -4340,7 +4103,7 @@ version = "2.0.1" source = "git+https://github.com/risc0/risc0.git?branch=release-2.0#fdd54f961b84b38831a8a488b9d67534a02d80a2" dependencies = [ "bytemuck", - "cfg-if 1.0.0", + "cfg-if", "getrandom 0.2.15", "libm", "stability", @@ -4363,7 +4126,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4382d3af3a4ebdae7f64ba6edd9114fff92c89808004c4943b393377a25d001" dependencies = [ "downcast-rs", - "paste 1.0.15", + "paste", ] [[package]] @@ -4372,7 +4135,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb09b49230ba22e8c676e7b75dfe2887dea8121f18b530ae0ba519ce442d2b21" dependencies = [ - "sha2 0.10.8", + "sha2", ] [[package]] @@ -4438,7 +4201,7 @@ dependencies = [ "ring", "rustls-pki-types", "rustls-webpki", - "subtle 2.6.1", + "subtle", "zeroize", ] @@ -4530,16 +4293,16 @@ dependencies = [ "elliptic-curve", "env_logger", "hex", + "indexed-merkle-tree", "k256", "light-poseidon", "log", - "monotree", "rand 0.8.5", "risc0-zkvm", "secp256k1-zkp", "serde", "serde_json", - "sha2 0.10.8", + "sha2", "storage", "utxo", ] @@ -4567,10 +4330,10 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", - "generic-array 0.14.7", + "generic-array", "pkcs8", "serdect", - "subtle 2.6.1", + "subtle", "zeroize", ] @@ -4782,21 +4545,9 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", + "digest", ] [[package]] @@ -4805,22 +4556,9 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha3" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" -dependencies = [ - "block-buffer 0.7.3", - "byte-tools", - "digest 0.8.1", - "keccak", - "opaque-debug 0.2.3", + "digest", ] [[package]] @@ -4844,7 +4582,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest 0.10.7", + "digest", "rand_core 0.6.4", ] @@ -4990,12 +4728,6 @@ dependencies = [ "syn 2.0.100", ] -[[package]] -name = "subtle" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" - [[package]] name = "subtle" version = "2.6.1" @@ -5398,7 +5130,7 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "static_assertions", ] @@ -5457,7 +5189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ "crypto-common", - "subtle 2.6.1", + "subtle", ] [[package]] @@ -5497,11 +5229,11 @@ dependencies = [ "common", "env_logger", "hex", + "indexed-merkle-tree", "log", - "monotree", "serde", "serde_json", - "sha2 0.10.8", + "sha2", ] [[package]] @@ -5554,12 +5286,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -5581,7 +5307,7 @@ version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", @@ -5607,7 +5333,7 @@ version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "once_cell", "wasm-bindgen", @@ -6002,7 +5728,7 @@ version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "windows-sys 0.48.0", ] diff --git a/Cargo.toml b/Cargo.toml index 59417cd..edad918 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,6 @@ lru = "0.7.8" thiserror = "1.0" rs_merkle = "1.4" sha2 = "0.10.8" -monotree = "0.1.5" hex = "0.4.3" aes-gcm = "0.10.3" toml = "0.7.4" @@ -46,6 +45,7 @@ tempfile = "3.14.0" light-poseidon = "0.3.0" ark-bn254 = "0.5.0" ark-ff = "0.5.0" +indexed-merkle-tree = "0.6.2" rocksdb = { version = "0.21.0", default-features = false, features = [ "snappy", diff --git a/common/Cargo.toml b/common/Cargo.toml index f3327ea..4d2f52b 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -9,7 +9,7 @@ thiserror.workspace = true serde_json.workspace = true serde.workspace = true reqwest.workspace = true -monotree.workspace = true +indexed-merkle-tree.workspace = true risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-2.0" } rs_merkle.workspace = true diff --git a/common/src/indexed_merkle_tree.rs b/common/src/indexed_merkle_tree.rs new file mode 100644 index 0000000..e8df6b5 --- /dev/null +++ b/common/src/indexed_merkle_tree.rs @@ -0,0 +1,248 @@ +use crate::merkle_tree_public::TreeHashType; + +use anyhow::Result; +use indexed_merkle_tree::node::Node; +use indexed_merkle_tree::tree::{IndexedMerkleTree, NonMembershipProof}; +use indexed_merkle_tree::Hash; + +pub struct IndexedMerkleTreeWrapper { + pub tree: IndexedMerkleTree, + pub leaf_len: usize, + //pub leafs: BTreeMap, +} + +impl IndexedMerkleTreeWrapper { + pub fn new() -> Self { + Self { + //Will not panic + //Deterministic operation + tree: IndexedMerkleTree::new(vec![]).unwrap(), + leaf_len: 0, + } + } + + pub fn get_curr_root(&self) -> Result { + //HELP + // self.tree.get_root().map(|node| + // serde_json::from_str::>(&serde_json::to_string(node).unwrap())[0] + // ) + Ok([0; 32]) + } + + pub fn insert_item(&mut self, hash: TreeHashType) -> Result<()> { + let left_parity = self.leaf_len / 2; + let mut node = match left_parity { + 0 => Node::new_leaf(true, Hash::new(hash), Hash::new(hash), Node::TAIL), + 1 => Node::new_leaf(false, Hash::new(hash), Hash::new(hash), Node::TAIL), + _ => unreachable!(), + }; + + self.tree.insert_node(&mut node)?; + + self.leaf_len += 1; + + Ok(()) + } + + pub fn insert_items(&mut self, tree_nullifiers: Vec) -> Result<()> { + for tree_nullifier in tree_nullifiers { + self.insert_item(tree_nullifier)?; + } + + Ok(()) + } + + pub fn search_item_inclusion(&mut self, nullifier_hash: TreeHashType) -> bool { + self.tree + .find_leaf_by_label(&Hash::new(nullifier_hash)) + .is_some() + } + + pub fn search_item_inclusions(&mut self, nullifier_hashes: &[TreeHashType]) -> Vec { + let mut inclusions = vec![]; + + for nullifier_hash in nullifier_hashes { + let is_included = self.search_item_inclusion(*nullifier_hash); + + inclusions.push(is_included); + } + + inclusions + } + + pub fn get_non_membership_proof( + &mut self, + nullifier_hash: TreeHashType, + ) -> Result { + let node = Node::new_leaf( + false, + Hash::new(nullifier_hash), + Hash::new(nullifier_hash), + Node::TAIL, + ); + + self.tree.generate_non_membership_proof(&node) + } + + #[allow(clippy::type_complexity)] + pub fn get_non_membership_proofs( + &mut self, + nullifier_hashes: &[TreeHashType], + ) -> Result> { + let mut non_membership_proofs = vec![]; + + for nullifier_hash in nullifier_hashes { + let non_mem_proof = self.get_non_membership_proof(*nullifier_hash)?; + + non_membership_proofs.push(non_mem_proof); + } + + Ok(non_membership_proofs) + } +} + +impl Default for IndexedMerkleTreeWrapper { + fn default() -> Self { + Self::new() + } +} + +#[cfg(test)] +mod tests { + // use super::*; + // use crate::nullifier::UTXONullifier; + + // fn create_nullifier(hash: TreeHashType) -> UTXONullifier { + // UTXONullifier { utxo_hash: hash } + // } + + // fn create_nullifier_input( + // hash: TreeHashType, + // nullifier_id: u64, + // tx_id: u64, + // block_id: u64, + // ) -> NullifierTreeInput { + // NullifierTreeInput { + // nullifier_id, + // tx_id, + // block_id, + // nullifier: create_nullifier(hash), + // } + // } + + // #[test] + // fn test_new_tree_initialization() { + // let tree = IndexedMerkleTree::new(); + // assert!(tree.curr_root.is_none()); + // } + + // #[test] + // fn test_insert_single_item() { + // let mut tree = IndexedMerkleTree::new(); + // let tree_nullifier = create_nullifier_input([1u8; 32], 1, 1, 1); // Sample 32-byte hash + + // let result = tree.insert_item(tree_nullifier); + // assert!(result.is_ok()); + // assert!(tree.curr_root.is_some()); + // } + + // #[test] + // fn test_insert_multiple_items() { + // let mut tree = IndexedMerkleTree::new(); + // let tree_nullifiers = vec![ + // create_nullifier_input([1u8; 32], 1, 1, 1), + // create_nullifier_input([2u8; 32], 2, 1, 1), + // create_nullifier_input([3u8; 32], 3, 1, 1), + // ]; + + // let result = tree.insert_items(tree_nullifiers); + // assert!(result.is_ok()); + // assert!(tree.curr_root.is_some()); + // } + + // #[test] + // fn test_search_item_inclusion() { + // let mut tree = IndexedMerkleTree::new(); + // let tree_nullifier = create_nullifier_input([1u8; 32], 1, 1, 1); + + // tree.insert_item(tree_nullifier.clone()).unwrap(); + + // let result = tree.search_item_inclusion([1u8; 32]); + // assert!(result.is_ok()); + // assert_eq!(result.unwrap(), true); + + // let non_existing = tree.search_item_inclusion([99u8; 32]); + // assert!(non_existing.is_ok()); + // assert_eq!(non_existing.unwrap(), false); + // } + + // #[test] + // fn test_search_multiple_item_inclusions() { + // let mut tree = IndexedMerkleTree::new(); + // let tree_nullifiers = vec![ + // create_nullifier_input([1u8; 32], 1, 1, 1), + // create_nullifier_input([2u8; 32], 2, 1, 1), + // create_nullifier_input([3u8; 32], 3, 1, 1), + // ]; + + // tree.insert_items(tree_nullifiers).unwrap(); + + // let search_hashes = vec![[1u8; 32], [2u8; 32], [99u8; 32]]; + // let result = tree.search_item_inclusions(&search_hashes); + // assert!(result.is_ok()); + + // let expected_results = vec![true, true, false]; + // assert_eq!(result.unwrap(), expected_results); + // } + + // #[test] + // fn test_non_membership_proof() { + // let mut tree = IndexedMerkleTree::new(); + // let non_member_hash = [5u8; 32]; + + // let result = tree.get_non_membership_proof(non_member_hash); + // assert!(result.is_ok()); + + // let (proof, root) = result.unwrap(); + // assert!(root.is_none()); + // } + + // #[test] + // fn test_non_membership_proofs_multiple() { + // let mut tree = IndexedMerkleTree::new(); + // let non_member_hashes = vec![[5u8; 32], [6u8; 32], [7u8; 32]]; + + // let result = tree.get_non_membership_proofs(&non_member_hashes); + // assert!(result.is_ok()); + + // let proofs = result.unwrap(); + // for (proof, root) in proofs { + // assert!(root.is_none()); + // } + // } + + // #[test] + // fn test_insert_and_get_proof_of_existing_item() { + // let mut tree = IndexedMerkleTree::new(); + // let tree_nullifier = create_nullifier_input([1u8; 32], 1, 1, 1); + + // tree.insert_item(tree_nullifier.clone()).unwrap(); + + // let proof_result = tree.get_non_membership_proof([1u8; 32]); + // assert!(proof_result.is_err()); + // } + + // #[test] + // fn test_insert_and_get_proofs_of_existing_items() { + // let mut tree = IndexedMerkleTree::new(); + // let tree_nullifiers = vec![ + // create_nullifier_input([1u8; 32], 1, 1, 1), + // create_nullifier_input([2u8; 32], 2, 1, 1), + // ]; + + // tree.insert_items(tree_nullifiers).unwrap(); + + // let proof_result = tree.get_non_membership_proofs(&[[1u8; 32], [2u8; 32]]); + // assert!(proof_result.is_err()); + // } +} diff --git a/common/src/lib.rs b/common/src/lib.rs index a13fdd4..9e238e2 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -3,10 +3,9 @@ use serde::Deserialize; pub mod block; pub mod commitment; -pub mod commitments_sparse_merkle_tree; +pub mod indexed_merkle_tree; pub mod merkle_tree_public; pub mod nullifier; -pub mod nullifier_sparse_merkle_tree; pub mod rpc_primitives; pub mod transaction; pub mod utxo_commitment; @@ -67,8 +66,6 @@ pub enum ExecutionFailureKind { AmountMismatchError, #[error("Sequencer client error: {0:?}")] SequencerClientError(#[from] SequencerClientError), - #[error("Datebase returned error : {0:?}")] - MonoTreeError(#[from] monotree::Errors), #[error("Insufficient gas for operation")] InsufficientGasError, #[error("Can not pay for operation")] diff --git a/common/src/nullifier_sparse_merkle_tree.rs b/common/src/nullifier_sparse_merkle_tree.rs deleted file mode 100644 index c6707a7..0000000 --- a/common/src/nullifier_sparse_merkle_tree.rs +++ /dev/null @@ -1,326 +0,0 @@ -use std::collections::BTreeMap; - -use monotree::database::MemoryDB; -use monotree::hasher::Blake3; -use monotree::{Hasher, Monotree, Proof}; - -use crate::merkle_tree_public::TreeHashType; -use crate::nullifier::UTXONullifier; - -#[derive(Debug, Clone)] -pub struct NullifierTreeInput { - pub nullifier_id: u64, - pub tx_id: u64, - pub block_id: u64, - pub nullifier: UTXONullifier, -} - -#[derive(Debug, Clone)] -pub struct TreeTxWithNullifierId { - pub id: u64, - pub nullifiers: BTreeMap, -} - -#[derive(Debug, Clone)] -pub struct TreeBlockWithTxId { - pub id: u64, - pub txs: BTreeMap, -} - -pub struct NullifierSparseMerkleTree { - pub curr_root: Option, - pub tree: Monotree, - pub hasher: Blake3, - pub leafs: BTreeMap, -} - -impl NullifierSparseMerkleTree { - pub fn new() -> Self { - NullifierSparseMerkleTree { - curr_root: None, - tree: Monotree::default(), - hasher: Blake3::new(), - leafs: BTreeMap::new(), - } - } - - pub fn modify_leavs_with_nullifier_input(&mut self, tree_nullifier: NullifierTreeInput) { - self.leafs - .entry(tree_nullifier.block_id) - .and_modify(|tree_block| { - tree_block - .txs - .entry(tree_nullifier.tx_id) - .and_modify(|tree_tx| { - tree_tx - .nullifiers - .insert(tree_nullifier.nullifier_id, tree_nullifier.nullifier); - }) - .or_insert(TreeTxWithNullifierId { - id: tree_nullifier.tx_id, - nullifiers: BTreeMap::new(), - }); - }) - .or_insert(TreeBlockWithTxId { - id: tree_nullifier.block_id, - txs: BTreeMap::new(), - }); - } - - pub fn insert_item( - &mut self, - tree_nullifier: NullifierTreeInput, - ) -> Result<(), monotree::Errors> { - let root = self.curr_root.as_ref(); - - let new_root = self.tree.insert( - root, - &tree_nullifier.nullifier.utxo_hash, - &tree_nullifier.nullifier.utxo_hash, - )?; - - self.curr_root = new_root; - - self.modify_leavs_with_nullifier_input(tree_nullifier); - - Ok(()) - } - - pub fn insert_items( - &mut self, - tree_nullifiers: Vec, - ) -> Result<(), monotree::Errors> { - let root = self.curr_root.as_ref(); - - let hashes: Vec = tree_nullifiers - .iter() - .map(|nu| nu.nullifier.utxo_hash) - .collect(); - - let new_root = self.tree.inserts(root, &hashes, &hashes)?; - - self.curr_root = new_root; - - for tree_nullifier in tree_nullifiers { - self.modify_leavs_with_nullifier_input(tree_nullifier); - } - - Ok(()) - } - - pub fn search_item_inclusion( - &mut self, - nullifier_hash: TreeHashType, - ) -> Result { - self.tree - .get(self.curr_root.as_ref(), &nullifier_hash) - .map(|data| data.is_some()) - } - - pub fn search_item_inclusions( - &mut self, - nullifier_hashes: &[TreeHashType], - ) -> Result, monotree::Errors> { - let mut inclusions = vec![]; - - for nullifier_hash in nullifier_hashes { - let is_included = self - .tree - .get(self.curr_root.as_ref(), nullifier_hash) - .map(|data| data.is_some())?; - - inclusions.push(is_included); - } - - Ok(inclusions) - } - - pub fn get_non_membership_proof( - &mut self, - nullifier_hash: TreeHashType, - ) -> Result<(Option, Option), monotree::Errors> { - let is_member = self.search_item_inclusion(nullifier_hash)?; - - if is_member { - Err(monotree::Errors::new("Is a member")) - } else { - Ok(( - self.tree - .get_merkle_proof(self.curr_root.as_ref(), &nullifier_hash)?, - self.curr_root, - )) - } - } - - #[allow(clippy::type_complexity)] - pub fn get_non_membership_proofs( - &mut self, - nullifier_hashes: &[TreeHashType], - ) -> Result, Option)>, monotree::Errors> { - let mut non_membership_proofs = vec![]; - - for nullifier_hash in nullifier_hashes { - let is_member = self.search_item_inclusion(*nullifier_hash)?; - - if is_member { - return Err(monotree::Errors::new( - format!("{nullifier_hash:?} Is a member").as_str(), - )); - } else { - non_membership_proofs.push(( - self.tree - .get_merkle_proof(self.curr_root.as_ref(), nullifier_hash)?, - self.curr_root, - )) - }; - } - - Ok(non_membership_proofs) - } -} - -impl Default for NullifierSparseMerkleTree { - fn default() -> Self { - Self::new() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::nullifier::UTXONullifier; - - fn create_nullifier(hash: TreeHashType) -> UTXONullifier { - UTXONullifier { utxo_hash: hash } - } - - fn create_nullifier_input( - hash: TreeHashType, - nullifier_id: u64, - tx_id: u64, - block_id: u64, - ) -> NullifierTreeInput { - NullifierTreeInput { - nullifier_id, - tx_id, - block_id, - nullifier: create_nullifier(hash), - } - } - - #[test] - fn test_new_tree_initialization() { - let tree = NullifierSparseMerkleTree::new(); - assert!(tree.curr_root.is_none()); - } - - #[test] - fn test_insert_single_item() { - let mut tree = NullifierSparseMerkleTree::new(); - let tree_nullifier = create_nullifier_input([1u8; 32], 1, 1, 1); // Sample 32-byte hash - - let result = tree.insert_item(tree_nullifier); - assert!(result.is_ok()); - assert!(tree.curr_root.is_some()); - } - - #[test] - fn test_insert_multiple_items() { - let mut tree = NullifierSparseMerkleTree::new(); - let tree_nullifiers = vec![ - create_nullifier_input([1u8; 32], 1, 1, 1), - create_nullifier_input([2u8; 32], 2, 1, 1), - create_nullifier_input([3u8; 32], 3, 1, 1), - ]; - - let result = tree.insert_items(tree_nullifiers); - assert!(result.is_ok()); - assert!(tree.curr_root.is_some()); - } - - #[test] - fn test_search_item_inclusion() { - let mut tree = NullifierSparseMerkleTree::new(); - let tree_nullifier = create_nullifier_input([1u8; 32], 1, 1, 1); - - tree.insert_item(tree_nullifier.clone()).unwrap(); - - let result = tree.search_item_inclusion([1u8; 32]); - assert!(result.is_ok()); - assert_eq!(result.unwrap(), true); - - let non_existing = tree.search_item_inclusion([99u8; 32]); - assert!(non_existing.is_ok()); - assert_eq!(non_existing.unwrap(), false); - } - - #[test] - fn test_search_multiple_item_inclusions() { - let mut tree = NullifierSparseMerkleTree::new(); - let tree_nullifiers = vec![ - create_nullifier_input([1u8; 32], 1, 1, 1), - create_nullifier_input([2u8; 32], 2, 1, 1), - create_nullifier_input([3u8; 32], 3, 1, 1), - ]; - - tree.insert_items(tree_nullifiers).unwrap(); - - let search_hashes = vec![[1u8; 32], [2u8; 32], [99u8; 32]]; - let result = tree.search_item_inclusions(&search_hashes); - assert!(result.is_ok()); - - let expected_results = vec![true, true, false]; - assert_eq!(result.unwrap(), expected_results); - } - - #[test] - fn test_non_membership_proof() { - let mut tree = NullifierSparseMerkleTree::new(); - let non_member_hash = [5u8; 32]; - - let result = tree.get_non_membership_proof(non_member_hash); - assert!(result.is_ok()); - - let (proof, root) = result.unwrap(); - assert!(root.is_none()); - } - - #[test] - fn test_non_membership_proofs_multiple() { - let mut tree = NullifierSparseMerkleTree::new(); - let non_member_hashes = vec![[5u8; 32], [6u8; 32], [7u8; 32]]; - - let result = tree.get_non_membership_proofs(&non_member_hashes); - assert!(result.is_ok()); - - let proofs = result.unwrap(); - for (proof, root) in proofs { - assert!(root.is_none()); - } - } - - #[test] - fn test_insert_and_get_proof_of_existing_item() { - let mut tree = NullifierSparseMerkleTree::new(); - let tree_nullifier = create_nullifier_input([1u8; 32], 1, 1, 1); - - tree.insert_item(tree_nullifier.clone()).unwrap(); - - let proof_result = tree.get_non_membership_proof([1u8; 32]); - assert!(proof_result.is_err()); - } - - #[test] - fn test_insert_and_get_proofs_of_existing_items() { - let mut tree = NullifierSparseMerkleTree::new(); - let tree_nullifiers = vec![ - create_nullifier_input([1u8; 32], 1, 1, 1), - create_nullifier_input([2u8; 32], 2, 1, 1), - ]; - - tree.insert_items(tree_nullifiers).unwrap(); - - let proof_result = tree.get_non_membership_proofs(&[[1u8; 32], [2u8; 32]]); - assert!(proof_result.is_err()); - } -} diff --git a/node_core/Cargo.toml b/node_core/Cargo.toml index d948e79..2b59783 100644 --- a/node_core/Cargo.toml +++ b/node_core/Cargo.toml @@ -12,7 +12,7 @@ serde.workspace = true rand.workspace = true k256.workspace = true sha2.workspace = true -monotree.workspace = true +indexed-merkle-tree.workspace = true bincode.workspace = true elliptic-curve.workspace = true reqwest.workspace = true diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index 90c9cb1..7fb3d85 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -8,9 +8,9 @@ use anyhow::Result; use block_store::NodeBlockStore; use common::{ block::Block, + indexed_merkle_tree::IndexedMerkleTreeWrapper, merkle_tree_public::merkle_tree::{PublicTransactionMerkleTree, UTXOCommitmentsMerkleTree}, nullifier::UTXONullifier, - nullifier_sparse_merkle_tree::{NullifierSparseMerkleTree, NullifierTreeInput}, utxo_commitment::UTXOCommitment, }; use k256::AffinePoint; @@ -26,7 +26,7 @@ pub mod public_context; pub struct NodeChainStore { pub acc_map: HashMap, pub block_store: NodeBlockStore, - pub nullifier_store: NullifierSparseMerkleTree, + pub nullifier_store: IndexedMerkleTreeWrapper, pub utxo_commitments_store: UTXOCommitmentsMerkleTree, pub pub_tx_store: PublicTransactionMerkleTree, } @@ -34,7 +34,7 @@ pub struct NodeChainStore { impl NodeChainStore { pub fn new_with_genesis(home_dir: &Path, genesis_block: Block) -> Self { let acc_map = HashMap::new(); - let nullifier_store = NullifierSparseMerkleTree::default(); + let nullifier_store = IndexedMerkleTreeWrapper::default(); let utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]); let pub_tx_store = PublicTransactionMerkleTree::new(vec![]); @@ -97,19 +97,8 @@ impl NodeChainStore { .collect(), ); - self.nullifier_store.insert_items( - tx.nullifier_created_hashes - .clone() - .into_iter() - .enumerate() - .map(|(idx, hash)| NullifierTreeInput { - nullifier_id: idx as u64, - tx_id: tx_id as u64, - block_id: block.block_id, - nullifier: UTXONullifier { utxo_hash: hash }, - }) - .collect(), - )?; + self.nullifier_store + .insert_items(tx.nullifier_created_hashes.clone())?; if !tx.encoded_data.is_empty() { let ephemeral_public_key_sender = @@ -159,7 +148,7 @@ impl NodeChainStore { caller_address: caller, caller_balance: self.acc_map.get(&caller).unwrap().balance, account_masks, - nullifier_store_root: self.nullifier_store.curr_root.unwrap_or([0; 32]), + nullifier_store_root: self.nullifier_store.get_curr_root().unwrap_or([0; 32]), comitment_store_root: self.utxo_commitments_store.get_root().unwrap_or([0; 32]), pub_tx_store_root: self.pub_tx_store.get_root().unwrap_or([0; 32]), } diff --git a/node_core/src/executions/de.rs b/node_core/src/executions/de.rs index ddc5e81..68acb7b 100644 --- a/node_core/src/executions/de.rs +++ b/node_core/src/executions/de.rs @@ -1,14 +1,10 @@ use std::collections::BTreeMap; use bincode; -use common::nullifier_sparse_merkle_tree::NullifierTreeInput; use common::{ - commitment::Commitment, commitments_sparse_merkle_tree::CommitmentsSparseMerkleTree, - nullifier::UTXONullifier, nullifier_sparse_merkle_tree::NullifierSparseMerkleTree, + commitment::Commitment, indexed_merkle_tree::IndexedMerkleTreeWrapper, nullifier::UTXONullifier, }; use k256::Scalar; -use monotree::hasher::Blake3; -use monotree::{Hasher, Monotree}; use rand::thread_rng; use secp256k1_zkp::{CommitmentSecrets, Generator, PedersenCommitment, Tag, Tweak, SECP256K1}; use sha2::{Digest, Sha256}; @@ -80,24 +76,16 @@ pub fn validate_in_commitments_proof( // Replace with Merkle proof verification logic. // hash(&[pedersen_commitment.serialize().to_vec(), in_commitments_proof.concat()].concat()) == root_commitment - let mut nsmt = CommitmentsSparseMerkleTree { - curr_root: Option::Some(root_commitment), - tree: Monotree::default(), - hasher: Blake3::new(), - }; + let mut nsmt = IndexedMerkleTreeWrapper::new(); let commitments: Vec<_> = in_commitments_proof .into_iter() - .map(|n_p| Commitment { - commitment_hash: n_p.clone(), - }) + .map(|n_p| n_p.clone().try_into().unwrap()) .collect(); nsmt.insert_items(commitments).unwrap(); - nsmt.get_non_membership_proof(in_commitment.clone()) - .unwrap() - .1 - .is_some() + nsmt.get_non_membership_proof(in_commitment.clone().try_into().unwrap()) + .is_ok() } // Validate non-membership proof for nullifiers @@ -109,32 +97,16 @@ pub fn validate_nullifiers_proof( root_nullifier: [u8; 32], nullifiers_proof: &[[u8; 32]], ) -> bool { - //There is no need for storage, so ids can be default there - let id = 1; + let mut nsmt = IndexedMerkleTreeWrapper::new(); - let mut nsmt = NullifierSparseMerkleTree { - curr_root: Option::Some(root_nullifier), - tree: Monotree::default(), - hasher: Blake3::new(), - leafs: BTreeMap::new(), - }; - - let nullifiers: Vec<_> = nullifiers_proof + let commitments: Vec<_> = nullifiers_proof .into_iter() - .enumerate() - .map(|(idx, n_p)| NullifierTreeInput { - nullifier_id: idx as u64, - tx_id: id, - block_id: id, - nullifier: UTXONullifier { utxo_hash: *n_p }, - }) + .map(|n_p| n_p.clone().try_into().unwrap()) .collect(); - nsmt.insert_items(nullifiers).unwrap(); + nsmt.insert_items(commitments).unwrap(); - nsmt.get_non_membership_proof(nullifier) - .unwrap() - .1 - .is_none() + nsmt.get_non_membership_proof(nullifier.clone().try_into().unwrap()) + .is_ok() } // Check balances diff --git a/node_core/src/executions/private_exec.rs b/node_core/src/executions/private_exec.rs index e3d55a1..4f61bd3 100644 --- a/node_core/src/executions/private_exec.rs +++ b/node_core/src/executions/private_exec.rs @@ -1,14 +1,10 @@ use std::collections::BTreeMap; use bincode; -use common::nullifier_sparse_merkle_tree::NullifierTreeInput; use common::{ - commitment::Commitment, commitments_sparse_merkle_tree::CommitmentsSparseMerkleTree, - nullifier::UTXONullifier, nullifier_sparse_merkle_tree::NullifierSparseMerkleTree, + commitment::Commitment, indexed_merkle_tree::IndexedMerkleTreeWrapper, nullifier::UTXONullifier, }; use k256::Scalar; -use monotree::hasher::Blake3; -use monotree::{Hasher, Monotree}; use sha2::{Digest, Sha256}; use utxo::utxo_core::UTXO; @@ -53,24 +49,16 @@ pub fn validate_in_commitments_proof( // Replace with Merkle proof verification logic. // hash(&[pedersen_commitment.serialize().to_vec(), in_commitments_proof.concat()].concat()) == root_commitment - let mut nsmt = CommitmentsSparseMerkleTree { - curr_root: Option::Some(root_commitment), - tree: Monotree::default(), - hasher: Blake3::new(), - }; + let mut nsmt = IndexedMerkleTreeWrapper::new(); let commitments: Vec<_> = in_commitments_proof .into_iter() - .map(|n_p| Commitment { - commitment_hash: n_p.clone(), - }) + .map(|n_p| n_p.clone().try_into().unwrap()) .collect(); nsmt.insert_items(commitments).unwrap(); - nsmt.get_non_membership_proof(in_commitment.clone()) - .unwrap() - .1 - .is_some() + nsmt.get_non_membership_proof(in_commitment.clone().try_into().unwrap()) + .is_ok() } // Validate non-membership proof for nullifiers @@ -82,32 +70,16 @@ pub fn validate_nullifiers_proof( root_nullifier: [u8; 32], nullifiers_proof: &[[u8; 32]], ) -> bool { - //There is no need for storage, so ids can be default there - let id = 1; + let mut nsmt = IndexedMerkleTreeWrapper::new(); - let mut nsmt = NullifierSparseMerkleTree { - curr_root: Option::Some(root_nullifier), - tree: Monotree::default(), - hasher: Blake3::new(), - leafs: BTreeMap::new(), - }; - - let nullifiers: Vec<_> = nullifiers_proof + let commitments: Vec<_> = nullifiers_proof .into_iter() - .enumerate() - .map(|(idx, n_p)| NullifierTreeInput { - nullifier_id: idx as u64, - tx_id: id, - block_id: id, - nullifier: UTXONullifier { utxo_hash: *n_p }, - }) + .map(|n_p| n_p.clone().try_into().unwrap()) .collect(); - nsmt.insert_items(nullifiers).unwrap(); + nsmt.insert_items(commitments).unwrap(); - nsmt.get_non_membership_proof(nullifier) - .unwrap() - .1 - .is_none() + nsmt.get_non_membership_proof(nullifier.clone().try_into().unwrap()) + .is_ok() } #[allow(unused)] diff --git a/node_core/src/executions/se.rs b/node_core/src/executions/se.rs index f9123c2..6b7285c 100644 --- a/node_core/src/executions/se.rs +++ b/node_core/src/executions/se.rs @@ -1,14 +1,10 @@ use std::collections::BTreeMap; use bincode; -use common::nullifier_sparse_merkle_tree::NullifierTreeInput; use common::{ - commitment::Commitment, commitments_sparse_merkle_tree::CommitmentsSparseMerkleTree, - nullifier::UTXONullifier, nullifier_sparse_merkle_tree::NullifierSparseMerkleTree, + commitment::Commitment, indexed_merkle_tree::IndexedMerkleTreeWrapper, nullifier::UTXONullifier, }; use k256::Scalar; -use monotree::hasher::Blake3; -use monotree::{Hasher, Monotree}; use rand::thread_rng; use secp256k1_zkp::{CommitmentSecrets, Generator, PedersenCommitment, Tag, Tweak, SECP256K1}; use sha2::{Digest, Sha256}; @@ -80,24 +76,16 @@ pub fn validate_in_commitments_proof( root_commitment: Vec, in_commitments_proof: &[Vec], ) -> bool { - let mut nsmt = CommitmentsSparseMerkleTree { - curr_root: Option::Some(root_commitment), - tree: Monotree::default(), - hasher: Blake3::new(), - }; + let mut nsmt = IndexedMerkleTreeWrapper::new(); let commitments: Vec<_> = in_commitments_proof .into_iter() - .map(|n_p| Commitment { - commitment_hash: n_p.clone(), - }) + .map(|n_p| n_p.clone().try_into().unwrap()) .collect(); nsmt.insert_items(commitments).unwrap(); - nsmt.get_non_membership_proof(pedersen_commitment.serialize().to_vec()) - .unwrap() - .1 - .is_some() + nsmt.get_non_membership_proof(pedersen_commitment.serialize().to_vec().try_into().unwrap()) + .is_ok() } // Validate non-membership proof for nullifiers @@ -111,32 +99,16 @@ pub fn validate_nullifiers_proof( root_nullifier: [u8; 32], nullifiers_proof: &[[u8; 32]], ) -> bool { - //There is no need for storage, so ids can be default there - let id = 1; + let mut nsmt = IndexedMerkleTreeWrapper::new(); - let mut nsmt = NullifierSparseMerkleTree { - curr_root: Option::Some(root_nullifier), - tree: Monotree::default(), - hasher: Blake3::new(), - leafs: BTreeMap::new(), - }; - - let nullifiers: Vec<_> = nullifiers_proof + let commitments: Vec<_> = nullifiers_proof .into_iter() - .enumerate() - .map(|(idx, n_p)| NullifierTreeInput { - nullifier_id: idx as u64, - tx_id: id, - block_id: id, - nullifier: UTXONullifier { utxo_hash: *n_p }, - }) + .map(|n_p| n_p.clone().try_into().unwrap()) .collect(); - nsmt.insert_items(nullifiers).unwrap(); + nsmt.insert_items(commitments).unwrap(); - nsmt.get_non_membership_proof(nullifier) - .unwrap() - .1 - .is_none() + nsmt.get_non_membership_proof(nullifier.clone().try_into().unwrap()) + .is_ok() } // Check balances diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index 5228e9b..5fc9289 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -167,7 +167,7 @@ impl NodeCore { pub async fn get_roots(&self) -> [[u8; 32]; 3] { let storage = self.storage.read().await; [ - storage.nullifier_store.curr_root.unwrap_or([0; 32]), + storage.nullifier_store.get_curr_root().unwrap_or([0; 32]), storage.utxo_commitments_store.get_root().unwrap_or([0; 32]), storage.pub_tx_store.get_root().unwrap_or([0; 32]), ] diff --git a/node_rpc/src/types/err_rpc.rs b/node_rpc/src/types/err_rpc.rs index e1ace1f..0e75f7a 100644 --- a/node_rpc/src/types/err_rpc.rs +++ b/node_rpc/src/types/err_rpc.rs @@ -81,6 +81,5 @@ pub fn cast_common_execution_error_into_rpc_error(comm_exec_err: ExecutionFailur ExecutionFailureKind::SequencerClientError(seq_cli_err) => { cast_seq_client_error_into_rpc_error(seq_cli_err) } - ExecutionFailureKind::MonoTreeError(_) => RpcError::new_internal_error(None, &error_string), } } diff --git a/sc_core/Cargo.toml b/sc_core/Cargo.toml index 55ba888..4401ddb 100644 --- a/sc_core/Cargo.toml +++ b/sc_core/Cargo.toml @@ -12,7 +12,7 @@ serde.workspace = true rand.workspace = true k256.workspace = true sha2.workspace = true -monotree.workspace = true +indexed-merkle-tree.workspace = true bincode.workspace = true elliptic-curve.workspace = true hex.workspace = true diff --git a/sc_core/src/proofs_circuits.rs b/sc_core/src/proofs_circuits.rs index 3574ec4..5bc63ae 100644 --- a/sc_core/src/proofs_circuits.rs +++ b/sc_core/src/proofs_circuits.rs @@ -1,14 +1,10 @@ use std::collections::BTreeMap; use bincode; -use common::nullifier_sparse_merkle_tree::NullifierTreeInput; use common::{ - commitment::Commitment, commitments_sparse_merkle_tree::CommitmentsSparseMerkleTree, - nullifier::UTXONullifier, nullifier_sparse_merkle_tree::NullifierSparseMerkleTree, + commitment::Commitment, indexed_merkle_tree::IndexedMerkleTreeWrapper, nullifier::UTXONullifier, }; use k256::Scalar; -use monotree::hasher::Blake3; -use monotree::{Hasher, Monotree}; use rand::{thread_rng, RngCore}; use secp256k1_zkp::{CommitmentSecrets, Generator, PedersenCommitment, Tag, Tweak, SECP256K1}; use sha2::{Digest, Sha256}; @@ -55,24 +51,16 @@ pub fn validate_in_commitments_proof( // Replace with Merkle proof verification logic. // hash(&[pedersen_commitment.serialize().to_vec(), in_commitments_proof.concat()].concat()) == root_commitment - let mut nsmt = CommitmentsSparseMerkleTree { - curr_root: Option::Some(root_commitment), - tree: Monotree::default(), - hasher: Blake3::new(), - }; + let mut nsmt = IndexedMerkleTreeWrapper::new(); let commitments: Vec<_> = in_commitments_proof .into_iter() - .map(|n_p| Commitment { - commitment_hash: n_p.clone(), - }) + .map(|n_p| n_p.clone().try_into().unwrap()) .collect(); nsmt.insert_items(commitments).unwrap(); - nsmt.get_non_membership_proof(in_commitment.clone()) - .unwrap() - .1 - .is_some() + nsmt.get_non_membership_proof(in_commitment.clone().try_into().unwrap()) + .is_ok() } // Validate non-membership proof for nullifiers @@ -84,32 +72,16 @@ pub fn validate_nullifiers_proof( root_nullifier: [u8; 32], nullifiers_proof: &[[u8; 32]], ) -> bool { - //There is no need for storage, so ids can be default there - let id = 1; + let mut nsmt = IndexedMerkleTreeWrapper::new(); - let mut nsmt = NullifierSparseMerkleTree { - curr_root: Option::Some(root_nullifier), - tree: Monotree::default(), - hasher: Blake3::new(), - leafs: BTreeMap::new(), - }; - - let nullifiers: Vec<_> = nullifiers_proof + let commitments: Vec<_> = nullifiers_proof .into_iter() - .enumerate() - .map(|(idx, n_p)| NullifierTreeInput { - nullifier_id: idx as u64, - tx_id: id, - block_id: id, - nullifier: UTXONullifier { utxo_hash: *n_p }, - }) + .map(|n_p| n_p.clone().try_into().unwrap()) .collect(); - nsmt.insert_items(nullifiers).unwrap(); + nsmt.insert_items(commitments).unwrap(); - nsmt.get_non_membership_proof(nullifier) - .unwrap() - .1 - .is_none() + nsmt.get_non_membership_proof(nullifier.clone().try_into().unwrap()) + .is_ok() } #[allow(unused)] @@ -277,24 +249,16 @@ pub fn validate_in_commitments_proof_se( root_commitment: Vec, in_commitments_proof: &[Vec], ) -> bool { - let mut nsmt = CommitmentsSparseMerkleTree { - curr_root: Option::Some(root_commitment), - tree: Monotree::default(), - hasher: Blake3::new(), - }; + let mut nsmt = IndexedMerkleTreeWrapper::new(); let commitments: Vec<_> = in_commitments_proof .into_iter() - .map(|n_p| Commitment { - commitment_hash: n_p.clone(), - }) + .map(|n_p| n_p.clone().try_into().unwrap()) .collect(); nsmt.insert_items(commitments).unwrap(); - nsmt.get_non_membership_proof(pedersen_commitment.serialize().to_vec()) - .unwrap() - .1 - .is_some() + nsmt.get_non_membership_proof(pedersen_commitment.serialize().to_vec().try_into().unwrap()) + .is_ok() } // Generate nullifiers SE diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 647af9b..4a055d8 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -5,7 +5,6 @@ use common::{ block::{Block, HashableBlockData}, merkle_tree_public::TreeHashType, nullifier::UTXONullifier, - nullifier_sparse_merkle_tree::NullifierTreeInput, transaction::{Transaction, TxKind}, utxo_commitment::UTXOCommitment, }; @@ -62,7 +61,10 @@ impl SequencerCore { pub fn get_tree_roots(&self) -> [[u8; 32]; 3] { [ - self.store.nullifier_store.curr_root.unwrap_or([0; 32]), + self.store + .nullifier_store + .get_curr_root() + .unwrap_or([0; 32]), self.store .utxo_commitments_store .get_root() @@ -139,7 +141,6 @@ impl SequencerCore { self.store .nullifier_store .search_item_inclusion(*nullifier_hash) - .unwrap_or(false) }) .any(|check| check); let utxo_commitments_check = utxo_commitments_created_hashes @@ -202,17 +203,10 @@ impl SequencerCore { .add_tx(UTXOCommitment { hash: *utxo_comm }); } - for (idx, nullifier) in nullifier_created_hashes.iter().enumerate() { + for nullifier in nullifier_created_hashes.iter() { self.store .nullifier_store - .insert_item(NullifierTreeInput { - nullifier_id: idx as u64, - tx_id, - block_id, - nullifier: UTXONullifier { - utxo_hash: *nullifier, - }, - }) + .insert_item(*nullifier) .map_err(|err| TransactionMalformationErrorKind::FailedToInsert { tx: hash, details: format!("{err:?}"), diff --git a/sequencer_core/src/sequencer_store/mod.rs b/sequencer_core/src/sequencer_store/mod.rs index fd09d93..592e61e 100644 --- a/sequencer_core/src/sequencer_store/mod.rs +++ b/sequencer_core/src/sequencer_store/mod.rs @@ -4,8 +4,8 @@ use accounts_store::SequencerAccountsStore; use block_store::SequecerBlockStore; use common::{ block::{Block, HashableBlockData}, + indexed_merkle_tree::IndexedMerkleTreeWrapper, merkle_tree_public::merkle_tree::{PublicTransactionMerkleTree, UTXOCommitmentsMerkleTree}, - nullifier_sparse_merkle_tree::NullifierSparseMerkleTree, }; use rand::{rngs::OsRng, RngCore}; @@ -15,7 +15,7 @@ pub mod block_store; pub struct SequecerChainStore { pub acc_store: SequencerAccountsStore, pub block_store: SequecerBlockStore, - pub nullifier_store: NullifierSparseMerkleTree, + pub nullifier_store: IndexedMerkleTreeWrapper, pub utxo_commitments_store: UTXOCommitmentsMerkleTree, pub pub_tx_store: PublicTransactionMerkleTree, } @@ -23,7 +23,7 @@ pub struct SequecerChainStore { impl SequecerChainStore { pub fn new_with_genesis(home_dir: &Path, genesis_id: u64, is_genesis_random: bool) -> Self { let acc_store = SequencerAccountsStore::default(); - let nullifier_store = NullifierSparseMerkleTree::default(); + let nullifier_store = IndexedMerkleTreeWrapper::default(); let utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]); let pub_tx_store = PublicTransactionMerkleTree::new(vec![]); diff --git a/utxo/Cargo.toml b/utxo/Cargo.toml index 9b99cf9..e7b35ef 100644 --- a/utxo/Cargo.toml +++ b/utxo/Cargo.toml @@ -9,7 +9,7 @@ serde_json.workspace = true env_logger.workspace = true log.workspace = true serde.workspace = true -monotree.workspace = true +indexed-merkle-tree.workspace = true sha2.workspace = true hex.workspace = true From cb22a95df25bfac699fd49b37ae43558e8ae5cc5 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Fri, 23 May 2025 09:04:04 +0300 Subject: [PATCH 4/8] fix: smt/imt replaced with sets --- common/src/commitments_sparse_merkle_tree.rs | 283 ------------------ common/src/indexed_merkle_tree.rs | 248 --------------- common/src/lib.rs | 1 - common/src/nullifier.rs | 2 +- common/src/rpc_primitives/requests.rs | 4 +- node_core/src/chain_storage/mod.rs | 15 +- node_core/src/chain_storage/public_context.rs | 5 - node_core/src/executions/de.rs | 217 -------------- node_core/src/executions/mod.rs | 3 - node_core/src/executions/private_exec.rs | 118 -------- node_core/src/executions/se.rs | 171 ----------- node_core/src/lib.rs | 9 +- node_core/src/sequencer_client/json.rs | 4 +- node_core/src/sequencer_client/mod.rs | 2 +- sc_core/src/proofs_circuits.rs | 44 +-- sequencer_core/src/lib.rs | 27 +- sequencer_core/src/sequencer_store/mod.rs | 9 +- 17 files changed, 35 insertions(+), 1127 deletions(-) delete mode 100644 common/src/commitments_sparse_merkle_tree.rs delete mode 100644 common/src/indexed_merkle_tree.rs delete mode 100644 node_core/src/executions/de.rs delete mode 100644 node_core/src/executions/mod.rs delete mode 100644 node_core/src/executions/private_exec.rs delete mode 100644 node_core/src/executions/se.rs diff --git a/common/src/commitments_sparse_merkle_tree.rs b/common/src/commitments_sparse_merkle_tree.rs deleted file mode 100644 index 3182275..0000000 --- a/common/src/commitments_sparse_merkle_tree.rs +++ /dev/null @@ -1,283 +0,0 @@ -use monotree::database::MemoryDB; -use monotree::hasher::Blake3; -use monotree::{Hasher, Monotree, Proof}; - -use crate::commitment::Commitment; -use crate::merkle_tree_public::CommitmentHashType; - -pub struct CommitmentsSparseMerkleTree { - pub curr_root: Option, - pub tree: Monotree, - pub hasher: Blake3, -} - -impl CommitmentsSparseMerkleTree { - pub fn new() -> Self { - CommitmentsSparseMerkleTree { - curr_root: None, - tree: Monotree::default(), - hasher: Blake3::new(), - } - } - - pub fn insert_item(&mut self, commitment: Commitment) -> Result<(), monotree::Errors> { - let root = self - .curr_root - .as_ref() - .map(|val| val[0..32].try_into().unwrap()); - - let new_root = self.tree.insert( - root, - &commitment.commitment_hash[0..32].try_into().unwrap(), - &commitment.commitment_hash[0..32].try_into().unwrap(), - )?; - - self.curr_root = new_root.map(|val| val.to_vec()); - - Ok(()) - } - - pub fn insert_items(&mut self, commitments: Vec) -> Result<(), monotree::Errors> { - let root = self - .curr_root - .as_ref() - .map(|val| val[0..32].try_into().unwrap()); - - let hashes: Vec<_> = commitments - .iter() - .map(|val| val.commitment_hash[0..32].try_into().unwrap()) - .collect::>(); - - let new_root = self.tree.inserts(root, &hashes, &hashes)?; - - self.curr_root = new_root.map(|val| val[0..32].try_into().unwrap()); - - Ok(()) - } - - pub fn search_item_inclusion( - &mut self, - commitment_hash: CommitmentHashType, - ) -> Result { - self.tree - .get( - self.curr_root - .as_ref() - .map(|val| val[0..32].try_into().unwrap()), - &commitment_hash[0..32].try_into().unwrap(), - ) - .map(|data| data.is_some()) - } - - pub fn search_item_inclusions( - &mut self, - commitment_hashes: &[CommitmentHashType], - ) -> Result, monotree::Errors> { - let mut inclusions = vec![]; - - for nullifier_hash in commitment_hashes { - let is_included = self - .tree - .get( - self.curr_root - .as_ref() - .map(|val| val[0..32].try_into().unwrap()), - nullifier_hash[0..32].try_into().unwrap(), - ) - .map(|data| data.is_some())?; - - inclusions.push(is_included); - } - - Ok(inclusions) - } - - pub fn get_non_membership_proof( - &mut self, - commitment_hash: CommitmentHashType, - ) -> Result<(Option, Option), monotree::Errors> { - let is_member = self.search_item_inclusion(commitment_hash.clone())?; - - if is_member { - Err(monotree::Errors::new("Is a member")) - } else { - Ok(( - self.tree.get_merkle_proof( - self.curr_root - .as_ref() - .map(|val| val[0..32].try_into().unwrap()), - &commitment_hash, - )?, - self.curr_root.clone(), - )) - } - } - - #[allow(clippy::type_complexity)] - pub fn get_non_membership_proofs( - &mut self, - commitment_hashes: &[CommitmentHashType], - ) -> Result, Option)>, monotree::Errors> { - let mut non_membership_proofs = vec![]; - - for commitment_hash in commitment_hashes { - let is_member = self.search_item_inclusion(commitment_hash.clone())?; - - if is_member { - return Err(monotree::Errors::new( - format!("{commitment_hash:?} Is a member").as_str(), - )); - } else { - non_membership_proofs.push(( - self.tree.get_merkle_proof( - self.curr_root - .as_ref() - .map(|val| val[0..32].try_into().unwrap()), - commitment_hash, - )?, - self.curr_root.clone(), - )) - }; - } - - Ok(non_membership_proofs) - } -} - -impl Default for CommitmentsSparseMerkleTree { - fn default() -> Self { - Self::new() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::nullifier::UTXONullifier; - use monotree::database::MemoryDB; - use monotree::hasher::Blake3; - use monotree::Monotree; - - fn create_nullifier(hash: CommitmentHashType) -> Commitment { - Commitment { - commitment_hash: hash, - } - } - - #[test] - fn test_new_tree_initialization() { - let tree = CommitmentsSparseMerkleTree::new(); - assert!(tree.curr_root.is_none()); - } - - #[test] - fn test_insert_single_item() { - let mut tree = CommitmentsSparseMerkleTree::new(); - let nullifier = create_nullifier([1u8; 32].to_vec()); // Sample 32-byte hash - - let result = tree.insert_item(nullifier); - assert!(result.is_ok()); - assert!(tree.curr_root.is_some()); - } - - #[test] - fn test_insert_multiple_items() { - let mut tree = CommitmentsSparseMerkleTree::new(); - let nullifiers = vec![ - create_nullifier([1u8; 32].to_vec()), - create_nullifier([2u8; 32].to_vec()), - create_nullifier([3u8; 32].to_vec()), - ]; - - let result = tree.insert_items(nullifiers); - assert!(result.is_ok()); - assert!(tree.curr_root.is_some()); - } - - #[test] - fn test_search_item_inclusion() { - let mut tree = CommitmentsSparseMerkleTree::new(); - let nullifier = create_nullifier([1u8; 32].to_vec()); - - tree.insert_item(nullifier.clone()).unwrap(); - - let result = tree.search_item_inclusion([1u8; 32].to_vec()); - assert!(result.is_ok()); - assert_eq!(result.unwrap(), true); - - let non_existing = tree.search_item_inclusion([99u8; 32].to_vec()); - assert!(non_existing.is_ok()); - assert_eq!(non_existing.unwrap(), false); - } - - #[test] - fn test_search_multiple_item_inclusions() { - let mut tree = CommitmentsSparseMerkleTree::new(); - let nullifiers = vec![ - create_nullifier([1u8; 32].to_vec()), - create_nullifier([2u8; 32].to_vec()), - create_nullifier([3u8; 32].to_vec()), - ]; - - tree.insert_items(nullifiers).unwrap(); - - let search_hashes = vec![[1u8; 32].to_vec(), [2u8; 32].to_vec(), [99u8; 32].to_vec()]; - let result = tree.search_item_inclusions(&search_hashes); - assert!(result.is_ok()); - - let expected_results = vec![true, true, false]; - assert_eq!(result.unwrap(), expected_results); - } - - #[test] - fn test_non_membership_proof() { - let mut tree = CommitmentsSparseMerkleTree::new(); - let non_member_hash = [5u8; 32].to_vec(); - - let result = tree.get_non_membership_proof(non_member_hash); - assert!(result.is_ok()); - - let (proof, root) = result.unwrap(); - assert!(root.is_none()); - } - - #[test] - fn test_non_membership_proofs_multiple() { - let mut tree = CommitmentsSparseMerkleTree::new(); - let non_member_hashes = vec![[5u8; 32].to_vec(), [6u8; 32].to_vec(), [7u8; 32].to_vec()]; - - let result = tree.get_non_membership_proofs(&non_member_hashes); - assert!(result.is_ok()); - - let proofs = result.unwrap(); - for (proof, root) in proofs { - assert!(root.is_none()); - } - } - - #[test] - fn test_insert_and_get_proof_of_existing_item() { - let mut tree = CommitmentsSparseMerkleTree::new(); - let nullifier = create_nullifier([1u8; 32].to_vec()); - - tree.insert_item(nullifier.clone()).unwrap(); - - let proof_result = tree.get_non_membership_proof([1u8; 32].to_vec()); - assert!(proof_result.is_err()); - } - - #[test] - fn test_insert_and_get_proofs_of_existing_items() { - let mut tree = CommitmentsSparseMerkleTree::new(); - let nullifiers = vec![ - create_nullifier([1u8; 32].to_vec()), - create_nullifier([2u8; 32].to_vec()), - ]; - - tree.insert_items(nullifiers).unwrap(); - - let proof_result = - tree.get_non_membership_proofs(&[[1u8; 32].to_vec(), [2u8; 32].to_vec()]); - assert!(proof_result.is_err()); - } -} diff --git a/common/src/indexed_merkle_tree.rs b/common/src/indexed_merkle_tree.rs deleted file mode 100644 index e8df6b5..0000000 --- a/common/src/indexed_merkle_tree.rs +++ /dev/null @@ -1,248 +0,0 @@ -use crate::merkle_tree_public::TreeHashType; - -use anyhow::Result; -use indexed_merkle_tree::node::Node; -use indexed_merkle_tree::tree::{IndexedMerkleTree, NonMembershipProof}; -use indexed_merkle_tree::Hash; - -pub struct IndexedMerkleTreeWrapper { - pub tree: IndexedMerkleTree, - pub leaf_len: usize, - //pub leafs: BTreeMap, -} - -impl IndexedMerkleTreeWrapper { - pub fn new() -> Self { - Self { - //Will not panic - //Deterministic operation - tree: IndexedMerkleTree::new(vec![]).unwrap(), - leaf_len: 0, - } - } - - pub fn get_curr_root(&self) -> Result { - //HELP - // self.tree.get_root().map(|node| - // serde_json::from_str::>(&serde_json::to_string(node).unwrap())[0] - // ) - Ok([0; 32]) - } - - pub fn insert_item(&mut self, hash: TreeHashType) -> Result<()> { - let left_parity = self.leaf_len / 2; - let mut node = match left_parity { - 0 => Node::new_leaf(true, Hash::new(hash), Hash::new(hash), Node::TAIL), - 1 => Node::new_leaf(false, Hash::new(hash), Hash::new(hash), Node::TAIL), - _ => unreachable!(), - }; - - self.tree.insert_node(&mut node)?; - - self.leaf_len += 1; - - Ok(()) - } - - pub fn insert_items(&mut self, tree_nullifiers: Vec) -> Result<()> { - for tree_nullifier in tree_nullifiers { - self.insert_item(tree_nullifier)?; - } - - Ok(()) - } - - pub fn search_item_inclusion(&mut self, nullifier_hash: TreeHashType) -> bool { - self.tree - .find_leaf_by_label(&Hash::new(nullifier_hash)) - .is_some() - } - - pub fn search_item_inclusions(&mut self, nullifier_hashes: &[TreeHashType]) -> Vec { - let mut inclusions = vec![]; - - for nullifier_hash in nullifier_hashes { - let is_included = self.search_item_inclusion(*nullifier_hash); - - inclusions.push(is_included); - } - - inclusions - } - - pub fn get_non_membership_proof( - &mut self, - nullifier_hash: TreeHashType, - ) -> Result { - let node = Node::new_leaf( - false, - Hash::new(nullifier_hash), - Hash::new(nullifier_hash), - Node::TAIL, - ); - - self.tree.generate_non_membership_proof(&node) - } - - #[allow(clippy::type_complexity)] - pub fn get_non_membership_proofs( - &mut self, - nullifier_hashes: &[TreeHashType], - ) -> Result> { - let mut non_membership_proofs = vec![]; - - for nullifier_hash in nullifier_hashes { - let non_mem_proof = self.get_non_membership_proof(*nullifier_hash)?; - - non_membership_proofs.push(non_mem_proof); - } - - Ok(non_membership_proofs) - } -} - -impl Default for IndexedMerkleTreeWrapper { - fn default() -> Self { - Self::new() - } -} - -#[cfg(test)] -mod tests { - // use super::*; - // use crate::nullifier::UTXONullifier; - - // fn create_nullifier(hash: TreeHashType) -> UTXONullifier { - // UTXONullifier { utxo_hash: hash } - // } - - // fn create_nullifier_input( - // hash: TreeHashType, - // nullifier_id: u64, - // tx_id: u64, - // block_id: u64, - // ) -> NullifierTreeInput { - // NullifierTreeInput { - // nullifier_id, - // tx_id, - // block_id, - // nullifier: create_nullifier(hash), - // } - // } - - // #[test] - // fn test_new_tree_initialization() { - // let tree = IndexedMerkleTree::new(); - // assert!(tree.curr_root.is_none()); - // } - - // #[test] - // fn test_insert_single_item() { - // let mut tree = IndexedMerkleTree::new(); - // let tree_nullifier = create_nullifier_input([1u8; 32], 1, 1, 1); // Sample 32-byte hash - - // let result = tree.insert_item(tree_nullifier); - // assert!(result.is_ok()); - // assert!(tree.curr_root.is_some()); - // } - - // #[test] - // fn test_insert_multiple_items() { - // let mut tree = IndexedMerkleTree::new(); - // let tree_nullifiers = vec![ - // create_nullifier_input([1u8; 32], 1, 1, 1), - // create_nullifier_input([2u8; 32], 2, 1, 1), - // create_nullifier_input([3u8; 32], 3, 1, 1), - // ]; - - // let result = tree.insert_items(tree_nullifiers); - // assert!(result.is_ok()); - // assert!(tree.curr_root.is_some()); - // } - - // #[test] - // fn test_search_item_inclusion() { - // let mut tree = IndexedMerkleTree::new(); - // let tree_nullifier = create_nullifier_input([1u8; 32], 1, 1, 1); - - // tree.insert_item(tree_nullifier.clone()).unwrap(); - - // let result = tree.search_item_inclusion([1u8; 32]); - // assert!(result.is_ok()); - // assert_eq!(result.unwrap(), true); - - // let non_existing = tree.search_item_inclusion([99u8; 32]); - // assert!(non_existing.is_ok()); - // assert_eq!(non_existing.unwrap(), false); - // } - - // #[test] - // fn test_search_multiple_item_inclusions() { - // let mut tree = IndexedMerkleTree::new(); - // let tree_nullifiers = vec![ - // create_nullifier_input([1u8; 32], 1, 1, 1), - // create_nullifier_input([2u8; 32], 2, 1, 1), - // create_nullifier_input([3u8; 32], 3, 1, 1), - // ]; - - // tree.insert_items(tree_nullifiers).unwrap(); - - // let search_hashes = vec![[1u8; 32], [2u8; 32], [99u8; 32]]; - // let result = tree.search_item_inclusions(&search_hashes); - // assert!(result.is_ok()); - - // let expected_results = vec![true, true, false]; - // assert_eq!(result.unwrap(), expected_results); - // } - - // #[test] - // fn test_non_membership_proof() { - // let mut tree = IndexedMerkleTree::new(); - // let non_member_hash = [5u8; 32]; - - // let result = tree.get_non_membership_proof(non_member_hash); - // assert!(result.is_ok()); - - // let (proof, root) = result.unwrap(); - // assert!(root.is_none()); - // } - - // #[test] - // fn test_non_membership_proofs_multiple() { - // let mut tree = IndexedMerkleTree::new(); - // let non_member_hashes = vec![[5u8; 32], [6u8; 32], [7u8; 32]]; - - // let result = tree.get_non_membership_proofs(&non_member_hashes); - // assert!(result.is_ok()); - - // let proofs = result.unwrap(); - // for (proof, root) in proofs { - // assert!(root.is_none()); - // } - // } - - // #[test] - // fn test_insert_and_get_proof_of_existing_item() { - // let mut tree = IndexedMerkleTree::new(); - // let tree_nullifier = create_nullifier_input([1u8; 32], 1, 1, 1); - - // tree.insert_item(tree_nullifier.clone()).unwrap(); - - // let proof_result = tree.get_non_membership_proof([1u8; 32]); - // assert!(proof_result.is_err()); - // } - - // #[test] - // fn test_insert_and_get_proofs_of_existing_items() { - // let mut tree = IndexedMerkleTree::new(); - // let tree_nullifiers = vec![ - // create_nullifier_input([1u8; 32], 1, 1, 1), - // create_nullifier_input([2u8; 32], 2, 1, 1), - // ]; - - // tree.insert_items(tree_nullifiers).unwrap(); - - // let proof_result = tree.get_non_membership_proofs(&[[1u8; 32], [2u8; 32]]); - // assert!(proof_result.is_err()); - // } -} diff --git a/common/src/lib.rs b/common/src/lib.rs index 9e238e2..46868d9 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -3,7 +3,6 @@ use serde::Deserialize; pub mod block; pub mod commitment; -pub mod indexed_merkle_tree; pub mod merkle_tree_public; pub mod nullifier; pub mod rpc_primitives; diff --git a/common/src/nullifier.rs b/common/src/nullifier.rs index 5033fa6..2c95741 100644 --- a/common/src/nullifier.rs +++ b/common/src/nullifier.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use crate::merkle_tree_public::TreeHashType; //ToDo: Update Nullifier model, when it is clear -#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, Eq)] +#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, Eq, Hash)] ///General nullifier object pub struct UTXONullifier { pub utxo_hash: TreeHashType, diff --git a/common/src/rpc_primitives/requests.rs b/common/src/rpc_primitives/requests.rs index 92e0abe..6cad01d 100644 --- a/common/src/rpc_primitives/requests.rs +++ b/common/src/rpc_primitives/requests.rs @@ -21,8 +21,8 @@ pub struct RegisterAccountRequest { #[derive(Serialize, Deserialize, Debug)] pub struct SendTxRequest { pub transaction: Transaction, - ///Nullifier Root, UTXO Commitment Root, Pub Tx Root - pub tx_roots: [[u8; 32]; 3], + ///UTXO Commitment Root, Pub Tx Root + pub tx_roots: [[u8; 32]; 2], } #[derive(Serialize, Deserialize, Debug)] diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index 7fb3d85..a6196f1 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -1,5 +1,5 @@ use std::{ - collections::{BTreeMap, HashMap}, + collections::{BTreeMap, HashMap, HashSet}, path::Path, }; @@ -8,7 +8,6 @@ use anyhow::Result; use block_store::NodeBlockStore; use common::{ block::Block, - indexed_merkle_tree::IndexedMerkleTreeWrapper, merkle_tree_public::merkle_tree::{PublicTransactionMerkleTree, UTXOCommitmentsMerkleTree}, nullifier::UTXONullifier, utxo_commitment::UTXOCommitment, @@ -26,7 +25,7 @@ pub mod public_context; pub struct NodeChainStore { pub acc_map: HashMap, pub block_store: NodeBlockStore, - pub nullifier_store: IndexedMerkleTreeWrapper, + pub nullifier_store: HashSet, pub utxo_commitments_store: UTXOCommitmentsMerkleTree, pub pub_tx_store: PublicTransactionMerkleTree, } @@ -34,7 +33,7 @@ pub struct NodeChainStore { impl NodeChainStore { pub fn new_with_genesis(home_dir: &Path, genesis_block: Block) -> Self { let acc_map = HashMap::new(); - let nullifier_store = IndexedMerkleTreeWrapper::default(); + let nullifier_store = HashSet::new(); let utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]); let pub_tx_store = PublicTransactionMerkleTree::new(vec![]); @@ -54,7 +53,7 @@ impl NodeChainStore { } pub fn dissect_insert_block(&mut self, block: Block) -> Result<()> { - for (tx_id, tx) in block.transactions.iter().enumerate() { + for tx in &block.transactions { if !tx.execution_input.is_empty() { let public_action = serde_json::from_slice::(&tx.execution_input); @@ -97,8 +96,9 @@ impl NodeChainStore { .collect(), ); - self.nullifier_store - .insert_items(tx.nullifier_created_hashes.clone())?; + for nullifier in tx.nullifier_created_hashes.iter() { + self.nullifier_store.insert(UTXONullifier { utxo_hash: *nullifier }); + } if !tx.encoded_data.is_empty() { let ephemeral_public_key_sender = @@ -148,7 +148,6 @@ impl NodeChainStore { caller_address: caller, caller_balance: self.acc_map.get(&caller).unwrap().balance, account_masks, - nullifier_store_root: self.nullifier_store.get_curr_root().unwrap_or([0; 32]), comitment_store_root: self.utxo_commitments_store.get_root().unwrap_or([0; 32]), pub_tx_store_root: self.pub_tx_store.get_root().unwrap_or([0; 32]), } diff --git a/node_core/src/chain_storage/public_context.rs b/node_core/src/chain_storage/public_context.rs index 5d5ceb6..438fa50 100644 --- a/node_core/src/chain_storage/public_context.rs +++ b/node_core/src/chain_storage/public_context.rs @@ -9,7 +9,6 @@ pub const CALLER_ADDRESS: &str = "caller_address"; pub const CALLER_BALANCE: &str = "caller_balance"; pub const ACCOUNT_MASKS_KEYS_SORTED: &str = "account_masks_keys_sorted"; pub const ACCOUNT_MASKS_VALUES_SORTED: &str = "account_masks_values_sorted"; -pub const NULLIFIER_STORE_ROOT: &str = "nullifier_store_root"; pub const COMMITMENT_STORE_ROOT: &str = "commitment_store_root"; pub const PUT_TX_STORE_ROOT: &str = "put_tx_store_root"; @@ -18,7 +17,6 @@ pub struct PublicSCContext { pub caller_address: AccountAddress, pub caller_balance: u64, pub account_masks: BTreeMap, - pub nullifier_store_root: TreeHashType, pub comitment_store_root: TreeHashType, pub pub_tx_store_root: TreeHashType, } @@ -41,7 +39,6 @@ impl Serialize for PublicSCContext { s.serialize_field(CALLER_BALANCE, &self.caller_balance)?; s.serialize_field(ACCOUNT_MASKS_KEYS_SORTED, &account_masks_keys)?; s.serialize_field(ACCOUNT_MASKS_VALUES_SORTED, &account_mask_values)?; - s.serialize_field(NULLIFIER_STORE_ROOT, &self.nullifier_store_root)?; s.serialize_field(COMMITMENT_STORE_ROOT, &self.comitment_store_root)?; s.serialize_field(PUT_TX_STORE_ROOT, &self.pub_tx_store_root)?; @@ -100,7 +97,6 @@ mod tests { fn create_test_context() -> PublicSCContext { let caller_address = [1; 32]; - let nullifier_store_root = [2; 32]; let comitment_store_root = [3; 32]; let pub_tx_store_root = [4; 32]; @@ -118,7 +114,6 @@ mod tests { caller_address, caller_balance: 100, account_masks, - nullifier_store_root, comitment_store_root, pub_tx_store_root, } diff --git a/node_core/src/executions/de.rs b/node_core/src/executions/de.rs deleted file mode 100644 index 68acb7b..0000000 --- a/node_core/src/executions/de.rs +++ /dev/null @@ -1,217 +0,0 @@ -use std::collections::BTreeMap; - -use bincode; -use common::{ - commitment::Commitment, indexed_merkle_tree::IndexedMerkleTreeWrapper, nullifier::UTXONullifier, -}; -use k256::Scalar; -use rand::thread_rng; -use secp256k1_zkp::{CommitmentSecrets, Generator, PedersenCommitment, Tag, Tweak, SECP256K1}; -use sha2::{Digest, Sha256}; -use utxo::utxo_core::UTXO; - -#[allow(unused)] -fn commitment_secrets_random(value: u64) -> CommitmentSecrets { - CommitmentSecrets { - value, - value_blinding_factor: Tweak::new(&mut thread_rng()), - generator_blinding_factor: Tweak::new(&mut thread_rng()), - } -} - -pub fn tag_random() -> Tag { - use rand::thread_rng; - use rand::RngCore; - - let mut bytes = [0u8; 32]; - thread_rng().fill_bytes(&mut bytes); - - Tag::from(bytes) -} - -pub fn commit(comm: &CommitmentSecrets, tag: Tag) -> PedersenCommitment { - let generator = Generator::new_blinded(SECP256K1, tag, comm.generator_blinding_factor); - - PedersenCommitment::new(SECP256K1, comm.value, comm.value_blinding_factor, generator) -} - -fn hash(input: &[u8]) -> Vec { - Sha256::digest(input).to_vec() -} - -// Generate nullifiers - -// takes the input_utxo and nsk -// returns the nullifiers[i], where the nullifier[i] = hash(in_commitments[i] || nsk) where the hash function -pub fn generate_nullifiers(input_utxo: &UTXO, nsk: &[u8]) -> Vec { - let mut input = bincode::serialize(input_utxo).unwrap().to_vec(); - input.extend_from_slice(nsk); - hash(&input) -} - -// Generate commitments for output UTXOs - -// uses the list of input_utxos[] -// returns in_commitments[] where each in_commitments[i] = Commitment(in_utxos[i]) where the commitment -pub fn generate_commitments(input_utxos: &[UTXO]) -> Vec> { - input_utxos - .iter() - .map(|utxo| { - let serialized = bincode::serialize(utxo).unwrap(); // Serialize UTXO. - hash(&serialized) - }) - .collect() -} - -// Validate inclusion proof for in_commitments - -// takes the in_commitments[i] as a leaf, the root hash root_commitment and the path in_commitments_proofs[i][], -// returns True if the in_commitments[i] is in the tree with root hash root_commitment otherwise returns False, as membership proof. -pub fn validate_in_commitments_proof( - in_commitment: &Vec, - root_commitment: Vec, - in_commitments_proof: &[Vec], -) -> bool { - // Placeholder implementation. - // Replace with Merkle proof verification logic. - // hash(&[pedersen_commitment.serialize().to_vec(), in_commitments_proof.concat()].concat()) == root_commitment - - let mut nsmt = IndexedMerkleTreeWrapper::new(); - - let commitments: Vec<_> = in_commitments_proof - .into_iter() - .map(|n_p| n_p.clone().try_into().unwrap()) - .collect(); - nsmt.insert_items(commitments).unwrap(); - - nsmt.get_non_membership_proof(in_commitment.clone().try_into().unwrap()) - .is_ok() -} - -// Validate non-membership proof for nullifiers - -// takes the nullifiers[i], path nullifiers_proof[i][] and the root hash root_nullifier, -// returns True if the nullifiers[i] is not in the tree with root hash root_nullifier otherwise returns False, as non-membership proof. -pub fn validate_nullifiers_proof( - nullifier: [u8; 32], - root_nullifier: [u8; 32], - nullifiers_proof: &[[u8; 32]], -) -> bool { - let mut nsmt = IndexedMerkleTreeWrapper::new(); - - let commitments: Vec<_> = nullifiers_proof - .into_iter() - .map(|n_p| n_p.clone().try_into().unwrap()) - .collect(); - nsmt.insert_items(commitments).unwrap(); - - nsmt.get_non_membership_proof(nullifier.clone().try_into().unwrap()) - .is_ok() -} - -// Check balances - -// takes the public_info and output_utxos[], -// returns the True if the token amount in public_info matches the sum of all output_utxos[], otherwise return False. -pub fn check_balances(public_info: u128, output_utxos: &[UTXO]) -> bool { - let total_output: u128 = output_utxos.iter().map(|utxo| utxo.amount).sum(); - public_info == total_output -} - -// Verify Pedersen commitment - -// takes the public_info, secret_r and pedersen_commitment and -// checks that commitment(public_info,secret_r) is equal pedersen_commitment where the commitment is pedersen commitment. -pub fn verify_commitment( - public_info: u64, - secret_r: &[u8], - pedersen_commitment: &PedersenCommitment, -) -> bool { - let commitment_secrets = CommitmentSecrets { - value: public_info, - value_blinding_factor: Tweak::from_slice(secret_r).unwrap(), - generator_blinding_factor: Tweak::new(&mut thread_rng()), - }; - - let tag = tag_random(); - let commitment = commit(&commitment_secrets, tag); - - commitment == *pedersen_commitment -} - -// new_commitment -pub fn new_commitment(public_info: u64, secret_r: &[u8]) -> (Tweak, &[u8], PedersenCommitment) { - let generator_blinding_factor = Tweak::new(&mut thread_rng()); - let commitment_secrets = CommitmentSecrets { - value: public_info, - value_blinding_factor: Tweak::from_slice(secret_r).unwrap(), - generator_blinding_factor, - }; - - let tag = tag_random(); - let commitment = commit(&commitment_secrets, tag); - - (generator_blinding_factor, secret_r, commitment) -} - -// new_commitment for a Vec of values -pub fn new_commitment_vec( - public_info_vec: Vec, - secret_r: &[u8], -) -> (Tweak, &[u8], Vec) { - let generator_blinding_factor = Tweak::new(&mut thread_rng()); - let tag = tag_random(); - - let vec_commitments = public_info_vec - .into_iter() - .map(|public_info| { - let commitment_secrets = CommitmentSecrets { - value: public_info, - value_blinding_factor: Tweak::from_slice(secret_r).unwrap(), - generator_blinding_factor, - }; - - commit(&commitment_secrets, tag) - }) - .collect(); - - (generator_blinding_factor, secret_r, vec_commitments) -} - -#[allow(unused)] -fn de_kernel( - root_commitment: &[u8], - root_nullifier: [u8; 32], - public_info: u64, - input_utxos: &[UTXO], - in_commitments_proof: &[Vec], - nullifiers_proof: &[[u8; 32]], - nullifier_secret_key: Scalar, -) -> (Vec, Vec>) { - check_balances(public_info as u128, input_utxos); - - let nullifiers: Vec<_> = input_utxos - .into_iter() - .map(|utxo| generate_nullifiers(&utxo, &nullifier_secret_key.to_bytes())) - .collect(); - - let in_commitments = generate_commitments(&input_utxos); - - for in_commitment in in_commitments { - validate_in_commitments_proof( - &in_commitment, - root_commitment.to_vec(), - in_commitments_proof, - ); - } - - for nullifier in nullifiers.iter() { - validate_nullifiers_proof( - nullifier[0..32].try_into().unwrap(), - root_nullifier, - nullifiers_proof, - ); - } - - (vec![], nullifiers) -} diff --git a/node_core/src/executions/mod.rs b/node_core/src/executions/mod.rs deleted file mode 100644 index 7c9d33e..0000000 --- a/node_core/src/executions/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod de; -pub mod private_exec; -pub mod se; diff --git a/node_core/src/executions/private_exec.rs b/node_core/src/executions/private_exec.rs deleted file mode 100644 index 4f61bd3..0000000 --- a/node_core/src/executions/private_exec.rs +++ /dev/null @@ -1,118 +0,0 @@ -use std::collections::BTreeMap; - -use bincode; -use common::{ - commitment::Commitment, indexed_merkle_tree::IndexedMerkleTreeWrapper, nullifier::UTXONullifier, -}; -use k256::Scalar; -use sha2::{Digest, Sha256}; -use utxo::utxo_core::UTXO; - -fn hash(input: &[u8]) -> Vec { - Sha256::digest(input).to_vec() -} - -// Generate nullifiers - -// takes the input_utxo and nsk -// returns the nullifiers[i], where the nullifier[i] = hash(in_commitments[i] || nsk) where the hash function -pub fn generate_nullifiers(input_utxo: &UTXO, nsk: &[u8]) -> Vec { - let mut input = bincode::serialize(input_utxo).unwrap().to_vec(); - input.extend_from_slice(nsk); - hash(&input) -} - -// Generate commitments for output UTXOs - -// uses the list of input_utxos[] -// returns in_commitments[] where each in_commitments[i] = Commitment(in_utxos[i]) where the commitment -pub fn generate_commitments(input_utxos: &[UTXO]) -> Vec> { - input_utxos - .iter() - .map(|utxo| { - let serialized = bincode::serialize(utxo).unwrap(); // Serialize UTXO. - hash(&serialized) - }) - .collect() -} - -// Validate inclusion proof for in_commitments - -// takes the in_commitments[i] as a leaf, the root hash root_commitment and the path in_commitments_proofs[i][], -// returns True if the in_commitments[i] is in the tree with root hash root_commitment otherwise returns False, as membership proof. -pub fn validate_in_commitments_proof( - in_commitment: &Vec, - root_commitment: Vec, - in_commitments_proof: &[Vec], -) -> bool { - // Placeholder implementation. - // Replace with Merkle proof verification logic. - // hash(&[pedersen_commitment.serialize().to_vec(), in_commitments_proof.concat()].concat()) == root_commitment - - let mut nsmt = IndexedMerkleTreeWrapper::new(); - - let commitments: Vec<_> = in_commitments_proof - .into_iter() - .map(|n_p| n_p.clone().try_into().unwrap()) - .collect(); - nsmt.insert_items(commitments).unwrap(); - - nsmt.get_non_membership_proof(in_commitment.clone().try_into().unwrap()) - .is_ok() -} - -// Validate non-membership proof for nullifiers - -// takes the nullifiers[i], path nullifiers_proof[i][] and the root hash root_nullifier, -// returns True if the nullifiers[i] is not in the tree with root hash root_nullifier otherwise returns False, as non-membership proof. -pub fn validate_nullifiers_proof( - nullifier: [u8; 32], - root_nullifier: [u8; 32], - nullifiers_proof: &[[u8; 32]], -) -> bool { - let mut nsmt = IndexedMerkleTreeWrapper::new(); - - let commitments: Vec<_> = nullifiers_proof - .into_iter() - .map(|n_p| n_p.clone().try_into().unwrap()) - .collect(); - nsmt.insert_items(commitments).unwrap(); - - nsmt.get_non_membership_proof(nullifier.clone().try_into().unwrap()) - .is_ok() -} - -#[allow(unused)] -fn private_kernel( - root_commitment: &[u8], - root_nullifier: [u8; 32], - input_utxos: &[UTXO], - in_commitments_proof: &[Vec], - nullifiers_proof: &[[u8; 32]], - nullifier_secret_key: Scalar, -) -> (Vec, Vec>) { - let nullifiers: Vec<_> = input_utxos - .into_iter() - .map(|utxo| generate_nullifiers(&utxo, &nullifier_secret_key.to_bytes())) - .collect(); - - let in_commitments = generate_commitments(&input_utxos); - - for in_commitment in in_commitments { - validate_in_commitments_proof( - &in_commitment, - root_commitment.to_vec(), - in_commitments_proof, - ); - } - - for nullifier in nullifiers.iter() { - validate_nullifiers_proof( - nullifier[0..32].try_into().unwrap(), - root_nullifier, - nullifiers_proof, - ); - } - - (vec![], nullifiers) -} diff --git a/node_core/src/executions/se.rs b/node_core/src/executions/se.rs deleted file mode 100644 index 6b7285c..0000000 --- a/node_core/src/executions/se.rs +++ /dev/null @@ -1,171 +0,0 @@ -use std::collections::BTreeMap; - -use bincode; -use common::{ - commitment::Commitment, indexed_merkle_tree::IndexedMerkleTreeWrapper, nullifier::UTXONullifier, -}; -use k256::Scalar; -use rand::thread_rng; -use secp256k1_zkp::{CommitmentSecrets, Generator, PedersenCommitment, Tag, Tweak, SECP256K1}; -use sha2::{Digest, Sha256}; -use utxo::utxo_core::UTXO; - -#[allow(unused)] -fn commitment_secrets_random(value: u64) -> CommitmentSecrets { - CommitmentSecrets { - value, - value_blinding_factor: Tweak::new(&mut thread_rng()), - generator_blinding_factor: Tweak::new(&mut thread_rng()), - } -} - -pub fn tag_random() -> Tag { - use rand::thread_rng; - use rand::RngCore; - - let mut bytes = [0u8; 32]; - thread_rng().fill_bytes(&mut bytes); - - Tag::from(bytes) -} - -pub fn commit(comm: &CommitmentSecrets, tag: Tag) -> PedersenCommitment { - let generator = Generator::new_blinded(SECP256K1, tag, comm.generator_blinding_factor); - - PedersenCommitment::new(SECP256K1, comm.value, comm.value_blinding_factor, generator) -} - -fn hash(input: &[u8]) -> Vec { - Sha256::digest(input).to_vec() -} - -// Generate nullifiers - -// takes the pedersen_commitment and nsk then -// returns a list of nullifiers, where the nullifier = hash(pedersen_commitment || nsk) where the hash function will be determined - -pub fn generate_nullifiers(pedersen_commitment: &PedersenCommitment, nsk: &[u8]) -> Vec { - let mut input = pedersen_commitment.serialize().to_vec(); - input.extend_from_slice(nsk); - hash(&input) -} - -// Generate commitments for output UTXOs - -// uses the list of output_utxos[] and -// returns out_commitments[] where each out_commitments[i] = Commitment(output_utxos[i]) -// where the commitment will be determined -pub fn generate_commitments(output_utxos: &[UTXO]) -> Vec> { - output_utxos - .iter() - .map(|utxo| { - let serialized = bincode::serialize(utxo).unwrap(); // Serialize UTXO. - hash(&serialized) - }) - .collect() -} - -// Validate inclusion proof for in_commitments - -// takes the pedersen_commitment as a leaf, the root hash root_commitment and the path in_commitments_proof[], -// returns True if the pedersen_commitment is in the tree with root hash root_commitment -// otherwise -// returns False, as membership proof. -pub fn validate_in_commitments_proof( - pedersen_commitment: &PedersenCommitment, - root_commitment: Vec, - in_commitments_proof: &[Vec], -) -> bool { - let mut nsmt = IndexedMerkleTreeWrapper::new(); - - let commitments: Vec<_> = in_commitments_proof - .into_iter() - .map(|n_p| n_p.clone().try_into().unwrap()) - .collect(); - nsmt.insert_items(commitments).unwrap(); - - nsmt.get_non_membership_proof(pedersen_commitment.serialize().to_vec().try_into().unwrap()) - .is_ok() -} - -// Validate non-membership proof for nullifiers - -// takes the nullifier, path nullifiers_proof[] and the root hash root_nullifier, -// returns True if the nullifier is not in the tree with root hash root_nullifier -// otherwise -// returns False, as non-membership proof. -pub fn validate_nullifiers_proof( - nullifier: [u8; 32], - root_nullifier: [u8; 32], - nullifiers_proof: &[[u8; 32]], -) -> bool { - let mut nsmt = IndexedMerkleTreeWrapper::new(); - - let commitments: Vec<_> = nullifiers_proof - .into_iter() - .map(|n_p| n_p.clone().try_into().unwrap()) - .collect(); - nsmt.insert_items(commitments).unwrap(); - - nsmt.get_non_membership_proof(nullifier.clone().try_into().unwrap()) - .is_ok() -} - -// Check balances - -// takes the public_info and output_utxos[], -// returns the True if the token amount in public_info matches the sum of all output_utxos[], otherwise return False. -pub fn check_balances(public_info: u128, output_utxos: &[UTXO]) -> bool { - let total_output: u128 = output_utxos.iter().map(|utxo| utxo.amount).sum(); - public_info == total_output -} - -// Verify Pedersen commitment - -// takes the public_info, secret_r and pedersen_commitment and -// checks that commitment(public_info,secret_r) is equal pedersen_commitment where the commitment is pedersen commitment. -pub fn verify_commitment( - public_info: u64, - secret_r: &[u8], - pedersen_commitment: &PedersenCommitment, -) -> bool { - let commitment_secrets = CommitmentSecrets { - value: public_info, - value_blinding_factor: Tweak::from_slice(secret_r).unwrap(), - generator_blinding_factor: Tweak::new(&mut thread_rng()), - }; - - let tag = tag_random(); - let commitment = commit(&commitment_secrets, tag); - - commitment == *pedersen_commitment -} - -#[allow(unused)] -fn se_kernel( - root_commitment: &[u8], - root_nullifier: [u8; 32], - public_info: u64, - pedersen_commitment: PedersenCommitment, - secret_r: &[u8], - output_utxos: &[UTXO], - in_commitments_proof: &[Vec], - nullifiers_proof: &[[u8; 32]], - nullifier_secret_key: Scalar, -) -> (Vec, Vec>, Vec) { - check_balances(public_info as u128, output_utxos); - - let out_commitments = generate_commitments(output_utxos); - - let nullifier = generate_nullifiers(&pedersen_commitment, &nullifier_secret_key.to_bytes()); - - validate_in_commitments_proof( - &pedersen_commitment, - root_commitment.to_vec(), - in_commitments_proof, - ); - - verify_commitment(public_info, secret_r, &pedersen_commitment); - - (vec![], out_commitments, nullifier) -} diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index 5fc9289..c36c34f 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -10,9 +10,8 @@ use anyhow::Result; use chain_storage::NodeChainStore; use common::transaction::{Transaction, TransactionPayload, TxKind}; use config::NodeConfig; -use executions::private_exec::{generate_commitments, generate_nullifiers}; use log::info; -use sc_core::proofs_circuits::pedersen_commitment_vec; +use sc_core::proofs_circuits::{generate_commitments, generate_nullifiers, generate_nullifiers_se, pedersen_commitment_vec}; use sequencer_client::{json::SendTxResponse, SequencerClient}; use serde::{Deserialize, Serialize}; use storage::sc_db_utils::DataBlobChangeVariant; @@ -28,7 +27,6 @@ pub const BLOCK_GEN_DELAY_SECS: u64 = 20; pub mod chain_storage; pub mod config; -pub mod executions; ///Module, which includes pre start setup helperfunctions pub mod pre_start; pub mod sequencer_client; @@ -164,10 +162,9 @@ impl NodeCore { }) } - pub async fn get_roots(&self) -> [[u8; 32]; 3] { + pub async fn get_roots(&self) -> [[u8; 32]; 2] { let storage = self.storage.read().await; [ - storage.nullifier_store.get_curr_root().unwrap_or([0; 32]), storage.utxo_commitments_store.get_root().unwrap_or([0; 32]), storage.pub_tx_store.get_root().unwrap_or([0; 32]), ] @@ -651,7 +648,7 @@ impl NodeCore { ) .unwrap(); - let nullifier = executions::se::generate_nullifiers( + let nullifier = generate_nullifiers_se( &commitment, &account .key_holder diff --git a/node_core/src/sequencer_client/json.rs b/node_core/src/sequencer_client/json.rs index 0c5373b..df94ca2 100644 --- a/node_core/src/sequencer_client/json.rs +++ b/node_core/src/sequencer_client/json.rs @@ -6,8 +6,8 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] pub struct SendTxRequest { pub transaction: Transaction, - ///Nullifier Root, UTXO Commitment Root, Pub Tx Root - pub tx_roots: [[u8; 32]; 3], + ///UTXO Commitment Root, Pub Tx Root + pub tx_roots: [[u8; 32]; 2], } //Responses diff --git a/node_core/src/sequencer_client/mod.rs b/node_core/src/sequencer_client/mod.rs index bc40a3a..7accd5f 100644 --- a/node_core/src/sequencer_client/mod.rs +++ b/node_core/src/sequencer_client/mod.rs @@ -73,7 +73,7 @@ impl SequencerClient { pub async fn send_tx( &self, transaction: Transaction, - tx_roots: [[u8; 32]; 3], + tx_roots: [[u8; 32]; 2], ) -> Result { let tx_req = SendTxRequest { transaction, diff --git a/sc_core/src/proofs_circuits.rs b/sc_core/src/proofs_circuits.rs index 5bc63ae..d7c27d6 100644 --- a/sc_core/src/proofs_circuits.rs +++ b/sc_core/src/proofs_circuits.rs @@ -1,9 +1,4 @@ -use std::collections::BTreeMap; - use bincode; -use common::{ - commitment::Commitment, indexed_merkle_tree::IndexedMerkleTreeWrapper, nullifier::UTXONullifier, -}; use k256::Scalar; use rand::{thread_rng, RngCore}; use secp256k1_zkp::{CommitmentSecrets, Generator, PedersenCommitment, Tag, Tweak, SECP256K1}; @@ -44,23 +39,14 @@ pub fn generate_commitments(input_utxos: &[UTXO]) -> Vec> { // returns True if the in_commitments[i] is in the tree with root hash root_commitment otherwise returns False, as membership proof. pub fn validate_in_commitments_proof( in_commitment: &Vec, - root_commitment: Vec, + _root_commitment: Vec, in_commitments_proof: &[Vec], ) -> bool { // Placeholder implementation. // Replace with Merkle proof verification logic. // hash(&[pedersen_commitment.serialize().to_vec(), in_commitments_proof.concat()].concat()) == root_commitment - let mut nsmt = IndexedMerkleTreeWrapper::new(); - - let commitments: Vec<_> = in_commitments_proof - .into_iter() - .map(|n_p| n_p.clone().try_into().unwrap()) - .collect(); - nsmt.insert_items(commitments).unwrap(); - - nsmt.get_non_membership_proof(in_commitment.clone().try_into().unwrap()) - .is_ok() + in_commitments_proof.contains(in_commitment) } // Validate non-membership proof for nullifiers @@ -69,19 +55,10 @@ pub fn validate_in_commitments_proof( // returns True if the nullifiers[i] is not in the tree with root hash root_nullifier otherwise returns False, as non-membership proof. pub fn validate_nullifiers_proof( nullifier: [u8; 32], - root_nullifier: [u8; 32], + _root_nullifier: [u8; 32], nullifiers_proof: &[[u8; 32]], ) -> bool { - let mut nsmt = IndexedMerkleTreeWrapper::new(); - - let commitments: Vec<_> = nullifiers_proof - .into_iter() - .map(|n_p| n_p.clone().try_into().unwrap()) - .collect(); - nsmt.insert_items(commitments).unwrap(); - - nsmt.get_non_membership_proof(nullifier.clone().try_into().unwrap()) - .is_ok() + !nullifiers_proof.contains(&nullifier) } #[allow(unused)] @@ -246,19 +223,10 @@ fn de_kernel( // returns False, as membership proof. pub fn validate_in_commitments_proof_se( pedersen_commitment: &PedersenCommitment, - root_commitment: Vec, + _root_commitment: Vec, in_commitments_proof: &[Vec], ) -> bool { - let mut nsmt = IndexedMerkleTreeWrapper::new(); - - let commitments: Vec<_> = in_commitments_proof - .into_iter() - .map(|n_p| n_p.clone().try_into().unwrap()) - .collect(); - nsmt.insert_items(commitments).unwrap(); - - nsmt.get_non_membership_proof(pedersen_commitment.serialize().to_vec().try_into().unwrap()) - .is_ok() + in_commitments_proof.contains(&pedersen_commitment.serialize().to_vec()) } // Generate nullifiers SE diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 4a055d8..05aac2b 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -59,12 +59,8 @@ impl SequencerCore { } } - pub fn get_tree_roots(&self) -> [[u8; 32]; 3] { + pub fn get_tree_roots(&self) -> [[u8; 32]; 2] { [ - self.store - .nullifier_store - .get_curr_root() - .unwrap_or([0; 32]), self.store .utxo_commitments_store .get_root() @@ -76,7 +72,7 @@ impl SequencerCore { pub fn transaction_pre_check( &mut self, tx: &Transaction, - tx_roots: [[u8; 32]; 3], + tx_roots: [[u8; 32]; 2], ) -> Result<(), TransactionMalformationErrorKind> { let Transaction { hash, @@ -140,7 +136,7 @@ impl SequencerCore { .map(|nullifier_hash| { self.store .nullifier_store - .search_item_inclusion(*nullifier_hash) + .contains(&UTXONullifier { utxo_hash: *nullifier_hash }) }) .any(|check| check); let utxo_commitments_check = utxo_commitments_created_hashes @@ -175,7 +171,7 @@ impl SequencerCore { pub fn push_tx_into_mempool_pre_check( &mut self, item: TransactionMempool, - tx_roots: [[u8; 32]; 3], + tx_roots: [[u8; 32]; 2], ) -> Result<(), TransactionMalformationErrorKind> { self.transaction_pre_check(&item.tx, tx_roots)?; @@ -187,11 +183,10 @@ impl SequencerCore { fn execute_check_transaction_on_state( &mut self, tx: TransactionMempool, - tx_id: u64, - block_id: u64, ) -> Result<(), TransactionMalformationErrorKind> { let Transaction { - hash, + // ToDo: remove hashing of transactions on node side [Issue #66] + hash: _, ref utxo_commitments_created_hashes, ref nullifier_created_hashes, .. @@ -206,11 +201,7 @@ impl SequencerCore { for nullifier in nullifier_created_hashes.iter() { self.store .nullifier_store - .insert_item(*nullifier) - .map_err(|err| TransactionMalformationErrorKind::FailedToInsert { - tx: hash, - details: format!("{err:?}"), - })?; + .insert(UTXONullifier{ utxo_hash: *nullifier}); } self.store.pub_tx_store.add_tx(tx.tx); @@ -233,8 +224,8 @@ impl SequencerCore { .mempool .pop_size(self.sequencer_config.max_num_tx_in_block); - for (idx, tx) in transactions.clone().into_iter().enumerate() { - self.execute_check_transaction_on_state(tx, idx as u64, new_block_height)?; + for tx in &transactions { + self.execute_check_transaction_on_state(tx.clone())?; } let prev_block_hash = self diff --git a/sequencer_core/src/sequencer_store/mod.rs b/sequencer_core/src/sequencer_store/mod.rs index 592e61e..5d28abd 100644 --- a/sequencer_core/src/sequencer_store/mod.rs +++ b/sequencer_core/src/sequencer_store/mod.rs @@ -1,11 +1,10 @@ -use std::path::Path; +use std::{collections::HashSet, path::Path}; use accounts_store::SequencerAccountsStore; use block_store::SequecerBlockStore; use common::{ block::{Block, HashableBlockData}, - indexed_merkle_tree::IndexedMerkleTreeWrapper, - merkle_tree_public::merkle_tree::{PublicTransactionMerkleTree, UTXOCommitmentsMerkleTree}, + merkle_tree_public::merkle_tree::{PublicTransactionMerkleTree, UTXOCommitmentsMerkleTree}, nullifier::UTXONullifier, }; use rand::{rngs::OsRng, RngCore}; @@ -15,7 +14,7 @@ pub mod block_store; pub struct SequecerChainStore { pub acc_store: SequencerAccountsStore, pub block_store: SequecerBlockStore, - pub nullifier_store: IndexedMerkleTreeWrapper, + pub nullifier_store: HashSet, pub utxo_commitments_store: UTXOCommitmentsMerkleTree, pub pub_tx_store: PublicTransactionMerkleTree, } @@ -23,7 +22,7 @@ pub struct SequecerChainStore { impl SequecerChainStore { pub fn new_with_genesis(home_dir: &Path, genesis_id: u64, is_genesis_random: bool) -> Self { let acc_store = SequencerAccountsStore::default(); - let nullifier_store = IndexedMerkleTreeWrapper::default(); + let nullifier_store = HashSet::new(); let utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]); let pub_tx_store = PublicTransactionMerkleTree::new(vec![]); From 9bf0ec9de7608d4820e3d48a81b4d071c4aff830 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Fri, 23 May 2025 09:07:53 +0300 Subject: [PATCH 5/8] fix: fmt --- node_core/src/chain_storage/mod.rs | 4 +++- node_core/src/lib.rs | 4 +++- sequencer_core/src/lib.rs | 14 +++++++------- sequencer_core/src/sequencer_store/mod.rs | 3 ++- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/node_core/src/chain_storage/mod.rs b/node_core/src/chain_storage/mod.rs index a6196f1..26bb809 100644 --- a/node_core/src/chain_storage/mod.rs +++ b/node_core/src/chain_storage/mod.rs @@ -97,7 +97,9 @@ impl NodeChainStore { ); for nullifier in tx.nullifier_created_hashes.iter() { - self.nullifier_store.insert(UTXONullifier { utxo_hash: *nullifier }); + self.nullifier_store.insert(UTXONullifier { + utxo_hash: *nullifier, + }); } if !tx.encoded_data.is_empty() { diff --git a/node_core/src/lib.rs b/node_core/src/lib.rs index c36c34f..ca412c4 100644 --- a/node_core/src/lib.rs +++ b/node_core/src/lib.rs @@ -11,7 +11,9 @@ use chain_storage::NodeChainStore; use common::transaction::{Transaction, TransactionPayload, TxKind}; 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, generate_nullifiers, generate_nullifiers_se, pedersen_commitment_vec, +}; use sequencer_client::{json::SendTxResponse, SequencerClient}; use serde::{Deserialize, Serialize}; use storage::sc_db_utils::DataBlobChangeVariant; diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 05aac2b..ca07f6a 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -134,9 +134,9 @@ impl SequencerCore { let nullifier_tree_check = nullifier_created_hashes .iter() .map(|nullifier_hash| { - self.store - .nullifier_store - .contains(&UTXONullifier { utxo_hash: *nullifier_hash }) + self.store.nullifier_store.contains(&UTXONullifier { + utxo_hash: *nullifier_hash, + }) }) .any(|check| check); let utxo_commitments_check = utxo_commitments_created_hashes @@ -185,7 +185,7 @@ impl SequencerCore { tx: TransactionMempool, ) -> Result<(), TransactionMalformationErrorKind> { let Transaction { - // ToDo: remove hashing of transactions on node side [Issue #66] + // ToDo: remove hashing of transactions on node side [Issue #66] hash: _, ref utxo_commitments_created_hashes, ref nullifier_created_hashes, @@ -199,9 +199,9 @@ impl SequencerCore { } for nullifier in nullifier_created_hashes.iter() { - self.store - .nullifier_store - .insert(UTXONullifier{ utxo_hash: *nullifier}); + self.store.nullifier_store.insert(UTXONullifier { + utxo_hash: *nullifier, + }); } self.store.pub_tx_store.add_tx(tx.tx); diff --git a/sequencer_core/src/sequencer_store/mod.rs b/sequencer_core/src/sequencer_store/mod.rs index 5d28abd..322c99d 100644 --- a/sequencer_core/src/sequencer_store/mod.rs +++ b/sequencer_core/src/sequencer_store/mod.rs @@ -4,7 +4,8 @@ use accounts_store::SequencerAccountsStore; use block_store::SequecerBlockStore; use common::{ block::{Block, HashableBlockData}, - merkle_tree_public::merkle_tree::{PublicTransactionMerkleTree, UTXOCommitmentsMerkleTree}, nullifier::UTXONullifier, + merkle_tree_public::merkle_tree::{PublicTransactionMerkleTree, UTXOCommitmentsMerkleTree}, + nullifier::UTXONullifier, }; use rand::{rngs::OsRng, RngCore}; From 958e1dcb9c94b9a7a8c3f77a134c5b0a62fde037 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Fri, 23 May 2025 09:10:34 +0300 Subject: [PATCH 6/8] fix: tests fix --- sequencer_core/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index ca07f6a..7a083f1 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -332,7 +332,7 @@ mod tests { common_setup(&mut sequencer); let roots = sequencer.get_tree_roots(); - assert_eq!(roots.len(), 3); // Should return three roots + assert_eq!(roots.len(), 2); // Should return two roots } #[test] From 8d3ee363929db827dd89dbf7384718e13fa31e15 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Wed, 28 May 2025 08:23:54 +0300 Subject: [PATCH 7/8] fix: suggersion added 1 --- Cargo.lock | 68 ---------------------------------- Cargo.toml | 1 - common/Cargo.toml | 1 - node_core/Cargo.toml | 1 - sc_core/Cargo.toml | 1 - sc_core/src/proofs_circuits.rs | 2 - utxo/Cargo.toml | 1 - 7 files changed, 75 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b294ce1..6f663dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -764,17 +764,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "bls12_381" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc6d6292be3a19e6379786dac800f551e5865a5bb51ebbe3064ab80433f403" -dependencies = [ - "ff", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "bonsai-sdk" version = "1.4.0" @@ -1007,7 +996,6 @@ dependencies = [ "anyhow", "elliptic-curve", "hex", - "indexed-merkle-tree", "log", "reqwest 0.11.27", "risc0-zkvm", @@ -2366,23 +2354,6 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee796ad498c8d9a1d68e477df8f754ed784ef875de1414ebdaf169f70a6a784" -[[package]] -name = "indexed-merkle-tree" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86e7e0a70243eb602dba292003d26682c23cff528c5b3c06c002d242a26d865" -dependencies = [ - "anyhow", - "bls12_381", - "borsh", - "hex", - "num", - "num-bigint 0.4.6", - "num-traits", - "serde", - "sha2", -] - [[package]] name = "indexmap" version = "1.9.3" @@ -2956,7 +2927,6 @@ dependencies = [ "elliptic-curve", "env_logger", "hex", - "indexed-merkle-tree", "k256", "log", "rand 0.8.5", @@ -3037,20 +3007,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint 0.4.6", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - [[package]] name = "num-bigint" version = "0.3.3" @@ -3107,28 +3063,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint 0.4.6", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -4293,7 +4227,6 @@ dependencies = [ "elliptic-curve", "env_logger", "hex", - "indexed-merkle-tree", "k256", "light-poseidon", "log", @@ -5229,7 +5162,6 @@ dependencies = [ "common", "env_logger", "hex", - "indexed-merkle-tree", "log", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index edad918..7af2e24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,6 @@ tempfile = "3.14.0" light-poseidon = "0.3.0" ark-bn254 = "0.5.0" ark-ff = "0.5.0" -indexed-merkle-tree = "0.6.2" rocksdb = { version = "0.21.0", default-features = false, features = [ "snappy", diff --git a/common/Cargo.toml b/common/Cargo.toml index 4d2f52b..b692f5f 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -9,7 +9,6 @@ thiserror.workspace = true serde_json.workspace = true serde.workspace = true reqwest.workspace = true -indexed-merkle-tree.workspace = true risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-2.0" } rs_merkle.workspace = true diff --git a/node_core/Cargo.toml b/node_core/Cargo.toml index 2b59783..18120b2 100644 --- a/node_core/Cargo.toml +++ b/node_core/Cargo.toml @@ -12,7 +12,6 @@ serde.workspace = true rand.workspace = true k256.workspace = true sha2.workspace = true -indexed-merkle-tree.workspace = true bincode.workspace = true elliptic-curve.workspace = true reqwest.workspace = true diff --git a/sc_core/Cargo.toml b/sc_core/Cargo.toml index 4401ddb..e93c955 100644 --- a/sc_core/Cargo.toml +++ b/sc_core/Cargo.toml @@ -12,7 +12,6 @@ serde.workspace = true rand.workspace = true k256.workspace = true sha2.workspace = true -indexed-merkle-tree.workspace = true bincode.workspace = true elliptic-curve.workspace = true hex.workspace = true diff --git a/sc_core/src/proofs_circuits.rs b/sc_core/src/proofs_circuits.rs index d7c27d6..55e1e21 100644 --- a/sc_core/src/proofs_circuits.rs +++ b/sc_core/src/proofs_circuits.rs @@ -43,8 +43,6 @@ pub fn validate_in_commitments_proof( in_commitments_proof: &[Vec], ) -> bool { // Placeholder implementation. - // Replace with Merkle proof verification logic. - // hash(&[pedersen_commitment.serialize().to_vec(), in_commitments_proof.concat()].concat()) == root_commitment in_commitments_proof.contains(in_commitment) } diff --git a/utxo/Cargo.toml b/utxo/Cargo.toml index e7b35ef..0d97789 100644 --- a/utxo/Cargo.toml +++ b/utxo/Cargo.toml @@ -9,7 +9,6 @@ serde_json.workspace = true env_logger.workspace = true log.workspace = true serde.workspace = true -indexed-merkle-tree.workspace = true sha2.workspace = true hex.workspace = true From 9ad013253ab53c567e0ca6d264d1e3146f0fe98e Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Wed, 28 May 2025 20:32:43 +0300 Subject: [PATCH 8/8] fix: suggestions added 2 --- sc_core/src/proofs_circuits.rs | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/sc_core/src/proofs_circuits.rs b/sc_core/src/proofs_circuits.rs index 55e1e21..cbebe3e 100644 --- a/sc_core/src/proofs_circuits.rs +++ b/sc_core/src/proofs_circuits.rs @@ -38,25 +38,21 @@ pub fn generate_commitments(input_utxos: &[UTXO]) -> Vec> { // takes the in_commitments[i] as a leaf, the root hash root_commitment and the path in_commitments_proofs[i][], // returns True if the in_commitments[i] is in the tree with root hash root_commitment otherwise returns False, as membership proof. pub fn validate_in_commitments_proof( - in_commitment: &Vec, + _in_commitment: &Vec, _root_commitment: Vec, - in_commitments_proof: &[Vec], + _in_commitments_proof: &[Vec], ) -> bool { - // Placeholder implementation. + // ToDo: Implement correct check - in_commitments_proof.contains(in_commitment) + todo!() } -// Validate non-membership proof for nullifiers - -// takes the nullifiers[i], path nullifiers_proof[i][] and the root hash root_nullifier, -// returns True if the nullifiers[i] is not in the tree with root hash root_nullifier otherwise returns False, as non-membership proof. -pub fn validate_nullifiers_proof( +// Validate that `nullifier` has not been present in set items before +pub fn validate_nullifier_not_present_in_set_items( nullifier: [u8; 32], - _root_nullifier: [u8; 32], - nullifiers_proof: &[[u8; 32]], + nullifiers_items: &[[u8; 32]], ) -> bool { - !nullifiers_proof.contains(&nullifier) + !nullifiers_items.contains(&nullifier) } #[allow(unused)] @@ -84,9 +80,8 @@ fn private_kernel( } for nullifier in nullifiers.iter() { - validate_nullifiers_proof( + validate_nullifier_not_present_in_set_items( nullifier[0..32].try_into().unwrap(), - root_nullifier, nullifiers_proof, ); } @@ -203,9 +198,8 @@ fn de_kernel( } for nullifier in nullifiers.iter() { - validate_nullifiers_proof( + validate_nullifier_not_present_in_set_items( nullifier[0..32].try_into().unwrap(), - root_nullifier, nullifiers_proof, ); } @@ -220,11 +214,13 @@ fn de_kernel( // otherwise // returns False, as membership proof. pub fn validate_in_commitments_proof_se( - pedersen_commitment: &PedersenCommitment, + _pedersen_commitment: &PedersenCommitment, _root_commitment: Vec, - in_commitments_proof: &[Vec], + _in_commitments_proof: &[Vec], ) -> bool { - in_commitments_proof.contains(&pedersen_commitment.serialize().to_vec()) + // ToDo: Implement correct check + + todo!() } // Generate nullifiers SE