diff --git a/cl/cl/Cargo.toml b/cl/cl/Cargo.toml index 30ee678..500bbe3 100644 --- a/cl/cl/Cargo.toml +++ b/cl/cl/Cargo.toml @@ -12,9 +12,9 @@ risc0-groth16 = "1.0.1" blake2 = "0.10.6" # jubjub = "0.10.0" group = "0.13.0" +rand = "0.8.5" rand_core = "0.6.0" -rand_chacha = "0.3.1" lazy_static = "1.4.0" hex = "0.4.3" curve25519-dalek = {version = "4.1", features = ["serde", "digest", "rand_core"]} -sha2 = "0.10" \ No newline at end of file +sha2 = "0.10" diff --git a/cl/cl/src/balance.rs b/cl/cl/src/balance.rs index 91f185a..01fb26a 100644 --- a/cl/cl/src/balance.rs +++ b/cl/cl/src/balance.rs @@ -149,8 +149,6 @@ pub fn balance(value: u64, unit: RistrettoPoint, blinding: Scalar) -> RistrettoP mod test { use super::*; - use crate::test_util::seed_rng; - use k256::elliptic_curve::group::prime::PrimeCurveAffine; #[test] fn test_pederson_blinding_point_pre_compute() { @@ -166,8 +164,8 @@ mod test { #[test] fn test_balance_zero_unitless() { // Zero is the same across all units - let rng = seed_rng(0); - let r = Scalar::random(rng); + let mut rng = rand::thread_rng(); + let r = Scalar::random(&mut rng); assert_eq!( BalanceWitness::new(0, "NMO", r).commit(), BalanceWitness::new(0, "ETH", r).commit(), @@ -184,10 +182,7 @@ mod test { let a = a_w.commit(); let b = b_w.commit(); assert_ne!(a, b); - assert_eq!( - a.0.to_curve() - b.0.to_curve(), - BalanceWitness::new(0, "NMO", r1 - r2).commit().0.to_curve() - ); + assert_eq!(a.0 - b.0, BalanceWitness::new(0, "NMO", r1 - r2).commit().0); } #[test] @@ -201,7 +196,7 @@ mod test { #[test] fn test_balance_homomorphism() { - let mut rng = seed_rng(0); + let mut rng = rand::thread_rng(); let r1 = Scalar::random(&mut rng); let r2 = Scalar::random(&mut rng); let ten = BalanceWitness::new(10, "NMO", 0u32.into()); @@ -209,16 +204,13 @@ mod test { let two = BalanceWitness::new(2, "NMO", 0u32.into()); // Values of same unit are homomorphic - assert_eq!( - ten.commit().0.to_curve() - eight.commit().0.to_curve(), - two.commit().0.to_curve() - ); + assert_eq!(ten.commit().0 - eight.commit().0, two.commit().0); // Blinding factors are also homomorphic. assert_eq!( - BalanceWitness::new(10, "NMO", r1).commit().0.to_curve() - - BalanceWitness::new(10, "NMO", r2).commit().0.to_curve(), - BalanceWitness::new(0, "NMO", r1 - r2).commit().0.to_curve() + BalanceWitness::new(10, "NMO", r1).commit().0 + - BalanceWitness::new(10, "NMO", r2).commit().0, + BalanceWitness::new(0, "NMO", r1 - r2).commit().0 ); } } diff --git a/cl/cl/src/bundle.rs b/cl/cl/src/bundle.rs index bfb0030..2196c3b 100644 --- a/cl/cl/src/bundle.rs +++ b/cl/cl/src/bundle.rs @@ -87,14 +87,14 @@ impl Bundle { mod test { use crate::{ crypto::hash_to_curve, input::InputWitness, note::NoteWitness, nullifier::NullifierSecret, - output::OutputWitness, partial_tx::PartialTxWitness, test_util::seed_rng, + output::OutputWitness, partial_tx::PartialTxWitness, }; use super::*; #[test] fn test_bundle_balance() { - let mut rng = seed_rng(0); + let mut rng = rand::thread_rng(); let nmo_10_in = InputWitness::random(NoteWitness::new(10, "NMO", [0u8; 32], &mut rng), &mut rng); @@ -169,7 +169,11 @@ mod test { assert_eq!( bundle.balance(), - crate::balance::balance(0, RistrettoPoint::GENERATOR, witness.balance_blinding) + crate::balance::balance( + 0, + curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT, + witness.balance_blinding + ) ); assert!(bundle.is_balanced(witness.balance_blinding)); diff --git a/cl/cl/src/input.rs b/cl/cl/src/input.rs index 132085c..7feba93 100644 --- a/cl/cl/src/input.rs +++ b/cl/cl/src/input.rs @@ -52,57 +52,6 @@ impl InputWitness { } impl Input { - // pub fn prove( - // &self, - // w: &InputWitness, - // ptx_root: PtxRoot, - // death_proof: Vec, - // ) -> Result { - // if bincode::serialize(&w.commit()).unwrap() != bincode::serialize(&self).unwrap() { - // Err(Error::ProofFailed) - // } else { - // Ok(InputProof { - // input: w.clone(), - // ptx_root, - // death_proof, - // }) - // } - // } - - // pub fn verify(&self, ptx_root: PtxRoot, proof: &InputProof) -> bool { - // // verification checks the relation - // // - nf_pk == hash(nf_sk) - // // - note_comm == commit(note || nf_pk) - // // - nullifier == hash(nf_sk || nonce) - // // - balance == v * hash_to_curve(Unit) + blinding * H - // // - ptx_root is the same one that was used in proving. - - // let witness = &proof.input; - - // let nf_pk = witness.nf_sk.commit(); - - // // let death_constraint_was_committed_to = - // // witness.note.death_constraint == bincode::serialize(&death_constraint).unwrap(); - - // // let death_constraint_is_satisfied: bool = Verifier::from_json( - // // bincode::deserialize(&proof.death_proof).unwrap(), - // // PublicInputsJson { - // // values: vec![ptx_root.hex()], - // // }, - // // bincode::deserialize(&witness.note.death_constraint).unwrap(), - // // ) - // // .unwrap() - // // .verify() - // // .is_ok(); - // let death_constraint_is_satisfied = true; - // self.note_comm == witness.note.commit(nf_pk, witness.nonce) - // && self.nullifier == Nullifier::new(witness.nf_sk, witness.nonce) - // && self.balance == witness.note.balance() - // && ptx_root == proof.ptx_root - // // && death_constraint_was_committed_to - // && death_constraint_is_satisfied - // } - pub fn to_bytes(&self) -> [u8; 96] { let mut bytes = [0u8; 96]; bytes[..32].copy_from_slice(self.note_comm.as_bytes()); @@ -111,76 +60,3 @@ impl Input { bytes } } - -#[cfg(test)] -mod test { - use super::*; - use crate::{nullifier::NullifierNonce, test_util::seed_rng}; - - #[test] - fn test_input_proof() { - let mut rng = seed_rng(0); - - let ptx_root = PtxRoot::default(); - - let note = NoteWitness::new(10, "NMO", [0u8; 32], &mut rng); - let nf_sk = NullifierSecret::random(&mut rng); - let nonce = NullifierNonce::random(&mut rng); - - let input_witness = InputWitness { note, nf_sk, nonce }; - - let input = input_witness.commit(); - let proof = input.prove(&input_witness, ptx_root, vec![]).unwrap(); - - assert!(input.verify(ptx_root, &proof)); - - let wrong_witnesses = [ - InputWitness { - note: NoteWitness::new(11, "NMO", [0u8; 32], &mut rng), - ..input_witness.clone() - }, - InputWitness { - note: NoteWitness::new(10, "ETH", [0u8; 32], &mut rng), - ..input_witness.clone() - }, - InputWitness { - nf_sk: NullifierSecret::random(&mut rng), - ..input_witness.clone() - }, - InputWitness { - nonce: NullifierNonce::random(&mut rng), - ..input_witness.clone() - }, - ]; - - for wrong_witness in wrong_witnesses { - assert!(input.prove(&wrong_witness, ptx_root, vec![]).is_err()); - - let wrong_input = wrong_witness.commit(); - let wrong_proof = wrong_input.prove(&wrong_witness, ptx_root, vec![]).unwrap(); - assert!(!input.verify(ptx_root, &wrong_proof)); - } - } - - #[test] - fn test_input_ptx_coupling() { - let mut rng = seed_rng(0); - - let note = NoteWitness::new(10, "NMO", [0u8; 32], &mut rng); - let nf_sk = NullifierSecret::random(&mut rng); - let nonce = NullifierNonce::random(&mut rng); - - let witness = InputWitness { note, nf_sk, nonce }; - - let input = witness.commit(); - - let ptx_root = PtxRoot::random(&mut rng); - let proof = input.prove(&witness, ptx_root, vec![]).unwrap(); - - assert!(input.verify(ptx_root, &proof)); - - // The same input proof can not be used in another partial transaction. - let another_ptx_root = PtxRoot::random(&mut rng); - assert!(!input.verify(another_ptx_root, &proof)); - } -} diff --git a/cl/cl/src/lib.rs b/cl/cl/src/lib.rs index c50b763..0ab85c9 100644 --- a/cl/cl/src/lib.rs +++ b/cl/cl/src/lib.rs @@ -16,6 +16,3 @@ pub use note::{NoteCommitment, NoteWitness}; pub use nullifier::{Nullifier, NullifierCommitment, NullifierNonce, NullifierSecret}; pub use output::{Output, OutputWitness}; pub use partial_tx::{PartialTx, PartialTxWitness, PtxRoot}; - -#[cfg(test)] -mod test_util; diff --git a/cl/cl/src/merkle.rs b/cl/cl/src/merkle.rs index a51ae1d..bb10e3c 100644 --- a/cl/cl/src/merkle.rs +++ b/cl/cl/src/merkle.rs @@ -204,7 +204,7 @@ mod test { PathNode::Right(node(leaf(b"feels"), leaf(b"warm"))), ]; assert_eq!(p0, expected0); - assert!(path_root(leaf(b"desert"), &p0), r); + assert_eq!(path_root(leaf(b"desert"), &p0), r); // --- proof for element at idx 1 diff --git a/cl/cl/src/note.rs b/cl/cl/src/note.rs index ea8c8f8..a819f7f 100644 --- a/cl/cl/src/note.rs +++ b/cl/cl/src/note.rs @@ -1,6 +1,6 @@ -use sha2::{Digest, Sha256}; use rand_core::CryptoRngCore; use serde::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; use crate::{ balance::{Balance, BalanceWitness}, @@ -69,13 +69,13 @@ impl NoteWitness { #[cfg(test)] mod test { - use crate::{nullifier::NullifierSecret, test_util::seed_rng}; + use crate::nullifier::NullifierSecret; use super::*; #[test] fn test_note_commitments_dont_commit_to_balance_blinding() { - let mut rng = seed_rng(0); + let mut rng = rand::thread_rng(); let n1 = NoteWitness::new(12, "NMO", [0u8; 32], &mut rng); let n2 = NoteWitness::new(12, "NMO", [0u8; 32], &mut rng); diff --git a/cl/cl/src/nullifier.rs b/cl/cl/src/nullifier.rs index a54c3bf..76c3b06 100644 --- a/cl/cl/src/nullifier.rs +++ b/cl/cl/src/nullifier.rs @@ -94,7 +94,6 @@ impl Nullifier { #[cfg(test)] mod test { use super::*; - use crate::test_util::seed_rng; #[test] fn test_nullifier_commitment_vectors() { @@ -114,9 +113,10 @@ mod test { #[test] fn test_nullifier_same_sk_different_nonce() { - let sk = NullifierSecret::random(seed_rng(0)); - let nonce_1 = NullifierNonce::random(seed_rng(1)); - let nonce_2 = NullifierNonce::random(seed_rng(2)); + let mut rng = rand::thread_rng(); + let sk = NullifierSecret::random(&mut rng); + let nonce_1 = NullifierNonce::random(&mut rng); + let nonce_2 = NullifierNonce::random(&mut rng); let nf_1 = Nullifier::new(sk, nonce_1); let nf_2 = Nullifier::new(sk, nonce_2); diff --git a/cl/cl/src/output.rs b/cl/cl/src/output.rs index be05249..f7e2391 100644 --- a/cl/cl/src/output.rs +++ b/cl/cl/src/output.rs @@ -76,11 +76,11 @@ impl Output { #[cfg(test)] mod test { use super::*; - use crate::{nullifier::NullifierSecret, test_util::seed_rng}; + use crate::nullifier::NullifierSecret; #[test] fn test_output_proof() { - let mut rng = seed_rng(0); + let mut rng = rand::thread_rng(); let note = NoteWitness::new(10, "NMO", [0u8; 32], &mut rng); let nf_pk = NullifierSecret::random(&mut rng).commit(); diff --git a/cl/cl/src/partial_tx.rs b/cl/cl/src/partial_tx.rs index 61e5e06..0aa041a 100644 --- a/cl/cl/src/partial_tx.rs +++ b/cl/cl/src/partial_tx.rs @@ -96,64 +96,6 @@ impl PartialTx { PtxRoot(root) } - // pub fn prove( - // &self, - // w: PartialTxWitness, - // death_proofs: Vec>, - // ) -> Result { - // if bincode::serialize(&Self::from_witness(w.clone())).unwrap() - // != bincode::serialize(&self).unwrap() - // { - // return Err(Error::ProofFailed); - // } - // let input_note_comms = BTreeSet::from_iter(self.inputs.iter().map(|i| i.note_comm)); - // let output_note_comms = BTreeSet::from_iter(self.outputs.iter().map(|o| o.note_comm)); - - // if input_note_comms.len() != self.inputs.len() - // || output_note_comms.len() != self.outputs.len() - // { - // return Err(Error::ProofFailed); - // } - - // let ptx_root = self.root(); - - // let input_proofs: Vec = Result::from_iter( - // self.inputs - // .iter() - // .zip(&w.inputs) - // .zip(death_proofs.into_iter()) - // .map(|((i, i_w), death_p)| i.prove(i_w, ptx_root, death_p)), - // )?; - - // let output_proofs: Vec = Result::from_iter( - // self.outputs - // .iter() - // .zip(&w.outputs) - // .map(|(o, o_w)| o.prove(o_w)), - // )?; - - // Ok(PartialTxProof { - // inputs: input_proofs, - // outputs: output_proofs, - // }) - // } - - // pub fn verify(&self, proof: &PartialTxProof) -> bool { - // let ptx_root = self.root(); - // self.inputs.len() == proof.inputs.len() - // && self.outputs.len() == proof.outputs.len() - // && self - // .inputs - // .iter() - // .zip(&proof.inputs) - // .all(|(i, p)| i.verify(ptx_root, p)) - // && self - // .outputs - // .iter() - // .zip(&proof.outputs) - // .all(|(o, p)| o.verify(p)) - // } - pub fn balance(&self) -> RistrettoPoint { let in_sum: RistrettoPoint = self.inputs.iter().map(|i| i.balance.0).sum(); let out_sum: RistrettoPoint = self.outputs.iter().map(|o| o.balance.0).sum(); @@ -165,41 +107,39 @@ impl PartialTx { #[cfg(test)] mod test { - use crate::{ - crypto::hash_to_curve, note::NoteWitness, nullifier::NullifierSecret, test_util::seed_rng, - }; + use crate::{crypto::hash_to_curve, note::NoteWitness, nullifier::NullifierSecret}; use super::*; - #[test] - fn test_partial_tx_proof() { - let mut rng = seed_rng(0); + // #[test] + // fn test_partial_tx_proof() { + // let mut rng = rand::thread_rng(); - let nmo_10 = - InputWitness::random(NoteWitness::new(10, "NMO", [0u8; 32], &mut rng), &mut rng); - let eth_23 = - InputWitness::random(NoteWitness::new(23, "ETH", [0u8; 32], &mut rng), &mut rng); - let crv_4840 = OutputWitness::random( - NoteWitness::new(4840, "CRV", [0u8; 32], &mut rng), - NullifierSecret::random(&mut rng).commit(), // transferring to a random owner - &mut rng, - ); + // let nmo_10 = + // InputWitness::random(NoteWitness::new(10, "NMO", [0u8; 32], &mut rng), &mut rng); + // let eth_23 = + // InputWitness::random(NoteWitness::new(23, "ETH", [0u8; 32], &mut rng), &mut rng); + // let crv_4840 = OutputWitness::random( + // NoteWitness::new(4840, "CRV", [0u8; 32], &mut rng), + // NullifierSecret::random(&mut rng).commit(), // transferring to a random owner + // &mut rng, + // ); - let ptx_witness = PartialTxWitness { - inputs: vec![nmo_10, eth_23], - outputs: vec![crv_4840], - }; + // let ptx_witness = PartialTxWitness { + // inputs: vec![nmo_10, eth_23], + // outputs: vec![crv_4840], + // }; - let ptx = PartialTx::from_witness(ptx_witness.clone()); + // let ptx = PartialTx::from_witness(ptx_witness.clone()); - let ptx_proof = ptx.prove(ptx_witness, vec![vec![], vec![]]).unwrap(); + // let ptx_proof = ptx.prove(ptx_witness, vec![vec![], vec![]]).unwrap(); - assert!(ptx.verify(&ptx_proof)); - } + // assert!(ptx.verify(&ptx_proof)); + // } #[test] fn test_partial_tx_balance() { - let mut rng = seed_rng(0); + let mut rng = rand::thread_rng(); let nmo_10 = InputWitness::random(NoteWitness::new(10, "NMO", [0u8; 32], &mut rng), &mut rng); diff --git a/cl/cl/src/test_util.rs b/cl/cl/src/test_util.rs deleted file mode 100644 index e542e76..0000000 --- a/cl/cl/src/test_util.rs +++ /dev/null @@ -1,7 +0,0 @@ -use rand_core::SeedableRng; - -pub fn seed_rng(seed: u64) -> impl rand_core::RngCore { - let mut bytes = [0u8; 32]; - bytes[..8].copy_from_slice(&seed.to_le_bytes()); - rand_chacha::ChaCha12Rng::from_seed(bytes) -} diff --git a/cl/ledger/src/input.rs b/cl/ledger/src/input.rs index d4533f7..f11cadf 100644 --- a/cl/ledger/src/input.rs +++ b/cl/ledger/src/input.rs @@ -122,4 +122,71 @@ mod test { assert!(!proof.verify(wrong_public_inputs)); } + + #[test] + fn test_input_proof() { + let mut rng = rand::thread_rng(); + + let ptx_root = PtxRoot::default(); + + let note = NoteWitness::new(10, "NMO", [0u8; 32], &mut rng); + let nf_sk = NullifierSecret::random(&mut rng); + let nonce = NullifierNonce::random(&mut rng); + + let input_witness = InputWitness { note, nf_sk, nonce }; + + let input = input_witness.commit(); + let proof = input.prove(&input_witness, ptx_root, vec![]).unwrap(); + + assert!(input.verify(ptx_root, &proof)); + + let wrong_witnesses = [ + InputWitness { + note: NoteWitness::new(11, "NMO", [0u8; 32], &mut rng), + ..input_witness.clone() + }, + InputWitness { + note: NoteWitness::new(10, "ETH", [0u8; 32], &mut rng), + ..input_witness.clone() + }, + InputWitness { + nf_sk: NullifierSecret::random(&mut rng), + ..input_witness.clone() + }, + InputWitness { + nonce: NullifierNonce::random(&mut rng), + ..input_witness.clone() + }, + ]; + + for wrong_witness in wrong_witnesses { + assert!(input.prove(&wrong_witness, ptx_root, vec![]).is_err()); + + let wrong_input = wrong_witness.commit(); + let wrong_proof = wrong_input.prove(&wrong_witness, ptx_root, vec![]).unwrap(); + assert!(!input.verify(ptx_root, &wrong_proof)); + } + } + + #[test] + fn test_input_ptx_coupling() { + let mut rng = seed_rng(0); + + let note = NoteWitness::new(10, "NMO", [0u8; 32], &mut rng); + let nf_sk = NullifierSecret::random(&mut rng); + let nonce = NullifierNonce::random(&mut rng); + + let witness = InputWitness { note, nf_sk, nonce }; + + let input = witness.commit(); + + let ptx_root = PtxRoot::random(&mut rng); + let proof = input.prove(&witness, ptx_root, vec![]).unwrap(); + + assert!(input.verify(ptx_root, &proof)); + + // The same input proof can not be used in another partial transaction. + let another_ptx_root = PtxRoot::random(&mut rng); + assert!(!input.verify(another_ptx_root, &proof)); + } }