Skip to main content

miden_protocol/block/
block_number.rs

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