Skip to content

Commit

Permalink
refactor(core): combine execute_block impls (blockchain module) (#1575
Browse files Browse the repository at this point in the history
)

**Motivation**
Both impls have the exact same code differing only by a couple lines.
Having two feature-gated copies only makes the code harder to follow and
refactor.
<!-- Why does this pull request exist? What are its goals? -->

**Description**
* Replaces the two feature-gated `execute_block` functions in the
blockchain module with a single non-gated `execute_block` function, and
only feature-gates the lines of code that differ between the two
features

<!-- A clear and concise general description of the changes this PR
introduces -->

<!-- Link to issues: Resolves #111, Resolves #222 -->

Closes #issue_number
  • Loading branch information
fmoletta authored Dec 30, 2024
1 parent 3398ac8 commit f204cd9
Showing 1 changed file with 13 additions and 53 deletions.
66 changes: 13 additions & 53 deletions crates/blockchain/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use ethrex_core::types::{
use ethrex_core::H256;

use ethrex_storage::error::StoreError;
use ethrex_storage::Store;
use ethrex_storage::{AccountUpdate, Store};
use ethrex_vm::{evm_state, execute_block, spec_id, EvmState, SpecId};

//TODO: Implement a struct Chain or BlockChain to encapsulate
Expand All @@ -26,10 +26,7 @@ use ethrex_vm::{evm_state, execute_block, spec_id, EvmState, SpecId};
/// canonical chain/head. Fork choice needs to be updated for that in a separate step.
///
/// Performs pre and post execution validation, and updates the database with the post state.
#[cfg(not(feature = "levm"))]
pub fn add_block(block: &Block, storage: &Store) -> Result<(), ChainError> {
use ethrex_vm::get_state_transitions;

let block_hash = block.header.compute_block_hash();

// Validate if it can be the new head and find the parent
Expand All @@ -42,56 +39,19 @@ pub fn add_block(block: &Block, storage: &Store) -> Result<(), ChainError> {

// Validate the block pre-execution
validate_block(block, &parent_header, &state)?;

let receipts = execute_block(block, &mut state)?;

validate_gas_used(&receipts, &block.header)?;

let account_updates = get_state_transitions(&mut state);

// Apply the account updates over the last block's state and compute the new state root
let new_state_root = state
.database()
.ok_or(ChainError::StoreError(StoreError::MissingStore))?
.apply_account_updates(block.header.parent_hash, &account_updates)?
.ok_or(ChainError::ParentStateNotFound)?;

// Check state root matches the one in block header after execution
validate_state_root(&block.header, new_state_root)?;

// Check receipts root matches the one in block header after execution
validate_receipts_root(&block.header, &receipts)?;

store_block(storage, block.clone())?;
store_receipts(storage, receipts, block_hash)?;

Ok(())
}

/// Adds a new block to the store. It may or may not be canonical, as long as its ancestry links
/// with the canonical chain and its parent's post-state is calculated. It doesn't modify the
/// canonical chain/head. Fork choice needs to be updated for that in a separate step.
///
/// Performs pre and post execution validation, and updates the database with the post state.
#[cfg(feature = "levm")]
pub fn add_block(block: &Block, storage: &Store) -> Result<(), ChainError> {
let block_hash = block.header.compute_block_hash();

// Validate if it can be the new head and find the parent
let Ok(parent_header) = find_parent_header(&block.header, storage) else {
// If the parent is not present, we store it as pending.
storage.add_pending_block(block.clone())?;
return Err(ChainError::ParentNotFound);
let (receipts, account_updates): (Vec<Receipt>, Vec<AccountUpdate>) = {
// TODO: Consider refactoring both implementations so that they have the same signature
#[cfg(feature = "levm")]
{
execute_block(block, &mut state)?
}
#[cfg(not(feature = "levm"))]
{
let receipts = execute_block(block, &mut state)?;
let account_updates = ethrex_vm::get_state_transitions(&mut state);
(receipts, account_updates)
}
};
let mut state = evm_state(storage.clone(), block.header.parent_hash);

// Validate the block pre-execution
validate_block(block, &parent_header, &state)?;

let (receipts, account_updates) = execute_block(block, &mut state)?;

// Note: these is commented because it is still being used in development.
// dbg!(&account_updates);

validate_gas_used(&receipts, &block.header)?;

Expand Down

0 comments on commit f204cd9

Please sign in to comment.