reth_db_models/
blocks.rs

1use std::ops::Range;
2
3use alloy_eips::eip4895::Withdrawals;
4use alloy_primitives::TxNumber;
5use reth_codecs::{add_arbitrary_tests, Compact};
6use serde::{Deserialize, Serialize};
7
8/// Total number of transactions.
9pub type NumTransactions = u64;
10
11/// The storage of the block body indices.
12///
13/// It has the pointer to the transaction Number of the first
14/// transaction in the block and the total number of transactions.
15#[derive(Debug, Default, Eq, PartialEq, Clone, Copy, Serialize, Deserialize, Compact)]
16#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
17#[add_arbitrary_tests(compact)]
18pub struct StoredBlockBodyIndices {
19    /// The number of the first transaction in this block
20    ///
21    /// Note: If the block is empty, this is the number of the first transaction
22    /// in the next non-empty block.
23    pub first_tx_num: TxNumber,
24    /// The total number of transactions in the block
25    ///
26    /// NOTE: Number of transitions is equal to number of transactions with
27    /// additional transition for block change if block has block reward or withdrawal.
28    pub tx_count: NumTransactions,
29}
30
31impl StoredBlockBodyIndices {
32    /// Return the range of transaction ids for this block.
33    pub const fn tx_num_range(&self) -> Range<TxNumber> {
34        self.first_tx_num..self.first_tx_num + self.tx_count
35    }
36
37    /// Return the index of last transaction in this block unless the block
38    /// is empty in which case it refers to the last transaction in a previous
39    /// non-empty block
40    pub const fn last_tx_num(&self) -> TxNumber {
41        self.first_tx_num.saturating_add(self.tx_count).saturating_sub(1)
42    }
43
44    /// First transaction index.
45    ///
46    /// Caution: If the block is empty, this is the number of the first transaction
47    /// in the next non-empty block.
48    pub const fn first_tx_num(&self) -> TxNumber {
49        self.first_tx_num
50    }
51
52    /// Return the index of the next transaction after this block.
53    pub const fn next_tx_num(&self) -> TxNumber {
54        self.first_tx_num + self.tx_count
55    }
56
57    /// Return a flag whether the block is empty
58    pub const fn is_empty(&self) -> bool {
59        self.tx_count == 0
60    }
61
62    /// Return number of transaction inside block
63    ///
64    /// NOTE: This is not the same as the number of transitions.
65    pub const fn tx_count(&self) -> NumTransactions {
66        self.tx_count
67    }
68}
69
70/// The storage representation of block withdrawals.
71#[derive(Debug, Default, Eq, PartialEq, Clone, Serialize, Deserialize, Compact)]
72#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
73#[add_arbitrary_tests(compact)]
74pub struct StoredBlockWithdrawals {
75    /// The block withdrawals.
76    pub withdrawals: Withdrawals,
77}
78
79#[cfg(test)]
80mod tests {
81    use crate::StoredBlockBodyIndices;
82
83    #[test]
84    fn block_indices() {
85        let first_tx_num = 10;
86        let tx_count = 6;
87        let block_indices = StoredBlockBodyIndices { first_tx_num, tx_count };
88
89        assert_eq!(block_indices.first_tx_num(), first_tx_num);
90        assert_eq!(block_indices.last_tx_num(), first_tx_num + tx_count - 1);
91        assert_eq!(block_indices.next_tx_num(), first_tx_num + tx_count);
92        assert_eq!(block_indices.tx_count(), tx_count);
93        assert_eq!(block_indices.tx_num_range(), first_tx_num..first_tx_num + tx_count);
94    }
95}