miden_objects/block/
block_number.rs

1use core::{fmt, ops::Add};
2
3use super::Felt;
4use crate::utils::serde::{
5    ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
6};
7
8// BLOCK NUMBER
9// ================================================================================================
10
11/// A convenience wrapper around a `u32` representing the number of a block.
12///
13/// Each block has a unique number and block numbers increase monotonically by `1`.
14#[derive(Debug, Default, Eq, PartialEq, Copy, Clone, PartialOrd, Ord, Hash)]
15pub struct BlockNumber(u32);
16
17impl BlockNumber {
18    /// The length of an epoch expressed as a power of two. `2^(EPOCH_LENGTH_EXPONENT)` is the
19    /// number of blocks in an epoch.
20    ///
21    /// The epoch of a block can be obtained by shifting the block number to the right by this
22    /// exponent.
23    pub const EPOCH_LENGTH_EXPONENT: u8 = 16;
24
25    /// The block height of the genesis block.
26    pub const GENESIS: Self = Self(0);
27
28    /// Returns the previous block number
29    pub fn parent(self) -> Option<BlockNumber> {
30        self.checked_sub(1)
31    }
32
33    /// Returns the next block number
34    pub fn child(self) -> BlockNumber {
35        self + 1
36    }
37
38    /// Creates the [`BlockNumber`] corresponding to the epoch block for the provided `epoch`.
39    pub const fn from_epoch(epoch: u16) -> BlockNumber {
40        BlockNumber((epoch as u32) << BlockNumber::EPOCH_LENGTH_EXPONENT)
41    }
42
43    /// Creates a `BlockNumber` from a `usize`.
44    pub fn from_usize(value: usize) -> Self {
45        BlockNumber(value as u32)
46    }
47
48    /// Returns the epoch to which this block number belongs.
49    pub const fn block_epoch(&self) -> u16 {
50        (self.0 >> BlockNumber::EPOCH_LENGTH_EXPONENT) as u16
51    }
52
53    /// Returns the block number as a `u32`.
54    pub fn as_u32(&self) -> u32 {
55        self.0
56    }
57
58    /// Returns the block number as a `u64`.
59    pub fn as_u64(&self) -> u64 {
60        self.0 as u64
61    }
62
63    /// Returns the block number as a `usize`.
64    pub fn as_usize(&self) -> usize {
65        self.0 as usize
66    }
67
68    /// Checked integer subtraction. Computes `self - rhs`, returning `None` if underflow occurred.
69    pub fn checked_sub(&self, rhs: u32) -> Option<Self> {
70        self.0.checked_sub(rhs).map(Self)
71    }
72}
73
74impl Add<u32> for BlockNumber {
75    type Output = Self;
76
77    fn add(self, other: u32) -> Self::Output {
78        BlockNumber(self.0 + other)
79    }
80}
81
82impl Serializable for BlockNumber {
83    fn write_into<W: ByteWriter>(&self, target: &mut W) {
84        target.write_u32(self.0);
85    }
86
87    fn get_size_hint(&self) -> usize {
88        core::mem::size_of::<u32>()
89    }
90}
91
92impl Deserializable for BlockNumber {
93    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
94        source.read::<u32>().map(BlockNumber::from)
95    }
96}
97
98impl From<BlockNumber> for Felt {
99    fn from(value: BlockNumber) -> Self {
100        Felt::from(value.as_u32())
101    }
102}
103
104impl From<u32> for BlockNumber {
105    fn from(value: u32) -> Self {
106        BlockNumber(value)
107    }
108}
109
110impl fmt::Display for BlockNumber {
111    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112        write!(f, "{}", self.0)
113    }
114}