From 3fbbd933cfaf9087b82782022c341f89d11c1e3e Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Thu, 8 Mar 2018 01:16:21 -0700 Subject: [PATCH] Simplify value commitment abstraction. --- src/circuit/mod.rs | 93 +++++++++++++++++++++---------------------- src/primitives/mod.rs | 22 ++++++++++ 2 files changed, 67 insertions(+), 48 deletions(-) diff --git a/src/circuit/mod.rs b/src/circuit/mod.rs index 3c1826e..c4f0db2 100644 --- a/src/circuit/mod.rs +++ b/src/circuit/mod.rs @@ -29,6 +29,10 @@ use jubjub::{ use constants; +use primitives::{ + ValueCommitment +}; + // TODO: This should probably be removed and we // should use existing helper methods on `Option` @@ -53,8 +57,7 @@ impl Assignment for Option { /// input to the circuit fn expose_value_commitment( mut cs: CS, - value: Option, - randomness: Option, + value_commitment: Option>, params: &E::Params ) -> Result, SynthesisError> where E: JubjubEngine, @@ -63,7 +66,7 @@ fn expose_value_commitment( // Booleanize the value into little-endian bit order let value_bits = boolean::u64_into_boolean_vec_le( cs.namespace(|| "value"), - value + value_commitment.as_ref().map(|c| c.value) )?; // Compute the note value in the exponent @@ -79,7 +82,7 @@ fn expose_value_commitment( // it doesn't matter for security. let hr = boolean::field_into_boolean_vec_le( cs.namespace(|| "hr"), - randomness + value_commitment.as_ref().map(|c| c.randomness) )?; // Compute the randomness in the exponent @@ -106,23 +109,27 @@ fn expose_value_commitment( /// This is an instance of the `Spend` circuit. pub struct Spend<'a, E: JubjubEngine> { pub params: &'a E::Params, - /// Value of the note being spent - pub value: Option, - /// Randomness that will hide the value - pub value_randomness: Option, + + /// Pedersen commitment to the value being spent + pub value_commitment: Option>, + /// Key which allows the proof to be constructed /// as defense-in-depth against a flaw in the /// protocol that would otherwise be exploitable /// by a holder of a viewing key. pub rsk: Option, + /// The public key that will be re-randomized for /// use as a nullifier and signing key for the /// transaction. pub ak: Option>, + /// The diversified base used to compute pk_d. pub g_d: Option>, + /// The randomness used to hide the note commitment data pub commitment_randomness: Option, + /// The authentication path of the commitment in the tree pub auth_path: Vec> } @@ -132,8 +139,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { { let value_bits = expose_value_commitment( cs.namespace(|| "value commitment"), - self.value, - self.value_randomness, + self.value_commitment, self.params )?; @@ -404,16 +410,19 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { /// This is an output circuit instance. pub struct Output<'a, E: JubjubEngine> { pub params: &'a E::Params, - /// Value of the note being created - pub value: Option, - /// Randomness that will hide the value - pub value_randomness: Option, + + /// Pedersen commitment to the value being spent + pub value_commitment: Option>, + /// The diversified base, computed by GH(d) pub g_d: Option>, + /// The diversified address point, computed by GH(d)^ivk 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 pub esk: Option } @@ -423,8 +432,7 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { { let value_bits = expose_value_commitment( cs.namespace(|| "value commitment"), - self.value, - self.value_randomness, + self.value_commitment, self.params )?; @@ -559,15 +567,17 @@ fn test_input_circuit_with_bls12_381() { use pairing::bls12_381::*; use rand::{SeedableRng, Rng, XorShiftRng}; use ::circuit::test::*; - use jubjub::{JubjubParams, JubjubBls12, fs}; + use jubjub::{JubjubBls12, fs}; let params = &JubjubBls12::new(); let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let tree_depth = 32; - let value: u64 = 1; - let value_randomness: fs::Fs = rng.gen(); + let value_commitment = ValueCommitment { + value: rng.gen(), + randomness: rng.gen() + }; let rsk: fs::Fs = rng.gen(); let ak: edwards::Point = edwards::Point::rand(rng, params).mul_by_cofactor(params); @@ -603,8 +613,7 @@ fn test_input_circuit_with_bls12_381() { let instance = Spend { params: params, - value: Some(value), - value_randomness: Some(value_randomness), + value_commitment: Some(value_commitment.clone()), rsk: Some(rsk), ak: Some(ak), g_d: Some(g_d.clone()), @@ -618,22 +627,15 @@ fn test_input_circuit_with_bls12_381() { 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(); + let expected_value_cm = value_commitment.cm(params).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/commitment point/x/input variable"), expected_value_cm_xy.0); - assert_eq!(cs.get_input(2, "value commitment/commitment point/y/input variable"), expected_value_cm_xy.1); + assert_eq!(cs.get_input(1, "value commitment/commitment point/x/input variable"), expected_value_cm.0); + assert_eq!(cs.get_input(2, "value commitment/commitment point/y/input variable"), expected_value_cm.1); let note = ::primitives::Note { - value: value, + value: value_commitment.value, g_d: g_d.clone(), pk_d: payment_address.pk_d.clone(), r: commitment_randomness.clone() @@ -689,13 +691,16 @@ fn test_output_circuit_with_bls12_381() { use pairing::bls12_381::*; use rand::{SeedableRng, Rng, XorShiftRng}; use ::circuit::test::*; - use jubjub::{JubjubParams, JubjubBls12, fs}; + use jubjub::{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 value_commitment = ValueCommitment { + value: rng.gen(), + randomness: rng.gen() + }; + 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(); @@ -706,8 +711,7 @@ fn test_output_circuit_with_bls12_381() { let instance = Output { params: params, - value: Some(value), - value_randomness: Some(value_randomness), + value_commitment: Some(value_commitment.clone()), g_d: Some(g_d.clone()), pk_d: Some(pk_d.clone()), commitment_randomness: Some(commitment_randomness), @@ -721,28 +725,21 @@ fn test_output_circuit_with_bls12_381() { assert_eq!(cs.hash(), "2896f259ad7a50c83604976ee9362358396d547b70f2feaf91d82d287e4ffc1d"); let expected_cm = ::primitives::Note { - value: value, + value: value_commitment.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_value_cm = value_commitment.cm(params).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/commitment point/x/input variable"), expected_value_cm_xy.0); - assert_eq!(cs.get_input(2, "value commitment/commitment point/y/input variable"), expected_value_cm_xy.1); + assert_eq!(cs.get_input(1, "value commitment/commitment point/x/input variable"), expected_value_cm.0); + assert_eq!(cs.get_input(2, "value commitment/commitment point/y/input variable"), expected_value_cm.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/primitives/mod.rs b/src/primitives/mod.rs index 5aa2260..6c12892 100644 --- a/src/primitives/mod.rs +++ b/src/primitives/mod.rs @@ -27,6 +27,28 @@ use jubjub::{ use blake2_rfc::blake2s::Blake2s; +#[derive(Clone)] +pub struct ValueCommitment { + pub value: u64, + pub randomness: E::Fs +} + +impl ValueCommitment { + pub fn cm( + &self, + params: &E::Params + ) -> edwards::Point + { + params.generator(FixedGenerators::ValueCommitmentValue) + .mul(self.value, params) + .add( + ¶ms.generator(FixedGenerators::ValueCommitmentRandomness) + .mul(self.randomness, params), + params + ) + } +} + pub struct ProofGenerationKey { pub ak: edwards::Point, pub rsk: E::Fs