mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
Compare commits
7 Commits
nb-2025100
...
05fc0df236
| Author | SHA1 | Date | |
|---|---|---|---|
| 05fc0df236 | |||
| bcdf4d933d | |||
| 2390ed864a | |||
| 567d6ce2e4 | |||
| 8b2c3a4a34 | |||
| 92759f04db | |||
| 71bb70bca6 |
@ -23,7 +23,7 @@ use jsonrpsee::{PendingSubscriptionSink, SubscriptionMessage, SubscriptionSink,
|
||||
use jsonrpsee_core::{RpcResult, async_trait};
|
||||
use jsonrpsee_types::{ErrorObject, error::INTERNAL_ERROR_CODE};
|
||||
use reth::{api::FullNodeComponents, builder::rpc::RpcContext, tasks::TaskSpawner};
|
||||
use reth_primitives_traits::{BlockBody as _, SignedTransaction};
|
||||
use reth_primitives_traits::SignedTransaction;
|
||||
use reth_provider::{BlockIdReader, BlockReader, BlockReaderIdExt, ReceiptProvider};
|
||||
use reth_rpc::{EthFilter, EthPubSub, RpcTypes, eth::pubsub::SubscriptionSerializeError};
|
||||
use reth_rpc_eth_api::{
|
||||
@ -32,6 +32,7 @@ use reth_rpc_eth_api::{
|
||||
helpers::{EthBlocks, EthTransactions, LoadReceipt},
|
||||
transaction::ConvertReceiptInput,
|
||||
};
|
||||
use reth_rpc_eth_types::EthApiError;
|
||||
use serde::Serialize;
|
||||
use std::{marker::PhantomData, sync::Arc};
|
||||
use tokio_stream::{Stream, StreamExt};
|
||||
@ -578,9 +579,9 @@ async fn adjust_transaction_receipt<Eth: EthWrapper>(
|
||||
// This function assumes that `block_id` is already validated by the caller.
|
||||
fn system_tx_count_for_block<Eth: EthWrapper>(eth_api: &Eth, block_id: BlockId) -> usize {
|
||||
let provider = eth_api.provider();
|
||||
let block = provider.block_by_id(block_id).unwrap().unwrap();
|
||||
let header = provider.header_by_id(block_id).unwrap().unwrap();
|
||||
|
||||
block.body.transactions().iter().filter(|tx| tx.is_system_transaction()).count()
|
||||
header.extras.system_tx_count.try_into().unwrap()
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@ -654,6 +655,9 @@ where
|
||||
block_id: BlockId,
|
||||
) -> RpcResult<Option<Vec<RpcReceipt<Eth::NetworkTypes>>>> {
|
||||
trace!(target: "rpc::eth", ?block_id, "Serving eth_getBlockReceipts");
|
||||
if self.eth_api.provider().block_by_id(block_id).map_err(EthApiError::from)?.is_none() {
|
||||
return Ok(None);
|
||||
}
|
||||
let result =
|
||||
adjust_block_receipts(block_id, &*self.eth_api).instrument(engine_span!()).await?;
|
||||
Ok(result.map(|(_, receipts)| receipts))
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
pub mod hl;
|
||||
pub mod parser;
|
||||
|
||||
use crate::hardforks::HlHardforks;
|
||||
use alloy_consensus::Header;
|
||||
use crate::{hardforks::HlHardforks, node::primitives::{header::HlHeaderExtras, HlHeader}};
|
||||
use alloy_eips::eip7840::BlobParams;
|
||||
use alloy_genesis::Genesis;
|
||||
use alloy_primitives::{Address, B256, U256};
|
||||
@ -20,10 +19,11 @@ pub const TESTNET_CHAIN_ID: u64 = 998;
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
pub struct HlChainSpec {
|
||||
pub inner: ChainSpec,
|
||||
pub genesis_header: HlHeader,
|
||||
}
|
||||
|
||||
impl EthChainSpec for HlChainSpec {
|
||||
type Header = Header;
|
||||
type Header = HlHeader;
|
||||
|
||||
fn blob_params_at_timestamp(&self, timestamp: u64) -> Option<BlobParams> {
|
||||
self.inner.blob_params_at_timestamp(timestamp)
|
||||
@ -57,8 +57,8 @@ impl EthChainSpec for HlChainSpec {
|
||||
Box::new(self.inner.display_hardforks())
|
||||
}
|
||||
|
||||
fn genesis_header(&self) -> &Header {
|
||||
self.inner.genesis_header()
|
||||
fn genesis_header(&self) -> &HlHeader {
|
||||
&self.genesis_header
|
||||
}
|
||||
|
||||
fn genesis(&self) -> &Genesis {
|
||||
@ -127,4 +127,10 @@ impl HlChainSpec {
|
||||
_ => unreachable!("Unreachable since ChainSpecParser won't return other chains"),
|
||||
}
|
||||
}
|
||||
|
||||
fn new(inner: ChainSpec) -> Self {
|
||||
let genesis_header =
|
||||
HlHeader { inner: inner.genesis_header().clone(), extras: HlHeaderExtras::default() };
|
||||
Self { inner, genesis_header }
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,8 +26,8 @@ impl ChainSpecParser for HlChainSpecParser {
|
||||
/// Currently only mainnet is supported.
|
||||
pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<HlChainSpec>> {
|
||||
match s {
|
||||
"mainnet" => Ok(Arc::new(HlChainSpec { inner: hl_mainnet() })),
|
||||
"testnet" => Ok(Arc::new(HlChainSpec { inner: hl_testnet() })),
|
||||
"mainnet" => Ok(Arc::new(HlChainSpec::new(hl_mainnet()))),
|
||||
"testnet" => Ok(Arc::new(HlChainSpec::new(hl_testnet()))),
|
||||
_ => Err(eyre::eyre!("Unsupported chain: {}", s)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,36 +7,12 @@ use alloy_primitives::keccak256;
|
||||
use revm::{
|
||||
context::Host,
|
||||
interpreter::{
|
||||
InstructionContext, InterpreterTypes, as_u64_saturated, interpreter_types::StackTr,
|
||||
_count, InstructionContext, InterpreterTypes, as_u64_saturated, interpreter_types::StackTr,
|
||||
popn_top,
|
||||
},
|
||||
primitives::{BLOCK_HASH_HISTORY, U256},
|
||||
};
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
#[collapse_debuginfo(yes)]
|
||||
macro_rules! _count {
|
||||
(@count) => { 0 };
|
||||
(@count $head:tt $($tail:tt)*) => { 1 + _count!(@count $($tail)*) };
|
||||
($($arg:tt)*) => { _count!(@count $($arg)*) };
|
||||
}
|
||||
|
||||
/// Pops n values from the stack and returns the top value. Fails the instruction if n values can't
|
||||
/// be popped.
|
||||
#[macro_export]
|
||||
#[collapse_debuginfo(yes)]
|
||||
macro_rules! popn_top {
|
||||
([ $($x:ident),* ], $top:ident, $interpreter:expr $(,$ret:expr)? ) => {
|
||||
// Workaround for https://github.com/rust-lang/rust/issues/144329.
|
||||
if $interpreter.stack.len() < (1 + $crate::_count!($($x)*)) {
|
||||
$interpreter.halt_underflow();
|
||||
return $($ret)?;
|
||||
}
|
||||
let ([$( $x ),*], $top) = unsafe { $interpreter.stack.popn_top().unwrap_unchecked() };
|
||||
};
|
||||
}
|
||||
|
||||
/// Implements the BLOCKHASH instruction.
|
||||
///
|
||||
/// Gets the hash of one of the 256 most recent complete blocks.
|
||||
|
||||
@ -7,4 +7,4 @@ pub mod node;
|
||||
pub mod pseudo_peer;
|
||||
pub mod version;
|
||||
|
||||
pub use node::primitives::{HlBlock, HlBlockBody, HlPrimitives};
|
||||
pub use node::primitives::{HlBlock, HlBlockBody, HlHeader, HlPrimitives};
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
use crate::{HlBlock, HlBlockBody, HlPrimitives, hardforks::HlHardforks, node::HlNode};
|
||||
use alloy_consensus::Header;
|
||||
use crate::{hardforks::HlHardforks, node::{primitives::HlHeader, HlNode}, HlBlock, HlBlockBody, HlPrimitives};
|
||||
use reth::{
|
||||
api::{FullNodeTypes, NodeTypes},
|
||||
beacon_consensus::EthBeaconConsensus,
|
||||
@ -101,14 +100,14 @@ where
|
||||
|
||||
impl<ChainSpec> Consensus<HlBlock> for HlConsensus<ChainSpec>
|
||||
where
|
||||
ChainSpec: EthChainSpec<Header = Header> + HlHardforks,
|
||||
ChainSpec: EthChainSpec<Header = HlHeader> + HlHardforks,
|
||||
{
|
||||
type Error = ConsensusError;
|
||||
|
||||
fn validate_body_against_header(
|
||||
&self,
|
||||
body: &HlBlockBody,
|
||||
header: &SealedHeader,
|
||||
header: &SealedHeader<HlHeader>,
|
||||
) -> Result<(), ConsensusError> {
|
||||
Consensus::<HlBlock>::validate_body_against_header(&self.inner, body, header)
|
||||
}
|
||||
@ -148,7 +147,7 @@ mod reth_copy;
|
||||
|
||||
impl<ChainSpec> FullConsensus<HlPrimitives> for HlConsensus<ChainSpec>
|
||||
where
|
||||
ChainSpec: EthChainSpec<Header = Header> + HlHardforks,
|
||||
ChainSpec: EthChainSpec<Header = HlHeader> + HlHardforks,
|
||||
{
|
||||
fn validate_block_post_execution(
|
||||
&self,
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
//! Copy of reth codebase.
|
||||
|
||||
use crate::HlBlock;
|
||||
use alloy_consensus::{BlockHeader, TxReceipt, proofs::calculate_receipt_root};
|
||||
use alloy_eips::eip7685::Requests;
|
||||
use alloy_primitives::{B256, Bloom};
|
||||
use reth::consensus::ConsensusError;
|
||||
use reth_chainspec::EthereumHardforks;
|
||||
use reth_primitives::{GotExpected, RecoveredBlock, gas_spent_by_transactions};
|
||||
use reth_primitives_traits::{Block, Receipt as ReceiptTrait};
|
||||
use reth_primitives_traits::Receipt as ReceiptTrait;
|
||||
|
||||
pub fn validate_block_post_execution<B, R, ChainSpec>(
|
||||
block: &RecoveredBlock<B>,
|
||||
pub fn validate_block_post_execution<R, ChainSpec>(
|
||||
block: &RecoveredBlock<HlBlock>,
|
||||
chain_spec: &ChainSpec,
|
||||
receipts: &[R],
|
||||
requests: &Requests,
|
||||
) -> Result<(), ConsensusError>
|
||||
where
|
||||
B: Block,
|
||||
R: ReceiptTrait,
|
||||
ChainSpec: EthereumHardforks,
|
||||
{
|
||||
@ -42,7 +42,7 @@ where
|
||||
receipts.iter().filter(|&r| r.cumulative_gas_used() != 0).cloned().collect::<Vec<_>>();
|
||||
if let Err(error) = verify_receipts(
|
||||
block.header().receipts_root(),
|
||||
block.header().logs_bloom(),
|
||||
block.header().inner.logs_bloom(),
|
||||
&receipts_for_root,
|
||||
) {
|
||||
tracing::debug!(%error, ?receipts, "receipts verification failed");
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
use crate::{
|
||||
HlBlock,
|
||||
node::evm::config::{HlBlockExecutorFactory, HlEvmConfig},
|
||||
node::evm::config::{HlBlockExecutorFactory, HlEvmConfig}, HlBlock, HlHeader
|
||||
};
|
||||
use alloy_consensus::Header;
|
||||
use reth_evm::{
|
||||
block::BlockExecutionError,
|
||||
execute::{BlockAssembler, BlockAssemblerInput},
|
||||
@ -13,7 +11,7 @@ impl BlockAssembler<HlBlockExecutorFactory> for HlEvmConfig {
|
||||
|
||||
fn assemble_block(
|
||||
&self,
|
||||
input: BlockAssemblerInput<'_, '_, HlBlockExecutorFactory, Header>,
|
||||
input: BlockAssemblerInput<'_, '_, HlBlockExecutorFactory, HlHeader>,
|
||||
) -> Result<Self::Block, BlockExecutionError> {
|
||||
let HlBlock { header, body } = self.block_assembler.assemble_block(input)?;
|
||||
Ok(HlBlock { header, body })
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use super::{executor::HlBlockExecutor, factory::HlEvmFactory};
|
||||
use crate::{
|
||||
HlBlock, HlBlockBody, HlPrimitives,
|
||||
HlBlock, HlBlockBody, HlHeader, HlPrimitives,
|
||||
chainspec::HlChainSpec,
|
||||
evm::{spec::HlSpecId, transaction::HlTxEnv},
|
||||
hardforks::HlHardforks,
|
||||
@ -54,7 +54,7 @@ where
|
||||
|
||||
fn assemble_block(
|
||||
&self,
|
||||
input: BlockAssemblerInput<'_, '_, F>,
|
||||
input: BlockAssemblerInput<'_, '_, F, HlHeader>,
|
||||
) -> Result<Self::Block, BlockExecutionError> {
|
||||
// TODO: Copy of EthBlockAssembler::assemble_block
|
||||
let inner = &self.inner;
|
||||
@ -136,6 +136,9 @@ where
|
||||
excess_blob_gas,
|
||||
requests_hash,
|
||||
};
|
||||
let system_tx_count =
|
||||
transactions.iter().filter(|t| is_system_transaction(t)).count() as u64;
|
||||
let header = HlHeader::from_ethereum_header(header, receipts, system_tx_count);
|
||||
|
||||
Ok(Self::Block {
|
||||
header,
|
||||
@ -269,6 +272,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
static EMPTY_OMMERS: [Header; 0] = [];
|
||||
|
||||
impl ConfigureEvm for HlEvmConfig
|
||||
where
|
||||
Self: Send + Sync + Unpin + Clone + 'static,
|
||||
@ -287,7 +292,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
fn evm_env(&self, header: &Header) -> Result<EvmEnv<HlSpecId>, Self::Error> {
|
||||
fn evm_env(&self, header: &HlHeader) -> Result<EvmEnv<HlSpecId>, Self::Error> {
|
||||
let blob_params = self.chain_spec().blob_params_at_timestamp(header.timestamp);
|
||||
let spec = revm_spec_by_timestamp_and_block_number(
|
||||
self.chain_spec().clone(),
|
||||
@ -332,7 +337,7 @@ where
|
||||
|
||||
fn next_evm_env(
|
||||
&self,
|
||||
parent: &Header,
|
||||
parent: &HlHeader,
|
||||
attributes: &Self::NextBlockEnvCtx,
|
||||
) -> Result<EvmEnv<HlSpecId>, Self::Error> {
|
||||
// ensure we're not missing any timestamp based hardforks
|
||||
@ -382,7 +387,7 @@ where
|
||||
ctx: EthBlockExecutionCtx {
|
||||
parent_hash: block.header().parent_hash,
|
||||
parent_beacon_block_root: block.header().parent_beacon_block_root,
|
||||
ommers: &block.body().ommers,
|
||||
ommers: &EMPTY_OMMERS,
|
||||
withdrawals: block.body().withdrawals.as_ref().map(Cow::Borrowed),
|
||||
},
|
||||
extras: HlExtras {
|
||||
@ -420,7 +425,7 @@ impl ConfigureEngineEvm<HlExecutionData> for HlEvmConfig {
|
||||
ctx: EthBlockExecutionCtx {
|
||||
parent_hash: block.header.parent_hash,
|
||||
parent_beacon_block_root: block.header.parent_beacon_block_root,
|
||||
ommers: &block.body.ommers,
|
||||
ommers: &EMPTY_OMMERS,
|
||||
withdrawals: block.body.withdrawals.as_ref().map(Cow::Borrowed),
|
||||
},
|
||||
extras: HlExtras {
|
||||
|
||||
@ -179,7 +179,7 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::chainspec::hl::hl_mainnet;
|
||||
use crate::{chainspec::hl::hl_mainnet, HlHeader};
|
||||
|
||||
use super::*;
|
||||
use alloy_primitives::{B256, U128};
|
||||
@ -355,7 +355,7 @@ mod tests {
|
||||
/// Creates a test block message
|
||||
fn create_test_block() -> NewBlockMessage<HlNewBlock> {
|
||||
let block = HlBlock {
|
||||
header: Header::default(),
|
||||
header: HlHeader::default(),
|
||||
body: HlBlockBody {
|
||||
inner: BlockBody {
|
||||
transactions: Vec::new(),
|
||||
|
||||
@ -38,10 +38,10 @@ pub struct HlNewBlock(pub NewBlock<HlBlock>);
|
||||
mod rlp {
|
||||
use super::*;
|
||||
use crate::{
|
||||
HlBlockBody,
|
||||
HlBlockBody, HlHeader,
|
||||
node::primitives::{BlockBody, TransactionSigned},
|
||||
};
|
||||
use alloy_consensus::{BlobTransactionSidecar, Header};
|
||||
use alloy_consensus::BlobTransactionSidecar;
|
||||
use alloy_primitives::{Address, U128};
|
||||
use alloy_rlp::{RlpDecodable, RlpEncodable};
|
||||
use alloy_rpc_types::Withdrawals;
|
||||
@ -50,9 +50,9 @@ mod rlp {
|
||||
#[derive(RlpEncodable, RlpDecodable)]
|
||||
#[rlp(trailing)]
|
||||
struct BlockHelper<'a> {
|
||||
header: Cow<'a, Header>,
|
||||
header: Cow<'a, HlHeader>,
|
||||
transactions: Cow<'a, Vec<TransactionSigned>>,
|
||||
ommers: Cow<'a, Vec<Header>>,
|
||||
ommers: Cow<'a, Vec<HlHeader>>,
|
||||
withdrawals: Option<Cow<'a, Withdrawals>>,
|
||||
}
|
||||
|
||||
|
||||
49
src/node/primitives/block.rs
Normal file
49
src/node/primitives/block.rs
Normal file
@ -0,0 +1,49 @@
|
||||
use super::{HlBlockBody, HlHeader, rlp};
|
||||
use alloy_rlp::Encodable;
|
||||
use reth_primitives_traits::{Block, InMemorySize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::borrow::Cow;
|
||||
|
||||
/// Block for HL
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct HlBlock {
|
||||
pub header: HlHeader,
|
||||
pub body: HlBlockBody,
|
||||
}
|
||||
|
||||
impl InMemorySize for HlBlock {
|
||||
fn size(&self) -> usize {
|
||||
self.header.size() + self.body.size()
|
||||
}
|
||||
}
|
||||
|
||||
impl Block for HlBlock {
|
||||
type Header = HlHeader;
|
||||
type Body = HlBlockBody;
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
fn rlp_length(header: &Self::Header, body: &Self::Body) -> usize {
|
||||
rlp::BlockHelper {
|
||||
header: Cow::Borrowed(header),
|
||||
transactions: Cow::Borrowed(&body.inner.transactions),
|
||||
ommers: Cow::Borrowed(&body.inner.ommers),
|
||||
withdrawals: body.inner.withdrawals.as_ref().map(Cow::Borrowed),
|
||||
sidecars: body.sidecars.as_ref().map(Cow::Borrowed),
|
||||
read_precompile_calls: body.read_precompile_calls.as_ref().map(Cow::Borrowed),
|
||||
highest_precompile_address: body.highest_precompile_address.as_ref().map(Cow::Borrowed),
|
||||
}
|
||||
.length()
|
||||
}
|
||||
}
|
||||
73
src/node/primitives/body.rs
Normal file
73
src/node/primitives/body.rs
Normal file
@ -0,0 +1,73 @@
|
||||
use alloy_consensus::BlobTransactionSidecar;
|
||||
use alloy_primitives::Address;
|
||||
use reth_primitives_traits::{BlockBody as BlockBodyTrait, InMemorySize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::node::primitives::{BlockBody, TransactionSigned};
|
||||
pub use crate::node::types::{ReadPrecompileCall, ReadPrecompileCalls};
|
||||
|
||||
/// Block body for HL. It is equivalent to Ethereum [`BlockBody`] but additionally stores sidecars
|
||||
/// for blob transactions.
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Default,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
derive_more::Deref,
|
||||
derive_more::DerefMut,
|
||||
)]
|
||||
pub struct HlBlockBody {
|
||||
#[serde(flatten)]
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub inner: BlockBody,
|
||||
pub sidecars: Option<Vec<BlobTransactionSidecar>>,
|
||||
pub read_precompile_calls: Option<ReadPrecompileCalls>,
|
||||
pub highest_precompile_address: Option<Address>,
|
||||
}
|
||||
|
||||
impl InMemorySize for HlBlockBody {
|
||||
fn size(&self) -> usize {
|
||||
self.inner.size() +
|
||||
self.sidecars
|
||||
.as_ref()
|
||||
.map_or(0, |s| s.capacity() * core::mem::size_of::<BlobTransactionSidecar>()) +
|
||||
self.read_precompile_calls
|
||||
.as_ref()
|
||||
.map_or(0, |s| s.0.capacity() * core::mem::size_of::<ReadPrecompileCall>())
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockBodyTrait for HlBlockBody {
|
||||
type Transaction = TransactionSigned;
|
||||
type OmmerHeader = super::HlHeader;
|
||||
|
||||
fn transactions(&self) -> &[Self::Transaction] {
|
||||
BlockBodyTrait::transactions(&self.inner)
|
||||
}
|
||||
fn into_ethereum_body(self) -> BlockBody {
|
||||
self.inner
|
||||
}
|
||||
fn into_transactions(self) -> Vec<Self::Transaction> {
|
||||
self.inner.into_transactions()
|
||||
}
|
||||
fn withdrawals(&self) -> Option<&alloy_rpc_types::Withdrawals> {
|
||||
self.inner.withdrawals()
|
||||
}
|
||||
fn ommers(&self) -> Option<&[Self::OmmerHeader]> {
|
||||
self.inner.ommers()
|
||||
}
|
||||
|
||||
fn calculate_tx_root(&self) -> alloy_primitives::B256 {
|
||||
alloy_consensus::proofs::calculate_transaction_root(
|
||||
&self
|
||||
.transactions()
|
||||
.iter()
|
||||
.filter(|tx| !tx.is_system_transaction())
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
241
src/node/primitives/header.rs
Normal file
241
src/node/primitives/header.rs
Normal file
@ -0,0 +1,241 @@
|
||||
use alloy_consensus::Header;
|
||||
use alloy_primitives::{Address, B64, B256, BlockNumber, Bloom, Bytes, Sealable, U256};
|
||||
use alloy_rlp::{RlpDecodable, RlpEncodable};
|
||||
use reth_cli_commands::common::CliHeader;
|
||||
use reth_codecs::Compact;
|
||||
use reth_ethereum_primitives::EthereumReceipt;
|
||||
use reth_primitives::{SealedHeader, logs_bloom};
|
||||
use reth_primitives_traits::{BlockHeader, InMemorySize, serde_bincode_compat::RlpBincode};
|
||||
use reth_rpc_convert::transaction::FromConsensusHeader;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// The header type of this node
|
||||
///
|
||||
/// This type extends the regular ethereum header with an extension.
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Hash,
|
||||
derive_more::AsRef,
|
||||
derive_more::Deref,
|
||||
Default,
|
||||
RlpEncodable,
|
||||
RlpDecodable,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct HlHeader {
|
||||
/// The regular eth header
|
||||
#[as_ref]
|
||||
#[deref]
|
||||
pub inner: Header,
|
||||
/// The extended header fields that is not part of the block hash
|
||||
pub extras: HlHeaderExtras,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, RlpEncodable, RlpDecodable, Hash,
|
||||
)]
|
||||
pub struct HlHeaderExtras {
|
||||
pub logs_bloom_with_system_txs: Bloom,
|
||||
pub system_tx_count: u64,
|
||||
}
|
||||
|
||||
impl HlHeader {
|
||||
pub(crate) fn from_ethereum_header(header: Header, receipts: &[EthereumReceipt], system_tx_count: u64) -> HlHeader {
|
||||
let logs_bloom = logs_bloom(receipts.iter().flat_map(|r| &r.logs));
|
||||
HlHeader {
|
||||
inner: header,
|
||||
extras: HlHeaderExtras { logs_bloom_with_system_txs: logs_bloom, system_tx_count },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Header> for HlHeader {
|
||||
fn from(_value: Header) -> Self {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Self> for HlHeader {
|
||||
fn as_ref(&self) -> &Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Sealable for HlHeader {
|
||||
fn hash_slow(&self) -> B256 {
|
||||
self.inner.hash_slow()
|
||||
}
|
||||
}
|
||||
|
||||
impl alloy_consensus::BlockHeader for HlHeader {
|
||||
fn parent_hash(&self) -> B256 {
|
||||
self.inner.parent_hash()
|
||||
}
|
||||
|
||||
fn ommers_hash(&self) -> B256 {
|
||||
self.inner.ommers_hash()
|
||||
}
|
||||
|
||||
fn beneficiary(&self) -> Address {
|
||||
self.inner.beneficiary()
|
||||
}
|
||||
|
||||
fn state_root(&self) -> B256 {
|
||||
self.inner.state_root()
|
||||
}
|
||||
|
||||
fn transactions_root(&self) -> B256 {
|
||||
self.inner.transactions_root()
|
||||
}
|
||||
|
||||
fn receipts_root(&self) -> B256 {
|
||||
self.inner.receipts_root()
|
||||
}
|
||||
|
||||
fn withdrawals_root(&self) -> Option<B256> {
|
||||
self.inner.withdrawals_root()
|
||||
}
|
||||
|
||||
fn logs_bloom(&self) -> Bloom {
|
||||
self.extras.logs_bloom_with_system_txs
|
||||
}
|
||||
|
||||
fn difficulty(&self) -> U256 {
|
||||
self.inner.difficulty()
|
||||
}
|
||||
|
||||
fn number(&self) -> BlockNumber {
|
||||
self.inner.number()
|
||||
}
|
||||
|
||||
fn gas_limit(&self) -> u64 {
|
||||
self.inner.gas_limit()
|
||||
}
|
||||
|
||||
fn gas_used(&self) -> u64 {
|
||||
self.inner.gas_used()
|
||||
}
|
||||
|
||||
fn timestamp(&self) -> u64 {
|
||||
self.inner.timestamp()
|
||||
}
|
||||
|
||||
fn mix_hash(&self) -> Option<B256> {
|
||||
self.inner.mix_hash()
|
||||
}
|
||||
|
||||
fn nonce(&self) -> Option<B64> {
|
||||
self.inner.nonce()
|
||||
}
|
||||
|
||||
fn base_fee_per_gas(&self) -> Option<u64> {
|
||||
self.inner.base_fee_per_gas()
|
||||
}
|
||||
|
||||
fn blob_gas_used(&self) -> Option<u64> {
|
||||
self.inner.blob_gas_used()
|
||||
}
|
||||
|
||||
fn excess_blob_gas(&self) -> Option<u64> {
|
||||
self.inner.excess_blob_gas()
|
||||
}
|
||||
|
||||
fn parent_beacon_block_root(&self) -> Option<B256> {
|
||||
self.inner.parent_beacon_block_root()
|
||||
}
|
||||
|
||||
fn requests_hash(&self) -> Option<B256> {
|
||||
self.inner.requests_hash()
|
||||
}
|
||||
|
||||
fn extra_data(&self) -> &Bytes {
|
||||
self.inner.extra_data()
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.extras.system_tx_count == 0 && self.inner.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl InMemorySize for HlHeader {
|
||||
fn size(&self) -> usize {
|
||||
self.inner.size() + self.extras.size()
|
||||
}
|
||||
}
|
||||
|
||||
impl InMemorySize for HlHeaderExtras {
|
||||
fn size(&self) -> usize {
|
||||
self.logs_bloom_with_system_txs.data().len() + self.system_tx_count.size()
|
||||
}
|
||||
}
|
||||
|
||||
impl reth_codecs::Compact for HlHeader {
|
||||
fn to_compact<B>(&self, buf: &mut B) -> usize
|
||||
where
|
||||
B: alloy_rlp::bytes::BufMut + AsMut<[u8]>,
|
||||
{
|
||||
// Because Header ends with extra_data which is `Bytes`, we can't use to_compact for extras,
|
||||
// because Compact trait requires the Bytes field to be placed at the end of the struct.
|
||||
// Bytes::from_compact just reads all trailing data as the Bytes field.
|
||||
//
|
||||
// Hence we need to use other form of serialization, since extra headers are not Compact-compatible.
|
||||
// We just treat all header fields as rmp-serialized one `Bytes` field.
|
||||
let result: Bytes = rmp_serde::to_vec(&self).unwrap().into();
|
||||
result.to_compact(buf)
|
||||
}
|
||||
|
||||
fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
|
||||
let (bytes, remaining) = Bytes::from_compact(buf, len);
|
||||
let header: HlHeader = rmp_serde::from_slice(&bytes).unwrap();
|
||||
(header, remaining)
|
||||
}
|
||||
}
|
||||
|
||||
impl reth_db_api::table::Compress for HlHeader {
|
||||
type Compressed = Vec<u8>;
|
||||
|
||||
fn compress_to_buf<B: alloy_primitives::bytes::BufMut + AsMut<[u8]>>(&self, buf: &mut B) {
|
||||
let _ = Compact::to_compact(self, buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl reth_db_api::table::Decompress for HlHeader {
|
||||
fn decompress(value: &[u8]) -> Result<Self, reth_db_api::DatabaseError> {
|
||||
let (obj, _) = Compact::from_compact(value, value.len());
|
||||
Ok(obj)
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockHeader for HlHeader {}
|
||||
|
||||
impl RlpBincode for HlHeader {}
|
||||
|
||||
impl CliHeader for HlHeader {
|
||||
fn set_number(&mut self, number: u64) {
|
||||
self.inner.set_number(number);
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HlHeader> for Header {
|
||||
fn from(value: HlHeader) -> Self {
|
||||
value.inner
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_ethereum_ommers(ommers: &[HlHeader]) -> Vec<Header> {
|
||||
ommers.iter().map(|ommer| ommer.clone().into()).collect()
|
||||
}
|
||||
|
||||
impl FromConsensusHeader<HlHeader> for alloy_rpc_types::Header {
|
||||
fn from_consensus_header(header: SealedHeader<HlHeader>, block_size: usize) -> Self {
|
||||
FromConsensusHeader::<Header>::from_consensus_header(
|
||||
SealedHeader::<Header>::new(header.inner.clone(), header.hash()),
|
||||
block_size,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,17 +1,18 @@
|
||||
#![allow(clippy::owned_cow)]
|
||||
use alloy_consensus::{BlobTransactionSidecar, Header};
|
||||
use alloy_primitives::Address;
|
||||
use alloy_rlp::{Encodable, RlpDecodable, RlpEncodable};
|
||||
use reth_ethereum_primitives::Receipt;
|
||||
use reth_primitives::NodePrimitives;
|
||||
use reth_primitives_traits::{Block, BlockBody as BlockBodyTrait, InMemorySize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crate::node::types::{ReadPrecompileCall, ReadPrecompileCalls};
|
||||
pub mod transaction;
|
||||
pub use transaction::{BlockBody, TransactionSigned};
|
||||
|
||||
pub mod tx_wrapper;
|
||||
pub use tx_wrapper::{BlockBody, TransactionSigned};
|
||||
pub mod block;
|
||||
pub use block::HlBlock;
|
||||
pub mod body;
|
||||
pub use body::HlBlockBody;
|
||||
pub mod header;
|
||||
pub use header::HlHeader;
|
||||
|
||||
pub mod rlp;
|
||||
pub mod serde_bincode_compat;
|
||||
|
||||
/// Primitive types for HyperEVM.
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
|
||||
@ -20,321 +21,8 @@ pub struct HlPrimitives;
|
||||
|
||||
impl NodePrimitives for HlPrimitives {
|
||||
type Block = HlBlock;
|
||||
type BlockHeader = Header;
|
||||
type BlockHeader = HlHeader;
|
||||
type BlockBody = HlBlockBody;
|
||||
type SignedTx = TransactionSigned;
|
||||
type Receipt = Receipt;
|
||||
}
|
||||
|
||||
/// Block body for HL. It is equivalent to Ethereum [`BlockBody`] but additionally stores sidecars
|
||||
/// for blob transactions.
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Default,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
derive_more::Deref,
|
||||
derive_more::DerefMut,
|
||||
)]
|
||||
pub struct HlBlockBody {
|
||||
#[serde(flatten)]
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub inner: BlockBody,
|
||||
pub sidecars: Option<Vec<BlobTransactionSidecar>>,
|
||||
pub read_precompile_calls: Option<ReadPrecompileCalls>,
|
||||
pub highest_precompile_address: Option<Address>,
|
||||
}
|
||||
|
||||
impl InMemorySize for HlBlockBody {
|
||||
fn size(&self) -> usize {
|
||||
self.inner.size() +
|
||||
self.sidecars
|
||||
.as_ref()
|
||||
.map_or(0, |s| s.capacity() * core::mem::size_of::<BlobTransactionSidecar>()) +
|
||||
self.read_precompile_calls
|
||||
.as_ref()
|
||||
.map_or(0, |s| s.0.capacity() * core::mem::size_of::<ReadPrecompileCall>())
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockBodyTrait for HlBlockBody {
|
||||
type Transaction = TransactionSigned;
|
||||
type OmmerHeader = Header;
|
||||
|
||||
fn transactions(&self) -> &[Self::Transaction] {
|
||||
BlockBodyTrait::transactions(&self.inner)
|
||||
}
|
||||
fn into_ethereum_body(self) -> BlockBody {
|
||||
self.inner
|
||||
}
|
||||
fn into_transactions(self) -> Vec<Self::Transaction> {
|
||||
self.inner.into_transactions()
|
||||
}
|
||||
fn withdrawals(&self) -> Option<&alloy_rpc_types::Withdrawals> {
|
||||
self.inner.withdrawals()
|
||||
}
|
||||
fn ommers(&self) -> Option<&[Self::OmmerHeader]> {
|
||||
self.inner.ommers()
|
||||
}
|
||||
|
||||
fn calculate_tx_root(&self) -> alloy_primitives::B256 {
|
||||
alloy_consensus::proofs::calculate_transaction_root(
|
||||
&self
|
||||
.transactions()
|
||||
.iter()
|
||||
.filter(|tx| !tx.is_system_transaction())
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Block for HL
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct HlBlock {
|
||||
pub header: Header,
|
||||
pub body: HlBlockBody,
|
||||
}
|
||||
|
||||
impl InMemorySize for HlBlock {
|
||||
fn size(&self) -> usize {
|
||||
self.header.size() + self.body.size()
|
||||
}
|
||||
}
|
||||
|
||||
impl Block for HlBlock {
|
||||
type Header = Header;
|
||||
type Body = HlBlockBody;
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
fn rlp_length(header: &Self::Header, body: &Self::Body) -> usize {
|
||||
rlp::BlockHelper {
|
||||
header: Cow::Borrowed(header),
|
||||
transactions: Cow::Borrowed(&body.inner.transactions),
|
||||
ommers: Cow::Borrowed(&body.inner.ommers),
|
||||
withdrawals: body.inner.withdrawals.as_ref().map(Cow::Borrowed),
|
||||
sidecars: body.sidecars.as_ref().map(Cow::Borrowed),
|
||||
read_precompile_calls: body.read_precompile_calls.as_ref().map(Cow::Borrowed),
|
||||
highest_precompile_address: body.highest_precompile_address.as_ref().map(Cow::Borrowed),
|
||||
}
|
||||
.length()
|
||||
}
|
||||
}
|
||||
|
||||
mod rlp {
|
||||
use super::*;
|
||||
use alloy_eips::eip4895::Withdrawals;
|
||||
use alloy_rlp::Decodable;
|
||||
|
||||
#[derive(RlpEncodable, RlpDecodable)]
|
||||
#[rlp(trailing)]
|
||||
struct BlockBodyHelper<'a> {
|
||||
transactions: Cow<'a, Vec<TransactionSigned>>,
|
||||
ommers: Cow<'a, Vec<Header>>,
|
||||
withdrawals: Option<Cow<'a, Withdrawals>>,
|
||||
sidecars: Option<Cow<'a, Vec<BlobTransactionSidecar>>>,
|
||||
read_precompile_calls: Option<Cow<'a, ReadPrecompileCalls>>,
|
||||
highest_precompile_address: Option<Cow<'a, Address>>,
|
||||
}
|
||||
|
||||
#[derive(RlpEncodable, RlpDecodable)]
|
||||
#[rlp(trailing)]
|
||||
pub(crate) struct BlockHelper<'a> {
|
||||
pub(crate) header: Cow<'a, Header>,
|
||||
pub(crate) transactions: Cow<'a, Vec<TransactionSigned>>,
|
||||
pub(crate) ommers: Cow<'a, Vec<Header>>,
|
||||
pub(crate) withdrawals: Option<Cow<'a, Withdrawals>>,
|
||||
pub(crate) sidecars: Option<Cow<'a, Vec<BlobTransactionSidecar>>>,
|
||||
pub(crate) read_precompile_calls: Option<Cow<'a, ReadPrecompileCalls>>,
|
||||
pub(crate) highest_precompile_address: Option<Cow<'a, Address>>,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a HlBlockBody> for BlockBodyHelper<'a> {
|
||||
fn from(value: &'a HlBlockBody) -> Self {
|
||||
let HlBlockBody {
|
||||
inner: BlockBody { transactions, ommers, withdrawals },
|
||||
sidecars,
|
||||
read_precompile_calls,
|
||||
highest_precompile_address,
|
||||
} = value;
|
||||
Self {
|
||||
transactions: Cow::Borrowed(transactions),
|
||||
ommers: Cow::Borrowed(ommers),
|
||||
withdrawals: withdrawals.as_ref().map(Cow::Borrowed),
|
||||
sidecars: sidecars.as_ref().map(Cow::Borrowed),
|
||||
read_precompile_calls: read_precompile_calls.as_ref().map(Cow::Borrowed),
|
||||
highest_precompile_address: highest_precompile_address.as_ref().map(Cow::Borrowed),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a HlBlock> for BlockHelper<'a> {
|
||||
fn from(value: &'a HlBlock) -> Self {
|
||||
let HlBlock {
|
||||
header,
|
||||
body:
|
||||
HlBlockBody {
|
||||
inner: BlockBody { transactions, ommers, withdrawals },
|
||||
sidecars,
|
||||
read_precompile_calls,
|
||||
highest_precompile_address,
|
||||
},
|
||||
} = value;
|
||||
Self {
|
||||
header: Cow::Borrowed(header),
|
||||
transactions: Cow::Borrowed(transactions),
|
||||
ommers: Cow::Borrowed(ommers),
|
||||
withdrawals: withdrawals.as_ref().map(Cow::Borrowed),
|
||||
sidecars: sidecars.as_ref().map(Cow::Borrowed),
|
||||
read_precompile_calls: read_precompile_calls.as_ref().map(Cow::Borrowed),
|
||||
highest_precompile_address: highest_precompile_address.as_ref().map(Cow::Borrowed),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for HlBlockBody {
|
||||
fn encode(&self, out: &mut dyn bytes::BufMut) {
|
||||
BlockBodyHelper::from(self).encode(out);
|
||||
}
|
||||
fn length(&self) -> usize {
|
||||
BlockBodyHelper::from(self).length()
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for HlBlockBody {
|
||||
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
let BlockBodyHelper {
|
||||
transactions,
|
||||
ommers,
|
||||
withdrawals,
|
||||
sidecars,
|
||||
read_precompile_calls,
|
||||
highest_precompile_address,
|
||||
} = BlockBodyHelper::decode(buf)?;
|
||||
Ok(Self {
|
||||
inner: BlockBody {
|
||||
transactions: transactions.into_owned(),
|
||||
ommers: ommers.into_owned(),
|
||||
withdrawals: withdrawals.map(|w| w.into_owned()),
|
||||
},
|
||||
sidecars: sidecars.map(|s| s.into_owned()),
|
||||
read_precompile_calls: read_precompile_calls.map(|s| s.into_owned()),
|
||||
highest_precompile_address: highest_precompile_address.map(|s| s.into_owned()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for HlBlock {
|
||||
fn encode(&self, out: &mut dyn bytes::BufMut) {
|
||||
BlockHelper::from(self).encode(out);
|
||||
}
|
||||
fn length(&self) -> usize {
|
||||
BlockHelper::from(self).length()
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for HlBlock {
|
||||
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
let BlockHelper {
|
||||
header,
|
||||
transactions,
|
||||
ommers,
|
||||
withdrawals,
|
||||
sidecars,
|
||||
read_precompile_calls,
|
||||
highest_precompile_address,
|
||||
} = BlockHelper::decode(buf)?;
|
||||
Ok(Self {
|
||||
header: header.into_owned(),
|
||||
body: HlBlockBody {
|
||||
inner: BlockBody {
|
||||
transactions: transactions.into_owned(),
|
||||
ommers: ommers.into_owned(),
|
||||
withdrawals: withdrawals.map(|w| w.into_owned()),
|
||||
},
|
||||
sidecars: sidecars.map(|s| s.into_owned()),
|
||||
read_precompile_calls: read_precompile_calls.map(|s| s.into_owned()),
|
||||
highest_precompile_address: highest_precompile_address.map(|s| s.into_owned()),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod serde_bincode_compat {
|
||||
use super::*;
|
||||
use reth_primitives_traits::serde_bincode_compat::{BincodeReprFor, SerdeBincodeCompat};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct HlBlockBodyBincode<'a> {
|
||||
inner: BincodeReprFor<'a, BlockBody>,
|
||||
sidecars: Option<Cow<'a, Vec<BlobTransactionSidecar>>>,
|
||||
read_precompile_calls: Option<Cow<'a, ReadPrecompileCalls>>,
|
||||
highest_precompile_address: Option<Cow<'a, Address>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct HlBlockBincode<'a> {
|
||||
header: BincodeReprFor<'a, Header>,
|
||||
body: BincodeReprFor<'a, HlBlockBody>,
|
||||
}
|
||||
|
||||
impl SerdeBincodeCompat for HlBlockBody {
|
||||
type BincodeRepr<'a> = HlBlockBodyBincode<'a>;
|
||||
|
||||
fn as_repr(&self) -> Self::BincodeRepr<'_> {
|
||||
HlBlockBodyBincode {
|
||||
inner: self.inner.as_repr(),
|
||||
sidecars: self.sidecars.as_ref().map(Cow::Borrowed),
|
||||
read_precompile_calls: self.read_precompile_calls.as_ref().map(Cow::Borrowed),
|
||||
highest_precompile_address: self
|
||||
.highest_precompile_address
|
||||
.as_ref()
|
||||
.map(Cow::Borrowed),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
|
||||
let HlBlockBodyBincode {
|
||||
inner,
|
||||
sidecars,
|
||||
read_precompile_calls,
|
||||
highest_precompile_address,
|
||||
} = repr;
|
||||
Self {
|
||||
inner: BlockBody::from_repr(inner),
|
||||
sidecars: sidecars.map(|s| s.into_owned()),
|
||||
read_precompile_calls: read_precompile_calls.map(|s| s.into_owned()),
|
||||
highest_precompile_address: highest_precompile_address.map(|s| s.into_owned()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SerdeBincodeCompat for HlBlock {
|
||||
type BincodeRepr<'a> = HlBlockBincode<'a>;
|
||||
|
||||
fn as_repr(&self) -> Self::BincodeRepr<'_> {
|
||||
HlBlockBincode { header: self.header.as_repr(), body: self.body.as_repr() }
|
||||
}
|
||||
|
||||
fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
|
||||
let HlBlockBincode { header, body } = repr;
|
||||
Self { header: Header::from_repr(header), body: HlBlockBody::from_repr(body) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
142
src/node/primitives/rlp.rs
Normal file
142
src/node/primitives/rlp.rs
Normal file
@ -0,0 +1,142 @@
|
||||
#![allow(clippy::owned_cow)]
|
||||
use super::{HlBlock, HlBlockBody, TransactionSigned};
|
||||
use crate::{node::types::ReadPrecompileCalls, HlHeader};
|
||||
use alloy_consensus::{BlobTransactionSidecar, BlockBody};
|
||||
use alloy_eips::eip4895::Withdrawals;
|
||||
use alloy_primitives::Address;
|
||||
use alloy_rlp::{Decodable, Encodable, RlpDecodable, RlpEncodable};
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[derive(RlpEncodable, RlpDecodable)]
|
||||
#[rlp(trailing)]
|
||||
struct BlockBodyHelper<'a> {
|
||||
transactions: Cow<'a, Vec<TransactionSigned>>,
|
||||
ommers: Cow<'a, Vec<HlHeader>>,
|
||||
withdrawals: Option<Cow<'a, Withdrawals>>,
|
||||
sidecars: Option<Cow<'a, Vec<BlobTransactionSidecar>>>,
|
||||
read_precompile_calls: Option<Cow<'a, ReadPrecompileCalls>>,
|
||||
highest_precompile_address: Option<Cow<'a, Address>>,
|
||||
}
|
||||
|
||||
#[derive(RlpEncodable, RlpDecodable)]
|
||||
#[rlp(trailing)]
|
||||
pub(crate) struct BlockHelper<'a> {
|
||||
pub(crate) header: Cow<'a, HlHeader>,
|
||||
pub(crate) transactions: Cow<'a, Vec<TransactionSigned>>,
|
||||
pub(crate) ommers: Cow<'a, Vec<HlHeader>>,
|
||||
pub(crate) withdrawals: Option<Cow<'a, Withdrawals>>,
|
||||
pub(crate) sidecars: Option<Cow<'a, Vec<BlobTransactionSidecar>>>,
|
||||
pub(crate) read_precompile_calls: Option<Cow<'a, ReadPrecompileCalls>>,
|
||||
pub(crate) highest_precompile_address: Option<Cow<'a, Address>>,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a HlBlockBody> for BlockBodyHelper<'a> {
|
||||
fn from(value: &'a HlBlockBody) -> Self {
|
||||
let HlBlockBody {
|
||||
inner: BlockBody { transactions, ommers, withdrawals },
|
||||
sidecars,
|
||||
read_precompile_calls,
|
||||
highest_precompile_address,
|
||||
} = value;
|
||||
Self {
|
||||
transactions: Cow::Borrowed(transactions),
|
||||
ommers: Cow::Borrowed(ommers),
|
||||
withdrawals: withdrawals.as_ref().map(Cow::Borrowed),
|
||||
sidecars: sidecars.as_ref().map(Cow::Borrowed),
|
||||
read_precompile_calls: read_precompile_calls.as_ref().map(Cow::Borrowed),
|
||||
highest_precompile_address: highest_precompile_address.as_ref().map(Cow::Borrowed),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a HlBlock> for BlockHelper<'a> {
|
||||
fn from(value: &'a HlBlock) -> Self {
|
||||
let HlBlock {
|
||||
header,
|
||||
body:
|
||||
HlBlockBody {
|
||||
inner: BlockBody { transactions, ommers, withdrawals },
|
||||
sidecars,
|
||||
read_precompile_calls,
|
||||
highest_precompile_address,
|
||||
},
|
||||
} = value;
|
||||
Self {
|
||||
header: Cow::Borrowed(header),
|
||||
transactions: Cow::Borrowed(transactions),
|
||||
ommers: Cow::Borrowed(ommers),
|
||||
withdrawals: withdrawals.as_ref().map(Cow::Borrowed),
|
||||
sidecars: sidecars.as_ref().map(Cow::Borrowed),
|
||||
read_precompile_calls: read_precompile_calls.as_ref().map(Cow::Borrowed),
|
||||
highest_precompile_address: highest_precompile_address.as_ref().map(Cow::Borrowed),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for HlBlockBody {
|
||||
fn encode(&self, out: &mut dyn bytes::BufMut) {
|
||||
BlockBodyHelper::from(self).encode(out);
|
||||
}
|
||||
fn length(&self) -> usize {
|
||||
BlockBodyHelper::from(self).length()
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for HlBlockBody {
|
||||
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
let BlockBodyHelper {
|
||||
transactions,
|
||||
ommers,
|
||||
withdrawals,
|
||||
sidecars,
|
||||
read_precompile_calls,
|
||||
highest_precompile_address,
|
||||
} = BlockBodyHelper::decode(buf)?;
|
||||
Ok(Self {
|
||||
inner: BlockBody {
|
||||
transactions: transactions.into_owned(),
|
||||
ommers: ommers.into_owned().into_iter().map(Into::into).collect(),
|
||||
withdrawals: withdrawals.map(|w| w.into_owned()),
|
||||
},
|
||||
sidecars: sidecars.map(|s| s.into_owned()),
|
||||
read_precompile_calls: read_precompile_calls.map(|s| s.into_owned()),
|
||||
highest_precompile_address: highest_precompile_address.map(|s| s.into_owned()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for HlBlock {
|
||||
fn encode(&self, out: &mut dyn bytes::BufMut) {
|
||||
BlockHelper::from(self).encode(out);
|
||||
}
|
||||
fn length(&self) -> usize {
|
||||
BlockHelper::from(self).length()
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for HlBlock {
|
||||
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
let BlockHelper {
|
||||
header,
|
||||
transactions,
|
||||
ommers,
|
||||
withdrawals,
|
||||
sidecars,
|
||||
read_precompile_calls,
|
||||
highest_precompile_address,
|
||||
} = BlockHelper::decode(buf)?;
|
||||
Ok(Self {
|
||||
header: header.into_owned(),
|
||||
body: HlBlockBody {
|
||||
inner: BlockBody {
|
||||
transactions: transactions.into_owned(),
|
||||
ommers: ommers.into_owned(),
|
||||
withdrawals: withdrawals.map(|w| w.into_owned()),
|
||||
},
|
||||
sidecars: sidecars.map(|s| s.into_owned()),
|
||||
read_precompile_calls: read_precompile_calls.map(|s| s.into_owned()),
|
||||
highest_precompile_address: highest_precompile_address.map(|s| s.into_owned()),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
64
src/node/primitives/serde_bincode_compat.rs
Normal file
64
src/node/primitives/serde_bincode_compat.rs
Normal file
@ -0,0 +1,64 @@
|
||||
#![allow(clippy::owned_cow)]
|
||||
use alloy_consensus::BlobTransactionSidecar;
|
||||
use alloy_primitives::Address;
|
||||
use reth_primitives_traits::serde_bincode_compat::{BincodeReprFor, SerdeBincodeCompat};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use super::{HlBlock, HlBlockBody};
|
||||
use crate::{node::{primitives::BlockBody, types::ReadPrecompileCalls}, HlHeader};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct HlBlockBodyBincode<'a> {
|
||||
inner: BincodeReprFor<'a, BlockBody>,
|
||||
sidecars: Option<Cow<'a, Vec<BlobTransactionSidecar>>>,
|
||||
read_precompile_calls: Option<Cow<'a, ReadPrecompileCalls>>,
|
||||
highest_precompile_address: Option<Cow<'a, Address>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct HlBlockBincode<'a> {
|
||||
header: BincodeReprFor<'a, HlHeader>,
|
||||
body: BincodeReprFor<'a, HlBlockBody>,
|
||||
}
|
||||
|
||||
impl SerdeBincodeCompat for HlBlockBody {
|
||||
type BincodeRepr<'a> = HlBlockBodyBincode<'a>;
|
||||
|
||||
fn as_repr(&self) -> Self::BincodeRepr<'_> {
|
||||
HlBlockBodyBincode {
|
||||
inner: self.inner.as_repr(),
|
||||
sidecars: self.sidecars.as_ref().map(Cow::Borrowed),
|
||||
read_precompile_calls: self.read_precompile_calls.as_ref().map(Cow::Borrowed),
|
||||
highest_precompile_address: self.highest_precompile_address.as_ref().map(Cow::Borrowed),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
|
||||
let HlBlockBodyBincode {
|
||||
inner,
|
||||
sidecars,
|
||||
read_precompile_calls,
|
||||
highest_precompile_address,
|
||||
} = repr;
|
||||
Self {
|
||||
inner: BlockBody::from_repr(inner),
|
||||
sidecars: sidecars.map(|s| s.into_owned()),
|
||||
read_precompile_calls: read_precompile_calls.map(|s| s.into_owned()),
|
||||
highest_precompile_address: highest_precompile_address.map(|s| s.into_owned()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SerdeBincodeCompat for HlBlock {
|
||||
type BincodeRepr<'a> = HlBlockBincode<'a>;
|
||||
|
||||
fn as_repr(&self) -> Self::BincodeRepr<'_> {
|
||||
HlBlockBincode { header: self.header.as_repr(), body: self.body.as_repr() }
|
||||
}
|
||||
|
||||
fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
|
||||
let HlBlockBincode { header, body } = repr;
|
||||
Self { header: HlHeader::from_repr(header), body: HlBlockBody::from_repr(body) }
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
//! except that it supports pseudo signer for system transactions.
|
||||
use std::convert::Infallible;
|
||||
|
||||
use crate::evm::transaction::HlTxEnv;
|
||||
use crate::{evm::transaction::HlTxEnv, HlHeader};
|
||||
use alloy_consensus::{
|
||||
SignableTransaction, Signed, Transaction as TransactionTrait, TransactionEnvelope, TxEip1559,
|
||||
TxEip2930, TxEip4844, TxEip7702, TxLegacy, TxType, TypedTransaction, crypto::RecoveryError,
|
||||
@ -181,7 +181,7 @@ impl SerdeBincodeCompat for TransactionSigned {
|
||||
}
|
||||
}
|
||||
|
||||
pub type BlockBody = alloy_consensus::BlockBody<TransactionSigned>;
|
||||
pub type BlockBody = alloy_consensus::BlockBody<TransactionSigned, HlHeader>;
|
||||
|
||||
impl TryFrom<TransactionSigned> for PooledTransactionVariant {
|
||||
type Error = <InnerType as TryInto<PooledTransactionVariant>>::Error;
|
||||
@ -211,15 +211,15 @@ impl Decompress for TransactionSigned {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert_to_eth_block_body(value: BlockBody) -> alloy_consensus::BlockBody<InnerType> {
|
||||
pub fn convert_to_eth_block_body(value: BlockBody) -> alloy_consensus::BlockBody<InnerType, HlHeader> {
|
||||
alloy_consensus::BlockBody {
|
||||
transactions: value.transactions.into_iter().map(|tx| tx.into_inner()).collect(),
|
||||
ommers: value.ommers,
|
||||
ommers: value.ommers.into_iter().map(|ommer| ommer.into()).collect(),
|
||||
withdrawals: value.withdrawals,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert_to_hl_block_body(value: alloy_consensus::BlockBody<InnerType>) -> BlockBody {
|
||||
pub fn convert_to_hl_block_body(value: alloy_consensus::BlockBody<InnerType, HlHeader>) -> BlockBody {
|
||||
BlockBody {
|
||||
transactions: value.transactions.into_iter().map(TransactionSigned::Default).collect(),
|
||||
ommers: value.ommers,
|
||||
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
HlBlock, HlBlockBody, HlPrimitives,
|
||||
HlBlock, HlBlockBody, HlHeader, HlPrimitives,
|
||||
node::{
|
||||
primitives::tx_wrapper::{convert_to_eth_block_body, convert_to_hl_block_body},
|
||||
primitives::transaction::{convert_to_eth_block_body, convert_to_hl_block_body},
|
||||
types::HlExtras,
|
||||
},
|
||||
};
|
||||
@ -13,6 +13,8 @@ use reth_db::{
|
||||
cursor::{DbCursorRO, DbCursorRW},
|
||||
transaction::{DbTx, DbTxMut},
|
||||
};
|
||||
use reth_primitives::TransactionSigned;
|
||||
use reth_primitives_traits::Block;
|
||||
use reth_provider::{
|
||||
BlockBodyReader, BlockBodyWriter, ChainSpecProvider, ChainStorageReader, ChainStorageWriter,
|
||||
DBProvider, DatabaseProvider, EthStorage, ProviderResult, ReadBodyInput, StorageLocation,
|
||||
@ -23,7 +25,7 @@ pub mod tables;
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[non_exhaustive]
|
||||
pub struct HlStorage(EthStorage);
|
||||
pub struct HlStorage(EthStorage<TransactionSigned, HlHeader>);
|
||||
|
||||
impl HlStorage {
|
||||
fn write_precompile_calls<Provider>(
|
||||
@ -146,15 +148,15 @@ where
|
||||
inputs: Vec<ReadBodyInput<'_, Self::Block>>,
|
||||
) -> ProviderResult<Vec<HlBlockBody>> {
|
||||
let read_precompile_calls = self.read_precompile_calls(provider, &inputs)?;
|
||||
let eth_bodies = self.0.read_block_bodies(
|
||||
provider,
|
||||
inputs
|
||||
.into_iter()
|
||||
.map(|(header, transactions)| {
|
||||
(header, transactions.into_iter().map(|tx| tx.into_inner()).collect())
|
||||
})
|
||||
.collect(),
|
||||
)?;
|
||||
let inputs: Vec<(&HlHeader, _)> = inputs
|
||||
.into_iter()
|
||||
.map(|(header, transactions)| {
|
||||
(header, transactions.into_iter().map(|tx| tx.into_inner()).collect())
|
||||
})
|
||||
.collect();
|
||||
let inputs: Vec<(&<Self::Block as Block>::Header, _)> = inputs;
|
||||
let eth_bodies = self.0.read_block_bodies(provider, inputs)?;
|
||||
let eth_bodies: Vec<alloy_consensus::BlockBody<_, HlHeader>> = eth_bodies;
|
||||
|
||||
// NOTE: sidecars are not used in HyperEVM yet.
|
||||
Ok(eth_bodies
|
||||
|
||||
@ -2,26 +2,39 @@
|
||||
//!
|
||||
//! Changes:
|
||||
//! - ReadPrecompileCalls supports RLP encoding / decoding
|
||||
use alloy_consensus::TxType;
|
||||
use alloy_primitives::{Address, B256, Bytes, Log};
|
||||
use alloy_rlp::{Decodable, Encodable, RlpDecodable, RlpEncodable};
|
||||
use bytes::BufMut;
|
||||
use reth_ethereum_primitives::EthereumReceipt;
|
||||
use reth_primitives_traits::InMemorySize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::HlBlock;
|
||||
|
||||
pub type ReadPrecompileCall = (Address, Vec<(ReadPrecompileInput, ReadPrecompileResult)>);
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Default)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Default, Hash)]
|
||||
pub struct ReadPrecompileCalls(pub Vec<ReadPrecompileCall>);
|
||||
|
||||
pub(crate) mod reth_compat;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
#[derive(
|
||||
Debug, Clone, Serialize, Deserialize, Default, RlpEncodable, RlpDecodable, Eq, PartialEq, Hash,
|
||||
)]
|
||||
#[rlp(trailing)]
|
||||
pub struct HlExtras {
|
||||
pub read_precompile_calls: Option<ReadPrecompileCalls>,
|
||||
pub highest_precompile_address: Option<Address>,
|
||||
}
|
||||
|
||||
impl InMemorySize for HlExtras {
|
||||
fn size(&self) -> usize {
|
||||
self.read_precompile_calls.as_ref().map_or(0, |s| s.0.len())
|
||||
+ self.highest_precompile_address.as_ref().map_or(0, |_| 20)
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for ReadPrecompileCalls {
|
||||
fn encode(&self, out: &mut dyn BufMut) {
|
||||
let buf: Bytes = rmp_serde::to_vec(&self.0).unwrap().into();
|
||||
@ -56,6 +69,7 @@ impl BlockAndReceipts {
|
||||
self.read_precompile_calls.clone(),
|
||||
self.highest_precompile_address,
|
||||
self.system_txs.clone(),
|
||||
self.receipts.clone(),
|
||||
chain_id,
|
||||
)
|
||||
}
|
||||
@ -84,6 +98,23 @@ pub struct LegacyReceipt {
|
||||
logs: Vec<Log>,
|
||||
}
|
||||
|
||||
impl From<LegacyReceipt> for EthereumReceipt {
|
||||
fn from(r: LegacyReceipt) -> Self {
|
||||
EthereumReceipt {
|
||||
tx_type: match r.tx_type {
|
||||
LegacyTxType::Legacy => TxType::Legacy,
|
||||
LegacyTxType::Eip2930 => TxType::Eip2930,
|
||||
LegacyTxType::Eip1559 => TxType::Eip1559,
|
||||
LegacyTxType::Eip4844 => TxType::Eip4844,
|
||||
LegacyTxType::Eip7702 => TxType::Eip7702,
|
||||
},
|
||||
success: r.success,
|
||||
cumulative_gas_used: r.cumulative_gas_used,
|
||||
logs: r.logs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
enum LegacyTxType {
|
||||
Legacy = 0,
|
||||
@ -117,7 +148,7 @@ pub struct ReadPrecompileInput {
|
||||
pub gas_limit: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
|
||||
pub enum ReadPrecompileResult {
|
||||
Ok { gas_used: u64, bytes: Bytes },
|
||||
OutOfGas,
|
||||
|
||||
@ -10,11 +10,11 @@ use std::{
|
||||
use tracing::info;
|
||||
|
||||
use crate::{
|
||||
HlBlock, HlBlockBody,
|
||||
HlBlock, HlBlockBody, HlHeader,
|
||||
node::{
|
||||
primitives::TransactionSigned as TxSigned,
|
||||
spot_meta::{SpotId, erc20_contract_to_spot_token},
|
||||
types::{ReadPrecompileCalls, SystemTx},
|
||||
types::{LegacyReceipt, ReadPrecompileCalls, SystemTx},
|
||||
},
|
||||
};
|
||||
|
||||
@ -114,22 +114,36 @@ impl SealedBlock {
|
||||
read_precompile_calls: ReadPrecompileCalls,
|
||||
highest_precompile_address: Option<Address>,
|
||||
system_txs: Vec<super::SystemTx>,
|
||||
receipts: Vec<LegacyReceipt>,
|
||||
chain_id: u64,
|
||||
) -> HlBlock {
|
||||
let mut merged_txs = vec![];
|
||||
merged_txs.extend(system_txs.iter().map(|tx| system_tx_to_reth_transaction(tx, chain_id)));
|
||||
merged_txs.extend(self.body.transactions.iter().map(|tx| tx.to_reth_transaction()));
|
||||
|
||||
let mut merged_receipts = vec![];
|
||||
merged_receipts.extend(system_txs.iter().map(|tx| tx.receipt.clone().unwrap().into()));
|
||||
merged_receipts.extend(receipts.into_iter().map(From::from));
|
||||
|
||||
let block_body = HlBlockBody {
|
||||
inner: reth_primitives::BlockBody {
|
||||
transactions: merged_txs,
|
||||
withdrawals: self.body.withdrawals.clone(),
|
||||
ommers: self.body.ommers.clone(),
|
||||
ommers: vec![],
|
||||
},
|
||||
sidecars: None,
|
||||
read_precompile_calls: Some(read_precompile_calls),
|
||||
highest_precompile_address,
|
||||
};
|
||||
|
||||
HlBlock { header: self.header.header.clone(), body: block_body }
|
||||
let system_tx_count = system_txs.len() as u64;
|
||||
HlBlock {
|
||||
header: HlHeader::from_ethereum_header(
|
||||
self.header.header.clone(),
|
||||
&merged_receipts,
|
||||
system_tx_count,
|
||||
),
|
||||
body: block_body,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user