#[doc(hidden)]
pub const STR_002_MODULE_PRESENT: () = ();
use chia_protocol::Bytes32;
use dig_block::Checkpoint;
use serde::{Deserialize, Serialize};
use crate::constants::{
BLOCKS_PER_EPOCH, EMPTY_ROOT, EPOCH_L1_BLOCKS, PHASE_BLOCK_PRODUCTION_END_PCT,
PHASE_CHECKPOINT_END_PCT, PHASE_FINALIZATION_END_PCT,
};
use crate::error::EpochError;
use crate::types::epoch_phase::EpochPhase;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EpochInfo {
pub epoch: u64,
pub start_l1_height: u32,
pub end_l1_height: u32,
pub start_l2_height: u64,
pub blocks_produced: u32,
pub phase: EpochPhase,
pub total_fees: u64,
pub total_transactions: u64,
pub checkpoint: Option<Checkpoint>,
pub start_state_root: Bytes32,
pub collateral_registry_root: Bytes32,
pub cid_state_root: Bytes32,
pub node_registry_root: Bytes32,
pub namespace_epoch_root: Bytes32,
pub dfsp_issuance_total: u64,
pub active_cid_count: u32,
pub active_node_count: u32,
}
impl EpochInfo {
pub fn new(
epoch: u64,
start_l1_height: u32,
start_l2_height: u64,
start_state_root: Bytes32,
) -> Self {
Self {
epoch,
start_l1_height,
end_l1_height: start_l1_height + EPOCH_L1_BLOCKS,
start_l2_height,
blocks_produced: 0,
phase: EpochPhase::BlockProduction,
total_fees: 0,
total_transactions: 0,
checkpoint: None,
start_state_root,
collateral_registry_root: EMPTY_ROOT,
cid_state_root: EMPTY_ROOT,
node_registry_root: EMPTY_ROOT,
namespace_epoch_root: EMPTY_ROOT,
dfsp_issuance_total: 0,
active_cid_count: 0,
active_node_count: 0,
}
}
pub fn target_blocks(&self) -> u64 {
BLOCKS_PER_EPOCH
}
pub fn can_produce_blocks(&self) -> bool {
self.phase == EpochPhase::BlockProduction
}
pub fn can_submit_checkpoint(&self) -> bool {
self.phase == EpochPhase::Checkpoint
}
pub fn is_complete(&self) -> bool {
self.phase == EpochPhase::Complete
}
pub fn is_finalized(&self) -> bool {
self.checkpoint.is_some()
}
pub fn record_block(&mut self, fees: u64, tx_count: u64) {
self.blocks_produced += 1;
self.total_fees += fees;
self.total_transactions += tx_count;
}
pub fn set_checkpoint(&mut self, checkpoint: Checkpoint) {
self.checkpoint = Some(checkpoint);
}
pub fn progress_percentage(&self, current_l1_height: u32) -> u32 {
if current_l1_height <= self.start_l1_height {
return 0;
}
let elapsed = (current_l1_height - self.start_l1_height) as u64;
let pct = elapsed * 100 / EPOCH_L1_BLOCKS as u64;
pct.min(100) as u32
}
pub fn calculate_phase(&self, current_l1_height: u32) -> EpochPhase {
let pct = self.progress_percentage(current_l1_height);
if pct < PHASE_BLOCK_PRODUCTION_END_PCT {
EpochPhase::BlockProduction
} else if pct < PHASE_CHECKPOINT_END_PCT {
EpochPhase::Checkpoint
} else if pct < PHASE_FINALIZATION_END_PCT {
EpochPhase::Finalization
} else {
EpochPhase::Complete
}
}
pub fn to_bytes(&self) -> Vec<u8> {
bincode::serialize(self).expect("EpochInfo serialization should never fail")
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, EpochError> {
bincode::deserialize(bytes).map_err(|e| EpochError::InvalidData(e.to_string()))
}
}