From 9a4500683be80267809e66ba5339b540bd2f3545 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Sat, 19 Aug 2023 10:23:24 -0400 Subject: [PATCH 1/2] Update BlockBaseFee to fit in 2 limbs --- evm/src/fixed_recursive_verifier.rs | 35 ++++++++++++++++++++++++----- evm/src/get_challenges.rs | 7 ++++-- evm/src/proof.rs | 18 +++++++++------ evm/src/recursive_verifier.rs | 11 ++++++--- 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/evm/src/fixed_recursive_verifier.rs b/evm/src/fixed_recursive_verifier.rs index d48afd8c..26579bec 100644 --- a/evm/src/fixed_recursive_verifier.rs +++ b/evm/src/fixed_recursive_verifier.rs @@ -570,7 +570,7 @@ where let mut prod = builder.constant(F::ONE); // Add metadata writes. - let block_fields_without_beneficiary = [ + let block_fields_without_beneficiary_and_basefee = [ ( GlobalMetadata::BlockTimestamp, public_values.block_metadata.block_timestamp, @@ -591,16 +591,13 @@ where GlobalMetadata::BlockChainId, public_values.block_metadata.block_chain_id, ), - ( - GlobalMetadata::BlockBaseFee, - public_values.block_metadata.block_base_fee, - ), ]; let zero = builder.constant(F::ZERO); let one = builder.constant(F::ONE); let segment = builder.constant(F::from_canonical_u32(Segment::GlobalMetadata as u32)); + // Include the block beneficiary. let row = builder.add_virtual_targets(13); // is_read builder.connect(row[0], zero); @@ -629,7 +626,7 @@ where let combined = challenge.combine_base_circuit(builder, &row); prod = builder.mul(prod, combined); - block_fields_without_beneficiary.map(|(field, target)| { + block_fields_without_beneficiary_and_basefee.map(|(field, target)| { let row = builder.add_virtual_targets(13); // is_read builder.connect(row[0], zero); @@ -651,6 +648,32 @@ where prod = builder.mul(prod, combined); }); + // Include the block base fee. + let row = builder.add_virtual_targets(13); + // is_read + builder.connect(row[0], zero); + // context + builder.connect(row[1], zero); + // segment + builder.connect(row[2], segment); + // virtual + let field_target = builder.constant(F::from_canonical_usize( + GlobalMetadata::BlockBaseFee as usize, + )); + builder.connect(row[3], field_target); + // values + for j in 0..2 { + builder.connect(row[4 + j], public_values.block_metadata.block_base_fee[j]); + } + for j in 2..VALUE_LIMBS { + builder.connect(row[4 + j], zero); + } + // timestamp + builder.connect(row[12], one); + + let combined = challenge.combine_base_circuit(builder, &row); + prod = builder.mul(prod, combined); + // Add trie roots writes. let trie_fields = [ ( diff --git a/evm/src/get_challenges.rs b/evm/src/get_challenges.rs index 07504350..9b03b80d 100644 --- a/evm/src/get_challenges.rs +++ b/evm/src/get_challenges.rs @@ -74,7 +74,10 @@ fn observe_block_metadata< block_metadata.block_chain_id.as_u32(), )); challenger.observe_element(F::from_canonical_u32( - block_metadata.block_base_fee.as_u32(), + block_metadata.block_base_fee.as_u64() as u32, + )); + challenger.observe_element(F::from_canonical_u32( + (block_metadata.block_base_fee.as_u64() >> 32) as u32, )); } @@ -94,7 +97,7 @@ fn observe_block_metadata_target< challenger.observe_element(block_metadata.block_difficulty); challenger.observe_element(block_metadata.block_gaslimit); challenger.observe_element(block_metadata.block_chain_id); - challenger.observe_element(block_metadata.block_base_fee); + challenger.observe_elements(&block_metadata.block_base_fee); } pub(crate) fn observe_public_values< diff --git a/evm/src/proof.rs b/evm/src/proof.rs index df4b9358..cd73d847 100644 --- a/evm/src/proof.rs +++ b/evm/src/proof.rs @@ -120,7 +120,7 @@ impl PublicValuesTarget { 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_vec(&block_base_fee)?; Ok(()) } @@ -145,7 +145,7 @@ impl PublicValuesTarget { block_difficulty: buffer.read_target()?, block_gaslimit: buffer.read_target()?, block_chain_id: buffer.read_target()?, - block_base_fee: buffer.read_target()?, + block_base_fee: buffer.read_target_vec()?.try_into().unwrap(), }; Ok(Self { @@ -264,11 +264,11 @@ pub struct BlockMetadataTarget { pub block_difficulty: Target, pub block_gaslimit: Target, pub block_chain_id: Target, - pub block_base_fee: Target, + pub block_base_fee: [Target; 2], } impl BlockMetadataTarget { - const SIZE: usize = 11; + const SIZE: usize = 12; pub fn from_public_inputs(pis: &[Target]) -> Self { let block_beneficiary = pis[0..5].try_into().unwrap(); @@ -277,7 +277,7 @@ impl BlockMetadataTarget { let block_difficulty = pis[7]; let block_gaslimit = pis[8]; let block_chain_id = pis[9]; - let block_base_fee = pis[10]; + let block_base_fee = pis[10..12].try_into().unwrap(); Self { block_beneficiary, @@ -309,7 +309,9 @@ impl BlockMetadataTarget { 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), + block_base_fee: core::array::from_fn(|i| { + builder.select(condition, bm0.block_base_fee[i], bm1.block_base_fee[i]) + }), } } @@ -326,7 +328,9 @@ impl BlockMetadataTarget { 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); + for i in 0..2 { + builder.connect(bm0.block_base_fee[i], bm1.block_base_fee[i]) + } } } diff --git a/evm/src/recursive_verifier.rs b/evm/src/recursive_verifier.rs index dc1469f3..ffe0e90d 100644 --- a/evm/src/recursive_verifier.rs +++ b/evm/src/recursive_verifier.rs @@ -548,7 +548,7 @@ pub(crate) fn add_virtual_block_metadata, const D: let block_difficulty = builder.add_virtual_public_input(); let block_gaslimit = builder.add_virtual_public_input(); let block_chain_id = builder.add_virtual_public_input(); - let block_base_fee = builder.add_virtual_public_input(); + let block_base_fee = builder.add_virtual_public_input_arr(); BlockMetadataTarget { block_beneficiary, block_timestamp, @@ -749,8 +749,13 @@ pub(crate) fn set_block_metadata_target( block_metadata_target.block_chain_id, F::from_canonical_u32(block_metadata.block_chain_id.as_u32()), ); + // Basefee fits in 2 limbs witness.set_target( - block_metadata_target.block_base_fee, - F::from_canonical_u32(block_metadata.block_base_fee.as_u32()), + block_metadata_target.block_base_fee[0], + F::from_canonical_u32(block_metadata.block_base_fee.as_u64() as u32), + ); + witness.set_target( + block_metadata_target.block_base_fee[1], + F::from_canonical_u32((block_metadata.block_base_fee.as_u64() >> 32) as u32), ); } From 8476fdcd938b26a63569484e2fd5a5e512545b58 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Sat, 19 Aug 2023 10:46:01 -0400 Subject: [PATCH 2/2] Refactor --- evm/src/fixed_recursive_verifier.rs | 182 +--------------------------- evm/src/recursive_verifier.rs | 134 ++++++++++++++++++++ 2 files changed, 140 insertions(+), 176 deletions(-) diff --git a/evm/src/fixed_recursive_verifier.rs b/evm/src/fixed_recursive_verifier.rs index 26579bec..e0e7f4cf 100644 --- a/evm/src/fixed_recursive_verifier.rs +++ b/evm/src/fixed_recursive_verifier.rs @@ -30,7 +30,6 @@ use crate::all_stark::{all_cross_table_lookups, AllStark, Table, NUM_TABLES}; use crate::arithmetic::arithmetic_stark::ArithmeticStark; use crate::config::StarkConfig; use crate::cpu::cpu_stark::CpuStark; -use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cross_table_lookup::{verify_cross_table_lookups_circuit, CrossTableLookup}; use crate::generation::GenerationInputs; use crate::get_challenges::observe_public_values_target; @@ -38,19 +37,16 @@ use crate::keccak::keccak_stark::KeccakStark; use crate::keccak_sponge::keccak_sponge_stark::KeccakSpongeStark; use crate::logic::LogicStark; use crate::memory::memory_stark::MemoryStark; -use crate::memory::segments::Segment; -use crate::memory::VALUE_LIMBS; -use crate::permutation::{ - get_grand_product_challenge_set_target, GrandProductChallenge, GrandProductChallengeSet, -}; +use crate::permutation::{get_grand_product_challenge_set_target, GrandProductChallengeSet}; use crate::proof::{ BlockMetadataTarget, PublicValues, PublicValuesTarget, StarkProofWithMetadata, TrieRootsTarget, }; use crate::prover::prove; use crate::recursive_verifier::{ - add_common_recursion_gates, add_virtual_public_values, recursive_stark_circuit, - set_block_metadata_target, set_public_value_targets, set_trie_roots_target, - PlonkWrapperCircuit, PublicInputs, StarkWrapperCircuit, + add_common_recursion_gates, add_virtual_public_values, + get_memory_extra_looking_products_circuit, recursive_stark_circuit, set_block_metadata_target, + set_public_value_targets, set_trie_roots_target, PlonkWrapperCircuit, PublicInputs, + StarkWrapperCircuit, }; use crate::stark::Stark; @@ -498,7 +494,7 @@ where // Memory let memory_looking_products = (0..stark_config.num_challenges) .map(|c| { - Self::get_memory_extra_looking_products_circuit( + get_memory_extra_looking_products_circuit( &mut builder, &public_values, ctl_challenges.challenges[c], @@ -561,172 +557,6 @@ where } } - /// Recursive version of `get_memory_extra_looking_products`. - pub(crate) fn get_memory_extra_looking_products_circuit( - builder: &mut CircuitBuilder, - public_values: &PublicValuesTarget, - challenge: GrandProductChallenge, - ) -> Target { - let mut prod = builder.constant(F::ONE); - - // Add metadata writes. - let block_fields_without_beneficiary_and_basefee = [ - ( - GlobalMetadata::BlockTimestamp, - public_values.block_metadata.block_timestamp, - ), - ( - GlobalMetadata::BlockNumber, - public_values.block_metadata.block_number, - ), - ( - 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, - ), - ]; - - let zero = builder.constant(F::ZERO); - let one = builder.constant(F::ONE); - let segment = builder.constant(F::from_canonical_u32(Segment::GlobalMetadata as u32)); - - // Include the block beneficiary. - let row = builder.add_virtual_targets(13); - // is_read - builder.connect(row[0], zero); - // context - builder.connect(row[1], zero); - // segment - builder.connect(row[2], segment); - // virtual - let field_target = builder.constant(F::from_canonical_usize( - GlobalMetadata::BlockBeneficiary as usize, - )); - builder.connect(row[3], field_target); - // values - for j in 0..5 { - builder.connect( - row[4 + j], - public_values.block_metadata.block_beneficiary[j], - ); - } - for j in 5..VALUE_LIMBS { - builder.connect(row[4 + j], zero); - } - // timestamp - builder.connect(row[12], one); - - let combined = challenge.combine_base_circuit(builder, &row); - prod = builder.mul(prod, combined); - - block_fields_without_beneficiary_and_basefee.map(|(field, target)| { - let row = builder.add_virtual_targets(13); - // is_read - builder.connect(row[0], zero); - // context - builder.connect(row[1], zero); - // segment - builder.connect(row[2], segment); - // virtual - let field_target = builder.constant(F::from_canonical_usize(field as usize)); - builder.connect(row[3], field_target); - // These values only have one cell. - builder.connect(row[4], target); - for j in 1..VALUE_LIMBS { - builder.connect(row[4 + j], zero); - } - // timestamp - builder.connect(row[12], one); - let combined = challenge.combine_base_circuit(builder, &row); - prod = builder.mul(prod, combined); - }); - - // Include the block base fee. - let row = builder.add_virtual_targets(13); - // is_read - builder.connect(row[0], zero); - // context - builder.connect(row[1], zero); - // segment - builder.connect(row[2], segment); - // virtual - let field_target = builder.constant(F::from_canonical_usize( - GlobalMetadata::BlockBaseFee as usize, - )); - builder.connect(row[3], field_target); - // values - for j in 0..2 { - builder.connect(row[4 + j], public_values.block_metadata.block_base_fee[j]); - } - for j in 2..VALUE_LIMBS { - builder.connect(row[4 + j], zero); - } - // timestamp - builder.connect(row[12], one); - - let combined = challenge.combine_base_circuit(builder, &row); - prod = builder.mul(prod, combined); - - // Add trie roots writes. - let trie_fields = [ - ( - GlobalMetadata::StateTrieRootDigestBefore, - public_values.trie_roots_before.state_root, - ), - ( - GlobalMetadata::TransactionTrieRootDigestBefore, - public_values.trie_roots_before.transactions_root, - ), - ( - GlobalMetadata::ReceiptTrieRootDigestBefore, - public_values.trie_roots_before.receipts_root, - ), - ( - GlobalMetadata::StateTrieRootDigestAfter, - public_values.trie_roots_after.state_root, - ), - ( - GlobalMetadata::TransactionTrieRootDigestAfter, - public_values.trie_roots_after.transactions_root, - ), - ( - GlobalMetadata::ReceiptTrieRootDigestAfter, - public_values.trie_roots_after.receipts_root, - ), - ]; - - trie_fields.map(|(field, targets)| { - let row = builder.add_virtual_targets(13); - // is_read - builder.connect(row[0], zero); - // context - builder.connect(row[1], zero); - // segment - builder.connect(row[2], segment); - // virtual - let field_target = builder.constant(F::from_canonical_usize(field as usize)); - builder.connect(row[3], field_target); - // values - for j in 0..VALUE_LIMBS { - builder.connect(row[4 + j], targets[j]); - } - // timestamp - builder.connect(row[12], one); - - let combined = challenge.combine_base_circuit(builder, &row); - prod = builder.mul(prod, combined); - }); - - prod - } - fn create_aggregation_circuit( root: &RootCircuitData, ) -> AggregationCircuitData { diff --git a/evm/src/recursive_verifier.rs b/evm/src/recursive_verifier.rs index ffe0e90d..b0f382f0 100644 --- a/evm/src/recursive_verifier.rs +++ b/evm/src/recursive_verifier.rs @@ -28,7 +28,10 @@ use plonky2_util::log2_ceil; use crate::all_stark::{Table, NUM_TABLES}; use crate::config::StarkConfig; use crate::constraint_consumer::RecursiveConstraintConsumer; +use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cross_table_lookup::{verify_cross_table_lookups, CrossTableLookup, CtlCheckVarsTarget}; +use crate::memory::segments::Segment; +use crate::memory::VALUE_LIMBS; use crate::permutation::{ get_grand_product_challenge_set, GrandProductChallenge, GrandProductChallengeSet, PermutationCheckDataTarget, @@ -494,6 +497,137 @@ fn verify_stark_proof_with_challenges_circuit< ); } +/// Recursive version of `get_memory_extra_looking_products`. +pub(crate) fn get_memory_extra_looking_products_circuit< + F: RichField + Extendable, + const D: usize, +>( + builder: &mut CircuitBuilder, + public_values: &PublicValuesTarget, + challenge: GrandProductChallenge, +) -> Target { + let mut product = builder.one(); + + // Add metadata writes. + let block_fields_without_beneficiary_and_basefee = [ + ( + GlobalMetadata::BlockTimestamp as usize, + public_values.block_metadata.block_timestamp, + ), + ( + GlobalMetadata::BlockNumber as usize, + public_values.block_metadata.block_number, + ), + ( + GlobalMetadata::BlockDifficulty as usize, + public_values.block_metadata.block_difficulty, + ), + ( + GlobalMetadata::BlockGasLimit as usize, + public_values.block_metadata.block_gaslimit, + ), + ( + GlobalMetadata::BlockChainId as usize, + public_values.block_metadata.block_chain_id, + ), + ]; + + product = add_metadata_write( + builder, + challenge, + product, + GlobalMetadata::BlockBeneficiary as usize, + &public_values.block_metadata.block_beneficiary, + ); + + block_fields_without_beneficiary_and_basefee.map(|(field, target)| { + // Each of those fields fit in 32 bits, hence in a single Target. + product = add_metadata_write(builder, challenge, product, field, &[target]); + }); + + product = add_metadata_write( + builder, + challenge, + product, + GlobalMetadata::BlockBaseFee as usize, + &public_values.block_metadata.block_base_fee, + ); + + // Add trie roots writes. + let trie_fields = [ + ( + GlobalMetadata::StateTrieRootDigestBefore as usize, + public_values.trie_roots_before.state_root, + ), + ( + GlobalMetadata::TransactionTrieRootDigestBefore as usize, + public_values.trie_roots_before.transactions_root, + ), + ( + GlobalMetadata::ReceiptTrieRootDigestBefore as usize, + public_values.trie_roots_before.receipts_root, + ), + ( + GlobalMetadata::StateTrieRootDigestAfter as usize, + public_values.trie_roots_after.state_root, + ), + ( + GlobalMetadata::TransactionTrieRootDigestAfter as usize, + public_values.trie_roots_after.transactions_root, + ), + ( + GlobalMetadata::ReceiptTrieRootDigestAfter as usize, + public_values.trie_roots_after.receipts_root, + ), + ]; + + trie_fields.map(|(field, targets)| { + product = add_metadata_write(builder, challenge, product, field, &targets); + }); + + product +} + +fn add_metadata_write, const D: usize>( + builder: &mut CircuitBuilder, + challenge: GrandProductChallenge, + running_product: Target, + metadata_idx: usize, + metadata: &[Target], +) -> Target { + debug_assert!(metadata.len() <= VALUE_LIMBS); + let len = core::cmp::min(metadata.len(), VALUE_LIMBS); + + let zero = builder.zero(); + let one = builder.one(); + let segment = builder.constant(F::from_canonical_u32(Segment::GlobalMetadata as u32)); + + let row = builder.add_virtual_targets(13); + // is_read + builder.connect(row[0], zero); + // context + builder.connect(row[1], zero); + // segment + builder.connect(row[2], segment); + // virtual + let field_target = builder.constant(F::from_canonical_usize(metadata_idx)); + builder.connect(row[3], field_target); + + // values + for j in 0..len { + builder.connect(row[4 + j], metadata[j]); + } + for j in len..VALUE_LIMBS { + builder.connect(row[4 + j], zero); + } + + // timestamp + builder.connect(row[12], one); + + let combined = challenge.combine_base_circuit(builder, &row); + builder.mul(running_product, combined) +} + fn eval_l_0_and_l_last_circuit, const D: usize>( builder: &mut CircuitBuilder, log_n: usize,