builder gas limit & some refactoring (#6583)

* Cache gas_limit

* Payload Parameters Refactor

* Enforce Proposer Gas Limit

* Fixed and Added New Tests

* Fix Beacon Chain Tests
This commit is contained in:
ethDreamer
2024-12-15 21:43:58 -08:00
committed by GitHub
parent 11e1d5bf14
commit 86891e6d0f
14 changed files with 598 additions and 243 deletions

View File

@@ -28,8 +28,8 @@ use super::DEFAULT_TERMINAL_BLOCK;
const TEST_BLOB_BUNDLE: &[u8] = include_bytes!("fixtures/mainnet/test_blobs_bundle.ssz");
const GAS_LIMIT: u64 = 16384;
const GAS_USED: u64 = GAS_LIMIT - 1;
pub const DEFAULT_GAS_LIMIT: u64 = 30_000_000;
const GAS_USED: u64 = DEFAULT_GAS_LIMIT - 1;
#[derive(Clone, Debug, PartialEq)]
#[allow(clippy::large_enum_variant)] // This struct is only for testing.
@@ -38,6 +38,10 @@ pub enum Block<E: EthSpec> {
PoS(ExecutionPayload<E>),
}
pub fn mock_el_extra_data<E: EthSpec>() -> types::VariableList<u8, E::MaxExtraDataBytes> {
"block gen was here".as_bytes().to_vec().into()
}
impl<E: EthSpec> Block<E> {
pub fn block_number(&self) -> u64 {
match self {
@@ -67,6 +71,13 @@ impl<E: EthSpec> Block<E> {
}
}
pub fn gas_limit(&self) -> u64 {
match self {
Block::PoW(_) => DEFAULT_GAS_LIMIT,
Block::PoS(payload) => payload.gas_limit(),
}
}
pub fn as_execution_block(&self, total_difficulty: Uint256) -> ExecutionBlock {
match self {
Block::PoW(block) => ExecutionBlock {
@@ -570,10 +581,10 @@ impl<E: EthSpec> ExecutionBlockGenerator<E> {
logs_bloom: vec![0; 256].into(),
prev_randao: pa.prev_randao,
block_number: parent.block_number() + 1,
gas_limit: GAS_LIMIT,
gas_limit: DEFAULT_GAS_LIMIT,
gas_used: GAS_USED,
timestamp: pa.timestamp,
extra_data: "block gen was here".as_bytes().to_vec().into(),
extra_data: mock_el_extra_data::<E>(),
base_fee_per_gas: Uint256::from(1u64),
block_hash: ExecutionBlockHash::zero(),
transactions: vec![].into(),
@@ -587,10 +598,10 @@ impl<E: EthSpec> ExecutionBlockGenerator<E> {
logs_bloom: vec![0; 256].into(),
prev_randao: pa.prev_randao,
block_number: parent.block_number() + 1,
gas_limit: GAS_LIMIT,
gas_limit: DEFAULT_GAS_LIMIT,
gas_used: GAS_USED,
timestamp: pa.timestamp,
extra_data: "block gen was here".as_bytes().to_vec().into(),
extra_data: mock_el_extra_data::<E>(),
base_fee_per_gas: Uint256::from(1u64),
block_hash: ExecutionBlockHash::zero(),
transactions: vec![].into(),
@@ -603,10 +614,10 @@ impl<E: EthSpec> ExecutionBlockGenerator<E> {
logs_bloom: vec![0; 256].into(),
prev_randao: pa.prev_randao,
block_number: parent.block_number() + 1,
gas_limit: GAS_LIMIT,
gas_limit: DEFAULT_GAS_LIMIT,
gas_used: GAS_USED,
timestamp: pa.timestamp,
extra_data: "block gen was here".as_bytes().to_vec().into(),
extra_data: mock_el_extra_data::<E>(),
base_fee_per_gas: Uint256::from(1u64),
block_hash: ExecutionBlockHash::zero(),
transactions: vec![].into(),
@@ -623,10 +634,10 @@ impl<E: EthSpec> ExecutionBlockGenerator<E> {
logs_bloom: vec![0; 256].into(),
prev_randao: pa.prev_randao,
block_number: parent.block_number() + 1,
gas_limit: GAS_LIMIT,
gas_limit: DEFAULT_GAS_LIMIT,
gas_used: GAS_USED,
timestamp: pa.timestamp,
extra_data: "block gen was here".as_bytes().to_vec().into(),
extra_data: mock_el_extra_data::<E>(),
base_fee_per_gas: Uint256::from(1u64),
block_hash: ExecutionBlockHash::zero(),
transactions: vec![].into(),
@@ -642,10 +653,10 @@ impl<E: EthSpec> ExecutionBlockGenerator<E> {
logs_bloom: vec![0; 256].into(),
prev_randao: pa.prev_randao,
block_number: parent.block_number() + 1,
gas_limit: GAS_LIMIT,
gas_limit: DEFAULT_GAS_LIMIT,
gas_used: GAS_USED,
timestamp: pa.timestamp,
extra_data: "block gen was here".as_bytes().to_vec().into(),
extra_data: mock_el_extra_data::<E>(),
base_fee_per_gas: Uint256::from(1u64),
block_hash: ExecutionBlockHash::zero(),
transactions: vec![].into(),

View File

@@ -1,5 +1,5 @@
use crate::test_utils::{DEFAULT_BUILDER_PAYLOAD_VALUE_WEI, DEFAULT_JWT_SECRET};
use crate::{Config, ExecutionLayer, PayloadAttributes};
use crate::{Config, ExecutionLayer, PayloadAttributes, PayloadParameters};
use eth2::types::{BlobsBundle, BlockId, StateId, ValidatorId};
use eth2::{BeaconNodeHttpClient, Timeouts, CONSENSUS_VERSION_HEADER};
use fork_choice::ForkchoiceUpdateParameters;
@@ -54,6 +54,10 @@ impl Operation {
}
}
pub fn mock_builder_extra_data<E: EthSpec>() -> types::VariableList<u8, E::MaxExtraDataBytes> {
"mock_builder".as_bytes().to_vec().into()
}
#[derive(Debug)]
// We don't use the string value directly, but it's used in the Debug impl which is required by `warp::reject::Reject`.
struct Custom(#[allow(dead_code)] String);
@@ -72,6 +76,8 @@ pub trait BidStuff<E: EthSpec> {
fn set_withdrawals_root(&mut self, withdrawals_root: Hash256);
fn sign_builder_message(&mut self, sk: &SecretKey, spec: &ChainSpec) -> Signature;
fn stamp_payload(&mut self);
}
impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
@@ -203,6 +209,29 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
let message = self.signing_root(domain);
sk.sign(message)
}
// this helps differentiate a builder block from a regular block
fn stamp_payload(&mut self) {
let extra_data = mock_builder_extra_data::<E>();
match self.to_mut().header_mut() {
ExecutionPayloadHeaderRefMut::Bellatrix(header) => {
header.extra_data = extra_data;
header.block_hash = ExecutionBlockHash::from_root(header.tree_hash_root());
}
ExecutionPayloadHeaderRefMut::Capella(header) => {
header.extra_data = extra_data;
header.block_hash = ExecutionBlockHash::from_root(header.tree_hash_root());
}
ExecutionPayloadHeaderRefMut::Deneb(header) => {
header.extra_data = extra_data;
header.block_hash = ExecutionBlockHash::from_root(header.tree_hash_root());
}
ExecutionPayloadHeaderRefMut::Electra(header) => {
header.extra_data = extra_data;
header.block_hash = ExecutionBlockHash::from_root(header.tree_hash_root());
}
}
}
}
#[derive(Clone)]
@@ -286,6 +315,7 @@ impl<E: EthSpec> MockBuilder<E> {
while let Some(op) = guard.pop() {
op.apply(bid);
}
bid.stamp_payload();
}
}
@@ -413,11 +443,12 @@ pub fn serve<E: EthSpec>(
let block = head.data.message();
let head_block_root = block.tree_hash_root();
let head_execution_hash = block
let head_execution_payload = block
.body()
.execution_payload()
.map_err(|_| reject("pre-merge block"))?
.block_hash();
.map_err(|_| reject("pre-merge block"))?;
let head_execution_hash = head_execution_payload.block_hash();
let head_gas_limit = head_execution_payload.gas_limit();
if head_execution_hash != parent_hash {
return Err(reject("head mismatch"));
}
@@ -529,14 +560,24 @@ pub fn serve<E: EthSpec>(
finalized_hash: Some(finalized_execution_hash),
};
let proposer_gas_limit = builder
.val_registration_cache
.read()
.get(&pubkey)
.map(|v| v.message.gas_limit);
let payload_parameters = PayloadParameters {
parent_hash: head_execution_hash,
parent_gas_limit: head_gas_limit,
proposer_gas_limit,
payload_attributes: &payload_attributes,
forkchoice_update_params: &forkchoice_update_params,
current_fork: fork,
};
let payload_response_type = builder
.el
.get_full_payload_caching(
head_execution_hash,
&payload_attributes,
forkchoice_update_params,
fork,
)
.get_full_payload_caching(payload_parameters)
.await
.map_err(|_| reject("couldn't get payload"))?;
@@ -648,8 +689,6 @@ pub fn serve<E: EthSpec>(
}
};
message.set_gas_limit(cached_data.gas_limit);
builder.apply_operations(&mut message);
let mut signature =

View File

@@ -90,6 +90,7 @@ impl<E: EthSpec> MockExecutionLayer<E> {
};
let parent_hash = latest_execution_block.block_hash();
let parent_gas_limit = latest_execution_block.gas_limit();
let block_number = latest_execution_block.block_number() + 1;
let timestamp = block_number;
let prev_randao = Hash256::from_low_u64_be(block_number);
@@ -131,14 +132,20 @@ impl<E: EthSpec> MockExecutionLayer<E> {
let payload_attributes =
PayloadAttributes::new(timestamp, prev_randao, suggested_fee_recipient, None, None);
let payload_parameters = PayloadParameters {
parent_hash,
parent_gas_limit,
proposer_gas_limit: None,
payload_attributes: &payload_attributes,
forkchoice_update_params: &forkchoice_update_params,
current_fork: ForkName::Bellatrix,
};
let block_proposal_content_type = self
.el
.get_payload(
parent_hash,
&payload_attributes,
forkchoice_update_params,
payload_parameters,
builder_params,
ForkName::Bellatrix,
&self.spec,
None,
BlockProductionVersion::FullV2,
@@ -171,14 +178,20 @@ impl<E: EthSpec> MockExecutionLayer<E> {
let payload_attributes =
PayloadAttributes::new(timestamp, prev_randao, suggested_fee_recipient, None, None);
let payload_parameters = PayloadParameters {
parent_hash,
parent_gas_limit,
proposer_gas_limit: None,
payload_attributes: &payload_attributes,
forkchoice_update_params: &forkchoice_update_params,
current_fork: ForkName::Bellatrix,
};
let block_proposal_content_type = self
.el
.get_payload(
parent_hash,
&payload_attributes,
forkchoice_update_params,
payload_parameters,
builder_params,
ForkName::Bellatrix,
&self.spec,
None,
BlockProductionVersion::BlindedV2,

View File

@@ -25,12 +25,13 @@ use types::{EthSpec, ExecutionBlockHash, Uint256};
use warp::{http::StatusCode, Filter, Rejection};
use crate::EngineCapabilities;
pub use execution_block_generator::DEFAULT_GAS_LIMIT;
pub use execution_block_generator::{
generate_blobs, generate_genesis_block, generate_genesis_header, generate_pow_block,
static_valid_tx, Block, ExecutionBlockGenerator,
mock_el_extra_data, static_valid_tx, Block, ExecutionBlockGenerator,
};
pub use hook::Hook;
pub use mock_builder::{MockBuilder, Operation};
pub use mock_builder::{mock_builder_extra_data, MockBuilder, Operation};
pub use mock_execution_layer::MockExecutionLayer;
pub const DEFAULT_TERMINAL_DIFFICULTY: u64 = 6400;