Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions src/engine/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ use crate::{
BerachainBuiltPayload, BerachainPayloadAttributes, BerachainPayloadBuilderAttributes,
},
hardforks::BerachainHardforks,
node::evm::config::{BerachainEvmConfig, BerachainNextBlockEnvAttributes},
node::evm::{
config::{BerachainEvmConfig, BerachainNextBlockEnvAttributes},
error::BerachainExecutionError,
},
primitives::{BerachainHeader, BerachainPrimitives},
transaction::BerachainTxEnvelope,
transaction::{BerachainTxEnvelope, pol::create_pol_transaction},
};
use alloy_consensus::Transaction;
use alloy_eips::eip7002::SYSTEM_ADDRESS;
use alloy_primitives::U256;
use alloy_rlp::Encodable;
use reth::{
Expand Down Expand Up @@ -234,6 +238,26 @@ where
PayloadBuilderError::Internal(err.into())
})?;

// Execute PoL as tx #0 post-Prague1.
if chain_spec.is_prague1_active_at_timestamp(attributes.timestamp()) {
let prev_proposer_pubkey = attributes.prev_proposer_pubkey.ok_or_else(|| {
PayloadBuilderError::Internal(
BlockExecutionError::from(BerachainExecutionError::MissingProposerPubkey).into(),
)
})?;
let pol_envelope = create_pol_transaction(
chain_spec.clone(),
prev_proposer_pubkey,
builder.evm_mut().block().number(),
builder.evm_mut().block().basefee(),
)
.map_err(|err| PayloadBuilderError::Internal(err.into()))?;
builder.execute_transaction(pol_envelope.with_signer(SYSTEM_ADDRESS)).map_err(|err| {
warn!(target: "payload_builder", %err, "failed to execute PoL transaction");
PayloadBuilderError::evm(err)
})?;
}

// initialize empty blob sidecars at first. If cancun is active then this will be populated by
// blob sidecars if any.
let mut blob_sidecars = BlobSidecars::Empty;
Expand Down
10 changes: 8 additions & 2 deletions src/evm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ where
}
TxKind::Call(to) => {
let mut result = self.transact_system_call(tx.caller, to, tx.data)?;
// Set gas_used to 0 for POL transactions
// POL transactions are system calls that always consume zero gas, regardless
// of whether they succeed, revert, or halt.
result.result = match result.result {
ExecutionResult::Success { reason, gas_refunded, logs, output, .. } => {
ExecutionResult::Success {
Expand All @@ -223,7 +224,12 @@ where
output,
}
}
other => other,
ExecutionResult::Revert { output, .. } => {
ExecutionResult::Revert { gas_used: 0, output }
}
ExecutionResult::Halt { reason, .. } => {
ExecutionResult::Halt { reason, gas_used: 0 }
}
};
Ok(result)
}
Expand Down
23 changes: 5 additions & 18 deletions src/node/evm/assembler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
hardforks::BerachainHardforks,
node::evm::{block_context::BerachainBlockExecutionCtx, error::BerachainExecutionError},
primitives::{BerachainBlock, BerachainHeader},
transaction::{BerachainTxEnvelope, BerachainTxType, pol::create_pol_transaction},
transaction::{BerachainTxEnvelope, BerachainTxType},
};
use alloy_consensus::{Block, BlockBody, BlockHeader, EMPTY_OMMER_ROOT_HASH, TxReceipt, proofs};
use alloy_eips::merge::BEACON_NONCE;
Expand Down Expand Up @@ -53,7 +53,7 @@ where
evm_env,
execution_ctx: ctx,
parent,
mut transactions,
transactions,
output: BlockExecutionResult { receipts, requests, gas_used, blob_gas_used },
state_root,
..
Expand All @@ -64,27 +64,14 @@ where
// Validate proposer pubkey presence for Prague1
validate_proposer_pubkey_prague1(&*self.chain_spec, timestamp, ctx.prev_proposer_pubkey)?;

// Check if Prague1 is active and we need to inject POL transaction
// Post-Prague1, PoL is executed as tx #0, so the block must have a PoL
// transaction at index 0 and at least one receipt.
if self.chain_spec.is_prague1_active_at_timestamp(timestamp) {
let prev_proposer_pubkey = ctx.prev_proposer_pubkey.unwrap();

// Synthesize POL transaction and prepend to transactions list
let base_fee = evm_env.block_env.basefee();
let pol_transaction = create_pol_transaction(
self.chain_spec.clone(),
prev_proposer_pubkey,
evm_env.block_env.number(),
base_fee,
)?;

transactions.insert(0, pol_transaction);

// Validate that we have receipts after POL transaction execution
if receipts.is_empty() {
return Err(BerachainExecutionError::MissingPolReceipts.into());
}

// Validate that the first transaction in the list is indeed a POL transaction
// Validate that the first transaction is a PoL transaction
if let Some(first_tx) = transactions.first() {
if !matches!(first_tx, BerachainTxEnvelope::Berachain(_)) {
return Err(BerachainExecutionError::MissingPolTransactionAtIndex0.into());
Expand Down
Loading