stratus/eth/primitives/
external_block.rs1#[cfg(test)]
2use alloy_eips::eip4895::Withdrawals;
3#[cfg(test)]
4use alloy_primitives::B64;
5#[cfg(test)]
6use alloy_primitives::B256;
7#[cfg(test)]
8use alloy_primitives::Bloom;
9#[cfg(test)]
10use alloy_primitives::Bytes;
11#[cfg(test)]
12use alloy_primitives::U256;
13#[cfg(test)]
14use fake::Dummy;
15#[cfg(test)]
16use fake::Fake;
17#[cfg(test)]
18use fake::Faker;
19use serde::Deserialize;
20
21use super::Block;
22use crate::alias::AlloyBlockExternalTransaction;
23use crate::alias::JsonValue;
24use crate::eth::primitives::Address;
25use crate::eth::primitives::BlockNumber;
26use crate::eth::primitives::Hash;
27use crate::eth::primitives::UnixTime;
28#[cfg(test)]
29use crate::eth::primitives::external_transaction::ExternalTransaction;
30use crate::log_and_err;
31
32#[derive(Debug, Clone, PartialEq, derive_more::Deref, derive_more::DerefMut, serde::Deserialize, serde::Serialize)]
33#[serde(transparent)]
34pub struct ExternalBlock(#[deref] pub AlloyBlockExternalTransaction);
35
36impl ExternalBlock {
37 #[allow(clippy::expect_used)]
39 pub fn hash(&self) -> Hash {
40 Hash::from(self.0.header.hash)
41 }
42
43 #[allow(clippy::expect_used)]
45 pub fn number(&self) -> BlockNumber {
46 BlockNumber::from(self.0.header.inner.number)
47 }
48
49 pub fn timestamp(&self) -> UnixTime {
51 self.0.header.inner.timestamp.into()
52 }
53
54 pub fn author(&self) -> Address {
56 self.0.header.inner.beneficiary.into()
57 }
58}
59
60impl PartialEq<Block> for ExternalBlock {
61 fn eq(&self, other: &Block) -> bool {
62 self.number() == other.number() && self.timestamp() == other.header.timestamp && self.hash() == other.header.hash
63 }
64}
65
66#[cfg(test)]
67impl Dummy<Faker> for ExternalBlock {
68 fn dummy_with_rng<R: rand::Rng + ?Sized>(faker: &Faker, rng: &mut R) -> Self {
69 let mut addr_bytes = [0u8; 20];
70 let mut hash_bytes = [0u8; 32];
71 let mut nonce_bytes = [0u8; 8];
72 rng.fill_bytes(&mut addr_bytes);
73 rng.fill_bytes(&mut hash_bytes);
74 rng.fill_bytes(&mut nonce_bytes);
75
76 let transaction: ExternalTransaction = faker.fake_with_rng(rng);
77
78 let block = alloy_rpc_types_eth::Block {
79 header: alloy_rpc_types_eth::Header {
80 hash: B256::from_slice(&hash_bytes),
81 inner: alloy_consensus::Header {
82 parent_hash: B256::from_slice(&hash_bytes),
83 ommers_hash: B256::from_slice(&hash_bytes),
84 beneficiary: alloy_primitives::Address::from_slice(&addr_bytes),
85 state_root: B256::from_slice(&hash_bytes),
86 transactions_root: B256::from_slice(&hash_bytes),
87 receipts_root: B256::from_slice(&hash_bytes),
88 withdrawals_root: Some(B256::from_slice(&hash_bytes)),
89 number: rng.next_u64(),
90 gas_used: rng.next_u64(),
91 gas_limit: rng.next_u64(),
92 extra_data: Bytes::default(),
93 logs_bloom: Bloom::default(),
94 timestamp: rng.next_u64(),
95 difficulty: U256::from(rng.next_u64()),
96 mix_hash: B256::from_slice(&hash_bytes),
97 nonce: B64::from_slice(&nonce_bytes),
98 base_fee_per_gas: Some(rng.next_u64()),
99 blob_gas_used: None,
100 excess_blob_gas: None,
101 parent_beacon_block_root: None,
102 requests_hash: None,
103 },
104 total_difficulty: Some(U256::from(rng.next_u64())),
105 size: Some(U256::from(rng.next_u64())),
106 },
107 uncles: vec![B256::from_slice(&hash_bytes)],
108 transactions: alloy_rpc_types_eth::BlockTransactions::Full(vec![transaction]),
109 withdrawals: Some(Withdrawals::default()),
110 };
111
112 ExternalBlock(block)
113 }
114}
115
116impl TryFrom<JsonValue> for ExternalBlock {
121 type Error = anyhow::Error;
122
123 fn try_from(value: JsonValue) -> Result<Self, Self::Error> {
124 match ExternalBlock::deserialize(&value) {
125 Ok(v) => Ok(v),
126 Err(e) => log_and_err!(reason = e, payload = value, "failed to convert payload value to ExternalBlock"),
127 }
128 }
129}