plonky2/evm/src/proof.rs

611 lines
22 KiB
Rust
Raw Normal View History

use ethereum_types::{Address, H256, U256};
2022-05-04 20:57:07 +02:00
use itertools::Itertools;
use plonky2::field::extension::{Extendable, FieldExtension};
2022-05-04 20:57:07 +02:00
use plonky2::fri::oracle::PolynomialBatch;
use plonky2::fri::proof::{FriChallenges, FriChallengesTarget, FriProof, FriProofTarget};
2022-05-04 20:57:07 +02:00
use plonky2::fri::structure::{
FriOpeningBatch, FriOpeningBatchTarget, FriOpenings, FriOpeningsTarget,
};
use plonky2::hash::hash_types::{MerkleCapTarget, RichField};
use plonky2::hash::merkle_tree::MerkleCap;
use plonky2::iop::ext_target::ExtensionTarget;
use plonky2::iop::target::{BoolTarget, Target};
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::config::{GenericConfig, Hasher};
use plonky2::util::serialization::{Buffer, IoResult, Read, Write};
2023-01-30 08:51:33 -08:00
use plonky2_maybe_rayon::*;
use serde::{Deserialize, Serialize};
2022-05-04 20:57:07 +02:00
2022-08-26 10:12:45 +02:00
use crate::all_stark::NUM_TABLES;
2022-05-04 20:57:07 +02:00
use crate::config::StarkConfig;
use crate::permutation::GrandProductChallengeSet;
2022-05-11 14:35:33 +02:00
/// A STARK proof for each table, plus some metadata used to create recursive wrapper proofs.
2022-05-11 14:35:33 +02:00
#[derive(Debug, Clone)]
pub struct AllProof<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> {
pub stark_proofs: [StarkProofWithMetadata<F, C, D>; NUM_TABLES],
pub(crate) ctl_challenges: GrandProductChallengeSet<F>,
2022-08-25 12:24:22 -07:00
pub public_values: PublicValues,
2022-05-11 14:35:33 +02:00
}
impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> AllProof<F, C, D> {
2022-08-26 10:12:45 +02:00
pub fn degree_bits(&self, config: &StarkConfig) -> [usize; NUM_TABLES] {
2023-01-30 08:51:33 -08:00
core::array::from_fn(|i| self.stark_proofs[i].proof.recover_degree_bits(config))
2022-05-26 16:27:15 +02:00
}
2022-09-05 08:38:57 +02:00
}
2022-05-26 16:27:15 +02:00
2022-05-11 14:35:33 +02:00
pub(crate) struct AllProofChallenges<F: RichField + Extendable<D>, const D: usize> {
2022-08-26 10:12:45 +02:00
pub stark_challenges: [StarkProofChallenges<F, D>; NUM_TABLES],
pub ctl_challenges: GrandProductChallengeSet<F>,
2022-05-11 14:35:33 +02:00
}
2022-05-04 20:57:07 +02:00
2022-10-06 16:40:03 +02:00
#[allow(unused)] // TODO: should be used soon
pub(crate) struct AllChallengerState<F: RichField + Extendable<D>, H: Hasher<F>, const D: usize> {
2022-09-23 16:36:17 +02:00
/// Sponge state of the challenger before starting each proof,
/// along with the final state after all proofs are done. This final state isn't strictly needed.
pub states: [H::Permutation; NUM_TABLES + 1],
2022-09-22 11:01:27 +02:00
pub ctl_challenges: GrandProductChallengeSet<F>,
}
2022-08-25 22:11:25 -07:00
/// Memory values which are public.
#[derive(Debug, Clone, Default)]
2022-08-25 12:24:22 -07:00
pub struct PublicValues {
pub trie_roots_before: TrieRoots,
pub trie_roots_after: TrieRoots,
pub block_metadata: BlockMetadata,
pub cpu_trace_len: usize,
2022-08-25 12:24:22 -07:00
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2022-08-25 12:24:22 -07:00
pub struct TrieRoots {
pub state_root: H256,
pub transactions_root: H256,
pub receipts_root: H256,
2022-08-25 12:24:22 -07:00
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
2022-08-25 12:24:22 -07:00
pub struct BlockMetadata {
2022-08-25 23:35:38 -07:00
pub block_beneficiary: Address,
2022-08-25 12:24:22 -07:00
pub block_timestamp: U256,
pub block_number: U256,
pub block_difficulty: U256,
pub block_gaslimit: U256,
pub block_chain_id: U256,
2022-08-25 23:35:38 -07:00
pub block_base_fee: U256,
2022-08-25 12:24:22 -07:00
}
2022-08-25 22:11:25 -07:00
/// Memory values which are public.
2022-08-25 12:24:22 -07:00
/// Note: All the larger integers are encoded with 32-bit limbs in little-endian order.
#[derive(Eq, PartialEq, Debug)]
2022-08-25 12:24:22 -07:00
pub struct PublicValuesTarget {
pub trie_roots_before: TrieRootsTarget,
pub trie_roots_after: TrieRootsTarget,
pub block_metadata: BlockMetadataTarget,
pub cpu_trace_len: Target,
}
impl PublicValuesTarget {
pub fn to_buffer(&self, buffer: &mut Vec<u8>) -> IoResult<()> {
let TrieRootsTarget {
state_root: state_root_before,
transactions_root: transactions_root_before,
receipts_root: receipts_root_before,
} = self.trie_roots_before;
buffer.write_target_vec(&state_root_before)?;
buffer.write_target_vec(&transactions_root_before)?;
buffer.write_target_vec(&receipts_root_before)?;
let TrieRootsTarget {
state_root: state_root_after,
transactions_root: transactions_root_after,
receipts_root: receipts_root_after,
} = self.trie_roots_after;
buffer.write_target_vec(&state_root_after)?;
buffer.write_target_vec(&transactions_root_after)?;
buffer.write_target_vec(&receipts_root_after)?;
let BlockMetadataTarget {
block_beneficiary,
block_timestamp,
block_number,
block_difficulty,
block_gaslimit,
block_chain_id,
block_base_fee,
} = self.block_metadata;
buffer.write_target_vec(&block_beneficiary)?;
buffer.write_target(block_timestamp)?;
buffer.write_target(block_number)?;
buffer.write_target(block_difficulty)?;
buffer.write_target(block_gaslimit)?;
buffer.write_target(block_chain_id)?;
buffer.write_target(block_base_fee)?;
buffer.write_target(self.cpu_trace_len)?;
Ok(())
}
pub fn from_buffer(buffer: &mut Buffer) -> IoResult<Self> {
let trie_roots_before = TrieRootsTarget {
state_root: buffer.read_target_vec()?.try_into().unwrap(),
transactions_root: buffer.read_target_vec()?.try_into().unwrap(),
receipts_root: buffer.read_target_vec()?.try_into().unwrap(),
};
let trie_roots_after = TrieRootsTarget {
state_root: buffer.read_target_vec()?.try_into().unwrap(),
transactions_root: buffer.read_target_vec()?.try_into().unwrap(),
receipts_root: buffer.read_target_vec()?.try_into().unwrap(),
};
let block_metadata = BlockMetadataTarget {
block_beneficiary: buffer.read_target_vec()?.try_into().unwrap(),
block_timestamp: buffer.read_target()?,
block_number: buffer.read_target()?,
block_difficulty: buffer.read_target()?,
block_gaslimit: buffer.read_target()?,
block_chain_id: buffer.read_target()?,
block_base_fee: buffer.read_target()?,
};
let cpu_trace_len = buffer.read_target()?;
Ok(Self {
trie_roots_before,
trie_roots_after,
block_metadata,
cpu_trace_len,
})
}
pub fn from_public_inputs(pis: &[Target]) -> Self {
assert!(pis.len() > TrieRootsTarget::SIZE * 2 + BlockMetadataTarget::SIZE);
Self {
trie_roots_before: TrieRootsTarget::from_public_inputs(&pis[0..TrieRootsTarget::SIZE]),
trie_roots_after: TrieRootsTarget::from_public_inputs(
&pis[TrieRootsTarget::SIZE..TrieRootsTarget::SIZE * 2],
),
block_metadata: BlockMetadataTarget::from_public_inputs(
&pis[TrieRootsTarget::SIZE * 2
..TrieRootsTarget::SIZE * 2 + BlockMetadataTarget::SIZE],
),
cpu_trace_len: pis[TrieRootsTarget::SIZE * 2 + BlockMetadataTarget::SIZE],
}
}
pub fn select<F: RichField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
condition: BoolTarget,
pv0: Self,
pv1: Self,
) -> Self {
Self {
trie_roots_before: TrieRootsTarget::select(
builder,
condition,
pv0.trie_roots_before,
pv1.trie_roots_before,
),
trie_roots_after: TrieRootsTarget::select(
builder,
condition,
pv0.trie_roots_after,
pv1.trie_roots_after,
),
block_metadata: BlockMetadataTarget::select(
builder,
condition,
pv0.block_metadata,
pv1.block_metadata,
),
cpu_trace_len: builder.select(condition, pv0.cpu_trace_len, pv1.cpu_trace_len),
}
}
2022-08-25 12:24:22 -07:00
}
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
2022-08-25 12:24:22 -07:00
pub struct TrieRootsTarget {
pub state_root: [Target; 8],
pub transactions_root: [Target; 8],
pub receipts_root: [Target; 8],
}
impl TrieRootsTarget {
const SIZE: usize = 24;
pub fn from_public_inputs(pis: &[Target]) -> Self {
let state_root = pis[0..8].try_into().unwrap();
let transactions_root = pis[8..16].try_into().unwrap();
let receipts_root = pis[16..24].try_into().unwrap();
Self {
state_root,
transactions_root,
receipts_root,
}
}
pub fn select<F: RichField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
condition: BoolTarget,
tr0: Self,
tr1: Self,
) -> Self {
Self {
state_root: core::array::from_fn(|i| {
builder.select(condition, tr0.state_root[i], tr1.state_root[i])
}),
transactions_root: core::array::from_fn(|i| {
builder.select(
condition,
tr0.transactions_root[i],
tr1.transactions_root[i],
)
}),
receipts_root: core::array::from_fn(|i| {
builder.select(condition, tr0.receipts_root[i], tr1.receipts_root[i])
}),
}
}
pub fn connect<F: RichField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
tr0: Self,
tr1: Self,
) {
for i in 0..8 {
builder.connect(tr0.state_root[i], tr1.state_root[i]);
builder.connect(tr0.transactions_root[i], tr1.transactions_root[i]);
builder.connect(tr0.receipts_root[i], tr1.receipts_root[i]);
}
}
}
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
2022-08-25 12:24:22 -07:00
pub struct BlockMetadataTarget {
2022-08-25 23:35:38 -07:00
pub block_beneficiary: [Target; 5],
2022-08-25 12:24:22 -07:00
pub block_timestamp: Target,
pub block_number: Target,
pub block_difficulty: Target,
pub block_gaslimit: Target,
pub block_chain_id: Target,
2022-08-25 23:35:38 -07:00
pub block_base_fee: Target,
2022-05-20 11:21:13 +02:00
}
impl BlockMetadataTarget {
const SIZE: usize = 11;
pub fn from_public_inputs(pis: &[Target]) -> Self {
let block_beneficiary = pis[0..5].try_into().unwrap();
let block_timestamp = pis[5];
let block_number = pis[6];
let block_difficulty = pis[7];
let block_gaslimit = pis[8];
let block_chain_id = pis[9];
let block_base_fee = pis[10];
Self {
block_beneficiary,
block_timestamp,
block_number,
block_difficulty,
block_gaslimit,
block_chain_id,
block_base_fee,
}
}
pub fn select<F: RichField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
condition: BoolTarget,
bm0: Self,
bm1: Self,
) -> Self {
Self {
block_beneficiary: core::array::from_fn(|i| {
builder.select(
condition,
bm0.block_beneficiary[i],
bm1.block_beneficiary[i],
)
}),
block_timestamp: builder.select(condition, bm0.block_timestamp, bm1.block_timestamp),
block_number: builder.select(condition, bm0.block_number, bm1.block_number),
block_difficulty: builder.select(condition, bm0.block_difficulty, bm1.block_difficulty),
block_gaslimit: builder.select(condition, bm0.block_gaslimit, bm1.block_gaslimit),
block_chain_id: builder.select(condition, bm0.block_chain_id, bm1.block_chain_id),
block_base_fee: builder.select(condition, bm0.block_base_fee, bm1.block_base_fee),
}
}
pub fn connect<F: RichField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
bm0: Self,
bm1: Self,
) {
for i in 0..5 {
builder.connect(bm0.block_beneficiary[i], bm1.block_beneficiary[i]);
}
builder.connect(bm0.block_timestamp, bm1.block_timestamp);
builder.connect(bm0.block_number, bm1.block_number);
builder.connect(bm0.block_difficulty, bm1.block_difficulty);
builder.connect(bm0.block_gaslimit, bm1.block_gaslimit);
builder.connect(bm0.block_chain_id, bm1.block_chain_id);
builder.connect(bm0.block_base_fee, bm1.block_base_fee);
}
}
2022-05-04 20:57:07 +02:00
#[derive(Debug, Clone)]
pub struct StarkProof<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> {
2022-05-04 20:57:07 +02:00
/// Merkle cap of LDEs of trace values.
pub trace_cap: MerkleCap<F, C::Hasher>,
2022-05-04 20:57:07 +02:00
/// Merkle cap of LDEs of permutation Z values.
pub permutation_ctl_zs_cap: MerkleCap<F, C::Hasher>,
2022-05-04 20:57:07 +02:00
/// Merkle cap of LDEs of trace values.
pub quotient_polys_cap: MerkleCap<F, C::Hasher>,
2022-05-04 20:57:07 +02:00
/// Purported values of each polynomial at the challenge point.
pub openings: StarkOpeningSet<F, D>,
/// A batch FRI argument for all openings.
pub opening_proof: FriProof<F, C::Hasher, D>,
2022-05-04 20:57:07 +02:00
}
/// A `StarkProof` along with some metadata about the initial Fiat-Shamir state, which is used when
/// creating a recursive wrapper proof around a STARK proof.
#[derive(Debug, Clone)]
pub struct StarkProofWithMetadata<F, C, const D: usize>
where
F: RichField + Extendable<D>,
C: GenericConfig<D, F = F>,
{
pub(crate) init_challenger_state: <C::Hasher as Hasher<F>>::Permutation,
// TODO: set it back to pub(crate) when cpu trace len is a public input
pub proof: StarkProof<F, C, D>,
}
impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> StarkProof<F, C, D> {
2022-05-04 20:57:07 +02:00
/// Recover the length of the trace from a STARK proof and a STARK config.
pub fn recover_degree_bits(&self, config: &StarkConfig) -> usize {
let initial_merkle_proof = &self.opening_proof.query_round_proofs[0]
.initial_trees_proof
.evals_proofs[0]
.1;
let lde_bits = config.fri_config.cap_height + initial_merkle_proof.siblings.len();
lde_bits - config.fri_config.rate_bits
}
2022-08-25 22:04:28 +02:00
pub fn num_ctl_zs(&self) -> usize {
self.openings.ctl_zs_last.len()
}
2022-05-04 20:57:07 +02:00
}
#[derive(Eq, PartialEq, Debug)]
2022-05-04 20:57:07 +02:00
pub struct StarkProofTarget<const D: usize> {
pub trace_cap: MerkleCapTarget,
2022-05-20 11:21:13 +02:00
pub permutation_ctl_zs_cap: MerkleCapTarget,
2022-05-04 20:57:07 +02:00
pub quotient_polys_cap: MerkleCapTarget,
pub openings: StarkOpeningSetTarget<D>,
pub opening_proof: FriProofTarget<D>,
}
impl<const D: usize> StarkProofTarget<D> {
pub fn to_buffer(&self, buffer: &mut Vec<u8>) -> IoResult<()> {
buffer.write_target_merkle_cap(&self.trace_cap)?;
buffer.write_target_merkle_cap(&self.permutation_ctl_zs_cap)?;
buffer.write_target_merkle_cap(&self.quotient_polys_cap)?;
buffer.write_target_fri_proof(&self.opening_proof)?;
self.openings.to_buffer(buffer)?;
Ok(())
}
pub fn from_buffer(buffer: &mut Buffer) -> IoResult<Self> {
let trace_cap = buffer.read_target_merkle_cap()?;
let permutation_ctl_zs_cap = buffer.read_target_merkle_cap()?;
let quotient_polys_cap = buffer.read_target_merkle_cap()?;
let opening_proof = buffer.read_target_fri_proof()?;
let openings = StarkOpeningSetTarget::from_buffer(buffer)?;
Ok(Self {
trace_cap,
permutation_ctl_zs_cap,
quotient_polys_cap,
openings,
opening_proof,
})
}
2022-05-04 20:57:07 +02:00
/// Recover the length of the trace from a STARK proof and a STARK config.
pub fn recover_degree_bits(&self, config: &StarkConfig) -> usize {
let initial_merkle_proof = &self.opening_proof.query_round_proofs[0]
.initial_trees_proof
.evals_proofs[0]
.1;
let lde_bits = config.fri_config.cap_height + initial_merkle_proof.siblings.len();
lde_bits - config.fri_config.rate_bits
}
}
pub(crate) struct StarkProofChallenges<F: RichField + Extendable<D>, const D: usize> {
/// Randomness used in any permutation arguments.
pub permutation_challenge_sets: Option<Vec<GrandProductChallengeSet<F>>>,
2022-05-04 20:57:07 +02:00
/// Random values used to combine STARK constraints.
pub stark_alphas: Vec<F>,
/// Point at which the STARK polynomials are opened.
pub stark_zeta: F::Extension,
pub fri_challenges: FriChallenges<F, D>,
}
pub(crate) struct StarkProofChallengesTarget<const D: usize> {
pub permutation_challenge_sets: Option<Vec<GrandProductChallengeSet<Target>>>,
2022-05-04 20:57:07 +02:00
pub stark_alphas: Vec<Target>,
pub stark_zeta: ExtensionTarget<D>,
pub fri_challenges: FriChallengesTarget<D>,
}
/// Purported values of each polynomial at the challenge point.
#[derive(Debug, Clone)]
pub struct StarkOpeningSet<F: RichField + Extendable<D>, const D: usize> {
2022-05-16 20:45:30 +02:00
/// Openings of trace polynomials at `zeta`.
2022-05-04 20:57:07 +02:00
pub local_values: Vec<F::Extension>,
2022-05-16 20:45:30 +02:00
/// Openings of trace polynomials at `g * zeta`.
2022-05-04 20:57:07 +02:00
pub next_values: Vec<F::Extension>,
2022-05-16 20:45:30 +02:00
/// Openings of permutations and cross-table lookups `Z` polynomials at `zeta`.
pub permutation_ctl_zs: Vec<F::Extension>,
2022-05-16 20:45:30 +02:00
/// Openings of permutations and cross-table lookups `Z` polynomials at `g * zeta`.
2022-06-02 23:55:56 +02:00
pub permutation_ctl_zs_next: Vec<F::Extension>,
2022-05-16 20:45:30 +02:00
/// Openings of cross-table lookups `Z` polynomials at `g^-1`.
2022-05-13 11:20:29 +02:00
pub ctl_zs_last: Vec<F>,
2022-05-16 20:45:30 +02:00
/// Openings of quotient polynomials at `zeta`.
2022-05-04 20:57:07 +02:00
pub quotient_polys: Vec<F::Extension>,
}
impl<F: RichField + Extendable<D>, const D: usize> StarkOpeningSet<F, D> {
pub fn new<C: GenericConfig<D, F = F>>(
2022-05-04 20:57:07 +02:00
zeta: F::Extension,
g: F,
trace_commitment: &PolynomialBatch<F, C, D>,
permutation_ctl_zs_commitment: &PolynomialBatch<F, C, D>,
quotient_commitment: &PolynomialBatch<F, C, D>,
2022-05-10 15:21:09 +02:00
degree_bits: usize,
num_permutation_zs: usize,
2022-05-04 20:57:07 +02:00
) -> Self {
let eval_commitment = |z: F::Extension, c: &PolynomialBatch<F, C, D>| {
2022-05-04 20:57:07 +02:00
c.polynomials
.par_iter()
.map(|p| p.to_extension().eval(z))
.collect::<Vec<_>>()
};
let eval_commitment_base = |z: F, c: &PolynomialBatch<F, C, D>| {
2022-05-11 16:09:12 +02:00
c.polynomials
.par_iter()
.map(|p| p.eval(z))
.collect::<Vec<_>>()
};
2022-06-02 23:55:56 +02:00
let zeta_next = zeta.scalar_mul(g);
2022-05-04 20:57:07 +02:00
Self {
local_values: eval_commitment(zeta, trace_commitment),
2022-06-02 23:55:56 +02:00
next_values: eval_commitment(zeta_next, trace_commitment),
permutation_ctl_zs: eval_commitment(zeta, permutation_ctl_zs_commitment),
2022-06-02 23:55:56 +02:00
permutation_ctl_zs_next: eval_commitment(zeta_next, permutation_ctl_zs_commitment),
ctl_zs_last: eval_commitment_base(
F::primitive_root_of_unity(degree_bits).inverse(),
permutation_ctl_zs_commitment,
)[num_permutation_zs..]
.to_vec(),
2022-05-04 20:57:07 +02:00
quotient_polys: eval_commitment(zeta, quotient_commitment),
}
}
pub(crate) fn to_fri_openings(&self) -> FriOpenings<F, D> {
let zeta_batch = FriOpeningBatch {
values: self
.local_values
.iter()
.chain(&self.permutation_ctl_zs)
2022-05-04 20:57:07 +02:00
.chain(&self.quotient_polys)
.copied()
.collect_vec(),
};
2022-06-02 23:55:56 +02:00
let zeta_next_batch = FriOpeningBatch {
2022-05-04 20:57:07 +02:00
values: self
.next_values
.iter()
2022-06-02 23:55:56 +02:00
.chain(&self.permutation_ctl_zs_next)
2022-05-04 20:57:07 +02:00
.copied()
.collect_vec(),
};
2022-05-20 11:21:13 +02:00
debug_assert!(!self.ctl_zs_last.is_empty());
let ctl_last_batch = FriOpeningBatch {
values: self
.ctl_zs_last
.iter()
.copied()
.map(F::Extension::from_basefield)
.collect(),
};
2022-05-10 15:21:09 +02:00
2022-05-20 11:21:13 +02:00
FriOpenings {
2022-06-02 23:55:56 +02:00
batches: vec![zeta_batch, zeta_next_batch, ctl_last_batch],
2022-05-20 11:21:13 +02:00
}
2022-05-04 20:57:07 +02:00
}
}
#[derive(Eq, PartialEq, Debug)]
2022-05-04 20:57:07 +02:00
pub struct StarkOpeningSetTarget<const D: usize> {
pub local_values: Vec<ExtensionTarget<D>>,
pub next_values: Vec<ExtensionTarget<D>>,
2022-05-20 11:21:13 +02:00
pub permutation_ctl_zs: Vec<ExtensionTarget<D>>,
2022-06-02 23:55:56 +02:00
pub permutation_ctl_zs_next: Vec<ExtensionTarget<D>>,
2022-05-20 11:21:13 +02:00
pub ctl_zs_last: Vec<Target>,
2022-05-04 20:57:07 +02:00
pub quotient_polys: Vec<ExtensionTarget<D>>,
}
impl<const D: usize> StarkOpeningSetTarget<D> {
pub fn to_buffer(&self, buffer: &mut Vec<u8>) -> IoResult<()> {
buffer.write_target_ext_vec(&self.local_values)?;
buffer.write_target_ext_vec(&self.next_values)?;
buffer.write_target_ext_vec(&self.permutation_ctl_zs)?;
buffer.write_target_ext_vec(&self.permutation_ctl_zs_next)?;
buffer.write_target_vec(&self.ctl_zs_last)?;
buffer.write_target_ext_vec(&self.quotient_polys)?;
Ok(())
}
pub fn from_buffer(buffer: &mut Buffer) -> IoResult<Self> {
let local_values = buffer.read_target_ext_vec::<D>()?;
let next_values = buffer.read_target_ext_vec::<D>()?;
let permutation_ctl_zs = buffer.read_target_ext_vec::<D>()?;
let permutation_ctl_zs_next = buffer.read_target_ext_vec::<D>()?;
let ctl_zs_last = buffer.read_target_vec()?;
let quotient_polys = buffer.read_target_ext_vec::<D>()?;
Ok(Self {
local_values,
next_values,
permutation_ctl_zs,
permutation_ctl_zs_next,
ctl_zs_last,
quotient_polys,
})
}
2022-05-20 11:21:13 +02:00
pub(crate) fn to_fri_openings(&self, zero: Target) -> FriOpeningsTarget<D> {
2022-05-04 20:57:07 +02:00
let zeta_batch = FriOpeningBatchTarget {
values: self
.local_values
.iter()
2022-05-20 11:21:13 +02:00
.chain(&self.permutation_ctl_zs)
2022-05-04 20:57:07 +02:00
.chain(&self.quotient_polys)
.copied()
.collect_vec(),
};
2022-06-02 23:55:56 +02:00
let zeta_next_batch = FriOpeningBatchTarget {
2022-05-04 20:57:07 +02:00
values: self
.next_values
.iter()
2022-06-02 23:55:56 +02:00
.chain(&self.permutation_ctl_zs_next)
2022-05-04 20:57:07 +02:00
.copied()
.collect_vec(),
};
2022-05-20 11:21:13 +02:00
debug_assert!(!self.ctl_zs_last.is_empty());
let ctl_last_batch = FriOpeningBatchTarget {
values: self
.ctl_zs_last
.iter()
.copied()
.map(|t| t.to_ext_target(zero))
.collect(),
};
2022-05-04 20:57:07 +02:00
FriOpeningsTarget {
2022-06-02 23:55:56 +02:00
batches: vec![zeta_batch, zeta_next_batch, ctl_last_batch],
2022-05-04 20:57:07 +02:00
}
}
}