Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat(Zeromorph PCS): Add Zeromorph Multilinear PCS Scheme #339

Merged
merged 17 commits into from
Jun 3, 2024
112 changes: 73 additions & 39 deletions jolt-core/src/benches/bench.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
use crate::host;
use crate::jolt::vm::rv32i_vm::{RV32IJoltVM, C, M};
use crate::jolt::vm::Jolt;
use crate::poly::commitment::commitment_scheme::CommitmentScheme;
use crate::poly::commitment::hyrax::HyraxScheme;
use ark_bn254::G1Projective;
use crate::poly::commitment::zeromorph::Zeromorph;
use crate::poly::field::JoltField;
use ark_bn254::{Bn254, Fr, G1Projective};
use serde::Serialize;

#[derive(Debug, Copy, Clone, clap::ValueEnum)]
pub enum PCSType {
Hyrax,
Zeromorph,
}

#[derive(Debug, Copy, Clone, clap::ValueEnum)]
pub enum BenchType {
Fibonacci,
Expand All @@ -15,30 +24,53 @@ pub enum BenchType {

#[allow(unreachable_patterns)] // good errors on new BenchTypes
pub fn benchmarks(
pcs_type: PCSType,
bench_type: BenchType,
_num_cycles: Option<usize>,
_memory_size: Option<usize>,
_bytecode_size: Option<usize>,
) -> Vec<(tracing::Span, Box<dyn FnOnce()>)> {
match bench_type {
BenchType::Sha2 => sha2(),
BenchType::Sha3 => sha3(),
BenchType::Sha2Chain => sha2chain(),
BenchType::Fibonacci => fibonacci(),
_ => panic!("BenchType does not have a mapping"),
match pcs_type {
PCSType::Hyrax => match bench_type {
BenchType::Sha2 => sha2::<Fr, HyraxScheme<G1Projective>>(),
BenchType::Sha3 => sha3::<Fr, HyraxScheme<G1Projective>>(),
BenchType::Sha2Chain => sha2chain::<Fr, HyraxScheme<G1Projective>>(),
BenchType::Fibonacci => fibonacci::<Fr, HyraxScheme<G1Projective>>(),
_ => panic!("BenchType does not have a mapping"),
},
PCSType::Zeromorph => match bench_type {
BenchType::Sha2 => sha2::<Fr, Zeromorph<Bn254>>(),
BenchType::Sha3 => sha3::<Fr, Zeromorph<Bn254>>(),
BenchType::Sha2Chain => sha2chain::<Fr, Zeromorph<Bn254>>(),
BenchType::Fibonacci => fibonacci::<Fr, Zeromorph<Bn254>>(),
_ => panic!("BenchType does not have a mapping"),
},
_ => panic!("PCS Type does not have a mapping"),
}
}

fn fibonacci() -> Vec<(tracing::Span, Box<dyn FnOnce()>)> {
prove_example("fibonacci-guest", &9u32)
fn fibonacci<F, PCS>() -> Vec<(tracing::Span, Box<dyn FnOnce()>)>
where
F: JoltField,
PCS: CommitmentScheme<Field = F>,
{
prove_example::<u32, PCS, F>("fibonacci-guest", &9u32)
}

fn sha2() -> Vec<(tracing::Span, Box<dyn FnOnce()>)> {
prove_example("sha2-guest", &vec![5u8; 2048])
fn sha2<F, PCS>() -> Vec<(tracing::Span, Box<dyn FnOnce()>)>
where
F: JoltField,
PCS: CommitmentScheme<Field = F>,
{
prove_example::<Vec<u8>, PCS, F>("sha2-guest", &vec![5u8; 2048])
}

fn sha3() -> Vec<(tracing::Span, Box<dyn FnOnce()>)> {
prove_example("sha3-guest", &vec![5u8; 2048])
fn sha3<F, PCS>() -> Vec<(tracing::Span, Box<dyn FnOnce()>)>
where
F: JoltField,
PCS: CommitmentScheme<Field = F>,
{
prove_example::<Vec<u8>, PCS, F>("sha3-guest", &vec![5u8; 2048])
}

#[allow(dead_code)]
Expand All @@ -52,10 +84,14 @@ fn serialize_and_print_size(name: &str, item: &impl ark_serialize::CanonicalSeri
println!("{:<30} : {:.3} MB", name, file_size_mb);
}

fn prove_example<T: Serialize>(
fn prove_example<T: Serialize, PCS, F>(
example_name: &str,
input: &T,
) -> Vec<(tracing::Span, Box<dyn FnOnce()>)> {
) -> Vec<(tracing::Span, Box<dyn FnOnce()>)>
where
F: JoltField,
PCS: CommitmentScheme<Field = F>,
{
let mut tasks = Vec::new();
let mut program = host::Program::new(example_name);
program.set_input(input);
Expand All @@ -64,18 +100,15 @@ fn prove_example<T: Serialize>(
let (bytecode, memory_init) = program.decode();
let (io_device, trace, circuit_flags) = program.trace();

let preprocessing: crate::jolt::vm::JoltPreprocessing<
ark_ff::Fp<ark_ff::MontBackend<ark_bn254::FrConfig, 4>, 4>,
HyraxScheme<ark_ec::short_weierstrass::Projective<ark_bn254::g1::Config>>,
> = RV32IJoltVM::preprocess(bytecode.clone(), memory_init, 1 << 20, 1 << 20, 1 << 22);
let preprocessing: crate::jolt::vm::JoltPreprocessing<F, PCS> =
RV32IJoltVM::preprocess(bytecode.clone(), memory_init, 1 << 20, 1 << 20, 1 << 22);

let (jolt_proof, jolt_commitments) =
<RV32IJoltVM as Jolt<_, HyraxScheme<G1Projective>, C, M>>::prove(
io_device,
trace,
circuit_flags,
preprocessing.clone(),
);
let (jolt_proof, jolt_commitments) = <RV32IJoltVM as Jolt<_, PCS, C, M>>::prove(
io_device,
trace,
circuit_flags,
preprocessing.clone(),
);

// println!("Proof sizing:");
// serialize_and_print_size("jolt_commitments", &jolt_commitments);
Expand All @@ -101,7 +134,11 @@ fn prove_example<T: Serialize>(
tasks
}

fn sha2chain() -> Vec<(tracing::Span, Box<dyn FnOnce()>)> {
fn sha2chain<F, PCS>() -> Vec<(tracing::Span, Box<dyn FnOnce()>)>
where
F: JoltField,
PCS: CommitmentScheme<Field = F>,
{
let mut tasks = Vec::new();
let mut program = host::Program::new("sha2-chain-guest");
program.set_input(&[5u8; 32]);
Expand All @@ -111,18 +148,15 @@ fn sha2chain() -> Vec<(tracing::Span, Box<dyn FnOnce()>)> {
let (bytecode, memory_init) = program.decode();
let (io_device, trace, circuit_flags) = program.trace();

let preprocessing: crate::jolt::vm::JoltPreprocessing<
ark_ff::Fp<ark_ff::MontBackend<ark_bn254::FrConfig, 4>, 4>,
HyraxScheme<ark_ec::short_weierstrass::Projective<ark_bn254::g1::Config>>,
> = RV32IJoltVM::preprocess(bytecode.clone(), memory_init, 1 << 20, 1 << 20, 1 << 22);

let (jolt_proof, jolt_commitments) =
<RV32IJoltVM as Jolt<_, HyraxScheme<G1Projective>, C, M>>::prove(
io_device,
trace,
circuit_flags,
preprocessing.clone(),
);
let preprocessing: crate::jolt::vm::JoltPreprocessing<F, PCS> =
RV32IJoltVM::preprocess(bytecode.clone(), memory_init, 1 << 20, 1 << 20, 1 << 22);

let (jolt_proof, jolt_commitments) = <RV32IJoltVM as Jolt<_, PCS, C, M>>::prove(
io_device,
trace,
circuit_flags,
preprocessing.clone(),
);
let verification_result = RV32IJoltVM::verify(preprocessing, jolt_proof, jolt_commitments);
assert!(
verification_result.is_ok(),
Expand Down
19 changes: 16 additions & 3 deletions jolt-core/src/jolt/vm/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,7 @@ where

#[tracing::instrument(skip_all, name = "BytecodeReadWriteOpenings::prove_openings")]
fn prove_openings(
generators: &C::Setup,
polynomials: &BytecodePolynomials<F, C>,
opening_point: &[F],
openings: &Self,
Expand All @@ -634,6 +635,7 @@ where
combined_openings.extend(openings.v_read_write_openings.iter());

C::batch_prove(
generators,
&[
&polynomials.a_read_write,
&polynomials.t_read,
Expand Down Expand Up @@ -705,12 +707,13 @@ where

#[tracing::instrument(skip_all, name = "BytecodeInitFinalOpenings::prove_openings")]
fn prove_openings(
generators: &C::Setup,
polynomials: &BytecodePolynomials<F, C>,
opening_point: &[F],
_openings: &Self,
transcript: &mut ProofTranscript,
) -> Self::Proof {
C::prove(&polynomials.t_final, opening_point, transcript)
C::prove(generators, &polynomials.t_final, opening_point, transcript)
}

fn compute_verifier_openings(
Expand Down Expand Up @@ -859,7 +862,12 @@ mod tests {

let generators = HyraxScheme::<G1Projective>::setup(&commitment_shapes);
let commitments = polys.commit(&generators);
let proof = BytecodeProof::prove_memory_checking(&preprocessing, &polys, &mut transcript);
let proof = BytecodeProof::prove_memory_checking(
&generators,
&preprocessing,
&polys,
&mut transcript,
);

let mut transcript = ProofTranscript::new(b"test_transcript");
BytecodeProof::verify_memory_checking(
Expand Down Expand Up @@ -921,7 +929,12 @@ mod tests {

let mut transcript = ProofTranscript::new(b"test_transcript");

let proof = BytecodeProof::prove_memory_checking(&preprocessing, &polys, &mut transcript);
let proof = BytecodeProof::prove_memory_checking(
&generators,
&preprocessing,
&polys,
&mut transcript,
);

let mut transcript = ProofTranscript::new(b"test_transcript");
BytecodeProof::verify_memory_checking(
Expand Down
11 changes: 10 additions & 1 deletion jolt-core/src/jolt/vm/instruction_lookups.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ where

#[tracing::instrument(skip_all, name = "PrimarySumcheckOpenings::prove_openings")]
fn prove_openings(
generators: &C::Setup,
polynomials: &InstructionPolynomials<F, C>,
opening_point: &[F],
openings: &Self,
Expand All @@ -165,6 +166,7 @@ where
primary_sumcheck_openings.push(openings.lookup_outputs_opening);

C::batch_prove(
generators,
&primary_sumcheck_polys,
opening_point,
&primary_sumcheck_openings,
Expand Down Expand Up @@ -262,6 +264,7 @@ where

#[tracing::instrument(skip_all, name = "InstructionReadWriteOpenings::prove_openings")]
fn prove_openings(
generators: &C::Setup,
polynomials: &InstructionPolynomials<F, C>,
opening_point: &[F],
openings: &Self,
Expand All @@ -284,6 +287,7 @@ where
.concat();

C::batch_prove(
generators,
&read_write_polys,
opening_point,
&read_write_openings,
Expand Down Expand Up @@ -364,12 +368,14 @@ where

#[tracing::instrument(skip_all, name = "InstructionFinalOpenings::prove_openings")]
fn prove_openings(
generators: &C::Setup,
polynomials: &InstructionPolynomials<F, C>,
opening_point: &[F],
openings: &Self,
transcript: &mut ProofTranscript,
) -> Self::Proof {
C::batch_prove(
generators,
&polynomials.final_cts.iter().collect::<Vec<_>>(),
opening_point,
&openings.final_openings,
Expand Down Expand Up @@ -802,6 +808,7 @@ where

#[tracing::instrument(skip_all, name = "InstructionLookups::prove")]
pub fn prove(
generators: &CS::Setup,
polynomials: &InstructionPolynomials<F, CS>,
preprocessing: &InstructionLookupsPreprocessing<F>,
transcript: &mut ProofTranscript,
Expand Down Expand Up @@ -835,6 +842,7 @@ where
lookup_outputs_opening: outputs_eval,
};
let sumcheck_opening_proof = PrimarySumcheckOpenings::prove_openings(
generators,
polynomials,
&r_primary_sumcheck,
&sumcheck_openings,
Expand All @@ -848,7 +856,8 @@ where
opening_proof: sumcheck_opening_proof,
};

let memory_checking = Self::prove_memory_checking(preprocessing, polynomials, transcript);
let memory_checking =
Self::prove_memory_checking(generators, preprocessing, polynomials, transcript);

InstructionLookupsProof {
_instructions: PhantomData,
Expand Down
12 changes: 10 additions & 2 deletions jolt-core/src/jolt/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,18 +376,21 @@ pub trait Jolt<F: JoltField, PCS: CommitmentScheme<Field = F>, const C: usize, c
jolt_commitments.append_to_transcript(&mut transcript);

let bytecode_proof = BytecodeProof::prove_memory_checking(
&preprocessing.generators,
&preprocessing.bytecode,
&jolt_polynomials.bytecode,
&mut transcript,
);

let instruction_proof = InstructionLookupsProof::prove(
&preprocessing.generators,
&jolt_polynomials.instruction_lookups,
&preprocessing.instruction_lookups,
&mut transcript,
);

let memory_proof = ReadWriteMemoryProof::prove(
&preprocessing.generators,
&preprocessing.read_write_memory,
&jolt_polynomials,
&program_io,
Expand All @@ -396,8 +399,13 @@ pub trait Jolt<F: JoltField, PCS: CommitmentScheme<Field = F>, const C: usize, c

drop_in_background_thread(jolt_polynomials);

let r1cs_proof =
R1CSProof::prove(spartan_key, witness_segments, &mut transcript).expect("proof failed");
let r1cs_proof = R1CSProof::prove(
&preprocessing.generators,
spartan_key,
witness_segments,
&mut transcript,
)
.expect("proof failed");

let jolt_proof = JoltProof {
trace_length,
Expand Down
Loading
Loading