mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-07 15:53:14 +00:00
feat: indexed tree migration 1
This commit is contained in:
parent
00fe02c1d1
commit
00297db3ab
504
Cargo.lock
generated
504
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -36,7 +36,6 @@ lru = "0.7.8"
|
|||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
rs_merkle = "1.4"
|
rs_merkle = "1.4"
|
||||||
sha2 = "0.10.8"
|
sha2 = "0.10.8"
|
||||||
monotree = "0.1.5"
|
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
aes-gcm = "0.10.3"
|
aes-gcm = "0.10.3"
|
||||||
toml = "0.7.4"
|
toml = "0.7.4"
|
||||||
@ -46,6 +45,7 @@ tempfile = "3.14.0"
|
|||||||
light-poseidon = "0.3.0"
|
light-poseidon = "0.3.0"
|
||||||
ark-bn254 = "0.5.0"
|
ark-bn254 = "0.5.0"
|
||||||
ark-ff = "0.5.0"
|
ark-ff = "0.5.0"
|
||||||
|
indexed-merkle-tree = "0.6.2"
|
||||||
|
|
||||||
rocksdb = { version = "0.21.0", default-features = false, features = [
|
rocksdb = { version = "0.21.0", default-features = false, features = [
|
||||||
"snappy",
|
"snappy",
|
||||||
|
|||||||
@ -9,7 +9,7 @@ thiserror.workspace = true
|
|||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
reqwest.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" }
|
risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-2.0" }
|
||||||
|
|
||||||
rs_merkle.workspace = true
|
rs_merkle.workspace = true
|
||||||
|
|||||||
248
common/src/indexed_merkle_tree.rs
Normal file
248
common/src/indexed_merkle_tree.rs
Normal file
@ -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<u64, TreeBlockWithTxId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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<TreeHashType> {
|
||||||
|
//HELP
|
||||||
|
// self.tree.get_root().map(|node|
|
||||||
|
// serde_json::from_str::<Vec<[TreeHashType]>>(&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<TreeHashType>) -> 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<bool> {
|
||||||
|
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<NonMembershipProof> {
|
||||||
|
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<Vec<NonMembershipProof>> {
|
||||||
|
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());
|
||||||
|
// }
|
||||||
|
}
|
||||||
@ -3,10 +3,9 @@ use serde::Deserialize;
|
|||||||
|
|
||||||
pub mod block;
|
pub mod block;
|
||||||
pub mod commitment;
|
pub mod commitment;
|
||||||
pub mod commitments_sparse_merkle_tree;
|
pub mod indexed_merkle_tree;
|
||||||
pub mod merkle_tree_public;
|
pub mod merkle_tree_public;
|
||||||
pub mod nullifier;
|
pub mod nullifier;
|
||||||
pub mod nullifier_sparse_merkle_tree;
|
|
||||||
pub mod rpc_primitives;
|
pub mod rpc_primitives;
|
||||||
pub mod transaction;
|
pub mod transaction;
|
||||||
pub mod utxo_commitment;
|
pub mod utxo_commitment;
|
||||||
@ -67,8 +66,6 @@ pub enum ExecutionFailureKind {
|
|||||||
AmountMismatchError,
|
AmountMismatchError,
|
||||||
#[error("Sequencer client error: {0:?}")]
|
#[error("Sequencer client error: {0:?}")]
|
||||||
SequencerClientError(#[from] SequencerClientError),
|
SequencerClientError(#[from] SequencerClientError),
|
||||||
#[error("Datebase returned error : {0:?}")]
|
|
||||||
MonoTreeError(#[from] monotree::Errors),
|
|
||||||
#[error("Insufficient gas for operation")]
|
#[error("Insufficient gas for operation")]
|
||||||
InsufficientGasError,
|
InsufficientGasError,
|
||||||
#[error("Can not pay for operation")]
|
#[error("Can not pay for operation")]
|
||||||
|
|||||||
@ -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<u64, UTXONullifier>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct TreeBlockWithTxId {
|
|
||||||
pub id: u64,
|
|
||||||
pub txs: BTreeMap<u64, TreeTxWithNullifierId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct NullifierSparseMerkleTree {
|
|
||||||
pub curr_root: Option<TreeHashType>,
|
|
||||||
pub tree: Monotree<MemoryDB, Blake3>,
|
|
||||||
pub hasher: Blake3,
|
|
||||||
pub leafs: BTreeMap<u64, TreeBlockWithTxId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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<NullifierTreeInput>,
|
|
||||||
) -> Result<(), monotree::Errors> {
|
|
||||||
let root = self.curr_root.as_ref();
|
|
||||||
|
|
||||||
let hashes: Vec<TreeHashType> = 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<bool, monotree::Errors> {
|
|
||||||
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<Vec<bool>, 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<Proof>, Option<TreeHashType>), 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<Vec<(Option<Proof>, Option<TreeHashType>)>, 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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -12,7 +12,7 @@ serde.workspace = true
|
|||||||
rand.workspace = true
|
rand.workspace = true
|
||||||
k256.workspace = true
|
k256.workspace = true
|
||||||
sha2.workspace = true
|
sha2.workspace = true
|
||||||
monotree.workspace = true
|
indexed-merkle-tree.workspace = true
|
||||||
bincode.workspace = true
|
bincode.workspace = true
|
||||||
elliptic-curve.workspace = true
|
elliptic-curve.workspace = true
|
||||||
reqwest.workspace = true
|
reqwest.workspace = true
|
||||||
|
|||||||
@ -8,9 +8,9 @@ use anyhow::Result;
|
|||||||
use block_store::NodeBlockStore;
|
use block_store::NodeBlockStore;
|
||||||
use common::{
|
use common::{
|
||||||
block::Block,
|
block::Block,
|
||||||
|
indexed_merkle_tree::IndexedMerkleTreeWrapper,
|
||||||
merkle_tree_public::merkle_tree::{PublicTransactionMerkleTree, UTXOCommitmentsMerkleTree},
|
merkle_tree_public::merkle_tree::{PublicTransactionMerkleTree, UTXOCommitmentsMerkleTree},
|
||||||
nullifier::UTXONullifier,
|
nullifier::UTXONullifier,
|
||||||
nullifier_sparse_merkle_tree::{NullifierSparseMerkleTree, NullifierTreeInput},
|
|
||||||
utxo_commitment::UTXOCommitment,
|
utxo_commitment::UTXOCommitment,
|
||||||
};
|
};
|
||||||
use k256::AffinePoint;
|
use k256::AffinePoint;
|
||||||
@ -26,7 +26,7 @@ pub mod public_context;
|
|||||||
pub struct NodeChainStore {
|
pub struct NodeChainStore {
|
||||||
pub acc_map: HashMap<AccountAddress, Account>,
|
pub acc_map: HashMap<AccountAddress, Account>,
|
||||||
pub block_store: NodeBlockStore,
|
pub block_store: NodeBlockStore,
|
||||||
pub nullifier_store: NullifierSparseMerkleTree,
|
pub nullifier_store: IndexedMerkleTreeWrapper,
|
||||||
pub utxo_commitments_store: UTXOCommitmentsMerkleTree,
|
pub utxo_commitments_store: UTXOCommitmentsMerkleTree,
|
||||||
pub pub_tx_store: PublicTransactionMerkleTree,
|
pub pub_tx_store: PublicTransactionMerkleTree,
|
||||||
}
|
}
|
||||||
@ -34,7 +34,7 @@ pub struct NodeChainStore {
|
|||||||
impl NodeChainStore {
|
impl NodeChainStore {
|
||||||
pub fn new_with_genesis(home_dir: &Path, genesis_block: Block) -> Self {
|
pub fn new_with_genesis(home_dir: &Path, genesis_block: Block) -> Self {
|
||||||
let acc_map = HashMap::new();
|
let acc_map = HashMap::new();
|
||||||
let nullifier_store = NullifierSparseMerkleTree::default();
|
let nullifier_store = IndexedMerkleTreeWrapper::default();
|
||||||
let utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]);
|
let utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]);
|
||||||
let pub_tx_store = PublicTransactionMerkleTree::new(vec![]);
|
let pub_tx_store = PublicTransactionMerkleTree::new(vec![]);
|
||||||
|
|
||||||
@ -97,19 +97,8 @@ impl NodeChainStore {
|
|||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
|
|
||||||
self.nullifier_store.insert_items(
|
self.nullifier_store
|
||||||
tx.nullifier_created_hashes
|
.insert_items(tx.nullifier_created_hashes.clone())?;
|
||||||
.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(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if !tx.encoded_data.is_empty() {
|
if !tx.encoded_data.is_empty() {
|
||||||
let ephemeral_public_key_sender =
|
let ephemeral_public_key_sender =
|
||||||
@ -159,7 +148,7 @@ impl NodeChainStore {
|
|||||||
caller_address: caller,
|
caller_address: caller,
|
||||||
caller_balance: self.acc_map.get(&caller).unwrap().balance,
|
caller_balance: self.acc_map.get(&caller).unwrap().balance,
|
||||||
account_masks,
|
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]),
|
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]),
|
pub_tx_store_root: self.pub_tx_store.get_root().unwrap_or([0; 32]),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,10 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use bincode;
|
use bincode;
|
||||||
use common::nullifier_sparse_merkle_tree::NullifierTreeInput;
|
|
||||||
use common::{
|
use common::{
|
||||||
commitment::Commitment, commitments_sparse_merkle_tree::CommitmentsSparseMerkleTree,
|
commitment::Commitment, indexed_merkle_tree::IndexedMerkleTreeWrapper, nullifier::UTXONullifier,
|
||||||
nullifier::UTXONullifier, nullifier_sparse_merkle_tree::NullifierSparseMerkleTree,
|
|
||||||
};
|
};
|
||||||
use k256::Scalar;
|
use k256::Scalar;
|
||||||
use monotree::hasher::Blake3;
|
|
||||||
use monotree::{Hasher, Monotree};
|
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
use secp256k1_zkp::{CommitmentSecrets, Generator, PedersenCommitment, Tag, Tweak, SECP256K1};
|
use secp256k1_zkp::{CommitmentSecrets, Generator, PedersenCommitment, Tag, Tweak, SECP256K1};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
@ -80,24 +76,16 @@ pub fn validate_in_commitments_proof(
|
|||||||
// Replace with Merkle proof verification logic.
|
// Replace with Merkle proof verification logic.
|
||||||
// hash(&[pedersen_commitment.serialize().to_vec(), in_commitments_proof.concat()].concat()) == root_commitment
|
// hash(&[pedersen_commitment.serialize().to_vec(), in_commitments_proof.concat()].concat()) == root_commitment
|
||||||
|
|
||||||
let mut nsmt = CommitmentsSparseMerkleTree {
|
let mut nsmt = IndexedMerkleTreeWrapper::new();
|
||||||
curr_root: Option::Some(root_commitment),
|
|
||||||
tree: Monotree::default(),
|
|
||||||
hasher: Blake3::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let commitments: Vec<_> = in_commitments_proof
|
let commitments: Vec<_> = in_commitments_proof
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|n_p| Commitment {
|
.map(|n_p| n_p.clone().try_into().unwrap())
|
||||||
commitment_hash: n_p.clone(),
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
nsmt.insert_items(commitments).unwrap();
|
nsmt.insert_items(commitments).unwrap();
|
||||||
|
|
||||||
nsmt.get_non_membership_proof(in_commitment.clone())
|
nsmt.get_non_membership_proof(in_commitment.clone().try_into().unwrap())
|
||||||
.unwrap()
|
.is_ok()
|
||||||
.1
|
|
||||||
.is_some()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate non-membership proof for nullifiers
|
// Validate non-membership proof for nullifiers
|
||||||
@ -109,32 +97,16 @@ pub fn validate_nullifiers_proof(
|
|||||||
root_nullifier: [u8; 32],
|
root_nullifier: [u8; 32],
|
||||||
nullifiers_proof: &[[u8; 32]],
|
nullifiers_proof: &[[u8; 32]],
|
||||||
) -> bool {
|
) -> bool {
|
||||||
//There is no need for storage, so ids can be default there
|
let mut nsmt = IndexedMerkleTreeWrapper::new();
|
||||||
let id = 1;
|
|
||||||
|
|
||||||
let mut nsmt = NullifierSparseMerkleTree {
|
let commitments: Vec<_> = nullifiers_proof
|
||||||
curr_root: Option::Some(root_nullifier),
|
|
||||||
tree: Monotree::default(),
|
|
||||||
hasher: Blake3::new(),
|
|
||||||
leafs: BTreeMap::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let nullifiers: Vec<_> = nullifiers_proof
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.map(|n_p| n_p.clone().try_into().unwrap())
|
||||||
.map(|(idx, n_p)| NullifierTreeInput {
|
|
||||||
nullifier_id: idx as u64,
|
|
||||||
tx_id: id,
|
|
||||||
block_id: id,
|
|
||||||
nullifier: UTXONullifier { utxo_hash: *n_p },
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
nsmt.insert_items(nullifiers).unwrap();
|
nsmt.insert_items(commitments).unwrap();
|
||||||
|
|
||||||
nsmt.get_non_membership_proof(nullifier)
|
nsmt.get_non_membership_proof(nullifier.clone().try_into().unwrap())
|
||||||
.unwrap()
|
.is_ok()
|
||||||
.1
|
|
||||||
.is_none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check balances
|
// Check balances
|
||||||
|
|||||||
@ -1,14 +1,10 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use bincode;
|
use bincode;
|
||||||
use common::nullifier_sparse_merkle_tree::NullifierTreeInput;
|
|
||||||
use common::{
|
use common::{
|
||||||
commitment::Commitment, commitments_sparse_merkle_tree::CommitmentsSparseMerkleTree,
|
commitment::Commitment, indexed_merkle_tree::IndexedMerkleTreeWrapper, nullifier::UTXONullifier,
|
||||||
nullifier::UTXONullifier, nullifier_sparse_merkle_tree::NullifierSparseMerkleTree,
|
|
||||||
};
|
};
|
||||||
use k256::Scalar;
|
use k256::Scalar;
|
||||||
use monotree::hasher::Blake3;
|
|
||||||
use monotree::{Hasher, Monotree};
|
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
use utxo::utxo_core::UTXO;
|
use utxo::utxo_core::UTXO;
|
||||||
|
|
||||||
@ -53,24 +49,16 @@ pub fn validate_in_commitments_proof(
|
|||||||
// Replace with Merkle proof verification logic.
|
// Replace with Merkle proof verification logic.
|
||||||
// hash(&[pedersen_commitment.serialize().to_vec(), in_commitments_proof.concat()].concat()) == root_commitment
|
// hash(&[pedersen_commitment.serialize().to_vec(), in_commitments_proof.concat()].concat()) == root_commitment
|
||||||
|
|
||||||
let mut nsmt = CommitmentsSparseMerkleTree {
|
let mut nsmt = IndexedMerkleTreeWrapper::new();
|
||||||
curr_root: Option::Some(root_commitment),
|
|
||||||
tree: Monotree::default(),
|
|
||||||
hasher: Blake3::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let commitments: Vec<_> = in_commitments_proof
|
let commitments: Vec<_> = in_commitments_proof
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|n_p| Commitment {
|
.map(|n_p| n_p.clone().try_into().unwrap())
|
||||||
commitment_hash: n_p.clone(),
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
nsmt.insert_items(commitments).unwrap();
|
nsmt.insert_items(commitments).unwrap();
|
||||||
|
|
||||||
nsmt.get_non_membership_proof(in_commitment.clone())
|
nsmt.get_non_membership_proof(in_commitment.clone().try_into().unwrap())
|
||||||
.unwrap()
|
.is_ok()
|
||||||
.1
|
|
||||||
.is_some()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate non-membership proof for nullifiers
|
// Validate non-membership proof for nullifiers
|
||||||
@ -82,32 +70,16 @@ pub fn validate_nullifiers_proof(
|
|||||||
root_nullifier: [u8; 32],
|
root_nullifier: [u8; 32],
|
||||||
nullifiers_proof: &[[u8; 32]],
|
nullifiers_proof: &[[u8; 32]],
|
||||||
) -> bool {
|
) -> bool {
|
||||||
//There is no need for storage, so ids can be default there
|
let mut nsmt = IndexedMerkleTreeWrapper::new();
|
||||||
let id = 1;
|
|
||||||
|
|
||||||
let mut nsmt = NullifierSparseMerkleTree {
|
let commitments: Vec<_> = nullifiers_proof
|
||||||
curr_root: Option::Some(root_nullifier),
|
|
||||||
tree: Monotree::default(),
|
|
||||||
hasher: Blake3::new(),
|
|
||||||
leafs: BTreeMap::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let nullifiers: Vec<_> = nullifiers_proof
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.map(|n_p| n_p.clone().try_into().unwrap())
|
||||||
.map(|(idx, n_p)| NullifierTreeInput {
|
|
||||||
nullifier_id: idx as u64,
|
|
||||||
tx_id: id,
|
|
||||||
block_id: id,
|
|
||||||
nullifier: UTXONullifier { utxo_hash: *n_p },
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
nsmt.insert_items(nullifiers).unwrap();
|
nsmt.insert_items(commitments).unwrap();
|
||||||
|
|
||||||
nsmt.get_non_membership_proof(nullifier)
|
nsmt.get_non_membership_proof(nullifier.clone().try_into().unwrap())
|
||||||
.unwrap()
|
.is_ok()
|
||||||
.1
|
|
||||||
.is_none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
|||||||
@ -1,14 +1,10 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use bincode;
|
use bincode;
|
||||||
use common::nullifier_sparse_merkle_tree::NullifierTreeInput;
|
|
||||||
use common::{
|
use common::{
|
||||||
commitment::Commitment, commitments_sparse_merkle_tree::CommitmentsSparseMerkleTree,
|
commitment::Commitment, indexed_merkle_tree::IndexedMerkleTreeWrapper, nullifier::UTXONullifier,
|
||||||
nullifier::UTXONullifier, nullifier_sparse_merkle_tree::NullifierSparseMerkleTree,
|
|
||||||
};
|
};
|
||||||
use k256::Scalar;
|
use k256::Scalar;
|
||||||
use monotree::hasher::Blake3;
|
|
||||||
use monotree::{Hasher, Monotree};
|
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
use secp256k1_zkp::{CommitmentSecrets, Generator, PedersenCommitment, Tag, Tweak, SECP256K1};
|
use secp256k1_zkp::{CommitmentSecrets, Generator, PedersenCommitment, Tag, Tweak, SECP256K1};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
@ -80,24 +76,16 @@ pub fn validate_in_commitments_proof(
|
|||||||
root_commitment: Vec<u8>,
|
root_commitment: Vec<u8>,
|
||||||
in_commitments_proof: &[Vec<u8>],
|
in_commitments_proof: &[Vec<u8>],
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut nsmt = CommitmentsSparseMerkleTree {
|
let mut nsmt = IndexedMerkleTreeWrapper::new();
|
||||||
curr_root: Option::Some(root_commitment),
|
|
||||||
tree: Monotree::default(),
|
|
||||||
hasher: Blake3::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let commitments: Vec<_> = in_commitments_proof
|
let commitments: Vec<_> = in_commitments_proof
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|n_p| Commitment {
|
.map(|n_p| n_p.clone().try_into().unwrap())
|
||||||
commitment_hash: n_p.clone(),
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
nsmt.insert_items(commitments).unwrap();
|
nsmt.insert_items(commitments).unwrap();
|
||||||
|
|
||||||
nsmt.get_non_membership_proof(pedersen_commitment.serialize().to_vec())
|
nsmt.get_non_membership_proof(pedersen_commitment.serialize().to_vec().try_into().unwrap())
|
||||||
.unwrap()
|
.is_ok()
|
||||||
.1
|
|
||||||
.is_some()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate non-membership proof for nullifiers
|
// Validate non-membership proof for nullifiers
|
||||||
@ -111,32 +99,16 @@ pub fn validate_nullifiers_proof(
|
|||||||
root_nullifier: [u8; 32],
|
root_nullifier: [u8; 32],
|
||||||
nullifiers_proof: &[[u8; 32]],
|
nullifiers_proof: &[[u8; 32]],
|
||||||
) -> bool {
|
) -> bool {
|
||||||
//There is no need for storage, so ids can be default there
|
let mut nsmt = IndexedMerkleTreeWrapper::new();
|
||||||
let id = 1;
|
|
||||||
|
|
||||||
let mut nsmt = NullifierSparseMerkleTree {
|
let commitments: Vec<_> = nullifiers_proof
|
||||||
curr_root: Option::Some(root_nullifier),
|
|
||||||
tree: Monotree::default(),
|
|
||||||
hasher: Blake3::new(),
|
|
||||||
leafs: BTreeMap::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let nullifiers: Vec<_> = nullifiers_proof
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.map(|n_p| n_p.clone().try_into().unwrap())
|
||||||
.map(|(idx, n_p)| NullifierTreeInput {
|
|
||||||
nullifier_id: idx as u64,
|
|
||||||
tx_id: id,
|
|
||||||
block_id: id,
|
|
||||||
nullifier: UTXONullifier { utxo_hash: *n_p },
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
nsmt.insert_items(nullifiers).unwrap();
|
nsmt.insert_items(commitments).unwrap();
|
||||||
|
|
||||||
nsmt.get_non_membership_proof(nullifier)
|
nsmt.get_non_membership_proof(nullifier.clone().try_into().unwrap())
|
||||||
.unwrap()
|
.is_ok()
|
||||||
.1
|
|
||||||
.is_none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check balances
|
// Check balances
|
||||||
|
|||||||
@ -167,7 +167,7 @@ impl NodeCore {
|
|||||||
pub async fn get_roots(&self) -> [[u8; 32]; 3] {
|
pub async fn get_roots(&self) -> [[u8; 32]; 3] {
|
||||||
let storage = self.storage.read().await;
|
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.utxo_commitments_store.get_root().unwrap_or([0; 32]),
|
||||||
storage.pub_tx_store.get_root().unwrap_or([0; 32]),
|
storage.pub_tx_store.get_root().unwrap_or([0; 32]),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -81,6 +81,5 @@ pub fn cast_common_execution_error_into_rpc_error(comm_exec_err: ExecutionFailur
|
|||||||
ExecutionFailureKind::SequencerClientError(seq_cli_err) => {
|
ExecutionFailureKind::SequencerClientError(seq_cli_err) => {
|
||||||
cast_seq_client_error_into_rpc_error(seq_cli_err)
|
cast_seq_client_error_into_rpc_error(seq_cli_err)
|
||||||
}
|
}
|
||||||
ExecutionFailureKind::MonoTreeError(_) => RpcError::new_internal_error(None, &error_string),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ serde.workspace = true
|
|||||||
rand.workspace = true
|
rand.workspace = true
|
||||||
k256.workspace = true
|
k256.workspace = true
|
||||||
sha2.workspace = true
|
sha2.workspace = true
|
||||||
monotree.workspace = true
|
indexed-merkle-tree.workspace = true
|
||||||
bincode.workspace = true
|
bincode.workspace = true
|
||||||
elliptic-curve.workspace = true
|
elliptic-curve.workspace = true
|
||||||
hex.workspace = true
|
hex.workspace = true
|
||||||
|
|||||||
@ -1,14 +1,10 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use bincode;
|
use bincode;
|
||||||
use common::nullifier_sparse_merkle_tree::NullifierTreeInput;
|
|
||||||
use common::{
|
use common::{
|
||||||
commitment::Commitment, commitments_sparse_merkle_tree::CommitmentsSparseMerkleTree,
|
commitment::Commitment, indexed_merkle_tree::IndexedMerkleTreeWrapper, nullifier::UTXONullifier,
|
||||||
nullifier::UTXONullifier, nullifier_sparse_merkle_tree::NullifierSparseMerkleTree,
|
|
||||||
};
|
};
|
||||||
use k256::Scalar;
|
use k256::Scalar;
|
||||||
use monotree::hasher::Blake3;
|
|
||||||
use monotree::{Hasher, Monotree};
|
|
||||||
use rand::{thread_rng, RngCore};
|
use rand::{thread_rng, RngCore};
|
||||||
use secp256k1_zkp::{CommitmentSecrets, Generator, PedersenCommitment, Tag, Tweak, SECP256K1};
|
use secp256k1_zkp::{CommitmentSecrets, Generator, PedersenCommitment, Tag, Tweak, SECP256K1};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
@ -55,24 +51,16 @@ pub fn validate_in_commitments_proof(
|
|||||||
// Replace with Merkle proof verification logic.
|
// Replace with Merkle proof verification logic.
|
||||||
// hash(&[pedersen_commitment.serialize().to_vec(), in_commitments_proof.concat()].concat()) == root_commitment
|
// hash(&[pedersen_commitment.serialize().to_vec(), in_commitments_proof.concat()].concat()) == root_commitment
|
||||||
|
|
||||||
let mut nsmt = CommitmentsSparseMerkleTree {
|
let mut nsmt = IndexedMerkleTreeWrapper::new();
|
||||||
curr_root: Option::Some(root_commitment),
|
|
||||||
tree: Monotree::default(),
|
|
||||||
hasher: Blake3::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let commitments: Vec<_> = in_commitments_proof
|
let commitments: Vec<_> = in_commitments_proof
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|n_p| Commitment {
|
.map(|n_p| n_p.clone().try_into().unwrap())
|
||||||
commitment_hash: n_p.clone(),
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
nsmt.insert_items(commitments).unwrap();
|
nsmt.insert_items(commitments).unwrap();
|
||||||
|
|
||||||
nsmt.get_non_membership_proof(in_commitment.clone())
|
nsmt.get_non_membership_proof(in_commitment.clone().try_into().unwrap())
|
||||||
.unwrap()
|
.is_ok()
|
||||||
.1
|
|
||||||
.is_some()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate non-membership proof for nullifiers
|
// Validate non-membership proof for nullifiers
|
||||||
@ -84,32 +72,16 @@ pub fn validate_nullifiers_proof(
|
|||||||
root_nullifier: [u8; 32],
|
root_nullifier: [u8; 32],
|
||||||
nullifiers_proof: &[[u8; 32]],
|
nullifiers_proof: &[[u8; 32]],
|
||||||
) -> bool {
|
) -> bool {
|
||||||
//There is no need for storage, so ids can be default there
|
let mut nsmt = IndexedMerkleTreeWrapper::new();
|
||||||
let id = 1;
|
|
||||||
|
|
||||||
let mut nsmt = NullifierSparseMerkleTree {
|
let commitments: Vec<_> = nullifiers_proof
|
||||||
curr_root: Option::Some(root_nullifier),
|
|
||||||
tree: Monotree::default(),
|
|
||||||
hasher: Blake3::new(),
|
|
||||||
leafs: BTreeMap::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let nullifiers: Vec<_> = nullifiers_proof
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.map(|n_p| n_p.clone().try_into().unwrap())
|
||||||
.map(|(idx, n_p)| NullifierTreeInput {
|
|
||||||
nullifier_id: idx as u64,
|
|
||||||
tx_id: id,
|
|
||||||
block_id: id,
|
|
||||||
nullifier: UTXONullifier { utxo_hash: *n_p },
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
nsmt.insert_items(nullifiers).unwrap();
|
nsmt.insert_items(commitments).unwrap();
|
||||||
|
|
||||||
nsmt.get_non_membership_proof(nullifier)
|
nsmt.get_non_membership_proof(nullifier.clone().try_into().unwrap())
|
||||||
.unwrap()
|
.is_ok()
|
||||||
.1
|
|
||||||
.is_none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
@ -277,24 +249,16 @@ pub fn validate_in_commitments_proof_se(
|
|||||||
root_commitment: Vec<u8>,
|
root_commitment: Vec<u8>,
|
||||||
in_commitments_proof: &[Vec<u8>],
|
in_commitments_proof: &[Vec<u8>],
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut nsmt = CommitmentsSparseMerkleTree {
|
let mut nsmt = IndexedMerkleTreeWrapper::new();
|
||||||
curr_root: Option::Some(root_commitment),
|
|
||||||
tree: Monotree::default(),
|
|
||||||
hasher: Blake3::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let commitments: Vec<_> = in_commitments_proof
|
let commitments: Vec<_> = in_commitments_proof
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|n_p| Commitment {
|
.map(|n_p| n_p.clone().try_into().unwrap())
|
||||||
commitment_hash: n_p.clone(),
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
nsmt.insert_items(commitments).unwrap();
|
nsmt.insert_items(commitments).unwrap();
|
||||||
|
|
||||||
nsmt.get_non_membership_proof(pedersen_commitment.serialize().to_vec())
|
nsmt.get_non_membership_proof(pedersen_commitment.serialize().to_vec().try_into().unwrap())
|
||||||
.unwrap()
|
.is_ok()
|
||||||
.1
|
|
||||||
.is_some()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate nullifiers SE
|
// Generate nullifiers SE
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use common::{
|
|||||||
block::{Block, HashableBlockData},
|
block::{Block, HashableBlockData},
|
||||||
merkle_tree_public::TreeHashType,
|
merkle_tree_public::TreeHashType,
|
||||||
nullifier::UTXONullifier,
|
nullifier::UTXONullifier,
|
||||||
nullifier_sparse_merkle_tree::NullifierTreeInput,
|
|
||||||
transaction::{Transaction, TxKind},
|
transaction::{Transaction, TxKind},
|
||||||
utxo_commitment::UTXOCommitment,
|
utxo_commitment::UTXOCommitment,
|
||||||
};
|
};
|
||||||
@ -62,7 +61,10 @@ impl SequencerCore {
|
|||||||
|
|
||||||
pub fn get_tree_roots(&self) -> [[u8; 32]; 3] {
|
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
|
self.store
|
||||||
.utxo_commitments_store
|
.utxo_commitments_store
|
||||||
.get_root()
|
.get_root()
|
||||||
@ -139,7 +141,6 @@ impl SequencerCore {
|
|||||||
self.store
|
self.store
|
||||||
.nullifier_store
|
.nullifier_store
|
||||||
.search_item_inclusion(*nullifier_hash)
|
.search_item_inclusion(*nullifier_hash)
|
||||||
.unwrap_or(false)
|
|
||||||
})
|
})
|
||||||
.any(|check| check);
|
.any(|check| check);
|
||||||
let utxo_commitments_check = utxo_commitments_created_hashes
|
let utxo_commitments_check = utxo_commitments_created_hashes
|
||||||
@ -202,17 +203,10 @@ impl SequencerCore {
|
|||||||
.add_tx(UTXOCommitment { hash: *utxo_comm });
|
.add_tx(UTXOCommitment { hash: *utxo_comm });
|
||||||
}
|
}
|
||||||
|
|
||||||
for (idx, nullifier) in nullifier_created_hashes.iter().enumerate() {
|
for nullifier in nullifier_created_hashes.iter() {
|
||||||
self.store
|
self.store
|
||||||
.nullifier_store
|
.nullifier_store
|
||||||
.insert_item(NullifierTreeInput {
|
.insert_item(*nullifier)
|
||||||
nullifier_id: idx as u64,
|
|
||||||
tx_id,
|
|
||||||
block_id,
|
|
||||||
nullifier: UTXONullifier {
|
|
||||||
utxo_hash: *nullifier,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.map_err(|err| TransactionMalformationErrorKind::FailedToInsert {
|
.map_err(|err| TransactionMalformationErrorKind::FailedToInsert {
|
||||||
tx: hash,
|
tx: hash,
|
||||||
details: format!("{err:?}"),
|
details: format!("{err:?}"),
|
||||||
|
|||||||
@ -4,8 +4,8 @@ use accounts_store::SequencerAccountsStore;
|
|||||||
use block_store::SequecerBlockStore;
|
use block_store::SequecerBlockStore;
|
||||||
use common::{
|
use common::{
|
||||||
block::{Block, HashableBlockData},
|
block::{Block, HashableBlockData},
|
||||||
|
indexed_merkle_tree::IndexedMerkleTreeWrapper,
|
||||||
merkle_tree_public::merkle_tree::{PublicTransactionMerkleTree, UTXOCommitmentsMerkleTree},
|
merkle_tree_public::merkle_tree::{PublicTransactionMerkleTree, UTXOCommitmentsMerkleTree},
|
||||||
nullifier_sparse_merkle_tree::NullifierSparseMerkleTree,
|
|
||||||
};
|
};
|
||||||
use rand::{rngs::OsRng, RngCore};
|
use rand::{rngs::OsRng, RngCore};
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ pub mod block_store;
|
|||||||
pub struct SequecerChainStore {
|
pub struct SequecerChainStore {
|
||||||
pub acc_store: SequencerAccountsStore,
|
pub acc_store: SequencerAccountsStore,
|
||||||
pub block_store: SequecerBlockStore,
|
pub block_store: SequecerBlockStore,
|
||||||
pub nullifier_store: NullifierSparseMerkleTree,
|
pub nullifier_store: IndexedMerkleTreeWrapper,
|
||||||
pub utxo_commitments_store: UTXOCommitmentsMerkleTree,
|
pub utxo_commitments_store: UTXOCommitmentsMerkleTree,
|
||||||
pub pub_tx_store: PublicTransactionMerkleTree,
|
pub pub_tx_store: PublicTransactionMerkleTree,
|
||||||
}
|
}
|
||||||
@ -23,7 +23,7 @@ pub struct SequecerChainStore {
|
|||||||
impl SequecerChainStore {
|
impl SequecerChainStore {
|
||||||
pub fn new_with_genesis(home_dir: &Path, genesis_id: u64, is_genesis_random: bool) -> Self {
|
pub fn new_with_genesis(home_dir: &Path, genesis_id: u64, is_genesis_random: bool) -> Self {
|
||||||
let acc_store = SequencerAccountsStore::default();
|
let acc_store = SequencerAccountsStore::default();
|
||||||
let nullifier_store = NullifierSparseMerkleTree::default();
|
let nullifier_store = IndexedMerkleTreeWrapper::default();
|
||||||
let utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]);
|
let utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]);
|
||||||
let pub_tx_store = PublicTransactionMerkleTree::new(vec![]);
|
let pub_tx_store = PublicTransactionMerkleTree::new(vec![]);
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ serde_json.workspace = true
|
|||||||
env_logger.workspace = true
|
env_logger.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
monotree.workspace = true
|
indexed-merkle-tree.workspace = true
|
||||||
sha2.workspace = true
|
sha2.workspace = true
|
||||||
hex.workspace = true
|
hex.workspace = true
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user