Browse Source

Bump to arkworks-0.4.0 (#126)

* Bump to arkworks-0.4.0

* Replace remaining usages of `msm_bigint` with `msm_unchecked`

Using `msm_unchecked` instead of `msm_bigint` allows to delete the BigInt conversion code by letting the library take care of it.
main
Ivan Mikushin 1 year ago
committed by GitHub
parent
commit
56b1085c11
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 444 additions and 484 deletions
  1. +6
    -6
      arithmetic/Cargo.toml
  2. +23
    -53
      arithmetic/src/univariate_polynomial.rs
  3. +2
    -3
      arithmetic/src/virtual_polynomial.rs
  4. +6
    -6
      hyperplonk/Cargo.toml
  5. +6
    -6
      hyperplonk/benches/bench.rs
  6. +5
    -5
      hyperplonk/src/lib.rs
  7. +1
    -1
      hyperplonk/src/mock.rs
  8. +81
    -59
      hyperplonk/src/snark.rs
  9. +7
    -7
      hyperplonk/src/structs.rs
  10. +7
    -7
      hyperplonk/src/utils.rs
  11. +6
    -6
      subroutines/Cargo.toml
  12. +13
    -13
      subroutines/benches/iop_bench.rs
  13. +9
    -12
      subroutines/src/pcs/mod.rs
  14. +28
    -30
      subroutines/src/pcs/multilinear_kzg/batching.rs
  15. +47
    -64
      subroutines/src/pcs/multilinear_kzg/mod.rs
  16. +28
    -38
      subroutines/src/pcs/multilinear_kzg/srs.rs
  17. +3
    -3
      subroutines/src/pcs/structs.rs
  18. +41
    -51
      subroutines/src/pcs/univariate_kzg/mod.rs
  19. +20
    -32
      subroutines/src/pcs/univariate_kzg/srs.rs
  20. +37
    -31
      subroutines/src/poly_iop/perm_check/mod.rs
  21. +60
    -43
      subroutines/src/poly_iop/prod_check/mod.rs
  22. +1
    -1
      subroutines/src/poly_iop/structs.rs
  23. +1
    -1
      subroutines/src/poly_iop/sum_check/verifier.rs
  24. +2
    -2
      subroutines/src/poly_iop/utils.rs
  25. +3
    -3
      transcript/Cargo.toml
  26. +1
    -1
      transcript/src/lib.rs

+ 6
- 6
arithmetic/Cargo.toml

@ -5,17 +5,17 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
ark-bls12-381 = { version = "0.3.0", default-features = false, features = [ "curve" ] }
ark-ff = { version = "^0.3.0", default-features = false }
ark-poly = { version = "^0.3.0", default-features = false }
ark-serialize = { version = "^0.3.0", default-features = false }
ark-std = { version = "^0.3.0", default-features = false }
ark-bls12-381 = { version = "0.4.0", default-features = false, features = [ "curve" ] }
ark-ff = { version = "^0.4.0", default-features = false }
ark-poly = { version = "^0.4.0", default-features = false }
ark-serialize = { version = "^0.4.0", default-features = false }
ark-std = { version = "^0.4.0", default-features = false }
displaydoc = { version = "0.2.3", default-features = false } displaydoc = { version = "0.2.3", default-features = false }
rand_chacha = { version = "0.3.0", default-features = false } rand_chacha = { version = "0.3.0", default-features = false }
rayon = { version = "1.5.2", default-features = false, optional = true } rayon = { version = "1.5.2", default-features = false, optional = true }
[dev-dependencies] [dev-dependencies]
ark-ec = { version = "^0.3.0", default-features = false }
ark-ec = { version = "^0.4.0", default-features = false }
criterion = "0.4.0" criterion = "0.4.0"
[features] [features]

+ 23
- 53
arithmetic/src/univariate_polynomial.rs

@ -81,8 +81,8 @@ pub fn get_uni_domain(
mod test { mod test {
use super::*; use super::*;
use ark_bls12_381::Fr; use ark_bls12_381::Fr;
use ark_ff::{field_new, One};
use ark_poly::UVPolynomial;
use ark_ff::{MontFp, One};
use ark_poly::DenseUVPolynomial;
#[test] #[test]
fn test_build_l_with_suffix() -> Result<(), ArithErrors> { fn test_build_l_with_suffix() -> Result<(), ArithErrors> {
@ -121,7 +121,7 @@ mod test {
{ {
let domain = get_uni_domain::<Fr>(3)?; let domain = get_uni_domain::<Fr>(3)?;
let l = build_l(&[point1, point2, point3], &domain, true)?;
let l = build_l::<Fr>(&[point1, point2, point3], &domain, true)?;
// sage: q = 52435875175126190479447740508185965837690552500527637822603658699938581184513 // sage: q = 52435875175126190479447740508185965837690552500527637822603658699938581184513
// sage: P.<x> = PolynomialRing(Zmod(q)) // sage: P.<x> = PolynomialRing(Zmod(q))
@ -142,20 +142,16 @@ mod test {
// 13108968793781547619861935127046491459422638125131909455650914674984645296128*x + // 13108968793781547619861935127046491459422638125131909455650914674984645296128*x +
// 39326906381344642859585805381139474378267914375395728366952744024953935888385 // 39326906381344642859585805381139474378267914375395728366952744024953935888385
let l0 = DensePolynomial::from_coefficients_vec(vec![ let l0 = DensePolynomial::from_coefficients_vec(vec![
field_new!(
Fr,
MontFp!(
"39326906381344642859585805381139474378267914375395728366952744024953935888385" "39326906381344642859585805381139474378267914375395728366952744024953935888385"
), ),
field_new!(
Fr,
MontFp!(
"13108968793781547619861935127046491459422638125131909455650914674984645296128" "13108968793781547619861935127046491459422638125131909455650914674984645296128"
), ),
field_new!(
Fr,
MontFp!(
"39326906381344642859585805381139474378267914375395728366952744024953935888385" "39326906381344642859585805381139474378267914375395728366952744024953935888385"
), ),
field_new!(
Fr,
MontFp!(
"13108968793781547619861935127046491459422638125131909455650914674984645296128" "13108968793781547619861935127046491459422638125131909455650914674984645296128"
), ),
]); ]);
@ -170,22 +166,16 @@ mod test {
// 52435875175126190478581454301667552757996485117855702128036095582747240693761*x + // 52435875175126190478581454301667552757996485117855702128036095582747240693761*x +
// 39326906381344642859585805381139474378267914375395728366952744024953935888385 // 39326906381344642859585805381139474378267914375395728366952744024953935888385
let l1 = DensePolynomial::from_coefficients_vec(vec![ let l1 = DensePolynomial::from_coefficients_vec(vec![
field_new!(
Fr,
MontFp!(
"39326906381344642859585805381139474378267914375395728366952744024953935888385" "39326906381344642859585805381139474378267914375395728366952744024953935888385"
), ),
field_new!(
Fr,
MontFp!(
"52435875175126190478581454301667552757996485117855702128036095582747240693761" "52435875175126190478581454301667552757996485117855702128036095582747240693761"
), ),
field_new!(
Fr,
MontFp!(
"13108968793781547619861935127046491459422638125131909455650914674984645296128" "13108968793781547619861935127046491459422638125131909455650914674984645296128"
), ),
field_new!(
Fr,
"866286206518413079694067382671935694567563117191340490752"
),
MontFp!("866286206518413079694067382671935694567563117191340490752"),
]); ]);
// ======================== // ========================
@ -198,22 +188,16 @@ mod test {
// 52435875175126190476848881888630726598608350352511830738900969348364559712256*x + // 52435875175126190476848881888630726598608350352511830738900969348364559712256*x +
// 39326906381344642859585805381139474378267914375395728366952744024953935888387 // 39326906381344642859585805381139474378267914375395728366952744024953935888387
let l2 = DensePolynomial::from_coefficients_vec(vec![ let l2 = DensePolynomial::from_coefficients_vec(vec![
field_new!(
Fr,
MontFp!(
"39326906381344642859585805381139474378267914375395728366952744024953935888387" "39326906381344642859585805381139474378267914375395728366952744024953935888387"
), ),
field_new!(
Fr,
MontFp!(
"52435875175126190476848881888630726598608350352511830738900969348364559712256" "52435875175126190476848881888630726598608350352511830738900969348364559712256"
), ),
field_new!(
Fr,
MontFp!(
"13108968793781547619861935127046491459422638125131909455650914674984645296129" "13108968793781547619861935127046491459422638125131909455650914674984645296129"
), ),
field_new!(
Fr,
"2598858619555239239082202148015807083702689351574021472255"
),
MontFp!("2598858619555239239082202148015807083702689351574021472255"),
]); ]);
// ======================== // ========================
@ -227,15 +211,11 @@ mod test {
// 3 // 3
let l3 = DensePolynomial::from_coefficients_vec(vec![ let l3 = DensePolynomial::from_coefficients_vec(vec![
Fr::from(3u64), Fr::from(3u64),
field_new!(
Fr,
MontFp!(
"52435875175126190475982595682112313518914282969839895044333406231173219221504" "52435875175126190475982595682112313518914282969839895044333406231173219221504"
), ),
Fr::one(), Fr::one(),
field_new!(
Fr,
"3465144826073652318776269530687742778270252468765361963007"
),
MontFp!("3465144826073652318776269530687742778270252468765361963007"),
]); ]);
assert_eq!(l0, l[0], "l0 not equal"); assert_eq!(l0, l[0], "l0 not equal");
@ -298,22 +278,16 @@ mod test {
// 52435875175126190476848881888630726598608350352511830738900969348364559712256*x + // 52435875175126190476848881888630726598608350352511830738900969348364559712256*x +
// 39326906381344642859585805381139474378267914375395728366952744024953935888387 // 39326906381344642859585805381139474378267914375395728366952744024953935888387
let l0 = DensePolynomial::from_coefficients_vec(vec![ let l0 = DensePolynomial::from_coefficients_vec(vec![
field_new!(
Fr,
MontFp!(
"39326906381344642859585805381139474378267914375395728366952744024953935888387" "39326906381344642859585805381139474378267914375395728366952744024953935888387"
), ),
field_new!(
Fr,
MontFp!(
"52435875175126190476848881888630726598608350352511830738900969348364559712256" "52435875175126190476848881888630726598608350352511830738900969348364559712256"
), ),
field_new!(
Fr,
MontFp!(
"13108968793781547619861935127046491459422638125131909455650914674984645296129" "13108968793781547619861935127046491459422638125131909455650914674984645296129"
), ),
field_new!(
Fr,
"2598858619555239239082202148015807083702689351574021472255"
),
MontFp!("2598858619555239239082202148015807083702689351574021472255"),
]); ]);
// ======================== // ========================
@ -327,15 +301,11 @@ mod test {
// 3 // 3
let l1 = DensePolynomial::from_coefficients_vec(vec![ let l1 = DensePolynomial::from_coefficients_vec(vec![
Fr::from(3u64), Fr::from(3u64),
field_new!(
Fr,
MontFp!(
"52435875175126190475982595682112313518914282969839895044333406231173219221504" "52435875175126190475982595682112313518914282969839895044333406231173219221504"
), ),
Fr::one(), Fr::one(),
field_new!(
Fr,
"3465144826073652318776269530687742778270252468765361963007"
),
MontFp!("3465144826073652318776269530687742778270252468765361963007"),
]); ]);
assert_eq!(l0, l[0], "l0 not equal"); assert_eq!(l0, l[0], "l0 not equal");

+ 2
- 3
arithmetic/src/virtual_polynomial.rs

@ -10,7 +10,7 @@
use crate::{errors::ArithErrors, multilinear_polynomial::random_zero_mle_list, random_mle_list}; use crate::{errors::ArithErrors, multilinear_polynomial::random_zero_mle_list, random_mle_list};
use ark_ff::PrimeField; use ark_ff::PrimeField;
use ark_poly::{DenseMultilinearExtension, MultilinearExtension}; use ark_poly::{DenseMultilinearExtension, MultilinearExtension};
use ark_serialize::{CanonicalSerialize, SerializationError, Write};
use ark_serialize::CanonicalSerialize;
use ark_std::{ use ark_std::{
end_timer, end_timer,
rand::{Rng, RngCore}, rand::{Rng, RngCore},
@ -546,7 +546,6 @@ mod test {
let mle = DenseMultilinearExtension::from_evaluations_vec(num_var, eval); let mle = DenseMultilinearExtension::from_evaluations_vec(num_var, eval);
let res = Arc::new(mle);
res
Arc::new(mle)
} }
} }

+ 6
- 6
hyperplonk/Cargo.toml

@ -6,11 +6,11 @@ edition = "2021"
[dependencies] [dependencies]
arithmetic = { path = "../arithmetic" } arithmetic = { path = "../arithmetic" }
ark-ec = { version = "^0.3.0", default-features = false }
ark-ff = { version = "^0.3.0", default-features = false }
ark-poly = { version = "^0.3.0", default-features = false }
ark-serialize = { version = "^0.3.0", default-features = false, features = [ "derive" ] }
ark-std = { version = "^0.3.0", default-features = false }
ark-ec = { version = "^0.4.0", default-features = false }
ark-ff = { version = "^0.4.0", default-features = false }
ark-poly = { version = "^0.4.0", default-features = false }
ark-serialize = { version = "^0.4.0", default-features = false, features = [ "derive" ] }
ark-std = { version = "^0.4.0", default-features = false }
displaydoc = { version = "0.2.3", default-features = false } displaydoc = { version = "0.2.3", default-features = false }
rayon = { version = "1.5.2", default-features = false, optional = true } rayon = { version = "1.5.2", default-features = false, optional = true }
subroutines = { path = "../subroutines" } subroutines = { path = "../subroutines" }
@ -18,7 +18,7 @@ transcript = { path = "../transcript" }
util = { path = "../util" } util = { path = "../util" }
[dev-dependencies] [dev-dependencies]
ark-bls12-381 = { version = "0.3.0", default-features = false, features = [ "curve" ] }
ark-bls12-381 = { version = "0.4.0", default-features = false, features = [ "curve" ] }
# Benchmarks # Benchmarks
[[bench]] [[bench]]
name = "hyperplonk-benches" name = "hyperplonk-benches"

+ 6
- 6
hyperplonk/benches/bench.rs

@ -58,7 +58,7 @@ fn main() -> Result<(), HyperPlonkErrors> {
fn read_srs() -> Result<MultilinearUniversalParams<Bls12_381>, io::Error> { fn read_srs() -> Result<MultilinearUniversalParams<Bls12_381>, io::Error> {
let mut f = File::open("srs.params")?; let mut f = File::open("srs.params")?;
Ok(MultilinearUniversalParams::<Bls12_381>::deserialize_unchecked(&mut f).unwrap())
Ok(MultilinearUniversalParams::<Bls12_381>::deserialize_compressed_unchecked(&mut f).unwrap())
} }
fn write_srs(pcs_srs: &MultilinearUniversalParams<Bls12_381>) { fn write_srs(pcs_srs: &MultilinearUniversalParams<Bls12_381>) {
@ -74,7 +74,7 @@ fn bench_vanilla_plonk(
let mut file = File::create(filename).unwrap(); let mut file = File::create(filename).unwrap();
for nv in MIN_NUM_VARS..=MAX_NUM_VARS { for nv in MIN_NUM_VARS..=MAX_NUM_VARS {
let vanilla_gate = CustomizedGates::vanilla_plonk_gate(); let vanilla_gate = CustomizedGates::vanilla_plonk_gate();
bench_mock_circuit_zkp_helper(&mut file, nv, &vanilla_gate, &pcs_srs)?;
bench_mock_circuit_zkp_helper(&mut file, nv, &vanilla_gate, pcs_srs)?;
} }
Ok(()) Ok(())
@ -88,7 +88,7 @@ fn bench_jellyfish_plonk(
let mut file = File::create(filename).unwrap(); let mut file = File::create(filename).unwrap();
for nv in MIN_NUM_VARS..=MAX_NUM_VARS { for nv in MIN_NUM_VARS..=MAX_NUM_VARS {
let jf_gate = CustomizedGates::jellyfish_turbo_plonk_gate(); let jf_gate = CustomizedGates::jellyfish_turbo_plonk_gate();
bench_mock_circuit_zkp_helper(&mut file, nv, &jf_gate, &pcs_srs)?;
bench_mock_circuit_zkp_helper(&mut file, nv, &jf_gate, pcs_srs)?;
} }
Ok(()) Ok(())
@ -103,7 +103,7 @@ fn bench_high_degree_plonk(
let mut file = File::create(filename).unwrap(); let mut file = File::create(filename).unwrap();
println!("custom gate of degree {}", degree); println!("custom gate of degree {}", degree);
let vanilla_gate = CustomizedGates::mock_gate(2, degree); let vanilla_gate = CustomizedGates::mock_gate(2, degree);
bench_mock_circuit_zkp_helper(&mut file, HIGH_DEGREE_TEST_NV, &vanilla_gate, &pcs_srs)?;
bench_mock_circuit_zkp_helper(&mut file, HIGH_DEGREE_TEST_NV, &vanilla_gate, pcs_srs)?;
Ok(()) Ok(())
} }
@ -133,7 +133,7 @@ fn bench_mock_circuit_zkp_helper(
let (_pk, _vk) = <PolyIOP<Fr> as HyperPlonkSNARK< let (_pk, _vk) = <PolyIOP<Fr> as HyperPlonkSNARK<
Bls12_381, Bls12_381,
MultilinearKzgPCS<Bls12_381>, MultilinearKzgPCS<Bls12_381>,
>>::preprocess(&index, &pcs_srs)?;
>>::preprocess(&index, pcs_srs)?;
} }
println!( println!(
"key extraction for {} variables: {} us", "key extraction for {} variables: {} us",
@ -142,7 +142,7 @@ fn bench_mock_circuit_zkp_helper(
); );
let (pk, vk) = let (pk, vk) =
<PolyIOP<Fr> as HyperPlonkSNARK<Bls12_381, MultilinearKzgPCS<Bls12_381>>>::preprocess( <PolyIOP<Fr> as HyperPlonkSNARK<Bls12_381, MultilinearKzgPCS<Bls12_381>>>::preprocess(
&index, &pcs_srs,
&index, pcs_srs,
)?; )?;
//========================================================== //==========================================================
// generate a proof // generate a proof

+ 5
- 5
hyperplonk/src/lib.rs

@ -6,7 +6,7 @@
//! Main module for the HyperPlonk SNARK. //! Main module for the HyperPlonk SNARK.
use ark_ec::PairingEngine;
use ark_ec::pairing::Pairing;
use errors::HyperPlonkErrors; use errors::HyperPlonkErrors;
use subroutines::{pcs::prelude::PolynomialCommitmentScheme, poly_iop::prelude::PermutationCheck}; use subroutines::{pcs::prelude::PolynomialCommitmentScheme, poly_iop::prelude::PermutationCheck};
use witness::WitnessColumn; use witness::WitnessColumn;
@ -25,7 +25,7 @@ mod witness;
/// A HyperPlonk is derived from ZeroChecks and PermutationChecks. /// A HyperPlonk is derived from ZeroChecks and PermutationChecks.
pub trait HyperPlonkSNARK<E, PCS>: PermutationCheck<E, PCS> pub trait HyperPlonkSNARK<E, PCS>: PermutationCheck<E, PCS>
where where
E: PairingEngine,
E: Pairing,
PCS: PolynomialCommitmentScheme<E>, PCS: PolynomialCommitmentScheme<E>,
{ {
type Index; type Index;
@ -58,8 +58,8 @@ where
/// - The HyperPlonk SNARK proof. /// - The HyperPlonk SNARK proof.
fn prove( fn prove(
pk: &Self::ProvingKey, pk: &Self::ProvingKey,
pub_input: &[E::Fr],
witnesses: &[WitnessColumn<E::Fr>],
pub_input: &[E::ScalarField],
witnesses: &[WitnessColumn<E::ScalarField>],
) -> Result<Self::Proof, HyperPlonkErrors>; ) -> Result<Self::Proof, HyperPlonkErrors>;
/// Verify the HyperPlonk proof. /// Verify the HyperPlonk proof.
@ -72,7 +72,7 @@ where
/// - Return a boolean on whether the verification is successful /// - Return a boolean on whether the verification is successful
fn verify( fn verify(
vk: &Self::VerifyingKey, vk: &Self::VerifyingKey,
pub_input: &[E::Fr],
pub_input: &[E::ScalarField],
proof: &Self::Proof, proof: &Self::Proof,
) -> Result<bool, HyperPlonkErrors>; ) -> Result<bool, HyperPlonkErrors>;
} }

+ 1
- 1
hyperplonk/src/mock.rs

@ -193,7 +193,7 @@ mod test {
// generate pk and vks // generate pk and vks
let (pk, vk) = let (pk, vk) =
<PolyIOP<Fr> as HyperPlonkSNARK<Bls12_381, MultilinearKzgPCS<Bls12_381>>>::preprocess( <PolyIOP<Fr> as HyperPlonkSNARK<Bls12_381, MultilinearKzgPCS<Bls12_381>>>::preprocess(
&index, &pcs_srs,
&index, pcs_srs,
)?; )?;
// generate a proof and verify // generate a proof and verify
let proof = let proof =

+ 81
- 59
hyperplonk/src/snark.rs

@ -12,7 +12,7 @@ use crate::{
HyperPlonkSNARK, HyperPlonkSNARK,
}; };
use arithmetic::{evaluate_opt, gen_eval_point, VPAuxInfo}; use arithmetic::{evaluate_opt, gen_eval_point, VPAuxInfo};
use ark_ec::PairingEngine;
use ark_ec::pairing::Pairing;
use ark_poly::DenseMultilinearExtension; use ark_poly::DenseMultilinearExtension;
use ark_std::{end_timer, log2, start_timer, One, Zero}; use ark_std::{end_timer, log2, start_timer, One, Zero};
use rayon::iter::IntoParallelRefIterator; use rayon::iter::IntoParallelRefIterator;
@ -29,22 +29,22 @@ use subroutines::{
}; };
use transcript::IOPTranscript; use transcript::IOPTranscript;
impl<E, PCS> HyperPlonkSNARK<E, PCS> for PolyIOP<E::Fr>
impl<E, PCS> HyperPlonkSNARK<E, PCS> for PolyIOP<E::ScalarField>
where where
E: PairingEngine,
E: Pairing,
// Ideally we want to access polynomial as PCS::Polynomial, instead of instantiating it here. // Ideally we want to access polynomial as PCS::Polynomial, instead of instantiating it here.
// But since PCS::Polynomial can be both univariate or multivariate in our implementation // But since PCS::Polynomial can be both univariate or multivariate in our implementation
// we cannot bound PCS::Polynomial with a property trait bound. // we cannot bound PCS::Polynomial with a property trait bound.
PCS: PolynomialCommitmentScheme< PCS: PolynomialCommitmentScheme<
E, E,
Polynomial = Arc<DenseMultilinearExtension<E::Fr>>,
Point = Vec<E::Fr>,
Evaluation = E::Fr,
Polynomial = Arc<DenseMultilinearExtension<E::ScalarField>>,
Point = Vec<E::ScalarField>,
Evaluation = E::ScalarField,
Commitment = Commitment<E>, Commitment = Commitment<E>,
BatchProof = BatchProof<E, PCS>, BatchProof = BatchProof<E, PCS>,
>, >,
{ {
type Index = HyperPlonkIndex<E::Fr>;
type Index = HyperPlonkIndex<E::ScalarField>;
type ProvingKey = HyperPlonkProvingKey<E, PCS>; type ProvingKey = HyperPlonkProvingKey<E, PCS>;
type VerifyingKey = HyperPlonkVerifyingKey<E, PCS>; type VerifyingKey = HyperPlonkVerifyingKey<E, PCS>;
type Proof = HyperPlonkProof<E, Self, PCS>; type Proof = HyperPlonkProof<E, Self, PCS>;
@ -75,7 +75,7 @@ where
} }
// build selector oracles and commit to it // build selector oracles and commit to it
let selector_oracles: Vec<Arc<DenseMultilinearExtension<E::Fr>>> = index
let selector_oracles: Vec<Arc<DenseMultilinearExtension<E::ScalarField>>> = index
.selectors .selectors
.iter() .iter()
.map(|s| Arc::new(DenseMultilinearExtension::from(s))) .map(|s| Arc::new(DenseMultilinearExtension::from(s)))
@ -153,11 +153,11 @@ where
/// - 5. deferred batch opening /// - 5. deferred batch opening
fn prove( fn prove(
pk: &Self::ProvingKey, pk: &Self::ProvingKey,
pub_input: &[E::Fr],
witnesses: &[WitnessColumn<E::Fr>],
pub_input: &[E::ScalarField],
witnesses: &[WitnessColumn<E::ScalarField>],
) -> Result<Self::Proof, HyperPlonkErrors> { ) -> Result<Self::Proof, HyperPlonkErrors> {
let start = start_timer!(|| "hyperplonk proving"); let start = start_timer!(|| "hyperplonk proving");
let mut transcript = IOPTranscript::<E::Fr>::new(b"hyperplonk");
let mut transcript = IOPTranscript::<E::ScalarField>::new(b"hyperplonk");
prover_sanity_check(&pk.params, pub_input, witnesses)?; prover_sanity_check(&pk.params, pub_input, witnesses)?;
@ -177,7 +177,7 @@ where
// ======================================================================= // =======================================================================
let step = start_timer!(|| "commit witnesses"); let step = start_timer!(|| "commit witnesses");
let witness_polys: Vec<Arc<DenseMultilinearExtension<E::Fr>>> = witnesses
let witness_polys: Vec<Arc<DenseMultilinearExtension<E::ScalarField>>> = witnesses
.iter() .iter()
.map(|w| Arc::new(DenseMultilinearExtension::from(w))) .map(|w| Arc::new(DenseMultilinearExtension::from(w)))
.collect(); .collect();
@ -212,7 +212,7 @@ where
&witness_polys, &witness_polys,
)?; )?;
let zero_check_proof = <Self as ZeroCheck<E::Fr>>::prove(&fx, &mut transcript)?;
let zero_check_proof = <Self as ZeroCheck<E::ScalarField>>::prove(&fx, &mut transcript)?;
end_timer!(step); end_timer!(step);
// ======================================================================= // =======================================================================
// 3. Run permutation check on `\{w_i(x)\}` and `permutation_oracle`, and // 3. Run permutation check on `\{w_i(x)\}` and `permutation_oracle`, and
@ -259,12 +259,20 @@ where
let step = start_timer!(|| "opening and evaluations"); let step = start_timer!(|| "opening and evaluations");
// (perm_check_point[2..n], 0) // (perm_check_point[2..n], 0)
let perm_check_point_0 = [&[E::Fr::zero()], &perm_check_point[0..num_vars - 1]].concat();
let perm_check_point_0 = [
&[E::ScalarField::zero()],
&perm_check_point[0..num_vars - 1],
]
.concat();
// (perm_check_point[2..n], 1) // (perm_check_point[2..n], 1)
let perm_check_point_1 = [&[E::Fr::one()], &perm_check_point[0..num_vars - 1]].concat();
let perm_check_point_1 =
[&[E::ScalarField::one()], &perm_check_point[0..num_vars - 1]].concat();
// (1, ..., 1, 0) // (1, ..., 1, 0)
let prod_final_query_point =
[vec![E::Fr::zero()], vec![E::Fr::one(); num_vars - 1]].concat();
let prod_final_query_point = [
vec![E::ScalarField::zero()],
vec![E::ScalarField::one(); num_vars - 1],
]
.concat();
// prod(x)'s points // prod(x)'s points
pcs_acc.insert_poly_and_points(&prod_x, &perm_check_proof.prod_x_comm, perm_check_point); pcs_acc.insert_poly_and_points(&prod_x, &perm_check_proof.prod_x_comm, perm_check_point);
@ -319,7 +327,7 @@ where
// - pi_poly(r_pi) where r_pi is sampled from transcript // - pi_poly(r_pi) where r_pi is sampled from transcript
let r_pi = transcript.get_and_append_challenge_vectors(b"r_pi", ell)?; let r_pi = transcript.get_and_append_challenge_vectors(b"r_pi", ell)?;
// padded with zeros // padded with zeros
let r_pi_padded = [r_pi, vec![E::Fr::zero(); num_vars - ell]].concat();
let r_pi_padded = [r_pi, vec![E::ScalarField::zero(); num_vars - ell]].concat();
// Evaluate witness_poly[0] at r_pi||0s which is equal to public_input evaluated // Evaluate witness_poly[0] at r_pi||0s which is equal to public_input evaluated
// at r_pi. Assumes that public_input is a power of 2 // at r_pi. Assumes that public_input is a power of 2
pcs_acc.insert_poly_and_points(&witness_polys[0], &witness_commits[0], &r_pi_padded); pcs_acc.insert_poly_and_points(&witness_polys[0], &witness_commits[0], &r_pi_padded);
@ -379,12 +387,12 @@ where
/// - public input consistency checks /// - public input consistency checks
fn verify( fn verify(
vk: &Self::VerifyingKey, vk: &Self::VerifyingKey,
pub_input: &[E::Fr],
pub_input: &[E::ScalarField],
proof: &Self::Proof, proof: &Self::Proof,
) -> Result<bool, HyperPlonkErrors> { ) -> Result<bool, HyperPlonkErrors> {
let start = start_timer!(|| "hyperplonk verification"); let start = start_timer!(|| "hyperplonk verification");
let mut transcript = IOPTranscript::<E::Fr>::new(b"hyperplonk");
let mut transcript = IOPTranscript::<E::ScalarField>::new(b"hyperplonk");
let num_selectors = vk.params.num_selector_columns(); let num_selectors = vk.params.num_selector_columns();
let num_witnesses = vk.params.num_witness_columns(); let num_witnesses = vk.params.num_witness_columns();
@ -429,7 +437,7 @@ where
// ======================================================================= // =======================================================================
let step = start_timer!(|| "verify zero check"); let step = start_timer!(|| "verify zero check");
// Zero check and perm check have different AuxInfo // Zero check and perm check have different AuxInfo
let zero_check_aux_info = VPAuxInfo::<E::Fr> {
let zero_check_aux_info = VPAuxInfo::<E::ScalarField> {
max_degree: vk.params.gate_func.degree(), max_degree: vk.params.gate_func.degree(),
num_variables: num_vars, num_variables: num_vars,
phantom: PhantomData::default(), phantom: PhantomData::default(),
@ -439,7 +447,7 @@ where
transcript.append_serializable_element(b"w", w_com)?; transcript.append_serializable_element(b"w", w_com)?;
} }
let zero_check_sub_claim = <Self as ZeroCheck<E::Fr>>::verify(
let zero_check_sub_claim = <Self as ZeroCheck<E::ScalarField>>::verify(
&proof.zero_check_proof, &proof.zero_check_proof,
&zero_check_aux_info, &zero_check_aux_info,
&mut transcript, &mut transcript,
@ -462,7 +470,7 @@ where
let step = start_timer!(|| "verify permutation check"); let step = start_timer!(|| "verify permutation check");
// Zero check and perm check have different AuxInfo // Zero check and perm check have different AuxInfo
let perm_check_aux_info = VPAuxInfo::<E::Fr> {
let perm_check_aux_info = VPAuxInfo::<E::ScalarField> {
// Prod(x) has a max degree of witnesses.len() + 1 // Prod(x) has a max degree of witnesses.len() + 1
max_degree: proof.witness_commits.len() + 1, max_degree: proof.witness_commits.len() + 1,
num_variables: num_vars, num_variables: num_vars,
@ -522,10 +530,18 @@ where
let mut comms = vec![]; let mut comms = vec![];
let mut points = vec![]; let mut points = vec![];
let perm_check_point_0 = [&[E::Fr::zero()], &perm_check_point[0..num_vars - 1]].concat();
let perm_check_point_1 = [&[E::Fr::one()], &perm_check_point[0..num_vars - 1]].concat();
let prod_final_query_point =
[vec![E::Fr::zero()], vec![E::Fr::one(); num_vars - 1]].concat();
let perm_check_point_0 = [
&[E::ScalarField::zero()],
&perm_check_point[0..num_vars - 1],
]
.concat();
let perm_check_point_1 =
[&[E::ScalarField::one()], &perm_check_point[0..num_vars - 1]].concat();
let prod_final_query_point = [
vec![E::ScalarField::zero()],
vec![E::ScalarField::one(); num_vars - 1],
]
.concat();
// prod(x)'s points // prod(x)'s points
comms.push(proof.perm_check_proof.prod_x_comm); comms.push(proof.perm_check_proof.prod_x_comm);
@ -581,7 +597,7 @@ where
pi_eval, expect_pi_eval, pi_eval, expect_pi_eval,
))); )));
} }
let r_pi_padded = [r_pi, vec![E::Fr::zero(); num_vars - ell]].concat();
let r_pi_padded = [r_pi, vec![E::ScalarField::zero(); num_vars - ell]].concat();
comms.push(proof.witness_commits[0]); comms.push(proof.witness_commits[0]);
points.push(r_pi_padded); points.push(r_pi_padded);
@ -638,7 +654,7 @@ mod tests {
test_hyperplonk_helper::<Bls12_381>(gates) test_hyperplonk_helper::<Bls12_381>(gates)
} }
fn test_hyperplonk_helper<E: PairingEngine>(
fn test_hyperplonk_helper<E: Pairing>(
gate_func: CustomizedGates, gate_func: CustomizedGates,
) -> Result<(), HyperPlonkErrors> { ) -> Result<(), HyperPlonkErrors> {
let mut rng = test_rng(); let mut rng = test_rng();
@ -656,7 +672,12 @@ mod tests {
gate_func, gate_func,
}; };
let permutation = identity_permutation(nv, num_witnesses); let permutation = identity_permutation(nv, num_witnesses);
let q1 = SelectorColumn(vec![E::Fr::one(), E::Fr::one(), E::Fr::one(), E::Fr::one()]);
let q1 = SelectorColumn(vec![
E::ScalarField::one(),
E::ScalarField::one(),
E::ScalarField::one(),
E::ScalarField::one(),
]);
let index = HyperPlonkIndex { let index = HyperPlonkIndex {
params, params,
permutation, permutation,
@ -664,58 +685,59 @@ mod tests {
}; };
// generate pk and vks // generate pk and vks
let (pk, vk) = <PolyIOP<E::Fr> as HyperPlonkSNARK<E, MultilinearKzgPCS<E>>>::preprocess(
&index, &pcs_srs,
)?;
let (pk, vk) =
<PolyIOP<E::ScalarField> as HyperPlonkSNARK<E, MultilinearKzgPCS<E>>>::preprocess(
&index, &pcs_srs,
)?;
// w1 := [0, 1, 2, 3] // w1 := [0, 1, 2, 3]
let w1 = WitnessColumn(vec![ let w1 = WitnessColumn(vec![
E::Fr::zero(),
E::Fr::one(),
E::Fr::from(2u128),
E::Fr::from(3u128),
E::ScalarField::zero(),
E::ScalarField::one(),
E::ScalarField::from(2u128),
E::ScalarField::from(3u128),
]); ]);
// w2 := [0^5, 1^5, 2^5, 3^5] // w2 := [0^5, 1^5, 2^5, 3^5]
let w2 = WitnessColumn(vec![ let w2 = WitnessColumn(vec![
E::Fr::zero(),
E::Fr::one(),
E::Fr::from(32u128),
E::Fr::from(243u128),
E::ScalarField::zero(),
E::ScalarField::one(),
E::ScalarField::from(32u128),
E::ScalarField::from(243u128),
]); ]);
// public input = w1 // public input = w1
let pi = w1.clone(); let pi = w1.clone();
// generate a proof and verify // generate a proof and verify
let proof = <PolyIOP<E::Fr> as HyperPlonkSNARK<E, MultilinearKzgPCS<E>>>::prove(
let proof = <PolyIOP<E::ScalarField> as HyperPlonkSNARK<E, MultilinearKzgPCS<E>>>::prove(
&pk, &pk,
&pi.0, &pi.0,
&[w1.clone(), w2.clone()], &[w1.clone(), w2.clone()],
)?; )?;
let _verify = <PolyIOP<E::Fr> as HyperPlonkSNARK<E, MultilinearKzgPCS<E>>>::verify(
&vk, &pi.0, &proof,
)?;
let _verify =
<PolyIOP<E::ScalarField> as HyperPlonkSNARK<E, MultilinearKzgPCS<E>>>::verify(
&vk, &pi.0, &proof,
)?;
// bad path 1: wrong permutation // bad path 1: wrong permutation
let rand_perm: Vec<E::Fr> = random_permutation(nv, num_witnesses, &mut rng);
let mut bad_index = index.clone();
let rand_perm: Vec<E::ScalarField> = random_permutation(nv, num_witnesses, &mut rng);
let mut bad_index = index;
bad_index.permutation = rand_perm; bad_index.permutation = rand_perm;
// generate pk and vks // generate pk and vks
let (_, bad_vk) = <PolyIOP<E::Fr> as HyperPlonkSNARK<E, MultilinearKzgPCS<E>>>::preprocess(
&bad_index, &pcs_srs,
)?;
assert_eq!(
<PolyIOP<E::Fr> as HyperPlonkSNARK<E, MultilinearKzgPCS<E>>>::verify(
&bad_vk, &pi.0, &proof,
)?,
false
);
let (_, bad_vk) =
<PolyIOP<E::ScalarField> as HyperPlonkSNARK<E, MultilinearKzgPCS<E>>>::preprocess(
&bad_index, &pcs_srs,
)?;
assert!(!<PolyIOP<E::ScalarField> as HyperPlonkSNARK<
E,
MultilinearKzgPCS<E>,
>>::verify(&bad_vk, &pi.0, &proof,)?);
// bad path 2: wrong witness // bad path 2: wrong witness
let mut w1_bad = w1.clone();
w1_bad.0[0] = E::Fr::one();
let mut w1_bad = w1;
w1_bad.0[0] = E::ScalarField::one();
assert!( assert!(
<PolyIOP<E::Fr> as HyperPlonkSNARK<E, MultilinearKzgPCS<E>>>::prove(
<PolyIOP<E::ScalarField> as HyperPlonkSNARK<E, MultilinearKzgPCS<E>>>::prove(
&pk, &pk,
&pi.0, &pi.0,
&[w1_bad, w2], &[w1_bad, w2],

+ 7
- 7
hyperplonk/src/structs.rs

@ -7,7 +7,7 @@
//! Main module for the HyperPlonk PolyIOP. //! Main module for the HyperPlonk PolyIOP.
use crate::{custom_gate::CustomizedGates, prelude::HyperPlonkErrors, selectors::SelectorColumn}; use crate::{custom_gate::CustomizedGates, prelude::HyperPlonkErrors, selectors::SelectorColumn};
use ark_ec::PairingEngine;
use ark_ec::pairing::Pairing;
use ark_ff::PrimeField; use ark_ff::PrimeField;
use ark_poly::DenseMultilinearExtension; use ark_poly::DenseMultilinearExtension;
use ark_std::log2; use ark_std::log2;
@ -25,7 +25,7 @@ use subroutines::{
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct HyperPlonkProof<E, PC, PCS> pub struct HyperPlonkProof<E, PC, PCS>
where where
E: PairingEngine,
E: Pairing,
PC: PermutationCheck<E, PCS>, PC: PermutationCheck<E, PCS>,
PCS: PolynomialCommitmentScheme<E>, PCS: PolynomialCommitmentScheme<E>,
{ {
@ -36,7 +36,7 @@ where
// IOP proofs // IOP proofs
// ======================================================================= // =======================================================================
// the custom gate zerocheck proof // the custom gate zerocheck proof
pub zero_check_proof: <PC as ZeroCheck<E::Fr>>::ZeroCheckProof,
pub zero_check_proof: <PC as ZeroCheck<E::ScalarField>>::ZeroCheckProof,
// the permutation check proof for copy constraints // the permutation check proof for copy constraints
pub perm_check_proof: PC::PermutationProof, pub perm_check_proof: PC::PermutationProof,
} }
@ -128,13 +128,13 @@ impl HyperPlonkIndex {
/// - the commitment to the selectors and permutations /// - the commitment to the selectors and permutations
/// - the parameters for polynomial commitment /// - the parameters for polynomial commitment
#[derive(Clone, Debug, Default, PartialEq)] #[derive(Clone, Debug, Default, PartialEq)]
pub struct HyperPlonkProvingKey<E: PairingEngine, PCS: PolynomialCommitmentScheme<E>> {
pub struct HyperPlonkProvingKey<E: Pairing, PCS: PolynomialCommitmentScheme<E>> {
/// Hyperplonk instance parameters /// Hyperplonk instance parameters
pub params: HyperPlonkParams, pub params: HyperPlonkParams,
/// The preprocessed permutation polynomials /// The preprocessed permutation polynomials
pub permutation_oracles: Vec<Arc<DenseMultilinearExtension<E::Fr>>>,
pub permutation_oracles: Vec<Arc<DenseMultilinearExtension<E::ScalarField>>>,
/// The preprocessed selector polynomials /// The preprocessed selector polynomials
pub selector_oracles: Vec<Arc<DenseMultilinearExtension<E::Fr>>>,
pub selector_oracles: Vec<Arc<DenseMultilinearExtension<E::ScalarField>>>,
/// Commitments to the preprocessed selector polynomials /// Commitments to the preprocessed selector polynomials
pub selector_commitments: Vec<PCS::Commitment>, pub selector_commitments: Vec<PCS::Commitment>,
/// Commitments to the preprocessed permutation polynomials /// Commitments to the preprocessed permutation polynomials
@ -148,7 +148,7 @@ pub struct HyperPlonkProvingKey
/// - the commitments to the preprocessed polynomials output by the indexer /// - the commitments to the preprocessed polynomials output by the indexer
/// - the parameters for polynomial commitment /// - the parameters for polynomial commitment
#[derive(Clone, Debug, Default, PartialEq)] #[derive(Clone, Debug, Default, PartialEq)]
pub struct HyperPlonkVerifyingKey<E: PairingEngine, PCS: PolynomialCommitmentScheme<E>> {
pub struct HyperPlonkVerifyingKey<E: Pairing, PCS: PolynomialCommitmentScheme<E>> {
/// Hyperplonk instance parameters /// Hyperplonk instance parameters
pub params: HyperPlonkParams, pub params: HyperPlonkParams,
/// The parameters for PCS commitment /// The parameters for PCS commitment

+ 7
- 7
hyperplonk/src/utils.rs

@ -9,7 +9,7 @@ use crate::{
witness::WitnessColumn, witness::WitnessColumn,
}; };
use arithmetic::{evaluate_opt, VirtualPolynomial}; use arithmetic::{evaluate_opt, VirtualPolynomial};
use ark_ec::PairingEngine;
use ark_ec::pairing::Pairing;
use ark_ff::PrimeField; use ark_ff::PrimeField;
use ark_poly::DenseMultilinearExtension; use ark_poly::DenseMultilinearExtension;
use std::{borrow::Borrow, sync::Arc}; use std::{borrow::Borrow, sync::Arc};
@ -19,7 +19,7 @@ use transcript::IOPTranscript;
/// An accumulator structure that holds a polynomial and /// An accumulator structure that holds a polynomial and
/// its opening points /// its opening points
#[derive(Debug)] #[derive(Debug)]
pub(super) struct PcsAccumulator<E: PairingEngine, PCS: PolynomialCommitmentScheme<E>> {
pub(super) struct PcsAccumulator<E: Pairing, PCS: PolynomialCommitmentScheme<E>> {
// sequence: // sequence:
// - prod(x) at 5 points // - prod(x) at 5 points
// - w_merged at perm check point // - w_merged at perm check point
@ -35,12 +35,12 @@ pub(super) struct PcsAccumulator
impl<E, PCS> PcsAccumulator<E, PCS> impl<E, PCS> PcsAccumulator<E, PCS>
where where
E: PairingEngine,
E: Pairing,
PCS: PolynomialCommitmentScheme< PCS: PolynomialCommitmentScheme<
E, E,
Polynomial = Arc<DenseMultilinearExtension<E::Fr>>,
Point = Vec<E::Fr>,
Evaluation = E::Fr,
Polynomial = Arc<DenseMultilinearExtension<E::ScalarField>>,
Point = Vec<E::ScalarField>,
Evaluation = E::ScalarField,
Commitment = Commitment<E>, Commitment = Commitment<E>,
>, >,
{ {
@ -78,7 +78,7 @@ where
pub(super) fn multi_open( pub(super) fn multi_open(
&self, &self,
prover_param: impl Borrow<PCS::ProverParam>, prover_param: impl Borrow<PCS::ProverParam>,
transcript: &mut IOPTranscript<E::Fr>,
transcript: &mut IOPTranscript<E::ScalarField>,
) -> Result<PCS::BatchProof, HyperPlonkErrors> { ) -> Result<PCS::BatchProof, HyperPlonkErrors> {
Ok(PCS::multi_open( Ok(PCS::multi_open(
prover_param.borrow(), prover_param.borrow(),

+ 6
- 6
subroutines/Cargo.toml

@ -6,12 +6,12 @@ edition = "2021"
[dependencies] [dependencies]
arithmetic = { path = "../arithmetic" } arithmetic = { path = "../arithmetic" }
ark-bls12-381 = { version = "0.3.0", default-features = false, features = [ "curve" ] }
ark-ec = { version = "^0.3.0", default-features = false }
ark-ff = { version = "^0.3.0", default-features = false }
ark-poly = { version = "^0.3.0", default-features = false }
ark-serialize = { version = "^0.3.0", default-features = false }
ark-std = { version = "^0.3.0", default-features = false }
ark-bls12-381 = { version = "0.4.0", default-features = false, features = [ "curve" ] }
ark-ec = { version = "^0.4.0", default-features = false }
ark-ff = { version = "^0.4.0", default-features = false }
ark-poly = { version = "^0.4.0", default-features = false }
ark-serialize = { version = "^0.4.0", default-features = false }
ark-std = { version = "^0.4.0", default-features = false }
derivative = { version = "2", features = ["use_core"] } derivative = { version = "2", features = ["use_core"] }
displaydoc = { version = "0.2.3", default-features = false } displaydoc = { version = "0.2.3", default-features = false }
itertools = { version = "0.10.4", optional = true } itertools = { version = "0.10.4", optional = true }

+ 13
- 13
subroutines/benches/iop_bench.rs

@ -16,7 +16,7 @@ use subroutines::{
}, },
}; };
type KZG = MultilinearKzgPCS<Bls12_381>;
type Kzg = MultilinearKzgPCS<Bls12_381>;
fn main() -> Result<(), PolyIOPErrors> { fn main() -> Result<(), PolyIOPErrors> {
bench_permutation_check()?; bench_permutation_check()?;
@ -139,8 +139,8 @@ fn bench_permutation_check() -> Result<(), PolyIOPErrors> {
let mut rng = test_rng(); let mut rng = test_rng();
for nv in 4..20 { for nv in 4..20 {
let srs = KZG::gen_srs_for_testing(&mut rng, nv + 1)?;
let (pcs_param, _) = KZG::trim(&srs, None, Some(nv + 1))?;
let srs = Kzg::gen_srs_for_testing(&mut rng, nv + 1)?;
let (pcs_param, _) = Kzg::trim(&srs, None, Some(nv + 1))?;
let repetition = if nv < 10 { let repetition = if nv < 10 {
100 100
@ -159,12 +159,12 @@ fn bench_permutation_check() -> Result<(), PolyIOPErrors> {
{ {
let start = Instant::now(); let start = Instant::now();
let mut transcript = let mut transcript =
<PolyIOP<Fr> as PermutationCheck<Bls12_381, KZG>>::init_transcript();
<PolyIOP<Fr> as PermutationCheck<Bls12_381, Kzg>>::init_transcript();
transcript.append_message(b"testing", b"initializing transcript for testing")?; transcript.append_message(b"testing", b"initializing transcript for testing")?;
let (proof, _q_x, _frac_poly) = <PolyIOP<Fr> as PermutationCheck< let (proof, _q_x, _frac_poly) = <PolyIOP<Fr> as PermutationCheck<
Bls12_381, Bls12_381,
KZG,
Kzg,
>>::prove( >>::prove(
&pcs_param, &ws, &ws, &perms, &mut transcript &pcs_param, &ws, &ws, &perms, &mut transcript
)?; )?;
@ -186,9 +186,9 @@ fn bench_permutation_check() -> Result<(), PolyIOPErrors> {
let start = Instant::now(); let start = Instant::now();
let mut transcript = let mut transcript =
<PolyIOP<Fr> as PermutationCheck<Bls12_381, KZG>>::init_transcript();
<PolyIOP<Fr> as PermutationCheck<Bls12_381, Kzg>>::init_transcript();
transcript.append_message(b"testing", b"initializing transcript for testing")?; transcript.append_message(b"testing", b"initializing transcript for testing")?;
let _perm_check_sum_claim = <PolyIOP<Fr> as PermutationCheck<Bls12_381, KZG>>::verify(
let _perm_check_sum_claim = <PolyIOP<Fr> as PermutationCheck<Bls12_381, Kzg>>::verify(
&proof, &proof,
&poly_info, &poly_info,
&mut transcript, &mut transcript,
@ -210,8 +210,8 @@ fn bench_prod_check() -> Result<(), PolyIOPErrors> {
let mut rng = test_rng(); let mut rng = test_rng();
for nv in 4..20 { for nv in 4..20 {
let srs = KZG::gen_srs_for_testing(&mut rng, nv + 1)?;
let (pcs_param, _) = KZG::trim(&srs, None, Some(nv + 1))?;
let srs = Kzg::gen_srs_for_testing(&mut rng, nv + 1)?;
let (pcs_param, _) = Kzg::trim(&srs, None, Some(nv + 1))?;
let repetition = if nv < 10 { let repetition = if nv < 10 {
100 100
@ -229,11 +229,11 @@ fn bench_prod_check() -> Result<(), PolyIOPErrors> {
let proof = { let proof = {
let start = Instant::now(); let start = Instant::now();
let mut transcript = <PolyIOP<Fr> as ProductCheck<Bls12_381, KZG>>::init_transcript();
let mut transcript = <PolyIOP<Fr> as ProductCheck<Bls12_381, Kzg>>::init_transcript();
transcript.append_message(b"testing", b"initializing transcript for testing")?; transcript.append_message(b"testing", b"initializing transcript for testing")?;
let (proof, _prod_x, _frac_poly) = let (proof, _prod_x, _frac_poly) =
<PolyIOP<Fr> as ProductCheck<Bls12_381, KZG>>::prove(
<PolyIOP<Fr> as ProductCheck<Bls12_381, Kzg>>::prove(
&pcs_param, &pcs_param,
&fs, &fs,
&gs, &gs,
@ -256,9 +256,9 @@ fn bench_prod_check() -> Result<(), PolyIOPErrors> {
}; };
let start = Instant::now(); let start = Instant::now();
let mut transcript = <PolyIOP<Fr> as ProductCheck<Bls12_381, KZG>>::init_transcript();
let mut transcript = <PolyIOP<Fr> as ProductCheck<Bls12_381, Kzg>>::init_transcript();
transcript.append_message(b"testing", b"initializing transcript for testing")?; transcript.append_message(b"testing", b"initializing transcript for testing")?;
let _perm_check_sum_claim = <PolyIOP<Fr> as ProductCheck<Bls12_381, KZG>>::verify(
let _perm_check_sum_claim = <PolyIOP<Fr> as ProductCheck<Bls12_381, Kzg>>::verify(
&proof, &proof,
&poly_info, &poly_info,
&mut transcript, &mut transcript,

+ 9
- 12
subroutines/src/pcs/mod.rs

@ -11,17 +11,17 @@ mod univariate_kzg;
pub mod prelude; pub mod prelude;
use ark_ec::PairingEngine;
use ark_ec::pairing::Pairing;
use ark_ff::Field; use ark_ff::Field;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_std::rand::{CryptoRng, RngCore};
use ark_std::rand::Rng;
use errors::PCSError; use errors::PCSError;
use std::{borrow::Borrow, fmt::Debug, hash::Hash}; use std::{borrow::Borrow, fmt::Debug, hash::Hash};
use transcript::IOPTranscript; use transcript::IOPTranscript;
/// This trait defines APIs for polynomial commitment schemes. /// This trait defines APIs for polynomial commitment schemes.
/// Note that for our usage of PCS, we do not require the hiding property. /// Note that for our usage of PCS, we do not require the hiding property.
pub trait PolynomialCommitmentScheme<E: PairingEngine> {
pub trait PolynomialCommitmentScheme<E: Pairing> {
/// Prover parameters /// Prover parameters
type ProverParam: Clone + Sync; type ProverParam: Clone + Sync;
/// Verifier parameters /// Verifier parameters
@ -49,7 +49,7 @@ pub trait PolynomialCommitmentScheme {
/// ///
/// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY.
/// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION.
fn gen_srs_for_testing<R: RngCore + CryptoRng>(
fn gen_srs_for_testing<R: Rng>(
rng: &mut R, rng: &mut R,
supported_size: usize, supported_size: usize,
) -> Result<Self::SRS, PCSError>; ) -> Result<Self::SRS, PCSError>;
@ -99,7 +99,7 @@ pub trait PolynomialCommitmentScheme {
_polynomials: &[Self::Polynomial], _polynomials: &[Self::Polynomial],
_points: &[Self::Point], _points: &[Self::Point],
_evals: &[Self::Evaluation], _evals: &[Self::Evaluation],
_transcript: &mut IOPTranscript<E::Fr>,
_transcript: &mut IOPTranscript<E::ScalarField>,
) -> Result<Self::BatchProof, PCSError> { ) -> Result<Self::BatchProof, PCSError> {
// the reason we use unimplemented!() is to enable developers to implement the // the reason we use unimplemented!() is to enable developers to implement the
// trait without always implementing the batching APIs. // trait without always implementing the batching APIs.
@ -112,7 +112,7 @@ pub trait PolynomialCommitmentScheme {
verifier_param: &Self::VerifierParam, verifier_param: &Self::VerifierParam,
commitment: &Self::Commitment, commitment: &Self::Commitment,
point: &Self::Point, point: &Self::Point,
value: &E::Fr,
value: &E::ScalarField,
proof: &Self::Proof, proof: &Self::Proof,
) -> Result<bool, PCSError>; ) -> Result<bool, PCSError>;
@ -123,7 +123,7 @@ pub trait PolynomialCommitmentScheme {
_commitments: &[Self::Commitment], _commitments: &[Self::Commitment],
_points: &[Self::Point], _points: &[Self::Point],
_batch_proof: &Self::BatchProof, _batch_proof: &Self::BatchProof,
_transcript: &mut IOPTranscript<E::Fr>,
_transcript: &mut IOPTranscript<E::ScalarField>,
) -> Result<bool, PCSError> { ) -> Result<bool, PCSError> {
// the reason we use unimplemented!() is to enable developers to implement the // the reason we use unimplemented!() is to enable developers to implement the
// trait without always implementing the batching APIs. // trait without always implementing the batching APIs.
@ -132,7 +132,7 @@ pub trait PolynomialCommitmentScheme {
} }
/// API definitions for structured reference string /// API definitions for structured reference string
pub trait StructuredReferenceString<E: PairingEngine>: Sized {
pub trait StructuredReferenceString<E: Pairing>: Sized {
/// Prover parameters /// Prover parameters
type ProverParam; type ProverParam;
/// Verifier parameters /// Verifier parameters
@ -165,8 +165,5 @@ pub trait StructuredReferenceString: Sized {
/// ///
/// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY.
/// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION.
fn gen_srs_for_testing<R: RngCore + CryptoRng>(
rng: &mut R,
supported_size: usize,
) -> Result<Self, PCSError>;
fn gen_srs_for_testing<R: Rng>(rng: &mut R, supported_size: usize) -> Result<Self, PCSError>;
} }

+ 28
- 30
subroutines/src/pcs/multilinear_kzg/batching.rs

@ -20,8 +20,8 @@ use crate::{
IOPProof, IOPProof,
}; };
use arithmetic::{build_eq_x_r_vec, DenseMultilinearExtension, VPAuxInfo, VirtualPolynomial}; use arithmetic::{build_eq_x_r_vec, DenseMultilinearExtension, VPAuxInfo, VirtualPolynomial};
use ark_ec::{msm::VariableBaseMSM, PairingEngine, ProjectiveCurve};
use ark_ff::PrimeField;
use ark_ec::{pairing::Pairing, scalar_mul::variable_base::VariableBaseMSM, CurveGroup};
use ark_std::{end_timer, log2, start_timer, One, Zero}; use ark_std::{end_timer, log2, start_timer, One, Zero};
use std::{collections::BTreeMap, iter, marker::PhantomData, ops::Deref, sync::Arc}; use std::{collections::BTreeMap, iter, marker::PhantomData, ops::Deref, sync::Arc};
use transcript::IOPTranscript; use transcript::IOPTranscript;
@ -29,13 +29,13 @@ use transcript::IOPTranscript;
#[derive(Clone, Debug, Default, PartialEq, Eq)] #[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct BatchProof<E, PCS> pub struct BatchProof<E, PCS>
where where
E: PairingEngine,
E: Pairing,
PCS: PolynomialCommitmentScheme<E>, PCS: PolynomialCommitmentScheme<E>,
{ {
/// A sum check proof proving tilde g's sum /// A sum check proof proving tilde g's sum
pub(crate) sum_check_proof: IOPProof<E::Fr>,
pub(crate) sum_check_proof: IOPProof<E::ScalarField>,
/// f_i(point_i) /// f_i(point_i)
pub f_i_eval_at_point_i: Vec<E::Fr>,
pub f_i_eval_at_point_i: Vec<E::ScalarField>,
/// proof for g'(a_2) /// proof for g'(a_2)
pub(crate) g_prime_proof: PCS::Proof, pub(crate) g_prime_proof: PCS::Proof,
} }
@ -53,15 +53,15 @@ pub(crate) fn multi_open_internal(
polynomials: &[PCS::Polynomial], polynomials: &[PCS::Polynomial],
points: &[PCS::Point], points: &[PCS::Point],
evals: &[PCS::Evaluation], evals: &[PCS::Evaluation],
transcript: &mut IOPTranscript<E::Fr>,
transcript: &mut IOPTranscript<E::ScalarField>,
) -> Result<BatchProof<E, PCS>, PCSError> ) -> Result<BatchProof<E, PCS>, PCSError>
where where
E: PairingEngine,
E: Pairing,
PCS: PolynomialCommitmentScheme< PCS: PolynomialCommitmentScheme<
E, E,
Polynomial = Arc<DenseMultilinearExtension<E::Fr>>,
Point = Vec<E::Fr>,
Evaluation = E::Fr,
Polynomial = Arc<DenseMultilinearExtension<E::ScalarField>>,
Point = Vec<E::ScalarField>,
Evaluation = E::ScalarField,
>, >,
{ {
let open_timer = start_timer!(|| format!("multi open {} points", points.len())); let open_timer = start_timer!(|| format!("multi open {} points", points.len()));
@ -127,11 +127,14 @@ where
let step = start_timer!(|| "add mle"); let step = start_timer!(|| "add mle");
let mut sum_check_vp = VirtualPolynomial::new(num_var); let mut sum_check_vp = VirtualPolynomial::new(num_var);
for (merged_tilde_g, tilde_eq) in merged_tilde_gs.iter().zip(tilde_eqs.into_iter()) { for (merged_tilde_g, tilde_eq) in merged_tilde_gs.iter().zip(tilde_eqs.into_iter()) {
sum_check_vp.add_mle_list([merged_tilde_g.clone(), tilde_eq], E::Fr::one())?;
sum_check_vp.add_mle_list([merged_tilde_g.clone(), tilde_eq], E::ScalarField::one())?;
} }
end_timer!(step); end_timer!(step);
let proof = match <PolyIOP<E::Fr> as SumCheck<E::Fr>>::prove(&sum_check_vp, transcript) {
let proof = match <PolyIOP<E::ScalarField> as SumCheck<E::ScalarField>>::prove(
&sum_check_vp,
transcript,
) {
Ok(p) => p, Ok(p) => p,
Err(_e) => { Err(_e) => {
// cannot wrap IOPError with PCSError due to cyclic dependency // cannot wrap IOPError with PCSError due to cyclic dependency
@ -182,15 +185,15 @@ pub(crate) fn batch_verify_internal(
f_i_commitments: &[Commitment<E>], f_i_commitments: &[Commitment<E>],
points: &[PCS::Point], points: &[PCS::Point],
proof: &BatchProof<E, PCS>, proof: &BatchProof<E, PCS>,
transcript: &mut IOPTranscript<E::Fr>,
transcript: &mut IOPTranscript<E::ScalarField>,
) -> Result<bool, PCSError> ) -> Result<bool, PCSError>
where where
E: PairingEngine,
E: Pairing,
PCS: PolynomialCommitmentScheme< PCS: PolynomialCommitmentScheme<
E, E,
Polynomial = Arc<DenseMultilinearExtension<E::Fr>>,
Point = Vec<E::Fr>,
Evaluation = E::Fr,
Polynomial = Arc<DenseMultilinearExtension<E::ScalarField>>,
Point = Vec<E::ScalarField>,
Evaluation = E::ScalarField,
Commitment = Commitment<E>, Commitment = Commitment<E>,
>, >,
{ {
@ -217,14 +220,14 @@ where
for (i, point) in points.iter().enumerate() { for (i, point) in points.iter().enumerate() {
let eq_i_a2 = eq_eval(a2, point)?; let eq_i_a2 = eq_eval(a2, point)?;
scalars.push((eq_i_a2 * eq_t_list[i]).into_repr());
scalars.push(eq_i_a2 * eq_t_list[i]);
bases.push(f_i_commitments[i].0); bases.push(f_i_commitments[i].0);
} }
let g_prime_commit = VariableBaseMSM::multi_scalar_mul(&bases, &scalars);
let g_prime_commit = E::G1::msm_unchecked(&bases, &scalars);
end_timer!(step); end_timer!(step);
// ensure \sum_i eq(t, <i>) * f_i_evals matches the sum via SumCheck // ensure \sum_i eq(t, <i>) * f_i_evals matches the sum via SumCheck
let mut sum = E::Fr::zero();
let mut sum = E::ScalarField::zero();
for (i, &e) in eq_t_list.iter().enumerate().take(k) { for (i, &e) in eq_t_list.iter().enumerate().take(k) {
sum += e * proof.f_i_eval_at_point_i[i]; sum += e * proof.f_i_eval_at_point_i[i];
} }
@ -233,7 +236,7 @@ where
num_variables: num_var, num_variables: num_var,
phantom: PhantomData, phantom: PhantomData,
}; };
let subclaim = match <PolyIOP<E::Fr> as SumCheck<E::Fr>>::verify(
let subclaim = match <PolyIOP<E::ScalarField> as SumCheck<E::ScalarField>>::verify(
sum, sum,
&proof.sum_check_proof, &proof.sum_check_proof,
&aux_info, &aux_info,
@ -271,18 +274,13 @@ mod tests {
}; };
use arithmetic::get_batched_nv; use arithmetic::get_batched_nv;
use ark_bls12_381::Bls12_381 as E; use ark_bls12_381::Bls12_381 as E;
use ark_ec::PairingEngine;
use ark_ec::pairing::Pairing;
use ark_poly::{DenseMultilinearExtension, MultilinearExtension}; use ark_poly::{DenseMultilinearExtension, MultilinearExtension};
use ark_std::{
rand::{CryptoRng, RngCore},
test_rng,
vec::Vec,
UniformRand,
};
use ark_std::{rand::Rng, test_rng, vec::Vec, UniformRand};
type Fr = <E as PairingEngine>::Fr;
type Fr = <E as Pairing>::ScalarField;
fn test_multi_open_helper<R: RngCore + CryptoRng>(
fn test_multi_open_helper<R: Rng>(
ml_params: &MultilinearUniversalParams<E>, ml_params: &MultilinearUniversalParams<E>,
polys: &[Arc<DenseMultilinearExtension<Fr>>], polys: &[Arc<DenseMultilinearExtension<Fr>>],
rng: &mut R, rng: &mut R,

+ 47
- 64
subroutines/src/pcs/multilinear_kzg/mod.rs

@ -16,24 +16,18 @@ use crate::{
}; };
use arithmetic::evaluate_opt; use arithmetic::evaluate_opt;
use ark_ec::{ use ark_ec::{
msm::{FixedBaseMSM, VariableBaseMSM},
AffineCurve, PairingEngine, ProjectiveCurve,
pairing::Pairing,
scalar_mul::{fixed_base::FixedBase, variable_base::VariableBaseMSM},
AffineRepr, CurveGroup,
}; };
use ark_ff::PrimeField; use ark_ff::PrimeField;
use ark_poly::{DenseMultilinearExtension, MultilinearExtension}; use ark_poly::{DenseMultilinearExtension, MultilinearExtension};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_std::{ use ark_std::{
borrow::Borrow,
end_timer, format,
marker::PhantomData,
rand::{CryptoRng, RngCore},
start_timer,
string::ToString,
sync::Arc,
vec,
vec::Vec,
One, Zero,
borrow::Borrow, end_timer, format, marker::PhantomData, rand::Rng, start_timer,
string::ToString, sync::Arc, vec, vec::Vec, One, Zero,
}; };
use std::ops::Mul;
// use batching::{batch_verify_internal, multi_open_internal}; // use batching::{batch_verify_internal, multi_open_internal};
use srs::{MultilinearProverParam, MultilinearUniversalParams, MultilinearVerifierParam}; use srs::{MultilinearProverParam, MultilinearUniversalParams, MultilinearVerifierParam};
use transcript::IOPTranscript; use transcript::IOPTranscript;
@ -41,27 +35,27 @@ use transcript::IOPTranscript;
use self::batching::{batch_verify_internal, multi_open_internal}; use self::batching::{batch_verify_internal, multi_open_internal};
/// KZG Polynomial Commitment Scheme on multilinear polynomials. /// KZG Polynomial Commitment Scheme on multilinear polynomials.
pub struct MultilinearKzgPCS<E: PairingEngine> {
pub struct MultilinearKzgPCS<E: Pairing> {
#[doc(hidden)] #[doc(hidden)]
phantom: PhantomData<E>, phantom: PhantomData<E>,
} }
#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq, Eq)] #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq, Eq)]
/// proof of opening /// proof of opening
pub struct MultilinearKzgProof<E: PairingEngine> {
pub struct MultilinearKzgProof<E: Pairing> {
/// Evaluation of quotients /// Evaluation of quotients
pub proofs: Vec<E::G1Affine>, pub proofs: Vec<E::G1Affine>,
} }
impl<E: PairingEngine> PolynomialCommitmentScheme<E> for MultilinearKzgPCS<E> {
impl<E: Pairing> PolynomialCommitmentScheme<E> for MultilinearKzgPCS<E> {
// Parameters // Parameters
type ProverParam = MultilinearProverParam<E>; type ProverParam = MultilinearProverParam<E>;
type VerifierParam = MultilinearVerifierParam<E>; type VerifierParam = MultilinearVerifierParam<E>;
type SRS = MultilinearUniversalParams<E>; type SRS = MultilinearUniversalParams<E>;
// Polynomial and its associated types // Polynomial and its associated types
type Polynomial = Arc<DenseMultilinearExtension<E::Fr>>;
type Point = Vec<E::Fr>;
type Evaluation = E::Fr;
type Polynomial = Arc<DenseMultilinearExtension<E::ScalarField>>;
type Point = Vec<E::ScalarField>;
type Evaluation = E::ScalarField;
// Commitments and proofs // Commitments and proofs
type Commitment = Commitment<E>; type Commitment = Commitment<E>;
type Proof = MultilinearKzgProof<E>; type Proof = MultilinearKzgProof<E>;
@ -74,10 +68,7 @@ impl PolynomialCommitmentScheme for MultilinearKzgPCS {
/// ///
/// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY.
/// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION.
fn gen_srs_for_testing<R: RngCore + CryptoRng>(
rng: &mut R,
log_size: usize,
) -> Result<Self::SRS, PCSError> {
fn gen_srs_for_testing<R: Rng>(rng: &mut R, log_size: usize) -> Result<Self::SRS, PCSError> {
MultilinearUniversalParams::<E>::gen_srs_for_testing(rng, log_size) MultilinearUniversalParams::<E>::gen_srs_for_testing(rng, log_size)
} }
@ -121,20 +112,14 @@ impl PolynomialCommitmentScheme for MultilinearKzgPCS {
))); )));
} }
let ignored = prover_param.num_vars - poly.num_vars; let ignored = prover_param.num_vars - poly.num_vars;
let scalars: Vec<_> = poly
.to_evaluations()
.into_iter()
.map(|x| x.into_repr())
.collect();
let scalars: Vec<_> = poly.to_evaluations();
let msm_timer = start_timer!(|| format!( let msm_timer = start_timer!(|| format!(
"msm of size {}", "msm of size {}",
prover_param.powers_of_g[ignored].evals.len() prover_param.powers_of_g[ignored].evals.len()
)); ));
let commitment = VariableBaseMSM::multi_scalar_mul(
&prover_param.powers_of_g[ignored].evals,
scalars.as_slice(),
)
.into_affine();
let commitment =
E::G1::msm_unchecked(&prover_param.powers_of_g[ignored].evals, scalars.as_slice())
.into_affine();
end_timer!(msm_timer); end_timer!(msm_timer);
end_timer!(commit_timer); end_timer!(commit_timer);
@ -165,7 +150,7 @@ impl PolynomialCommitmentScheme for MultilinearKzgPCS {
polynomials: &[Self::Polynomial], polynomials: &[Self::Polynomial],
points: &[Self::Point], points: &[Self::Point],
evals: &[Self::Evaluation], evals: &[Self::Evaluation],
transcript: &mut IOPTranscript<E::Fr>,
transcript: &mut IOPTranscript<E::ScalarField>,
) -> Result<BatchProof<E, Self>, PCSError> { ) -> Result<BatchProof<E, Self>, PCSError> {
multi_open_internal( multi_open_internal(
prover_param.borrow(), prover_param.borrow(),
@ -186,7 +171,7 @@ impl PolynomialCommitmentScheme for MultilinearKzgPCS {
verifier_param: &Self::VerifierParam, verifier_param: &Self::VerifierParam,
commitment: &Self::Commitment, commitment: &Self::Commitment,
point: &Self::Point, point: &Self::Point,
value: &E::Fr,
value: &E::ScalarField,
proof: &Self::Proof, proof: &Self::Proof,
) -> Result<bool, PCSError> { ) -> Result<bool, PCSError> {
verify_internal(verifier_param, commitment, point, value, proof) verify_internal(verifier_param, commitment, point, value, proof)
@ -199,7 +184,7 @@ impl PolynomialCommitmentScheme for MultilinearKzgPCS {
commitments: &[Self::Commitment], commitments: &[Self::Commitment],
points: &[Self::Point], points: &[Self::Point],
batch_proof: &Self::BatchProof, batch_proof: &Self::BatchProof,
transcript: &mut IOPTranscript<E::Fr>,
transcript: &mut IOPTranscript<E::ScalarField>,
) -> Result<bool, PCSError> { ) -> Result<bool, PCSError> {
batch_verify_internal(verifier_param, commitments, points, batch_proof, transcript) batch_verify_internal(verifier_param, commitments, points, batch_proof, transcript)
} }
@ -213,11 +198,11 @@ impl PolynomialCommitmentScheme for MultilinearKzgPCS {
/// G1: /// G1:
/// - it proceeds with `num_var` number of rounds, /// - it proceeds with `num_var` number of rounds,
/// - at round i, we compute an MSM for `2^{num_var - i}` number of G1 elements. /// - at round i, we compute an MSM for `2^{num_var - i}` number of G1 elements.
fn open_internal<E: PairingEngine>(
fn open_internal<E: Pairing>(
prover_param: &MultilinearProverParam<E>, prover_param: &MultilinearProverParam<E>,
polynomial: &DenseMultilinearExtension<E::Fr>,
point: &[E::Fr],
) -> Result<(MultilinearKzgProof<E>, E::Fr), PCSError> {
polynomial: &DenseMultilinearExtension<E::ScalarField>,
point: &[E::ScalarField],
) -> Result<(MultilinearKzgProof<E>, E::ScalarField), PCSError> {
let open_timer = start_timer!(|| format!("open mle with {} variable", polynomial.num_vars)); let open_timer = start_timer!(|| format!("open mle with {} variable", polynomial.num_vars));
if polynomial.num_vars() > prover_param.num_vars { if polynomial.num_vars() > prover_param.num_vars {
@ -251,8 +236,8 @@ fn open_internal(
let k = nv - 1 - i; let k = nv - 1 - i;
let cur_dim = 1 << k; let cur_dim = 1 << k;
let mut q = vec![E::Fr::zero(); cur_dim];
let mut r = vec![E::Fr::zero(); cur_dim];
let mut q = vec![E::ScalarField::zero(); cur_dim];
let mut r = vec![E::ScalarField::zero(); cur_dim];
let ith_round_eval = start_timer!(|| format!("{}-th round eval", i)); let ith_round_eval = start_timer!(|| format!("{}-th round eval", i));
for b in 0..(1 << k) { for b in 0..(1 << k) {
@ -264,12 +249,11 @@ fn open_internal(
} }
f = r; f = r;
end_timer!(ith_round_eval); end_timer!(ith_round_eval);
let scalars: Vec<_> = q.iter().map(|x| x.into_repr()).collect();
// this is a MSM over G1 and is likely to be the bottleneck // this is a MSM over G1 and is likely to be the bottleneck
let msm_timer = start_timer!(|| format!("msm of size {} at round {}", gi.evals.len(), i)); let msm_timer = start_timer!(|| format!("msm of size {} at round {}", gi.evals.len(), i));
proofs.push(VariableBaseMSM::multi_scalar_mul(&gi.evals, &scalars).into_affine());
proofs.push(E::G1::msm_unchecked(&gi.evals, &q).into_affine());
end_timer!(msm_timer); end_timer!(msm_timer);
end_timer!(ith_round); end_timer!(ith_round);
@ -285,11 +269,11 @@ fn open_internal(
/// This function takes /// This function takes
/// - num_var number of pairing product. /// - num_var number of pairing product.
/// - num_var number of MSM /// - num_var number of MSM
fn verify_internal<E: PairingEngine>(
fn verify_internal<E: Pairing>(
verifier_param: &MultilinearVerifierParam<E>, verifier_param: &MultilinearVerifierParam<E>,
commitment: &Commitment<E>, commitment: &Commitment<E>,
point: &[E::Fr],
value: &E::Fr,
point: &[E::ScalarField],
value: &E::ScalarField,
proof: &MultilinearKzgProof<E>, proof: &MultilinearKzgProof<E>,
) -> Result<bool, PCSError> { ) -> Result<bool, PCSError> {
let verify_timer = start_timer!(|| "verify"); let verify_timer = start_timer!(|| "verify");
@ -304,22 +288,18 @@ fn verify_internal(
let prepare_inputs_timer = start_timer!(|| "prepare pairing inputs"); let prepare_inputs_timer = start_timer!(|| "prepare pairing inputs");
let scalar_size = E::Fr::size_in_bits();
let window_size = FixedBaseMSM::get_mul_window_size(num_var);
let scalar_size = E::ScalarField::MODULUS_BIT_SIZE as usize;
let window_size = FixedBase::get_mul_window_size(num_var);
let h_table = FixedBaseMSM::get_window_table(
scalar_size,
window_size,
verifier_param.h.into_projective(),
);
let h_mul: Vec<E::G2Projective> =
FixedBaseMSM::multi_scalar_mul(scalar_size, window_size, &h_table, point);
let h_table =
FixedBase::get_window_table(scalar_size, window_size, verifier_param.h.into_group());
let h_mul: Vec<E::G2> = FixedBase::msm(scalar_size, window_size, &h_table, point);
let ignored = verifier_param.num_vars - num_var; let ignored = verifier_param.num_vars - num_var;
let h_vec: Vec<_> = (0..num_var) let h_vec: Vec<_> = (0..num_var)
.map(|i| verifier_param.h_mask[ignored + i].into_projective() - h_mul[i])
.map(|i| verifier_param.h_mask[ignored + i].into_group() - h_mul[i])
.collect(); .collect();
let h_vec: Vec<E::G2Affine> = E::G2Projective::batch_normalization_into_affine(&h_vec);
let h_vec: Vec<E::G2Affine> = E::G2::normalize_batch(&h_vec);
end_timer!(prepare_inputs_timer); end_timer!(prepare_inputs_timer);
let pairing_product_timer = start_timer!(|| "pairing product"); let pairing_product_timer = start_timer!(|| "pairing product");
@ -333,12 +313,15 @@ fn verify_internal(
pairings.push(( pairings.push((
E::G1Prepared::from( E::G1Prepared::from(
(verifier_param.g.mul(*value) - commitment.0.into_projective()).into_affine(),
(verifier_param.g.mul(*value) - commitment.0.into_group()).into_affine(),
), ),
E::G2Prepared::from(verifier_param.h), E::G2Prepared::from(verifier_param.h),
)); ));
let res = E::product_of_pairings(pairings.iter()) == E::Fqk::one();
let ps = pairings.iter().map(|(p, _)| p.clone());
let hs = pairings.iter().map(|(_, h)| h.clone());
let res = E::multi_pairing(ps, hs) == ark_ec::pairing::PairingOutput(E::TargetField::one());
end_timer!(pairing_product_timer); end_timer!(pairing_product_timer);
end_timer!(verify_timer); end_timer!(verify_timer);
@ -349,14 +332,14 @@ fn verify_internal(
mod tests { mod tests {
use super::*; use super::*;
use ark_bls12_381::Bls12_381; use ark_bls12_381::Bls12_381;
use ark_ec::PairingEngine;
use ark_ec::pairing::Pairing;
use ark_poly::{DenseMultilinearExtension, MultilinearExtension}; use ark_poly::{DenseMultilinearExtension, MultilinearExtension};
use ark_std::{rand::RngCore, test_rng, vec::Vec, UniformRand};
use ark_std::{test_rng, vec::Vec, UniformRand};
type E = Bls12_381; type E = Bls12_381;
type Fr = <E as PairingEngine>::Fr;
type Fr = <E as Pairing>::ScalarField;
fn test_single_helper<R: RngCore + CryptoRng>(
fn test_single_helper<R: Rng>(
params: &MultilinearUniversalParams<E>, params: &MultilinearUniversalParams<E>,
poly: &Arc<DenseMultilinearExtension<Fr>>, poly: &Arc<DenseMultilinearExtension<Fr>>,
rng: &mut R, rng: &mut R,

+ 28
- 38
subroutines/src/pcs/multilinear_kzg/srs.rs

@ -10,31 +10,26 @@ use crate::pcs::{
prelude::PCSError, prelude::PCSError,
StructuredReferenceString, StructuredReferenceString,
}; };
use ark_ec::{msm::FixedBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ec::{pairing::Pairing, scalar_mul::fixed_base::FixedBase, AffineRepr, CurveGroup};
use ark_ff::{Field, PrimeField, Zero}; use ark_ff::{Field, PrimeField, Zero};
use ark_poly::DenseMultilinearExtension; use ark_poly::DenseMultilinearExtension;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_std::{ use ark_std::{
collections::LinkedList,
end_timer, format,
rand::{CryptoRng, RngCore},
start_timer,
string::ToString,
vec::Vec,
collections::LinkedList, end_timer, format, rand::Rng, start_timer, string::ToString, vec::Vec,
UniformRand, UniformRand,
}; };
use core::iter::FromIterator; use core::iter::FromIterator;
/// Evaluations over {0,1}^n for G1 or G2 /// Evaluations over {0,1}^n for G1 or G2
#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)] #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
pub struct Evaluations<C: AffineCurve> {
pub struct Evaluations<C: AffineRepr> {
/// The evaluations. /// The evaluations.
pub evals: Vec<C>, pub evals: Vec<C>,
} }
/// Universal Parameter /// Universal Parameter
#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)] #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
pub struct MultilinearUniversalParams<E: PairingEngine> {
pub struct MultilinearUniversalParams<E: Pairing> {
/// prover parameters /// prover parameters
pub prover_param: MultilinearProverParam<E>, pub prover_param: MultilinearProverParam<E>,
/// h^randomness: h^t1, h^t2, ..., **h^{t_nv}** /// h^randomness: h^t1, h^t2, ..., **h^{t_nv}**
@ -43,7 +38,7 @@ pub struct MultilinearUniversalParams {
/// Prover Parameters /// Prover Parameters
#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)] #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
pub struct MultilinearProverParam<E: PairingEngine> {
pub struct MultilinearProverParam<E: Pairing> {
/// number of variables /// number of variables
pub num_vars: usize, pub num_vars: usize,
/// `pp_{0}`, `pp_{1}`, ...,pp_{nu_vars} defined /// `pp_{0}`, `pp_{1}`, ...,pp_{nu_vars} defined
@ -58,7 +53,7 @@ pub struct MultilinearProverParam {
/// Verifier Parameters /// Verifier Parameters
#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)] #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
pub struct MultilinearVerifierParam<E: PairingEngine> {
pub struct MultilinearVerifierParam<E: Pairing> {
/// number of variables /// number of variables
pub num_vars: usize, pub num_vars: usize,
/// generator of G1 /// generator of G1
@ -69,7 +64,7 @@ pub struct MultilinearVerifierParam {
pub h_mask: Vec<E::G2Affine>, pub h_mask: Vec<E::G2Affine>,
} }
impl<E: PairingEngine> StructuredReferenceString<E> for MultilinearUniversalParams<E> {
impl<E: Pairing> StructuredReferenceString<E> for MultilinearUniversalParams<E> {
type ProverParam = MultilinearProverParam<E>; type ProverParam = MultilinearProverParam<E>;
type VerifierParam = MultilinearVerifierParam<E>; type VerifierParam = MultilinearVerifierParam<E>;
@ -130,10 +125,7 @@ impl StructuredReferenceString for MultilinearUniversalPara
/// Build SRS for testing. /// Build SRS for testing.
/// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY.
/// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION.
fn gen_srs_for_testing<R: RngCore + CryptoRng>(
rng: &mut R,
num_vars: usize,
) -> Result<Self, PCSError> {
fn gen_srs_for_testing<R: Rng>(rng: &mut R, num_vars: usize) -> Result<Self, PCSError> {
if num_vars == 0 { if num_vars == 0 {
return Err(PCSError::InvalidParameters( return Err(PCSError::InvalidParameters(
"constant polynomial not supported".to_string(), "constant polynomial not supported".to_string(),
@ -144,15 +136,15 @@ impl StructuredReferenceString for MultilinearUniversalPara
let pp_generation_timer = start_timer!(|| "Prover Param generation"); let pp_generation_timer = start_timer!(|| "Prover Param generation");
let g = E::G1Projective::rand(rng);
let h = E::G2Projective::rand(rng);
let g = E::G1::rand(rng);
let h = E::G2::rand(rng);
let mut powers_of_g = Vec::new(); let mut powers_of_g = Vec::new();
let t: Vec<_> = (0..num_vars).map(|_| E::Fr::rand(rng)).collect();
let scalar_bits = E::Fr::size_in_bits();
let t: Vec<_> = (0..num_vars).map(|_| E::ScalarField::rand(rng)).collect();
let scalar_bits = E::ScalarField::MODULUS_BIT_SIZE as usize;
let mut eq: LinkedList<DenseMultilinearExtension<E::Fr>> =
let mut eq: LinkedList<DenseMultilinearExtension<E::ScalarField>> =
LinkedList::from_iter(eq_extension(&t).into_iter()); LinkedList::from_iter(eq_extension(&t).into_iter());
let mut eq_arr = LinkedList::new(); let mut eq_arr = LinkedList::new();
let mut base = eq.pop_back().unwrap().evaluations; let mut base = eq.pop_back().unwrap().evaluations;
@ -177,12 +169,15 @@ impl StructuredReferenceString for MultilinearUniversalPara
pp_powers.extend(pp_k_powers); pp_powers.extend(pp_k_powers);
total_scalars += 1 << (num_vars - i); total_scalars += 1 << (num_vars - i);
} }
let window_size = FixedBaseMSM::get_mul_window_size(total_scalars);
let g_table = FixedBaseMSM::get_window_table(scalar_bits, window_size, g);
let pp_g = E::G1Projective::batch_normalization_into_affine(
&FixedBaseMSM::multi_scalar_mul(scalar_bits, window_size, &g_table, &pp_powers),
);
let window_size = FixedBase::get_mul_window_size(total_scalars);
let g_table = FixedBase::get_window_table(scalar_bits, window_size, g);
let pp_g = E::G1::normalize_batch(&FixedBase::msm(
scalar_bits,
window_size,
&g_table,
&pp_powers,
));
let mut start = 0; let mut start = 0;
for i in 0..num_vars { for i in 0..num_vars {
@ -191,8 +186,8 @@ impl StructuredReferenceString for MultilinearUniversalPara
evals: pp_g[start..(start + size)].to_vec(), evals: pp_g[start..(start + size)].to_vec(),
}; };
// check correctness of pp_k_g // check correctness of pp_k_g
let t_eval_0 = eq_eval(&vec![E::Fr::zero(); num_vars - i], &t[i..num_vars])?;
assert_eq!(g.mul(t_eval_0.into_repr()).into_affine(), pp_k_g.evals[0]);
let t_eval_0 = eq_eval(&vec![E::ScalarField::zero(); num_vars - i], &t[i..num_vars])?;
assert_eq!((g * t_eval_0).into(), pp_k_g.evals[0]);
powers_of_g.push(pp_k_g); powers_of_g.push(pp_k_g);
start += size; start += size;
} }
@ -212,14 +207,9 @@ impl StructuredReferenceString for MultilinearUniversalPara
let vp_generation_timer = start_timer!(|| "VP generation"); let vp_generation_timer = start_timer!(|| "VP generation");
let h_mask = { let h_mask = {
let window_size = FixedBaseMSM::get_mul_window_size(num_vars);
let h_table = FixedBaseMSM::get_window_table(scalar_bits, window_size, h);
E::G2Projective::batch_normalization_into_affine(&FixedBaseMSM::multi_scalar_mul(
scalar_bits,
window_size,
&h_table,
&t,
))
let window_size = FixedBase::get_mul_window_size(num_vars);
let h_table = FixedBase::get_window_table(scalar_bits, window_size, h);
E::G2::normalize_batch(&FixedBase::msm(scalar_bits, window_size, &h_table, &t))
}; };
end_timer!(vp_generation_timer); end_timer!(vp_generation_timer);
end_timer!(total_timer); end_timer!(total_timer);

+ 3
- 3
subroutines/src/pcs/structs.rs

@ -4,8 +4,8 @@
// You should have received a copy of the MIT License // You should have received a copy of the MIT License
// along with the HyperPlonk library. If not, see <https://mit-license.org/>. // along with the HyperPlonk library. If not, see <https://mit-license.org/>.
use ark_ec::PairingEngine;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write};
use ark_ec::pairing::Pairing;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use derivative::Derivative; use derivative::Derivative;
#[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)] #[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)]
@ -19,7 +19,7 @@ use derivative::Derivative;
Eq(bound = "") Eq(bound = "")
)] )]
/// A commitment is an Affine point. /// A commitment is an Affine point.
pub struct Commitment<E: PairingEngine>(
pub struct Commitment<E: Pairing>(
/// the actual commitment is an affine point. /// the actual commitment is an affine point.
pub E::G1Affine, pub E::G1Affine,
); );

+ 41
- 51
subroutines/src/pcs/univariate_kzg/mod.rs

@ -9,49 +9,45 @@
use crate::pcs::{ use crate::pcs::{
prelude::Commitment, PCSError, PolynomialCommitmentScheme, StructuredReferenceString, prelude::Commitment, PCSError, PolynomialCommitmentScheme, StructuredReferenceString,
}; };
use ark_ec::{msm::VariableBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ec::{
pairing::Pairing, scalar_mul::variable_base::VariableBaseMSM, AffineRepr, CurveGroup,
};
use ark_ff::PrimeField; use ark_ff::PrimeField;
use ark_poly::{univariate::DensePolynomial, Polynomial, UVPolynomial};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write};
use ark_poly::{univariate::DensePolynomial, DenseUVPolynomial, Polynomial};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_std::{ use ark_std::{
borrow::Borrow,
end_timer, format,
marker::PhantomData,
rand::{CryptoRng, RngCore},
start_timer,
string::ToString,
vec,
vec::Vec,
One,
borrow::Borrow, end_timer, format, marker::PhantomData, rand::Rng, start_timer,
string::ToString, vec, vec::Vec, One,
}; };
use srs::{UnivariateProverParam, UnivariateUniversalParams, UnivariateVerifierParam}; use srs::{UnivariateProverParam, UnivariateUniversalParams, UnivariateVerifierParam};
use std::ops::Mul;
pub(crate) mod srs; pub(crate) mod srs;
/// KZG Polynomial Commitment Scheme on univariate polynomial. /// KZG Polynomial Commitment Scheme on univariate polynomial.
pub struct UnivariateKzgPCS<E: PairingEngine> {
pub struct UnivariateKzgPCS<E: Pairing> {
#[doc(hidden)] #[doc(hidden)]
phantom: PhantomData<E>, phantom: PhantomData<E>,
} }
#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq, Eq)] #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq, Eq)]
/// proof of opening /// proof of opening
pub struct UnivariateKzgProof<E: PairingEngine> {
pub struct UnivariateKzgProof<E: Pairing> {
/// Evaluation of quotients /// Evaluation of quotients
pub proof: E::G1Affine, pub proof: E::G1Affine,
} }
/// batch proof /// batch proof
pub type UnivariateKzgBatchProof<E> = Vec<UnivariateKzgProof<E>>; pub type UnivariateKzgBatchProof<E> = Vec<UnivariateKzgProof<E>>;
impl<E: PairingEngine> PolynomialCommitmentScheme<E> for UnivariateKzgPCS<E> {
impl<E: Pairing> PolynomialCommitmentScheme<E> for UnivariateKzgPCS<E> {
// Parameters // Parameters
type ProverParam = UnivariateProverParam<E::G1Affine>; type ProverParam = UnivariateProverParam<E::G1Affine>;
type VerifierParam = UnivariateVerifierParam<E>; type VerifierParam = UnivariateVerifierParam<E>;
type SRS = UnivariateUniversalParams<E>; type SRS = UnivariateUniversalParams<E>;
// Polynomial and its associated types // Polynomial and its associated types
type Polynomial = DensePolynomial<E::Fr>;
type Point = E::Fr;
type Evaluation = E::Fr;
type Polynomial = DensePolynomial<E::ScalarField>;
type Point = E::ScalarField;
type Evaluation = E::ScalarField;
// Polynomial and its associated types // Polynomial and its associated types
type Commitment = Commitment<E>; type Commitment = Commitment<E>;
type Proof = UnivariateKzgProof<E>; type Proof = UnivariateKzgProof<E>;
@ -65,7 +61,7 @@ impl PolynomialCommitmentScheme for UnivariateKzgPCS {
/// ///
/// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY.
/// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION.
fn gen_srs_for_testing<R: RngCore + CryptoRng>(
fn gen_srs_for_testing<R: Rng>(
rng: &mut R, rng: &mut R,
supported_size: usize, supported_size: usize,
) -> Result<Self::SRS, PCSError> { ) -> Result<Self::SRS, PCSError> {
@ -107,10 +103,10 @@ impl PolynomialCommitmentScheme for UnivariateKzgPCS {
))); )));
} }
let (num_leading_zeros, plain_coeffs) = skip_leading_zeros_and_convert_to_bigints(poly);
let (num_leading_zeros, plain_coeffs) = skip_leading_zeros(poly);
let msm_time = start_timer!(|| "MSM to compute commitment to plaintext poly"); let msm_time = start_timer!(|| "MSM to compute commitment to plaintext poly");
let commitment = VariableBaseMSM::multi_scalar_mul(
let commitment = E::G1::msm_unchecked(
&prover_param.powers_of_g[num_leading_zeros..], &prover_param.powers_of_g[num_leading_zeros..],
&plain_coeffs, &plain_coeffs,
) )
@ -130,16 +126,15 @@ impl PolynomialCommitmentScheme for UnivariateKzgPCS {
) -> Result<(Self::Proof, Self::Evaluation), PCSError> { ) -> Result<(Self::Proof, Self::Evaluation), PCSError> {
let open_time = let open_time =
start_timer!(|| format!("Opening polynomial of degree {}", polynomial.degree())); start_timer!(|| format!("Opening polynomial of degree {}", polynomial.degree()));
let divisor = Self::Polynomial::from_coefficients_vec(vec![-*point, E::Fr::one()]);
let divisor = Self::Polynomial::from_coefficients_vec(vec![-*point, E::ScalarField::one()]);
let witness_time = start_timer!(|| "Computing witness polynomial"); let witness_time = start_timer!(|| "Computing witness polynomial");
let witness_polynomial = polynomial / &divisor; let witness_polynomial = polynomial / &divisor;
end_timer!(witness_time); end_timer!(witness_time);
let (num_leading_zeros, witness_coeffs) =
skip_leading_zeros_and_convert_to_bigints(&witness_polynomial);
let (num_leading_zeros, witness_coeffs) = skip_leading_zeros(&witness_polynomial);
let proof = VariableBaseMSM::multi_scalar_mul(
let proof = E::G1::msm_unchecked(
&prover_param.borrow().powers_of_g[num_leading_zeros..], &prover_param.borrow().powers_of_g[num_leading_zeros..],
&witness_coeffs, &witness_coeffs,
) )
@ -157,45 +152,36 @@ impl PolynomialCommitmentScheme for UnivariateKzgPCS {
verifier_param: &Self::VerifierParam, verifier_param: &Self::VerifierParam,
commitment: &Self::Commitment, commitment: &Self::Commitment,
point: &Self::Point, point: &Self::Point,
value: &E::Fr,
value: &E::ScalarField,
proof: &Self::Proof, proof: &Self::Proof,
) -> Result<bool, PCSError> { ) -> Result<bool, PCSError> {
let check_time = start_timer!(|| "Checking evaluation"); let check_time = start_timer!(|| "Checking evaluation");
let pairing_inputs: Vec<(E::G1Prepared, E::G2Prepared)> = vec![ let pairing_inputs: Vec<(E::G1Prepared, E::G2Prepared)> = vec![
( (
(verifier_param.g.mul(value.into_repr())
- proof.proof.mul(point.into_repr())
- commitment.0.into_projective())
.into_affine()
.into(),
(verifier_param.g.mul(value) - proof.proof.mul(point) - commitment.0.into_group())
.into_affine()
.into(),
verifier_param.h.into(), verifier_param.h.into(),
), ),
(proof.proof.into(), verifier_param.beta_h.into()), (proof.proof.into(), verifier_param.beta_h.into()),
]; ];
let res = E::product_of_pairings(pairing_inputs.iter()).is_one();
let p1 = pairing_inputs.iter().map(|(a, _)| a.clone());
let p2 = pairing_inputs.iter().map(|(_, a)| a.clone());
let res = E::multi_pairing(p1, p2).0.is_one();
end_timer!(check_time, || format!("Result: {}", res)); end_timer!(check_time, || format!("Result: {}", res));
Ok(res) Ok(res)
} }
} }
fn skip_leading_zeros_and_convert_to_bigints<F: PrimeField, P: UVPolynomial<F>>(
p: &P,
) -> (usize, Vec<F::BigInt>) {
fn skip_leading_zeros<F: PrimeField, P: DenseUVPolynomial<F>>(p: &P) -> (usize, &[F]) {
let mut num_leading_zeros = 0; let mut num_leading_zeros = 0;
while num_leading_zeros < p.coeffs().len() && p.coeffs()[num_leading_zeros].is_zero() { while num_leading_zeros < p.coeffs().len() && p.coeffs()[num_leading_zeros].is_zero() {
num_leading_zeros += 1; num_leading_zeros += 1;
} }
let coeffs = convert_to_bigints(&p.coeffs()[num_leading_zeros..]);
(num_leading_zeros, coeffs)
}
fn convert_to_bigints<F: PrimeField>(p: &[F]) -> Vec<F::BigInt> {
let to_bigint_time = start_timer!(|| "Converting polynomial coeffs to bigints");
let coeffs = p.iter().map(|s| s.into_repr()).collect::<Vec<_>>();
end_timer!(to_bigint_time);
coeffs
(num_leading_zeros, &p.coeffs()[num_leading_zeros..])
} }
#[cfg(test)] #[cfg(test)]
@ -203,13 +189,13 @@ mod tests {
use super::*; use super::*;
use crate::StructuredReferenceString; use crate::StructuredReferenceString;
use ark_bls12_381::Bls12_381; use ark_bls12_381::Bls12_381;
use ark_ec::PairingEngine;
use ark_ec::pairing::Pairing;
use ark_poly::univariate::DensePolynomial; use ark_poly::univariate::DensePolynomial;
use ark_std::{test_rng, UniformRand}; use ark_std::{test_rng, UniformRand};
fn end_to_end_test_template<E>() -> Result<(), PCSError> fn end_to_end_test_template<E>() -> Result<(), PCSError>
where where
E: PairingEngine,
E: Pairing,
{ {
let rng = &mut test_rng(); let rng = &mut test_rng();
for _ in 0..100 { for _ in 0..100 {
@ -219,9 +205,11 @@ mod tests {
} }
let pp = UnivariateKzgPCS::<E>::gen_srs_for_testing(rng, degree)?; let pp = UnivariateKzgPCS::<E>::gen_srs_for_testing(rng, degree)?;
let (ck, vk) = pp.trim(degree)?; let (ck, vk) = pp.trim(degree)?;
let p = <DensePolynomial<E::Fr> as UVPolynomial<E::Fr>>::rand(degree, rng);
let p = <DensePolynomial<E::ScalarField> as DenseUVPolynomial<E::ScalarField>>::rand(
degree, rng,
);
let comm = UnivariateKzgPCS::<E>::commit(&ck, &p)?; let comm = UnivariateKzgPCS::<E>::commit(&ck, &p)?;
let point = E::Fr::rand(rng);
let point = E::ScalarField::rand(rng);
let (proof, value) = UnivariateKzgPCS::<E>::open(&ck, &p, &point)?; let (proof, value) = UnivariateKzgPCS::<E>::open(&ck, &p, &point)?;
assert!( assert!(
UnivariateKzgPCS::<E>::verify(&vk, &comm, &point, &value, &proof)?, UnivariateKzgPCS::<E>::verify(&vk, &comm, &point, &value, &proof)?,
@ -235,7 +223,7 @@ mod tests {
fn linear_polynomial_test_template<E>() -> Result<(), PCSError> fn linear_polynomial_test_template<E>() -> Result<(), PCSError>
where where
E: PairingEngine,
E: Pairing,
{ {
let rng = &mut test_rng(); let rng = &mut test_rng();
for _ in 0..100 { for _ in 0..100 {
@ -243,9 +231,11 @@ mod tests {
let pp = UnivariateKzgPCS::<E>::gen_srs_for_testing(rng, degree)?; let pp = UnivariateKzgPCS::<E>::gen_srs_for_testing(rng, degree)?;
let (ck, vk) = pp.trim(degree)?; let (ck, vk) = pp.trim(degree)?;
let p = <DensePolynomial<E::Fr> as UVPolynomial<E::Fr>>::rand(degree, rng);
let p = <DensePolynomial<E::ScalarField> as DenseUVPolynomial<E::ScalarField>>::rand(
degree, rng,
);
let comm = UnivariateKzgPCS::<E>::commit(&ck, &p)?; let comm = UnivariateKzgPCS::<E>::commit(&ck, &p)?;
let point = E::Fr::rand(rng);
let point = E::ScalarField::rand(rng);
let (proof, value) = UnivariateKzgPCS::<E>::open(&ck, &p, &point)?; let (proof, value) = UnivariateKzgPCS::<E>::open(&ck, &p, &point)?;
assert!( assert!(
UnivariateKzgPCS::<E>::verify(&vk, &comm, &point, &value, &proof)?, UnivariateKzgPCS::<E>::verify(&vk, &comm, &point, &value, &proof)?,

+ 20
- 32
subroutines/src/pcs/univariate_kzg/srs.rs

@ -7,23 +7,18 @@
//! Implementing Structured Reference Strings for univariate polynomial KZG //! Implementing Structured Reference Strings for univariate polynomial KZG
use crate::pcs::{PCSError, StructuredReferenceString}; use crate::pcs::{PCSError, StructuredReferenceString};
use ark_ec::{msm::FixedBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ec::{pairing::Pairing, scalar_mul::fixed_base::FixedBase, AffineRepr, CurveGroup};
use ark_ff::PrimeField; use ark_ff::PrimeField;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write};
use ark_std::{
end_timer,
rand::{CryptoRng, RngCore},
start_timer, vec,
vec::Vec,
One, UniformRand,
};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_std::{end_timer, rand::Rng, start_timer, vec, vec::Vec, One, UniformRand};
use derivative::Derivative; use derivative::Derivative;
use std::ops::Mul;
/// `UniversalParams` are the universal parameters for the KZG10 scheme. /// `UniversalParams` are the universal parameters for the KZG10 scheme.
// Adapted from // Adapted from
// https://github.com/arkworks-rs/poly-commit/blob/master/src/kzg10/data_structures.rs#L20 // https://github.com/arkworks-rs/poly-commit/blob/master/src/kzg10/data_structures.rs#L20
#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize, Default)] #[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize, Default)]
pub struct UnivariateUniversalParams<E: PairingEngine> {
pub struct UnivariateUniversalParams<E: Pairing> {
/// Group elements of the form `{ \beta^i G }`, where `i` ranges from 0 to /// Group elements of the form `{ \beta^i G }`, where `i` ranges from 0 to
/// `degree`. /// `degree`.
pub powers_of_g: Vec<E::G1Affine>, pub powers_of_g: Vec<E::G1Affine>,
@ -33,7 +28,7 @@ pub struct UnivariateUniversalParams {
pub beta_h: E::G2Affine, pub beta_h: E::G2Affine,
} }
impl<E: PairingEngine> UnivariateUniversalParams<E> {
impl<E: Pairing> UnivariateUniversalParams<E> {
/// Returns the maximum supported degree /// Returns the maximum supported degree
pub fn max_degree(&self) -> usize { pub fn max_degree(&self) -> usize {
self.powers_of_g.len() self.powers_of_g.len()
@ -42,7 +37,7 @@ impl UnivariateUniversalParams {
/// `UnivariateProverParam` is used to generate a proof /// `UnivariateProverParam` is used to generate a proof
#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, Eq, PartialEq, Default)] #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, Eq, PartialEq, Default)]
pub struct UnivariateProverParam<C: AffineCurve> {
pub struct UnivariateProverParam<C: AffineRepr> {
/// Parameters /// Parameters
pub powers_of_g: Vec<C>, pub powers_of_g: Vec<C>,
} }
@ -58,7 +53,7 @@ pub struct UnivariateProverParam {
PartialEq(bound = ""), PartialEq(bound = ""),
Eq(bound = "") Eq(bound = "")
)] )]
pub struct UnivariateVerifierParam<E: PairingEngine> {
pub struct UnivariateVerifierParam<E: Pairing> {
/// The generator of G1. /// The generator of G1.
pub g: E::G1Affine, pub g: E::G1Affine,
/// The generator of G2. /// The generator of G2.
@ -67,7 +62,7 @@ pub struct UnivariateVerifierParam {
pub beta_h: E::G2Affine, pub beta_h: E::G2Affine,
} }
impl<E: PairingEngine> StructuredReferenceString<E> for UnivariateUniversalParams<E> {
impl<E: Pairing> StructuredReferenceString<E> for UnivariateUniversalParams<E> {
type ProverParam = UnivariateProverParam<E::G1Affine>; type ProverParam = UnivariateProverParam<E::G1Affine>;
type VerifierParam = UnivariateVerifierParam<E>; type VerifierParam = UnivariateVerifierParam<E>;
@ -109,16 +104,13 @@ impl StructuredReferenceString for UnivariateUniversalParam
/// Build SRS for testing. /// Build SRS for testing.
/// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY. /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY.
/// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION. /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION.
fn gen_srs_for_testing<R: RngCore + CryptoRng>(
rng: &mut R,
max_degree: usize,
) -> Result<Self, PCSError> {
fn gen_srs_for_testing<R: Rng>(rng: &mut R, max_degree: usize) -> Result<Self, PCSError> {
let setup_time = start_timer!(|| format!("KZG10::Setup with degree {}", max_degree)); let setup_time = start_timer!(|| format!("KZG10::Setup with degree {}", max_degree));
let beta = E::Fr::rand(rng);
let g = E::G1Projective::rand(rng);
let h = E::G2Projective::rand(rng);
let beta = E::ScalarField::rand(rng);
let g = E::G1::rand(rng);
let h = E::G2::rand(rng);
let mut powers_of_beta = vec![E::Fr::one()];
let mut powers_of_beta = vec![E::ScalarField::one()];
let mut cur = beta; let mut cur = beta;
for _ in 0..max_degree { for _ in 0..max_degree {
@ -126,21 +118,17 @@ impl StructuredReferenceString for UnivariateUniversalParam
cur *= &beta; cur *= &beta;
} }
let window_size = FixedBaseMSM::get_mul_window_size(max_degree + 1);
let window_size = FixedBase::get_mul_window_size(max_degree + 1);
let scalar_bits = E::Fr::size_in_bits();
let scalar_bits = E::ScalarField::MODULUS_BIT_SIZE as usize;
let g_time = start_timer!(|| "Generating powers of G"); let g_time = start_timer!(|| "Generating powers of G");
// TODO: parallelization // TODO: parallelization
let g_table = FixedBaseMSM::get_window_table(scalar_bits, window_size, g);
let powers_of_g = FixedBaseMSM::multi_scalar_mul::<E::G1Projective>(
scalar_bits,
window_size,
&g_table,
&powers_of_beta,
);
let g_table = FixedBase::get_window_table(scalar_bits, window_size, g);
let powers_of_g =
FixedBase::msm::<E::G1>(scalar_bits, window_size, &g_table, &powers_of_beta);
end_timer!(g_time); end_timer!(g_time);
let powers_of_g = E::G1Projective::batch_normalization_into_affine(&powers_of_g);
let powers_of_g = E::G1::normalize_batch(&powers_of_g);
let h = h.into_affine(); let h = h.into_affine();
let beta_h = h.mul(beta).into_affine(); let beta_h = h.mul(beta).into_affine();

+ 37
- 31
subroutines/src/poly_iop/perm_check/mod.rs

@ -11,7 +11,7 @@ use crate::{
pcs::PolynomialCommitmentScheme, pcs::PolynomialCommitmentScheme,
poly_iop::{errors::PolyIOPErrors, prelude::ProductCheck, PolyIOP}, poly_iop::{errors::PolyIOPErrors, prelude::ProductCheck, PolyIOP},
}; };
use ark_ec::PairingEngine;
use ark_ec::pairing::Pairing;
use ark_poly::DenseMultilinearExtension; use ark_poly::DenseMultilinearExtension;
use ark_std::{end_timer, start_timer}; use ark_std::{end_timer, start_timer};
use std::sync::Arc; use std::sync::Arc;
@ -23,14 +23,14 @@ use transcript::IOPTranscript;
#[derive(Clone, Debug, Default, PartialEq)] #[derive(Clone, Debug, Default, PartialEq)]
pub struct PermutationCheckSubClaim<E, PCS, PC> pub struct PermutationCheckSubClaim<E, PCS, PC>
where where
E: PairingEngine,
E: Pairing,
PC: ProductCheck<E, PCS>, PC: ProductCheck<E, PCS>,
PCS: PolynomialCommitmentScheme<E>, PCS: PolynomialCommitmentScheme<E>,
{ {
/// the SubClaim from the ProductCheck /// the SubClaim from the ProductCheck
pub product_check_sub_claim: PC::ProductCheckSubClaim, pub product_check_sub_claim: PC::ProductCheckSubClaim,
/// Challenges beta and gamma /// Challenges beta and gamma
pub challenges: (E::Fr, E::Fr),
pub challenges: (E::ScalarField, E::ScalarField),
} }
pub mod util; pub mod util;
@ -48,7 +48,7 @@ pub mod util;
/// - permutation oracles = (p1, ..., pk) /// - permutation oracles = (p1, ..., pk)
pub trait PermutationCheck<E, PCS>: ProductCheck<E, PCS> pub trait PermutationCheck<E, PCS>: ProductCheck<E, PCS>
where where
E: PairingEngine,
E: Pairing,
PCS: PolynomialCommitmentScheme<E>, PCS: PolynomialCommitmentScheme<E>,
{ {
type PermutationCheckSubClaim; type PermutationCheckSubClaim;
@ -79,7 +79,7 @@ where
fxs: &[Self::MultilinearExtension], fxs: &[Self::MultilinearExtension],
gxs: &[Self::MultilinearExtension], gxs: &[Self::MultilinearExtension],
perms: &[Self::MultilinearExtension], perms: &[Self::MultilinearExtension],
transcript: &mut IOPTranscript<E::Fr>,
transcript: &mut IOPTranscript<E::ScalarField>,
) -> Result< ) -> Result<
( (
Self::PermutationProof, Self::PermutationProof,
@ -98,16 +98,16 @@ where
) -> Result<Self::PermutationCheckSubClaim, PolyIOPErrors>; ) -> Result<Self::PermutationCheckSubClaim, PolyIOPErrors>;
} }
impl<E, PCS> PermutationCheck<E, PCS> for PolyIOP<E::Fr>
impl<E, PCS> PermutationCheck<E, PCS> for PolyIOP<E::ScalarField>
where where
E: PairingEngine,
PCS: PolynomialCommitmentScheme<E, Polynomial = Arc<DenseMultilinearExtension<E::Fr>>>,
E: Pairing,
PCS: PolynomialCommitmentScheme<E, Polynomial = Arc<DenseMultilinearExtension<E::ScalarField>>>,
{ {
type PermutationCheckSubClaim = PermutationCheckSubClaim<E, PCS, Self>; type PermutationCheckSubClaim = PermutationCheckSubClaim<E, PCS, Self>;
type PermutationProof = Self::ProductCheckProof; type PermutationProof = Self::ProductCheckProof;
fn init_transcript() -> Self::Transcript { fn init_transcript() -> Self::Transcript {
IOPTranscript::<E::Fr>::new(b"Initializing PermutationCheck transcript")
IOPTranscript::<E::ScalarField>::new(b"Initializing PermutationCheck transcript")
} }
fn prove( fn prove(
@ -115,7 +115,7 @@ where
fxs: &[Self::MultilinearExtension], fxs: &[Self::MultilinearExtension],
gxs: &[Self::MultilinearExtension], gxs: &[Self::MultilinearExtension],
perms: &[Self::MultilinearExtension], perms: &[Self::MultilinearExtension],
transcript: &mut IOPTranscript<E::Fr>,
transcript: &mut IOPTranscript<E::ScalarField>,
) -> Result< ) -> Result<
( (
Self::PermutationProof, Self::PermutationProof,
@ -195,22 +195,25 @@ mod test {
}; };
use arithmetic::{evaluate_opt, identity_permutation_mles, random_permutation_mles, VPAuxInfo}; use arithmetic::{evaluate_opt, identity_permutation_mles, random_permutation_mles, VPAuxInfo};
use ark_bls12_381::Bls12_381; use ark_bls12_381::Bls12_381;
use ark_ec::PairingEngine;
use ark_ec::pairing::Pairing;
use ark_poly::{DenseMultilinearExtension, MultilinearExtension}; use ark_poly::{DenseMultilinearExtension, MultilinearExtension};
use ark_std::test_rng; use ark_std::test_rng;
use std::{marker::PhantomData, sync::Arc}; use std::{marker::PhantomData, sync::Arc};
type KZG = MultilinearKzgPCS<Bls12_381>;
type Kzg = MultilinearKzgPCS<Bls12_381>;
fn test_permutation_check_helper<E, PCS>( fn test_permutation_check_helper<E, PCS>(
pcs_param: &PCS::ProverParam, pcs_param: &PCS::ProverParam,
fxs: &[Arc<DenseMultilinearExtension<E::Fr>>],
gxs: &[Arc<DenseMultilinearExtension<E::Fr>>],
perms: &[Arc<DenseMultilinearExtension<E::Fr>>],
fxs: &[Arc<DenseMultilinearExtension<E::ScalarField>>],
gxs: &[Arc<DenseMultilinearExtension<E::ScalarField>>],
perms: &[Arc<DenseMultilinearExtension<E::ScalarField>>],
) -> Result<(), PolyIOPErrors> ) -> Result<(), PolyIOPErrors>
where where
E: PairingEngine,
PCS: PolynomialCommitmentScheme<E, Polynomial = Arc<DenseMultilinearExtension<E::Fr>>>,
E: Pairing,
PCS: PolynomialCommitmentScheme<
E,
Polynomial = Arc<DenseMultilinearExtension<E::ScalarField>>,
>,
{ {
let nv = fxs[0].num_vars; let nv = fxs[0].num_vars;
// what's AuxInfo used for? // what's AuxInfo used for?
@ -221,20 +224,23 @@ mod test {
}; };
// prover // prover
let mut transcript = <PolyIOP<E::Fr> as PermutationCheck<E, PCS>>::init_transcript();
let mut transcript =
<PolyIOP<E::ScalarField> as PermutationCheck<E, PCS>>::init_transcript();
transcript.append_message(b"testing", b"initializing transcript for testing")?; transcript.append_message(b"testing", b"initializing transcript for testing")?;
let (proof, prod_x, _frac_poly) = <PolyIOP<E::Fr> as PermutationCheck<E, PCS>>::prove(
pcs_param,
fxs,
gxs,
perms,
&mut transcript,
)?;
let (proof, prod_x, _frac_poly) =
<PolyIOP<E::ScalarField> as PermutationCheck<E, PCS>>::prove(
pcs_param,
fxs,
gxs,
perms,
&mut transcript,
)?;
// verifier // verifier
let mut transcript = <PolyIOP<E::Fr> as PermutationCheck<E, PCS>>::init_transcript();
let mut transcript =
<PolyIOP<E::ScalarField> as PermutationCheck<E, PCS>>::init_transcript();
transcript.append_message(b"testing", b"initializing transcript for testing")?; transcript.append_message(b"testing", b"initializing transcript for testing")?;
let perm_check_sub_claim = <PolyIOP<E::Fr> as PermutationCheck<E, PCS>>::verify(
let perm_check_sub_claim = <PolyIOP<E::ScalarField> as PermutationCheck<E, PCS>>::verify(
&proof, &proof,
&poly_info, &poly_info,
&mut transcript, &mut transcript,
@ -267,7 +273,7 @@ mod test {
Arc::new(DenseMultilinearExtension::rand(nv, &mut rng)), Arc::new(DenseMultilinearExtension::rand(nv, &mut rng)),
]; ];
// perms is the identity map // perms is the identity map
test_permutation_check_helper::<Bls12_381, KZG>(&pcs_param, &ws, &ws, &id_perms)?;
test_permutation_check_helper::<Bls12_381, Kzg>(&pcs_param, &ws, &ws, &id_perms)?;
} }
{ {
@ -281,7 +287,7 @@ mod test {
// perms is the reverse identity map // perms is the reverse identity map
let mut perms = id_perms.clone(); let mut perms = id_perms.clone();
perms.reverse(); perms.reverse();
test_permutation_check_helper::<Bls12_381, KZG>(&pcs_param, &fs, &gs, &perms)?;
test_permutation_check_helper::<Bls12_381, Kzg>(&pcs_param, &fs, &gs, &perms)?;
} }
{ {
@ -294,7 +300,7 @@ mod test {
let perms = random_permutation_mles(nv, 2, &mut rng); let perms = random_permutation_mles(nv, 2, &mut rng);
assert!( assert!(
test_permutation_check_helper::<Bls12_381, KZG>(&pcs_param, &ws, &ws, &perms)
test_permutation_check_helper::<Bls12_381, Kzg>(&pcs_param, &ws, &ws, &perms)
.is_err() .is_err()
); );
} }
@ -311,7 +317,7 @@ mod test {
]; ];
// s_perm is the identity map // s_perm is the identity map
assert!(test_permutation_check_helper::<Bls12_381, KZG>(
assert!(test_permutation_check_helper::<Bls12_381, Kzg>(
&pcs_param, &fs, &gs, &id_perms &pcs_param, &fs, &gs, &id_perms
) )
.is_err()); .is_err());

+ 60
- 43
subroutines/src/poly_iop/prod_check/mod.rs

@ -16,7 +16,7 @@ use crate::{
}, },
}; };
use arithmetic::VPAuxInfo; use arithmetic::VPAuxInfo;
use ark_ec::PairingEngine;
use ark_ec::pairing::Pairing;
use ark_ff::{One, PrimeField, Zero}; use ark_ff::{One, PrimeField, Zero};
use ark_poly::DenseMultilinearExtension; use ark_poly::DenseMultilinearExtension;
use ark_std::{end_timer, start_timer}; use ark_std::{end_timer, start_timer};
@ -52,9 +52,9 @@ mod util;
/// 2. `generate_challenge` from current transcript (generate alpha) /// 2. `generate_challenge` from current transcript (generate alpha)
/// 3. `verify` to verify the zerocheck proof and generate the subclaim for /// 3. `verify` to verify the zerocheck proof and generate the subclaim for
/// polynomial evaluations /// polynomial evaluations
pub trait ProductCheck<E, PCS>: ZeroCheck<E::Fr>
pub trait ProductCheck<E, PCS>: ZeroCheck<E::ScalarField>
where where
E: PairingEngine,
E: Pairing,
PCS: PolynomialCommitmentScheme<E>, PCS: PolynomialCommitmentScheme<E>,
{ {
type ProductCheckSubClaim; type ProductCheckSubClaim;
@ -90,7 +90,7 @@ where
pcs_param: &PCS::ProverParam, pcs_param: &PCS::ProverParam,
fxs: &[Self::MultilinearExtension], fxs: &[Self::MultilinearExtension],
gxs: &[Self::MultilinearExtension], gxs: &[Self::MultilinearExtension],
transcript: &mut IOPTranscript<E::Fr>,
transcript: &mut IOPTranscript<E::ScalarField>,
) -> Result< ) -> Result<
( (
Self::ProductCheckProof, Self::ProductCheckProof,
@ -106,7 +106,7 @@ where
/// = \prod_{x \in {0,1}^n} g1(x) * ... * gk(x)` /// = \prod_{x \in {0,1}^n} g1(x) * ... * gk(x)`
fn verify( fn verify(
proof: &Self::ProductCheckProof, proof: &Self::ProductCheckProof,
aux_info: &VPAuxInfo<E::Fr>,
aux_info: &VPAuxInfo<E::ScalarField>,
transcript: &mut Self::Transcript, transcript: &mut Self::Transcript,
) -> Result<Self::ProductCheckSubClaim, PolyIOPErrors>; ) -> Result<Self::ProductCheckSubClaim, PolyIOPErrors>;
} }
@ -136,32 +136,32 @@ pub struct ProductCheckSubClaim> {
/// - a polynomial commitment for the fractional polynomial /// - a polynomial commitment for the fractional polynomial
#[derive(Clone, Debug, Default, PartialEq)] #[derive(Clone, Debug, Default, PartialEq)]
pub struct ProductCheckProof< pub struct ProductCheckProof<
E: PairingEngine,
E: Pairing,
PCS: PolynomialCommitmentScheme<E>, PCS: PolynomialCommitmentScheme<E>,
ZC: ZeroCheck<E::Fr>,
ZC: ZeroCheck<E::ScalarField>,
> { > {
pub zero_check_proof: ZC::ZeroCheckProof, pub zero_check_proof: ZC::ZeroCheckProof,
pub prod_x_comm: PCS::Commitment, pub prod_x_comm: PCS::Commitment,
pub frac_comm: PCS::Commitment, pub frac_comm: PCS::Commitment,
} }
impl<E, PCS> ProductCheck<E, PCS> for PolyIOP<E::Fr>
impl<E, PCS> ProductCheck<E, PCS> for PolyIOP<E::ScalarField>
where where
E: PairingEngine,
PCS: PolynomialCommitmentScheme<E, Polynomial = Arc<DenseMultilinearExtension<E::Fr>>>,
E: Pairing,
PCS: PolynomialCommitmentScheme<E, Polynomial = Arc<DenseMultilinearExtension<E::ScalarField>>>,
{ {
type ProductCheckSubClaim = ProductCheckSubClaim<E::Fr, Self>;
type ProductCheckSubClaim = ProductCheckSubClaim<E::ScalarField, Self>;
type ProductCheckProof = ProductCheckProof<E, PCS, Self>; type ProductCheckProof = ProductCheckProof<E, PCS, Self>;
fn init_transcript() -> Self::Transcript { fn init_transcript() -> Self::Transcript {
IOPTranscript::<E::Fr>::new(b"Initializing ProductCheck transcript")
IOPTranscript::<E::ScalarField>::new(b"Initializing ProductCheck transcript")
} }
fn prove( fn prove(
pcs_param: &PCS::ProverParam, pcs_param: &PCS::ProverParam,
fxs: &[Self::MultilinearExtension], fxs: &[Self::MultilinearExtension],
gxs: &[Self::MultilinearExtension], gxs: &[Self::MultilinearExtension],
transcript: &mut IOPTranscript<E::Fr>,
transcript: &mut IOPTranscript<E::ScalarField>,
) -> Result< ) -> Result<
( (
Self::ProductCheckProof, Self::ProductCheckProof,
@ -220,7 +220,7 @@ where
fn verify( fn verify(
proof: &Self::ProductCheckProof, proof: &Self::ProductCheckProof,
aux_info: &VPAuxInfo<E::Fr>,
aux_info: &VPAuxInfo<E::ScalarField>,
transcript: &mut Self::Transcript, transcript: &mut Self::Transcript,
) -> Result<Self::ProductCheckSubClaim, PolyIOPErrors> { ) -> Result<Self::ProductCheckSubClaim, PolyIOPErrors> {
let start = start_timer!(|| "prod_check verify"); let start = start_timer!(|| "prod_check verify");
@ -232,14 +232,17 @@ where
// invoke the zero check on the iop_proof // invoke the zero check on the iop_proof
// the virtual poly info for Q(x) // the virtual poly info for Q(x)
let zero_check_sub_claim =
<Self as ZeroCheck<E::Fr>>::verify(&proof.zero_check_proof, aux_info, transcript)?;
let zero_check_sub_claim = <Self as ZeroCheck<E::ScalarField>>::verify(
&proof.zero_check_proof,
aux_info,
transcript,
)?;
// the final query is on prod_x // the final query is on prod_x
let mut final_query = vec![E::Fr::one(); aux_info.num_variables];
let mut final_query = vec![E::ScalarField::one(); aux_info.num_variables];
// the point has to be reversed because Arkworks uses big-endian. // the point has to be reversed because Arkworks uses big-endian.
final_query[0] = E::Fr::zero();
let final_eval = E::Fr::one();
final_query[0] = E::ScalarField::zero();
let final_eval = E::ScalarField::one();
end_timer!(start); end_timer!(start);
@ -260,53 +263,60 @@ mod test {
}; };
use arithmetic::VPAuxInfo; use arithmetic::VPAuxInfo;
use ark_bls12_381::{Bls12_381, Fr}; use ark_bls12_381::{Bls12_381, Fr};
use ark_ec::PairingEngine;
use ark_ec::pairing::Pairing;
use ark_poly::{DenseMultilinearExtension, MultilinearExtension}; use ark_poly::{DenseMultilinearExtension, MultilinearExtension};
use ark_std::test_rng; use ark_std::test_rng;
use std::{marker::PhantomData, sync::Arc}; use std::{marker::PhantomData, sync::Arc};
fn check_frac_poly<E>( fn check_frac_poly<E>(
frac_poly: &Arc<DenseMultilinearExtension<E::Fr>>,
fs: &[Arc<DenseMultilinearExtension<E::Fr>>],
gs: &[Arc<DenseMultilinearExtension<E::Fr>>],
frac_poly: &Arc<DenseMultilinearExtension<E::ScalarField>>,
fs: &[Arc<DenseMultilinearExtension<E::ScalarField>>],
gs: &[Arc<DenseMultilinearExtension<E::ScalarField>>],
) where ) where
E: PairingEngine,
E: Pairing,
{ {
let mut flag = true; let mut flag = true;
let num_vars = frac_poly.num_vars; let num_vars = frac_poly.num_vars;
for i in 0..1 << num_vars { for i in 0..1 << num_vars {
let nom = fs let nom = fs
.iter() .iter()
.fold(E::Fr::from(1u8), |acc, f| acc * f.evaluations[i]);
.fold(E::ScalarField::from(1u8), |acc, f| acc * f.evaluations[i]);
let denom = gs let denom = gs
.iter() .iter()
.fold(E::Fr::from(1u8), |acc, g| acc * g.evaluations[i]);
.fold(E::ScalarField::from(1u8), |acc, g| acc * g.evaluations[i]);
if denom * frac_poly.evaluations[i] != nom { if denom * frac_poly.evaluations[i] != nom {
flag = false; flag = false;
break; break;
} }
} }
assert_eq!(flag, true);
assert!(flag);
} }
// fs and gs are guaranteed to have the same product // fs and gs are guaranteed to have the same product
// fs and hs doesn't have the same product // fs and hs doesn't have the same product
fn test_product_check_helper<E, PCS>( fn test_product_check_helper<E, PCS>(
fs: &[Arc<DenseMultilinearExtension<E::Fr>>],
gs: &[Arc<DenseMultilinearExtension<E::Fr>>],
hs: &[Arc<DenseMultilinearExtension<E::Fr>>],
fs: &[Arc<DenseMultilinearExtension<E::ScalarField>>],
gs: &[Arc<DenseMultilinearExtension<E::ScalarField>>],
hs: &[Arc<DenseMultilinearExtension<E::ScalarField>>],
pcs_param: &PCS::ProverParam, pcs_param: &PCS::ProverParam,
) -> Result<(), PolyIOPErrors> ) -> Result<(), PolyIOPErrors>
where where
E: PairingEngine,
PCS: PolynomialCommitmentScheme<E, Polynomial = Arc<DenseMultilinearExtension<E::Fr>>>,
E: Pairing,
PCS: PolynomialCommitmentScheme<
E,
Polynomial = Arc<DenseMultilinearExtension<E::ScalarField>>,
>,
{ {
let mut transcript = <PolyIOP<E::Fr> as ProductCheck<E, PCS>>::init_transcript();
let mut transcript = <PolyIOP<E::ScalarField> as ProductCheck<E, PCS>>::init_transcript();
transcript.append_message(b"testing", b"initializing transcript for testing")?; transcript.append_message(b"testing", b"initializing transcript for testing")?;
let (proof, prod_x, frac_poly) =
<PolyIOP<E::Fr> as ProductCheck<E, PCS>>::prove(pcs_param, fs, gs, &mut transcript)?;
let (proof, prod_x, frac_poly) = <PolyIOP<E::ScalarField> as ProductCheck<E, PCS>>::prove(
pcs_param,
fs,
gs,
&mut transcript,
)?;
let mut transcript = <PolyIOP<E::Fr> as ProductCheck<E, PCS>>::init_transcript();
let mut transcript = <PolyIOP<E::ScalarField> as ProductCheck<E, PCS>>::init_transcript();
transcript.append_message(b"testing", b"initializing transcript for testing")?; transcript.append_message(b"testing", b"initializing transcript for testing")?;
// what's aux_info for? // what's aux_info for?
@ -315,8 +325,11 @@ mod test {
num_variables: fs[0].num_vars, num_variables: fs[0].num_vars,
phantom: PhantomData::default(), phantom: PhantomData::default(),
}; };
let prod_subclaim =
<PolyIOP<E::Fr> as ProductCheck<E, PCS>>::verify(&proof, &aux_info, &mut transcript)?;
let prod_subclaim = <PolyIOP<E::ScalarField> as ProductCheck<E, PCS>>::verify(
&proof,
&aux_info,
&mut transcript,
)?;
assert_eq!( assert_eq!(
prod_x.evaluate(&prod_subclaim.final_query.0).unwrap(), prod_x.evaluate(&prod_subclaim.final_query.0).unwrap(),
prod_subclaim.final_query.1, prod_subclaim.final_query.1,
@ -325,15 +338,19 @@ mod test {
check_frac_poly::<E>(&frac_poly, fs, gs); check_frac_poly::<E>(&frac_poly, fs, gs);
// bad path // bad path
let mut transcript = <PolyIOP<E::Fr> as ProductCheck<E, PCS>>::init_transcript();
let mut transcript = <PolyIOP<E::ScalarField> as ProductCheck<E, PCS>>::init_transcript();
transcript.append_message(b"testing", b"initializing transcript for testing")?; transcript.append_message(b"testing", b"initializing transcript for testing")?;
let (bad_proof, prod_x_bad, frac_poly) =
<PolyIOP<E::Fr> as ProductCheck<E, PCS>>::prove(pcs_param, fs, hs, &mut transcript)?;
let (bad_proof, prod_x_bad, frac_poly) = <PolyIOP<E::ScalarField> as ProductCheck<
E,
PCS,
>>::prove(
pcs_param, fs, hs, &mut transcript
)?;
let mut transcript = <PolyIOP<E::Fr> as ProductCheck<E, PCS>>::init_transcript();
let mut transcript = <PolyIOP<E::ScalarField> as ProductCheck<E, PCS>>::init_transcript();
transcript.append_message(b"testing", b"initializing transcript for testing")?; transcript.append_message(b"testing", b"initializing transcript for testing")?;
let bad_subclaim = <PolyIOP<E::Fr> as ProductCheck<E, PCS>>::verify(
let bad_subclaim = <PolyIOP<E::ScalarField> as ProductCheck<E, PCS>>::verify(
&bad_proof, &bad_proof,
&aux_info, &aux_info,
&mut transcript, &mut transcript,

+ 1
- 1
subroutines/src/poly_iop/structs.rs

@ -8,7 +8,7 @@
use arithmetic::VirtualPolynomial; use arithmetic::VirtualPolynomial;
use ark_ff::PrimeField; use ark_ff::PrimeField;
use ark_serialize::{CanonicalSerialize, SerializationError, Write};
use ark_serialize::CanonicalSerialize;
/// An IOP proof is a collections of /// An IOP proof is a collections of
/// - messages from prover to verifier at each round through the interactive /// - messages from prover to verifier at each round through the interactive

+ 1
- 1
subroutines/src/poly_iop/sum_check/verifier.rs

@ -321,7 +321,7 @@ mod test {
use super::interpolate_uni_poly; use super::interpolate_uni_poly;
use crate::poly_iop::errors::PolyIOPErrors; use crate::poly_iop::errors::PolyIOPErrors;
use ark_bls12_381::Fr; use ark_bls12_381::Fr;
use ark_poly::{univariate::DensePolynomial, Polynomial, UVPolynomial};
use ark_poly::{univariate::DensePolynomial, DenseUVPolynomial, Polynomial};
use ark_std::{vec::Vec, UniformRand}; use ark_std::{vec::Vec, UniformRand};
#[test] #[test]

+ 2
- 2
subroutines/src/poly_iop/utils.rs

@ -13,7 +13,7 @@
macro_rules! to_bytes { macro_rules! to_bytes {
($x:expr) => {{ ($x:expr) => {{
let mut buf = ark_std::vec![]; let mut buf = ark_std::vec![];
ark_serialize::CanonicalSerialize::serialize($x, &mut buf).map(|_| buf)
ark_serialize::CanonicalSerialize::serialize_compressed($x, &mut buf).map(|_| buf)
}}; }};
} }
@ -28,7 +28,7 @@ mod test {
let f1 = Fr::one(); let f1 = Fr::one();
let mut bytes = ark_std::vec![]; let mut bytes = ark_std::vec![];
f1.serialize(&mut bytes).unwrap();
f1.serialize_compressed(&mut bytes).unwrap();
assert_eq!(bytes, to_bytes!(&f1).unwrap()); assert_eq!(bytes, to_bytes!(&f1).unwrap());
} }
} }

+ 3
- 3
transcript/Cargo.toml

@ -6,8 +6,8 @@ edition = "2021"
[dependencies] [dependencies]
ark-ff = { version = "^0.3.0", default-features = false }
ark-serialize = { version = "^0.3.0", default-features = false }
ark-std = { version = "^0.3.0", default-features = false }
ark-ff = { version = "^0.4.0", default-features = false }
ark-serialize = { version = "^0.4.0", default-features = false }
ark-std = { version = "^0.4.0", default-features = false }
displaydoc = { version = "0.2.3", default-features = false } displaydoc = { version = "0.2.3", default-features = false }
merlin = { version = "3.0.0", default-features = false } merlin = { version = "3.0.0", default-features = false }

+ 1
- 1
transcript/src/lib.rs

@ -126,6 +126,6 @@ impl IOPTranscript {
macro_rules! to_bytes { macro_rules! to_bytes {
($x:expr) => {{ ($x:expr) => {{
let mut buf = ark_std::vec![]; let mut buf = ark_std::vec![];
ark_serialize::CanonicalSerialize::serialize($x, &mut buf).map(|_| buf)
ark_serialize::CanonicalSerialize::serialize_compressed($x, &mut buf).map(|_| buf)
}}; }};
} }

Loading…
Cancel
Save