diff --git a/crates/l2/prover/src/guest_program/src/execution.rs b/crates/l2/prover/src/guest_program/src/execution.rs index 8d9a453b52f..3b59cc1a99e 100644 --- a/crates/l2/prover/src/guest_program/src/execution.rs +++ b/crates/l2/prover/src/guest_program/src/execution.rs @@ -1,13 +1,10 @@ use crate::input::ProgramInput; use crate::output::ProgramOutput; -use crate::report_cycles; use ethrex_blockchain::error::ChainError; -use ethrex_blockchain::{ - validate_block, validate_gas_used, validate_receipts_root, validate_requests_hash, - validate_state_root, -}; use ethrex_common::types::AccountUpdate; +#[cfg(not(feature = "l2"))] +use ethrex_common::types::ELASTICITY_MULTIPLIER; use ethrex_common::types::block_execution_witness::ExecutionWitness; use ethrex_common::types::fee_config::FeeConfig; use ethrex_common::types::{ @@ -19,7 +16,7 @@ use ethrex_common::{H256, types::Block}; use ethrex_l2_common::l1_messages::L1Message; use ethrex_rlp::encode::RLPEncode; use ethrex_vm::{Evm, EvmError, GuestProgramStateWrapper, VmDatabase}; -use std::collections::{BTreeMap, HashMap}; +use std::collections::HashMap; #[cfg(feature = "l2")] use ethrex_common::types::{ @@ -91,42 +88,52 @@ pub enum StatelessExecutionError { TryIntoError(#[from] std::num::TryFromIntError), } +#[cfg(feature = "l2")] pub fn execution_program(input: ProgramInput) -> Result { let ProgramInput { blocks, execution_witness, elasticity_multiplier, - fee_configs: _fee_configs, - #[cfg(feature = "l2")] + fee_configs, blob_commitment, - #[cfg(feature = "l2")] blob_proof, } = input; let chain_id = execution_witness.chain_config.chain_id; - if cfg!(feature = "l2") { - #[cfg(feature = "l2")] - return stateless_validation_l2( - &blocks, - execution_witness, - elasticity_multiplier, - _fee_configs, - blob_commitment, - blob_proof, - chain_id, - ); - } + stateless_validation_l2( + &blocks, + execution_witness, + elasticity_multiplier, + fee_configs, + blob_commitment, + blob_proof, + chain_id, + ) +} + +#[cfg(not(feature = "l2"))] +pub fn execution_program(input: ProgramInput) -> Result { + let ProgramInput { + block, + execution_witness, + } = input; - stateless_validation_l1(blocks, execution_witness, elasticity_multiplier, chain_id) + let chain_id = execution_witness.chain_config.chain_id; + + stateless_validation_l1(&[block], execution_witness, chain_id) } +#[cfg(not(feature = "l2"))] pub fn stateless_validation_l1( blocks: Vec, execution_witness: ExecutionWitness, - elasticity_multiplier: u64, chain_id: u64, ) -> Result { + use std::collections::BTreeMap; + + use crate::report_cycles; + let guest_program_state: GuestProgramState = report_cycles("guest_program_state_initialization", || { execution_witness @@ -186,7 +193,7 @@ pub fn stateless_validation_l1( for block in blocks.iter() { // Validate the block report_cycles("validate_block", || { - validate_block( + ethrex_blockchain::validate_block( block, parent_block_header, &chain_config, @@ -227,19 +234,23 @@ pub fn stateless_validation_l1( } report_cycles("validate_gas_and_receipts", || { - validate_gas_used(&result.receipts, &block.header) + ethrex_blockchain::validate_gas_used(&result.receipts, &block.header) .map_err(StatelessExecutionError::GasValidationError) })?; report_cycles("validate_receipts_root", || { - validate_receipts_root(&block.header, &result.receipts) + ethrex_blockchain::validate_receipts_root(&block.header, &result.receipts) .map_err(StatelessExecutionError::ReceiptsRootValidationError) })?; // validate_requests_hash doesn't do anything for l2 blocks as this verifies l1 requests (messages, privileged transactions and consolidations) report_cycles("validate_requests_hash", || { - validate_requests_hash(&block.header, &chain_config, &result.requests) - .map_err(StatelessExecutionError::RequestsRootValidationError) + ethrex_blockchain::validate_requests_hash( + &block.header, + &chain_config, + &result.requests, + ) + .map_err(StatelessExecutionError::RequestsRootValidationError) })?; non_privileged_count += block.body.transactions.len(); @@ -258,7 +269,7 @@ pub fn stateless_validation_l1( .ok_or(StatelessExecutionError::EmptyBatchError)?; report_cycles("validate_state_root", || { - validate_state_root(&last_block.header, final_state_root) + ethrex_blockchain::validate_state_root(&last_block.header, final_state_root) .map_err(|_chain_err| StatelessExecutionError::InvalidFinalStateTrie) })?; @@ -282,7 +293,7 @@ pub fn stateless_validation_l2( blocks: &[Block], execution_witness: ExecutionWitness, elasticity_multiplier: u64, - fee_configs: Option>, + fee_configs: Vec, blob_commitment: Commitment, blob_proof: Proof, chain_id: u64, @@ -314,7 +325,9 @@ pub fn stateless_validation_l2( // Check blobs are valid let blob_versioned_hash = if !validium { - let fee_configs = fee_configs.ok_or_else(|| StatelessExecutionError::FeeConfigNotFound)?; + if fee_configs.is_empty() { + return Err(StatelessExecutionError::FeeConfigNotFound); + } verify_blob(blocks, &fee_configs, blob_commitment, blob_proof)? } else { H256::zero() @@ -344,14 +357,16 @@ fn execute_stateless( blocks: &[Block], execution_witness: ExecutionWitness, elasticity_multiplier: u64, - fee_configs: Option>, + fee_configs: Vec, ) -> Result { let guest_program_state: GuestProgramState = execution_witness .try_into() .map_err(StatelessExecutionError::GuestProgramState)?; #[cfg(feature = "l2")] - let fee_configs = fee_configs.ok_or_else(|| StatelessExecutionError::FeeConfigNotFound)?; + if fee_configs.is_empty() { + return Err(StatelessExecutionError::FeeConfigNotFound); + } let mut wrapped_db = GuestProgramStateWrapper::new(guest_program_state); let chain_config = wrapped_db.get_chain_config().map_err(|_| { @@ -394,7 +409,7 @@ fn execute_stateless( for (i, block) in blocks.iter().enumerate() { // Validate the block - validate_block( + ethrex_blockchain::validate_block( block, parent_block_header, &chain_config, @@ -439,12 +454,12 @@ fn execute_stateless( non_privileged_count += block.body.transactions.len() - get_block_privileged_transactions(&block.body.transactions).len(); - validate_gas_used(&receipts, &block.header) + ethrex_blockchain::validate_gas_used(&receipts, &block.header) .map_err(StatelessExecutionError::GasValidationError)?; - validate_receipts_root(&block.header, &receipts) + ethrex_blockchain::validate_receipts_root(&block.header, &receipts) .map_err(StatelessExecutionError::ReceiptsRootValidationError)?; // validate_requests_hash doesn't do anything for l2 blocks as this verifies l1 requests (messages, privileged transactions and consolidations) - validate_requests_hash(&block.header, &chain_config, &result.requests) + ethrex_blockchain::validate_requests_hash(&block.header, &chain_config, &result.requests) .map_err(StatelessExecutionError::RequestsRootValidationError)?; acc_receipts.push(receipts); diff --git a/crates/l2/prover/src/guest_program/src/input.rs b/crates/l2/prover/src/guest_program/src/input.rs index 6a352cc68c5..2323c2880fc 100644 --- a/crates/l2/prover/src/guest_program/src/input.rs +++ b/crates/l2/prover/src/guest_program/src/input.rs @@ -1,16 +1,25 @@ -use ethrex_common::types::{ - Block, block_execution_witness::ExecutionWitness, fee_config::FeeConfig, -}; -use rkyv::{Archive, Deserialize as RDeserialize, Serialize as RSerialize}; -use serde::{Deserialize, Serialize}; +use ethrex_common::types::{Block, block_execution_witness::ExecutionWitness}; use serde_with::serde_as; -#[cfg(feature = "l2")] -use ethrex_common::types::blobs_bundle; +/// Private input variables passed into the zkVM execution program. +#[cfg(not(feature = "l2"))] +#[serde_as] +#[derive( + serde::Serialize, serde::Deserialize, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, Default, +)] +pub struct ProgramInput { + /// Block to execute + pub block: Block, + /// database containing all the data necessary to execute + pub execution_witness: ExecutionWitness, +} /// Private input variables passed into the zkVM execution program. +#[cfg(feature = "l2")] #[serde_as] -#[derive(Serialize, Deserialize, RDeserialize, RSerialize, Archive)] +#[derive( + serde::Serialize, serde::Deserialize, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, +)] pub struct ProgramInput { /// blocks to execute pub blocks: Vec, @@ -19,28 +28,25 @@ pub struct ProgramInput { /// value used to calculate base fee pub elasticity_multiplier: u64, /// Configuration for L2 fees used for each block - pub fee_configs: Option>, - #[cfg(feature = "l2")] + pub fee_configs: Vec, /// KZG commitment to the blob data #[serde_as(as = "[_; 48]")] - pub blob_commitment: blobs_bundle::Commitment, - #[cfg(feature = "l2")] + pub blob_commitment: ethrex_common::types::blobs_bundle::Commitment, /// KZG opening for a challenge over the blob commitment #[serde_as(as = "[_; 48]")] - pub blob_proof: blobs_bundle::Proof, + pub blob_proof: ethrex_common::types::blobs_bundle::Proof, } +#[cfg(feature = "l2")] impl Default for ProgramInput { fn default() -> Self { Self { - blocks: Default::default(), + blocks: Vec::default(), execution_witness: ExecutionWitness::default(), - elasticity_multiplier: Default::default(), - fee_configs: None, - #[cfg(feature = "l2")] + elasticity_multiplier: u64::default(), + fee_configs: Vec::default(), blob_commitment: [0; 48], - #[cfg(feature = "l2")] - blob_proof: [0u8; 48], + blob_proof: [0; 48], } } } diff --git a/crates/l2/prover/src/guest_program/src/output.rs b/crates/l2/prover/src/guest_program/src/output.rs index 611314eb9a6..7896ead577a 100644 --- a/crates/l2/prover/src/guest_program/src/output.rs +++ b/crates/l2/prover/src/guest_program/src/output.rs @@ -3,19 +3,17 @@ use serde::{Deserialize, Serialize}; /// Public output variables exposed by the zkVM execution program. Some of these are part of /// the program input. +#[cfg(feature = "l2")] #[derive(Serialize, Deserialize)] pub struct ProgramOutput { /// initial state trie root hash pub initial_state_hash: H256, /// final state trie root hash pub final_state_hash: H256, - #[cfg(feature = "l2")] /// merkle root of all messages in a batch pub l1messages_merkle_root: H256, - #[cfg(feature = "l2")] /// hash of all the privileged transactions made in a batch pub privileged_transactions_hash: H256, - #[cfg(feature = "l2")] /// blob commitment versioned hash pub blob_versioned_hash: H256, /// hash of the last block in a batch @@ -26,16 +24,14 @@ pub struct ProgramOutput { pub non_privileged_count: U256, } +#[cfg(feature = "l2")] impl ProgramOutput { pub fn encode(&self) -> Vec { [ self.initial_state_hash.to_fixed_bytes(), self.final_state_hash.to_fixed_bytes(), - #[cfg(feature = "l2")] self.l1messages_merkle_root.to_fixed_bytes(), - #[cfg(feature = "l2")] self.privileged_transactions_hash.to_fixed_bytes(), - #[cfg(feature = "l2")] self.blob_versioned_hash.to_fixed_bytes(), self.last_block_hash.to_fixed_bytes(), self.chain_id.to_big_endian(), @@ -44,3 +40,34 @@ impl ProgramOutput { .concat() } } + +/// Public output variables exposed by the zkVM execution program. Some of these are part of +/// the program input. +#[cfg(not(feature = "l2"))] +#[derive(Serialize, Deserialize)] +pub struct ProgramOutput { + /// initial state trie root hash + pub initial_state_hash: H256, + /// final state trie root hash + pub final_state_hash: H256, + /// hash of the last block in a batch + pub last_block_hash: H256, + /// chain_id of the network + pub chain_id: U256, + /// amount of non-privileged transactions + pub non_privileged_count: U256, +} + +#[cfg(not(feature = "l2"))] +impl ProgramOutput { + pub fn encode(&self) -> Vec { + [ + self.initial_state_hash.to_fixed_bytes(), + self.final_state_hash.to_fixed_bytes(), + self.last_block_hash.to_fixed_bytes(), + self.chain_id.to_big_endian(), + self.non_privileged_count.to_big_endian(), + ] + .concat() + } +} diff --git a/crates/l2/prover/src/prover.rs b/crates/l2/prover/src/prover.rs index 0ed3366c719..5c30ca09fa5 100644 --- a/crates/l2/prover/src/prover.rs +++ b/crates/l2/prover/src/prover.rs @@ -123,14 +123,23 @@ impl Prover { Ok(Some(ProverData { batch_number, input: ProgramInput { + #[cfg(not(feature = "l2"))] + block: input + .blocks + .first() + .cloned() + .ok_or("Input blocks is empty")?, + #[cfg(feature = "l2")] blocks: input.blocks, execution_witness: input.execution_witness, + #[cfg(feature = "l2")] elasticity_multiplier: input.elasticity_multiplier, #[cfg(feature = "l2")] blob_commitment: input.blob_commitment, #[cfg(feature = "l2")] blob_proof: input.blob_proof, - fee_configs: Some(input.fee_configs), + #[cfg(feature = "l2")] + fee_configs: input.fee_configs, }, format, })) diff --git a/crates/l2/tee/quote-gen/src/sender.rs b/crates/l2/tee/quote-gen/src/sender.rs index 393f8b02a23..2326992c020 100644 --- a/crates/l2/tee/quote-gen/src/sender.rs +++ b/crates/l2/tee/quote-gen/src/sender.rs @@ -34,7 +34,7 @@ pub async fn get_batch(commit_hash: String) -> Result<(u64, ProgramInput), Strin blob_commitment: input.blob_commitment, #[cfg(feature = "l2")] blob_proof: input.blob_proof, - fee_configs: Some(input.fee_configs), + fee_configs: input.fee_configs, }, )), _ => Err("No blocks to prove.".to_owned()),