From e078359435b214815e48d3c4219da3004cd68634 Mon Sep 17 00:00:00 2001 From: refcell Date: Fri, 15 Nov 2024 14:22:32 -0500 Subject: [PATCH 1/3] feat(protocol): add batch --- Cargo.toml | 1 + crates/protocol/Cargo.toml | 4 +- crates/protocol/examples/batch_to_frames.rs | 44 ++----- crates/protocol/src/channel.rs | 23 ++-- crates/protocol/src/lib.rs | 7 +- crates/protocol/src/utils.rs | 124 +++++++++++++++++++- 6 files changed, 156 insertions(+), 47 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6ecd4316..c635bd12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,6 +81,7 @@ snap = "1.1.1" bincode = "1.3.3" ethereum_ssz = "0.8" brotli = { version = "7.0.0", default-features = false } +alloc-no-stdlib = "2.0.4" # rpc jsonrpsee = { version = "0.24", features = [ diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index 7aa577b1..7b12d3f5 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -26,6 +26,8 @@ alloy-eips.workspace = true alloy-consensus.workspace = true # Misc +brotli.workspace = true +alloc-no-stdlib.workspace = true tracing.workspace = true derive_more.workspace = true async-trait.workspace = true @@ -62,5 +64,5 @@ test-utils = [ "dep:tracing-subscriber", ] arbitrary = ["std", "dep:arbitrary", "alloy-consensus/arbitrary", "alloy-eips/arbitrary", "alloy-primitives/rand"] -std = ["op-alloy-consensus/std", "op-alloy-genesis/std"] +std = ["op-alloy-consensus/std", "op-alloy-genesis/std", "brotli/std"] serde = ["dep:serde", "dep:alloy-serde", "op-alloy-consensus/serde", "op-alloy-genesis/serde"] diff --git a/crates/protocol/examples/batch_to_frames.rs b/crates/protocol/examples/batch_to_frames.rs index e9e98491..d2239434 100644 --- a/crates/protocol/examples/batch_to_frames.rs +++ b/crates/protocol/examples/batch_to_frames.rs @@ -12,13 +12,15 @@ //! Finally, once [Frame]s are built from the [ChannelOut], they are encoded and ready //! to be batch-submitted to the data availability layer. +#[cfg(not(feature = "std"))] +panic!("The `std` feature flag must be enabled for this example"); + use alloy_consensus::{SignableTransaction, TxEip1559}; use alloy_eips::eip2718::{Decodable2718, Encodable2718}; -use alloy_primitives::{hex, Address, BlockHash, Bytes, PrimitiveSignature, U256}; -use brotli::enc::{BrotliCompress, BrotliEncoderParams}; +use alloy_primitives::{Address, BlockHash, Bytes, PrimitiveSignature, U256}; use op_alloy_consensus::OpTxEnvelope; use op_alloy_genesis::RollupConfig; -use op_alloy_protocol::{Batch, ChannelId, ChannelOut, SingleBatch, CHANNEL_ID_LENGTH}; +use op_alloy_protocol::{Batch, ChannelId, ChannelOut, SingleBatch}; fn main() { // Use the example transaction @@ -29,30 +31,16 @@ fn main() { let epoch_num = 1; let epoch_hash = BlockHash::ZERO; let timestamp = 1; - let single_batch = SingleBatch { parent_hash, epoch_num, epoch_hash, timestamp, transactions }; let batch = Batch::Single(single_batch); - // Encode the batch. - let mut encoded = Vec::new(); - batch.encode(&mut encoded).unwrap(); - let config = RollupConfig::default(); - let decoded = Batch::decode(&mut encoded.as_slice(), &config).unwrap(); - assert_eq!(batch, decoded); - println!("Encoded Batch: {}", hex::encode(&encoded)); - - // Compress the encoded batch. - let compressed = compress_brotli(&encoded); - let expected = hex!("1b1301f82f0f6c3734f4821cd090ef3979d71a98e7e483b1dccdd525024c0ef16f425c7b4976a7acc0c94a0514b72c096d4dcc52f0b22dae193c70c86d0790a304a08152c8250031d091063ea0b00d00005082edde7ccf05bded2004462b5e80e1c42cd08e307f5baac723b22864cc6cd01ddde84efc7c018d7ada56c2fa8e3c5bedd494c3a7a884439d5771afcecaf196cb38"); - assert_eq!(compressed, expected); - println!("Brotli-compressed batch: {}", hex::encode(&compressed)); - // Create a new channel. - let id = random_channel_id(); + let id = ChannelId::default(); + let config = RollupConfig::default(); let mut channel_out = ChannelOut::new(id, &config); // Add the compressed batch to the `ChannelOut`. - channel_out.add_raw_compressed_batch(compressed.into()); + channel_out.add_batch(batch).unwrap(); // Output frames while channel_out.ready_bytes() > 0 { @@ -64,21 +52,7 @@ fn main() { } assert!(channel_out.closed); -} - -/// Creates a random [ChannelId]. -pub fn random_channel_id() -> ChannelId { - let mut id = [0; CHANNEL_ID_LENGTH]; - id.iter_mut().for_each(|b| *b = rand::random()); - id -} - -/// Compresses the given bytes data using the Brotli compressor implemented -/// in the [`brotli`](https://crates.io/crates/brotli) crate. -pub fn compress_brotli(mut input: &[u8]) -> Vec { - let mut output = vec![]; - BrotliCompress(&mut input, &mut output, &BrotliEncoderParams::default()).expect("succeeds"); - output + println!("Successfully encoded Batch to frames"); } fn example_transactions() -> Vec { diff --git a/crates/protocol/src/channel.rs b/crates/protocol/src/channel.rs index 37616dae..d17c17f6 100644 --- a/crates/protocol/src/channel.rs +++ b/crates/protocol/src/channel.rs @@ -2,10 +2,9 @@ use alloc::{vec, vec::Vec}; use alloy_primitives::{map::HashMap, Bytes}; -use alloy_rlp::Encodable; use op_alloy_genesis::RollupConfig; -use crate::{block::BlockInfo, frame::Frame, SingleBatch}; +use crate::{block::BlockInfo, frame::Frame, Batch}; /// The frame overhead. const FRAME_V0_OVERHEAD: usize = 23; @@ -17,7 +16,7 @@ pub const CHANNEL_ID_LENGTH: usize = 16; pub type ChannelId = [u8; CHANNEL_ID_LENGTH]; /// An error returned by the [ChannelOut] when adding single batches. -#[derive(Debug, Clone, Copy, derive_more::Display, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, derive_more::Display)] pub enum ChannelOutError { /// The channel is closed. ChannelClosed, @@ -25,6 +24,10 @@ pub enum ChannelOutError { MaxFrameSizeTooSmall, /// Missing compressed batch data. MissingData, + /// An error from brotli compression. + BrotliCompression, + /// An error encoding the [Batch]. + BatchEncoding, } impl core::error::Error for ChannelOutError {} @@ -54,25 +57,26 @@ impl<'a> ChannelOut<'a> { Self { id, config, rlp_length: 0, frame_number: 0, closed: false, compressed: None } } - /// Accepts the given [SingleBatch] data into the [ChannelOut], compressing it + /// Accepts the given [Batch] data into the [ChannelOut], compressing it /// into frames. - pub fn add_single_batch(&mut self, batch: SingleBatch) -> Result<(), ChannelOutError> { + #[cfg(feature = "std")] + pub fn add_batch(&mut self, batch: Batch) -> Result<(), ChannelOutError> { if self.closed { return Err(ChannelOutError::ChannelClosed); } // Encode the batch. let mut buf = vec![]; - batch.encode(&mut buf); + batch.encode(&mut buf).map_err(|_| ChannelOutError::BatchEncoding)?; // Validate that the RLP length is within the channel's limits. - let max_rlp_bytes_per_channel = self.config.max_rlp_bytes_per_channel(batch.timestamp); + let max_rlp_bytes_per_channel = self.config.max_rlp_bytes_per_channel(batch.timestamp()); if self.rlp_length + buf.len() as u64 > max_rlp_bytes_per_channel { return Err(ChannelOutError::ChannelClosed); } - // Compress the batch. - todo!("compress the batch with a compression algorithm based on the rollup config") + self.compressed = Some(crate::compress_brotli(&buf).into()); + Ok(()) } /// Returns the number of bytes ready to be output to a frame. @@ -81,6 +85,7 @@ impl<'a> ChannelOut<'a> { } /// Accepts the raw compressed batch data into the [ChannelOut]. + #[deprecated] pub fn add_raw_compressed_batch(&mut self, compressed: Bytes) { self.compressed = Some(compressed); } diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index c42dd9d9..d0ec273d 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -34,7 +34,12 @@ mod iter; pub use iter::FrameIter; mod utils; -pub use utils::{read_tx_data, starts_with_2718_deposit, to_system_config, OpBlockConversionError}; +#[cfg(feature = "std")] +pub use utils::compress_brotli; +pub use utils::{ + compress_brotli_nostd, read_tx_data, starts_with_2718_deposit, to_system_config, + OpBlockConversionError, +}; mod channel; pub use channel::{ diff --git a/crates/protocol/src/utils.rs b/crates/protocol/src/utils.rs index 560edff3..7b74dce8 100644 --- a/crates/protocol/src/utils.rs +++ b/crates/protocol/src/utils.rs @@ -1,9 +1,26 @@ //! Utility methods used by protocol types. -use alloc::vec::Vec; +use alloc::{boxed::Box, vec, vec::Vec}; +use alloc_no_stdlib::*; use alloy_consensus::TxType; use alloy_primitives::B256; use alloy_rlp::{Buf, Header}; +use brotli::{ + enc::{ + cluster::HistogramPair, + command::Command, + compress_multi, + entropy_encode::HuffmanTree, + histogram::{ContextType, HistogramCommand, HistogramDistance, HistogramLiteral}, + pdf::PDF, + s16, + threading::SendAlloc, + v8, BrotliEncoderParams, BrotliEncoderThreadError, Owned, StaticCommand, UnionHasher, + ZopfliNode, + }, + CombiningAllocator, SliceWrapper, +}; +use core::ops; use op_alloy_consensus::{OpBlock, OpTxEnvelope}; use op_alloy_genesis::{RollupConfig, SystemConfig}; @@ -12,6 +29,111 @@ use crate::{ SpanDecodingError, }; +/// Compresses the given bytes data using the Brotli compressor implemented +/// in the [`brotli`](https://crates.io/crates/brotli) crate. +#[cfg(feature = "std")] +pub fn compress_brotli(mut input: &[u8]) -> Vec { + use brotli::enc::{BrotliCompress, BrotliEncoderParams}; + let mut output = vec![]; + BrotliCompress(&mut input, &mut output, &BrotliEncoderParams::default()).expect("succeeds"); + output +} + +/// Compresses the given bytes data using the Brotli compressor implemented +/// in the [`brotli`][brotli] crate. +/// +/// [brotli]: https://crates.io/crates/brotli +#[allow(clippy::too_many_arguments)] +pub fn compress_brotli_nostd( + data: &'static [u8], + u8_buffer: &'static mut Box<[u8]>, + u16_buffer: &'static mut Box<[u16]>, + i32_buffer: &'static mut Box<[i32]>, + u32_buffer: &'static mut Box<[u32]>, + u64_buffer: &'static mut Box<[u64]>, + cmd_buffer: &'static mut Box<[Command]>, + pdf_buffer: &'static mut Box<[PDF]>, + static_buffer: &'static mut Box<[StaticCommand]>, + hist_buffer: &'static mut Box<[HistogramLiteral]>, + hcmd_buffer: &'static mut Box<[HistogramCommand]>, + hdist_buffer: &'static mut Box<[HistogramDistance]>, + hpair_buffer: &'static mut Box<[HistogramPair]>, + ctx_buffer: &'static mut Box<[ContextType]>, + huff_buffer: &'static mut Box<[HuffmanTree]>, + zop_buffer: &'static mut Box<[ZopfliNode]>, +) -> Result, BrotliEncoderThreadError> { + // Construct the allocator + declare_stack_allocator_struct!(MemPool, 4096, stack); + + let u8_allocator = MemPool::::new_allocator(u8_buffer, bzero); + let u16_allocator = MemPool::::new_allocator(u16_buffer, bzero); + let i32_allocator = MemPool::::new_allocator(i32_buffer, bzero); + let u32_allocator = MemPool::::new_allocator(u32_buffer, bzero); + let u64_allocator = MemPool::::new_allocator(u64_buffer, bzero); + let command_allocator = MemPool::::new_allocator(cmd_buffer, bzero); + let float_allocator = MemPool::::new_allocator(&mut [], bzero); + let v8_allocator = MemPool::::new_allocator(&mut [], bzero); + let s16_allocator = MemPool::::new_allocator(&mut [], bzero); + let pdf_allocator = MemPool::::new_allocator(pdf_buffer, bzero); + let static_allocator = MemPool::::new_allocator(static_buffer, bzero); + let hist_allocator = MemPool::::new_allocator(hist_buffer, bzero); + let hcmd_allocator = MemPool::::new_allocator(hcmd_buffer, bzero); + let hdist_allocator = MemPool::::new_allocator(hdist_buffer, bzero); + let hpair_allocator = MemPool::::new_allocator(hpair_buffer, bzero); + let ctx_allocator = MemPool::::new_allocator(ctx_buffer, bzero); + let huff_allocator = MemPool::::new_allocator(huff_buffer, bzero); + let zop_allocator = MemPool::::new_allocator(zop_buffer, bzero); + + let alloc = CombiningAllocator::new( + u8_allocator, + u16_allocator, + i32_allocator, + u32_allocator, + u64_allocator, + command_allocator, + float_allocator, + v8_allocator, + s16_allocator, + pdf_allocator, + static_allocator, + hist_allocator, + hcmd_allocator, + hdist_allocator, + hpair_allocator, + ctx_allocator, + huff_allocator, + zop_allocator, + ); + let alloc = SendAlloc::new(alloc, UnionHasher::default()); + + // Need a wrapper type around the input + struct SliceRef<'a>(&'a [u8]); + impl<'a> SliceWrapper for SliceRef<'a> { + fn slice(&self) -> &[u8] { + self.0 + } + } + + // Compression inputs + let params = BrotliEncoderParams::default(); + let mut output = vec![]; + let mut input = Owned::new(SliceRef(data)); + match compress_multi(¶ms, &mut input, output.as_mut_slice(), &mut [alloc]) { + Ok(_) => { + // if written == 0 { + // break; + // } + // continue; + } + Err(e) => { + // TODO: on out of space, resize the output buffer? + return Err(e); + } + } + + Ok(output) +} + /// Returns if the given `value` is a deposit transaction. pub fn starts_with_2718_deposit(value: &B) -> bool where From 0cd1358bbaf24afb8d4dfe3f63535c1c2f31bd82 Mon Sep 17 00:00:00 2001 From: refcell Date: Fri, 15 Nov 2024 15:17:30 -0500 Subject: [PATCH 2/3] fix --- crates/consensus/src/receipt/envelope.rs | 2 +- crates/protocol/examples/batch_to_frames.rs | 28 +++++++++++++-------- crates/protocol/src/channel.rs | 8 +++--- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/crates/consensus/src/receipt/envelope.rs b/crates/consensus/src/receipt/envelope.rs index ddc19f49..c2831b06 100644 --- a/crates/consensus/src/receipt/envelope.rs +++ b/crates/consensus/src/receipt/envelope.rs @@ -317,7 +317,7 @@ mod tests { use alloy_rlp::Encodable; #[cfg(not(feature = "std"))] - use alloc::{vec, vec::Vec}; + use alloc::vec; // Test vector from: https://eips.ethereum.org/EIPS/eip-2481 #[test] diff --git a/crates/protocol/examples/batch_to_frames.rs b/crates/protocol/examples/batch_to_frames.rs index d2239434..c97a0803 100644 --- a/crates/protocol/examples/batch_to_frames.rs +++ b/crates/protocol/examples/batch_to_frames.rs @@ -12,17 +12,12 @@ //! Finally, once [Frame]s are built from the [ChannelOut], they are encoded and ready //! to be batch-submitted to the data availability layer. -#[cfg(not(feature = "std"))] -panic!("The `std` feature flag must be enabled for this example"); - -use alloy_consensus::{SignableTransaction, TxEip1559}; -use alloy_eips::eip2718::{Decodable2718, Encodable2718}; -use alloy_primitives::{Address, BlockHash, Bytes, PrimitiveSignature, U256}; -use op_alloy_consensus::OpTxEnvelope; -use op_alloy_genesis::RollupConfig; -use op_alloy_protocol::{Batch, ChannelId, ChannelOut, SingleBatch}; - +#[cfg(feature = "std")] fn main() { + use alloy_primitives::BlockHash; + use op_alloy_genesis::RollupConfig; + use op_alloy_protocol::{Batch, ChannelId, ChannelOut, SingleBatch}; + // Use the example transaction let transactions = example_transactions(); @@ -55,7 +50,13 @@ fn main() { println!("Successfully encoded Batch to frames"); } -fn example_transactions() -> Vec { +#[cfg(feature = "std")] +fn example_transactions() -> Vec { + use alloy_consensus::{SignableTransaction, TxEip1559}; + use alloy_eips::eip2718::{Decodable2718, Encodable2718}; + use alloy_primitives::{Address, PrimitiveSignature, U256}; + use op_alloy_consensus::OpTxEnvelope; + let mut transactions = Vec::new(); // First Transaction in the batch. @@ -102,3 +103,8 @@ fn example_transactions() -> Vec { transactions } + +#[cfg(not(feature = "std"))] +fn main() { + /* not implemented for no_std */ +} diff --git a/crates/protocol/src/channel.rs b/crates/protocol/src/channel.rs index d17c17f6..d9056f4d 100644 --- a/crates/protocol/src/channel.rs +++ b/crates/protocol/src/channel.rs @@ -4,7 +4,7 @@ use alloc::{vec, vec::Vec}; use alloy_primitives::{map::HashMap, Bytes}; use op_alloy_genesis::RollupConfig; -use crate::{block::BlockInfo, frame::Frame, Batch}; +use crate::{block::BlockInfo, frame::Frame}; /// The frame overhead. const FRAME_V0_OVERHEAD: usize = 23; @@ -26,7 +26,7 @@ pub enum ChannelOutError { MissingData, /// An error from brotli compression. BrotliCompression, - /// An error encoding the [Batch]. + /// An error encoding the `Batch`. BatchEncoding, } @@ -57,10 +57,10 @@ impl<'a> ChannelOut<'a> { Self { id, config, rlp_length: 0, frame_number: 0, closed: false, compressed: None } } - /// Accepts the given [Batch] data into the [ChannelOut], compressing it + /// Accepts the given [crate::Batch] data into the [ChannelOut], compressing it /// into frames. #[cfg(feature = "std")] - pub fn add_batch(&mut self, batch: Batch) -> Result<(), ChannelOutError> { + pub fn add_batch(&mut self, batch: crate::Batch) -> Result<(), ChannelOutError> { if self.closed { return Err(ChannelOutError::ChannelClosed); } From 0e89908f34a6d058fe54efeb586262f92e7a44ec Mon Sep 17 00:00:00 2001 From: refcell Date: Fri, 15 Nov 2024 15:28:29 -0500 Subject: [PATCH 3/3] fix(protocol): rip out no_std brotli --- Cargo.toml | 1 - crates/protocol/Cargo.toml | 1 - crates/protocol/src/lib.rs | 5 +- crates/protocol/src/utils.rs | 114 +---------------------------------- 4 files changed, 2 insertions(+), 119 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c635bd12..6ecd4316 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,7 +81,6 @@ snap = "1.1.1" bincode = "1.3.3" ethereum_ssz = "0.8" brotli = { version = "7.0.0", default-features = false } -alloc-no-stdlib = "2.0.4" # rpc jsonrpsee = { version = "0.24", features = [ diff --git a/crates/protocol/Cargo.toml b/crates/protocol/Cargo.toml index 7b12d3f5..ad8f1802 100644 --- a/crates/protocol/Cargo.toml +++ b/crates/protocol/Cargo.toml @@ -27,7 +27,6 @@ alloy-consensus.workspace = true # Misc brotli.workspace = true -alloc-no-stdlib.workspace = true tracing.workspace = true derive_more.workspace = true async-trait.workspace = true diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index d0ec273d..c1f9f337 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -36,10 +36,7 @@ pub use iter::FrameIter; mod utils; #[cfg(feature = "std")] pub use utils::compress_brotli; -pub use utils::{ - compress_brotli_nostd, read_tx_data, starts_with_2718_deposit, to_system_config, - OpBlockConversionError, -}; +pub use utils::{read_tx_data, starts_with_2718_deposit, to_system_config, OpBlockConversionError}; mod channel; pub use channel::{ diff --git a/crates/protocol/src/utils.rs b/crates/protocol/src/utils.rs index 7b74dce8..bc53b5aa 100644 --- a/crates/protocol/src/utils.rs +++ b/crates/protocol/src/utils.rs @@ -1,26 +1,9 @@ //! Utility methods used by protocol types. -use alloc::{boxed::Box, vec, vec::Vec}; -use alloc_no_stdlib::*; +use alloc::{vec, vec::Vec}; use alloy_consensus::TxType; use alloy_primitives::B256; use alloy_rlp::{Buf, Header}; -use brotli::{ - enc::{ - cluster::HistogramPair, - command::Command, - compress_multi, - entropy_encode::HuffmanTree, - histogram::{ContextType, HistogramCommand, HistogramDistance, HistogramLiteral}, - pdf::PDF, - s16, - threading::SendAlloc, - v8, BrotliEncoderParams, BrotliEncoderThreadError, Owned, StaticCommand, UnionHasher, - ZopfliNode, - }, - CombiningAllocator, SliceWrapper, -}; -use core::ops; use op_alloy_consensus::{OpBlock, OpTxEnvelope}; use op_alloy_genesis::{RollupConfig, SystemConfig}; @@ -39,101 +22,6 @@ pub fn compress_brotli(mut input: &[u8]) -> Vec { output } -/// Compresses the given bytes data using the Brotli compressor implemented -/// in the [`brotli`][brotli] crate. -/// -/// [brotli]: https://crates.io/crates/brotli -#[allow(clippy::too_many_arguments)] -pub fn compress_brotli_nostd( - data: &'static [u8], - u8_buffer: &'static mut Box<[u8]>, - u16_buffer: &'static mut Box<[u16]>, - i32_buffer: &'static mut Box<[i32]>, - u32_buffer: &'static mut Box<[u32]>, - u64_buffer: &'static mut Box<[u64]>, - cmd_buffer: &'static mut Box<[Command]>, - pdf_buffer: &'static mut Box<[PDF]>, - static_buffer: &'static mut Box<[StaticCommand]>, - hist_buffer: &'static mut Box<[HistogramLiteral]>, - hcmd_buffer: &'static mut Box<[HistogramCommand]>, - hdist_buffer: &'static mut Box<[HistogramDistance]>, - hpair_buffer: &'static mut Box<[HistogramPair]>, - ctx_buffer: &'static mut Box<[ContextType]>, - huff_buffer: &'static mut Box<[HuffmanTree]>, - zop_buffer: &'static mut Box<[ZopfliNode]>, -) -> Result, BrotliEncoderThreadError> { - // Construct the allocator - declare_stack_allocator_struct!(MemPool, 4096, stack); - - let u8_allocator = MemPool::::new_allocator(u8_buffer, bzero); - let u16_allocator = MemPool::::new_allocator(u16_buffer, bzero); - let i32_allocator = MemPool::::new_allocator(i32_buffer, bzero); - let u32_allocator = MemPool::::new_allocator(u32_buffer, bzero); - let u64_allocator = MemPool::::new_allocator(u64_buffer, bzero); - let command_allocator = MemPool::::new_allocator(cmd_buffer, bzero); - let float_allocator = MemPool::::new_allocator(&mut [], bzero); - let v8_allocator = MemPool::::new_allocator(&mut [], bzero); - let s16_allocator = MemPool::::new_allocator(&mut [], bzero); - let pdf_allocator = MemPool::::new_allocator(pdf_buffer, bzero); - let static_allocator = MemPool::::new_allocator(static_buffer, bzero); - let hist_allocator = MemPool::::new_allocator(hist_buffer, bzero); - let hcmd_allocator = MemPool::::new_allocator(hcmd_buffer, bzero); - let hdist_allocator = MemPool::::new_allocator(hdist_buffer, bzero); - let hpair_allocator = MemPool::::new_allocator(hpair_buffer, bzero); - let ctx_allocator = MemPool::::new_allocator(ctx_buffer, bzero); - let huff_allocator = MemPool::::new_allocator(huff_buffer, bzero); - let zop_allocator = MemPool::::new_allocator(zop_buffer, bzero); - - let alloc = CombiningAllocator::new( - u8_allocator, - u16_allocator, - i32_allocator, - u32_allocator, - u64_allocator, - command_allocator, - float_allocator, - v8_allocator, - s16_allocator, - pdf_allocator, - static_allocator, - hist_allocator, - hcmd_allocator, - hdist_allocator, - hpair_allocator, - ctx_allocator, - huff_allocator, - zop_allocator, - ); - let alloc = SendAlloc::new(alloc, UnionHasher::default()); - - // Need a wrapper type around the input - struct SliceRef<'a>(&'a [u8]); - impl<'a> SliceWrapper for SliceRef<'a> { - fn slice(&self) -> &[u8] { - self.0 - } - } - - // Compression inputs - let params = BrotliEncoderParams::default(); - let mut output = vec![]; - let mut input = Owned::new(SliceRef(data)); - match compress_multi(¶ms, &mut input, output.as_mut_slice(), &mut [alloc]) { - Ok(_) => { - // if written == 0 { - // break; - // } - // continue; - } - Err(e) => { - // TODO: on out of space, resize the output buffer? - return Err(e); - } - } - - Ok(output) -} - /// Returns if the given `value` is a deposit transaction. pub fn starts_with_2718_deposit(value: &B) -> bool where