1use super::*;
2use crate::internal_prelude::*;
3
4#[derive(Clone)]
5pub struct ProtocolBuilder {
6 settings: ProtocolSettings,
7}
8
9#[derive(Clone)]
10pub struct ProtocolSettings {
11 pub network_definition: NetworkDefinition,
12 pub babylon: BabylonSettings,
13 pub anemone: AnemoneSettings,
14 pub bottlenose: BottlenoseSettings,
15 pub cuttlefish_part1: CuttlefishPart1Settings,
16 pub cuttlefish_part2: CuttlefishPart2Settings,
17 pub dugong: DugongSettings,
18 pub eagle_ray: EagleRaySettings,
19}
20
21impl ProtocolSettings {
22 pub fn resolve_generator_for_update(
23 &self,
24 protocol_version: &ProtocolVersion,
25 ) -> Box<dyn ProtocolUpdateGenerator> {
26 match protocol_version {
27 ProtocolVersion::Unbootstrapped => Box::new(NoOpGenerator),
28 ProtocolVersion::Babylon => Box::new(self.babylon.create_generator()),
29 ProtocolVersion::Anemone => Box::new(self.anemone.create_generator()),
30 ProtocolVersion::Bottlenose => Box::new(self.bottlenose.create_generator()),
31 ProtocolVersion::CuttlefishPart1 => Box::new(self.cuttlefish_part1.create_generator()),
32 ProtocolVersion::CuttlefishPart2 => Box::new(self.cuttlefish_part2.create_generator()),
33 ProtocolVersion::Dugong => Box::new(self.dugong.create_generator()),
34 ProtocolVersion::EagleRay => Box::new(self.eagle_ray.create_generator()),
35 }
36 }
37}
38
39impl ProtocolBuilder {
40 pub fn for_simulator() -> Self {
41 Self::for_network(&NetworkDefinition::simulator())
42 }
43
44 pub fn for_network(network_definition: &NetworkDefinition) -> Self {
45 Self {
46 settings: ProtocolSettings {
47 network_definition: network_definition.clone(),
48 babylon: BabylonSettings::all_enabled_as_default_for_network(network_definition),
49 anemone: AnemoneSettings::all_enabled_as_default_for_network(network_definition),
50 bottlenose: BottlenoseSettings::all_enabled_as_default_for_network(
51 network_definition,
52 ),
53 cuttlefish_part1: CuttlefishPart1Settings::all_enabled_as_default_for_network(
54 network_definition,
55 ),
56 cuttlefish_part2: CuttlefishPart2Settings::all_enabled_as_default_for_network(
57 network_definition,
58 ),
59 dugong: DugongSettings::all_enabled_as_default_for_network(network_definition),
60 eagle_ray: EagleRaySettings::all_enabled_as_default_for_network(network_definition),
61 },
62 }
63 }
64
65 pub fn configure_babylon(
66 mut self,
67 creator: impl FnOnce(BabylonSettings) -> BabylonSettings,
68 ) -> Self {
69 self.settings.babylon = creator(self.settings.babylon);
70 self
71 }
72
73 pub fn configure_anemone(
74 mut self,
75 creator: impl FnOnce(AnemoneSettings) -> AnemoneSettings,
76 ) -> Self {
77 self.settings.anemone = creator(self.settings.anemone);
78 self
79 }
80
81 pub fn configure_bottlenose(
82 mut self,
83 creator: impl FnOnce(BottlenoseSettings) -> BottlenoseSettings,
84 ) -> Self {
85 self.settings.bottlenose = creator(self.settings.bottlenose);
86 self
87 }
88
89 pub fn configure_cuttlefish(
90 mut self,
91 creator: impl FnOnce(CuttlefishPart1Settings) -> CuttlefishPart1Settings,
92 ) -> Self {
93 self.settings.cuttlefish_part1 = creator(self.settings.cuttlefish_part1);
94 self
95 }
96
97 pub fn configure_dugong(
98 mut self,
99 creator: impl FnOnce(DugongSettings) -> DugongSettings,
100 ) -> Self {
101 self.settings.dugong = creator(self.settings.dugong);
102 self
103 }
104
105 pub fn configure_eagle_ray(
106 mut self,
107 creator: impl FnOnce(EagleRaySettings) -> EagleRaySettings,
108 ) -> Self {
109 self.settings.eagle_ray = creator(self.settings.eagle_ray);
110 self
111 }
112
113 pub fn unbootstrapped(self) -> ProtocolExecutor {
114 self.from_to(
115 ProtocolVersion::Unbootstrapped,
116 ProtocolVersion::Unbootstrapped,
117 )
118 }
119
120 pub fn from_bootstrap_to(self, protocol_version: ProtocolVersion) -> ProtocolExecutor {
121 self.from_to(ProtocolVersion::Unbootstrapped, protocol_version)
122 }
123
124 pub fn from_bootstrap_to_latest(self) -> ProtocolExecutor {
125 self.from_bootstrap_to(ProtocolVersion::LATEST)
126 }
127
128 pub fn only_babylon(self) -> ProtocolExecutor {
129 self.from_bootstrap_to(ProtocolVersion::Babylon)
130 }
131
132 pub fn from_to(
135 self,
136 start_protocol_version: ProtocolVersion,
137 end_protocol_version: ProtocolVersion,
138 ) -> ProtocolExecutor {
139 ProtocolExecutor::new(
140 ProtocolExecutorStart::FromCompleted(start_protocol_version),
141 end_protocol_version,
142 self.settings,
143 )
144 }
145
146 pub fn from_current_to_latest(self) -> ProtocolExecutor {
148 self.from_current_to(ProtocolVersion::LATEST)
149 }
150
151 pub fn from_current_to(self, end_protocol_version: ProtocolVersion) -> ProtocolExecutor {
153 ProtocolExecutor::new(
154 ProtocolExecutorStart::ResumeFromCurrent,
155 end_protocol_version,
156 self.settings,
157 )
158 }
159}
160
161enum ProtocolExecutorStart {
162 FromCompleted(ProtocolVersion),
163 ResumeFromCurrent,
164}
165
166pub struct ProtocolExecutor {
167 starting_at: ProtocolExecutorStart,
168 update_until: ProtocolVersion,
169 settings: ProtocolSettings,
170}
171
172impl ProtocolExecutor {
173 fn new(
174 starting_at: ProtocolExecutorStart,
175 update_until: ProtocolVersion,
176 settings: ProtocolSettings,
177 ) -> Self {
178 Self {
179 starting_at,
180 update_until,
181 settings,
182 }
183 }
184
185 pub fn commit_each_protocol_update(
186 self,
187 store: &mut (impl SubstateDatabase + CommittableSubstateDatabase),
188 ) {
189 for update_execution in self.each_protocol_update_executor(&*store) {
190 update_execution.run_and_commit(store);
191 }
192 }
193
194 pub fn commit_each_protocol_update_advanced(
198 self,
199 store: &mut (impl SubstateDatabase + CommittableSubstateDatabase),
200 hooks: &mut impl ProtocolUpdateExecutionHooks,
201 modules: &impl VmInitialize,
202 ) {
203 for update_execution in self.each_protocol_update_executor(&*store) {
204 update_execution.run_and_commit_advanced(store, hooks, modules);
205 }
206 }
207
208 pub fn each_target_protocol_version(
209 &self,
210 store: &impl SubstateDatabase,
211 ) -> impl Iterator<Item = (ProtocolVersion, (usize, usize))> {
212 let starting_at = match self.starting_at {
213 ProtocolExecutorStart::FromCompleted(protocol_version) => ProtocolUpdateStatusSummary {
214 protocol_version,
215 update_status: ProtocolUpdateStatus::Complete,
216 },
217 ProtocolExecutorStart::ResumeFromCurrent => {
218 ProtocolUpdateStatusSummarySubstate::load(store).into_unique_version()
219 }
220 };
221 let from_protocol_version = starting_at.protocol_version;
222 ProtocolVersion::all_between_inclusive(starting_at.protocol_version, self.update_until)
223 .filter_map(move |version| {
224 if from_protocol_version == version {
225 match &starting_at.update_status {
226 ProtocolUpdateStatus::Complete => None,
227 ProtocolUpdateStatus::InProgress { latest_commit } => Some((
228 version,
229 (
230 latest_commit.batch_group_index,
231 latest_commit.batch_index + 1,
232 ),
233 )),
234 }
235 } else {
236 Some((version, (0, 0)))
237 }
238 })
239 }
240
241 pub fn each_protocol_update_executor(
242 self,
243 store: &impl SubstateDatabase,
244 ) -> impl Iterator<Item = ProtocolUpdateExecutor> {
245 self.each_target_protocol_version(store)
246 .map(move |(version, start_from_inclusive)| {
247 ProtocolUpdateExecutor::continue_for_version(
248 version,
249 &self.settings,
250 start_from_inclusive,
251 )
252 })
253 }
254}