Skip to content

Commit

Permalink
Feature: add support for using MLSumcheck as subprotocol (#73)
Browse files Browse the repository at this point in the history
  • Loading branch information
JayWhite2357 authored May 23, 2023
1 parent 0ce77a0 commit 53244d0
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 15 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

### Improvements

- [\#73](https://github.com/arkworks-rs/sumcheck/pull/73) Add support for using `MLSumcheck` as subprotocol.

- [\#72](https://github.com/arkworks-rs/sumcheck/pull/72) Uses `rayon` in the prover when the `parallel` feature is enabled.

- [\#71](https://github.com/arkworks-rs/sumcheck/pull/71) Improve prover performance by using an arithmetic sequence rather than interpolation inside of the `prove_round` loop.
Expand Down
34 changes: 26 additions & 8 deletions src/ml_sumcheck/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Sumcheck Protocol for multilinear extension
use crate::ml_sumcheck::data_structures::{ListOfProductsOfPolynomials, PolynomialInfo};
use crate::ml_sumcheck::protocol::prover::ProverMsg;
use crate::ml_sumcheck::protocol::prover::{ProverMsg, ProverState};
use crate::ml_sumcheck::protocol::verifier::SubClaim;
use crate::ml_sumcheck::protocol::IPForMLSumcheck;
use crate::rng::{Blake2s512Rng, FeedableRNG};
Expand Down Expand Up @@ -41,6 +41,16 @@ impl<F: Field> MLSumcheck<F> {
/// $$\sum_{i=0}^{n}C_i\cdot\prod_{j=0}^{m_i}P_{ij}$$
pub fn prove(polynomial: &ListOfProductsOfPolynomials<F>) -> Result<Proof<F>, crate::Error> {
let mut fs_rng = Blake2s512Rng::setup();
Self::prove_as_subprotocol(&mut fs_rng, polynomial).map(|r| r.0)
}

/// This function does the same thing as `prove`, but it uses a `FeedableRNG` as the transcript/to generate the
/// verifier challenges. Additionally, it returns the prover's state in addition to the proof.
/// Both of these allow this sumcheck to be better used as a part of a larger protocol.
pub fn prove_as_subprotocol(
fs_rng: &mut impl FeedableRNG<Error = crate::Error>,
polynomial: &ListOfProductsOfPolynomials<F>,
) -> Result<(Proof<F>, ProverState<F>), crate::Error> {
fs_rng.feed(&polynomial.info())?;

let mut prover_state = IPForMLSumcheck::prover_init(polynomial);
Expand All @@ -50,10 +60,10 @@ impl<F: Field> MLSumcheck<F> {
let prover_msg = IPForMLSumcheck::prove_round(&mut prover_state, &verifier_msg);
fs_rng.feed(&prover_msg)?;
prover_msgs.push(prover_msg);
verifier_msg = Some(IPForMLSumcheck::sample_round(&mut fs_rng));
verifier_msg = Some(IPForMLSumcheck::sample_round(fs_rng));
}

Ok(prover_msgs)
Ok((prover_msgs, prover_state))
}

/// verify the claimed sum using the proof
Expand All @@ -63,16 +73,24 @@ impl<F: Field> MLSumcheck<F> {
proof: &Proof<F>,
) -> Result<SubClaim<F>, crate::Error> {
let mut fs_rng = Blake2s512Rng::setup();
Self::verify_as_subprotocol(&mut fs_rng, polynomial_info, claimed_sum, proof)
}

/// This function does the same thing as `prove`, but it uses a `FeedableRNG` as the transcript/to generate the
/// verifier challenges. This allows this sumcheck to be used as a part of a larger protocol.
pub fn verify_as_subprotocol(
fs_rng: &mut impl FeedableRNG<Error = crate::Error>,
polynomial_info: &PolynomialInfo,
claimed_sum: F,
proof: &Proof<F>,
) -> Result<SubClaim<F>, crate::Error> {
fs_rng.feed(polynomial_info)?;
let mut verifier_state = IPForMLSumcheck::verifier_init(polynomial_info);
for i in 0..polynomial_info.num_variables {
let prover_msg = proof.get(i).expect("proof is incomplete");
fs_rng.feed(prover_msg)?;
let _verifier_msg = IPForMLSumcheck::verify_round(
(*prover_msg).clone(),
&mut verifier_state,
&mut fs_rng,
);
let _verifier_msg =
IPForMLSumcheck::verify_round((*prover_msg).clone(), &mut verifier_state, fs_rng);
}

IPForMLSumcheck::check_and_generate_subclaim(verifier_state, claimed_sum)
Expand Down
9 changes: 6 additions & 3 deletions src/ml_sumcheck/protocol/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ pub struct ProverState<F: Field> {
pub list_of_products: Vec<(F, Vec<usize>)>,
/// Stores a list of multilinear extensions in which `self.list_of_products` points to
pub flattened_ml_extensions: Vec<DenseMultilinearExtension<F>>,
num_vars: usize,
max_multiplicands: usize,
round: usize,
/// Number of variables
pub num_vars: usize,
/// Max number of multiplicands in a product
pub max_multiplicands: usize,
/// The current round number
pub round: usize,
}

impl<F: Field> IPForMLSumcheck<F> {
Expand Down
87 changes: 83 additions & 4 deletions src/ml_sumcheck/test.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::ml_sumcheck::data_structures::ListOfProductsOfPolynomials;
use crate::ml_sumcheck::protocol::IPForMLSumcheck;
use crate::ml_sumcheck::MLSumcheck;
use crate::rng::Blake2s512Rng;
use crate::rng::FeedableRNG;
use ark_ff::Field;
use ark_poly::{DenseMultilinearExtension, MultilinearExtension};
use ark_std::rand::Rng;
Expand Down Expand Up @@ -94,23 +96,92 @@ fn test_protocol(nv: usize, num_multiplicands_range: (usize, usize), num_product
);
}

fn test_polynomial_as_subprotocol(
nv: usize,
num_multiplicands_range: (usize, usize),
num_products: usize,
prover_rng: &mut impl FeedableRNG<Error = crate::Error>,
verifier_rng: &mut impl FeedableRNG<Error = crate::Error>,
) {
let mut rng = test_rng();
let (poly, asserted_sum) =
random_list_of_products::<Fr, _>(nv, num_multiplicands_range, num_products, &mut rng);
let poly_info = poly.info();
let (proof, _prover_state) =
MLSumcheck::prove_as_subprotocol(prover_rng, &poly).expect("fail to prove");
let subclaim =
MLSumcheck::verify_as_subprotocol(verifier_rng, &poly_info, asserted_sum, &proof)
.expect("fail to verify");
assert!(
poly.evaluate(&subclaim.point) == subclaim.expected_evaluation,
"wrong subclaim"
);
}

#[test]
fn test_trivial_polynomial() {
let nv = 1;
let num_multiplicands_range = (4, 13);
let num_products = 5;

test_polynomial(nv, num_multiplicands_range, num_products);
test_protocol(nv, num_multiplicands_range, num_products);
for _ in 0..10 {
test_polynomial(nv, num_multiplicands_range, num_products);
test_protocol(nv, num_multiplicands_range, num_products);

let mut prover_rng = Blake2s512Rng::setup();
prover_rng.feed(b"Test Trivial Works").unwrap();
let mut verifier_rng = Blake2s512Rng::setup();
verifier_rng.feed(b"Test Trivial Works").unwrap();
test_polynomial_as_subprotocol(
nv,
num_multiplicands_range,
num_products,
&mut prover_rng,
&mut verifier_rng,
)
}
}
#[test]
fn test_normal_polynomial() {
let nv = 12;
let num_multiplicands_range = (4, 9);
let num_products = 5;

test_polynomial(nv, num_multiplicands_range, num_products);
test_protocol(nv, num_multiplicands_range, num_products);
for _ in 0..10 {
test_polynomial(nv, num_multiplicands_range, num_products);
test_protocol(nv, num_multiplicands_range, num_products);

let mut prover_rng = Blake2s512Rng::setup();
prover_rng.feed(b"Test Trivial Works").unwrap();
let mut verifier_rng = Blake2s512Rng::setup();
verifier_rng.feed(b"Test Trivial Works").unwrap();
test_polynomial_as_subprotocol(
nv,
num_multiplicands_range,
num_products,
&mut prover_rng,
&mut verifier_rng,
)
}
}
#[test]
#[should_panic]
fn test_normal_polynomial_different_transcripts_fails() {
let nv = 12;
let num_multiplicands_range = (4, 9);
let num_products = 5;

let mut prover_rng = Blake2s512Rng::setup();
prover_rng.feed(b"Test Trivial Works").unwrap();
let mut verifier_rng = Blake2s512Rng::setup();
verifier_rng.feed(b"Test Trivial Fails").unwrap();
test_polynomial_as_subprotocol(
nv,
num_multiplicands_range,
num_products,
&mut prover_rng,
&mut verifier_rng,
)
}
#[test]
#[should_panic]
Expand All @@ -120,6 +191,14 @@ fn zero_polynomial_should_error() {
let num_products = 5;

test_polynomial(nv, num_multiplicands_range, num_products);
}
#[test]
#[should_panic]
fn zero_polynomial_protocol_should_error() {
let nv = 0;
let num_multiplicands_range = (4, 13);
let num_products = 5;

test_protocol(nv, num_multiplicands_range, num_products);
}

Expand Down

0 comments on commit 53244d0

Please sign in to comment.