Simplify value commitment abstraction.

This commit is contained in:
Sean Bowe 2018-03-08 01:16:21 -07:00
parent d6d86737c8
commit 3fbbd933cf
No known key found for this signature in database
GPG Key ID: 95684257D8F8B031
2 changed files with 67 additions and 48 deletions

View File

@ -29,6 +29,10 @@ use jubjub::{
use constants; use constants;
use primitives::{
ValueCommitment
};
// TODO: This should probably be removed and we // TODO: This should probably be removed and we
// should use existing helper methods on `Option` // should use existing helper methods on `Option`
@ -53,8 +57,7 @@ impl<T> Assignment<T> for Option<T> {
/// input to the circuit /// input to the circuit
fn expose_value_commitment<E, CS>( fn expose_value_commitment<E, CS>(
mut cs: CS, mut cs: CS,
value: Option<u64>, value_commitment: Option<ValueCommitment<E>>,
randomness: Option<E::Fs>,
params: &E::Params params: &E::Params
) -> Result<Vec<boolean::Boolean>, SynthesisError> ) -> Result<Vec<boolean::Boolean>, SynthesisError>
where E: JubjubEngine, where E: JubjubEngine,
@ -63,7 +66,7 @@ fn expose_value_commitment<E, CS>(
// Booleanize the value into little-endian bit order // Booleanize the value into little-endian bit order
let value_bits = boolean::u64_into_boolean_vec_le( let value_bits = boolean::u64_into_boolean_vec_le(
cs.namespace(|| "value"), cs.namespace(|| "value"),
value value_commitment.as_ref().map(|c| c.value)
)?; )?;
// Compute the note value in the exponent // Compute the note value in the exponent
@ -79,7 +82,7 @@ fn expose_value_commitment<E, CS>(
// it doesn't matter for security. // it doesn't matter for security.
let hr = boolean::field_into_boolean_vec_le( let hr = boolean::field_into_boolean_vec_le(
cs.namespace(|| "hr"), cs.namespace(|| "hr"),
randomness value_commitment.as_ref().map(|c| c.randomness)
)?; )?;
// Compute the randomness in the exponent // Compute the randomness in the exponent
@ -106,23 +109,27 @@ fn expose_value_commitment<E, CS>(
/// This is an instance of the `Spend` circuit. /// This is an instance of the `Spend` circuit.
pub struct Spend<'a, E: JubjubEngine> { pub struct Spend<'a, E: JubjubEngine> {
pub params: &'a E::Params, pub params: &'a E::Params,
/// Value of the note being spent
pub value: Option<u64>, /// Pedersen commitment to the value being spent
/// Randomness that will hide the value pub value_commitment: Option<ValueCommitment<E>>,
pub value_randomness: Option<E::Fs>,
/// Key which allows the proof to be constructed /// Key which allows the proof to be constructed
/// as defense-in-depth against a flaw in the /// as defense-in-depth against a flaw in the
/// protocol that would otherwise be exploitable /// protocol that would otherwise be exploitable
/// by a holder of a viewing key. /// by a holder of a viewing key.
pub rsk: Option<E::Fs>, pub rsk: Option<E::Fs>,
/// The public key that will be re-randomized for /// The public key that will be re-randomized for
/// use as a nullifier and signing key for the /// use as a nullifier and signing key for the
/// transaction. /// transaction.
pub ak: Option<edwards::Point<E, PrimeOrder>>, pub ak: Option<edwards::Point<E, PrimeOrder>>,
/// The diversified base used to compute pk_d. /// The diversified base used to compute pk_d.
pub g_d: Option<edwards::Point<E, PrimeOrder>>, pub g_d: Option<edwards::Point<E, PrimeOrder>>,
/// The randomness used to hide the note commitment data /// The randomness used to hide the note commitment data
pub commitment_randomness: Option<E::Fs>, pub commitment_randomness: Option<E::Fs>,
/// The authentication path of the commitment in the tree /// The authentication path of the commitment in the tree
pub auth_path: Vec<Option<(E::Fr, bool)>> pub auth_path: Vec<Option<(E::Fr, bool)>>
} }
@ -132,8 +139,7 @@ impl<'a, E: JubjubEngine> Circuit<E> for Spend<'a, E> {
{ {
let value_bits = expose_value_commitment( let value_bits = expose_value_commitment(
cs.namespace(|| "value commitment"), cs.namespace(|| "value commitment"),
self.value, self.value_commitment,
self.value_randomness,
self.params self.params
)?; )?;
@ -404,16 +410,19 @@ impl<'a, E: JubjubEngine> Circuit<E> for Spend<'a, E> {
/// This is an output circuit instance. /// This is an output circuit instance.
pub struct Output<'a, E: JubjubEngine> { pub struct Output<'a, E: JubjubEngine> {
pub params: &'a E::Params, pub params: &'a E::Params,
/// Value of the note being created
pub value: Option<u64>, /// Pedersen commitment to the value being spent
/// Randomness that will hide the value pub value_commitment: Option<ValueCommitment<E>>,
pub value_randomness: Option<E::Fs>,
/// The diversified base, computed by GH(d) /// The diversified base, computed by GH(d)
pub g_d: Option<edwards::Point<E, PrimeOrder>>, pub g_d: Option<edwards::Point<E, PrimeOrder>>,
/// The diversified address point, computed by GH(d)^ivk /// The diversified address point, computed by GH(d)^ivk
pub pk_d: Option<edwards::Point<E, PrimeOrder>>, pub pk_d: Option<edwards::Point<E, PrimeOrder>>,
/// The randomness used to hide the note commitment data /// The randomness used to hide the note commitment data
pub commitment_randomness: Option<E::Fs>, pub commitment_randomness: Option<E::Fs>,
/// The ephemeral secret key for DH with recipient /// The ephemeral secret key for DH with recipient
pub esk: Option<E::Fs> pub esk: Option<E::Fs>
} }
@ -423,8 +432,7 @@ impl<'a, E: JubjubEngine> Circuit<E> for Output<'a, E> {
{ {
let value_bits = expose_value_commitment( let value_bits = expose_value_commitment(
cs.namespace(|| "value commitment"), cs.namespace(|| "value commitment"),
self.value, self.value_commitment,
self.value_randomness,
self.params self.params
)?; )?;
@ -559,15 +567,17 @@ fn test_input_circuit_with_bls12_381() {
use pairing::bls12_381::*; use pairing::bls12_381::*;
use rand::{SeedableRng, Rng, XorShiftRng}; use rand::{SeedableRng, Rng, XorShiftRng};
use ::circuit::test::*; use ::circuit::test::*;
use jubjub::{JubjubParams, JubjubBls12, fs}; use jubjub::{JubjubBls12, fs};
let params = &JubjubBls12::new(); let params = &JubjubBls12::new();
let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let tree_depth = 32; let tree_depth = 32;
let value: u64 = 1; let value_commitment = ValueCommitment {
let value_randomness: fs::Fs = rng.gen(); value: rng.gen(),
randomness: rng.gen()
};
let rsk: fs::Fs = rng.gen(); let rsk: fs::Fs = rng.gen();
let ak: edwards::Point<Bls12, PrimeOrder> = edwards::Point::rand(rng, params).mul_by_cofactor(params); let ak: edwards::Point<Bls12, PrimeOrder> = edwards::Point::rand(rng, params).mul_by_cofactor(params);
@ -603,8 +613,7 @@ fn test_input_circuit_with_bls12_381() {
let instance = Spend { let instance = Spend {
params: params, params: params,
value: Some(value), value_commitment: Some(value_commitment.clone()),
value_randomness: Some(value_randomness),
rsk: Some(rsk), rsk: Some(rsk),
ak: Some(ak), ak: Some(ak),
g_d: Some(g_d.clone()), 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.num_constraints(), 101550);
assert_eq!(cs.hash(), "3cc6d9383ca882ae3666267618e826e9d51a3177fc89ef6d42d9f63b84179f77"); assert_eq!(cs.hash(), "3cc6d9383ca882ae3666267618e826e9d51a3177fc89ef6d42d9f63b84179f77");
let expected_value_cm = params.generator(FixedGenerators::ValueCommitmentValue) let expected_value_cm = value_commitment.cm(params).into_xy();
.mul(fs::FsRepr::from(value), params)
.add(
&params.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.num_inputs(), 6);
assert_eq!(cs.get_input(0, "ONE"), Fr::one()); 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(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_xy.1); assert_eq!(cs.get_input(2, "value commitment/commitment point/y/input variable"), expected_value_cm.1);
let note = ::primitives::Note { let note = ::primitives::Note {
value: value, value: value_commitment.value,
g_d: g_d.clone(), g_d: g_d.clone(),
pk_d: payment_address.pk_d.clone(), pk_d: payment_address.pk_d.clone(),
r: commitment_randomness.clone() r: commitment_randomness.clone()
@ -689,13 +691,16 @@ fn test_output_circuit_with_bls12_381() {
use pairing::bls12_381::*; use pairing::bls12_381::*;
use rand::{SeedableRng, Rng, XorShiftRng}; use rand::{SeedableRng, Rng, XorShiftRng};
use ::circuit::test::*; use ::circuit::test::*;
use jubjub::{JubjubParams, JubjubBls12, fs}; use jubjub::{JubjubBls12, fs};
let params = &JubjubBls12::new(); let params = &JubjubBls12::new();
let rng = &mut XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let rng = &mut XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let value: u64 = 1; let value_commitment = ValueCommitment {
let value_randomness: fs::Fs = rng.gen(); value: rng.gen(),
randomness: rng.gen()
};
let g_d: edwards::Point<Bls12, PrimeOrder> = edwards::Point::rand(rng, params).mul_by_cofactor(params); let g_d: edwards::Point<Bls12, PrimeOrder> = edwards::Point::rand(rng, params).mul_by_cofactor(params);
let pk_d: edwards::Point<Bls12, PrimeOrder> = edwards::Point::rand(rng, params).mul_by_cofactor(params); let pk_d: edwards::Point<Bls12, PrimeOrder> = edwards::Point::rand(rng, params).mul_by_cofactor(params);
let commitment_randomness: fs::Fs = rng.gen(); let commitment_randomness: fs::Fs = rng.gen();
@ -706,8 +711,7 @@ fn test_output_circuit_with_bls12_381() {
let instance = Output { let instance = Output {
params: params, params: params,
value: Some(value), value_commitment: Some(value_commitment.clone()),
value_randomness: Some(value_randomness),
g_d: Some(g_d.clone()), g_d: Some(g_d.clone()),
pk_d: Some(pk_d.clone()), pk_d: Some(pk_d.clone()),
commitment_randomness: Some(commitment_randomness), commitment_randomness: Some(commitment_randomness),
@ -721,28 +725,21 @@ fn test_output_circuit_with_bls12_381() {
assert_eq!(cs.hash(), "2896f259ad7a50c83604976ee9362358396d547b70f2feaf91d82d287e4ffc1d"); assert_eq!(cs.hash(), "2896f259ad7a50c83604976ee9362358396d547b70f2feaf91d82d287e4ffc1d");
let expected_cm = ::primitives::Note { let expected_cm = ::primitives::Note {
value: value, value: value_commitment.value,
g_d: g_d.clone(), g_d: g_d.clone(),
pk_d: pk_d.clone(), pk_d: pk_d.clone(),
r: commitment_randomness.clone() r: commitment_randomness.clone()
}.cm(params); }.cm(params);
let expected_value_cm = params.generator(FixedGenerators::ValueCommitmentValue) let expected_value_cm = value_commitment.cm(params).into_xy();
.mul(fs::FsRepr::from(value), params)
.add(
&params.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 = g_d.mul(esk, params);
let expected_epk_xy = expected_epk.into_xy(); let expected_epk_xy = expected_epk.into_xy();
assert_eq!(cs.num_inputs(), 6); assert_eq!(cs.num_inputs(), 6);
assert_eq!(cs.get_input(0, "ONE"), Fr::one()); 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(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_xy.1); 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(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(4, "epk/y/input variable"), expected_epk_xy.1);
assert_eq!(cs.get_input(5, "commitment/input variable"), expected_cm); assert_eq!(cs.get_input(5, "commitment/input variable"), expected_cm);

View File

@ -27,6 +27,28 @@ use jubjub::{
use blake2_rfc::blake2s::Blake2s; use blake2_rfc::blake2s::Blake2s;
#[derive(Clone)]
pub struct ValueCommitment<E: JubjubEngine> {
pub value: u64,
pub randomness: E::Fs
}
impl<E: JubjubEngine> ValueCommitment<E> {
pub fn cm(
&self,
params: &E::Params
) -> edwards::Point<E, PrimeOrder>
{
params.generator(FixedGenerators::ValueCommitmentValue)
.mul(self.value, params)
.add(
&params.generator(FixedGenerators::ValueCommitmentRandomness)
.mul(self.randomness, params),
params
)
}
}
pub struct ProofGenerationKey<E: JubjubEngine> { pub struct ProofGenerationKey<E: JubjubEngine> {
pub ak: edwards::Point<E, PrimeOrder>, pub ak: edwards::Point<E, PrimeOrder>,
pub rsk: E::Fs pub rsk: E::Fs