diff --git a/evm_arithmetization/src/all_stark.rs b/evm_arithmetization/src/all_stark.rs index f37021897..41f4e13fc 100644 --- a/evm_arithmetization/src/all_stark.rs +++ b/evm_arithmetization/src/all_stark.rs @@ -4,10 +4,8 @@ use std::iter; use plonky2::field::extension::Extendable; use plonky2::field::types::Field; use plonky2::hash::hash_types::RichField; -use starky::config::StarkConfig; use starky::cross_table_lookup::{CrossTableLookup, TableIdx, TableWithColumns}; use starky::evaluation_frame::StarkFrame; -use starky::stark::Stark; use crate::arithmetic::arithmetic_stark; use crate::arithmetic::arithmetic_stark::ArithmeticStark; @@ -69,24 +67,6 @@ impl, const D: usize> Default for AllStark { } } -impl, const D: usize> AllStark { - pub(crate) fn num_lookups_helper_columns(&self, config: &StarkConfig) -> [usize; NUM_TABLES] { - [ - self.arithmetic_stark.num_lookup_helper_columns(config), - self.byte_packing_stark.num_lookup_helper_columns(config), - self.cpu_stark.num_lookup_helper_columns(config), - self.keccak_stark.num_lookup_helper_columns(config), - self.keccak_sponge_stark.num_lookup_helper_columns(config), - self.logic_stark.num_lookup_helper_columns(config), - self.memory_stark.num_lookup_helper_columns(config), - self.mem_before_stark.num_lookup_helper_columns(config), - self.mem_after_stark.num_lookup_helper_columns(config), - #[cfg(feature = "cdk_erigon")] - self.poseidon_stark.num_lookup_helper_columns(config), - ] - } -} - pub type EvmStarkFrame = StarkFrame; /// Associates STARK tables with a unique index. diff --git a/evm_arithmetization/src/get_challenges.rs b/evm_arithmetization/src/get_challenges.rs index 5f0df7cfa..1e6410353 100644 --- a/evm_arithmetization/src/get_challenges.rs +++ b/evm_arithmetization/src/get_challenges.rs @@ -3,8 +3,6 @@ use plonky2::field::extension::Extendable; use plonky2::hash::hash_types::RichField; use plonky2::iop::challenger::{Challenger, RecursiveChallenger}; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; -use starky::config::StarkConfig; -use starky::lookup::get_grand_product_challenge_set; use crate::proof::*; use crate::util::{h256_limbs, u256_limbs, u256_to_u32, u256_to_u64}; @@ -247,36 +245,59 @@ pub(crate) fn observe_public_values_target< observe_burn_addr_target::(challenger, public_values.burn_addr.clone()); } -impl, C: GenericConfig, const D: usize> AllProof { - /// Computes all Fiat-Shamir challenges used in the STARK proof. - pub(crate) fn get_challenges( - &self, - config: &StarkConfig, - ) -> Result, ProgramError> { - let mut challenger = Challenger::::new(); +pub mod testing { + use plonky2::field::extension::Extendable; + use plonky2::hash::hash_types::RichField; + use plonky2::iop::challenger::Challenger; + use plonky2::plonk::config::GenericConfig; + use starky::config::StarkConfig; + use starky::lookup::{get_grand_product_challenge_set, GrandProductChallengeSet}; + use starky::proof::StarkProofChallenges; - let stark_proofs = &self.multi_proof.stark_proofs; + use crate::get_challenges::observe_public_values; + use crate::proof::*; + use crate::witness::errors::ProgramError; + use crate::NUM_TABLES; - for proof in stark_proofs { - challenger.observe_cap(&proof.proof.trace_cap); - } + /// Randomness for all STARKs. + pub(crate) struct AllProofChallenges, const D: usize> { + /// Randomness used in each STARK proof. + pub stark_challenges: [StarkProofChallenges; NUM_TABLES], + /// Randomness used for cross-table lookups. It is shared by all STARKs. + pub ctl_challenges: GrandProductChallengeSet, + } + + impl, C: GenericConfig, const D: usize> AllProof { + /// Computes all Fiat-Shamir challenges used in the STARK proof. + pub(crate) fn get_challenges( + &self, + config: &StarkConfig, + ) -> Result, ProgramError> { + let mut challenger = Challenger::::new(); - observe_public_values::(&mut challenger, &self.public_values)?; + let stark_proofs = &self.multi_proof.stark_proofs; - let ctl_challenges = - get_grand_product_challenge_set(&mut challenger, config.num_challenges); + for proof in stark_proofs { + challenger.observe_cap(&proof.proof.trace_cap); + } - Ok(AllProofChallenges { - stark_challenges: core::array::from_fn(|i| { - challenger.compact(); - stark_proofs[i].proof.get_challenges( - &mut challenger, - Some(&ctl_challenges), - true, - config, - ) - }), - ctl_challenges, - }) + observe_public_values::(&mut challenger, &self.public_values)?; + + let ctl_challenges = + get_grand_product_challenge_set(&mut challenger, config.num_challenges); + + Ok(AllProofChallenges { + stark_challenges: core::array::from_fn(|i| { + challenger.compact(); + stark_proofs[i].proof.get_challenges( + &mut challenger, + Some(&ctl_challenges), + true, + config, + ) + }), + ctl_challenges, + }) + } } } diff --git a/evm_arithmetization/src/proof.rs b/evm_arithmetization/src/proof.rs index d4a04deff..ed3e20ee7 100644 --- a/evm_arithmetization/src/proof.rs +++ b/evm_arithmetization/src/proof.rs @@ -10,8 +10,7 @@ use plonky2::plonk::config::{GenericConfig, GenericHashOut, Hasher}; use plonky2::util::serialization::{Buffer, IoResult, Read, Write}; use serde::{Deserialize, Serialize}; use starky::config::StarkConfig; -use starky::lookup::GrandProductChallengeSet; -use starky::proof::{MultiProof, StarkProofChallenges}; +use starky::proof::MultiProof; use crate::all_stark::NUM_TABLES; use crate::util::{get_h160, get_h256, get_u256, h256_limbs, h2u}; @@ -40,14 +39,6 @@ impl, C: GenericConfig, const D: usize> A } } -/// Randomness for all STARKs. -pub(crate) struct AllProofChallenges, const D: usize> { - /// Randomness used in each STARK proof. - pub stark_challenges: [StarkProofChallenges; NUM_TABLES], - /// Randomness used for cross-table lookups. It is shared by all STARKs. - pub ctl_challenges: GrandProductChallengeSet, -} - /// Memory values which are public. #[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, Serialize)] #[serde(bound = "")] diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index f97fc8b40..1c28362c0 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -22,10 +22,10 @@ use starky::stark::Stark; use crate::all_stark::{AllStark, Table, NUM_TABLES}; use crate::cpu::kernel::aggregator::KERNEL; -use crate::generation::segments::GenerationSegmentData; use crate::generation::{generate_traces, GenerationInputs, TrimmedGenerationInputs}; use crate::get_challenges::observe_public_values; use crate::proof::{AllProof, MemCap, PublicValues, DEFAULT_CAP_LEN}; +use crate::GenerationSegmentData; /// Generate traces, then create all STARK proofs. pub fn prove( diff --git a/evm_arithmetization/src/verifier.rs b/evm_arithmetization/src/verifier.rs index caa01859e..1c3f090c5 100644 --- a/evm_arithmetization/src/verifier.rs +++ b/evm_arithmetization/src/verifier.rs @@ -1,27 +1,15 @@ -use anyhow::{ensure, Result}; -use ethereum_types::{BigEndianHash, U256}; -use itertools::Itertools; +use ethereum_types::U256; use plonky2::field::extension::Extendable; use plonky2::field::polynomial::PolynomialValues; use plonky2::fri::oracle::PolynomialBatch; use plonky2::hash::hash_types::RichField; use plonky2::hash::merkle_tree::MerkleCap; -use plonky2::plonk::config::{GenericConfig, GenericHashOut}; +use plonky2::plonk::config::GenericConfig; use plonky2::util::timing::TimingTree; use plonky2::util::transpose; -use starky::config::StarkConfig; -use starky::cross_table_lookup::{get_ctl_vars_from_proofs, verify_cross_table_lookups}; -use starky::lookup::GrandProductChallenge; -use starky::stark::Stark; -use starky::verifier::verify_stark_proof_with_challenges; -use crate::all_stark::{AllStark, Table, NUM_TABLES}; use crate::cpu::kernel::aggregator::KERNEL; -use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::memory::segments::Segment; -use crate::memory::VALUE_LIMBS; -use crate::proof::{AllProof, AllProofChallenges, PublicValues}; -use crate::util::h2u; pub(crate) fn initial_memory_merkle_cap< F: RichField + Extendable, @@ -89,328 +77,374 @@ pub(crate) fn initial_memory_merkle_cap< .cap } -fn verify_initial_memory< - F: RichField + Extendable, - C: GenericConfig, - const D: usize, ->( - public_values: &PublicValues, - config: &StarkConfig, -) -> Result<()> { - for (hash1, hash2) in initial_memory_merkle_cap::( - config.fri_config.rate_bits, - config.fri_config.cap_height, - ) - .0 - .iter() - .zip(public_values.mem_before.mem_cap.iter()) - { - for (&limb1, limb2) in hash1.to_vec().iter().zip(hash2) { - ensure!( - limb1 == F::from_canonical_u64(limb2.as_u64()), - anyhow::Error::msg("Invalid initial MemBefore Merkle cap.") - ); +pub mod testing { + use anyhow::{ensure, Result}; + use ethereum_types::{BigEndianHash, U256}; + use itertools::Itertools; + use plonky2::field::extension::Extendable; + use plonky2::hash::hash_types::RichField; + use plonky2::plonk::config::{GenericConfig, GenericHashOut}; + use starky::config::StarkConfig; + use starky::cross_table_lookup::{get_ctl_vars_from_proofs, verify_cross_table_lookups}; + use starky::lookup::GrandProductChallenge; + use starky::stark::Stark; + use starky::verifier::verify_stark_proof_with_challenges; + + use crate::all_stark::Table; + use crate::cpu::kernel::aggregator::KERNEL; + use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; + use crate::get_challenges::testing::AllProofChallenges; + use crate::memory::segments::Segment; + use crate::memory::VALUE_LIMBS; + use crate::proof::PublicValues; + use crate::proof::*; + use crate::util::h2u; + use crate::verifier::initial_memory_merkle_cap; + use crate::{AllStark, NUM_TABLES}; + + impl, const D: usize> AllStark { + pub(crate) fn num_lookups_helper_columns( + &self, + config: &StarkConfig, + ) -> [usize; NUM_TABLES] { + [ + self.arithmetic_stark.num_lookup_helper_columns(config), + self.byte_packing_stark.num_lookup_helper_columns(config), + self.cpu_stark.num_lookup_helper_columns(config), + self.keccak_stark.num_lookup_helper_columns(config), + self.keccak_sponge_stark.num_lookup_helper_columns(config), + self.logic_stark.num_lookup_helper_columns(config), + self.memory_stark.num_lookup_helper_columns(config), + self.mem_before_stark.num_lookup_helper_columns(config), + self.mem_after_stark.num_lookup_helper_columns(config), + #[cfg(feature = "cdk_erigon")] + self.poseidon_stark.num_lookup_helper_columns(config), + ] } } - Ok(()) -} + fn verify_initial_memory< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( + public_values: &PublicValues, + config: &StarkConfig, + ) -> Result<()> { + for (hash1, hash2) in initial_memory_merkle_cap::( + config.fri_config.rate_bits, + config.fri_config.cap_height, + ) + .0 + .iter() + .zip(public_values.mem_before.mem_cap.iter()) + { + for (&limb1, limb2) in hash1.to_vec().iter().zip(hash2) { + ensure!( + limb1 == F::from_canonical_u64(limb2.as_u64()), + anyhow::Error::msg("Invalid initial MemBefore Merkle cap.") + ); + } + } + + Ok(()) + } + + pub fn verify_proof< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( + all_stark: &AllStark, + all_proof: AllProof, + config: &StarkConfig, + is_initial: bool, + ) -> Result<()> { + let AllProofChallenges { + stark_challenges, + ctl_challenges, + } = all_proof + .get_challenges(config) + .map_err(|_| anyhow::Error::msg("Invalid sampling of proof challenges."))?; + + let num_lookup_columns = all_stark.num_lookups_helper_columns(config); + + let AllStark { + arithmetic_stark, + byte_packing_stark, + cpu_stark, + keccak_stark, + keccak_sponge_stark, + logic_stark, + memory_stark, + mem_before_stark, + mem_after_stark, + #[cfg(feature = "cdk_erigon")] + poseidon_stark, + cross_table_lookups, + } = all_stark; + + let ctl_vars_per_table = get_ctl_vars_from_proofs( + &all_proof.multi_proof, + cross_table_lookups, + &ctl_challenges, + &num_lookup_columns, + all_stark.arithmetic_stark.constraint_degree(), + ); + + let stark_proofs = &all_proof.multi_proof.stark_proofs; + + macro_rules! verify_table { + ($stark:ident, $table:expr) => { + verify_stark_proof_with_challenges( + $stark, + &stark_proofs[*$table].proof, + &stark_challenges[*$table], + Some(&ctl_vars_per_table[*$table]), + &[], + config, + )?; + }; + } + + verify_table!(arithmetic_stark, Table::Arithmetic); + verify_table!(byte_packing_stark, Table::BytePacking); + verify_table!(cpu_stark, Table::Cpu); + verify_table!(keccak_stark, Table::Keccak); + verify_table!(keccak_sponge_stark, Table::KeccakSponge); + verify_table!(logic_stark, Table::Logic); + verify_table!(memory_stark, Table::Memory); + verify_table!(mem_before_stark, Table::MemBefore); + verify_table!(mem_after_stark, Table::MemAfter); -fn verify_proof, C: GenericConfig, const D: usize>( - all_stark: &AllStark, - all_proof: AllProof, - config: &StarkConfig, - is_initial: bool, -) -> Result<()> { - let AllProofChallenges { - stark_challenges, - ctl_challenges, - } = all_proof - .get_challenges(config) - .map_err(|_| anyhow::Error::msg("Invalid sampling of proof challenges."))?; - - let num_lookup_columns = all_stark.num_lookups_helper_columns(config); - - let AllStark { - arithmetic_stark, - byte_packing_stark, - cpu_stark, - keccak_stark, - keccak_sponge_stark, - logic_stark, - memory_stark, - mem_before_stark, - mem_after_stark, #[cfg(feature = "cdk_erigon")] - poseidon_stark, - cross_table_lookups, - } = all_stark; - - let ctl_vars_per_table = get_ctl_vars_from_proofs( - &all_proof.multi_proof, - cross_table_lookups, - &ctl_challenges, - &num_lookup_columns, - all_stark.arithmetic_stark.constraint_degree(), - ); + verify_table!(poseidon_stark, Table::Poseidon); - let stark_proofs = &all_proof.multi_proof.stark_proofs; - - macro_rules! verify_table { - ($stark:ident, $table:expr) => { - verify_stark_proof_with_challenges( - $stark, - &stark_proofs[*$table].proof, - &stark_challenges[*$table], - Some(&ctl_vars_per_table[*$table]), - &[], - config, - )?; - }; + let public_values = all_proof.public_values; + + // Verify shift table and kernel code. + if is_initial { + verify_initial_memory::(&public_values, config)?; + } + + // Extra sums to add to the looked last value. + // Only necessary for the Memory values. + let mut extra_looking_sums = vec![vec![F::ZERO; config.num_challenges]; NUM_TABLES]; + + // Memory + extra_looking_sums[*Table::Memory] = (0..config.num_challenges) + .map(|i| get_memory_extra_looking_sum(&public_values, ctl_challenges.challenges[i])) + .collect_vec(); + + verify_cross_table_lookups::( + cross_table_lookups, + all_proof + .multi_proof + .stark_proofs + .map(|p| p.proof.openings.ctl_zs_first.unwrap()), + Some(&extra_looking_sums), + config, + ) } - verify_table!(arithmetic_stark, Table::Arithmetic); - verify_table!(byte_packing_stark, Table::BytePacking); - verify_table!(cpu_stark, Table::Cpu); - verify_table!(keccak_stark, Table::Keccak); - verify_table!(keccak_sponge_stark, Table::KeccakSponge); - verify_table!(logic_stark, Table::Logic); - verify_table!(memory_stark, Table::Memory); - verify_table!(mem_before_stark, Table::MemBefore); - verify_table!(mem_after_stark, Table::MemAfter); + /// Computes the extra product to multiply to the looked value. It contains + /// memory operations not in the CPU trace: + /// - block metadata writes, + /// - trie roots writes. + pub(crate) fn get_memory_extra_looking_sum( + public_values: &PublicValues, + challenge: GrandProductChallenge, + ) -> F + where + F: RichField + Extendable, + { + let mut sum = F::ZERO; - #[cfg(feature = "cdk_erigon")] - verify_table!(poseidon_stark, Table::Poseidon); + // Add metadata and tries writes. + let fields = [ + ( + GlobalMetadata::BlockBeneficiary, + U256::from_big_endian(&public_values.block_metadata.block_beneficiary.0), + ), + #[cfg(feature = "cdk_erigon")] + ( + GlobalMetadata::BurnAddr, + public_values + .burn_addr + .expect("There should be an address set in cdk_erigon."), + ), + ( + GlobalMetadata::BlockTimestamp, + public_values.block_metadata.block_timestamp, + ), + ( + GlobalMetadata::BlockNumber, + public_values.block_metadata.block_number, + ), + ( + GlobalMetadata::BlockRandom, + public_values.block_metadata.block_random.into_uint(), + ), + ( + GlobalMetadata::BlockDifficulty, + public_values.block_metadata.block_difficulty, + ), + ( + GlobalMetadata::BlockGasLimit, + public_values.block_metadata.block_gaslimit, + ), + ( + GlobalMetadata::BlockChainId, + public_values.block_metadata.block_chain_id, + ), + ( + GlobalMetadata::BlockBaseFee, + public_values.block_metadata.block_base_fee, + ), + #[cfg(feature = "eth_mainnet")] + ( + GlobalMetadata::ParentBeaconBlockRoot, + h2u(public_values.block_metadata.parent_beacon_block_root), + ), + ( + GlobalMetadata::BlockCurrentHash, + h2u(public_values.block_hashes.cur_hash), + ), + ( + GlobalMetadata::BlockGasUsed, + public_values.block_metadata.block_gas_used, + ), + #[cfg(feature = "eth_mainnet")] + ( + GlobalMetadata::BlockBlobGasUsed, + public_values.block_metadata.block_blob_gas_used, + ), + #[cfg(feature = "eth_mainnet")] + ( + GlobalMetadata::BlockExcessBlobGas, + public_values.block_metadata.block_excess_blob_gas, + ), + ( + GlobalMetadata::TxnNumberBefore, + public_values.extra_block_data.txn_number_before, + ), + ( + GlobalMetadata::TxnNumberAfter, + public_values.extra_block_data.txn_number_after, + ), + ( + GlobalMetadata::BlockGasUsedBefore, + public_values.extra_block_data.gas_used_before, + ), + ( + GlobalMetadata::BlockGasUsedAfter, + public_values.extra_block_data.gas_used_after, + ), + ( + GlobalMetadata::StateTrieRootDigestBefore, + h2u(public_values.trie_roots_before.state_root), + ), + ( + GlobalMetadata::TransactionTrieRootDigestBefore, + h2u(public_values.trie_roots_before.transactions_root), + ), + ( + GlobalMetadata::ReceiptTrieRootDigestBefore, + h2u(public_values.trie_roots_before.receipts_root), + ), + ( + GlobalMetadata::StateTrieRootDigestAfter, + h2u(public_values.trie_roots_after.state_root), + ), + ( + GlobalMetadata::TransactionTrieRootDigestAfter, + h2u(public_values.trie_roots_after.transactions_root), + ), + ( + GlobalMetadata::ReceiptTrieRootDigestAfter, + h2u(public_values.trie_roots_after.receipts_root), + ), + (GlobalMetadata::KernelHash, h2u(KERNEL.code_hash)), + (GlobalMetadata::KernelLen, KERNEL.code.len().into()), + ]; - let public_values = all_proof.public_values; + let segment = F::from_canonical_usize(Segment::GlobalMetadata.unscale()); - // Verify shift table and kernel code. - if is_initial { - verify_initial_memory::(&public_values, config)?; - } + fields.map(|(field, val)| { + // These fields are already scaled by their segment, and are in context 0 + // (kernel). + sum = add_data_write(challenge, segment, sum, field.unscale(), val) + }); - // Extra sums to add to the looked last value. - // Only necessary for the Memory values. - let mut extra_looking_sums = vec![vec![F::ZERO; config.num_challenges]; NUM_TABLES]; - - // Memory - extra_looking_sums[*Table::Memory] = (0..config.num_challenges) - .map(|i| get_memory_extra_looking_sum(&public_values, ctl_challenges.challenges[i])) - .collect_vec(); - - verify_cross_table_lookups::( - cross_table_lookups, - all_proof - .multi_proof - .stark_proofs - .map(|p| p.proof.openings.ctl_zs_first.unwrap()), - Some(&extra_looking_sums), - config, - ) -} + // Add block bloom writes. + let bloom_segment = F::from_canonical_usize(Segment::GlobalBlockBloom.unscale()); + for index in 0..8 { + let val = public_values.block_metadata.block_bloom[index]; + sum = add_data_write(challenge, bloom_segment, sum, index, val); + } -/// Computes the extra product to multiply to the looked value. It contains -/// memory operations not in the CPU trace: -/// - block metadata writes, -/// - trie roots writes. -pub(crate) fn get_memory_extra_looking_sum( - public_values: &PublicValues, - challenge: GrandProductChallenge, -) -> F -where - F: RichField + Extendable, -{ - let mut sum = F::ZERO; - - // Add metadata and tries writes. - let fields = [ - ( - GlobalMetadata::BlockBeneficiary, - U256::from_big_endian(&public_values.block_metadata.block_beneficiary.0), - ), - #[cfg(feature = "cdk_erigon")] - ( - GlobalMetadata::BurnAddr, - public_values - .burn_addr - .expect("There should be an address set in cdk_erigon."), - ), - ( - GlobalMetadata::BlockTimestamp, - public_values.block_metadata.block_timestamp, - ), - ( - GlobalMetadata::BlockNumber, - public_values.block_metadata.block_number, - ), - ( - GlobalMetadata::BlockRandom, - public_values.block_metadata.block_random.into_uint(), - ), - ( - GlobalMetadata::BlockDifficulty, - public_values.block_metadata.block_difficulty, - ), - ( - GlobalMetadata::BlockGasLimit, - public_values.block_metadata.block_gaslimit, - ), - ( - GlobalMetadata::BlockChainId, - public_values.block_metadata.block_chain_id, - ), - ( - GlobalMetadata::BlockBaseFee, - public_values.block_metadata.block_base_fee, - ), - #[cfg(feature = "eth_mainnet")] - ( - GlobalMetadata::ParentBeaconBlockRoot, - h2u(public_values.block_metadata.parent_beacon_block_root), - ), - ( - GlobalMetadata::BlockCurrentHash, - h2u(public_values.block_hashes.cur_hash), - ), - ( - GlobalMetadata::BlockGasUsed, - public_values.block_metadata.block_gas_used, - ), - #[cfg(feature = "eth_mainnet")] - ( - GlobalMetadata::BlockBlobGasUsed, - public_values.block_metadata.block_blob_gas_used, - ), - #[cfg(feature = "eth_mainnet")] - ( - GlobalMetadata::BlockExcessBlobGas, - public_values.block_metadata.block_excess_blob_gas, - ), - ( - GlobalMetadata::TxnNumberBefore, - public_values.extra_block_data.txn_number_before, - ), - ( - GlobalMetadata::TxnNumberAfter, - public_values.extra_block_data.txn_number_after, - ), - ( - GlobalMetadata::BlockGasUsedBefore, - public_values.extra_block_data.gas_used_before, - ), - ( - GlobalMetadata::BlockGasUsedAfter, - public_values.extra_block_data.gas_used_after, - ), - ( - GlobalMetadata::StateTrieRootDigestBefore, - h2u(public_values.trie_roots_before.state_root), - ), - ( - GlobalMetadata::TransactionTrieRootDigestBefore, - h2u(public_values.trie_roots_before.transactions_root), - ), - ( - GlobalMetadata::ReceiptTrieRootDigestBefore, - h2u(public_values.trie_roots_before.receipts_root), - ), - ( - GlobalMetadata::StateTrieRootDigestAfter, - h2u(public_values.trie_roots_after.state_root), - ), - ( - GlobalMetadata::TransactionTrieRootDigestAfter, - h2u(public_values.trie_roots_after.transactions_root), - ), - ( - GlobalMetadata::ReceiptTrieRootDigestAfter, - h2u(public_values.trie_roots_after.receipts_root), - ), - (GlobalMetadata::KernelHash, h2u(KERNEL.code_hash)), - (GlobalMetadata::KernelLen, KERNEL.code.len().into()), - ]; - - let segment = F::from_canonical_usize(Segment::GlobalMetadata.unscale()); - - fields.map(|(field, val)| { - // These fields are already scaled by their segment, and are in context 0 - // (kernel). - sum = add_data_write(challenge, segment, sum, field.unscale(), val) - }); - - // Add block bloom writes. - let bloom_segment = F::from_canonical_usize(Segment::GlobalBlockBloom.unscale()); - for index in 0..8 { - let val = public_values.block_metadata.block_bloom[index]; - sum = add_data_write(challenge, bloom_segment, sum, index, val); - } + // Add Blockhashes writes. + let block_hashes_segment = F::from_canonical_usize(Segment::BlockHashes.unscale()); + for index in 0..256 { + let val = h2u(public_values.block_hashes.prev_hashes[index]); + sum = add_data_write(challenge, block_hashes_segment, sum, index, val); + } - // Add Blockhashes writes. - let block_hashes_segment = F::from_canonical_usize(Segment::BlockHashes.unscale()); - for index in 0..256 { - let val = h2u(public_values.block_hashes.prev_hashes[index]); - sum = add_data_write(challenge, block_hashes_segment, sum, index, val); - } + let registers_segment = F::from_canonical_usize(Segment::RegistersStates.unscale()); + let registers_before = [ + public_values.registers_before.program_counter, + public_values.registers_before.is_kernel, + public_values.registers_before.stack_len, + public_values.registers_before.stack_top, + public_values.registers_before.context, + public_values.registers_before.gas_used, + ]; + for i in 0..registers_before.len() { + sum = add_data_write(challenge, registers_segment, sum, i, registers_before[i]); + } + let registers_after = [ + public_values.registers_after.program_counter, + public_values.registers_after.is_kernel, + public_values.registers_after.stack_len, + public_values.registers_after.stack_top, + public_values.registers_after.context, + public_values.registers_after.gas_used, + ]; + for i in 0..registers_before.len() { + sum = add_data_write( + challenge, + registers_segment, + sum, + registers_before.len() + i, + registers_after[i], + ); + } - let registers_segment = F::from_canonical_usize(Segment::RegistersStates.unscale()); - let registers_before = [ - public_values.registers_before.program_counter, - public_values.registers_before.is_kernel, - public_values.registers_before.stack_len, - public_values.registers_before.stack_top, - public_values.registers_before.context, - public_values.registers_before.gas_used, - ]; - for i in 0..registers_before.len() { - sum = add_data_write(challenge, registers_segment, sum, i, registers_before[i]); - } - let registers_after = [ - public_values.registers_after.program_counter, - public_values.registers_after.is_kernel, - public_values.registers_after.stack_len, - public_values.registers_after.stack_top, - public_values.registers_after.context, - public_values.registers_after.gas_used, - ]; - for i in 0..registers_before.len() { - sum = add_data_write( - challenge, - registers_segment, - sum, - registers_before.len() + i, - registers_after[i], - ); + sum } - sum -} + fn add_data_write( + challenge: GrandProductChallenge, + segment: F, + running_sum: F, + index: usize, + val: U256, + ) -> F + where + F: RichField + Extendable, + { + let mut row = [F::ZERO; 13]; + row[0] = F::ZERO; // is_read + row[1] = F::ZERO; // context + row[2] = segment; + row[3] = F::from_canonical_usize(index); -fn add_data_write( - challenge: GrandProductChallenge, - segment: F, - running_sum: F, - index: usize, - val: U256, -) -> F -where - F: RichField + Extendable, -{ - let mut row = [F::ZERO; 13]; - row[0] = F::ZERO; // is_read - row[1] = F::ZERO; // context - row[2] = segment; - row[3] = F::from_canonical_usize(index); - - for j in 0..VALUE_LIMBS { - row[j + 4] = F::from_canonical_u32((val >> (j * 32)).low_u32()); + for j in 0..VALUE_LIMBS { + row[j + 4] = F::from_canonical_u32((val >> (j * 32)).low_u32()); + } + row[12] = F::TWO; // timestamp + running_sum + challenge.combine(row.iter()).inverse() } - row[12] = F::TWO; // timestamp - running_sum + challenge.combine(row.iter()).inverse() -} - -/// A utility module designed to verify proofs. -pub mod testing { - use super::*; pub fn verify_all_proofs< F: RichField + Extendable, @@ -435,7 +469,13 @@ pub mod testing { #[cfg(debug_assertions)] pub(crate) mod debug_utils { + use ethereum_types::BigEndianHash; + use super::*; + use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; + use crate::memory::VALUE_LIMBS; + use crate::proof::*; + use crate::util::h2u; /// Output all the extra memory rows that don't appear in the CPU trace but /// are necessary to correctly check the MemoryStark CTL.