From 345b62e4f397c69ffa62296778010ca584846d3d Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Sun, 5 May 2024 17:06:44 -0400 Subject: [PATCH] Remove permissibility per discussions --- crypto/fcmps/src/circuit.rs | 3 -- crypto/fcmps/src/gadgets/mod.rs | 16 ------ crypto/fcmps/src/lib.rs | 89 ++++++++++++--------------------- crypto/fcmps/src/tests.rs | 83 +++++++++++++++--------------- 4 files changed, 74 insertions(+), 117 deletions(-) diff --git a/crypto/fcmps/src/circuit.rs b/crypto/fcmps/src/circuit.rs index d5b903ad..f7f1cb52 100644 --- a/crypto/fcmps/src/circuit.rs +++ b/crypto/fcmps/src/circuit.rs @@ -167,8 +167,6 @@ impl Circuit { let c_blind = self.discrete_log(transcript, curve, c_blind); self.incomplete_add_pub(C_tilde, c_blind, C); - self.permissible(C::F::ONE, C::F::ONE, O.y); - self.permissible(C::F::ONE, C::F::ONE, C.y); self.tuple_member_of_list(transcript, vec![O.x, I.x, I.y, C.x], branch); } @@ -184,7 +182,6 @@ impl Circuit { let blind = self.discrete_log(transcript, curve, blind); let hash = self.on_curve(curve, hash); self.incomplete_add_pub(blinded_hash, blind, hash); - self.permissible(C::F::ONE, C::F::ONE, hash.y); self.member_of_list(hash.x.into(), branch.into_iter().map(Into::into).collect::>()); } diff --git a/crypto/fcmps/src/gadgets/mod.rs b/crypto/fcmps/src/gadgets/mod.rs index 2867d41b..4943a3c2 100644 --- a/crypto/fcmps/src/gadgets/mod.rs +++ b/crypto/fcmps/src/gadgets/mod.rs @@ -160,20 +160,4 @@ impl Circuit { OnCurve { x: x2, y: y2 } } - - /// Constrain a `y` coordinate as being permissible. - /// - /// Panics if the prover and the `y` coordinate isn't permissible. - pub(crate) fn permissible(&mut self, a: C::F, b: C::F, y: Variable) { - // a y - -b = ay + b - let p = LinComb::empty().term(a, y).constant(b); - let p_eval = self.eval(&p); - let p_eval_sqrt = p_eval.map(|p_eval| p_eval.sqrt().unwrap()); - - let (l, r, o) = self.mul(None, None, p_eval_sqrt.map(|sqrt| (sqrt, sqrt))); - // Ensure this is actually a sqrt - self.equality(l.into(), &r.into()); - // Ensure the sq is the y coordinate derivative - self.equality(p, &o.into()); - } } diff --git a/crypto/fcmps/src/lib.rs b/crypto/fcmps/src/lib.rs index 65b3db78..ecc604e3 100644 --- a/crypto/fcmps/src/lib.rs +++ b/crypto/fcmps/src/lib.rs @@ -45,38 +45,18 @@ impl VectorCommitmentTape { (0 .. 256).map(|j| Variable::C(i, j)).collect() } - fn append_branch( + fn append_branch( &mut self, - generators: &Generators, branch_len: usize, branch: Option>, - ) -> (Vec, Option) + ) -> Vec where C::G: DivisorCurve, { - let mut branch_offset = None; let branch = branch.map(|mut branch| { assert_eq!(branch_len, branch.len()); assert!(branch.len() <= 256); - branch_offset = Some({ - let mut hash = multiexp( - &branch.iter().zip(generators.g_bold_slice()).map(|(s, p)| (*s, *p)).collect::>(), - ); - let mut offset = F::ZERO; - while Option::<<::G as DivisorCurve>::FieldElement>::from( - (<::G as DivisorCurve>::FieldElement::ONE + - ::G::to_xy(hash).1) - .sqrt(), - ) - .is_none() - { - hash += generators.h(); - offset += F::ONE; - } - offset - }); - // Pad the branch while branch.len() < 256 { branch.push(F::ZERO); @@ -86,7 +66,7 @@ impl VectorCommitmentTape { let mut branch = self.append(branch); branch.truncate(branch_len); - (branch, branch_offset) + branch } /// Append a discrete logarithm of up to 255 bits, allowing usage of the extra slot for an @@ -349,6 +329,11 @@ pub struct FcmpParams /// Generators for the second curve. curve_2_generators: Generators, + /// Initialization point for the hash function over the first curve. + curve_1_hash_init: C1::G, + /// Initialization point for the hash function over the first curve. + curve_2_hash_init: C2::G, + G_table: Vec<(C1::F, C1::F)>, T_table: Vec<(C1::F, C1::F)>, U_table: Vec<(C1::F, C1::F)>, @@ -362,9 +347,12 @@ where C1::G: DivisorCurve, C2::G: DivisorCurve, { + #[allow(clippy::too_many_arguments)] pub fn new( curve_1_generators: Generators, curve_2_generators: Generators, + curve_1_hash_init: C1::G, + curve_2_hash_init: C2::G, G: OC::G, T: OC::G, U: OC::G, @@ -392,6 +380,8 @@ where Self { curve_1_generators, curve_2_generators, + curve_1_hash_init, + curve_2_hash_init, G_table, T_table, U_table, @@ -484,51 +474,40 @@ where // Append the leaves and the rest of the branches to the tape let mut c1_tape = VectorCommitmentTape(vec![]); - let mut c1_branch_offsets = vec![]; let mut c1_branches = vec![]; { - let (branch, offset) = c1_tape.append_branch::( - ¶ms.curve_1_generators, - flattened_leaves.len(), - Some(flattened_leaves), - ); - c1_branch_offsets.push(offset.unwrap()); + let branch = c1_tape.append_branch::(flattened_leaves.len(), Some(flattened_leaves)); c1_branches.push(branch); } for branch in branches.curve_1_layers { - let (branch, offset) = - c1_tape.append_branch::(¶ms.curve_1_generators, branch.len(), Some(branch)); - c1_branch_offsets.push(offset.unwrap()); + let branch = c1_tape.append_branch::(branch.len(), Some(branch)); c1_branches.push(branch); } let mut c2_tape = VectorCommitmentTape(vec![]); - let mut c2_branch_offsets = vec![]; let mut c2_branches = vec![]; for branch in branches.curve_2_layers { - let (branch, offset) = - c2_tape.append_branch::(¶ms.curve_2_generators, branch.len(), Some(branch)); - c2_branch_offsets.push(offset.unwrap()); + let branch = c2_tape.append_branch::(branch.len(), Some(branch)); c2_branches.push(branch); } // Decide blinds for each branch let mut branches_1_blinds = vec![]; let mut branches_1_blinds_prepared = vec![]; - for offset in &c1_branch_offsets { + for _ in 0 .. c1_branches.len() { let blind = C1::F::random(&mut *rng); branches_1_blinds.push(blind); branches_1_blinds_prepared - .push(PreparedBlind::<_>::new::(params.curve_1_generators.h(), -(blind - offset))); + .push(PreparedBlind::<_>::new::(params.curve_1_generators.h(), -blind)); } let mut branches_2_blinds = vec![]; let mut branches_2_blinds_prepared = vec![]; - for offset in &c2_branch_offsets { + for _ in 0 .. c2_branches.len() { let blind = C2::F::random(&mut *rng); branches_2_blinds.push(blind); branches_2_blinds_prepared - .push(PreparedBlind::<_>::new::(params.curve_2_generators.h(), -(blind - offset))); + .push(PreparedBlind::<_>::new::(params.curve_2_generators.h(), -blind)); } // Accumulate the opening for the leaves @@ -710,14 +689,13 @@ where // - 1, as the leaves are the first branch assert_eq!(c1_branches.len() - 1, commitment_blind_claims_1.len()); assert!(commitments_2.len() > c1_branches.len()); - let commitment_iter = - commitments_2.clone().into_iter().zip(pvc_blinds_2.clone()).zip(c2_branch_offsets); + let commitment_iter = commitments_2.clone().into_iter().zip(pvc_blinds_2.clone()); let branch_iter = c1_branches.into_iter().skip(1).zip(commitment_blind_claims_1); - for (((prior_commitment, prior_blind), offset), (branch, prior_blind_opening)) in + for ((mut prior_commitment, prior_blind), (branch, prior_blind_opening)) in commitment_iter.into_iter().zip(branch_iter) { - let unblinded_hash = - prior_commitment - (params.curve_2_generators.h() * (prior_blind - offset)); + prior_commitment += params.curve_2_hash_init; + let unblinded_hash = prior_commitment - (params.curve_2_generators.h() * prior_blind); let (hash_x, hash_y, _) = c1_circuit.mul(None, None, Some(C2::G::to_xy(unblinded_hash))); c1_circuit.additional_layer( transcript, @@ -732,14 +710,13 @@ where assert_eq!(commitments_1.len(), pvc_blinds_1.len()); assert_eq!(c2_branches.len(), commitment_blind_claims_2.len()); assert!(commitments_1.len() > c2_branches.len()); - let commitment_iter = - commitments_1.clone().into_iter().zip(pvc_blinds_1.clone()).zip(c1_branch_offsets); + let commitment_iter = commitments_1.clone().into_iter().zip(pvc_blinds_1.clone()); let branch_iter = c2_branches.into_iter().zip(commitment_blind_claims_2); - for (((prior_commitment, prior_blind), offset), (branch, prior_blind_opening)) in + for ((mut prior_commitment, prior_blind), (branch, prior_blind_opening)) in commitment_iter.into_iter().zip(branch_iter) { - let unblinded_hash = - prior_commitment - (params.curve_1_generators.h() * (prior_blind - offset)); + prior_commitment += params.curve_1_hash_init; + let unblinded_hash = prior_commitment - (params.curve_1_generators.h() * prior_blind); let (hash_x, hash_y, _) = c2_circuit.mul(None, None, Some(C1::G::to_xy(unblinded_hash))); c2_circuit.additional_layer( transcript, @@ -808,12 +785,10 @@ where for (i, layer_len) in layer_lens.iter().enumerate() { if (i % 2) == 0 { - let (branch, _offset) = - c1_tape.append_branch::(¶ms.curve_1_generators, *layer_len, None); + let branch = c1_tape.append_branch::(*layer_len, None); c1_branches.push(branch); } else { - let (branch, _offset) = - c2_tape.append_branch::(¶ms.curve_2_generators, *layer_len, None); + let branch = c2_tape.append_branch::(*layer_len, None); c2_branches.push(branch); } } @@ -957,7 +932,7 @@ where c1_circuit.additional_layer( transcript, &CurveSpec { a: ::a(), b: ::b() }, - C2::G::to_xy(prior_commitment), + C2::G::to_xy(params.curve_2_hash_init + prior_commitment), prior_blind_opening, (hash_x, hash_y), branch, @@ -975,7 +950,7 @@ where c2_circuit.additional_layer( transcript, &CurveSpec { a: ::a(), b: ::b() }, - C1::G::to_xy(prior_commitment), + C1::G::to_xy(params.curve_1_hash_init + prior_commitment), prior_blind_opening, (hash_x, hash_y), branch, diff --git a/crypto/fcmps/src/tests.rs b/crypto/fcmps/src/tests.rs index 21cd4cc8..f6ed5d9f 100644 --- a/crypto/fcmps/src/tests.rs +++ b/crypto/fcmps/src/tests.rs @@ -7,28 +7,45 @@ use ciphersuite::{group::Group, Ciphersuite, Ed25519, Selene, Helios}; use crate::*; -fn make_permissible(generator: C, mut point: C) -> C { - while Option::::from((C::FieldElement::ONE + C::to_xy(point).1).sqrt()).is_none() - { - point += generator; - } - point -} - -fn random_permissible_point() -> C::G -where - C::G: DivisorCurve, -{ - make_permissible(C::G::generator(), C::G::random(&mut OsRng)) -} - fn random_output() -> Output { - let O = random_permissible_point::(); + let O = ::G::random(&mut OsRng); let I = ::G::random(&mut OsRng); - let C = random_permissible_point::(); + let C = ::G::random(&mut OsRng); Output { O, I, C } } +#[inline(never)] +fn verify_fn( + proof: Fcmp, + params: &FcmpParams, + root: TreeRoot, + layer_lens: Vec, + input: Input<::F>, +) { + let instant = std::time::Instant::now(); + + let mut verifier_1 = params.curve_1_generators.batch_verifier(); + let mut verifier_2 = params.curve_2_generators.batch_verifier(); + + for _ in 0 .. 100 { + proof.clone().verify::<_, _, Ed25519>( + &mut OsRng, + &mut RecommendedTranscript::new(b"FCMP Test"), + &mut verifier_1, + &mut verifier_2, + params, + root, + layer_lens.clone(), + input, + ); + } + + assert!(params.curve_1_generators.verify(verifier_1)); + assert!(params.curve_2_generators.verify(verifier_2)); + + dbg!((std::time::Instant::now() - instant).as_millis()); +} + #[test] fn test() { let G = ::G::random(&mut OsRng); @@ -41,6 +58,8 @@ fn test() { let params = FcmpParams::<_, _, _>::new::( curve_1_generators.clone(), curve_2_generators.clone(), + ::G::random(&mut OsRng), + ::G::random(&mut OsRng), G, T, U, @@ -75,7 +94,7 @@ fn test() { { multiexp.push((scalar, *point)); } - make_permissible(curve_1_generators.h(), multiexp_vartime(&multiexp)) + params.curve_1_hash_init + multiexp_vartime(&multiexp) }); let mut helios_hash; @@ -84,7 +103,7 @@ fn test() { for _ in 0 .. 2 { let mut curve_2_layer = vec![]; for _ in 0 .. usize::try_from(OsRng.next_u64() % 4).unwrap() + 1 { - curve_2_layer.push(random_permissible_point::()); + curve_2_layer.push(::G::random(&mut OsRng)); } let layer_len = curve_2_layer.len(); curve_2_layer[usize::try_from(OsRng.next_u64()).unwrap() % layer_len] = @@ -99,14 +118,14 @@ fn test() { for (scalar, point) in curve_2_layer.iter().zip(curve_2_generators.g_bold_slice()) { multiexp.push((*scalar, *point)); } - make_permissible(curve_2_generators.h(), multiexp_vartime(&multiexp)) + params.curve_2_hash_init + multiexp_vartime(&multiexp) }); curve_2_layers.push(curve_2_layer); let mut curve_1_layer = vec![]; for _ in 0 .. usize::try_from(OsRng.next_u64() % 4).unwrap() + 1 { - curve_1_layer.push(random_permissible_point::()); + curve_1_layer.push(::G::random(&mut OsRng)); } let layer_len = curve_1_layer.len(); curve_1_layer[usize::try_from(OsRng.next_u64()).unwrap() % layer_len] = @@ -121,7 +140,7 @@ fn test() { for (scalar, point) in curve_1_layer.iter().zip(curve_1_generators.g_bold_slice()) { multiexp.push((*scalar, *point)); } - make_permissible(curve_1_generators.h(), multiexp_vartime(&multiexp)) + params.curve_1_hash_init + multiexp_vartime(&multiexp) }); curve_1_layers.push(curve_1_layer); @@ -147,23 +166,5 @@ fn test() { branches, ); - let mut verifier_1 = params.curve_1_generators.batch_verifier(); - let mut verifier_2 = params.curve_2_generators.batch_verifier(); - - let instant = std::time::Instant::now(); - for _ in 0 .. 10 { - proof.clone().verify::<_, _, Ed25519>( - &mut OsRng, - &mut RecommendedTranscript::new(b"FCMP Test"), - &mut verifier_1, - &mut verifier_2, - ¶ms, - root, - layer_lens.clone(), - input, - ); - } - assert!(params.curve_1_generators.verify(verifier_1)); - assert!(params.curve_2_generators.verify(verifier_2)); - dbg!((std::time::Instant::now() - instant).as_millis()); + verify_fn(proof, ¶ms, root, layer_lens, input); }