diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 6039c51505..c4deba99c5 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -200,7 +200,7 @@ impl<'a> Interpreter<'a> { self.generation_state.memory.contexts[0].segments[segment as usize] .content .iter() - .map(|x| x.as_u32() as u8) + .map(|x| x.low_u32() as u8) .collect() } @@ -1045,7 +1045,7 @@ impl<'a> Interpreter<'a> { self.generation_state .memory .mload_general(context, segment, offset + i) - .as_u32() as u8 + .low_u32() as u8 }) .collect(); let value = U256::from_big_endian(&bytes); diff --git a/evm/src/cpu/kernel/tests/blake2_f.rs b/evm/src/cpu/kernel/tests/blake2_f.rs index 1b465bed55..b12c9f32a6 100644 --- a/evm/src/cpu/kernel/tests/blake2_f.rs +++ b/evm/src/cpu/kernel/tests/blake2_f.rs @@ -75,7 +75,7 @@ fn run_blake2_f( Ok(hash .iter() - .map(|&x| x.as_u64()) + .map(|&x| x.low_u64()) .collect::>() .try_into() .unwrap()) diff --git a/evm/src/fixed_recursive_verifier.rs b/evm/src/fixed_recursive_verifier.rs index 5c0f1f8084..0b19c16a02 100644 --- a/evm/src/fixed_recursive_verifier.rs +++ b/evm/src/fixed_recursive_verifier.rs @@ -47,9 +47,8 @@ use crate::proof::{ use crate::prover::prove; use crate::recursive_verifier::{ add_common_recursion_gates, add_virtual_public_values, - get_memory_extra_looking_products_circuit, recursive_stark_circuit, set_block_hashes_target, - set_block_metadata_target, set_extra_public_values_target, set_public_value_targets, - set_trie_roots_target, PlonkWrapperCircuit, PublicInputs, StarkWrapperCircuit, + get_memory_extra_looking_products_circuit, recursive_stark_circuit, set_public_value_targets, + PlonkWrapperCircuit, PublicInputs, StarkWrapperCircuit, }; use crate::stark::Stark; use crate::util::h256_limbs; @@ -905,7 +904,8 @@ where &mut root_inputs, &self.root.public_values, &all_proof.public_values, - ); + ) + .map_err(|_| anyhow::Error::msg("Invalid conversion when setting public_values target."))?; let root_proof = self.root.circuit.prove(root_inputs)?; @@ -939,32 +939,13 @@ where &self.aggregation.circuit.verifier_only, ); - set_block_hashes_target( - &mut agg_inputs, - &self.aggregation.public_values.block_hashes, - &public_values.block_hashes, - ); - set_block_metadata_target( + set_public_value_targets( &mut agg_inputs, - &self.aggregation.public_values.block_metadata, - &public_values.block_metadata, - ); + &self.aggregation.public_values, + &public_values, + ) + .map_err(|_| anyhow::Error::msg("Invalid conversion when setting public values target."))?; - set_trie_roots_target( - &mut agg_inputs, - &self.aggregation.public_values.trie_roots_before, - &public_values.trie_roots_before, - ); - set_trie_roots_target( - &mut agg_inputs, - &self.aggregation.public_values.trie_roots_after, - &public_values.trie_roots_after, - ); - set_extra_public_values_target( - &mut agg_inputs, - &self.aggregation.public_values.extra_block_data, - &public_values.extra_block_data, - ); let aggregation_proof = self.aggregation.circuit.prove(agg_inputs)?; Ok((aggregation_proof, public_values)) } @@ -1022,32 +1003,10 @@ where block_inputs .set_verifier_data_target(&self.block.cyclic_vk, &self.block.circuit.verifier_only); - set_block_hashes_target( - &mut block_inputs, - &self.block.public_values.block_hashes, - &public_values.block_hashes, - ); - set_extra_public_values_target( - &mut block_inputs, - &self.block.public_values.extra_block_data, - &public_values.extra_block_data, - ); - set_block_metadata_target( - &mut block_inputs, - &self.block.public_values.block_metadata, - &public_values.block_metadata, - ); - - set_trie_roots_target( - &mut block_inputs, - &self.block.public_values.trie_roots_before, - &public_values.trie_roots_before, - ); - set_trie_roots_target( - &mut block_inputs, - &self.block.public_values.trie_roots_after, - &public_values.trie_roots_after, - ); + set_public_value_targets(&mut block_inputs, &self.block.public_values, &public_values) + .map_err(|_| { + anyhow::Error::msg("Invalid conversion when setting public values target.") + })?; let block_proof = self.block.circuit.prove(block_inputs)?; Ok((block_proof, public_values)) diff --git a/evm/src/generation/state.rs b/evm/src/generation/state.rs index c0c03e28d3..2b85821fe1 100644 --- a/evm/src/generation/state.rs +++ b/evm/src/generation/state.rs @@ -116,7 +116,7 @@ impl GenerationState { let code = self.memory.contexts[ctx].segments[Segment::Returndata as usize].content [..returndata_size] .iter() - .map(|x| x.as_u32() as u8) + .map(|x| x.low_u32() as u8) .collect::>(); debug_assert_eq!(keccak(&code), codehash); diff --git a/evm/src/generation/trie_extractor.rs b/evm/src/generation/trie_extractor.rs index 8311f692e5..a508a720f7 100644 --- a/evm/src/generation/trie_extractor.rs +++ b/evm/src/generation/trie_extractor.rs @@ -20,7 +20,7 @@ pub(crate) struct AccountTrieRecord { pub(crate) fn read_state_trie_value(slice: &[U256]) -> AccountTrieRecord { AccountTrieRecord { - nonce: slice[0].as_u64(), + nonce: slice[0].low_u64(), balance: slice[1], storage_ptr: slice[2].as_usize(), code_hash: H256::from_uint(&slice[3]), diff --git a/evm/src/get_challenges.rs b/evm/src/get_challenges.rs index 59be8439d8..8cd6fd810f 100644 --- a/evm/src/get_challenges.rs +++ b/evm/src/get_challenges.rs @@ -13,7 +13,8 @@ use crate::permutation::{ get_n_grand_product_challenge_sets_target, }; use crate::proof::*; -use crate::util::{h256_limbs, u256_limbs}; +use crate::util::{h256_limbs, u256_limbs, u256_lowest_limb, u256_lowest_word}; +use crate::witness::errors::ProgramError; fn observe_root, C: GenericConfig, const D: usize>( challenger: &mut Challenger, @@ -56,35 +57,24 @@ fn observe_block_metadata< >( challenger: &mut Challenger, block_metadata: &BlockMetadata, -) { +) -> Result<(), ProgramError> { challenger.observe_elements( &u256_limbs::(U256::from_big_endian(&block_metadata.block_beneficiary.0))[..5], ); - challenger.observe_element(F::from_canonical_u32( - block_metadata.block_timestamp.as_u32(), - )); - challenger.observe_element(F::from_canonical_u32(block_metadata.block_number.as_u32())); - challenger.observe_element(F::from_canonical_u32( - block_metadata.block_difficulty.as_u32(), - )); - challenger.observe_element(F::from_canonical_u32( - block_metadata.block_gaslimit.as_u32(), - )); - challenger.observe_element(F::from_canonical_u32( - block_metadata.block_chain_id.as_u32(), - )); - challenger.observe_element(F::from_canonical_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, - )); - challenger.observe_element(F::from_canonical_u32( - block_metadata.block_gas_used.as_u32(), - )); + challenger.observe_element(u256_lowest_limb(block_metadata.block_timestamp)?); + challenger.observe_element(u256_lowest_limb(block_metadata.block_number)?); + challenger.observe_element(u256_lowest_limb(block_metadata.block_difficulty)?); + challenger.observe_element(u256_lowest_limb(block_metadata.block_gaslimit)?); + challenger.observe_element(u256_lowest_limb(block_metadata.block_chain_id)?); + let basefee = u256_lowest_word(block_metadata.block_base_fee)?; + challenger.observe_element(basefee.0); + challenger.observe_element(basefee.1); + challenger.observe_element(u256_lowest_limb(block_metadata.block_gas_used)?); for i in 0..8 { challenger.observe_elements(&u256_limbs(block_metadata.block_bloom[i])); } + + Ok(()) } fn observe_block_metadata_target< @@ -115,17 +105,19 @@ fn observe_extra_block_data< >( challenger: &mut Challenger, extra_data: &ExtraBlockData, -) { - challenger.observe_element(F::from_canonical_u32(extra_data.txn_number_before.as_u32())); - challenger.observe_element(F::from_canonical_u32(extra_data.txn_number_after.as_u32())); - challenger.observe_element(F::from_canonical_u32(extra_data.gas_used_before.as_u32())); - challenger.observe_element(F::from_canonical_u32(extra_data.gas_used_after.as_u32())); +) -> Result<(), ProgramError> { + challenger.observe_element(u256_lowest_limb(extra_data.txn_number_before)?); + challenger.observe_element(u256_lowest_limb(extra_data.txn_number_after)?); + challenger.observe_element(u256_lowest_limb(extra_data.gas_used_before)?); + challenger.observe_element(u256_lowest_limb(extra_data.gas_used_after)?); for i in 0..8 { challenger.observe_elements(&u256_limbs(extra_data.block_bloom_before[i])); } for i in 0..8 { challenger.observe_elements(&u256_limbs(extra_data.block_bloom_after[i])); } + + Ok(()) } fn observe_extra_block_data_target< @@ -181,12 +173,12 @@ pub(crate) fn observe_public_values< >( challenger: &mut Challenger, public_values: &PublicValues, -) { +) -> Result<(), ProgramError> { observe_trie_roots::(challenger, &public_values.trie_roots_before); observe_trie_roots::(challenger, &public_values.trie_roots_after); - observe_block_metadata::(challenger, &public_values.block_metadata); + observe_block_metadata::(challenger, &public_values.block_metadata)?; observe_block_hashes::(challenger, &public_values.block_hashes); - observe_extra_block_data::(challenger, &public_values.extra_block_data); + observe_extra_block_data::(challenger, &public_values.extra_block_data) } pub(crate) fn observe_public_values_target< @@ -212,14 +204,14 @@ impl, C: GenericConfig, const D: usize> A &self, all_stark: &AllStark, config: &StarkConfig, - ) -> AllProofChallenges { + ) -> Result, ProgramError> { let mut challenger = Challenger::::new(); for proof in &self.stark_proofs { challenger.observe_cap(&proof.proof.trace_cap); } - observe_public_values::(&mut challenger, &self.public_values); + observe_public_values::(&mut challenger, &self.public_values)?; let ctl_challenges = get_grand_product_challenge_set(&mut challenger, config.num_challenges); @@ -227,7 +219,7 @@ impl, C: GenericConfig, const D: usize> A let num_permutation_zs = all_stark.nums_permutation_zs(config); let num_permutation_batch_sizes = all_stark.permutation_batch_sizes(); - AllProofChallenges { + Ok(AllProofChallenges { stark_challenges: core::array::from_fn(|i| { challenger.compact(); self.stark_proofs[i].proof.get_challenges( @@ -238,7 +230,7 @@ impl, C: GenericConfig, const D: usize> A ) }), ctl_challenges, - } + }) } #[allow(unused)] // TODO: should be used soon diff --git a/evm/src/prover.rs b/evm/src/prover.rs index 8f5878232b..425634943e 100644 --- a/evm/src/prover.rs +++ b/evm/src/prover.rs @@ -150,7 +150,8 @@ where challenger.observe_cap(cap); } - observe_public_values::(&mut challenger, &public_values); + observe_public_values::(&mut challenger, &public_values) + .map_err(|_| anyhow::Error::msg("Invalid conversion of public values."))?; let ctl_challenges = get_grand_product_challenge_set(&mut challenger, config.num_challenges); let ctl_data_per_table = timed!( diff --git a/evm/src/recursive_verifier.rs b/evm/src/recursive_verifier.rs index e669f4ab35..531669c03e 100644 --- a/evm/src/recursive_verifier.rs +++ b/evm/src/recursive_verifier.rs @@ -43,9 +43,10 @@ use crate::proof::{ TrieRootsTarget, }; use crate::stark::Stark; -use crate::util::{h256_limbs, u256_limbs}; +use crate::util::{h256_limbs, u256_limbs, u256_lowest_limb, u256_lowest_word}; use crate::vanishing_poly::eval_vanishing_poly_circuit; use crate::vars::StarkEvaluationTargets; +use crate::witness::errors::ProgramError; /// Table-wise recursive proofs of an `AllProof`. pub struct RecursiveAllProof< @@ -905,7 +906,8 @@ pub(crate) fn set_public_value_targets( witness: &mut W, public_values_target: &PublicValuesTarget, public_values: &PublicValues, -) where +) -> Result<(), ProgramError> +where F: RichField + Extendable, W: Witness, { @@ -923,7 +925,7 @@ pub(crate) fn set_public_value_targets( witness, &public_values_target.block_metadata, &public_values.block_metadata, - ); + )?; set_block_hashes_target( witness, &public_values_target.block_hashes, @@ -934,6 +936,8 @@ pub(crate) fn set_public_value_targets( &public_values_target.extra_block_data, &public_values.extra_block_data, ); + + Ok(()) } pub(crate) fn set_trie_roots_target( @@ -994,7 +998,8 @@ pub(crate) fn set_block_metadata_target( witness: &mut W, block_metadata_target: &BlockMetadataTarget, block_metadata: &BlockMetadata, -) where +) -> Result<(), ProgramError> +where F: RichField + Extendable, W: Witness, { @@ -1005,42 +1010,39 @@ pub(crate) fn set_block_metadata_target( witness.set_target_arr(&block_metadata_target.block_beneficiary, &beneficiary_limbs); witness.set_target( block_metadata_target.block_timestamp, - F::from_canonical_u32(block_metadata.block_timestamp.as_u32()), + u256_lowest_limb(block_metadata.block_timestamp)?, ); witness.set_target( block_metadata_target.block_number, - F::from_canonical_u32(block_metadata.block_number.as_u32()), + u256_lowest_limb(block_metadata.block_number)?, ); witness.set_target( block_metadata_target.block_difficulty, - F::from_canonical_u32(block_metadata.block_difficulty.as_u32()), + u256_lowest_limb(block_metadata.block_difficulty)?, ); witness.set_target( block_metadata_target.block_gaslimit, - F::from_canonical_u32(block_metadata.block_gaslimit.as_u32()), + u256_lowest_limb(block_metadata.block_gaslimit)?, ); witness.set_target( block_metadata_target.block_chain_id, - F::from_canonical_u32(block_metadata.block_chain_id.as_u32()), + u256_lowest_limb(block_metadata.block_chain_id)?, ); // Basefee fits in 2 limbs - witness.set_target( - 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), - ); + let basefee = u256_lowest_word(block_metadata.block_base_fee)?; + witness.set_target(block_metadata_target.block_base_fee[0], basefee.0); + witness.set_target(block_metadata_target.block_base_fee[1], basefee.1); witness.set_target( block_metadata_target.block_gas_used, - F::from_canonical_u64(block_metadata.block_gas_used.as_u64()), + u256_lowest_limb(block_metadata.block_gas_used)?, ); let mut block_bloom_limbs = [F::ZERO; 64]; for (i, limbs) in block_bloom_limbs.chunks_exact_mut(8).enumerate() { limbs.copy_from_slice(&u256_limbs(block_metadata.block_bloom[i])); } witness.set_target_arr(&block_metadata_target.block_bloom, &block_bloom_limbs); + + Ok(()) } pub(crate) fn set_block_hashes_target( diff --git a/evm/src/util.rs b/evm/src/util.rs index 5fa085dcf2..9a0cd87fd5 100644 --- a/evm/src/util.rs +++ b/evm/src/util.rs @@ -11,6 +11,8 @@ use plonky2::hash::hash_types::RichField; use plonky2::iop::ext_target::ExtensionTarget; use plonky2::util::transpose; +use crate::witness::errors::ProgramError; + /// Construct an integer from its constituent bits (in little-endian order) pub fn limb_from_bits_le(iter: impl IntoIterator) -> P { // TODO: This is technically wrong, as 1 << i won't be canonical for all fields... @@ -45,6 +47,29 @@ pub fn trace_rows_to_poly_values( .collect() } +/// Returns the lowest LE 32-bit limb of a `U256` as a field element, +/// and errors in case the integer is actually greater. +pub(crate) fn u256_lowest_limb(u256: U256) -> Result { + if TryInto::::try_into(u256).is_err() { + return Err(ProgramError::IntegerTooLarge); + } + + Ok(F::from_canonical_u32(u256.low_u32())) +} + +/// Returns the lowest LE 64-bit word of a `U256` as two field elements +/// each storing a 32-bit limb, and errors in case the integer is actually greater. +pub(crate) fn u256_lowest_word(u256: U256) -> Result<(F, F), ProgramError> { + if TryInto::::try_into(u256).is_err() { + return Err(ProgramError::IntegerTooLarge); + } + + Ok(( + F::from_canonical_u32(u256.low_u64() as u32), + F::from_canonical_u32((u256.low_u64() >> 32) as u32), + )) +} + #[allow(unused)] // TODO: Remove? /// Returns the 32-bit little-endian limbs of a `U256`. pub(crate) fn u256_limbs(u256: U256) -> [F; 8] { diff --git a/evm/src/verifier.rs b/evm/src/verifier.rs index 1aa9db9782..297d9276a6 100644 --- a/evm/src/verifier.rs +++ b/evm/src/verifier.rs @@ -50,7 +50,9 @@ where let AllProofChallenges { stark_challenges, ctl_challenges, - } = all_proof.get_challenges(all_stark, config); + } = all_proof + .get_challenges(all_stark, config) + .map_err(|_| anyhow::Error::msg("Invalid sampling of proof challenges."))?; let nums_permutation_zs = all_stark.nums_permutation_zs(config); diff --git a/evm/src/witness/errors.rs b/evm/src/witness/errors.rs index 44693a3363..1ab99eae18 100644 --- a/evm/src/witness/errors.rs +++ b/evm/src/witness/errors.rs @@ -13,6 +13,7 @@ pub enum ProgramError { MemoryError(MemoryError), GasLimitError, InterpreterError, + IntegerTooLarge, } #[allow(clippy::enum_variant_names)] diff --git a/evm/src/witness/mod.rs b/evm/src/witness/mod.rs index 7d491e4e54..fbb88a719c 100644 --- a/evm/src/witness/mod.rs +++ b/evm/src/witness/mod.rs @@ -1,4 +1,4 @@ -mod errors; +pub(crate) mod errors; mod gas; pub(crate) mod memory; mod operation; diff --git a/evm/src/witness/operation.rs b/evm/src/witness/operation.rs index 7d07576d30..b1339d0cee 100644 --- a/evm/src/witness/operation.rs +++ b/evm/src/witness/operation.rs @@ -139,7 +139,7 @@ pub(crate) fn generate_keccak_general( ..base_address }; let val = state.memory.get(address); - val.as_u32() as u8 + val.low_u32() as u8 }) .collect_vec(); log::debug!("Hashing {:?}", input); @@ -377,7 +377,7 @@ pub(crate) fn generate_push( Segment::Code, initial_offset + i, )) - .as_u32() as u8 + .low_u32() as u8 }) .collect_vec(); @@ -710,7 +710,7 @@ pub(crate) fn generate_mload_32bytes( ..base_address }; let val = state.memory.get(address); - val.as_u32() as u8 + val.low_u32() as u8 }) .collect_vec();