iota_core/authority/
epoch_start_configuration.rs1use std::fmt;
6
7use enum_dispatch::enum_dispatch;
8use iota_config::{ExecutionCacheConfig, NodeConfig};
9use iota_types::{
10 authenticator_state::get_authenticator_state_obj_initial_shared_version,
11 base_types::SequenceNumber,
12 deny_list_v1::get_deny_list_obj_initial_shared_version,
13 epoch_data::EpochData,
14 error::IotaResult,
15 iota_system_state::epoch_start_iota_system_state::{
16 EpochStartSystemState, EpochStartSystemStateTrait,
17 },
18 messages_checkpoint::{CheckpointDigest, CheckpointTimestamp},
19 randomness_state::get_randomness_state_obj_initial_shared_version,
20 storage::ObjectStore,
21};
22use serde::{Deserialize, Serialize};
23
24use crate::execution_cache::{ExecutionCacheConfigType, choose_execution_cache};
25
26#[enum_dispatch]
27pub trait EpochStartConfigTrait {
28 fn epoch_digest(&self) -> CheckpointDigest;
29 fn epoch_start_state(&self) -> &EpochStartSystemState;
30 fn flags(&self) -> &[EpochFlag];
31 fn authenticator_obj_initial_shared_version(&self) -> Option<SequenceNumber>;
32 fn randomness_obj_initial_shared_version(&self) -> SequenceNumber;
33 fn coin_deny_list_obj_initial_shared_version(&self) -> SequenceNumber;
34
35 fn execution_cache_type(&self) -> ExecutionCacheConfigType {
36 if self.flags().contains(&EpochFlag::WritebackCacheEnabled) {
37 ExecutionCacheConfigType::WritebackCache
38 } else {
39 ExecutionCacheConfigType::PassthroughCache
40 }
41 }
42}
43
44#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
53pub enum EpochFlag {
54 WritebackCacheEnabled = 0,
55}
56
57impl EpochFlag {
58 pub fn default_flags_for_new_epoch(config: &NodeConfig) -> Vec<Self> {
59 Self::default_flags_impl(&config.execution_cache)
60 }
61
62 pub fn default_for_no_config() -> Vec<Self> {
65 Self::default_flags_impl(&Default::default())
66 }
67
68 fn default_flags_impl(cache_config: &ExecutionCacheConfig) -> Vec<Self> {
69 let mut new_flags = vec![];
70
71 if matches!(
72 choose_execution_cache(cache_config),
73 ExecutionCacheConfigType::WritebackCache
74 ) {
75 new_flags.push(EpochFlag::WritebackCacheEnabled);
76 }
77
78 new_flags
79 }
80}
81
82impl fmt::Display for EpochFlag {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 match self {
87 EpochFlag::WritebackCacheEnabled => write!(f, "WritebackCacheEnabled"),
88 }
89 }
90}
91
92#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
94#[enum_dispatch(EpochStartConfigTrait)]
95pub enum EpochStartConfiguration {
96 V1(EpochStartConfigurationV1),
97 V2(EpochStartConfigurationV2),
98}
99
100impl EpochStartConfiguration {
101 pub fn new(
102 system_state: EpochStartSystemState,
103 epoch_digest: CheckpointDigest,
104 object_store: &dyn ObjectStore,
105 initial_epoch_flags: Vec<EpochFlag>,
106 ) -> IotaResult<Self> {
107 let authenticator_obj_initial_shared_version =
108 get_authenticator_state_obj_initial_shared_version(object_store)?;
109 let randomness_obj_initial_shared_version =
110 get_randomness_state_obj_initial_shared_version(object_store)?;
111 let coin_deny_list_obj_initial_shared_version =
112 get_deny_list_obj_initial_shared_version(object_store)?;
113 Ok(Self::V2(EpochStartConfigurationV2 {
114 system_state,
115 epoch_digest,
116 flags: initial_epoch_flags,
117 authenticator_obj_initial_shared_version,
118 randomness_obj_initial_shared_version,
119 coin_deny_list_obj_initial_shared_version,
120 }))
121 }
122
123 #[expect(unreachable_patterns)]
124 pub fn new_at_next_epoch_for_testing(&self) -> Self {
125 match self {
128 Self::V1(config) => Self::V1(EpochStartConfigurationV1 {
129 system_state: config.system_state.new_at_next_epoch_for_testing(),
130 epoch_digest: config.epoch_digest,
131 flags: config.flags.clone(),
132 authenticator_obj_initial_shared_version: config
133 .authenticator_obj_initial_shared_version,
134 randomness_obj_initial_shared_version: config.randomness_obj_initial_shared_version,
135 coin_deny_list_obj_initial_shared_version: config
136 .coin_deny_list_obj_initial_shared_version,
137 bridge_obj_initial_shared_version: config.bridge_obj_initial_shared_version,
138 bridge_committee_initiated: config.bridge_committee_initiated,
139 }),
140 Self::V2(config) => Self::V2(EpochStartConfigurationV2 {
141 system_state: config.system_state.new_at_next_epoch_for_testing(),
142 epoch_digest: config.epoch_digest,
143 flags: config.flags.clone(),
144 authenticator_obj_initial_shared_version: config
145 .authenticator_obj_initial_shared_version,
146 randomness_obj_initial_shared_version: config.randomness_obj_initial_shared_version,
147 coin_deny_list_obj_initial_shared_version: config
148 .coin_deny_list_obj_initial_shared_version,
149 }),
150 _ => panic!(
151 "This function is only implemented for the latest version of EpochStartConfiguration"
152 ),
153 }
154 }
155
156 pub fn epoch_data(&self) -> EpochData {
157 EpochData::new(
158 self.epoch_start_state().epoch(),
159 self.epoch_start_state().epoch_start_timestamp_ms(),
160 self.epoch_digest(),
161 )
162 }
163
164 pub fn epoch_start_timestamp_ms(&self) -> CheckpointTimestamp {
165 self.epoch_start_state().epoch_start_timestamp_ms()
166 }
167}
168
169#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
170pub struct EpochStartConfigurationV1 {
171 system_state: EpochStartSystemState,
172 epoch_digest: CheckpointDigest,
173 flags: Vec<EpochFlag>,
174 authenticator_obj_initial_shared_version: Option<SequenceNumber>,
176 randomness_obj_initial_shared_version: SequenceNumber,
177 coin_deny_list_obj_initial_shared_version: SequenceNumber,
178 bridge_obj_initial_shared_version: Option<SequenceNumber>,
179 bridge_committee_initiated: bool,
180}
181
182impl EpochStartConfigTrait for EpochStartConfigurationV1 {
183 fn epoch_digest(&self) -> CheckpointDigest {
184 self.epoch_digest
185 }
186
187 fn epoch_start_state(&self) -> &EpochStartSystemState {
188 &self.system_state
189 }
190
191 fn flags(&self) -> &[EpochFlag] {
192 &self.flags
193 }
194
195 fn authenticator_obj_initial_shared_version(&self) -> Option<SequenceNumber> {
196 self.authenticator_obj_initial_shared_version
197 }
198
199 fn randomness_obj_initial_shared_version(&self) -> SequenceNumber {
200 self.randomness_obj_initial_shared_version
201 }
202
203 fn coin_deny_list_obj_initial_shared_version(&self) -> SequenceNumber {
204 self.coin_deny_list_obj_initial_shared_version
205 }
206}
207
208#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
209pub struct EpochStartConfigurationV2 {
210 system_state: EpochStartSystemState,
211 epoch_digest: CheckpointDigest,
212 flags: Vec<EpochFlag>,
213 authenticator_obj_initial_shared_version: Option<SequenceNumber>,
215 randomness_obj_initial_shared_version: SequenceNumber,
216 coin_deny_list_obj_initial_shared_version: SequenceNumber,
217}
218
219impl EpochStartConfigTrait for EpochStartConfigurationV2 {
220 fn epoch_digest(&self) -> CheckpointDigest {
221 self.epoch_digest
222 }
223
224 fn epoch_start_state(&self) -> &EpochStartSystemState {
225 &self.system_state
226 }
227
228 fn flags(&self) -> &[EpochFlag] {
229 &self.flags
230 }
231
232 fn authenticator_obj_initial_shared_version(&self) -> Option<SequenceNumber> {
233 self.authenticator_obj_initial_shared_version
234 }
235
236 fn randomness_obj_initial_shared_version(&self) -> SequenceNumber {
237 self.randomness_obj_initial_shared_version
238 }
239
240 fn coin_deny_list_obj_initial_shared_version(&self) -> SequenceNumber {
241 self.coin_deny_list_obj_initial_shared_version
242 }
243}