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: Serialize proofs #219

Merged
merged 11 commits into from
Mar 31, 2024
1 change: 1 addition & 0 deletions common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.2.0"
edition = "2021"

[dependencies]
ark-serialize = { version = "0.4.2", features = ["derive"] }
serde = { version = "1.0.193", features = ["derive"] }
serde_json = "1.0.108"
strum_macros = "0.25.3"
3 changes: 2 additions & 1 deletion common/src/rv_trace.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::constants::{MEMORY_OPS_PER_INSTRUCTION, PANIC_ADDRESS, INPUT_START_ADDRESS, OUTPUT_START_ADDRESS};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use serde::{Deserialize, Serialize};
use strum_macros::FromRepr;

Expand Down Expand Up @@ -611,7 +612,7 @@ impl RV32IM {
/// all reads from the reserved memory address space for program inputs and all writes
/// to the reserved memory address space for program outputs.
/// The inputs and outputs are part of the public inputs to the proof.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, CanonicalSerialize, CanonicalDeserialize)]
pub struct JoltDevice {
pub inputs: Vec<u8>,
pub outputs: Vec<u8>,
Expand Down
20 changes: 20 additions & 0 deletions jolt-core/src/benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::jolt::vm::rv32i_vm::{RV32IJoltVM, C, M, RV32I};
use crate::jolt::vm::Jolt;
use crate::poly::dense_mlpoly::bench::{init_commit_bench, run_commit_bench};
use ark_bn254::{Fr, G1Projective};
use ark_serialize::CanonicalSerialize;
use common::rv_trace::{ELFInstruction, JoltDevice};
use criterion::black_box;
use merlin::Transcript;
Expand Down Expand Up @@ -220,6 +221,16 @@ fn sha3() -> Vec<(tracing::Span, Box<dyn FnOnce()>)> {
prove_example("sha3-guest", &vec![5u8; 2048])
}

fn serialize_and_print_size(name: &str, item: &impl ark_serialize::CanonicalSerialize) {
use std::fs::File;
let mut file = File::create("temp_file").unwrap();
item.serialize_compressed(&mut file).unwrap();
let file_size_bytes = file.metadata().unwrap().len();
let file_size_kb = file_size_bytes as f64 / 1024.0;
let file_size_mb = file_size_kb / 1024.0;
println!("{:<30} : {:.3} MB", name, file_size_mb);
}

fn prove_example<T: Serialize>(
example_name: &str,
input: &T,
Expand All @@ -246,6 +257,15 @@ fn prove_example<T: Serialize>(
circuit_flags,
preprocessing.clone(),
);

println!("Proof sizing:");
serialize_and_print_size("jolt_commitments", &jolt_commitments);
serialize_and_print_size("jolt_proof", &jolt_proof);
serialize_and_print_size(" jolt_proof.r1cs", &jolt_proof.r1cs);
serialize_and_print_size(" jolt_proof.bytecode", &jolt_proof.bytecode);
serialize_and_print_size(" jolt_proof.read_write_memory", &jolt_proof.read_write_memory);
serialize_and_print_size(" jolt_proof.instruction_lookups", &jolt_proof.instruction_lookups);

let verification_result = RV32IJoltVM::verify(preprocessing, jolt_proof, jolt_commitments);
assert!(
verification_result.is_ok(),
Expand Down
4 changes: 2 additions & 2 deletions jolt-core/src/jolt/instruction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use common::rv_trace::ELFInstruction;
use std::fmt::Debug;

#[enum_dispatch]
pub trait JoltInstruction: Sync + Clone + Debug {
pub trait JoltInstruction: Clone + Debug + Send + Sync {
fn operands(&self) -> [u64; 2];
/// Combines `vals` according to the instruction's "collation" polynomial `g`.
/// If `vals` are subtable entries (as opposed to MLE evaluations), this function returns the
Expand Down Expand Up @@ -70,7 +70,7 @@ pub trait JoltInstruction: Sync + Clone + Debug {
}

pub trait JoltInstructionSet:
JoltInstruction + IntoEnumIterator + EnumCount + for<'a> TryFrom<&'a ELFInstruction>
JoltInstruction + IntoEnumIterator + EnumCount + for<'a> TryFrom<&'a ELFInstruction> + Send + Sync
{
fn enum_index(instruction: &Self) -> usize {
unsafe { *<*const _>::from(instruction).cast::<u8>() as usize }
Expand Down
2 changes: 1 addition & 1 deletion jolt-core/src/jolt/subtable/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub trait LassoSubtable<F: PrimeField>: 'static + Sync {

pub type SubtableId = TypeId;
pub trait JoltSubtableSet<F: PrimeField>:
LassoSubtable<F> + IntoEnumIterator + EnumCount + From<SubtableId> + Into<usize>
LassoSubtable<F> + IntoEnumIterator + EnumCount + From<SubtableId> + Into<usize> + Send + Sync
{
fn enum_index(subtable: Box<dyn LassoSubtable<F>>) -> usize {
Self::from(subtable.subtable_id()).into()
Expand Down
5 changes: 5 additions & 0 deletions jolt-core/src/jolt/vm/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::poly::pedersen::PedersenGenerators;
use common::constants::{BYTES_PER_INSTRUCTION, NUM_R1CS_POLYS, RAM_START_ADDRESS, REGISTER_COUNT};
use common::rv_trace::ELFInstruction;
use common::to_ram_address;
use ark_serialize::{CanonicalSerialize, CanonicalDeserialize};

use rayon::prelude::*;

Expand Down Expand Up @@ -325,6 +326,8 @@ impl<F: PrimeField, G: CurveGroup<ScalarField = F>> BytecodePolynomials<F, G> {
}
}


#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct BytecodeCommitment<G: CurveGroup> {
pub read_write_generators: HyraxGenerators<NUM_R1CS_POLYS, G>,
pub read_write_commitments: Vec<HyraxCommitment<NUM_R1CS_POLYS, G>>,
Expand Down Expand Up @@ -569,6 +572,7 @@ where
}
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct BytecodeReadWriteOpenings<F>
where
F: PrimeField,
Expand Down Expand Up @@ -657,6 +661,7 @@ where
}
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct BytecodeInitFinalOpenings<F>
where
F: PrimeField,
Expand Down
8 changes: 5 additions & 3 deletions jolt-core/src/jolt/vm/instruction_lookups.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ pub struct BatchedInstructionPolynomials<F: PrimeField> {
}

/// Commitments to BatchedInstructionPolynomials.
#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct InstructionCommitment<G: CurveGroup> {
pub read_write_generators: HyraxGenerators<NUM_R1CS_POLYS, G>,
/// Commitments to dim_i and read_cts_i polynomials.
Expand Down Expand Up @@ -220,6 +221,7 @@ where
}
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct InstructionReadWriteOpenings<F>
where
F: PrimeField,
Expand Down Expand Up @@ -336,6 +338,7 @@ where
}
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct InstructionFinalOpenings<F, Subtables>
where
F: PrimeField,
Expand Down Expand Up @@ -750,6 +753,7 @@ where
}

/// Proof of instruction lookups for a single Jolt program execution.
#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct InstructionLookupsProof<const C: usize, const M: usize, F, G, InstructionSet, Subtables>
where
F: PrimeField,
Expand All @@ -758,10 +762,7 @@ where
InstructionSet: JoltInstructionSet,
{
_instructions: PhantomData<InstructionSet>,
/// "Primary" sumcheck, i.e. proving \sum_x \tilde{eq}(r, x) * \sum_i flag_i(x) * g_i(E_1(x), ..., E_\alpha(x))
primary_sumcheck: PrimarySumcheck<F, G>,

/// Memory checking proof, showing that E_i polynomials are well-formed.
memory_checking: MemoryCheckingProof<
G,
InstructionPolynomials<F, G>,
Expand All @@ -770,6 +771,7 @@ where
>,
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct PrimarySumcheck<F: PrimeField, G: CurveGroup<ScalarField = F>> {
sumcheck_proof: SumcheckInstanceProof<F>,
num_rounds: usize,
Expand Down
14 changes: 9 additions & 5 deletions jolt-core/src/jolt/vm/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use ark_ec::CurveGroup;
use ark_ff::PrimeField;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_std::log2;
use common::constants::NUM_R1CS_POLYS;
use common::rv_trace::{JoltDevice, NUM_CIRCUIT_FLAGS};
Expand Down Expand Up @@ -49,18 +50,19 @@ where
pub read_write_memory: ReadWriteMemoryPreprocessing,
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct JoltProof<const C: usize, const M: usize, F, G, InstructionSet, Subtables>
where
F: PrimeField,
G: CurveGroup<ScalarField = F>,
InstructionSet: JoltInstructionSet,
Subtables: JoltSubtableSet<F>,
{
program_io: JoltDevice,
bytecode: BytecodeProof<F, G>,
read_write_memory: ReadWriteMemoryProof<F, G>,
instruction_lookups: InstructionLookupsProof<C, M, F, G, InstructionSet, Subtables>,
r1cs: R1CSProof<F, G>,
pub program_io: JoltDevice,
pub bytecode: BytecodeProof<F, G>,
pub read_write_memory: ReadWriteMemoryProof<F, G>,
pub instruction_lookups: InstructionLookupsProof<C, M, F, G, InstructionSet, Subtables>,
pub r1cs: R1CSProof<F, G>,
}

pub struct JoltPolynomials<F, G>
Expand All @@ -73,6 +75,7 @@ where
pub instruction_lookups: InstructionPolynomials<F, G>,
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct JoltCommitments<G: CurveGroup> {
pub bytecode: BytecodeCommitment<G>,
pub read_write_memory: MemoryCommitment<G>,
Expand Down Expand Up @@ -152,6 +155,7 @@ pub trait Jolt<F: PrimeField, G: CurveGroup<ScalarField = F>, const C: usize, co
JoltProof<C, M, F, G, Self::InstructionSet, Self::Subtables>,
JoltCommitments<G>,
) {
println!("Jolt::prove({})", memory_trace.len());
let mut transcript = Transcript::new(b"Jolt transcript");
let (bytecode_proof, bytecode_polynomials, bytecode_commitment) = Self::prove_bytecode(
&preprocessing.bytecode,
Expand Down
8 changes: 8 additions & 0 deletions jolt-core/src/jolt/vm/read_write_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use common::constants::{
};
use common::rv_trace::{ELFInstruction, JoltDevice, MemoryOp, RV32IM};
use common::to_ram_address;
use ark_serialize::{CanonicalSerialize, CanonicalDeserialize};

use super::timestamp_range_check::TimestampValidityProof;

Expand Down Expand Up @@ -437,6 +438,7 @@ pub struct BatchedMemoryPolynomials<F: PrimeField> {
pub(crate) batched_t_read_write: DensePolynomial<F>,
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct MemoryCommitment<G: CurveGroup> {
/// Generators for a_read_write, v_read, v_write
pub read_write_generators: HyraxGenerators<NUM_R1CS_POLYS, G>,
Expand Down Expand Up @@ -511,6 +513,7 @@ where
}
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct MemoryReadWriteOpenings<F, G>
where
F: PrimeField,
Expand All @@ -528,6 +531,7 @@ where
pub t_write_opening: [F; MEMORY_OPS_PER_INSTRUCTION],
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct MemoryReadWriteOpeningProof<G: CurveGroup> {
a_v_opening_proof: BatchedHyraxOpeningProof<NUM_R1CS_POLYS, G>,
t_opening_proof: ConcatenatedPolynomialOpeningProof<G>,
Expand Down Expand Up @@ -646,6 +650,7 @@ where
}
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct MemoryInitFinalOpenings<F>
where
F: PrimeField,
Expand All @@ -660,6 +665,7 @@ where
t_final: F,
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct MemoryInitFinalOpeningProof<F, G>
where
F: PrimeField,
Expand Down Expand Up @@ -949,6 +955,7 @@ where
}
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct OutputSumcheckProof<F, G>
where
F: PrimeField,
Expand Down Expand Up @@ -1109,6 +1116,7 @@ where
}
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct ReadWriteMemoryProof<F, G>
where
F: PrimeField,
Expand Down
4 changes: 4 additions & 0 deletions jolt-core/src/jolt/vm/timestamp_range_check.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use ark_ec::CurveGroup;
use ark_ff::PrimeField;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use common::constants::MEMORY_OPS_PER_INSTRUCTION;
use itertools::interleave;
use merlin::Transcript;
Expand Down Expand Up @@ -201,6 +202,7 @@ where
}
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct RangeCheckOpenings<F, G>
where
F: PrimeField,
Expand All @@ -215,6 +217,7 @@ where
identity_poly_opening: Option<F>,
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct RangeCheckOpeningProof<G>
where
G: CurveGroup,
Expand Down Expand Up @@ -589,6 +592,7 @@ where
}
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct TimestampValidityProof<F, G>
where
F: PrimeField,
Expand Down
5 changes: 4 additions & 1 deletion jolt-core/src/lasso/memory_checking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ use crate::utils::transcript::ProofTranscript;

use ark_ec::CurveGroup;
use ark_ff::PrimeField;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use itertools::interleave;
use merlin::Transcript;
use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator};
use std::iter::zip;
use std::marker::PhantomData;

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct MultisetHashes<F: PrimeField> {
/// Multiset hash of "read" tuples
pub read_hashes: Vec<F>,
Expand Down Expand Up @@ -58,10 +60,11 @@ impl<F: PrimeField> MultisetHashes<F> {
}
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct MemoryCheckingProof<G, Polynomials, ReadWriteOpenings, InitFinalOpenings>
where
G: CurveGroup,
Polynomials: BatchablePolynomials<G> + ?Sized,
Polynomials: BatchablePolynomials<G>,
ReadWriteOpenings: StructuredOpeningProof<G::ScalarField, G, Polynomials>,
InitFinalOpenings: StructuredOpeningProof<G::ScalarField, G, Polynomials>,
{
Expand Down
5 changes: 5 additions & 0 deletions jolt-core/src/lasso/surge.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use ark_ec::CurveGroup;
use ark_ff::PrimeField;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use merlin::Transcript;
use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator};
use std::marker::{PhantomData, Sync};
Expand Down Expand Up @@ -40,6 +41,7 @@ pub struct BatchedSurgePolynomials<F: PrimeField> {
pub batched_E: DensePolynomial<F>,
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct SurgeCommitment<G: CurveGroup> {
pub dim_read_commitment: ConcatenatedPolynomialCommitment<G>,
pub final_commitment: ConcatenatedPolynomialCommitment<G>,
Expand Down Expand Up @@ -137,6 +139,7 @@ impl<F: PrimeField, G: CurveGroup<ScalarField = F>> StructuredOpeningProof<F, G,
}
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct SurgeReadWriteOpenings<F>
where
F: PrimeField,
Expand All @@ -146,6 +149,7 @@ where
E_poly_openings: Vec<F>, // NUM_MEMORIES-sized
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct SurgeReadWriteOpeningProof<F, G>
where
F: PrimeField,
Expand Down Expand Up @@ -238,6 +242,7 @@ where
}
}

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct SurgeFinalOpenings<F, Instruction, const C: usize, const M: usize>
where
F: PrimeField,
Expand Down
Loading