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; use crate::field::field::Field; use crate::gadgets::polynomial::PolynomialCoeffsExtTarget; use crate::merkle_proofs::{MerkleProof, MerkleProofTarget}; use crate::plonk_common::PolynomialsIndexBlinding; use crate::polynomial::commitment::{ListPolynomialCommitment, OpeningProof, OpeningProofTarget}; use crate::polynomial::polynomial::PolynomialCoeffs; use crate::target::Target; /// Represents a ~256 bit hash output. #[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(bound = "")] pub struct Hash { pub(crate) elements: [F; 4], } impl Hash { pub(crate) fn from_vec(elements: Vec) -> Self { debug_assert!(elements.len() == 4); Self { elements: elements.try_into().unwrap(), } } pub(crate) fn from_partial(mut elements: Vec) -> Self { debug_assert!(elements.len() <= 4); while elements.len() < 4 { elements.push(F::ZERO); } Self { elements: [elements[0], elements[1], elements[2], elements[3]], } } pub(crate) fn rand() -> Self { Self { elements: [F::rand(), F::rand(), F::rand(), F::rand()], } } } /// Represents a ~256 bit hash output. #[derive(Copy, Clone, Debug)] pub struct HashTarget { pub(crate) elements: [Target; 4], } impl HashTarget { pub(crate) fn from_vec(elements: Vec) -> Self { debug_assert!(elements.len() == 4); Self { elements: elements.try_into().unwrap(), } } pub(crate) fn from_partial(mut elements: Vec, zero: Target) -> Self { debug_assert!(elements.len() <= 4); while elements.len() < 4 { elements.push(zero); } Self { elements: [elements[0], elements[1], elements[2], elements[3]], } } } #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(bound = "")] pub struct Proof, const D: usize> { /// Merkle root of LDEs of wire values. pub wires_root: Hash, /// Merkle root of LDEs of Z, in the context of Plonk's permutation argument. pub plonk_zs_partial_products_root: Hash, /// Merkle root of LDEs of the quotient polynomial components. pub quotient_polys_root: Hash, /// Purported values of each polynomial at the challenge point. pub openings: OpeningSet, /// A FRI argument for each FRI query. pub opening_proof: OpeningProof, } #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(bound = "")] pub struct ProofWithPublicInputs, const D: usize> { pub proof: Proof, pub public_inputs: Vec, } pub struct ProofTarget { pub wires_root: HashTarget, pub plonk_zs_partial_products_root: HashTarget, pub quotient_polys_root: HashTarget, pub openings: OpeningSetTarget, pub opening_proof: OpeningProofTarget, } pub struct ProofWithPublicInputsTarget { pub proof: ProofTarget, pub public_inputs: Vec, } /// Evaluations and Merkle proof produced by the prover in a FRI query step. #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(bound = "")] pub struct FriQueryStep, const D: usize> { pub evals: Vec, pub merkle_proof: MerkleProof, } #[derive(Clone)] pub struct FriQueryStepTarget { pub evals: Vec>, pub merkle_proof: MerkleProofTarget, } /// Evaluations and Merkle proofs of the original set of polynomials, /// before they are combined into a composition polynomial. #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(bound = "")] pub struct FriInitialTreeProof { pub evals_proofs: Vec<(Vec, MerkleProof)>, } impl FriInitialTreeProof { pub(crate) fn unsalted_evals( &self, polynomials: PolynomialsIndexBlinding, zero_knowledge: bool, ) -> &[F] { let evals = &self.evals_proofs[polynomials.index].0; &evals[..evals.len() - polynomials.salt_size(zero_knowledge)] } } #[derive(Clone)] pub struct FriInitialTreeProofTarget { pub evals_proofs: Vec<(Vec, MerkleProofTarget)>, } impl FriInitialTreeProofTarget { pub(crate) fn unsalted_evals( &self, polynomials: PolynomialsIndexBlinding, zero_knowledge: bool, ) -> &[Target] { let evals = &self.evals_proofs[polynomials.index].0; &evals[..evals.len() - polynomials.salt_size(zero_knowledge)] } } /// Proof for a FRI query round. #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(bound = "")] pub struct FriQueryRound, const D: usize> { pub initial_trees_proof: FriInitialTreeProof, pub steps: Vec>, } #[derive(Clone)] pub struct FriQueryRoundTarget { pub initial_trees_proof: FriInitialTreeProofTarget, pub steps: Vec>, } #[derive(Serialize, Deserialize, Clone, 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>, /// Query rounds proofs pub query_round_proofs: Vec>, /// The final polynomial in coefficient form. pub final_poly: PolynomialCoeffs, /// Witness showing that the prover did PoW. pub pow_witness: F, } pub struct FriProofTarget { pub commit_phase_merkle_roots: Vec, pub query_round_proofs: Vec>, pub final_poly: PolynomialCoeffsExtTarget, pub pow_witness: Target, } #[derive(Clone, Debug, Serialize, Deserialize)] /// The purported values of each polynomial at a single point. pub struct OpeningSet, const D: usize> { pub constants: Vec, pub plonk_sigmas: Vec, pub wires: Vec, pub plonk_zs: Vec, pub plonk_zs_right: Vec, pub partial_products: Vec, pub quotient_polys: Vec, } impl, const D: usize> OpeningSet { pub fn new( z: F::Extension, g: F::Extension, constants_sigmas_commitment: &ListPolynomialCommitment, wires_commitment: &ListPolynomialCommitment, zs_partial_products_commitment: &ListPolynomialCommitment, quotient_polys_commitment: &ListPolynomialCommitment, common_data: &CommonCircuitData, ) -> Self { let eval_commitment = |z: F::Extension, c: &ListPolynomialCommitment| { c.polynomials .iter() .map(|p| p.to_extension().eval(z)) .collect::>() }; let constants_sigmas_eval = eval_commitment(z, constants_sigmas_commitment); let zs_partial_products_eval = eval_commitment(z, zs_partial_products_commitment); Self { constants: constants_sigmas_eval[common_data.constants_range()].to_vec(), plonk_sigmas: constants_sigmas_eval[common_data.sigmas_range()].to_vec(), wires: eval_commitment(z, wires_commitment), plonk_zs: zs_partial_products_eval[common_data.zs_range()].to_vec(), plonk_zs_right: eval_commitment(g * z, zs_partial_products_commitment) [common_data.zs_range()] .to_vec(), partial_products: zs_partial_products_eval[common_data.partial_products_range()] .to_vec(), quotient_polys: eval_commitment(z, quotient_polys_commitment), } } } /// The purported values of each polynomial at a single point. #[derive(Clone, Debug)] pub struct OpeningSetTarget { pub constants: Vec>, pub plonk_sigmas: Vec>, pub wires: Vec>, pub plonk_zs: Vec>, pub plonk_zs_right: Vec>, pub partial_products: Vec>, pub quotient_polys: Vec>, }