radix_engine/updates/
protocol_builder.rs

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    /// The `start_protocol_version` is assumed to be currently active.
122    /// If you want to also run bootstrap (i.e. enact `ProtocolVersion::Babylon`), use the `from_bootstrap_to` method.
123    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    /// Discovers the start point from the database
136    pub fn from_current_to_latest(self) -> ProtocolExecutor {
137        self.from_current_to(ProtocolVersion::LATEST)
138    }
139
140    /// Discovers the start point from the database
141    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    /// For defaults:
184    /// * For the hooks, you can use `&mut ()`
185    /// * For the modules you can use `&mut VmModules::default()`
186    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}