feat: Introduce HlHeader

This commit is contained in:
sprites0
2025-10-05 23:34:04 +00:00
parent 8b2c3a4a34
commit 567d6ce2e4
3 changed files with 202 additions and 3 deletions

View File

@ -0,0 +1,187 @@
use alloy_consensus::Header;
use alloy_primitives::{Address, B64, B256, BlockNumber, Bloom, Bytes, Sealable, U256};
use alloy_rlp::{RlpDecodable, RlpEncodable};
use reth_codecs::Compact;
use reth_primitives_traits::{BlockHeader, InMemorySize, serde_bincode_compat::RlpBincode};
use serde::{Deserialize, Serialize};
use crate::node::types::HlExtras;
/// 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]
#[serde(flatten)]
pub inner: Header,
/// The extended header fields that is not part of the block hash
pub logs_bloom_with_system_txs: Bloom,
pub system_tx_count: u64,
pub read_precompile_calls: HlExtras,
}
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.inner.logs_bloom()
}
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()
}
}
impl InMemorySize for HlHeader {
fn size(&self) -> usize {
self.inner.size()
+ self.logs_bloom_with_system_txs.data().len()
+ self.system_tx_count.size()
+ self.read_precompile_calls.size()
}
}
impl reth_codecs::Compact for HlHeader {
fn to_compact<B>(&self, buf: &mut B) -> usize
where
B: alloy_rlp::bytes::BufMut + AsMut<[u8]>,
{
// It's too tedious to implement to_compact for every field, so use rmp_serde to serialize
// This also helps the struct to be upgradable in future thanks to serde's flexibility.
let result: Bytes = rmp_serde::to_vec(&self).unwrap().into();
result.to_compact(buf)
}
fn from_compact(buf: &[u8], identifier: usize) -> (Self, &[u8]) {
let header: HlHeader = rmp_serde::from_slice(&buf[identifier..]).unwrap();
(header, &buf[identifier + buf.len()..])
}
}
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 {}

View File

@ -9,6 +9,7 @@ pub mod block;
pub use block::HlBlock;
pub mod body;
pub use body::HlBlockBody;
pub mod header;
pub mod rlp;
pub mod serde_bincode_compat;

View File

@ -5,23 +5,34 @@
use alloy_primitives::{Address, B256, Bytes, Log};
use alloy_rlp::{Decodable, Encodable, RlpDecodable, RlpEncodable};
use bytes::BufMut;
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();
@ -117,7 +128,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,