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

Onchain decider for Protogalaxy #172

Open
wants to merge 17 commits into
base: main
Choose a base branch
from

Conversation

winderica
Copy link
Contributor

Depends on #145.

This PR implements the onchain decider for Protogalaxy, which follows the design of Nova's decider described in Sonobe docs.

Specifically, the prover generates a Groth16 proof for the decider circuit and a KZG proof for the commitment $\phi$ in Protogalaxy's committed instance.

let kzg_proofs = circuit
.W_i1
.get_openings()
.iter()
.zip(&kzg_challenges)
.map(|((v, _), &c)| {
CS1::prove_with_challenge(&cs_pk, c, v, &C1::ScalarField::zero(), None)
})
.collect::<Result<Vec<_>, _>>()?;
let snark_proof =
S::prove(&snark_pk, circuit, &mut rng).map_err(|e| Error::Other(e.to_string()))?;

In addition, the randomness (i.e., the evaluations of $L_0(X), ..., L_k(X)$ at $\gamma$) are also included in the proof.
let L_X_evals = circuit.randomness.clone();
Ok(Self::Proof {
snark_proof,
L_X_evals,
kzg_proofs: kzg_proofs.try_into().unwrap(),
kzg_challenges: kzg_challenges.try_into().unwrap(),
})

Later, the verifier uses the randomness to compute the group operations in NIFS.V, i.e., the random linear combination of commitments in the running and incoming instances.

// 6.2. Fold the commitments
let U_final_commitments = DeciderProtoGalaxyGadget::fold_group_elements_native(
running_commitments,
incoming_commitments,
None,
proof.L_X_evals.clone(),
)?;

With the folded commitment U_final_commitments as a public input, the verifier checks the validity of Groth16 proof. The KZG proof is also verified against U_final_commitments.
let public_input = [
&[pp_hash, i][..],
&z_0,
&z_i,
&U_final_commitments
.iter()
.flat_map(|c| c.inputize())
.collect::<Vec<_>>(),
&proof.kzg_challenges,
&proof.kzg_proofs.iter().map(|p| p.eval).collect::<Vec<_>>(),
&proof.L_X_evals,
]
.concat();
let snark_v = S::verify(&snark_vp, &public_input, &proof.snark_proof)
.map_err(|e| Error::Other(e.to_string()))?;
if !snark_v {
return Err(Error::SNARKVerificationFail);
}
// 7.3. Verify the KZG proofs
for ((cm, &c), pi) in U_final_commitments
.iter()
.zip(&proof.kzg_challenges)
.zip(&proof.kzg_proofs)
{
// we're at the Ethereum EVM case, so the CS1 is KZG commitments
CS1::verify_with_challenge(&cs_vp, c, cm, pi)?;
}

Note that the decider circuit already enforces that the randomness indeed consists of the evaluations of $L_i(X)$, so the prover cannot cheat by providing the verifier with incorrect randomness.

@winderica winderica mentioned this pull request Nov 11, 2024
13 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant