mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: use alloy block types (#13518)
This commit is contained in:
@ -18,7 +18,7 @@ use clap::Parser;
|
||||
use csv::Writer;
|
||||
use reth_cli_runner::CliContext;
|
||||
use reth_node_core::args::BenchmarkArgs;
|
||||
use reth_primitives::{Block, BlockExt};
|
||||
use reth_primitives::SealedBlock;
|
||||
use reth_rpc_types_compat::engine::payload::block_to_payload;
|
||||
use std::time::Instant;
|
||||
use tracing::{debug, info};
|
||||
@ -46,8 +46,7 @@ impl Command {
|
||||
let block_res =
|
||||
block_provider.get_block_by_number(next_block.into(), true.into()).await;
|
||||
let block = block_res.unwrap().unwrap();
|
||||
let block_hash = block.header.hash;
|
||||
let block = Block::try_from(block).unwrap().seal(block_hash);
|
||||
let block: SealedBlock = block.try_into().unwrap();
|
||||
let head_block_hash = block.hash();
|
||||
let safe_block_hash = block_provider
|
||||
.get_block_by_number(block.number.saturating_sub(32).into(), false.into());
|
||||
|
||||
@ -16,7 +16,7 @@ use clap::Parser;
|
||||
use csv::Writer;
|
||||
use reth_cli_runner::CliContext;
|
||||
use reth_node_core::args::BenchmarkArgs;
|
||||
use reth_primitives::{Block, BlockExt};
|
||||
use reth_primitives::SealedBlock;
|
||||
use reth_rpc_types_compat::engine::payload::block_to_payload;
|
||||
use std::time::Instant;
|
||||
use tracing::{debug, info};
|
||||
@ -46,8 +46,7 @@ impl Command {
|
||||
let block_res =
|
||||
block_provider.get_block_by_number(next_block.into(), true.into()).await;
|
||||
let block = block_res.unwrap().unwrap();
|
||||
let block_hash = block.header.hash;
|
||||
let block = Block::try_from(block).unwrap().seal(block_hash);
|
||||
let block: SealedBlock = block.try_into().unwrap();
|
||||
|
||||
next_block += 1;
|
||||
sender.send(block).await.unwrap();
|
||||
|
||||
@ -25,7 +25,7 @@ pub fn validate_block_post_execution(
|
||||
block.header.logs_bloom,
|
||||
receipts,
|
||||
chain_spec,
|
||||
block.timestamp,
|
||||
block.header.timestamp,
|
||||
) {
|
||||
tracing::debug!(%error, ?receipts, "receipts verification failed");
|
||||
return Err(error)
|
||||
@ -35,9 +35,9 @@ pub fn validate_block_post_execution(
|
||||
// Check if gas used matches the value set in header.
|
||||
let cumulative_gas_used =
|
||||
receipts.last().map(|receipt| receipt.cumulative_gas_used()).unwrap_or(0);
|
||||
if block.gas_used != cumulative_gas_used {
|
||||
if block.header.gas_used != cumulative_gas_used {
|
||||
return Err(ConsensusError::BlockGasUsed {
|
||||
gas: GotExpected { got: cumulative_gas_used, expected: block.gas_used },
|
||||
gas: GotExpected { got: cumulative_gas_used, expected: block.header.gas_used },
|
||||
gas_spent_by_tx: gas_spent_by_transactions(receipts),
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
use core::fmt::Debug;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
|
||||
pub use super::header::{serde_bincode_compat as header, serde_bincode_compat::*};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
pub use block_bincode::BlockBody;
|
||||
|
||||
/// Trait for types that can be serialized and deserialized using bincode.
|
||||
pub trait SerdeBincodeCompat: Sized + 'static {
|
||||
@ -12,3 +13,82 @@ pub trait SerdeBincodeCompat: Sized + 'static {
|
||||
impl SerdeBincodeCompat for alloy_consensus::Header {
|
||||
type BincodeRepr<'a> = alloy_consensus::serde_bincode_compat::Header<'a>;
|
||||
}
|
||||
|
||||
mod block_bincode {
|
||||
use crate::serde_bincode_compat::SerdeBincodeCompat;
|
||||
use alloc::{borrow::Cow, vec::Vec};
|
||||
use alloy_consensus::serde_bincode_compat::Header;
|
||||
use alloy_eips::eip4895::Withdrawals;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde_with::{DeserializeAs, SerializeAs};
|
||||
|
||||
/// Bincode-compatible [`alloy_consensus::BlockBody`] serde implementation.
|
||||
///
|
||||
/// Intended to use with the [`serde_with::serde_as`] macro in the following way:
|
||||
/// ```rust
|
||||
/// use reth_primitives_traits::serde_bincode_compat::{self, SerdeBincodeCompat};
|
||||
/// use serde::{Deserialize, Serialize};
|
||||
/// use serde_with::serde_as;
|
||||
///
|
||||
/// #[serde_as]
|
||||
/// #[derive(Serialize, Deserialize)]
|
||||
/// struct Data<T: SerdeBincodeCompat> {
|
||||
/// #[serde_as(as = "serde_bincode_compat::BlockBody<'_, T>")]
|
||||
/// body: alloy_consensus::BlockBody<T>,
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(derive_more::Debug, Serialize, Deserialize)]
|
||||
#[debug(bound())]
|
||||
pub struct BlockBody<'a, T: SerdeBincodeCompat> {
|
||||
transactions: Vec<T::BincodeRepr<'a>>,
|
||||
ommers: Vec<Header<'a>>,
|
||||
withdrawals: Cow<'a, Option<Withdrawals>>,
|
||||
}
|
||||
|
||||
impl<'a, T: SerdeBincodeCompat> From<&'a alloy_consensus::BlockBody<T>> for BlockBody<'a, T> {
|
||||
fn from(value: &'a alloy_consensus::BlockBody<T>) -> Self {
|
||||
Self {
|
||||
transactions: value.transactions.iter().map(Into::into).collect(),
|
||||
ommers: value.ommers.iter().map(Into::into).collect(),
|
||||
withdrawals: Cow::Borrowed(&value.withdrawals),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: SerdeBincodeCompat> From<BlockBody<'a, T>> for alloy_consensus::BlockBody<T> {
|
||||
fn from(value: BlockBody<'a, T>) -> Self {
|
||||
Self {
|
||||
transactions: value.transactions.into_iter().map(Into::into).collect(),
|
||||
ommers: value.ommers.into_iter().map(Into::into).collect(),
|
||||
withdrawals: value.withdrawals.into_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SerdeBincodeCompat> SerializeAs<alloy_consensus::BlockBody<T>> for BlockBody<'_, T> {
|
||||
fn serialize_as<S>(
|
||||
source: &alloy_consensus::BlockBody<T>,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
BlockBody::from(source).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, T: SerdeBincodeCompat> DeserializeAs<'de, alloy_consensus::BlockBody<T>>
|
||||
for BlockBody<'de, T>
|
||||
{
|
||||
fn deserialize_as<D>(deserializer: D) -> Result<alloy_consensus::BlockBody<T>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
BlockBody::deserialize(deserializer).map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SerdeBincodeCompat> SerdeBincodeCompat for alloy_consensus::BlockBody<T> {
|
||||
type BincodeRepr<'a> = BlockBody<'a, T>;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,92 +1,25 @@
|
||||
//! Common conversions from alloy types.
|
||||
|
||||
use crate::{Block, BlockBody, Transaction, TransactionSigned};
|
||||
use alloc::{string::ToString, vec::Vec};
|
||||
use alloy_consensus::{constants::EMPTY_TRANSACTIONS, Header, TxEnvelope};
|
||||
use alloy_network::{AnyHeader, AnyRpcBlock, AnyRpcTransaction, AnyTxEnvelope};
|
||||
use crate::{BlockBody, SealedBlock, Transaction, TransactionSigned};
|
||||
use alloc::string::ToString;
|
||||
use alloy_consensus::TxEnvelope;
|
||||
use alloy_network::{AnyRpcBlock, AnyRpcTransaction, AnyTxEnvelope};
|
||||
use alloy_serde::WithOtherFields;
|
||||
use op_alloy_rpc_types as _;
|
||||
use reth_primitives_traits::SealedHeader;
|
||||
|
||||
impl TryFrom<AnyRpcBlock> for Block {
|
||||
impl TryFrom<AnyRpcBlock> for SealedBlock {
|
||||
type Error = alloy_rpc_types::ConversionError;
|
||||
|
||||
fn try_from(block: AnyRpcBlock) -> Result<Self, Self::Error> {
|
||||
use alloy_rpc_types::ConversionError;
|
||||
|
||||
let block = block.inner;
|
||||
|
||||
let transactions = {
|
||||
let transactions: Result<Vec<TransactionSigned>, ConversionError> = match block
|
||||
.transactions
|
||||
{
|
||||
alloy_rpc_types::BlockTransactions::Full(transactions) => {
|
||||
transactions.into_iter().map(|tx| tx.try_into()).collect()
|
||||
}
|
||||
alloy_rpc_types::BlockTransactions::Hashes(_) |
|
||||
alloy_rpc_types::BlockTransactions::Uncle => {
|
||||
// alloy deserializes empty blocks into `BlockTransactions::Hashes`, if the tx
|
||||
// root is the empty root then we can just return an empty vec.
|
||||
if block.header.transactions_root == EMPTY_TRANSACTIONS {
|
||||
Ok(Vec::new())
|
||||
} else {
|
||||
Err(ConversionError::Custom("missing transactions".to_string()))
|
||||
}
|
||||
}
|
||||
};
|
||||
transactions?
|
||||
};
|
||||
|
||||
let AnyHeader {
|
||||
parent_hash,
|
||||
ommers_hash,
|
||||
beneficiary,
|
||||
state_root,
|
||||
transactions_root,
|
||||
receipts_root,
|
||||
logs_bloom,
|
||||
difficulty,
|
||||
number,
|
||||
gas_limit,
|
||||
gas_used,
|
||||
timestamp,
|
||||
extra_data,
|
||||
mix_hash,
|
||||
nonce,
|
||||
base_fee_per_gas,
|
||||
withdrawals_root,
|
||||
blob_gas_used,
|
||||
excess_blob_gas,
|
||||
parent_beacon_block_root,
|
||||
requests_hash,
|
||||
} = block.header.inner;
|
||||
let block_hash = block.header.hash;
|
||||
let block = block.try_map_transactions(|tx| tx.try_into())?;
|
||||
|
||||
Ok(Self {
|
||||
header: Header {
|
||||
parent_hash,
|
||||
ommers_hash,
|
||||
beneficiary,
|
||||
state_root,
|
||||
transactions_root,
|
||||
receipts_root,
|
||||
logs_bloom,
|
||||
difficulty,
|
||||
number,
|
||||
gas_limit,
|
||||
gas_used,
|
||||
timestamp,
|
||||
extra_data,
|
||||
mix_hash: mix_hash
|
||||
.ok_or_else(|| ConversionError::Custom("missing mixHash".to_string()))?,
|
||||
nonce: nonce.ok_or_else(|| ConversionError::Custom("missing nonce".to_string()))?,
|
||||
base_fee_per_gas,
|
||||
withdrawals_root,
|
||||
blob_gas_used,
|
||||
excess_blob_gas,
|
||||
parent_beacon_block_root,
|
||||
requests_hash,
|
||||
},
|
||||
header: SealedHeader::new(block.header.inner.into_header_with_defaults(), block_hash),
|
||||
body: BlockBody {
|
||||
transactions,
|
||||
transactions: block.transactions.into_transactions().collect(),
|
||||
ommers: Default::default(),
|
||||
withdrawals: block.withdrawals.map(|w| w.into_inner().into()),
|
||||
},
|
||||
|
||||
@ -3,66 +3,25 @@ use crate::{
|
||||
RecoveredTx, SealedHeader, TransactionSigned,
|
||||
};
|
||||
use alloc::vec::Vec;
|
||||
use alloy_consensus::{Header, Typed2718};
|
||||
use alloy_consensus::Header;
|
||||
use alloy_eips::{eip2718::Encodable2718, eip4895::Withdrawals};
|
||||
use alloy_primitives::{Address, Bytes, B256};
|
||||
use alloy_rlp::{Decodable, Encodable, RlpDecodable, RlpEncodable};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
pub use reth_primitives_traits::test_utils::{generate_valid_header, valid_header_strategy};
|
||||
use reth_primitives_traits::{BlockBody as _, InMemorySize, SignedTransaction, Transaction};
|
||||
use reth_primitives_traits::{BlockBody as _, InMemorySize, SignedTransaction};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Ethereum full block.
|
||||
///
|
||||
/// Withdrawals can be optionally included at the end of the RLP encoded message.
|
||||
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(rlp, 25))]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Deref)]
|
||||
pub struct Block<T = TransactionSigned> {
|
||||
/// Block header.
|
||||
#[deref]
|
||||
pub header: Header,
|
||||
/// Block body.
|
||||
pub body: BlockBody<T>,
|
||||
}
|
||||
pub type Block<T = TransactionSigned> = alloy_consensus::Block<T>;
|
||||
|
||||
impl<T> Default for Block<T> {
|
||||
fn default() -> Self {
|
||||
Self { header: Default::default(), body: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> reth_primitives_traits::Block for Block<T>
|
||||
where
|
||||
T: SignedTransaction,
|
||||
{
|
||||
type Header = Header;
|
||||
type Body = BlockBody<T>;
|
||||
|
||||
fn new(header: Self::Header, body: Self::Body) -> Self {
|
||||
Self { header, body }
|
||||
}
|
||||
|
||||
fn header(&self) -> &Self::Header {
|
||||
&self.header
|
||||
}
|
||||
|
||||
fn body(&self) -> &Self::Body {
|
||||
&self.body
|
||||
}
|
||||
|
||||
fn split(self) -> (Self::Header, Self::Body) {
|
||||
(self.header, self.body)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: InMemorySize> InMemorySize for Block<T> {
|
||||
/// Calculates a heuristic for the in-memory size of the [`Block`].
|
||||
#[inline]
|
||||
fn size(&self) -> usize {
|
||||
self.header.size() + self.body.size()
|
||||
}
|
||||
}
|
||||
/// A response to `GetBlockBodies`, containing bodies if any bodies were found.
|
||||
///
|
||||
/// Withdrawals can be optionally included at the end of the RLP encoded message.
|
||||
pub type BlockBody<T = TransactionSigned> = alloy_consensus::BlockBody<T>;
|
||||
|
||||
/// We need to implement RLP traits manually because we currently don't have a way to flatten
|
||||
/// [`BlockBody`] into [`Block`].
|
||||
@ -102,13 +61,6 @@ mod block_rlp {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Decodable> Decodable for Block<T> {
|
||||
fn decode(b: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
let Helper { header, transactions, ommers, withdrawals } = Helper::decode(b)?;
|
||||
Ok(Self { header, body: BlockBody { transactions, ommers, withdrawals } })
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for SealedBlock {
|
||||
fn decode(b: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
let Helper { header, transactions, ommers, withdrawals } = Helper::decode(b)?;
|
||||
@ -116,18 +68,6 @@ mod block_rlp {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Encodable> Encodable for Block<T> {
|
||||
fn encode(&self, out: &mut dyn bytes::BufMut) {
|
||||
let helper: HelperRef<'_, _, _> = self.into();
|
||||
helper.encode(out)
|
||||
}
|
||||
|
||||
fn length(&self) -> usize {
|
||||
let helper: HelperRef<'_, _, _> = self.into();
|
||||
helper.length()
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for SealedBlock {
|
||||
fn encode(&self, out: &mut dyn bytes::BufMut) {
|
||||
let helper: HelperRef<'_, _, _> = self.into();
|
||||
@ -141,24 +81,6 @@ mod block_rlp {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
impl<'a> arbitrary::Arbitrary<'a> for Block {
|
||||
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||
// first generate up to 100 txs
|
||||
let transactions = (0..100)
|
||||
.map(|_| TransactionSigned::arbitrary(u))
|
||||
.collect::<arbitrary::Result<Vec<_>>>()?;
|
||||
|
||||
// then generate up to 2 ommers
|
||||
let ommers = (0..2).map(|_| Header::arbitrary(u)).collect::<arbitrary::Result<Vec<_>>>()?;
|
||||
|
||||
Ok(Self {
|
||||
header: u.arbitrary()?,
|
||||
body: BlockBody { transactions, ommers, withdrawals: u.arbitrary()? },
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Sealed block with senders recovered from transactions.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default, Deref, DerefMut)]
|
||||
pub struct BlockWithSenders<B = Block> {
|
||||
@ -565,154 +487,10 @@ impl<'a> arbitrary::Arbitrary<'a> for SealedBlockWithSenders {
|
||||
}
|
||||
}
|
||||
|
||||
/// A response to `GetBlockBodies`, containing bodies if any bodies were found.
|
||||
///
|
||||
/// Withdrawals can be optionally included at the end of the RLP encoded message.
|
||||
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(rlp, 10))]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, RlpEncodable, RlpDecodable)]
|
||||
#[rlp(trailing)]
|
||||
pub struct BlockBody<T = TransactionSigned> {
|
||||
/// Transactions in the block
|
||||
pub transactions: Vec<T>,
|
||||
/// Uncle headers for the given block
|
||||
pub ommers: Vec<Header>,
|
||||
/// Withdrawals in the block.
|
||||
pub withdrawals: Option<Withdrawals>,
|
||||
}
|
||||
|
||||
impl<T> Default for BlockBody<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
transactions: Default::default(),
|
||||
ommers: Default::default(),
|
||||
withdrawals: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockBody {
|
||||
/// Create a [`Block`] from the body and its header.
|
||||
pub const fn into_block(self, header: Header) -> Block {
|
||||
Block { header, body: self }
|
||||
}
|
||||
|
||||
/// Returns an iterator over all blob versioned hashes from the block body.
|
||||
#[inline]
|
||||
pub fn blob_versioned_hashes_iter(&self) -> impl Iterator<Item = &B256> + '_ {
|
||||
self.eip4844_transactions_iter()
|
||||
.filter_map(|tx| tx.as_eip4844().map(|blob_tx| &blob_tx.blob_versioned_hashes))
|
||||
.flatten()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> BlockBody<T> {
|
||||
/// Calculate the ommers root for the block body.
|
||||
pub fn calculate_ommers_root(&self) -> B256 {
|
||||
crate::proofs::calculate_ommers_root(&self.ommers)
|
||||
}
|
||||
|
||||
/// Calculate the withdrawals root for the block body, if withdrawals exist. If there are no
|
||||
/// withdrawals, this will return `None`.
|
||||
pub fn calculate_withdrawals_root(&self) -> Option<B256> {
|
||||
self.withdrawals.as_ref().map(|w| crate::proofs::calculate_withdrawals_root(w))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Transaction> BlockBody<T> {
|
||||
/// Returns whether or not the block body contains any blob transactions.
|
||||
#[inline]
|
||||
pub fn has_eip4844_transactions(&self) -> bool {
|
||||
self.transactions.iter().any(|tx| tx.is_eip4844())
|
||||
}
|
||||
|
||||
/// Returns whether or not the block body contains any EIP-7702 transactions.
|
||||
#[inline]
|
||||
pub fn has_eip7702_transactions(&self) -> bool {
|
||||
self.transactions.iter().any(|tx| tx.is_eip7702())
|
||||
}
|
||||
|
||||
/// Returns an iterator over all blob transactions of the block
|
||||
#[inline]
|
||||
pub fn eip4844_transactions_iter(&self) -> impl Iterator<Item = &T> + '_ {
|
||||
self.transactions.iter().filter(|tx| tx.is_eip4844())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: InMemorySize> InMemorySize for BlockBody<T> {
|
||||
/// Calculates a heuristic for the in-memory size of the [`BlockBody`].
|
||||
#[inline]
|
||||
fn size(&self) -> usize {
|
||||
self.transactions.iter().map(T::size).sum::<usize>() +
|
||||
self.transactions.capacity() * core::mem::size_of::<T>() +
|
||||
self.ommers.iter().map(Header::size).sum::<usize>() +
|
||||
self.ommers.capacity() * core::mem::size_of::<Header>() +
|
||||
self.withdrawals
|
||||
.as_ref()
|
||||
.map_or(core::mem::size_of::<Option<Withdrawals>>(), Withdrawals::total_size)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> reth_primitives_traits::BlockBody for BlockBody<T>
|
||||
where
|
||||
T: SignedTransaction,
|
||||
{
|
||||
type Transaction = T;
|
||||
type OmmerHeader = Header;
|
||||
|
||||
fn transactions(&self) -> &[Self::Transaction] {
|
||||
&self.transactions
|
||||
}
|
||||
|
||||
fn into_transactions(self) -> Vec<Self::Transaction> {
|
||||
self.transactions
|
||||
}
|
||||
|
||||
fn withdrawals(&self) -> Option<&Withdrawals> {
|
||||
self.withdrawals.as_ref()
|
||||
}
|
||||
|
||||
fn ommers(&self) -> Option<&[Self::OmmerHeader]> {
|
||||
Some(&self.ommers)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Block> for BlockBody {
|
||||
fn from(block: Block) -> Self {
|
||||
Self {
|
||||
transactions: block.body.transactions,
|
||||
ommers: block.body.ommers,
|
||||
withdrawals: block.body.withdrawals,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
impl<'a> arbitrary::Arbitrary<'a> for BlockBody {
|
||||
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||
// first generate up to 100 txs
|
||||
let transactions = (0..100)
|
||||
.map(|_| TransactionSigned::arbitrary(u))
|
||||
.collect::<arbitrary::Result<Vec<_>>>()?;
|
||||
|
||||
// then generate up to 2 ommers
|
||||
let ommers = (0..2)
|
||||
.map(|_| {
|
||||
let header = Header::arbitrary(u)?;
|
||||
|
||||
Ok(header)
|
||||
})
|
||||
.collect::<arbitrary::Result<Vec<_>>>()?;
|
||||
|
||||
Ok(Self { transactions, ommers, withdrawals: u.arbitrary()? })
|
||||
}
|
||||
}
|
||||
|
||||
/// Bincode-compatible block type serde implementations.
|
||||
#[cfg(feature = "serde-bincode-compat")]
|
||||
pub(super) mod serde_bincode_compat {
|
||||
use alloc::{borrow::Cow, vec::Vec};
|
||||
use alloy_consensus::serde_bincode_compat::Header;
|
||||
use alloy_eips::eip4895::Withdrawals;
|
||||
use alloy_primitives::Address;
|
||||
use reth_primitives_traits::{
|
||||
serde_bincode_compat::{SealedHeader, SerdeBincodeCompat},
|
||||
@ -722,69 +500,8 @@ pub(super) mod serde_bincode_compat {
|
||||
use serde_with::{DeserializeAs, SerializeAs};
|
||||
|
||||
/// Bincode-compatible [`super::BlockBody`] serde implementation.
|
||||
///
|
||||
/// Intended to use with the [`serde_with::serde_as`] macro in the following way:
|
||||
/// ```rust
|
||||
/// use reth_primitives::{serde_bincode_compat, BlockBody};
|
||||
/// use serde::{Deserialize, Serialize};
|
||||
/// use serde_with::serde_as;
|
||||
///
|
||||
/// #[serde_as]
|
||||
/// #[derive(Serialize, Deserialize)]
|
||||
/// struct Data {
|
||||
/// #[serde_as(as = "serde_bincode_compat::BlockBody")]
|
||||
/// body: BlockBody,
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(derive_more::Debug, Serialize, Deserialize)]
|
||||
#[debug(bound())]
|
||||
pub struct BlockBody<'a, T: SerdeBincodeCompat = super::TransactionSigned> {
|
||||
transactions: Vec<T::BincodeRepr<'a>>,
|
||||
ommers: Vec<Header<'a>>,
|
||||
withdrawals: Cow<'a, Option<Withdrawals>>,
|
||||
}
|
||||
|
||||
impl<'a, T: SerdeBincodeCompat> From<&'a super::BlockBody<T>> for BlockBody<'a, T> {
|
||||
fn from(value: &'a super::BlockBody<T>) -> Self {
|
||||
Self {
|
||||
transactions: value.transactions.iter().map(Into::into).collect(),
|
||||
ommers: value.ommers.iter().map(Into::into).collect(),
|
||||
withdrawals: Cow::Borrowed(&value.withdrawals),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: SerdeBincodeCompat> From<BlockBody<'a, T>> for super::BlockBody<T> {
|
||||
fn from(value: BlockBody<'a, T>) -> Self {
|
||||
Self {
|
||||
transactions: value.transactions.into_iter().map(Into::into).collect(),
|
||||
ommers: value.ommers.into_iter().map(Into::into).collect(),
|
||||
withdrawals: value.withdrawals.into_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SerializeAs<super::BlockBody> for BlockBody<'_> {
|
||||
fn serialize_as<S>(source: &super::BlockBody, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
BlockBody::from(source).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> DeserializeAs<'de, super::BlockBody> for BlockBody<'de> {
|
||||
fn deserialize_as<D>(deserializer: D) -> Result<super::BlockBody, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
BlockBody::deserialize(deserializer).map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SerdeBincodeCompat> SerdeBincodeCompat for super::BlockBody<T> {
|
||||
type BincodeRepr<'a> = BlockBody<'a, T>;
|
||||
}
|
||||
pub type BlockBody<'a, T = super::TransactionSigned> =
|
||||
reth_primitives_traits::serde_bincode_compat::BlockBody<'a, T>;
|
||||
|
||||
/// Bincode-compatible [`super::SealedBlock`] serde implementation.
|
||||
///
|
||||
@ -918,7 +635,6 @@ pub(super) mod serde_bincode_compat {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::{serde_bincode_compat, BlockBody, SealedBlock, SealedBlockWithSenders};
|
||||
|
||||
use arbitrary::Arbitrary;
|
||||
use rand::Rng;
|
||||
use reth_testing_utils::generators;
|
||||
|
||||
@ -146,7 +146,6 @@ impl PruneInput {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use alloy_primitives::B256;
|
||||
use reth_primitives_traits::BlockBody;
|
||||
use reth_provider::{
|
||||
providers::BlockchainProvider2,
|
||||
test_utils::{create_test_provider_factory, MockEthProvider},
|
||||
@ -243,8 +242,7 @@ mod tests {
|
||||
let range = input.get_next_tx_num_range(&provider).expect("Expected range").unwrap();
|
||||
|
||||
// Calculate the total number of transactions
|
||||
let num_txs =
|
||||
blocks.iter().map(|block| block.body.transactions().len() as u64).sum::<u64>();
|
||||
let num_txs = blocks.iter().map(|block| block.body.transactions.len() as u64).sum::<u64>();
|
||||
|
||||
assert_eq!(range, 0..=num_txs - 1);
|
||||
}
|
||||
@ -290,8 +288,7 @@ mod tests {
|
||||
let range = input.get_next_tx_num_range(&provider).expect("Expected range").unwrap();
|
||||
|
||||
// Calculate the total number of transactions
|
||||
let num_txs =
|
||||
blocks.iter().map(|block| block.body.transactions().len() as u64).sum::<u64>();
|
||||
let num_txs = blocks.iter().map(|block| block.body.transactions.len() as u64).sum::<u64>();
|
||||
|
||||
assert_eq!(range, 0..=num_txs - 1,);
|
||||
}
|
||||
@ -325,8 +322,7 @@ mod tests {
|
||||
|
||||
// Get the last tx number
|
||||
// Calculate the total number of transactions
|
||||
let num_txs =
|
||||
blocks.iter().map(|block| block.body.transactions().len() as u64).sum::<u64>();
|
||||
let num_txs = blocks.iter().map(|block| block.body.transactions.len() as u64).sum::<u64>();
|
||||
let max_range = num_txs - 1;
|
||||
|
||||
// Create a prune input with a previous checkpoint that is the last tx number
|
||||
|
||||
@ -907,7 +907,7 @@ mod tests {
|
||||
transactions_writer.increment_block(block.number)?;
|
||||
receipts_writer.increment_block(block.number)?;
|
||||
|
||||
for (tx, receipt) in block.body.transactions().iter().zip(receipts) {
|
||||
for (tx, receipt) in block.body().transactions().zip(receipts) {
|
||||
transactions_writer.append_transaction(tx_num, tx)?;
|
||||
receipts_writer.append_receipt(tx_num, receipt)?;
|
||||
tx_num += 1;
|
||||
|
||||
Reference in New Issue
Block a user