diff --git a/src/gadgets/lookup.rs b/src/gadgets/lookup.rs index e39b30ba7..bea2de983 100644 --- a/src/gadgets/lookup.rs +++ b/src/gadgets/lookup.rs @@ -158,7 +158,7 @@ impl LookupTrace { mut cs: CS, ro_const: ROConstantsCircuit, prev_intermediate_gamma: &AllocatedNum, - gamma: &AllocatedNum, + challanges: &(AllocatedNum, AllocatedNum), prev_R: &AllocatedNum, prev_W: &AllocatedNum, prev_rw_counter: &AllocatedNum, @@ -189,7 +189,7 @@ impl LookupTrace { let (next_R, next_W, next_rw_counter) = self.rw_operation_circuit( cs.namespace(|| format!("{}th read ", i)), addr, - gamma, + challanges, read_value, read_value, &prev_R, @@ -213,7 +213,7 @@ impl LookupTrace { let (next_R, next_W, next_rw_counter) = self.rw_operation_circuit( cs.namespace(|| format!("{}th write ", i)), addr, - gamma, + challanges, read_value, write_value, &prev_R, @@ -245,8 +245,7 @@ impl LookupTrace { &mut self, mut cs: CS, addr: &AllocatedNum, - // challenges: &(AllocatedNum, AllocatedNum), - gamma: &AllocatedNum, + challenges: &(AllocatedNum, AllocatedNum), read_value: &AllocatedNum, write_value: &AllocatedNum, prev_R: &AllocatedNum, @@ -257,27 +256,28 @@ impl LookupTrace { where F: Ord, { + let (alpha, gamma) = challenges; // update R let gamma_square = gamma.mul(cs.namespace(|| "gamme^2"), gamma)?; // read_value_term = gamma * value let read_value_term = gamma.mul(cs.namespace(|| "read_value_term"), read_value)?; // counter_term = gamma^2 * counter let read_counter_term = gamma_square.mul(cs.namespace(|| "read_counter_term"), read_counter)?; - // new_R = R * (gamma - (addr + gamma * value + gamma^2 * counter)) + // new_R = R * (alpha - (addr + gamma * value + gamma^2 * counter)) let new_R = AllocatedNum::alloc(cs.namespace(|| "new_R"), || { prev_R .get_value() - .zip(gamma.get_value()) + .zip(alpha.get_value()) .zip(addr.get_value()) .zip(read_value_term.get_value()) .zip(read_counter_term.get_value()) - .map(|((((R, gamma), addr), value_term), counter_term)| { - R * (gamma - (addr + value_term + counter_term)) + .map(|((((R, alpha), addr), value_term), counter_term)| { + R * (alpha - (addr + value_term + counter_term)) }) .ok_or(SynthesisError::AssignmentMissing) })?; let mut r_blc = LinearCombination::::zero(); - r_blc = r_blc + gamma.get_variable() + r_blc = r_blc + alpha.get_variable() - addr.get_variable() - read_value_term.get_variable() - read_counter_term.get_variable(); @@ -324,21 +324,21 @@ impl LookupTrace { let new_W = AllocatedNum::alloc(cs.namespace(|| "new_W"), || { prev_W .get_value() - .zip(gamma.get_value()) + .zip(alpha.get_value()) .zip(addr.get_value()) .zip(write_value_term.get_value()) .zip(write_counter_term.get_value()) .zip(gamma_square.get_value()) .map( - |(((((W, gamma), addr), value_term), write_counter_term), gamma_square)| { - W * (gamma - (addr + value_term + write_counter_term + gamma_square)) + |(((((W, alpha), addr), value_term), write_counter_term), gamma_square)| { + W * (alpha - (addr + value_term + write_counter_term + gamma_square)) }, ) .ok_or(SynthesisError::AssignmentMissing) })?; - // new_W = W * (gamma - (addr + gamma * value + gamma^2 * counter + gamma^2))) + // new_W = W * (alpha - (addr + gamma * value + gamma^2 * counter + gamma^2))) let mut w_blc = LinearCombination::::zero(); - w_blc = w_blc + gamma.get_variable() + w_blc = w_blc + alpha.get_variable() - addr.get_variable() - write_value_term.get_variable() - write_counter_term.get_variable() @@ -471,7 +471,7 @@ impl<'a, G: Group> LookupTraceBuilder<'a, G> { ck: &<::CE as CommitmentEngineTrait>::CommitmentKey, final_table: &Lookup, intermediate_gamma: G::Scalar, - ) -> G::Scalar + ) -> (G::Scalar, G::Scalar) where G: Group::Scalar>, G2: Group::Scalar>, @@ -495,12 +495,19 @@ impl<'a, G: Group> LookupTraceBuilder<'a, G> { || G::CE::commit(ck, &final_counters), ); - let mut hasher = ::RO::new(ro_consts, 7); + // gamma + let mut hasher = ::RO::new(ro_consts.clone(), 7); let intermediate_gamma: G2::Scalar = scalar_as_base::(intermediate_gamma); hasher.absorb(intermediate_gamma); comm_final_value.absorb_in_ro(&mut hasher); comm_final_counter.absorb_in_ro(&mut hasher); - hasher.squeeze(NUM_CHALLENGE_BITS) + let gamma = hasher.squeeze(NUM_CHALLENGE_BITS); + + // alpha + let mut hasher = ::RO::new(ro_consts, 1); + hasher.absorb(scalar_as_base::(gamma)); + let alpha = hasher.squeeze(NUM_CHALLENGE_BITS); + (alpha, gamma) } } @@ -734,10 +741,17 @@ mod test { ]; let mut lookup = Lookup::<::Scalar>::new(1024, TableType::ReadOnly, initial_table); let mut lookup_trace_builder = LookupTraceBuilder::::new(&mut lookup); - let gamma = AllocatedNum::alloc(cs.namespace(|| "gamma"), || { - Ok(::Scalar::from(2)) - }) - .unwrap(); + let challenges = ( + AllocatedNum::alloc(cs.namespace(|| "alpha"), || { + Ok(::Scalar::from(5)) + }) + .unwrap(), + AllocatedNum::alloc(cs.namespace(|| "gamma"), || { + Ok(::Scalar::from(7)) + }) + .unwrap(), + ); + let (alpha, gamma) = &challenges; let zero = alloc_zero(cs.namespace(|| "zero")).unwrap(); let one = alloc_one(cs.namespace(|| "one")).unwrap(); let prev_intermediate_gamma = &one; @@ -774,7 +788,7 @@ mod test { cs.namespace(|| "commit"), ro_consts.clone(), prev_intermediate_gamma, - &gamma, + &challenges, prev_W, prev_R, prev_rw_counter, @@ -789,25 +803,27 @@ mod test { next_R.get_value(), prev_R .get_value() + .zip(alpha.get_value()) .zip(gamma.get_value()) .zip(addr.get_value()) .zip(read_value.get_value()) - .map(|(((prev_R, gamma), addr), read_value)| prev_R - * (gamma - (addr + gamma * read_value + gamma * gamma * ::Scalar::ZERO)) - * (gamma - (addr + gamma * read_value + gamma * gamma * ::Scalar::ONE))) + .map(|((((prev_R, alpha), gamma), addr), read_value)| prev_R + * (alpha - (addr + gamma * read_value + gamma * gamma * ::Scalar::ZERO)) + * (alpha - (addr + gamma * read_value + gamma * gamma * ::Scalar::ONE))) ); // next_W check assert_eq!( next_W.get_value(), prev_W .get_value() + .zip(alpha.get_value()) .zip(gamma.get_value()) .zip(addr.get_value()) .zip(read_value.get_value()) - .map(|(((prev_W, gamma), addr), read_value)| { + .map(|((((prev_W, alpha), gamma), addr), read_value)| { prev_W - * (gamma - (addr + gamma * read_value + gamma * gamma * (::Scalar::ONE))) - * (gamma + * (alpha - (addr + gamma * read_value + gamma * gamma * (::Scalar::ONE))) + * (alpha - (addr + gamma * read_value + gamma * gamma * (::Scalar::from(2)))) }), ); @@ -825,12 +841,6 @@ mod test { scalar_as_base::(res), next_intermediate_gamma.get_value().unwrap() ); - // TODO check rics is_sat - // let (_, _) = cs.r1cs_shape_with_commitmentkey(); - // let (U1, W1) = cs.r1cs_instance_and_witness(&shape, &ck).unwrap(); - - // // Make sure that the first instance is satisfiable - // assert!(shape.is_sat(&ck, &U1, &W1).is_ok()); } #[test] @@ -849,10 +859,17 @@ mod test { let mut lookup = Lookup::<::Scalar>::new(1024, TableType::ReadWrite, initial_table); let mut lookup_trace_builder = LookupTraceBuilder::::new(&mut lookup); - let gamma = AllocatedNum::alloc(cs.namespace(|| "gamma"), || { - Ok(::Scalar::from(2)) - }) - .unwrap(); + let challenges = ( + AllocatedNum::alloc(cs.namespace(|| "alpha"), || { + Ok(::Scalar::from(5)) + }) + .unwrap(), + AllocatedNum::alloc(cs.namespace(|| "gamma"), || { + Ok(::Scalar::from(7)) + }) + .unwrap(), + ); + let (alpha, gamma) = &challenges; let zero = alloc_zero(cs.namespace(|| "zero")).unwrap(); let one = alloc_one(cs.namespace(|| "one")).unwrap(); let prev_intermediate_gamma = &one; @@ -890,7 +907,7 @@ mod test { cs.namespace(|| "commit"), ro_consts.clone(), prev_intermediate_gamma, - &gamma, + &challenges, prev_W, prev_R, prev_rw_counter, @@ -905,28 +922,30 @@ mod test { next_R.get_value(), prev_R .get_value() + .zip(alpha.get_value()) .zip(gamma.get_value()) .zip(addr.get_value()) .zip(read_value.get_value()) - .map(|(((prev_R, gamma), addr), read_value)| prev_R - * (gamma + .map(|((((prev_R, alpha), gamma), addr), read_value)| prev_R + * (alpha - (addr + gamma * ::Scalar::ZERO + gamma * gamma * ::Scalar::ZERO)) - * (gamma - (addr + gamma * read_value + gamma * gamma * ::Scalar::ONE))) + * (alpha - (addr + gamma * read_value + gamma * gamma * ::Scalar::ONE))) ); // next_W check assert_eq!( next_W.get_value(), prev_W .get_value() + .zip(alpha.get_value()) .zip(gamma.get_value()) .zip(addr.get_value()) .zip(read_value.get_value()) - .map(|(((prev_W, gamma), addr), read_value)| { + .map(|((((prev_W, alpha), gamma), addr), read_value)| { prev_W - * (gamma - (addr + gamma * read_value + gamma * gamma * (::Scalar::ONE))) - * (gamma + * (alpha - (addr + gamma * read_value + gamma * gamma * (::Scalar::ONE))) + * (alpha - (addr + gamma * read_value + gamma * gamma * (::Scalar::from(2)))) }), ); diff --git a/src/lib.rs b/src/lib.rs index c2d60dbc9..0fe1a2e8b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1790,9 +1790,12 @@ mod tests { ::Scalar::from(0), ); + let (alpha, gamma) = + LookupTraceBuilder::::get_challenge::(ck, final_table, intermediate_gamma); vec![ initial_intermediate_gamma, - LookupTraceBuilder::::get_challenge::(ck, final_table, intermediate_gamma), + alpha, + gamma, init_prev_R, init_prev_W, init_rw_counter, @@ -1809,7 +1812,7 @@ mod tests { G2: Group::Scalar>, { fn arity(&self) -> usize { - 6 + 7 } fn synthesize>( @@ -1819,11 +1822,12 @@ mod tests { ) -> Result>, SynthesisError> { let mut lookup_trace = self.lookup_trace.clone(); let prev_intermediate_gamma = &z[0]; - let gamma = &z[1]; - let prev_R = &z[2]; - let prev_W = &z[3]; - let prev_rw_counter = &z[4]; - let index = &z[5]; + let alpha = &z[1]; + let gamma = &z[2]; + let prev_R = &z[3]; + let prev_W = &z[4]; + let prev_rw_counter = &z[5]; + let index = &z[6]; let left_child_index = AllocatedNum::alloc(cs.namespace(|| "left_child_index"), || { index @@ -1921,7 +1925,7 @@ mod tests { cs.namespace(|| "commit"), self.ro_consts.clone(), prev_intermediate_gamma, - gamma, + &(alpha.clone(), gamma.clone()), prev_W, prev_R, prev_rw_counter, @@ -1941,6 +1945,7 @@ mod tests { ); Ok(vec![ next_intermediate_gamma, + alpha.clone(), gamma.clone(), next_R, next_W, @@ -2062,25 +2067,26 @@ mod tests { assert!(res.is_ok()); let (zn_primary, _) = res.unwrap(); - assert_eq!(::Scalar::from(1).neg(), zn_primary[5]); + assert_eq!(::Scalar::from(1).neg(), zn_primary[6]); let number_of_iterated_nodes = (heap_size - 4) / 2 + 1; assert_eq!( ::Scalar::from((number_of_iterated_nodes * 7) as u64), - zn_primary[4] + zn_primary[5] ); // rw counter = number_of_iterated_nodes * (3r + 4w) operations - assert_eq!(pp.circuit_shape_primary.r1cs_shape.num_cons, 12598); - assert_eq!(pp.circuit_shape_primary.r1cs_shape.num_vars, 12604); + assert_eq!(pp.circuit_shape_primary.r1cs_shape.num_cons, 12599); + assert_eq!(pp.circuit_shape_primary.r1cs_shape.num_vars, 12607); assert_eq!(pp.circuit_shape_secondary.r1cs_shape.num_cons, 10347); assert_eq!(pp.circuit_shape_secondary.r1cs_shape.num_vars, 10329); println!("zn_primary {:?}", zn_primary); let intermediate_gamma = zn_primary[0]; - let gamma = zn_primary[1]; - let read_row = zn_primary[2]; - let write_row = zn_primary[3]; + let alpha = zn_primary[1]; + let gamma = zn_primary[2]; + let read_row = zn_primary[3]; + let write_row = zn_primary[4]; assert_eq!( expected_intermediate_gamma, intermediate_gamma, "expected_intermediate_gamma != intermediate_gamma" @@ -2093,7 +2099,7 @@ mod tests { let snark_proof = LookupSNARK::::prove( &pp.ck_primary, &pk, - gamma, + (alpha, gamma), read_row, write_row, initial_table.get_table(), @@ -2101,7 +2107,7 @@ mod tests { ) .unwrap(); - let res = snark_proof.verify::(&vk, expected_intermediate_gamma, gamma); + let res = snark_proof.verify::(&vk, expected_intermediate_gamma, (alpha, gamma)); let _ = res.clone().map_err(|err| println!("{:?}", err)); res.unwrap() } diff --git a/src/spartan/lookupsnark.rs b/src/spartan/lookupsnark.rs index 799a643b8..a7d243df7 100644 --- a/src/spartan/lookupsnark.rs +++ b/src/spartan/lookupsnark.rs @@ -150,7 +150,7 @@ where pub fn prove( ck: &CommitmentKey, pk: &ProverKey, - fingerprint_gamma: G::Scalar, + challenges: (G::Scalar, G::Scalar), read_row: G::Scalar, write_row: G::Scalar, initial_table: Vec<(G::Scalar, G::Scalar, G::Scalar)>, @@ -159,9 +159,10 @@ where // a list of polynomial evaluation claims that will be batched let mut w_u_vec = Vec::new(); - let gamma_square = fingerprint_gamma * fingerprint_gamma; + let (fingerprint_alpha, fingerprint_gamma) = challenges; + let gamma_square: ::Scalar = fingerprint_gamma * fingerprint_gamma; let hash_func = |addr: &G::Scalar, val: &G::Scalar, ts: &G::Scalar| -> G::Scalar { - fingerprint_gamma - (*ts * gamma_square + *val * fingerprint_gamma + *addr) + fingerprint_alpha - (*ts * gamma_square + *val * fingerprint_gamma + *addr) }; // init_row let initial_row: Vec = initial_table @@ -178,6 +179,7 @@ where transcript.absorb(b"vk", &pk.vk_digest); transcript.absorb(b"read_row", &read_row); transcript.absorb(b"write_row", &write_row); + transcript.absorb(b"alpha", &fingerprint_alpha); transcript.absorb(b"gamma", &fingerprint_gamma); let init_values: Vec<::Scalar> = @@ -561,19 +563,19 @@ where comm_final_value: <::CE as CommitmentEngineTrait>::Commitment, comm_final_counter: <::CE as CommitmentEngineTrait>::Commitment, fingerprint_intermediate_gamma: G::Scalar, - fingerprint_gamma: G::Scalar, + challenges: (G::Scalar, G::Scalar), ) -> Result<(), NovaError> where G: Group::Scalar>, G2: Group::Scalar>, { // verify fingerprint challenge + let (fingerprint_alpha, fingerprint_gamma) = challenges; + let ro_consts = <::RO as ROTrait<::Base, ::Scalar>>::Constants::default(); - // final_value and final_counter - - let mut hasher = ::RO::new(ro_consts, 7); + let mut hasher = ::RO::new(ro_consts.clone(), 7); let fingerprint_intermediate_gamma: G2::Scalar = scalar_as_base::(fingerprint_intermediate_gamma); hasher.absorb(fingerprint_intermediate_gamma); @@ -582,11 +584,21 @@ where let computed_gamma = hasher.squeeze(NUM_CHALLENGE_BITS); if fingerprint_gamma != computed_gamma { println!( - "fingerprint_gamma {:?} != computed_gamma {:?},,,fingerprint_intermediate_gamma", + "fingerprint_gamma {:?} != computed_gamma {:?}", fingerprint_gamma, computed_gamma ); return Err(NovaError::InvalidMultisetProof); } + let mut hasher = ::RO::new(ro_consts, 1); + hasher.absorb(scalar_as_base::(computed_gamma)); + let computed_alpha = hasher.squeeze(NUM_CHALLENGE_BITS); + if fingerprint_alpha != computed_alpha { + println!( + "fingerprint_alpha {:?} != computed_alpha {:?}", + fingerprint_alpha, computed_alpha + ); + return Err(NovaError::InvalidMultisetProof); + } Ok(()) } @@ -595,21 +607,21 @@ where &self, vk: &VerifierKey, fingerprint_intermediate_gamma: G::Scalar, - fingerprint_gamma: G::Scalar, + challenges: (G::Scalar, G::Scalar), ) -> Result<(), NovaError> where G: Group::Scalar>, G2: Group::Scalar>, { + let (fingerprint_alpha, fingerprint_gamma) = challenges; let comm_final_value = Commitment::::decompress(&self.comm_final_value)?; let comm_final_counter = Commitment::::decompress(&self.comm_final_counter)?; - // TODO enable verify challenge Self::verify_challenge::( comm_final_value, comm_final_counter, fingerprint_intermediate_gamma, - fingerprint_gamma, + challenges, )?; let mut transcript = G::TE::new(b"LookupSNARK"); @@ -619,6 +631,7 @@ where transcript.absorb(b"vk", &vk.digest()); transcript.absorb(b"read_row", &self.read_row); transcript.absorb(b"write_row", &self.write_row); + transcript.absorb(b"alpha", &fingerprint_alpha); transcript.absorb(b"gamma", &fingerprint_gamma); // add commitment into the challenge @@ -629,7 +642,7 @@ where // hash function let gamma_square = fingerprint_gamma * fingerprint_gamma; let hash_func = |addr: &G::Scalar, val: &G::Scalar, ts: &G::Scalar| -> G::Scalar { - fingerprint_gamma - (*ts * gamma_square + *val * fingerprint_gamma + *addr) + fingerprint_alpha - (*ts * gamma_square + *val * fingerprint_gamma + *addr) }; // check claimed_prod_init_row * write_row - claimed_prod_audit_row * read_row = 0