Skip to content

Commit

Permalink
chore(derive): Blob Source Test Coverage (#631)
Browse files Browse the repository at this point in the history
* chore(derive): blob source tests

* chore(derive): blob source tests

* chore(derive): blob source tests
  • Loading branch information
refcell authored Oct 5, 2024
1 parent faadb05 commit a2ec985
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 0 deletions.
134 changes: 134 additions & 0 deletions crates/derive/src/sources/blobs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,137 @@ where
}
}
}

#[cfg(test)]
pub(crate) mod tests {
use super::*;
use crate::{errors::PipelineErrorKind, traits::test_utils::TestBlobProvider};
use alloy_rlp::Decodable;
use kona_providers::test_utils::TestChainProvider;

pub(crate) fn default_test_blob_source() -> BlobSource<TestChainProvider, TestBlobProvider> {
let chain_provider = TestChainProvider::default();
let blob_fetcher = TestBlobProvider::default();
let batcher_address = Address::default();
let block_ref = BlockInfo::default();
let signer = Address::default();
BlobSource::new(chain_provider, blob_fetcher, batcher_address, block_ref, signer)
}

pub(crate) fn valid_blob_txs() -> Vec<TxEnvelope> {
// https://sepolia.etherscan.io/getRawTx?tx=0x9a22ccb0029bc8b0ddd073be1a1d923b7ae2b2ea52100bae0db4424f9107e9c0
let raw_tx = alloy_primitives::hex::decode("0x03f9011d83aa36a7820fa28477359400852e90edd0008252089411e9ca82a3a762b4b5bd264d4173a242e7a770648080c08504a817c800f8a5a0012ec3d6f66766bedb002a190126b3549fce0047de0d4c25cffce0dc1c57921aa00152d8e24762ff22b1cfd9f8c0683786a7ca63ba49973818b3d1e9512cd2cec4a0013b98c6c83e066d5b14af2b85199e3d4fc7d1e778dd53130d180f5077e2d1c7a001148b495d6e859114e670ca54fb6e2657f0cbae5b08063605093a4b3dc9f8f1a0011ac212f13c5dff2b2c6b600a79635103d6f580a4221079951181b25c7e654901a0c8de4cced43169f9aa3d36506363b2d2c44f6c49fc1fd91ea114c86f3757077ea01e11fdd0d1934eda0492606ee0bb80a7bf8f35cc5f86ec60fe5031ba48bfd544").unwrap();
let eip4844 = TxEnvelope::decode(&mut raw_tx.as_slice()).unwrap();
vec![eip4844]
}

#[tokio::test]
async fn test_load_blobs_open() {
let mut source = default_test_blob_source();
source.open = true;
assert!(source.load_blobs().await.is_ok());
}

#[tokio::test]
async fn test_load_blobs_chain_provider_err() {
let mut source = default_test_blob_source();
assert!(matches!(source.load_blobs().await, Err(BlobProviderError::Backend(_))));
}

#[tokio::test]
async fn test_load_blobs_chain_provider_empty_txs() {
let mut source = default_test_blob_source();
let block_info = BlockInfo::default();
source.chain_provider.insert_block_with_transactions(0, block_info, Vec::new());
assert!(!source.open); // Source is not open by default.
assert!(source.load_blobs().await.is_ok());
assert!(source.data.is_empty());
assert!(source.open);
}

#[tokio::test]
async fn test_load_blobs_chain_provider_4844_txs_blob_fetch_error() {
let mut source = default_test_blob_source();
let block_info = BlockInfo::default();
source.signer = alloy_primitives::address!("A83C816D4f9b2783761a22BA6FADB0eB0606D7B2");
source.batcher_address =
alloy_primitives::address!("11E9CA82A3a762b4B5bd264d4173a242e7a77064");
let txs = valid_blob_txs();
source.blob_fetcher.should_error = true;
source.chain_provider.insert_block_with_transactions(1, block_info, txs);
assert!(matches!(source.load_blobs().await, Err(BlobProviderError::Backend(_))));
}

#[tokio::test]
async fn test_load_blobs_chain_provider_4844_txs_succeeds() {
use alloy_consensus::Blob;

let mut source = default_test_blob_source();
let block_info = BlockInfo::default();
source.signer = alloy_primitives::address!("A83C816D4f9b2783761a22BA6FADB0eB0606D7B2");
source.batcher_address =
alloy_primitives::address!("11E9CA82A3a762b4B5bd264d4173a242e7a77064");
let txs = valid_blob_txs();
source.chain_provider.insert_block_with_transactions(1, block_info, txs);
let hashes = [
alloy_primitives::b256!(
"012ec3d6f66766bedb002a190126b3549fce0047de0d4c25cffce0dc1c57921a"
),
alloy_primitives::b256!(
"0152d8e24762ff22b1cfd9f8c0683786a7ca63ba49973818b3d1e9512cd2cec4"
),
alloy_primitives::b256!(
"013b98c6c83e066d5b14af2b85199e3d4fc7d1e778dd53130d180f5077e2d1c7"
),
alloy_primitives::b256!(
"01148b495d6e859114e670ca54fb6e2657f0cbae5b08063605093a4b3dc9f8f1"
),
alloy_primitives::b256!(
"011ac212f13c5dff2b2c6b600a79635103d6f580a4221079951181b25c7e6549"
),
];
for hash in hashes {
source.blob_fetcher.insert_blob(hash, Blob::with_last_byte(1u8));
}
source.load_blobs().await.unwrap();
assert!(source.open);
assert!(!source.data.is_empty());
}

#[tokio::test]
async fn test_open_empty_data_eof() {
let mut source = default_test_blob_source();
source.open = true;

let err = source.next().await.unwrap_err();
assert!(matches!(err, PipelineErrorKind::Temporary(PipelineError::Eof)));
}

#[tokio::test]
async fn test_open_calldata() {
let mut source = default_test_blob_source();
source.open = true;
source.data.push(BlobData { data: None, calldata: Some(Bytes::default()) });

let data = source.next().await.unwrap();
assert_eq!(data, Bytes::default());
}

#[tokio::test]
async fn test_open_blob_data_decode_missing_data() {
let mut source = default_test_blob_source();
source.open = true;
source.data.push(BlobData { data: Some(Bytes::from(&[1; 32])), calldata: None });

let err = source.next().await.unwrap_err();
assert!(matches!(err, PipelineErrorKind::Temporary(PipelineError::Eof)));
}

#[tokio::test]
async fn test_blob_source_pipeline_error() {
let mut source = default_test_blob_source();

let err = source.next().await.unwrap_err();
assert!(matches!(err, PipelineErrorKind::Temporary(PipelineError::Provider(_))));
}
}
5 changes: 5 additions & 0 deletions crates/derive/src/traits/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ impl DataAvailabilityProvider for TestDAP {
pub struct TestBlobProvider {
/// Maps block hashes to blob data.
pub blobs: HashMap<B256, Blob>,
/// whether the blob provider should return an error.
pub should_error: bool,
}

impl TestBlobProvider {
Expand All @@ -84,6 +86,9 @@ impl BlobProvider for TestBlobProvider {
_block_ref: &BlockInfo,
blob_hashes: &[IndexedBlobHash],
) -> Result<Vec<Blob>, Self::Error> {
if self.should_error {
return Err(BlobProviderError::SlotDerivation);
}
let mut blobs = Vec::new();
for blob_hash in blob_hashes {
if let Some(data) = self.blobs.get(&blob_hash.hash) {
Expand Down

0 comments on commit a2ec985

Please sign in to comment.