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