agglayer_config/
epoch.rs

1use std::{num::NonZeroU64, time::Duration};
2
3use serde::{Deserialize, Serialize};
4
5/// The Epoch configuration.
6#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
7#[serde(rename_all = "kebab-case")]
8pub enum Epoch {
9    TimeClock(TimeClockConfig),
10    BlockClock(BlockClockConfig),
11}
12
13impl Default for Epoch {
14    fn default() -> Self {
15        Self::BlockClock(BlockClockConfig::default())
16    }
17}
18
19#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
20#[serde(rename_all = "kebab-case")]
21pub struct BlockClockConfig {
22    #[serde(default = "default_block_epoch_duration")]
23    pub epoch_duration: NonZeroU64,
24
25    #[serde(default = "default_genesis_block")]
26    pub genesis_block: u64,
27}
28
29impl Default for BlockClockConfig {
30    fn default() -> Self {
31        Self {
32            epoch_duration: default_block_epoch_duration(),
33            genesis_block: default_genesis_block(),
34        }
35    }
36}
37
38#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
39#[serde(rename_all = "kebab-case")]
40pub struct TimeClockConfig {
41    #[serde(
42        default = "default_epoch_duration",
43        with = "crate::with::HumanDuration",
44        alias = "EpochDuration"
45    )]
46    pub epoch_duration: Duration,
47}
48
49impl Default for TimeClockConfig {
50    fn default() -> Self {
51        Self {
52            epoch_duration: default_epoch_duration(),
53        }
54    }
55}
56
57// We estimate the block time of L1 to 10min.
58// The goal is to have an epoch duration of 1h.
59// So we need 6 blocks per epoch.
60fn default_block_epoch_duration() -> NonZeroU64 {
61    NonZeroU64::new(6).unwrap()
62}
63
64const fn default_genesis_block() -> u64 {
65    0
66}
67
68fn default_epoch_duration() -> Duration {
69    Duration::from_secs(60)
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn serialize_epoch() {
78        let epoch = Epoch::TimeClock(TimeClockConfig::default());
79        let serialized = serde_json::to_string(&epoch).unwrap();
80
81        assert_eq!(serialized, r#"{"time-clock":{"epoch-duration":"1m"}}"#);
82    }
83
84    #[test]
85    fn deserialize_epoch() {
86        let config = r#"{"time-clock":{"epoch-duration":3600}}"#;
87
88        let expected_duration = Duration::from_secs(3600);
89        let epoch: Epoch = serde_json::from_str(config).unwrap();
90
91        assert!(
92            matches!(epoch, Epoch::TimeClock(TimeClockConfig { epoch_duration }) if epoch_duration == expected_duration)
93        );
94    }
95}