-
Notifications
You must be signed in to change notification settings - Fork 8
Fix nonlinear relation handling in SchnorrProof #63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
b3d7b88
b0faeb4
916c372
4ebf8d8
a852b0d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -147,11 +147,13 @@ where | |
| } | ||
|
|
||
| let lhs = self.0.linear_map.evaluate(response)?; | ||
| let zero_vec = vec![<<G as Group>::Scalar as Field>::ZERO; self.0.linear_map.num_scalars]; | ||
| let zero_image = self.0.linear_map.evaluate(&zero_vec)?; | ||
| let mut rhs = Vec::new(); | ||
| for (i, g) in commitment.iter().enumerate() { | ||
| rhs.push({ | ||
| let image_var = self.0.image[i]; | ||
| self.0.linear_map.group_elements.get(image_var)? * challenge + g | ||
| (self.0.linear_map.group_elements.get(image_var)? - zero_image[i]) * challenge + g | ||
| }); | ||
| } | ||
| if lhs == rhs { | ||
|
|
@@ -322,13 +324,16 @@ where | |
| return Err(Error::InvalidInstanceWitnessPair); | ||
| } | ||
|
|
||
| let zero_vec = vec![<<G as Group>::Scalar as Field>::ZERO; self.0.linear_map.num_scalars]; | ||
| let zero_image = self.0.linear_map.evaluate(&zero_vec)?; | ||
| let response_image = self.0.linear_map.evaluate(response)?; | ||
| let image = self.0.image()?; | ||
|
|
||
| let commitment = response_image | ||
| .iter() | ||
| .zip(&image) | ||
| .map(|(res, img)| *res - *img * challenge) | ||
| .zip(&zero_image) | ||
| .map(|((res, img), z_img)| *res - (*img - *z_img) * challenge) | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Taking again the example of the relation X = (x + 1) * G: response_image = (r + w·c)·G + G image = w·G + G To recover T, which by definition equals r·G + G, we used to compute: This works in the case where we do not have a nonlinear component. Therefore, in the fix, during the computation of T, we must subtract c · zero_image, |
||
| .collect::<Vec<_>>(); | ||
| Ok(commitment) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| //! Definitions used in tests for this crate. | ||
|
|
||
| use ff::Field; | ||
| use group::{Group, GroupEncoding}; | ||
|
|
||
| use crate::linear_relation::{msm_pr, LinearRelation}; | ||
|
|
@@ -25,6 +26,27 @@ pub fn discrete_logarithm<G: Group + GroupEncoding>( | |
| (relation, vec![x]) | ||
| } | ||
|
|
||
| /// LinearMap for knowledge of a translated discrete logarithm relative to a fixed basepoint. | ||
| #[allow(non_snake_case)] | ||
| pub fn translated_discrete_logarithm<G: Group + GroupEncoding>( | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Implementation of the relation X = (x + 1) * G, viewed as a “translated” discrete logarithm, in order to perform tests on the protocol induced by it. Here, the function corresponds to x -> (x + 1)*G, and the part called "nonlinear" is the image of zero, so G |
||
| x: G::Scalar, | ||
| ) -> (LinearRelation<G>, Vec<G::Scalar>) { | ||
| let mut relation: LinearRelation<G> = LinearRelation::new(); | ||
|
|
||
| let var_x = relation.allocate_scalar(); | ||
| let var_G = relation.allocate_element(); | ||
|
|
||
| let var_X = relation.allocate_eq((var_x + <<G as Group>::Scalar as Field>::ONE) * var_G); | ||
|
|
||
| relation.set_element(var_G, G::generator()); | ||
| relation.compute_image(&[x]).unwrap(); | ||
|
|
||
| let X = relation.linear_map.group_elements.get(var_X).unwrap(); | ||
|
|
||
| assert!(vec![X] == relation.linear_map.evaluate(&[x]).unwrap()); | ||
| (relation, vec![x]) | ||
| } | ||
|
|
||
| /// LinearMap for knowledge of a discrete logarithm equality between two pairs. | ||
| #[allow(non_snake_case)] | ||
| pub fn dleq<G: Group + GroupEncoding>(H: G, x: G::Scalar) -> (LinearRelation<G>, Vec<G::Scalar>) { | ||
|
|
@@ -85,7 +107,8 @@ pub fn pedersen_commitment_dleq<G: Group + GroupEncoding>( | |
| let [var_x, var_r] = relation.allocate_scalars(); | ||
|
|
||
| let var_Gs = relation.allocate_elements::<4>(); | ||
| let [var_X, var_Y] = relation.allocate_elements(); | ||
| let var_X = relation.allocate_eq(var_x * var_Gs[0] + var_r * var_Gs[1]); | ||
| let var_Y = relation.allocate_eq(var_x * var_Gs[2] + var_r * var_Gs[3]); | ||
|
|
||
| relation.set_elements([ | ||
| (var_Gs[0], generators[0]), | ||
|
|
@@ -95,9 +118,6 @@ pub fn pedersen_commitment_dleq<G: Group + GroupEncoding>( | |
| ]); | ||
| relation.set_elements([(var_X, X), (var_Y, Y)]); | ||
|
|
||
| relation.append_equation(var_X, [(var_x, var_Gs[0]), (var_r, var_Gs[1])]); | ||
| relation.append_equation(var_Y, [(var_x, var_Gs[2]), (var_r, var_Gs[3])]); | ||
|
|
||
| assert!(vec![X, Y] == relation.linear_map.evaluate(&witness).unwrap()); | ||
| (relation, witness.to_vec()) | ||
| } | ||
|
|
@@ -119,7 +139,12 @@ pub fn bbs_blind_commitment_computation<G: Group + GroupEncoding>( | |
| let [var_secret_prover_blind, var_msg_1, var_msg_2, var_msg_3] = relation.allocate_scalars(); | ||
|
|
||
| let [var_Q_2, var_J_1, var_J_2, var_J_3] = relation.allocate_elements(); | ||
| let var_C = relation.allocate_element(); | ||
| let var_C = relation.allocate_eq( | ||
| var_secret_prover_blind * var_Q_2 | ||
| + var_msg_1 * var_J_1 | ||
| + var_msg_2 * var_J_2 | ||
| + var_msg_3 * var_J_3, | ||
| ); | ||
|
|
||
| relation.set_elements([ | ||
| (var_Q_2, Q_2), | ||
|
|
@@ -129,16 +154,6 @@ pub fn bbs_blind_commitment_computation<G: Group + GroupEncoding>( | |
| (var_C, C), | ||
| ]); | ||
|
|
||
| relation.append_equation( | ||
| var_C, | ||
| [ | ||
| (var_secret_prover_blind, var_Q_2), | ||
| (var_msg_1, var_J_1), | ||
| (var_msg_2, var_J_2), | ||
| (var_msg_3, var_J_3), | ||
| ], | ||
| ); | ||
|
|
||
| let witness = vec![secret_prover_blind, msg_1, msg_2, msg_3]; | ||
|
|
||
| assert!(vec![C] == relation.linear_map.evaluate(&witness).unwrap()); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Taking the example of a relation of the form X = (x + 1) * G = x * G + G where the nonlinear part is G:
Before the correction, the verification consisted of checking the equality between:
lhs = (r + wc) * G + G
rhs = (wG + G)c + (rG + G)
which is completely false since the relation contains a nonlinear part (the excess c*G component remains in rhs).
So, to correct this problem, we must subtract the image of the zero vector by the function before multiplying by c in rhs, which amounts to checking the equality between:
lhs = (r + wc) * G + G
rhs = ((wG + G) - G)c + (rG + G) = (w*G)c + (rG + G)
which is now verified