diff --git a/src/circuit/mod.rs b/src/circuit/mod.rs index def6d9e..a81d6c7 100644 --- a/src/circuit/mod.rs +++ b/src/circuit/mod.rs @@ -23,6 +23,7 @@ use bellman::{ use jubjub::{ JubjubEngine, Unknown, + PrimeOrder, FixedGenerators, edwards }; @@ -329,9 +330,9 @@ pub struct Output<'a, E: JubjubEngine> { /// Randomness that will hide the value pub value_randomness: Option, /// The diversified base, computed by GH(d) - pub g_d: Option>, + pub g_d: Option>, /// The diversified address point, computed by GH(d)^ivk - pub p_d: Option>, + pub pk_d: Option>, /// The randomness used to hide the note commitment data pub commitment_randomness: Option, /// The ephemeral secret key for DH with recipient @@ -413,20 +414,20 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { epk.inputize(cs.namespace(|| "epk"))?; } - // Now let's deal with p_d. We don't do any checks and + // Now let's deal with pk_d. We don't do any checks and // essentially allow the prover to witness any 256 bits // they would like. { - let p_d = self.p_d.map(|e| e.into_xy()); + let pk_d = self.pk_d.map(|e| e.into_xy()); let y_contents = boolean::field_into_boolean_vec_le( - cs.namespace(|| "p_d bits of y"), - p_d.map(|e| e.1) + cs.namespace(|| "pk_d bits of y"), + pk_d.map(|e| e.1) )?; let sign_bit = boolean::Boolean::from(boolean::AllocatedBit::alloc( - cs.namespace(|| "p_d bit of x"), - p_d.map(|e| e.0.into_repr().is_odd()) + cs.namespace(|| "pk_d bit of x"), + pk_d.map(|e| e.0.into_repr().is_odd()) )?); note_contents.extend(y_contents); @@ -481,10 +482,11 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { #[test] fn test_input_circuit_with_bls12_381() { + use pairing::{Field}; use pairing::bls12_381::*; use rand::{SeedableRng, Rng, XorShiftRng}; use ::circuit::test::*; - use jubjub::{JubjubBls12, fs}; + use jubjub::{JubjubParams, JubjubBls12, fs}; let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); @@ -510,7 +512,7 @@ fn test_input_circuit_with_bls12_381() { ak: Some(ak), g_d: Some(g_d), commitment_randomness: Some(commitment_randomness), - auth_path: auth_path + auth_path: auth_path.clone() }; instance.synthesize(&mut cs).unwrap(); @@ -518,23 +520,42 @@ fn test_input_circuit_with_bls12_381() { assert!(cs.is_satisfied()); assert_eq!(cs.num_constraints(), 101550); assert_eq!(cs.hash(), "3cc6d9383ca882ae3666267618e826e9d51a3177fc89ef6d42d9f63b84179f77"); + + let expected_value_cm = params.generator(FixedGenerators::ValueCommitmentValue) + .mul(fs::FsRepr::from(value), params) + .add( + ¶ms.generator(FixedGenerators::ValueCommitmentRandomness) + .mul(value_randomness, params), + params + ); + let expected_value_cm_xy = expected_value_cm.into_xy(); + + assert_eq!(cs.num_inputs(), 6); + assert_eq!(cs.get_input(0, "ONE"), Fr::one()); + assert_eq!(cs.get_input(1, "value commitment/x/input variable"), expected_value_cm_xy.0); + assert_eq!(cs.get_input(2, "value commitment/y/input variable"), expected_value_cm_xy.1); + + cs.get_input(3, "anchor/input variable"); + cs.get_input(4, "nullifier/x/input variable"); + cs.get_input(5, "nullifier/y/input variable"); } } #[test] fn test_output_circuit_with_bls12_381() { + use pairing::{Field}; use pairing::bls12_381::*; use rand::{SeedableRng, Rng, XorShiftRng}; use ::circuit::test::*; - use jubjub::{JubjubBls12, fs}; + use jubjub::{JubjubParams, JubjubBls12, fs}; let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let value: u64 = 1; let value_randomness: fs::Fs = rng.gen(); - let g_d: edwards::Point = edwards::Point::rand(rng, params); - let p_d: edwards::Point = edwards::Point::rand(rng, params); + let g_d: edwards::Point = edwards::Point::rand(rng, params).mul_by_cofactor(params); + let pk_d: edwards::Point = edwards::Point::rand(rng, params).mul_by_cofactor(params); let commitment_randomness: fs::Fs = rng.gen(); let esk: fs::Fs = rng.gen(); @@ -546,7 +567,7 @@ fn test_output_circuit_with_bls12_381() { value: Some(value), value_randomness: Some(value_randomness), g_d: Some(g_d.clone()), - p_d: Some(p_d.clone()), + pk_d: Some(pk_d.clone()), commitment_randomness: Some(commitment_randomness), esk: Some(esk.clone()) }; @@ -556,5 +577,32 @@ fn test_output_circuit_with_bls12_381() { assert!(cs.is_satisfied()); assert_eq!(cs.num_constraints(), 7827); assert_eq!(cs.hash(), "2896f259ad7a50c83604976ee9362358396d547b70f2feaf91d82d287e4ffc1d"); + + let expected_cm = ::primitives::Note { + value: value, + g_d: g_d.clone(), + pk_d: pk_d.clone(), + r: commitment_randomness.clone() + }.cm(params); + + let expected_value_cm = params.generator(FixedGenerators::ValueCommitmentValue) + .mul(fs::FsRepr::from(value), params) + .add( + ¶ms.generator(FixedGenerators::ValueCommitmentRandomness) + .mul(value_randomness, params), + params + ); + let expected_value_cm_xy = expected_value_cm.into_xy(); + + let expected_epk = g_d.mul(esk, params); + let expected_epk_xy = expected_epk.into_xy(); + + assert_eq!(cs.num_inputs(), 6); + assert_eq!(cs.get_input(0, "ONE"), Fr::one()); + assert_eq!(cs.get_input(1, "value commitment/x/input variable"), expected_value_cm_xy.0); + assert_eq!(cs.get_input(2, "value commitment/y/input variable"), expected_value_cm_xy.1); + assert_eq!(cs.get_input(3, "epk/x/input variable"), expected_epk_xy.0); + assert_eq!(cs.get_input(4, "epk/y/input variable"), expected_epk_xy.1); + assert_eq!(cs.get_input(5, "commitment/input variable"), expected_cm); } } diff --git a/src/circuit/test/mod.rs b/src/circuit/test/mod.rs index 01fda4a..9728e04 100644 --- a/src/circuit/test/mod.rs +++ b/src/circuit/test/mod.rs @@ -294,6 +294,19 @@ impl TestConstraintSystem { } } + pub fn num_inputs(&self) -> usize { + self.inputs.len() + } + + pub fn get_input(&mut self, index: usize, path: &str) -> E::Fr + { + let (assignment, name) = self.inputs[index].clone(); + + assert_eq!(path, name); + + assignment + } + pub fn get(&mut self, path: &str) -> E::Fr { match self.named_objects.get(path) { diff --git a/src/primitives/mod.rs b/src/primitives/mod.rs index 7a99092..237b633 100644 --- a/src/primitives/mod.rs +++ b/src/primitives/mod.rs @@ -5,7 +5,7 @@ use pedersen_hash::{ use byteorder::{ BigEndian, - ByteOrder + WriteBytesExt }; use jubjub::{ @@ -35,7 +35,7 @@ impl Note { let mut note_contents = vec![]; // Write the value in big endian - BigEndian::write_u64(&mut note_contents, self.value); + (&mut note_contents).write_u64::(self.value).unwrap(); // Write g_d self.g_d.write(&mut note_contents).unwrap(); @@ -43,6 +43,8 @@ impl Note { // Write pk_d self.pk_d.write(&mut note_contents).unwrap(); + assert_eq!(note_contents.len(), 32 + 32 + 8); + // Compute the Pedersen hash of the note contents let hash_of_contents = pedersen_hash( Personalization::NoteCommitment,