use k256::Scalar; use secp256k1_zkp::{compute_adaptive_blinding_factor, verify_commitments_sum_to_equal, CommitmentSecrets, Generator, PedersenCommitment, Tag, Tweak, SECP256K1}; use rand::thread_rng; use sha2::{Digest, Sha256}; use serde::{Serialize, Deserialize}; use storage::{commitment::Commitment, commitments_sparse_merkle_tree::CommitmentsSparseMerkleTree, nullifier::UTXONullifier, nullifier_sparse_merkle_tree::NullifierSparseMerkleTree}; use utxo::{ utxo_core::{UTXOPayload, UTXO}, utxo_tree::UTXOSparseMerkleTree, }; use monotree::hasher::Blake3; use monotree::{Hasher, Monotree, Proof}; use bincode; 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) } // Hash function placeholder (replace with your cryptographic library's hash). fn hash(input: &[u8]) -> Vec { Sha256::digest(input).to_vec() } // Generate nullifiers // takes the pedersen_commitment and nsk then // returns a list of nullifiers, where the nullifier = hash(pedersen_commitment || nsk) where the hash function will be determined pub fn generate_nullifiers(pedersen_commitment: &PedersenCommitment, nsk: &[u8]) -> Vec { let mut input = pedersen_commitment.serialize().to_vec(); input.extend_from_slice(nsk); hash(&input) } // Generate commitments for output UTXOs // uses the list of output_utxos[] and // returns out_commitments[] where each out_commitments[i] = Commitment(output_utxos[i]) // where the commitment will be determined pub fn generate_commitments(output_utxos: &[UTXO]) -> Vec> { output_utxos .iter() .map(|utxo| { let serialized = bincode::serialize(utxo).unwrap(); // Serialize UTXO. hash(&serialized) }) .collect() } // Validate inclusion proof for in_commitments // takes the pedersen_commitment as a leaf, the root hash root_commitment and the path in_commitments_proof[], // returns True if the pedersen_commitment is in the tree with root hash root_commitment // otherwise // returns False, as membership proof. pub fn validate_in_commitments_proof( pedersen_commitment: &PedersenCommitment, root_commitment: Vec, in_commitments_proof: &[Vec], ) -> bool { let mut nsmt = CommitmentsSparseMerkleTree { curr_root: Option::Some(root_commitment), tree: Monotree::default(), hasher: Blake3::new(), }; let commitments: Vec<_> = in_commitments_proof.into_iter().map(|n_p| Commitment { commitment_hash: n_p.clone() }).collect(); nsmt.insert_items(commitments).unwrap(); nsmt.get_non_membership_proof(pedersen_commitment.serialize().to_vec()).unwrap().1.is_some() } // 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 = NullifierSparseMerkleTree { curr_root: Option::Some(root_nullifier), tree: Monotree::default(), hasher: Blake3::new(), }; let nullifiers: Vec<_> = nullifiers_proof.into_iter().map(|n_p| UTXONullifier { utxo_hash: *n_p }).collect(); nsmt.insert_items(nullifiers).unwrap(); nsmt.get_non_membership_proof(nullifier).unwrap().1.is_none() }