1use std::convert::Infallible;
7
8use alloy_consensus::{BlockHeader, Header};
9use alloy_primitives::{B256, U256};
10use alloy_rpc_types_eth::Header as RpcHeader;
11use alloy_serde::WithOtherFields;
12use reth_primitives_traits::SealedHeader;
13use reth_rpc_convert::transaction::HeaderConverter;
14
15pub fn l1_block_number_from_mix_hash(mix_hash: &B256) -> u64 {
17 u64::from_be_bytes(mix_hash.0[8..16].try_into().unwrap_or_default())
18}
19
20#[derive(Debug, Clone)]
22pub struct ArbHeaderConverter;
23
24impl HeaderConverter<Header, WithOtherFields<RpcHeader<Header>>> for ArbHeaderConverter {
25 type Err = Infallible;
26
27 fn convert_header(
28 &self,
29 header: SealedHeader<Header>,
30 block_size: usize,
31 ) -> Result<WithOtherFields<RpcHeader<Header>>, Self::Err> {
32 let mix = header.mix_hash().unwrap_or_default();
33 let extra = header.extra_data();
34
35 let send_count = u64::from_be_bytes(mix.0[0..8].try_into().unwrap_or_default());
37 let l1_block_number = u64::from_be_bytes(mix.0[8..16].try_into().unwrap_or_default());
38
39 let send_root = if extra.len() >= 32 {
41 B256::from_slice(&extra[..32])
42 } else {
43 B256::ZERO
44 };
45
46 let base_header =
47 RpcHeader::from_consensus(header.into(), None, Some(U256::from(block_size)));
48
49 let mut other = std::collections::BTreeMap::new();
50 other.insert(
51 "sendRoot".to_string(),
52 serde_json::to_value(send_root).unwrap_or_default(),
53 );
54 other.insert(
55 "sendCount".to_string(),
56 serde_json::to_value(format!("{send_count:#x}")).unwrap_or_default(),
57 );
58 other.insert(
59 "l1BlockNumber".to_string(),
60 serde_json::to_value(format!("{l1_block_number:#x}")).unwrap_or_default(),
61 );
62
63 Ok(WithOtherFields {
64 inner: base_header,
65 other: alloy_serde::OtherFields::new(other),
66 })
67 }
68}