mirror of
https://github.com/arnaucube/protogalaxy-poc.git
synced 2026-01-12 08:51:31 +01:00
add test folding k instances and n iterations. also some polishing
This commit is contained in:
@@ -15,7 +15,7 @@ This code has been done in the context of the research on folding schemes in [0x
|
|||||||
## Details
|
## Details
|
||||||
Implementation of ProtoGalaxy's scheme described in section 4 of the paper.
|
Implementation of ProtoGalaxy's scheme described in section 4 of the paper.
|
||||||
|
|
||||||
Current version implements the folding on prover & verifier and it works, but it is not optimized.
|
Current version implements the folding on prover & verifier and it works for k-to-1 instances and with multiple iterations, but it is not optimized.
|
||||||
Next steps in terms of implementation include: F(X) O(n) construction following Claim 4.4, compute K(X) in O(kd log(kd)M + ndkC) as described in Claim 4.5, add tests folding in multiple iterations and also in a tree approach, add the decider and integrate with some existing R1CS tooling for the R1CS & witness generation.
|
Next steps in terms of implementation include: F(X) O(n) construction following Claim 4.4, compute K(X) in O(kd log(kd)M + ndkC) as described in Claim 4.5, add tests folding in multiple iterations and also in a tree approach, add the decider and integrate with some existing R1CS tooling for the R1CS & witness generation.
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
@@ -45,7 +45,6 @@ for i in 0..k {
|
|||||||
betas: betas.clone(),
|
betas: betas.clone(),
|
||||||
e: Fr::zero(),
|
e: Fr::zero(),
|
||||||
};
|
};
|
||||||
witnesses.push(witness_i);
|
|
||||||
instances.push(instance_i);
|
instances.push(instance_i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,5 +75,6 @@ let folded_instance_v = Folding::<G1Projective>::verifier(
|
|||||||
// check that the folded instance satisfies the relation
|
// check that the folded instance satisfies the relation
|
||||||
assert!(check_instance(&r2cs, folded_instance, folded_witness));
|
assert!(check_instance(&r2cs, folded_instance, folded_witness));
|
||||||
|
|
||||||
|
// now, the folded instance & witness can be folded again with n other instances.
|
||||||
```
|
```
|
||||||
(see the actual code for more details)
|
(see the actual code for more details)
|
||||||
|
|||||||
@@ -97,16 +97,14 @@ where
|
|||||||
// 'refreshed' randomness) satisfies the relation.
|
// 'refreshed' randomness) satisfies the relation.
|
||||||
assert!(check_instance(
|
assert!(check_instance(
|
||||||
r1cs,
|
r1cs,
|
||||||
CommittedInstance {
|
&CommittedInstance {
|
||||||
phi: instance.phi.clone(),
|
phi: instance.phi.clone(),
|
||||||
betas: betas_star.clone(),
|
betas: betas_star.clone(),
|
||||||
e: F_alpha,
|
e: F_alpha,
|
||||||
},
|
},
|
||||||
w.clone(),
|
&w,
|
||||||
));
|
));
|
||||||
|
|
||||||
let gamma = transcript.get_challenge();
|
|
||||||
|
|
||||||
let mut ws: Vec<Vec<C::ScalarField>> = Vec::new();
|
let mut ws: Vec<Vec<C::ScalarField>> = Vec::new();
|
||||||
ws.push(w.w.clone());
|
ws.push(w.w.clone());
|
||||||
for wj in vec_w.iter() {
|
for wj in vec_w.iter() {
|
||||||
@@ -116,6 +114,7 @@ where
|
|||||||
|
|
||||||
let k = vec_instances.len();
|
let k = vec_instances.len();
|
||||||
let H = GeneralEvaluationDomain::<C::ScalarField>::new(k + 1).unwrap();
|
let H = GeneralEvaluationDomain::<C::ScalarField>::new(k + 1).unwrap();
|
||||||
|
// WIP review t/d
|
||||||
let EH = GeneralEvaluationDomain::<C::ScalarField>::new(t * k + 1).unwrap();
|
let EH = GeneralEvaluationDomain::<C::ScalarField>::new(t * k + 1).unwrap();
|
||||||
let L_X: Vec<DensePolynomial<C::ScalarField>> = lagrange_polys(H);
|
let L_X: Vec<DensePolynomial<C::ScalarField>> = lagrange_polys(H);
|
||||||
|
|
||||||
@@ -165,6 +164,10 @@ where
|
|||||||
let (K_X, remainder) = G_L0e.divide_by_vanishing_poly(H).unwrap();
|
let (K_X, remainder) = G_L0e.divide_by_vanishing_poly(H).unwrap();
|
||||||
assert!(remainder.is_zero());
|
assert!(remainder.is_zero());
|
||||||
|
|
||||||
|
transcript.add_vec(&K_X.coeffs);
|
||||||
|
|
||||||
|
let gamma = transcript.get_challenge();
|
||||||
|
|
||||||
let e_star =
|
let e_star =
|
||||||
F_alpha * L_X[0].evaluate(&gamma) + Z_X.evaluate(&gamma) * K_X.evaluate(&gamma);
|
F_alpha * L_X[0].evaluate(&gamma) + Z_X.evaluate(&gamma) * K_X.evaluate(&gamma);
|
||||||
|
|
||||||
@@ -179,6 +182,10 @@ where
|
|||||||
&vec_scalar_mul(&vec_w[i].w, &L_X[i + 1].evaluate(&gamma)),
|
&vec_scalar_mul(&vec_w[i].w, &L_X[i + 1].evaluate(&gamma)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
let mut r_w_star: C::ScalarField = w.r_w * L_X[0].evaluate(&gamma);
|
||||||
|
for i in 0..k {
|
||||||
|
r_w_star += vec_w[i].r_w * L_X[i + 1].evaluate(&gamma);
|
||||||
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
F_X_dense.coeffs,
|
F_X_dense.coeffs,
|
||||||
@@ -219,8 +226,8 @@ where
|
|||||||
|
|
||||||
// F(alpha) = e + \sum_t F_i * alpha^i
|
// F(alpha) = e + \sum_t F_i * alpha^i
|
||||||
let mut F_alpha = instance.e;
|
let mut F_alpha = instance.e;
|
||||||
for (i, F_i) in F_coeffs.iter().enumerate() {
|
for (i, F_i) in F_coeffs.iter().skip(1).enumerate() {
|
||||||
F_alpha += *F_i * alphas[i];
|
F_alpha += *F_i * alphas[i + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
let betas_star: Vec<C::ScalarField> = instance
|
let betas_star: Vec<C::ScalarField> = instance
|
||||||
@@ -235,8 +242,6 @@ where
|
|||||||
.map(|(beta_i, delta_i_alpha)| *beta_i + delta_i_alpha)
|
.map(|(beta_i, delta_i_alpha)| *beta_i + delta_i_alpha)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let gamma = transcript.get_challenge();
|
|
||||||
|
|
||||||
let k = vec_instances.len();
|
let k = vec_instances.len();
|
||||||
let H = GeneralEvaluationDomain::<C::ScalarField>::new(k + 1).unwrap();
|
let H = GeneralEvaluationDomain::<C::ScalarField>::new(k + 1).unwrap();
|
||||||
let L_X: Vec<DensePolynomial<C::ScalarField>> = lagrange_polys(H);
|
let L_X: Vec<DensePolynomial<C::ScalarField>> = lagrange_polys(H);
|
||||||
@@ -244,6 +249,10 @@ where
|
|||||||
let K_X: DensePolynomial<C::ScalarField> =
|
let K_X: DensePolynomial<C::ScalarField> =
|
||||||
DensePolynomial::<C::ScalarField>::from_coefficients_vec(K_coeffs);
|
DensePolynomial::<C::ScalarField>::from_coefficients_vec(K_coeffs);
|
||||||
|
|
||||||
|
transcript.add_vec(&K_X.coeffs);
|
||||||
|
|
||||||
|
let gamma = transcript.get_challenge();
|
||||||
|
|
||||||
let e_star =
|
let e_star =
|
||||||
F_alpha * L_X[0].evaluate(&gamma) + Z_X.evaluate(&gamma) * K_X.evaluate(&gamma);
|
F_alpha * L_X[0].evaluate(&gamma) + Z_X.evaluate(&gamma) * K_X.evaluate(&gamma);
|
||||||
|
|
||||||
@@ -325,8 +334,8 @@ fn eval_f<F: PrimeField>(r1cs: &R1CS<F>, w: &[F]) -> Vec<F> {
|
|||||||
|
|
||||||
fn check_instance<C: CurveGroup>(
|
fn check_instance<C: CurveGroup>(
|
||||||
r1cs: &R1CS<C::ScalarField>,
|
r1cs: &R1CS<C::ScalarField>,
|
||||||
instance: CommittedInstance<C>,
|
instance: &CommittedInstance<C>,
|
||||||
w: Witness<C>,
|
w: &Witness<C>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let n = 2_u64.pow(instance.betas.len() as u32) as usize;
|
let n = 2_u64.pow(instance.betas.len() as u32) as usize;
|
||||||
|
|
||||||
@@ -473,15 +482,18 @@ mod tests {
|
|||||||
assert!(!is_zero_vec(&f_w));
|
assert!(!is_zero_vec(&f_w));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
// k represents the number of instances to be fold, appart from the running instance
|
||||||
fn test_fold_native_case() {
|
fn prepare_inputs(
|
||||||
|
k: usize,
|
||||||
|
) -> (
|
||||||
|
Witness<G1Projective>,
|
||||||
|
CommittedInstance<G1Projective>,
|
||||||
|
Vec<Witness<G1Projective>>,
|
||||||
|
Vec<CommittedInstance<G1Projective>>,
|
||||||
|
) {
|
||||||
let mut rng = ark_std::test_rng();
|
let mut rng = ark_std::test_rng();
|
||||||
let pedersen_params = Pedersen::<G1Projective>::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec
|
let pedersen_params = Pedersen::<G1Projective>::new_params(&mut rng, 100); // 100 is wip, will get it from actual vec
|
||||||
let poseidon_config = poseidon_test_config::<Fr>();
|
|
||||||
|
|
||||||
let k = 6;
|
|
||||||
|
|
||||||
let r1cs = get_test_r1cs::<Fr>();
|
|
||||||
let z = get_test_z::<Fr>(3);
|
let z = get_test_z::<Fr>(3);
|
||||||
let mut zs: Vec<Vec<Fr>> = Vec::new();
|
let mut zs: Vec<Vec<Fr>> = Vec::new();
|
||||||
for i in 0..k {
|
for i in 0..k {
|
||||||
@@ -489,10 +501,6 @@ mod tests {
|
|||||||
zs.push(z_i);
|
zs.push(z_i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// init Prover & Verifier's transcript
|
|
||||||
let mut transcript_p = Transcript::<Fr, G1Projective>::new(&poseidon_config);
|
|
||||||
let mut transcript_v = Transcript::<Fr, G1Projective>::new(&poseidon_config);
|
|
||||||
|
|
||||||
let n = z.len();
|
let n = z.len();
|
||||||
let t = log2(n) as usize;
|
let t = log2(n) as usize;
|
||||||
|
|
||||||
@@ -528,6 +536,20 @@ mod tests {
|
|||||||
instances.push(instance_i);
|
instances.push(instance_i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(witness, instance, witnesses, instances)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fold_native_case() {
|
||||||
|
let k = 6;
|
||||||
|
let (witness, instance, witnesses, instances) = prepare_inputs(k);
|
||||||
|
let r1cs = get_test_r1cs::<Fr>();
|
||||||
|
|
||||||
|
// init Prover & Verifier's transcript
|
||||||
|
let poseidon_config = poseidon_test_config::<Fr>();
|
||||||
|
let mut transcript_p = Transcript::<Fr, G1Projective>::new(&poseidon_config);
|
||||||
|
let mut transcript_v = Transcript::<Fr, G1Projective>::new(&poseidon_config);
|
||||||
|
|
||||||
let (F_coeffs, K_coeffs, folded_instance, folded_witness) = Folding::<G1Projective>::prover(
|
let (F_coeffs, K_coeffs, folded_instance, folded_witness) = Folding::<G1Projective>::prover(
|
||||||
&mut transcript_p,
|
&mut transcript_p,
|
||||||
&r1cs,
|
&r1cs,
|
||||||
@@ -554,6 +576,58 @@ mod tests {
|
|||||||
assert!(!folded_instance.e.is_zero());
|
assert!(!folded_instance.e.is_zero());
|
||||||
|
|
||||||
// check that the folded instance satisfies the relation
|
// check that the folded instance satisfies the relation
|
||||||
assert!(check_instance(&r1cs, folded_instance, folded_witness));
|
assert!(check_instance(&r1cs, &folded_instance, &folded_witness));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fold_various_iterations() {
|
||||||
|
let r1cs = get_test_r1cs::<Fr>();
|
||||||
|
|
||||||
|
// init Prover & Verifier's transcript
|
||||||
|
let poseidon_config = poseidon_test_config::<Fr>();
|
||||||
|
let mut transcript_p = Transcript::<Fr, G1Projective>::new(&poseidon_config);
|
||||||
|
let mut transcript_v = Transcript::<Fr, G1Projective>::new(&poseidon_config);
|
||||||
|
|
||||||
|
let (mut running_witness, mut running_instance, _, _) = prepare_inputs(0);
|
||||||
|
|
||||||
|
// fold k instances on each of num_iters iterations
|
||||||
|
let k = 6;
|
||||||
|
let num_iters = 10;
|
||||||
|
for _ in 0..num_iters {
|
||||||
|
// generate the instances to be fold
|
||||||
|
let (_, _, witnesses, instances) = prepare_inputs(k);
|
||||||
|
|
||||||
|
let (F_coeffs, K_coeffs, folded_instance, folded_witness) =
|
||||||
|
Folding::<G1Projective>::prover(
|
||||||
|
&mut transcript_p,
|
||||||
|
&r1cs,
|
||||||
|
running_instance.clone(),
|
||||||
|
running_witness.clone(),
|
||||||
|
instances.clone(),
|
||||||
|
witnesses,
|
||||||
|
);
|
||||||
|
|
||||||
|
// veriier
|
||||||
|
let folded_instance_v = Folding::<G1Projective>::verifier(
|
||||||
|
&mut transcript_v,
|
||||||
|
&r1cs,
|
||||||
|
running_instance.clone(),
|
||||||
|
instances,
|
||||||
|
F_coeffs,
|
||||||
|
K_coeffs,
|
||||||
|
);
|
||||||
|
|
||||||
|
// check that prover & verifier folded instances are the same values
|
||||||
|
assert_eq!(folded_instance.phi.0, folded_instance_v.phi.0);
|
||||||
|
assert_eq!(folded_instance.betas, folded_instance_v.betas);
|
||||||
|
assert_eq!(folded_instance.e, folded_instance_v.e);
|
||||||
|
assert!(!folded_instance.e.is_zero());
|
||||||
|
|
||||||
|
// check that the folded instance satisfies the relation
|
||||||
|
assert!(check_instance(&r1cs, &folded_instance, &folded_witness));
|
||||||
|
|
||||||
|
running_witness = folded_witness;
|
||||||
|
running_instance = folded_instance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user