fix transcript inconsistency

This commit is contained in:
Mara Mihali
2022-12-22 14:08:48 +02:00
committed by maramihali
parent f88d29fb0c
commit adf96ae8bc
4 changed files with 49 additions and 17 deletions

View File

@@ -21,8 +21,8 @@ jobs:
run: rustup default nightly run: rustup default nightly
- name: Install rustfmt Components - name: Install rustfmt Components
run: rustup component add rustfmt run: rustup component add rustfmt
- name: Install clippy # - name: Install clippy
run: rustup component add clippy # run: rustup component add clippy
- name: Build - name: Build
run: cargo build --verbose run: cargo build --verbose
- name: Run tests - name: Run tests
@@ -32,6 +32,6 @@ jobs:
- name: Check Rustfmt Code Style - name: Check Rustfmt Code Style
run: cargo fmt --all -- --check run: cargo fmt --all -- --check
# cargo clippy uses cargo check which returns an error when asm is emitted # cargo clippy uses cargo check which returns an error when asm is emitted
# we want to emit asm for ff operations so we avoid using clippy for now # we want to emit asm for ark-ff operations so we avoid using clippy for # now
# - name: Check clippy warnings # - name: Check clippy warnings
# run: cargo clippy --all-targets --all-features # run: cargo clippy --all-targets --all-features

View File

@@ -255,6 +255,7 @@ pub struct R1CSVerificationCircuit {
pub sc_phase2: SumcheckVerificationCircuit, pub sc_phase2: SumcheckVerificationCircuit,
// The point on which the polynomial was evaluated by the prover. // The point on which the polynomial was evaluated by the prover.
pub claimed_ry: Vec<Scalar>, pub claimed_ry: Vec<Scalar>,
pub claimed_transcript_sat_state: Scalar,
} }
impl R1CSVerificationCircuit { impl R1CSVerificationCircuit {
@@ -276,6 +277,7 @@ impl R1CSVerificationCircuit {
polys: config.polys_sc2.clone(), polys: config.polys_sc2.clone(),
}, },
claimed_ry: config.ry.clone(), claimed_ry: config.ry.clone(),
claimed_transcript_sat_state: config.transcript_sat_state,
} }
} }
} }
@@ -386,13 +388,21 @@ impl ConstraintSynthesizer<Fr> for R1CSVerificationCircuit {
let eval_A_r_var = FpVar::<Fr>::new_witness(cs.clone(), || Ok(eval_A_r))?; let eval_A_r_var = FpVar::<Fr>::new_witness(cs.clone(), || Ok(eval_A_r))?;
let eval_B_r_var = FpVar::<Fr>::new_witness(cs.clone(), || Ok(eval_B_r))?; let eval_B_r_var = FpVar::<Fr>::new_witness(cs.clone(), || Ok(eval_B_r))?;
let eval_C_r_var = FpVar::<Fr>::new_witness(cs, || Ok(eval_C_r))?; let eval_C_r_var = FpVar::<Fr>::new_witness(cs.clone(), || Ok(eval_C_r))?;
let scalar_var = &r_A_var * &eval_A_r_var + &r_B_var * &eval_B_r_var + &r_C_var * &eval_C_r_var; let scalar_var = &r_A_var * &eval_A_r_var + &r_B_var * &eval_B_r_var + &r_C_var * &eval_C_r_var;
let expected_claim_post_phase2_var = eval_Z_at_ry_var * scalar_var; let expected_claim_post_phase2_var = eval_Z_at_ry_var * scalar_var;
claim_post_phase2_var.enforce_equal(&expected_claim_post_phase2_var)?; claim_post_phase2_var.enforce_equal(&expected_claim_post_phase2_var)?;
let expected_transcript_state_var = transcript_var.challenge()?;
let claimed_transcript_state_var =
FpVar::<Fr>::new_input(cs, || Ok(self.claimed_transcript_sat_state))?;
// Ensure that the prover and verifier transcipt views are consistent at
// the end of the satisfiability proof.
expected_transcript_state_var.enforce_equal(&claimed_transcript_state_var)?;
Ok(()) Ok(())
} }
} }
@@ -411,6 +421,7 @@ pub struct VerifierConfig {
pub polys_sc1: Vec<UniPoly>, pub polys_sc1: Vec<UniPoly>,
pub polys_sc2: Vec<UniPoly>, pub polys_sc2: Vec<UniPoly>,
pub ry: Vec<Scalar>, pub ry: Vec<Scalar>,
pub transcript_sat_state: Scalar,
} }
#[derive(Clone)] #[derive(Clone)]
pub struct VerifierCircuit { pub struct VerifierCircuit {
@@ -420,6 +431,7 @@ pub struct VerifierCircuit {
pub eval_vars_at_ry: Fr, pub eval_vars_at_ry: Fr,
pub claims_phase2: (Fr, Fr, Fr, Fr), pub claims_phase2: (Fr, Fr, Fr, Fr),
pub ry: Vec<Fr>, pub ry: Vec<Fr>,
pub transcript_sat_state: Scalar,
} }
impl VerifierCircuit { impl VerifierCircuit {
@@ -438,6 +450,7 @@ impl VerifierCircuit {
eval_vars_at_ry: config.eval_vars_at_ry, eval_vars_at_ry: config.eval_vars_at_ry,
claims_phase2: config.claims_phase2, claims_phase2: config.claims_phase2,
ry: config.ry.clone(), ry: config.ry.clone(),
transcript_sat_state: config.transcript_sat_state,
}) })
} }
} }
@@ -449,7 +462,8 @@ impl ConstraintSynthesizer<Fq> for VerifierCircuit {
let mut pubs = vec![]; let mut pubs = vec![];
pubs.extend(self.ry); pubs.extend(self.ry);
pubs.extend(vec![v_A, v_B, v_C, v_AB]); pubs.extend(vec![v_A, v_B, v_C, v_AB]);
pubs.extend(vec![self.eval_vars_at_ry]); pubs.extend(vec![self.eval_vars_at_ry, self.transcript_sat_state]);
let bits = pubs let bits = pubs
.iter() .iter()
.map(|c| { .map(|c| {

View File

@@ -42,6 +42,7 @@ mod constraints;
pub mod poseidon_transcript; pub mod poseidon_transcript;
use ark_ff::Field; use ark_ff::Field;
use ark_relations::r1cs;
use ark_serialize::*; use ark_serialize::*;
use ark_std::Zero; use ark_std::Zero;
use core::cmp::max; use core::cmp::max;
@@ -400,6 +401,13 @@ impl SNARK {
(proof, rx, ry) (proof, rx, ry)
}; };
// We need to reset the transcript state before starting the evaluation
// proof and share this state with the verifier because, on the verifier's
// side all the previous updates are done on the transcript
// circuit variable and the transcript outside the circuit will be
// inconsistent wrt to the prover's.
transcript.new_from_state(&r1cs_sat_proof.transcript_sat_state);
// We send evaluations of A, B, C at r = (rx, ry) as claims // We send evaluations of A, B, C at r = (rx, ry) as claims
// to enable the verifier complete the first sum-check // to enable the verifier complete the first sum-check
let timer_eval = Timer::new("eval_sparse_polys"); let timer_eval = Timer::new("eval_sparse_polys");
@@ -466,24 +474,27 @@ impl SNARK {
)?; )?;
timer_sat_proof.stop(); timer_sat_proof.stop();
// let timer_eval_proof = Timer::new("verify_eval_proof"); let timer_eval_proof = Timer::new("verify_eval_proof");
// Reset the transcript using the state sent by the prover.
// TODO: find a way to retrieve this state from the circuit. Currently
// the API for generating constraints doesn't support returning values
// computed inside the circuit.
transcript.new_from_state(&self.r1cs_sat_proof.transcript_sat_state);
let (Ar, Br, Cr) = &self.inst_evals; let (Ar, Br, Cr) = &self.inst_evals;
transcript.append_scalar(&Ar); transcript.append_scalar(&Ar);
transcript.append_scalar(&Br); transcript.append_scalar(&Br);
transcript.append_scalar(&Cr); transcript.append_scalar(&Cr);
// TODO: debug this self.r1cs_eval_proof.verify(
// https://github.com/maramihali/Spartan/issues/6 &comm.comm,
// self.r1cs_eval_proof.verify( &self.rx,
// &comm.comm, &self.ry,
// &self.rx, &self.inst_evals,
// &self.ry, &gens.gens_r1cs_eval,
// &self.inst_evals, transcript,
// &gens.gens_r1cs_eval, )?;
// transcript, timer_eval_proof.stop();
// )?;
// timer_eval_proof.stop();
timer_verify.stop(); timer_verify.stop();
Ok(res) Ok(res)
} }

View File

@@ -40,6 +40,8 @@ pub struct R1CSProof {
proof_eval_vars_at_ry: Proof<I>, proof_eval_vars_at_ry: Proof<I>,
rx: Vec<Scalar>, rx: Vec<Scalar>,
ry: Vec<Scalar>, ry: Vec<Scalar>,
// The transcript state after the satisfiability proof was computed.
pub transcript_sat_state: Scalar,
} }
#[derive(Clone)] #[derive(Clone)]
pub struct R1CSSumcheckGens { pub struct R1CSSumcheckGens {
@@ -245,6 +247,8 @@ impl R1CSProof {
timer_prove.stop(); timer_prove.stop();
let c = transcript.challenge_scalar();
( (
R1CSProof { R1CSProof {
comm, comm,
@@ -255,6 +259,7 @@ impl R1CSProof {
proof_eval_vars_at_ry, proof_eval_vars_at_ry,
rx: rx.clone(), rx: rx.clone(),
ry: ry.clone(), ry: ry.clone(),
transcript_sat_state: c,
}, },
rx, rx,
ry, ry,
@@ -300,6 +305,7 @@ impl R1CSProof {
input_as_sparse_poly, input_as_sparse_poly,
// rx: self.rx.clone(), // rx: self.rx.clone(),
ry: self.ry.clone(), ry: self.ry.clone(),
transcript_sat_state: self.transcript_sat_state,
}; };
let mut rng = ark_std::test_rng(); let mut rng = ark_std::test_rng();
@@ -389,6 +395,7 @@ impl R1CSProof {
input_as_sparse_poly, input_as_sparse_poly,
// rx: self.rx.clone(), // rx: self.rx.clone(),
ry: self.ry.clone(), ry: self.ry.clone(),
transcript_sat_state: self.transcript_sat_state,
}; };
let mut rng = ark_std::test_rng(); let mut rng = ark_std::test_rng();