Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move HackReceiptFileCodec into reth-optimism-cli #9393

Closed
emhane opened this issue Jul 9, 2024 · 1 comment · Fixed by #9499
Closed

Move HackReceiptFileCodec into reth-optimism-cli #9393

emhane opened this issue Jul 9, 2024 · 1 comment · Fixed by #9499
Assignees
Labels
A-cli Related to the reth CLI A-op-reth Related to Optimism and op-reth C-debt A clean up/refactor of existing code D-good-first-issue Nice and easy! A great choice to get started

Comments

@emhane
Copy link
Member

emhane commented Jul 9, 2024

Describe the feature

Move HackReceiptFileCodec into reth-optimism-cli.

/// Codec for reading raw receipts from a file.
///
/// If using with [`FramedRead`](tokio_util::codec::FramedRead), the user should make sure the
/// framed reader has capacity for the entire receipts file. Otherwise, the decoder will return
/// [`InputTooShort`](alloy_rlp::Error::InputTooShort), because RLP receipts can only be
/// decoded if the internal buffer is large enough to contain the entire receipt.
///
/// Without ensuring the framed reader has capacity for the entire file, a receipt is likely to
/// fall across two read buffers, the decoder will not be able to decode the receipt, which will
/// cause it to fail.
///
/// It's recommended to use [`with_capacity`](tokio_util::codec::FramedRead::with_capacity) to set
/// the capacity of the framed reader to the size of the file.
#[derive(Debug, Default)]
pub struct HackReceiptFileCodec;
impl Decoder for HackReceiptFileCodec {
type Item = Option<ReceiptWithBlockNumber>;
type Error = FileClientError;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
if src.is_empty() {
return Ok(None)
}
let buf_slice = &mut src.as_ref();
let receipt = HackReceiptContainer::decode(buf_slice)
.map_err(|err| Self::Error::Rlp(err, src.to_vec()))?
.0;
src.advance(src.len() - buf_slice.len());
Ok(Some(
receipt.map(|receipt| receipt.try_into().map_err(FileClientError::from)).transpose()?,
))
}
}

Requires implementing a mock receipt file codec to replace HackReceiptFileCodec in ReceiptFileClient tests.

#[cfg(test)]
mod test {
use reth_primitives::hex;
use reth_tracing::init_test_tracing;
use crate::file_codec_ovm_receipt::{
test::{
receipt_block_1 as op_mainnet_receipt_block_1,
receipt_block_2 as op_mainnet_receipt_block_2,
receipt_block_3 as op_mainnet_receipt_block_3,
HACK_RECEIPT_ENCODED_BLOCK_1 as HACK_RECEIPT_ENCODED_BLOCK_1_OP_MAINNET,
HACK_RECEIPT_ENCODED_BLOCK_2 as HACK_RECEIPT_ENCODED_BLOCK_2_OP_MAINNET,
HACK_RECEIPT_ENCODED_BLOCK_3 as HACK_RECEIPT_ENCODED_BLOCK_3_OP_MAINNET,
},
HackReceiptFileCodec,
};
use super::*;
/// No receipts for genesis block
const HACK_RECEIPT_BLOCK_NO_TRANSACTIONS: &[u8] = &hex!("c0");
#[tokio::test]
async fn receipt_file_client_ovm_codec() {
init_test_tracing();
// genesis block has no hack receipts
let mut encoded_receipts = HACK_RECEIPT_BLOCK_NO_TRANSACTIONS.to_vec();
// one receipt each for block 1 and 2
encoded_receipts.extend_from_slice(HACK_RECEIPT_ENCODED_BLOCK_1_OP_MAINNET);
encoded_receipts.extend_from_slice(HACK_RECEIPT_ENCODED_BLOCK_2_OP_MAINNET);
// no receipt for block 4
encoded_receipts.extend_from_slice(HACK_RECEIPT_BLOCK_NO_TRANSACTIONS);
let encoded_byte_len = encoded_receipts.len() as u64;
let reader = &mut &encoded_receipts[..];
let (
ReceiptFileClient { receipts, first_block, total_receipts, _marker },
_remaining_bytes,
) = ReceiptFileClient::<HackReceiptFileCodec>::from_reader(reader, encoded_byte_len)
.await
.unwrap();
// 2 non-empty receipt objects
assert_eq!(2, total_receipts);
assert_eq!(0, first_block);
assert!(receipts[0].is_empty());
assert_eq!(op_mainnet_receipt_block_1().receipt, receipts[1][0].clone().unwrap());
assert_eq!(op_mainnet_receipt_block_2().receipt, receipts[2][0].clone().unwrap());
assert!(receipts[3].is_empty());
}
#[tokio::test]
async fn no_receipts_middle_block() {
init_test_tracing();
// genesis block has no hack receipts
let mut encoded_receipts = HACK_RECEIPT_BLOCK_NO_TRANSACTIONS.to_vec();
// one receipt each for block 1
encoded_receipts.extend_from_slice(HACK_RECEIPT_ENCODED_BLOCK_1_OP_MAINNET);
// no receipt for block 2
encoded_receipts.extend_from_slice(HACK_RECEIPT_BLOCK_NO_TRANSACTIONS);
// one receipt for block 3
encoded_receipts.extend_from_slice(HACK_RECEIPT_ENCODED_BLOCK_3_OP_MAINNET);
let encoded_byte_len = encoded_receipts.len() as u64;
let reader = &mut &encoded_receipts[..];
let (
ReceiptFileClient { receipts, first_block, total_receipts, _marker },
_remaining_bytes,
) = ReceiptFileClient::<HackReceiptFileCodec>::from_reader(reader, encoded_byte_len)
.await
.unwrap();
// 2 non-empty receipt objects
assert_eq!(2, total_receipts);
assert_eq!(0, first_block);
assert!(receipts[0].is_empty());
assert_eq!(op_mainnet_receipt_block_1().receipt, receipts[1][0].clone().unwrap());
assert!(receipts[2].is_empty());
assert_eq!(op_mainnet_receipt_block_3().receipt, receipts[3][0].clone().unwrap());
}
#[tokio::test]
async fn two_receipts_same_block() {
init_test_tracing();
// genesis block has no hack receipts
let mut encoded_receipts = HACK_RECEIPT_BLOCK_NO_TRANSACTIONS.to_vec();
// one receipt each for block 1
encoded_receipts.extend_from_slice(HACK_RECEIPT_ENCODED_BLOCK_1_OP_MAINNET);
// two receipts for block 2
encoded_receipts.extend_from_slice(HACK_RECEIPT_ENCODED_BLOCK_2_OP_MAINNET);
encoded_receipts.extend_from_slice(HACK_RECEIPT_ENCODED_BLOCK_2_OP_MAINNET);
// one receipt for block 3
encoded_receipts.extend_from_slice(HACK_RECEIPT_ENCODED_BLOCK_3_OP_MAINNET);
let encoded_byte_len = encoded_receipts.len() as u64;
let reader = &mut &encoded_receipts[..];
let (
ReceiptFileClient { receipts, first_block, total_receipts, _marker },
_remaining_bytes,
) = ReceiptFileClient::<HackReceiptFileCodec>::from_reader(reader, encoded_byte_len)
.await
.unwrap();
// 4 non-empty receipt objects
assert_eq!(4, total_receipts);
assert_eq!(0, first_block);
assert!(receipts[0].is_empty());
assert_eq!(op_mainnet_receipt_block_1().receipt, receipts[1][0].clone().unwrap());
assert_eq!(op_mainnet_receipt_block_2().receipt, receipts[2][0].clone().unwrap());
assert_eq!(op_mainnet_receipt_block_2().receipt, receipts[2][1].clone().unwrap());
assert_eq!(op_mainnet_receipt_block_3().receipt, receipts[3][0].clone().unwrap());
}
}

Additional context

No response

@emhane emhane added D-good-first-issue Nice and easy! A great choice to get started C-debt A clean up/refactor of existing code A-cli Related to the reth CLI A-op-reth Related to Optimism and op-reth labels Jul 9, 2024
@nkysg
Copy link
Contributor

nkysg commented Jul 9, 2024

Can I take this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-cli Related to the reth CLI A-op-reth Related to Optimism and op-reth C-debt A clean up/refactor of existing code D-good-first-issue Nice and easy! A great choice to get started
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

2 participants