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