diff --git a/crates/transaction-pool/src/blobstore/disk.rs b/crates/transaction-pool/src/blobstore/disk.rs index a3520b9757..76e6f61eef 100644 --- a/crates/transaction-pool/src/blobstore/disk.rs +++ b/crates/transaction-pool/src/blobstore/disk.rs @@ -194,9 +194,67 @@ impl BlobStore for DiskFileBlobStore { fn get_by_versioned_hashes_v2( &self, - _versioned_hashes: &[B256], + versioned_hashes: &[B256], ) -> Result>, BlobStoreError> { - Ok(None) + // we must return the blobs in order but we don't necessarily find them in the requested + // order + let mut result = vec![None; versioned_hashes.len()]; + + // first scan all cached full sidecars + for (_tx_hash, blob_sidecar) in self.inner.blob_cache.lock().iter() { + if let Some(blob_sidecar) = blob_sidecar.as_eip7594() { + for (hash_idx, match_result) in + blob_sidecar.match_versioned_hashes(versioned_hashes) + { + result[hash_idx] = Some(match_result); + } + } + + // return early if all blobs are found. + if result.iter().all(|blob| blob.is_some()) { + // got all blobs, can return early + return Ok(Some(result.into_iter().map(Option::unwrap).collect())) + } + } + + // not all versioned hashes were found, try to look up a matching tx + let mut missing_tx_hashes = Vec::new(); + + { + let mut versioned_to_txhashes = self.inner.versioned_hashes_to_txhash.lock(); + for (idx, _) in + result.iter().enumerate().filter(|(_, blob_and_proof)| blob_and_proof.is_none()) + { + // this is safe because the result vec has the same len + let versioned_hash = versioned_hashes[idx]; + if let Some(tx_hash) = versioned_to_txhashes.get(&versioned_hash).copied() { + missing_tx_hashes.push(tx_hash); + } + } + } + + // if we have missing blobs, try to read them from disk and try again + if !missing_tx_hashes.is_empty() { + let blobs_from_disk = self.inner.read_many_decoded(missing_tx_hashes); + for (_, blob_sidecar) in blobs_from_disk { + if let Some(blob_sidecar) = blob_sidecar.as_eip7594() { + for (hash_idx, match_result) in + blob_sidecar.match_versioned_hashes(versioned_hashes) + { + if result[hash_idx].is_none() { + result[hash_idx] = Some(match_result); + } + } + } + } + } + + // only return the blobs if we found all requested versioned hashes + if result.iter().all(|blob| blob.is_some()) { + Ok(Some(result.into_iter().map(Option::unwrap).collect())) + } else { + Ok(None) + } } fn data_size_hint(&self) -> Option { diff --git a/crates/transaction-pool/src/blobstore/mem.rs b/crates/transaction-pool/src/blobstore/mem.rs index 89655c2c23..44dff1cceb 100644 --- a/crates/transaction-pool/src/blobstore/mem.rs +++ b/crates/transaction-pool/src/blobstore/mem.rs @@ -127,9 +127,27 @@ impl BlobStore for InMemoryBlobStore { fn get_by_versioned_hashes_v2( &self, - _versioned_hashes: &[B256], + versioned_hashes: &[B256], ) -> Result>, BlobStoreError> { - Ok(None) + let mut result = vec![None; versioned_hashes.len()]; + for (_tx_hash, blob_sidecar) in self.inner.store.read().iter() { + if let Some(blob_sidecar) = blob_sidecar.as_eip7594() { + for (hash_idx, match_result) in + blob_sidecar.match_versioned_hashes(versioned_hashes) + { + result[hash_idx] = Some(match_result); + } + } + + if result.iter().all(|blob| blob.is_some()) { + break; + } + } + if result.iter().all(|blob| blob.is_some()) { + Ok(Some(result.into_iter().map(Option::unwrap).collect())) + } else { + Ok(None) + } } fn data_size_hint(&self) -> Option { diff --git a/crates/transaction-pool/src/blobstore/mod.rs b/crates/transaction-pool/src/blobstore/mod.rs index 603b781665..29844994bc 100644 --- a/crates/transaction-pool/src/blobstore/mod.rs +++ b/crates/transaction-pool/src/blobstore/mod.rs @@ -86,6 +86,13 @@ pub trait BlobStore: fmt::Debug + Send + Sync + 'static { /// Return the [`BlobAndProofV2`]s for a list of blob versioned hashes. /// Blobs and proofs are returned only if they are present for _all_ requested /// versioned hashes. + /// + /// This differs from [`BlobStore::get_by_versioned_hashes_v1`] in that it also returns all the + /// cell proofs in [`BlobAndProofV2`] supported by the EIP-7594 blob sidecar variant. + /// + /// The response also differs from [`BlobStore::get_by_versioned_hashes_v1`] in that this + /// returns `None` if any of the requested versioned hashes are not present in the blob store: + /// e.g. where v1 would return `[A, None, C]` v2 would return `None`. See also fn get_by_versioned_hashes_v2( &self, versioned_hashes: &[B256],