Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 6 additions & 4 deletions crates/ethereum/cli/src/debug_cmd/build_block.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! Command for debugging block building.
use alloy_consensus::BlockHeader;
use alloy_eips::{
eip2718::Encodable2718,
eip4844::{env_settings::EnvKzgSettings, BlobTransactionSidecar},
eip2718::Encodable2718, eip4844::env_settings::EnvKzgSettings,
eip7594::BlobTransactionSidecarVariant,
};
use alloy_primitives::{Address, Bytes, B256};
use alloy_rlp::Decodable;
Expand Down Expand Up @@ -152,8 +152,10 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
eyre::eyre!("encountered a blob tx. `--blobs-bundle-path` must be provided")
})?;

let sidecar: BlobTransactionSidecar =
blobs_bundle.pop_sidecar(tx.tx().blob_versioned_hashes.len());
let sidecar: BlobTransactionSidecarVariant =
BlobTransactionSidecarVariant::Eip4844(
blobs_bundle.pop_sidecar(tx.tx().blob_versioned_hashes.len()),
);

let pooled = transaction
.clone()
Expand Down
43 changes: 42 additions & 1 deletion crates/ethereum/engine-primitives/src/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

use alloc::{sync::Arc, vec::Vec};
use alloy_eips::{
eip4844::BlobTransactionSidecar, eip4895::Withdrawals, eip7594::BlobTransactionSidecarEip7594,
eip4844::BlobTransactionSidecar,
eip4895::Withdrawals,
eip7594::{BlobTransactionSidecarEip7594, BlobTransactionSidecarVariant},
eip7685::Requests,
};
use alloy_primitives::{Address, B256, U256};
Expand Down Expand Up @@ -243,6 +245,45 @@ impl BlobSidecars {
pub const fn eip7594(sidecars: Vec<BlobTransactionSidecarEip7594>) -> Self {
Self::Eip7594(sidecars)
}

/// Push EIP-4844 blob sidecar. Ignores the item if sidecars already contain EIP-7594 sidecars.
pub fn push_eip4844_sidecar(&mut self, sidecar: BlobTransactionSidecar) {
match self {
Self::Empty => {
*self = Self::Eip4844(Vec::from([sidecar]));
}
Self::Eip4844(sidecars) => {
sidecars.push(sidecar);
}
Self::Eip7594(_) => {}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense

}
}

/// Push EIP-7594 blob sidecar. Ignores the item if sidecars already contain EIP-4844 sidecars.
pub fn push_eip7594_sidecar(&mut self, sidecar: BlobTransactionSidecarEip7594) {
match self {
Self::Empty => {
*self = Self::Eip7594(Vec::from([sidecar]));
}
Self::Eip7594(sidecars) => {
sidecars.push(sidecar);
}
Self::Eip4844(_) => {}
}
}

/// Push a [`BlobTransactionSidecarVariant`]. Ignores the item if sidecars already contain the
/// opposite type.
pub fn push_sidecar_variant(&mut self, sidecar: BlobTransactionSidecarVariant) {
match sidecar {
BlobTransactionSidecarVariant::Eip4844(sidecar) => {
self.push_eip4844_sidecar(sidecar);
}
BlobTransactionSidecarVariant::Eip7594(sidecar) => {
self.push_eip7594_sidecar(sidecar);
}
}
}
}

impl From<Vec<BlobTransactionSidecar>> for BlobSidecars {
Expand Down
7 changes: 5 additions & 2 deletions crates/ethereum/node/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use reth_ethereum_consensus::EthBeaconConsensus;
use reth_ethereum_engine_primitives::{
EthBuiltPayload, EthPayloadAttributes, EthPayloadBuilderAttributes,
};
use reth_ethereum_primitives::{EthPrimitives, PooledTransaction, TransactionSigned};
use reth_ethereum_primitives::{EthPrimitives, PooledTransactionVariant, TransactionSigned};
use reth_evm::{ConfigureEvm, EvmFactory, EvmFactoryFor, NextBlockEnvAttributes};
use reth_network::{EthNetworkPrimitives, NetworkHandle, PeersInfo};
use reth_node_api::{AddOnsContext, FullNodeComponents, NodeAddOns, NodePrimitives, TxTy};
Expand Down Expand Up @@ -431,7 +431,10 @@ impl<Node, Pool> NetworkBuilder<Node, Pool> for EthereumNetworkBuilder
where
Node: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec, Primitives = EthPrimitives>>,
Pool: TransactionPool<
Transaction: PoolTransaction<Consensus = TxTy<Node::Types>, Pooled = PooledTransaction>,
Transaction: PoolTransaction<
Consensus = TxTy<Node::Types>,
Pooled = PooledTransactionVariant,
>,
> + Unpin
+ 'static,
{
Expand Down
63 changes: 42 additions & 21 deletions crates/ethereum/payload/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#![allow(clippy::useless_let_if_seq)]

use alloy_consensus::{Transaction, Typed2718};
use alloy_consensus::Transaction;
use alloy_primitives::U256;
use reth_basic_payload_builder::{
is_better_payload, BuildArguments, BuildOutcome, MissingPayloadBehaviour, PayloadBuilder,
Expand All @@ -23,7 +23,7 @@ use reth_evm::{
ConfigureEvm, Evm, NextBlockEnvAttributes,
};
use reth_evm_ethereum::EthEvmConfig;
use reth_payload_builder::{EthBuiltPayload, EthPayloadBuilderAttributes};
use reth_payload_builder::{BlobSidecars, EthBuiltPayload, EthPayloadBuilderAttributes};
use reth_payload_builder_primitives::PayloadBuilderError;
use reth_payload_primitives::PayloadBuilderAttributes;
use reth_primitives_traits::transaction::error::InvalidTransactionError;
Expand Down Expand Up @@ -188,7 +188,12 @@ where
PayloadBuilderError::Internal(err.into())
})?;

// 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;

let mut block_blob_count = 0;

let blob_params = chain_spec.blob_params_at_timestamp(attributes.timestamp);
let max_blob_count =
blob_params.as_ref().map(|params| params.max_blob_count).unwrap_or_default();
Expand Down Expand Up @@ -216,6 +221,7 @@ where

// There's only limited amount of blob space available per block, so we need to check if
// the EIP-4844 can still fit in the block
let mut blob_tx_sidecar = None;
if let Some(blob_tx) = tx.as_eip4844() {
let tx_blob_count = blob_tx.tx().blob_versioned_hashes.len() as u64;

Expand All @@ -236,6 +242,34 @@ where
);
continue
}

let blob_sidecar_result = 'sidecar: {
let Some(sidecar) =
pool.get_blob(*tx.hash()).map_err(PayloadBuilderError::other)?
else {
break 'sidecar Err(Eip4844PoolTransactionError::MissingEip4844BlobSidecar)
};

if chain_spec.is_osaka_active_at_timestamp(attributes.timestamp) {
if sidecar.is_eip7594() {
Ok(sidecar)
} else {
Err(Eip4844PoolTransactionError::UnexpectedEip4844SidecarAfterOsaka)
}
} else if sidecar.is_eip4844() {
Ok(sidecar)
} else {
Err(Eip4844PoolTransactionError::UnexpectedEip7594SidecarBeforeOsaka)
}
};

blob_tx_sidecar = match blob_sidecar_result {
Ok(sidecar) => Some(sidecar),
Err(error) => {
best_txs.mark_invalid(&pool_tx, InvalidPoolTransactionError::Eip4844(error));
continue
}
};
}

let gas_used = match builder.execute_transaction(tx.clone()) {
Expand Down Expand Up @@ -278,6 +312,11 @@ where
tx.effective_tip_per_gas(base_fee).expect("fee is always valid; execution succeeded");
total_fees += U256::from(miner_fee) * U256::from(gas_used);
cumulative_gas_used += gas_used;

// Add blob tx sidecar to the payload.
if let Some(sidecar) = blob_tx_sidecar {
blob_sidecars.push_sidecar_variant(sidecar.as_ref().clone());
}
}

// check if we have a better block
Expand All @@ -294,30 +333,12 @@ where
.is_prague_active_at_timestamp(attributes.timestamp)
.then_some(execution_result.requests);

// initialize empty blob sidecars at first. If cancun is active then this will
let mut blob_sidecars = Vec::new();

// only determine cancun fields when active
if chain_spec.is_cancun_active_at_timestamp(attributes.timestamp) {
// grab the blob sidecars from the executed txs
blob_sidecars = pool
.get_all_blobs_exact(
block
.body()
.transactions()
.filter(|tx| tx.is_eip4844())
.map(|tx| *tx.tx_hash())
.collect(),
)
.map_err(PayloadBuilderError::other)?;
}

let sealed_block = Arc::new(block.sealed_block().clone());
debug!(target: "payload_builder", id=%attributes.id, sealed_block_header = ?sealed_block.sealed_header(), "sealed built block");

let payload = EthBuiltPayload::new(attributes.id, sealed_block, total_fees, requests)
// add blob sidecars from the executed txs
.with_sidecars(blob_sidecars.into_iter().map(Arc::unwrap_or_clone).collect::<Vec<_>>());
.with_sidecars(blob_sidecars);

Ok(BuildOutcome::Better { payload, cached_reads })
}
2 changes: 1 addition & 1 deletion crates/net/eth-wire-types/src/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,6 @@ impl NetworkPrimitives for EthNetworkPrimitives {
type BlockBody = reth_ethereum_primitives::BlockBody;
type Block = reth_ethereum_primitives::Block;
type BroadcastedTransaction = reth_ethereum_primitives::TransactionSigned;
type PooledTransaction = reth_ethereum_primitives::PooledTransaction;
type PooledTransaction = reth_ethereum_primitives::PooledTransactionVariant;
type Receipt = reth_ethereum_primitives::Receipt;
}
18 changes: 13 additions & 5 deletions crates/net/network/src/test_utils/testnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@ use crate::{
},
NetworkConfig, NetworkConfigBuilder, NetworkHandle, NetworkManager,
};
use alloy_consensus::transaction::PooledTransaction;
use futures::{FutureExt, StreamExt};
use pin_project::pin_project;
use reth_chainspec::{ChainSpecProvider, EthereumHardforks, Hardforks};
use reth_eth_wire::{
protocol::Protocol, DisconnectReason, EthNetworkPrimitives, HelloMessageWithProtocols,
};
use reth_ethereum_primitives::TransactionSigned;
use reth_ethereum_primitives::{PooledTransactionVariant, TransactionSigned};
use reth_network_api::{
events::{PeerEvent, SessionInfo},
test_utils::{PeersHandle, PeersHandleProvider},
Expand Down Expand Up @@ -246,7 +245,10 @@ where
+ Unpin
+ 'static,
Pool: TransactionPool<
Transaction: PoolTransaction<Consensus = TransactionSigned, Pooled = PooledTransaction>,
Transaction: PoolTransaction<
Consensus = TransactionSigned,
Pooled = PooledTransactionVariant,
>,
> + Unpin
+ 'static,
{
Expand Down Expand Up @@ -314,7 +316,10 @@ where
+ Unpin
+ 'static,
Pool: TransactionPool<
Transaction: PoolTransaction<Consensus = TransactionSigned, Pooled = PooledTransaction>,
Transaction: PoolTransaction<
Consensus = TransactionSigned,
Pooled = PooledTransactionVariant,
>,
> + Unpin
+ 'static,
{
Expand Down Expand Up @@ -562,7 +567,10 @@ where
+ Unpin
+ 'static,
Pool: TransactionPool<
Transaction: PoolTransaction<Consensus = TransactionSigned, Pooled = PooledTransaction>,
Transaction: PoolTransaction<
Consensus = TransactionSigned,
Pooled = PooledTransactionVariant,
>,
> + Unpin
+ 'static,
{
Expand Down
15 changes: 8 additions & 7 deletions crates/net/network/src/transactions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1995,12 +1995,12 @@ mod tests {
},
NetworkConfigBuilder, NetworkManager,
};
use alloy_consensus::{transaction::PooledTransaction, TxEip1559, TxLegacy};
use alloy_consensus::{TxEip1559, TxLegacy};
use alloy_primitives::{hex, Signature, TxKind, U256};
use alloy_rlp::Decodable;
use futures::FutureExt;
use reth_chainspec::MIN_TRANSACTION_GAS;
use reth_ethereum_primitives::{Transaction, TransactionSigned};
use reth_ethereum_primitives::{PooledTransactionVariant, Transaction, TransactionSigned};
use reth_network_api::{NetworkInfo, PeerKind};
use reth_network_p2p::{
error::{RequestError, RequestResult},
Expand Down Expand Up @@ -2236,10 +2236,10 @@ mod tests {
let PeerRequest::GetPooledTransactions { request, response } = req else { unreachable!() };
assert_eq!(request, GetPooledTransactions::from(txs_hashes.clone()));

let message: Vec<PooledTransaction> = txs
let message: Vec<PooledTransactionVariant> = txs
.into_iter()
.map(|tx| {
PooledTransaction::try_from(tx)
PooledTransactionVariant::try_from(tx)
.expect("Failed to convert MockTransaction to PooledTransaction")
})
.collect();
Expand Down Expand Up @@ -2399,7 +2399,8 @@ mod tests {

let request = GetPooledTransactions(vec![*tx.get_hash()]);

let (send, receive) = oneshot::channel::<RequestResult<PooledTransactions>>();
let (send, receive) =
oneshot::channel::<RequestResult<PooledTransactions<PooledTransactionVariant>>>();

transactions.on_network_tx_event(NetworkTransactionEvent::GetPooledTransactions {
peer_id: *handle1.peer_id(),
Expand Down Expand Up @@ -2510,11 +2511,11 @@ mod tests {
.expect("peer_1 session should receive request with buffered hashes");
let PeerRequest::GetPooledTransactions { response, .. } = req else { unreachable!() };

let message: Vec<PooledTransaction> = txs
let message: Vec<PooledTransactionVariant> = txs
.into_iter()
.take(1)
.map(|tx| {
PooledTransaction::try_from(tx)
PooledTransactionVariant::try_from(tx)
.expect("Failed to convert MockTransaction to PooledTransaction")
})
.collect();
Expand Down
11 changes: 5 additions & 6 deletions crates/optimism/txpool/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ use crate::{
conditional::MaybeConditionalTransaction, estimated_da_size::DataAvailabilitySized,
interop::MaybeInteropTransaction,
};
use alloy_consensus::{
transaction::Recovered, BlobTransactionSidecar, BlobTransactionValidationError, Typed2718,
};
use alloy_consensus::{transaction::Recovered, BlobTransactionValidationError, Typed2718};
use alloy_eips::{
eip2718::{Encodable2718, WithEncoded},
eip2930::AccessList,
eip7594::BlobTransactionSidecarVariant,
eip7702::SignedAuthorization,
};
use alloy_primitives::{Address, Bytes, TxHash, TxKind, B256, U256};
Expand Down Expand Up @@ -268,21 +267,21 @@ where

fn try_into_pooled_eip4844(
self,
_sidecar: Arc<BlobTransactionSidecar>,
_sidecar: Arc<BlobTransactionSidecarVariant>,
) -> Option<Recovered<Self::Pooled>> {
None
}

fn try_from_eip4844(
_tx: Recovered<Self::Consensus>,
_sidecar: BlobTransactionSidecar,
_sidecar: BlobTransactionSidecarVariant,
) -> Option<Self> {
None
}

fn validate_blob(
&self,
_sidecar: &BlobTransactionSidecar,
_sidecar: &BlobTransactionSidecarVariant,
_settings: &KzgSettings,
) -> Result<(), BlobTransactionValidationError> {
Err(BlobTransactionValidationError::NotBlobTransaction(self.ty()))
Expand Down
4 changes: 3 additions & 1 deletion crates/payload/builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,6 @@ pub use traits::{KeepPayloadJobAlive, PayloadJob, PayloadJobGenerator};

// re-export the Ethereum engine primitives for convenience
#[doc(inline)]
pub use reth_ethereum_engine_primitives::{EthBuiltPayload, EthPayloadBuilderAttributes};
pub use reth_ethereum_engine_primitives::{
BlobSidecars, EthBuiltPayload, EthPayloadBuilderAttributes,
};
Loading
Loading