From 77ce69dc15d1c0a7ad6f3ebf70fbd1d0a0c54ccc Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Thu, 15 Jul 2021 07:35:12 -0700 Subject: [PATCH] Proof serialization (#93) Using `serde_cbor` for now. It's probably far from optimal, as we have many `Vec`s which I assume it will prefix with their lengths, but it's a nice and easy method for now. --- Cargo.toml | 2 ++ src/bin/bench_recursion.rs | 12 ++++++++---- src/circuit_data.rs | 2 +- src/field/crandall_field.rs | 3 ++- src/field/extension_field/quadratic.rs | 3 ++- src/field/extension_field/quartic.rs | 3 ++- src/field/field.rs | 4 ++++ src/merkle_proofs.rs | 4 +++- src/polynomial/commitment.rs | 3 +++ src/polynomial/polynomial.rs | 4 +++- src/proof.rs | 17 +++++++++++++++-- 11 files changed, 45 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 21708d41..062ab1dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,8 @@ rand_chacha = "0.2.2" rayon = "1.5.0" unroll = "0.1.5" anyhow = "1.0.40" +serde = { version = "1.0", features = ["derive"] } +serde_cbor = "0.11.1" [profile.release] opt-level = 3 diff --git a/src/bin/bench_recursion.rs b/src/bin/bench_recursion.rs index b75d4bdc..e35f51dd 100644 --- a/src/bin/bench_recursion.rs +++ b/src/bin/bench_recursion.rs @@ -1,4 +1,5 @@ use env_logger::Env; +use log::info; use plonky2::circuit_builder::CircuitBuilder; use plonky2::circuit_data::CircuitConfig; use plonky2::field::crandall_field::CrandallField; @@ -25,10 +26,10 @@ fn bench_prove, const D: usize>() { rate_bits: 3, num_challenges: 3, fri_config: FriConfig { - proof_of_work_bits: 1, + proof_of_work_bits: 10, rate_bits: 3, reduction_arity_bits: vec![2, 2, 2, 2, 2], - num_query_rounds: 1, + num_query_rounds: 35, }, }; @@ -46,7 +47,10 @@ fn bench_prove, const D: usize>() { builder.add(zero, zero); builder.add_extension(zero_ext, zero_ext); - let prover = builder.build_prover(); + let circuit = builder.build(); let inputs = PartialWitness::new(); - prover.prove(inputs); + let proof = circuit.prove(inputs); + let proof_bytes = serde_cbor::to_vec(&proof).unwrap(); + info!("Proof length: {} bytes", proof_bytes.len()); + circuit.verify(proof).unwrap(); } diff --git a/src/circuit_data.rs b/src/circuit_data.rs index 10c5ffe0..b5d2c6e8 100644 --- a/src/circuit_data.rs +++ b/src/circuit_data.rs @@ -38,7 +38,7 @@ impl Default for CircuitConfig { num_challenges: 3, fri_config: FriConfig { proof_of_work_bits: 1, - rate_bits: 1, + rate_bits: 3, reduction_arity_bits: vec![1, 1, 1, 1], num_query_rounds: 1, }, diff --git a/src/field/crandall_field.rs b/src/field/crandall_field.rs index 7a1d18d6..9d38ff1a 100644 --- a/src/field/crandall_field.rs +++ b/src/field/crandall_field.rs @@ -5,6 +5,7 @@ use std::iter::{Product, Sum}; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use num::Integer; +use serde::{Deserialize, Serialize}; use crate::field::extension_field::quadratic::QuadraticCrandallField; use crate::field::extension_field::quartic::QuarticCrandallField; @@ -106,7 +107,7 @@ const CAUCHY_MDS_8: [[CrandallField; 8]; 8] = [ /// = 2**64 - 9 * 2**28 + 1 /// = 2**28 * (2**36 - 9) + 1 /// ``` -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Serialize, Deserialize)] pub struct CrandallField(pub u64); impl PartialEq for CrandallField { diff --git a/src/field/extension_field/quadratic.rs b/src/field/extension_field/quadratic.rs index ede2ef26..256803ab 100644 --- a/src/field/extension_field/quadratic.rs +++ b/src/field/extension_field/quadratic.rs @@ -4,12 +4,13 @@ use std::iter::{Product, Sum}; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use rand::Rng; +use serde::{Deserialize, Serialize}; use crate::field::crandall_field::CrandallField; use crate::field::extension_field::{FieldExtension, Frobenius, OEF}; use crate::field::field::Field; -#[derive(Copy, Clone, Eq, PartialEq, Hash)] +#[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] pub struct QuadraticCrandallField([CrandallField; 2]); impl OEF<2> for QuadraticCrandallField { diff --git a/src/field/extension_field/quartic.rs b/src/field/extension_field/quartic.rs index f609eeb7..22e91353 100644 --- a/src/field/extension_field/quartic.rs +++ b/src/field/extension_field/quartic.rs @@ -4,13 +4,14 @@ use std::iter::{Product, Sum}; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use rand::Rng; +use serde::{Deserialize, Serialize}; use crate::field::crandall_field::CrandallField; use crate::field::extension_field::{FieldExtension, Frobenius, OEF}; use crate::field::field::Field; /// A quartic extension of `CrandallField`. -#[derive(Copy, Clone, Eq, PartialEq, Hash)] +#[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] pub struct QuarticCrandallField(pub(crate) [CrandallField; 4]); impl OEF<4> for QuarticCrandallField { diff --git a/src/field/field.rs b/src/field/field.rs index 9c733d04..28a52202 100644 --- a/src/field/field.rs +++ b/src/field/field.rs @@ -6,6 +6,8 @@ use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssi use num::Integer; use rand::Rng; +use serde::de::DeserializeOwned; +use serde::Serialize; use crate::field::extension_field::Frobenius; use crate::util::bits_u64; @@ -31,6 +33,8 @@ pub trait Field: + Display + Send + Sync + + Serialize + + DeserializeOwned { type PrimeField: Field; diff --git a/src/merkle_proofs.rs b/src/merkle_proofs.rs index 7d50f466..ae8b7daf 100644 --- a/src/merkle_proofs.rs +++ b/src/merkle_proofs.rs @@ -1,4 +1,5 @@ use anyhow::{ensure, Result}; +use serde::{Deserialize, Serialize}; use crate::circuit_builder::CircuitBuilder; use crate::field::extension_field::Extendable; @@ -10,7 +11,8 @@ use crate::proof::{Hash, HashTarget}; use crate::target::Target; use crate::wire::Wire; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(bound = "")] pub struct MerkleProof { /// The Merkle digest of each sibling subtree, staying from the bottommost layer. pub siblings: Vec>, diff --git a/src/polynomial/commitment.rs b/src/polynomial/commitment.rs index b6ff44cc..ef935657 100644 --- a/src/polynomial/commitment.rs +++ b/src/polynomial/commitment.rs @@ -1,5 +1,6 @@ use anyhow::Result; use rayon::prelude::*; +use serde::{Deserialize, Serialize}; use crate::circuit_data::CommonCircuitData; use crate::field::extension_field::Extendable; @@ -245,6 +246,8 @@ impl ListPolynomialCommitment { } } +#[derive(Serialize, Deserialize, Debug)] +#[serde(bound = "")] pub struct OpeningProof, const D: usize> { fri_proof: FriProof, // TODO: Get the degree from `CommonCircuitData` instead. diff --git a/src/polynomial/polynomial.rs b/src/polynomial/polynomial.rs index 81d07b8f..5f9bccd9 100644 --- a/src/polynomial/polynomial.rs +++ b/src/polynomial/polynomial.rs @@ -3,6 +3,7 @@ use std::iter::Sum; use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; use anyhow::{ensure, Result}; +use serde::{Deserialize, Serialize}; use crate::field::extension_field::Extendable; use crate::field::fft::{fft, fft_with_options, ifft}; @@ -76,7 +77,8 @@ impl From> for PolynomialValues { } /// A polynomial in coefficient form. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(bound = "")] pub struct PolynomialCoeffs { pub(crate) coeffs: Vec, } diff --git a/src/proof.rs b/src/proof.rs index f712da40..3855e327 100644 --- a/src/proof.rs +++ b/src/proof.rs @@ -1,5 +1,7 @@ use std::convert::TryInto; +use serde::{Deserialize, Serialize}; + use crate::circuit_data::CommonCircuitData; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; @@ -12,7 +14,8 @@ use crate::polynomial::polynomial::PolynomialCoeffs; use crate::target::Target; /// Represents a ~256 bit hash output. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(bound = "")] pub struct Hash { pub(crate) elements: [F; 4], } @@ -61,6 +64,8 @@ impl HashTarget { } } +#[derive(Serialize, Deserialize, Debug)] +#[serde(bound = "")] pub struct Proof, const D: usize> { /// Merkle root of LDEs of wire values. pub wires_root: Hash, @@ -83,6 +88,8 @@ pub struct ProofTarget { } /// Evaluations and Merkle proof produced by the prover in a FRI query step. +#[derive(Serialize, Deserialize, Debug)] +#[serde(bound = "")] pub struct FriQueryStep, const D: usize> { pub evals: Vec, pub merkle_proof: MerkleProof, @@ -95,6 +102,8 @@ pub struct FriQueryStepTarget { /// Evaluations and Merkle proofs of the original set of polynomials, /// before they are combined into a composition polynomial. +#[derive(Serialize, Deserialize, Debug)] +#[serde(bound = "")] pub struct FriInitialTreeProof { pub evals_proofs: Vec<(Vec, MerkleProof)>, } @@ -118,6 +127,8 @@ impl FriInitialTreeProofTarget { } /// Proof for a FRI query round. +#[derive(Serialize, Deserialize, Debug)] +#[serde(bound = "")] pub struct FriQueryRound, const D: usize> { pub initial_trees_proof: FriInitialTreeProof, pub steps: Vec>, @@ -128,6 +139,8 @@ pub struct FriQueryRoundTarget { pub steps: Vec>, } +#[derive(Serialize, Deserialize, Debug)] +#[serde(bound = "")] pub struct FriProof, const D: usize> { /// A Merkle root for each reduced polynomial in the commit phase. pub commit_phase_merkle_roots: Vec>, @@ -146,7 +159,7 @@ pub struct FriProofTarget { pub pow_witness: Target, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] /// The purported values of each polynomial at a single point. pub struct OpeningSet, const D: usize> { pub constants: Vec,