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

feat: tx and receipt compression utils for no-std config #11112

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 29 additions & 2 deletions crates/primitives/src/compression/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use alloc::vec::Vec;
use core::cell::RefCell;
use std::thread_local;
use zstd::bulk::{Compressor, Decompressor};

/// Compression/Decompression dictionary for `Receipt`.
Expand All @@ -10,7 +9,8 @@ pub static TRANSACTION_DICTIONARY: &[u8] = include_bytes!("./transaction_diction

// We use `thread_local` compressors and decompressors because dictionaries can be quite big, and
// zstd-rs recommends to use one context/compressor per thread
thread_local! {
#[cfg(feature = "std")]
std::thread_local! {
/// Thread Transaction compressor.
pub static TRANSACTION_COMPRESSOR: RefCell<Compressor<'static>> = RefCell::new(
Compressor::with_dictionary(0, TRANSACTION_DICTIONARY)
Expand Down Expand Up @@ -38,6 +38,33 @@ thread_local! {
));
}

/// Fn creates tx [`Compressor`]
pub fn create_tx_compressor() -> Compressor<'static> {
Compressor::with_dictionary(0, RECEIPT_DICTIONARY).expect("Failed to instantiate tx compressor")
}

/// Fn creates tx [`Decompressor`]
pub fn create_tx_decompressor() -> ReusableDecompressor {
ReusableDecompressor::new(
Decompressor::with_dictionary(TRANSACTION_DICTIONARY)
.expect("Failed to instantiate tx decompressor"),
)
}

/// Fn creates receipt [`Compressor`]
pub fn create_receipt_compressor() -> Compressor<'static> {
Compressor::with_dictionary(0, RECEIPT_DICTIONARY)
.expect("Failed to instantiate receipt compressor")
}

/// Fn creates receipt [`Decompressor`]
pub fn create_receipt_decompressor() -> ReusableDecompressor {
ReusableDecompressor::new(
Decompressor::with_dictionary(RECEIPT_DICTIONARY)
.expect("Failed to instantiate receipt decompressor"),
)
}

/// Reusable decompressor that uses its own internal buffer.
#[allow(missing_debug_implementations)]
pub struct ReusableDecompressor {
Expand Down
34 changes: 24 additions & 10 deletions crates/primitives/src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -960,15 +960,20 @@ impl reth_codecs::Compact for TransactionSignedNoHash {
let zstd_bit = self.transaction.input().len() >= 32;

let tx_bits = if zstd_bit {
crate::compression::TRANSACTION_COMPRESSOR.with(|compressor| {
let mut compressor = compressor.borrow_mut();
let mut tmp = Vec::with_capacity(256);
let mut tmp = Vec::with_capacity(256);
if cfg!(feature = "std") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use cfg_if here?

Copy link
Contributor Author

@nadtech-hub nadtech-hub Sep 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've viewed that crate. I can't foresee more than 2 if-else branches in this place, therefore this crate doesn't seem much useful

crate::compression::TRANSACTION_COMPRESSOR.with(|compressor| {
let mut compressor = compressor.borrow_mut();
let tx_bits = self.transaction.to_compact(&mut tmp);
buf.put_slice(&compressor.compress(&tmp).expect("Failed to compress"));
tx_bits as u8
})
} else {
let mut compressor = crate::compression::create_tx_compressor();
let tx_bits = self.transaction.to_compact(&mut tmp);

buf.put_slice(&compressor.compress(&tmp).expect("Failed to compress"));

tx_bits as u8
})
}
} else {
self.transaction.to_compact(buf) as u8
};
Expand All @@ -988,17 +993,26 @@ impl reth_codecs::Compact for TransactionSignedNoHash {

let zstd_bit = bitflags >> 3;
let (transaction, buf) = if zstd_bit != 0 {
crate::compression::TRANSACTION_DECOMPRESSOR.with(|decompressor| {
let mut decompressor = decompressor.borrow_mut();
if cfg!(feature = "std") {
crate::compression::TRANSACTION_DECOMPRESSOR.with(|decompressor| {
let mut decompressor = decompressor.borrow_mut();

// TODO: enforce that zstd is only present at a "top" level type
// TODO: enforce that zstd is only present at a "top" level type

let transaction_type = (bitflags & 0b110) >> 1;
let (transaction, _) =
Transaction::from_compact(decompressor.decompress(buf), transaction_type);

(transaction, buf)
})
} else {
let mut decompressor = crate::compression::create_tx_decompressor();
let transaction_type = (bitflags & 0b110) >> 1;
let (transaction, _) =
Transaction::from_compact(decompressor.decompress(buf), transaction_type);

(transaction, buf)
})
}
} else {
let transaction_type = bitflags >> 1;
Transaction::from_compact(buf, transaction_type)
Expand Down
Loading