diff --git a/crates/payload/basic/src/lib.rs b/crates/payload/basic/src/lib.rs index c56dba46d..49307b506 100644 --- a/crates/payload/basic/src/lib.rs +++ b/crates/payload/basic/src/lib.rs @@ -790,13 +790,10 @@ where // 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( + blob_sidecars = pool.get_all_blobs_exact( 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(); diff --git a/crates/transaction-pool/src/blobstore/mem.rs b/crates/transaction-pool/src/blobstore/mem.rs index 352ecae61..2a2d2fd86 100644 --- a/crates/transaction-pool/src/blobstore/mem.rs +++ b/crates/transaction-pool/src/blobstore/mem.rs @@ -83,7 +83,7 @@ impl BlobStore for InMemoryBlobStore { // Retrieves the decoded blob data for the given transaction hash. fn get(&self, tx: H256) -> Result, BlobStoreError> { - let store = self.inner.store.write(); + let store = self.inner.store.read(); Ok(store.get(&tx).cloned()) } @@ -92,7 +92,7 @@ impl BlobStore for InMemoryBlobStore { txs: Vec, ) -> Result, BlobStoreError> { let mut items = Vec::with_capacity(txs.len()); - let store = self.inner.store.write(); + let store = self.inner.store.read(); for tx in txs { if let Some(item) = store.get(&tx) { items.push((tx, item.clone())); @@ -102,6 +102,20 @@ impl BlobStore for InMemoryBlobStore { Ok(items) } + fn get_exact(&self, txs: Vec) -> Result, BlobStoreError> { + let mut items = Vec::with_capacity(txs.len()); + let store = self.inner.store.read(); + for tx in txs { + if let Some(item) = store.get(&tx) { + items.push(item.clone()); + } else { + return Err(BlobStoreError::MissingSidecar(tx)) + } + } + + Ok(items) + } + fn data_size_hint(&self) -> Option { Some(self.inner.data_size.load(std::sync::atomic::Ordering::Relaxed)) } diff --git a/crates/transaction-pool/src/blobstore/mod.rs b/crates/transaction-pool/src/blobstore/mod.rs index 786bbcd4f..ce2e875bf 100644 --- a/crates/transaction-pool/src/blobstore/mod.rs +++ b/crates/transaction-pool/src/blobstore/mod.rs @@ -41,6 +41,12 @@ pub trait BlobStore: fmt::Debug + Send + Sync + 'static { txs: Vec, ) -> Result, BlobStoreError>; + /// Returns the exact [BlobTransactionSidecar] for the given transaction hashes in the order + /// they were requested. + /// + /// Returns an error if any of the blobs are not found in the blob store. + fn get_exact(&self, txs: Vec) -> Result, BlobStoreError>; + /// Data size of all transactions in the blob store. fn data_size_hint(&self) -> Option; @@ -51,6 +57,9 @@ pub trait BlobStore: fmt::Debug + Send + Sync + 'static { /// Error variants that can occur when interacting with a blob store. #[derive(Debug, thiserror::Error)] pub enum BlobStoreError { + /// Thrown if the blob sidecar is not found for a given transaction hash but was required. + #[error("blob sidecar not found for transaction {0:?}")] + MissingSidecar(H256), /// Failed to decode the stored blob data. #[error("failed to decode blob data: {0}")] DecodeError(#[from] reth_rlp::DecodeError), diff --git a/crates/transaction-pool/src/blobstore/noop.rs b/crates/transaction-pool/src/blobstore/noop.rs index 3cb30a22e..431d34cc8 100644 --- a/crates/transaction-pool/src/blobstore/noop.rs +++ b/crates/transaction-pool/src/blobstore/noop.rs @@ -34,6 +34,13 @@ impl BlobStore for NoopBlobStore { Ok(vec![]) } + fn get_exact(&self, txs: Vec) -> Result, BlobStoreError> { + if txs.is_empty() { + return Ok(vec![]) + } + Err(BlobStoreError::MissingSidecar(txs[0])) + } + fn data_size_hint(&self) -> Option { Some(0) } diff --git a/crates/transaction-pool/src/lib.rs b/crates/transaction-pool/src/lib.rs index cdf928024..667e611aa 100644 --- a/crates/transaction-pool/src/lib.rs +++ b/crates/transaction-pool/src/lib.rs @@ -481,6 +481,13 @@ where ) -> Result, BlobStoreError> { self.pool.blob_store().get_all(tx_hashes) } + + fn get_all_blobs_exact( + &self, + tx_hashes: Vec, + ) -> Result, BlobStoreError> { + self.pool.blob_store().get_exact(tx_hashes) + } } impl TransactionPoolExt for Pool diff --git a/crates/transaction-pool/src/noop.rs b/crates/transaction-pool/src/noop.rs index d2c8bcd71..bfeea1c73 100644 --- a/crates/transaction-pool/src/noop.rs +++ b/crates/transaction-pool/src/noop.rs @@ -192,6 +192,16 @@ impl TransactionPool for NoopTransactionPool { ) -> Result, BlobStoreError> { Ok(vec![]) } + + fn get_all_blobs_exact( + &self, + tx_hashes: Vec, + ) -> Result, BlobStoreError> { + if tx_hashes.is_empty() { + return Ok(vec![]) + } + Err(BlobStoreError::MissingSidecar(tx_hashes[0])) + } } /// A [`TransactionValidator`] that does nothing. diff --git a/crates/transaction-pool/src/traits.rs b/crates/transaction-pool/src/traits.rs index 506ced494..0df53ed51 100644 --- a/crates/transaction-pool/src/traits.rs +++ b/crates/transaction-pool/src/traits.rs @@ -310,6 +310,15 @@ pub trait TransactionPool: Send + Sync + Clone { &self, tx_hashes: Vec, ) -> Result, BlobStoreError>; + + /// Returns the exact [BlobTransactionSidecar] for the given transaction hashes in the order + /// they were requested. + /// + /// Returns an error if any of the blobs are not found in the blob store. + fn get_all_blobs_exact( + &self, + tx_hashes: Vec, + ) -> Result, BlobStoreError>; } /// Extension for [TransactionPool] trait that allows to set the current block info.