Skip to content
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

Optimising proving by avoiding recomputing final Pi polynomial in MLKZG #242

Merged
merged 3 commits into from
Jan 10, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 59 additions & 30 deletions src/provider/mlkzg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@ where
ck: &UniversalKZGParam<E>,
_pk: &Self::ProverKey,
transcript: &mut <NE as NovaEngine>::TE,
C: &Commitment<NE>,
_C: &Commitment<NE>,
hat_P: &[E::Fr],
point: &[E::Fr],
eval: &E::Fr,
_eval: &E::Fr,
) -> Result<Self::EvaluationArgument, NovaError> {
let x: Vec<E::Fr> = point.to_vec();

Expand Down Expand Up @@ -164,8 +164,7 @@ where
.to_affine()
};

let kzg_open_batch = |C: &[E::G1Affine],
f: &[Vec<E::Fr>],
let kzg_open_batch = |f: &[Vec<E::Fr>],
u: &[E::Fr],
transcript: &mut <NE as NovaEngine>::TE|
-> (Vec<E::G1Affine>, Vec<Vec<E::Fr>>) {
Expand Down Expand Up @@ -194,15 +193,14 @@ where

let k = f.len();
let t = u.len();
assert!(C.len() == k);

// The verifier needs f_i(u_j), so we compute them here
// (V will compute B(u_j) itself)
let mut v = vec![vec!(E::Fr::ZERO; k); t];
v.par_iter_mut().enumerate().for_each(|(i, v_i)| {
// for each point u
v_i.par_iter_mut().zip_eq(f).for_each(|(v_ij, f)| {
// for each poly f
// for each poly f (except the last one - since it is constant)
*v_ij = UniPoly::ref_cast(f).evaluate(&u[i]);
});
});
Expand All @@ -216,7 +214,6 @@ where
// The prover computes the challenge to keep the transcript in the same
// state as that of the verifier
let _d_0 = Self::verifier_second_challenge(&w, transcript);

(w, v)
};

Expand All @@ -229,7 +226,10 @@ where
// Phase 1 -- create commitments com_1, ..., com_\ell
let mut polys: Vec<Vec<E::Fr>> = Vec::new();
polys.push(hat_P.to_vec());
for i in 0..ell {

// We don't compute final Pi (and its commitment) as it is constant and equals to 'eval'
// also known to verifier, so can be derived on its side as well
for i in 0..x.len() - 1 {
let Pi_len = polys[i].len() / 2;
let mut Pi = vec![E::Fr::ZERO; Pi_len];

Expand All @@ -238,10 +238,6 @@ where
*Pi_j = x[ell - i - 1] * (polys[i][2 * j + 1] - polys[i][2 * j]) + polys[i][2 * j];
});

if i == ell - 1 && *eval != Pi[0] {
return Err(NovaError::UnSat);
}

polys.push(Pi);
}

Expand All @@ -263,9 +259,7 @@ where
let u = vec![r, -r, r * r];

// Phase 3 -- create response
let mut com_all = comms.clone();
com_all.insert(0, C.comm.to_affine());
let (w, evals) = kzg_open_batch(&com_all, &polys, &u, transcript);
let (w, evals) = kzg_open_batch(&polys, &u, transcript);

Ok(EvaluationArgument { comms, w, evals })
}
Expand Down Expand Up @@ -380,7 +374,6 @@ where
// we do not need to add x to the transcript, because in our context x was
// obtained from the transcript
let r = Self::compute_challenge(&com, transcript);

if r == E::Fr::ZERO || C.comm == E::G1::identity() {
return Err(NovaError::ProofVerifyError);
}
Expand All @@ -393,18 +386,15 @@ where
if v.len() != 3 {
return Err(NovaError::ProofVerifyError);
}
if v[0].len() != ell + 1 || v[1].len() != ell + 1 || v[2].len() != ell + 1 {
if v[0].len() != ell || v[1].len() != ell || v[2].len() != ell {
return Err(NovaError::ProofVerifyError);
}
let ypos = &v[0];
let yneg = &v[1];
let Y = &v[2];
let mut Y = v[2].to_vec();
Y.push(*y);

// Check consistency of (Y, ypos, yneg)
if Y[ell] != *y {
return Err(NovaError::ProofVerifyError);
}

let two = E::Fr::from(2u64);
for i in 0..ell {
if two * r * Y[i + 1]
Expand Down Expand Up @@ -474,15 +464,54 @@ mod tests {
let point = vec![Fr::from(2), Fr::from(2)];
let eval = Fr::from(9);
assert!(EvaluationEngine::<E, NE>::prove(&ck, &pk, &mut tr, &C, &poly, &point, &eval).is_ok());
}

// Try a couple incorrect evaluations and expect failure
let point = vec![Fr::from(2), Fr::from(2)];
let eval = Fr::from(50);
assert!(EvaluationEngine::<E, NE>::prove(&ck, &pk, &mut tr, &C, &poly, &point, &eval).is_err());
#[test]
fn test_mlkzg_alternative() {
fn test_inner(n: usize, poly: &[Fr], point: &[Fr], eval: Fr) -> Result<(), NovaError> {
let ck: CommitmentKey<NE> =
<KZGCommitmentEngine<E> as CommitmentEngineTrait<NE>>::setup(b"test", n);
let (pk, vk): (KZGProverKey<E>, KZGVerifierKey<E>) = EvaluationEngine::<E, NE>::setup(&ck);

// make a commitment
let C = KZGCommitmentEngine::commit(&ck, poly);

// prove an evaluation
let mut prover_transcript = Keccak256Transcript::new(b"TestEval");
let proof =
EvaluationEngine::<E, NE>::prove(&ck, &pk, &mut prover_transcript, &C, poly, point, &eval)
.unwrap();

// verify the evaluation
let mut verifier_transcript = Keccak256Transcript::<NE>::new(b"TestEval");
EvaluationEngine::<E, NE>::verify(&vk, &mut verifier_transcript, &C, point, &eval, &proof)
}

let point = vec![Fr::from(0), Fr::from(2)];
let eval = Fr::from(4);
assert!(EvaluationEngine::<E, NE>::prove(&ck, &pk, &mut tr, &C, &poly, &point, &eval).is_err());
let n = 8;

// poly = [1, 2, 1, 4, 1, 2, 1, 4]
let poly = vec![
Fr::ONE,
Fr::from(2),
Fr::from(1),
Fr::from(4),
Fr::ONE,
Fr::from(2),
Fr::from(1),
Fr::from(4),
];

// point = [4,3,8]
let point = vec![Fr::from(4), Fr::from(3), Fr::from(8)];

// eval = 57
let eval = Fr::from(57);

assert!(test_inner(n, &poly, &point, eval).is_ok());

// wrong eval
let eval = Fr::from(56);
assert!(test_inner(n, &poly, &point, eval).is_err());
}

#[test]
Expand Down Expand Up @@ -541,7 +570,7 @@ mod tests {

// Change the proof and expect verification to fail
let mut bad_proof = proof.clone();
bad_proof.comms[0] = (bad_proof.comms[0] + bad_proof.comms[1]).to_affine();
bad_proof.comms[0] = (bad_proof.comms[0] + bad_proof.comms[0] * Fr::from(123)).to_affine();
let mut verifier_transcript2 = Keccak256Transcript::<NE>::new(b"TestEval");
assert!(EvaluationEngine::<E, NE>::verify(
&vk,
Expand Down
Loading