Skip to content

Commit

Permalink
refactor(l1): refactor withdrawals and beacon root call (#1871)
Browse files Browse the repository at this point in the history
**Motivation**

<!-- Why does this pull request exist? What are its goals? -->
This pull request includes updates to the `crates/blockchain/payload.rs`
file, grouping the withdrawal for the different evm implementations.
Additionally, there are minor changes in `crates/vm/vm.rs` related to
state transitions.

**Description**

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

* Added a new function `make_beacon_root_call` to handle beacon root
contract calls within the `build_payload` function.
* Removed withdrawal processing code from the `finalize_payload`
function, as it is now handled within the `apply_withdrawals` function.
* Updated the `apply_plain_transaction` function to use
`get_state_transitions_levm` for account updates, ensuring consistency
with the new beacon root call integration.

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

---------

Co-authored-by: Francisco Krause Arnim <56402156+fkrause98@users.noreply.github.com>
Co-authored-by: Federico Borello <156438142+fborello-lambda@users.noreply.github.com>
  • Loading branch information
3 people authored Feb 7, 2025
1 parent 2e66c11 commit aa58d4c
Showing 1 changed file with 56 additions and 40 deletions.
96 changes: 56 additions & 40 deletions crates/blockchain/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ pub fn build_payload(
debug!("Building payload");
let mut evm_state = evm_state(store.clone(), payload.header.parent_hash);
let mut context = PayloadBuildContext::new(payload, &mut evm_state)?;
make_beacon_root_call(&mut context)?;
apply_withdrawals(&mut context)?;
fill_transactions(&mut context)?;
finalize_payload(&mut context)?;
Expand All @@ -260,7 +261,61 @@ pub fn build_payload(
pub fn apply_withdrawals(context: &mut PayloadBuildContext) -> Result<(), EvmError> {
#[cfg(feature = "levm")]
{
// Apply withdrawals & call beacon root contract, and obtain the new state root
if let Some(withdrawals) = &context.payload.body.withdrawals {
// For every withdrawal we increment the target account's balance
for (address, increment) in withdrawals
.iter()
.filter(|withdrawal| withdrawal.amount > 0)
.map(|w| (w.address, u128::from(w.amount) * u128::from(GWEI_TO_WEI)))
{
// We check if it was in block_cache, if not, we get it from DB.
let mut account = context.block_cache.get(&address).cloned().unwrap_or({
let acc_info = context
.store()
.ok_or(StoreError::MissingStore)?
.get_account_info_by_hash(context.parent_hash(), address)?
.unwrap_or_default();
let acc_code = context
.store()
.ok_or(StoreError::MissingStore)?
.get_account_code(acc_info.code_hash)?
.unwrap_or_default();

Account {
info: AccountInfo {
balance: acc_info.balance,
bytecode: acc_code,
nonce: acc_info.nonce,
},
// This is the added_storage for the withdrawal.
// If not involved in the TX, there won't be any updates in the storage
storage: HashMap::new(),
}
});

account.info.balance += increment.into();
context.block_cache.insert(address, account);
}
}
}
#[cfg(not(feature = "levm"))]
{
process_withdrawals(
context.evm_state,
context
.payload
.body
.withdrawals
.as_ref()
.unwrap_or(&Vec::new()),
)?;
}
Ok(())
}

pub fn make_beacon_root_call(context: &mut PayloadBuildContext) -> Result<(), EvmError> {
#[cfg(feature = "levm")]
{
let fork = context
.chain_config()?
.fork(context.payload.header.timestamp);
Expand Down Expand Up @@ -302,8 +357,6 @@ pub fn apply_withdrawals(context: &mut PayloadBuildContext) -> Result<(), EvmErr
if context.payload.header.parent_beacon_block_root.is_some() && spec_id >= SpecId::CANCUN {
beacon_root_contract_call(context.evm_state, &context.payload.header, spec_id)?;
}
let withdrawals = context.payload.body.withdrawals.clone().unwrap_or_default();
process_withdrawals(context.evm_state, &withdrawals)?;
Ok(())
}
}
Expand Down Expand Up @@ -583,43 +636,6 @@ fn apply_plain_transaction(
fn finalize_payload(context: &mut PayloadBuildContext) -> Result<(), StoreError> {
#[cfg(feature = "levm")]
{
if let Some(withdrawals) = &context.payload.body.withdrawals {
// For every withdrawal we increment the target account's balance
for (address, increment) in withdrawals
.iter()
.filter(|withdrawal| withdrawal.amount > 0)
.map(|w| (w.address, u128::from(w.amount) * u128::from(GWEI_TO_WEI)))
{
// We check if it was in block_cache, if not, we get it from DB.
let mut account = context.block_cache.get(&address).cloned().unwrap_or({
let acc_info = context
.store()
.unwrap()
.get_account_info_by_hash(context.parent_hash(), address)?
.unwrap_or_default();
let acc_code = context
.store()
.unwrap()
.get_account_code(acc_info.code_hash)?
.unwrap_or_default();

Account {
info: AccountInfo {
balance: acc_info.balance,
bytecode: acc_code,
nonce: acc_info.nonce,
},
// This is the added_storage for the withdrawal.
// If not involved in the TX, there won't be any updates in the storage
storage: HashMap::new(),
}
});

account.info.balance += increment.into();
context.block_cache.insert(address, account);
}
}

let account_updates = get_state_transitions_levm(
context.evm_state,
context.parent_hash(),
Expand Down

0 comments on commit aa58d4c

Please sign in to comment.