feat: integrate blobs into the payload builder (#4305)

This commit is contained in:
Dan Cline
2023-08-29 11:33:51 -07:00
committed by GitHub
parent 505be45559
commit 82fb0eedb3
8 changed files with 142 additions and 21 deletions

View File

@ -22,7 +22,9 @@ use reth_payload_builder::{
};
use reth_primitives::{
bytes::{Bytes, BytesMut},
calculate_excess_blob_gas,
constants::{
eip4844::{DATA_GAS_PER_BLOB, MAX_DATA_GAS_PER_BLOCK},
BEACON_NONCE, EMPTY_RECEIPTS, EMPTY_TRANSACTIONS, EMPTY_WITHDRAWALS,
ETHEREUM_BLOCK_GAS_LIMIT, RETH_CLIENT_VERSION, SLOT_DURATION,
},
@ -651,6 +653,7 @@ where
let mut post_state = PostState::default();
let mut cumulative_gas_used = 0;
let mut sum_blob_gas_used = 0;
let block_gas_limit: u64 = initialized_block_env.gas_limit.try_into().unwrap_or(u64::MAX);
let base_fee = initialized_block_env.basefee.to::<u64>();
@ -679,6 +682,20 @@ where
// convert tx to a signed transaction
let tx = pool_tx.to_recovered_transaction();
if let Some(blob_tx) = tx.transaction.as_eip4844() {
let tx_blob_gas = blob_tx.blob_versioned_hashes.len() as u64 * DATA_GAS_PER_BLOB;
if sum_blob_gas_used + tx_blob_gas > MAX_DATA_GAS_PER_BLOCK {
// we can't fit this _blob_ transaction into the block, so we mark it as invalid,
// which removes its dependent transactions from the iterator. This is similar to
// the gas limit condition for regular transactions above.
best_txs.mark_invalid(&pool_tx);
continue
} else {
// add to the data gas if we're going to execute the transaction
sum_blob_gas_used += tx_blob_gas;
}
}
// Configure the environment for the block.
let env = Env {
cfg: initialized_cfg.clone(),
@ -765,6 +782,34 @@ where
// create the block header
let transactions_root = proofs::calculate_transaction_root(&executed_txs);
// initialize empty blob sidecars at first. If cancun is active then this will
let mut blob_sidecars = Vec::new();
let mut excess_blob_gas = None;
let mut blob_gas_used = None;
// only determine cancun fields when active
if chain_spec.is_cancun_activated_at_timestamp(attributes.timestamp) {
// grab the blob sidecars from the executed txs
let blobs = pool.get_all_blobs(
executed_txs.iter().filter(|tx| tx.is_eip4844()).map(|tx| tx.hash).collect(),
)?;
// map to just the sidecars
blob_sidecars = blobs.into_iter().map(|(_, sidecars)| sidecars).collect();
excess_blob_gas = if chain_spec.is_cancun_activated_at_timestamp(parent_block.timestamp) {
let parent_excess_blob_gas = parent_block.excess_blob_gas.unwrap_or_default();
let parent_blob_gas_used = parent_block.blob_gas_used.unwrap_or_default();
Some(calculate_excess_blob_gas(parent_excess_blob_gas, parent_blob_gas_used))
} else {
// for the first post-fork block, both parent.blob_gas_used and parent.excess_blob_gas
// are evaluated as 0
Some(calculate_excess_blob_gas(0, 0))
};
blob_gas_used = Some(sum_blob_gas_used);
}
let header = Header {
parent_hash: parent_block.hash,
ommers_hash: EMPTY_OMMER_ROOT,
@ -783,19 +828,23 @@ where
difficulty: U256::ZERO,
gas_used: cumulative_gas_used,
extra_data: extra_data.into(),
blob_gas_used: None,
excess_blob_gas: None,
parent_beacon_block_root: None,
blob_gas_used,
excess_blob_gas,
};
// seal the block
let block = Block { header, body: executed_txs, ommers: vec![], withdrawals };
let sealed_block = block.seal_slow();
Ok(BuildOutcome::Better {
payload: BuiltPayload::new(attributes.id, sealed_block, total_fees),
cached_reads,
})
let mut payload = BuiltPayload::new(attributes.id, sealed_block, total_fees);
if !blob_sidecars.is_empty() {
// extend the payload with the blob sidecars from the executed txs
payload.extend_sidecars(blob_sidecars);
}
Ok(BuildOutcome::Better { payload, cached_reads })
}
/// Builds an empty payload without any transactions.