Browse Source

fix transcript inconsistency

master
Mara Mihali 1 year ago
committed by maramihali
parent
commit
adf96ae8bc
4 changed files with 49 additions and 17 deletions
  1. +3
    -3
      .github/workflows/testudo.yml
  2. +16
    -2
      src/constraints.rs
  3. +23
    -12
      src/lib.rs
  4. +7
    -0
      src/r1csproof.rs

+ 3
- 3
.github/workflows/testudo.yml

@ -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
run: rustup component add clippy
# - name: Install 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

+ 16
- 2
src/constraints.rs

@ -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 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 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| {

+ 23
- 12
src/lib.rs

@ -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
// https://github.com/maramihali/Spartan/issues/6
// self.r1cs_eval_proof.verify(
// &comm.comm,
// &self.rx,
// &self.ry,
// &self.inst_evals,
// &gens.gens_r1cs_eval,
// transcript,
// )?;
// timer_eval_proof.stop();
self.r1cs_eval_proof.verify(
&comm.comm,
&self.rx,
&self.ry,
&self.inst_evals,
&gens.gens_r1cs_eval,
transcript,
)?;
timer_eval_proof.stop();
timer_verify.stop(); timer_verify.stop();
Ok(res) Ok(res)
} }

+ 7
- 0
src/r1csproof.rs

@ -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();

Loading…
Cancel
Save