1use alloy_eips::eip4895::Withdrawals;
2use alloy_primitives::TxNumber;
3use core::ops::Range;
4
5pub type NumTransactions = u64;
7
8#[derive(Debug, Default, Eq, PartialEq, Clone, Copy)]
13#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
14#[cfg_attr(any(test, feature = "reth-codec"), derive(reth_codecs::Compact))]
15#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17pub struct StoredBlockBodyIndices {
18 pub first_tx_num: TxNumber,
23 pub tx_count: NumTransactions,
28}
29
30impl StoredBlockBodyIndices {
31 pub const fn tx_num_range(&self) -> Range<TxNumber> {
33 self.first_tx_num..self.first_tx_num + self.tx_count
34 }
35
36 pub const fn last_tx_num(&self) -> TxNumber {
40 self.first_tx_num.saturating_add(self.tx_count).saturating_sub(1)
41 }
42
43 pub const fn first_tx_num(&self) -> TxNumber {
48 self.first_tx_num
49 }
50
51 pub const fn next_tx_num(&self) -> TxNumber {
53 self.first_tx_num + self.tx_count
54 }
55
56 pub const fn is_empty(&self) -> bool {
58 self.tx_count == 0
59 }
60
61 pub const fn tx_count(&self) -> NumTransactions {
65 self.tx_count
66 }
67}
68
69#[derive(Debug, Default, Eq, PartialEq, Clone)]
71#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
72#[cfg_attr(any(test, feature = "reth-codec"), derive(reth_codecs::Compact))]
73#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))]
74#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
75pub struct StoredBlockWithdrawals {
76 pub withdrawals: Withdrawals,
78}
79
80#[derive(Debug, Default, Eq, PartialEq, Clone)]
83#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
84#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))]
85#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
86pub struct StaticFileBlockWithdrawals {
87 pub withdrawals: Option<Withdrawals>,
89}
90
91#[cfg(any(test, feature = "reth-codec"))]
92impl reth_codecs::Compact for StaticFileBlockWithdrawals {
93 fn to_compact<B>(&self, buf: &mut B) -> usize
94 where
95 B: bytes::BufMut + AsMut<[u8]>,
96 {
97 buf.put_u8(self.withdrawals.is_some() as u8);
98 if let Some(withdrawals) = &self.withdrawals {
99 return 1 + withdrawals.to_compact(buf);
100 }
101 1
102 }
103 fn from_compact(mut buf: &[u8], _: usize) -> (Self, &[u8]) {
104 use bytes::Buf;
105 if buf.get_u8() == 1 {
106 let (w, buf) = Withdrawals::from_compact(buf, buf.len());
107 (Self { withdrawals: Some(w) }, buf)
108 } else {
109 (Self { withdrawals: None }, buf)
110 }
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use crate::StoredBlockBodyIndices;
117
118 #[test]
119 fn block_indices() {
120 let first_tx_num = 10;
121 let tx_count = 6;
122 let block_indices = StoredBlockBodyIndices { first_tx_num, tx_count };
123
124 assert_eq!(block_indices.first_tx_num(), first_tx_num);
125 assert_eq!(block_indices.last_tx_num(), first_tx_num + tx_count - 1);
126 assert_eq!(block_indices.next_tx_num(), first_tx_num + tx_count);
127 assert_eq!(block_indices.tx_count(), tx_count);
128 assert_eq!(block_indices.tx_num_range(), first_tx_num..first_tx_num + tx_count);
129 }
130}