Skip to content

Commit f163b3d

Browse files
authored
feat: use alloy block types (#13518)
1 parent 9a062c0 commit f163b3d

File tree

8 files changed

+111
-388
lines changed

8 files changed

+111
-388
lines changed

bin/reth-bench/src/bench/new_payload_fcu.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use clap::Parser;
1818
use csv::Writer;
1919
use reth_cli_runner::CliContext;
2020
use reth_node_core::args::BenchmarkArgs;
21-
use reth_primitives::{Block, BlockExt};
21+
use reth_primitives::SealedBlock;
2222
use reth_rpc_types_compat::engine::payload::block_to_payload;
2323
use std::time::Instant;
2424
use tracing::{debug, info};
@@ -46,8 +46,7 @@ impl Command {
4646
let block_res =
4747
block_provider.get_block_by_number(next_block.into(), true.into()).await;
4848
let block = block_res.unwrap().unwrap();
49-
let block_hash = block.header.hash;
50-
let block = Block::try_from(block).unwrap().seal(block_hash);
49+
let block: SealedBlock = block.try_into().unwrap();
5150
let head_block_hash = block.hash();
5251
let safe_block_hash = block_provider
5352
.get_block_by_number(block.number.saturating_sub(32).into(), false.into());

bin/reth-bench/src/bench/new_payload_only.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use clap::Parser;
1616
use csv::Writer;
1717
use reth_cli_runner::CliContext;
1818
use reth_node_core::args::BenchmarkArgs;
19-
use reth_primitives::{Block, BlockExt};
19+
use reth_primitives::SealedBlock;
2020
use reth_rpc_types_compat::engine::payload::block_to_payload;
2121
use std::time::Instant;
2222
use tracing::{debug, info};
@@ -46,8 +46,7 @@ impl Command {
4646
let block_res =
4747
block_provider.get_block_by_number(next_block.into(), true.into()).await;
4848
let block = block_res.unwrap().unwrap();
49-
let block_hash = block.header.hash;
50-
let block = Block::try_from(block).unwrap().seal(block_hash);
49+
let block: SealedBlock = block.try_into().unwrap();
5150

5251
next_block += 1;
5352
sender.send(block).await.unwrap();

crates/optimism/consensus/src/validation.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub fn validate_block_post_execution(
2525
block.header.logs_bloom,
2626
receipts,
2727
chain_spec,
28-
block.timestamp,
28+
block.header.timestamp,
2929
) {
3030
tracing::debug!(%error, ?receipts, "receipts verification failed");
3131
return Err(error)
@@ -35,9 +35,9 @@ pub fn validate_block_post_execution(
3535
// Check if gas used matches the value set in header.
3636
let cumulative_gas_used =
3737
receipts.last().map(|receipt| receipt.cumulative_gas_used()).unwrap_or(0);
38-
if block.gas_used != cumulative_gas_used {
38+
if block.header.gas_used != cumulative_gas_used {
3939
return Err(ConsensusError::BlockGasUsed {
40-
gas: GotExpected { got: cumulative_gas_used, expected: block.gas_used },
40+
gas: GotExpected { got: cumulative_gas_used, expected: block.header.gas_used },
4141
gas_spent_by_tx: gas_spent_by_transactions(receipts),
4242
})
4343
}

crates/primitives-traits/src/serde_bincode_compat.rs

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use core::fmt::Debug;
2+
use serde::{de::DeserializeOwned, Serialize};
23

34
pub use super::header::{serde_bincode_compat as header, serde_bincode_compat::*};
4-
use serde::{de::DeserializeOwned, Serialize};
5+
pub use block_bincode::BlockBody;
56

67
/// Trait for types that can be serialized and deserialized using bincode.
78
pub trait SerdeBincodeCompat: Sized + 'static {
@@ -12,3 +13,82 @@ pub trait SerdeBincodeCompat: Sized + 'static {
1213
impl SerdeBincodeCompat for alloy_consensus::Header {
1314
type BincodeRepr<'a> = alloy_consensus::serde_bincode_compat::Header<'a>;
1415
}
16+
17+
mod block_bincode {
18+
use crate::serde_bincode_compat::SerdeBincodeCompat;
19+
use alloc::{borrow::Cow, vec::Vec};
20+
use alloy_consensus::serde_bincode_compat::Header;
21+
use alloy_eips::eip4895::Withdrawals;
22+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
23+
use serde_with::{DeserializeAs, SerializeAs};
24+
25+
/// Bincode-compatible [`alloy_consensus::BlockBody`] serde implementation.
26+
///
27+
/// Intended to use with the [`serde_with::serde_as`] macro in the following way:
28+
/// ```rust
29+
/// use reth_primitives_traits::serde_bincode_compat::{self, SerdeBincodeCompat};
30+
/// use serde::{Deserialize, Serialize};
31+
/// use serde_with::serde_as;
32+
///
33+
/// #[serde_as]
34+
/// #[derive(Serialize, Deserialize)]
35+
/// struct Data<T: SerdeBincodeCompat> {
36+
/// #[serde_as(as = "serde_bincode_compat::BlockBody<'_, T>")]
37+
/// body: alloy_consensus::BlockBody<T>,
38+
/// }
39+
/// ```
40+
#[derive(derive_more::Debug, Serialize, Deserialize)]
41+
#[debug(bound())]
42+
pub struct BlockBody<'a, T: SerdeBincodeCompat> {
43+
transactions: Vec<T::BincodeRepr<'a>>,
44+
ommers: Vec<Header<'a>>,
45+
withdrawals: Cow<'a, Option<Withdrawals>>,
46+
}
47+
48+
impl<'a, T: SerdeBincodeCompat> From<&'a alloy_consensus::BlockBody<T>> for BlockBody<'a, T> {
49+
fn from(value: &'a alloy_consensus::BlockBody<T>) -> Self {
50+
Self {
51+
transactions: value.transactions.iter().map(Into::into).collect(),
52+
ommers: value.ommers.iter().map(Into::into).collect(),
53+
withdrawals: Cow::Borrowed(&value.withdrawals),
54+
}
55+
}
56+
}
57+
58+
impl<'a, T: SerdeBincodeCompat> From<BlockBody<'a, T>> for alloy_consensus::BlockBody<T> {
59+
fn from(value: BlockBody<'a, T>) -> Self {
60+
Self {
61+
transactions: value.transactions.into_iter().map(Into::into).collect(),
62+
ommers: value.ommers.into_iter().map(Into::into).collect(),
63+
withdrawals: value.withdrawals.into_owned(),
64+
}
65+
}
66+
}
67+
68+
impl<T: SerdeBincodeCompat> SerializeAs<alloy_consensus::BlockBody<T>> for BlockBody<'_, T> {
69+
fn serialize_as<S>(
70+
source: &alloy_consensus::BlockBody<T>,
71+
serializer: S,
72+
) -> Result<S::Ok, S::Error>
73+
where
74+
S: Serializer,
75+
{
76+
BlockBody::from(source).serialize(serializer)
77+
}
78+
}
79+
80+
impl<'de, T: SerdeBincodeCompat> DeserializeAs<'de, alloy_consensus::BlockBody<T>>
81+
for BlockBody<'de, T>
82+
{
83+
fn deserialize_as<D>(deserializer: D) -> Result<alloy_consensus::BlockBody<T>, D::Error>
84+
where
85+
D: Deserializer<'de>,
86+
{
87+
BlockBody::deserialize(deserializer).map(Into::into)
88+
}
89+
}
90+
91+
impl<T: SerdeBincodeCompat> SerdeBincodeCompat for alloy_consensus::BlockBody<T> {
92+
type BincodeRepr<'a> = BlockBody<'a, T>;
93+
}
94+
}

crates/primitives/src/alloy_compat.rs

Lines changed: 10 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,25 @@
11
//! Common conversions from alloy types.
22
3-
use crate::{Block, BlockBody, Transaction, TransactionSigned};
4-
use alloc::{string::ToString, vec::Vec};
5-
use alloy_consensus::{constants::EMPTY_TRANSACTIONS, Header, TxEnvelope};
6-
use alloy_network::{AnyHeader, AnyRpcBlock, AnyRpcTransaction, AnyTxEnvelope};
3+
use crate::{BlockBody, SealedBlock, Transaction, TransactionSigned};
4+
use alloc::string::ToString;
5+
use alloy_consensus::TxEnvelope;
6+
use alloy_network::{AnyRpcBlock, AnyRpcTransaction, AnyTxEnvelope};
77
use alloy_serde::WithOtherFields;
88
use op_alloy_rpc_types as _;
9+
use reth_primitives_traits::SealedHeader;
910

10-
impl TryFrom<AnyRpcBlock> for Block {
11+
impl TryFrom<AnyRpcBlock> for SealedBlock {
1112
type Error = alloy_rpc_types::ConversionError;
1213

1314
fn try_from(block: AnyRpcBlock) -> Result<Self, Self::Error> {
14-
use alloy_rpc_types::ConversionError;
15-
1615
let block = block.inner;
17-
18-
let transactions = {
19-
let transactions: Result<Vec<TransactionSigned>, ConversionError> = match block
20-
.transactions
21-
{
22-
alloy_rpc_types::BlockTransactions::Full(transactions) => {
23-
transactions.into_iter().map(|tx| tx.try_into()).collect()
24-
}
25-
alloy_rpc_types::BlockTransactions::Hashes(_) |
26-
alloy_rpc_types::BlockTransactions::Uncle => {
27-
// alloy deserializes empty blocks into `BlockTransactions::Hashes`, if the tx
28-
// root is the empty root then we can just return an empty vec.
29-
if block.header.transactions_root == EMPTY_TRANSACTIONS {
30-
Ok(Vec::new())
31-
} else {
32-
Err(ConversionError::Custom("missing transactions".to_string()))
33-
}
34-
}
35-
};
36-
transactions?
37-
};
38-
39-
let AnyHeader {
40-
parent_hash,
41-
ommers_hash,
42-
beneficiary,
43-
state_root,
44-
transactions_root,
45-
receipts_root,
46-
logs_bloom,
47-
difficulty,
48-
number,
49-
gas_limit,
50-
gas_used,
51-
timestamp,
52-
extra_data,
53-
mix_hash,
54-
nonce,
55-
base_fee_per_gas,
56-
withdrawals_root,
57-
blob_gas_used,
58-
excess_blob_gas,
59-
parent_beacon_block_root,
60-
requests_hash,
61-
} = block.header.inner;
16+
let block_hash = block.header.hash;
17+
let block = block.try_map_transactions(|tx| tx.try_into())?;
6218

6319
Ok(Self {
64-
header: Header {
65-
parent_hash,
66-
ommers_hash,
67-
beneficiary,
68-
state_root,
69-
transactions_root,
70-
receipts_root,
71-
logs_bloom,
72-
difficulty,
73-
number,
74-
gas_limit,
75-
gas_used,
76-
timestamp,
77-
extra_data,
78-
mix_hash: mix_hash
79-
.ok_or_else(|| ConversionError::Custom("missing mixHash".to_string()))?,
80-
nonce: nonce.ok_or_else(|| ConversionError::Custom("missing nonce".to_string()))?,
81-
base_fee_per_gas,
82-
withdrawals_root,
83-
blob_gas_used,
84-
excess_blob_gas,
85-
parent_beacon_block_root,
86-
requests_hash,
87-
},
20+
header: SealedHeader::new(block.header.inner.into_header_with_defaults(), block_hash),
8821
body: BlockBody {
89-
transactions,
22+
transactions: block.transactions.into_transactions().collect(),
9023
ommers: Default::default(),
9124
withdrawals: block.withdrawals.map(|w| w.into_inner().into()),
9225
},

0 commit comments

Comments
 (0)