diff --git a/crates/blockchain/blockchain.rs b/crates/blockchain/blockchain.rs index ffb4e1d8f45..cd60c75e873 100644 --- a/crates/blockchain/blockchain.rs +++ b/crates/blockchain/blockchain.rs @@ -1191,18 +1191,42 @@ impl Blockchain { Ok(()) } + /// Add a previously validated blob transaction and its blobs bundle to the mempool + #[cfg(feature = "c-kzg")] + pub async fn add_blob_transaction_to_pool_unchecked( + &self, + transaction: EIP4844Transaction, + blobs_bundle: BlobsBundle, + ) -> Result { + self.add_blob_transaction_to_pool_maybe_validate(transaction, blobs_bundle, true) + .await + } + /// Add a blob transaction and its blobs bundle to the mempool checking that the transaction is valid #[cfg(feature = "c-kzg")] pub async fn add_blob_transaction_to_pool( &self, transaction: EIP4844Transaction, blobs_bundle: BlobsBundle, + ) -> Result { + self.add_blob_transaction_to_pool_maybe_validate(transaction, blobs_bundle, false) + .await + } + + #[cfg(feature = "c-kzg")] + async fn add_blob_transaction_to_pool_maybe_validate( + &self, + transaction: EIP4844Transaction, + blobs_bundle: BlobsBundle, + assume_valid: bool, ) -> Result { // Validate blobs bundle let fork = self.current_fork().await?; - blobs_bundle.validate(&transaction, fork)?; + if !assume_valid { + blobs_bundle.validate(&transaction, fork)?; + } let transaction = Transaction::EIP4844Transaction(transaction); let hash = transaction.hash(); diff --git a/crates/networking/p2p/rlpx/connection/server.rs b/crates/networking/p2p/rlpx/connection/server.rs index c63573ae43b..b705dadaaaf 100644 --- a/crates/networking/p2p/rlpx/connection/server.rs +++ b/crates/networking/p2p/rlpx/connection/server.rs @@ -1047,22 +1047,30 @@ async fn handle_incoming_message( } } if state.blockchain.is_synced() { - if let Some(requested) = state.requested_pooled_txs.get(&msg.id) { - let fork = state.blockchain.current_fork().await?; - if let Err(error) = msg.validate_requested(requested, fork).await { - warn!( - peer=%state.node, - reason=%error, - "disconnected from peer", - ); - send_disconnect_message(state, Some(DisconnectReason::SubprotocolError)) - .await; - return Err(PeerConnectionError::DisconnectSent( - DisconnectReason::SubprotocolError, - )); - } else { - state.requested_pooled_txs.remove(&msg.id); - } + let Some(requested) = state.requested_pooled_txs.get(&msg.id) else { + warn!( + peer=%state.node, + reason="unsolicited PooledTransactions message", + "disconnected from peer", + ); + send_disconnect_message(state, Some(DisconnectReason::SubprotocolError)).await; + return Err(PeerConnectionError::DisconnectSent( + DisconnectReason::SubprotocolError, + )); + }; + let fork = state.blockchain.current_fork().await?; + if let Err(error) = msg.validate_requested(requested, fork).await { + warn!( + peer=%state.node, + reason=%error, + "disconnected from peer", + ); + send_disconnect_message(state, Some(DisconnectReason::SubprotocolError)).await; + return Err(PeerConnectionError::DisconnectSent( + DisconnectReason::SubprotocolError, + )); + } else { + state.requested_pooled_txs.remove(&msg.id); } #[cfg(feature = "l2")] let is_l2_mode = state.l2_state.is_supported(); diff --git a/crates/networking/p2p/rlpx/eth/transactions.rs b/crates/networking/p2p/rlpx/eth/transactions.rs index 0256a173201..c7ef36624a6 100644 --- a/crates/networking/p2p/rlpx/eth/transactions.rs +++ b/crates/networking/p2p/rlpx/eth/transactions.rs @@ -283,8 +283,10 @@ impl PooledTransactions { ); continue; } + // SAFETY: PooledTransactions::validate_requested is called before PooledTransactions::handle, + // so we already validated the blobs at this point. if let Err(e) = blockchain - .add_blob_transaction_to_pool(itx.tx, itx.blobs_bundle) + .add_blob_transaction_to_pool_unchecked(itx.tx, itx.blobs_bundle) .await { debug!(