dig_epoch/types/epoch_phase.rs
1//! # `types::epoch_phase` — `EpochPhase` enum and `PhaseTransition` struct
2//!
3//! **Implemented by:** `TYP-001` — SPEC §3.2-3.3.
4
5use serde::{Deserialize, Serialize};
6
7/// Sentinel marker proving the module exists and is reachable at
8/// `dig_epoch::types::epoch_phase::STR_002_MODULE_PRESENT`.
9#[doc(hidden)]
10pub const STR_002_MODULE_PRESENT: () = ();
11
12/// The lifecycle phase of a DIG L2 epoch, driven by L1 block-height progress.
13///
14/// Phase progress is `(l1_now - epoch_start_l1) * 100 / EPOCH_L1_BLOCKS`:
15///
16/// | Range | Phase |
17/// |-------|-------|
18/// | 0 – 49 % | `BlockProduction` |
19/// | 50 – 74 % | `Checkpoint` |
20/// | 75 – 99 % | `Finalization` |
21/// | ≥ 100 % | `Complete` |
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
23pub enum EpochPhase {
24 /// Block production (0–50 % of L1 window).
25 BlockProduction,
26 /// Checkpoint submission (50–75 % of L1 window).
27 Checkpoint,
28 /// Finalization (75–100 % of L1 window).
29 Finalization,
30 /// Epoch complete (≥ 100 % of L1 window).
31 Complete,
32}
33
34impl EpochPhase {
35 /// Ordinal index: `BlockProduction=0`, `Checkpoint=1`, `Finalization=2`, `Complete=3`.
36 pub fn index(&self) -> usize {
37 match self {
38 Self::BlockProduction => 0,
39 Self::Checkpoint => 1,
40 Self::Finalization => 2,
41 Self::Complete => 3,
42 }
43 }
44
45 /// Successor phase, or `None` if already `Complete`.
46 pub fn next(&self) -> Option<EpochPhase> {
47 match self {
48 Self::BlockProduction => Some(Self::Checkpoint),
49 Self::Checkpoint => Some(Self::Finalization),
50 Self::Finalization => Some(Self::Complete),
51 Self::Complete => None,
52 }
53 }
54
55 /// Predecessor phase, or `None` if already `BlockProduction`.
56 pub fn previous(&self) -> Option<EpochPhase> {
57 match self {
58 Self::Complete => Some(Self::Finalization),
59 Self::Finalization => Some(Self::Checkpoint),
60 Self::Checkpoint => Some(Self::BlockProduction),
61 Self::BlockProduction => None,
62 }
63 }
64
65 /// Canonical string name used in Display and logging.
66 pub fn name(&self) -> &'static str {
67 match self {
68 Self::BlockProduction => "BlockProduction",
69 Self::Checkpoint => "Checkpoint",
70 Self::Finalization => "Finalization",
71 Self::Complete => "Complete",
72 }
73 }
74
75 /// Returns `true` only during `BlockProduction`.
76 pub fn allows_block_production(&self) -> bool {
77 matches!(self, Self::BlockProduction)
78 }
79
80 /// Returns `true` only during `Checkpoint`.
81 pub fn allows_checkpoint_submission(&self) -> bool {
82 matches!(self, Self::Checkpoint)
83 }
84
85 /// Returns `true` only during `Finalization`.
86 pub fn allows_finalization(&self) -> bool {
87 matches!(self, Self::Finalization)
88 }
89}
90
91impl std::fmt::Display for EpochPhase {
92 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93 f.write_str(self.name())
94 }
95}
96
97/// Records the details of a phase transition event.
98#[derive(Debug, Clone)]
99pub struct PhaseTransition {
100 /// Epoch number in which the transition occurred.
101 pub epoch: u64,
102 /// Phase before the transition.
103 pub from: EpochPhase,
104 /// Phase after the transition.
105 pub to: EpochPhase,
106 /// L1 block height at which the transition was observed.
107 pub l1_height: u32,
108}