mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-02 21:33:09 +00:00
fix: smt/imt replaced with sets
This commit is contained in:
parent
00297db3ab
commit
cb22a95df2
@ -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<CommitmentHashType>,
|
||||
pub tree: Monotree<MemoryDB, Blake3>,
|
||||
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<Commitment>) -> 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::<Vec<_>>();
|
||||
|
||||
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<bool, monotree::Errors> {
|
||||
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<Vec<bool>, 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<Proof>, Option<CommitmentHashType>), 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<Vec<(Option<Proof>, Option<CommitmentHashType>)>, 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());
|
||||
}
|
||||
}
|
||||
@ -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<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,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;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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)]
|
||||
|
||||
@ -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<AccountAddress, Account>,
|
||||
pub block_store: NodeBlockStore,
|
||||
pub nullifier_store: IndexedMerkleTreeWrapper,
|
||||
pub nullifier_store: HashSet<UTXONullifier>,
|
||||
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::<ActionData>(&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]),
|
||||
}
|
||||
|
||||
@ -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<AccountAddress, AccountPublicMask>,
|
||||
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,
|
||||
}
|
||||
|
||||
@ -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<u8> {
|
||||
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<u8> {
|
||||
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<Vec<u8>> {
|
||||
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<u8>,
|
||||
root_commitment: Vec<u8>,
|
||||
in_commitments_proof: &[Vec<u8>],
|
||||
) -> 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<u64>,
|
||||
secret_r: &[u8],
|
||||
) -> (Tweak, &[u8], Vec<PedersenCommitment>) {
|
||||
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<u8>],
|
||||
nullifiers_proof: &[[u8; 32]],
|
||||
nullifier_secret_key: Scalar,
|
||||
) -> (Vec<u8>, Vec<Vec<u8>>) {
|
||||
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)
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
pub mod de;
|
||||
pub mod private_exec;
|
||||
pub mod se;
|
||||
@ -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<u8> {
|
||||
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<u8> {
|
||||
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<Vec<u8>> {
|
||||
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<u8>,
|
||||
root_commitment: Vec<u8>,
|
||||
in_commitments_proof: &[Vec<u8>],
|
||||
) -> 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<u8>],
|
||||
nullifiers_proof: &[[u8; 32]],
|
||||
nullifier_secret_key: Scalar,
|
||||
) -> (Vec<u8>, Vec<Vec<u8>>) {
|
||||
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)
|
||||
}
|
||||
@ -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<u8> {
|
||||
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<u8> {
|
||||
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<Vec<u8>> {
|
||||
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<u8>,
|
||||
in_commitments_proof: &[Vec<u8>],
|
||||
) -> 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<u8>],
|
||||
nullifiers_proof: &[[u8; 32]],
|
||||
nullifier_secret_key: Scalar,
|
||||
) -> (Vec<u8>, Vec<Vec<u8>>, Vec<u8>) {
|
||||
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)
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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<SendTxResponse, SequencerClientError> {
|
||||
let tx_req = SendTxRequest {
|
||||
transaction,
|
||||
|
||||
@ -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<Vec<u8>> {
|
||||
// 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<u8>,
|
||||
root_commitment: Vec<u8>,
|
||||
_root_commitment: Vec<u8>,
|
||||
in_commitments_proof: &[Vec<u8>],
|
||||
) -> 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<u8>,
|
||||
_root_commitment: Vec<u8>,
|
||||
in_commitments_proof: &[Vec<u8>],
|
||||
) -> 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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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<UTXONullifier>,
|
||||
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![]);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user