/__w/smoldot/smoldot/repo/lib/src/chain/chain_information.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Smoldot |
2 | | // Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. |
3 | | // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 |
4 | | |
5 | | // This program is free software: you can redistribute it and/or modify |
6 | | // it under the terms of the GNU General Public License as published by |
7 | | // the Free Software Foundation, either version 3 of the License, or |
8 | | // (at your option) any later version. |
9 | | |
10 | | // This program is distributed in the hope that it will be useful, |
11 | | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | // GNU General Public License for more details. |
14 | | |
15 | | // You should have received a copy of the GNU General Public License |
16 | | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | | |
18 | | //! Data structures containing the finalized state of the chain, except for its storage. |
19 | | //! |
20 | | //! The types provided in this module contain the state of the chain, other than its storage, that |
21 | | //! has been finalized. |
22 | | //! |
23 | | //! > **Note**: These data structures only provide a way to communicate that finalized state, but |
24 | | //! > the existence of a [`ChainInformation`] alone does in no way mean that its content |
25 | | //! > is accurate. As an example, one use case of [`ChainInformation`] is to be written |
26 | | //! > to disk then later reloaded. It is possible for the user to modify the data on |
27 | | //! > disk, in which case the loaded [`ChainInformation`] might be erroneous. |
28 | | //! |
29 | | //! These data structures contain all the information that is necessary to verify the |
30 | | //! authenticity (but not the correctness) of blocks that descend from the finalized block |
31 | | //! contained in the structure. |
32 | | //! |
33 | | //! They do not, however, contain the storage of the finalized block, which is necessary to verify |
34 | | //! the correctness of new blocks. It is possible, though, for instance to download the |
35 | | //! storage of the finalized block from another node. This downloaded storage can be verified |
36 | | //! to make sure that it matches the content of the [`ChainInformation`]. |
37 | | //! |
38 | | //! They also do not contain the past history of the chain. It is, however, similarly possible to |
39 | | //! for instance download the history from other nodes. |
40 | | |
41 | | use crate::header; |
42 | | |
43 | | use alloc::{boxed::Box, vec::Vec}; |
44 | | use core::num::NonZeroU64; |
45 | | |
46 | | pub mod build; |
47 | | |
48 | | /// Information about the latest finalized block and state found in its ancestors. |
49 | | /// |
50 | | /// Similar to [`ChainInformation`], but guaranteed to be coherent. |
51 | | #[derive(Debug, Clone)] |
52 | | pub struct ValidChainInformation { |
53 | | inner: ChainInformation, |
54 | | } |
55 | | |
56 | | impl From<ValidChainInformation> for ChainInformation { |
57 | 23 | fn from(i: ValidChainInformation) -> Self { |
58 | 23 | i.inner |
59 | 23 | } _RNvXNtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB2_16ChainInformationINtNtCsaYZPK01V26L_4core7convert4FromNtB2_21ValidChainInformationE4from Line | Count | Source | 57 | 2 | fn from(i: ValidChainInformation) -> Self { | 58 | 2 | i.inner | 59 | 2 | } |
_RNvXNtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB2_16ChainInformationINtNtCsaYZPK01V26L_4core7convert4FromNtB2_21ValidChainInformationE4from Line | Count | Source | 57 | 21 | fn from(i: ValidChainInformation) -> Self { | 58 | 21 | i.inner | 59 | 21 | } |
|
60 | | } |
61 | | |
62 | | impl ValidChainInformation { |
63 | | /// Gives access to the information. |
64 | 274 | pub fn as_ref(&self) -> ChainInformationRef { |
65 | 274 | From::from(&self.inner) |
66 | 274 | } _RNvMs_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB4_21ValidChainInformation6as_ref Line | Count | Source | 64 | 1 | pub fn as_ref(&self) -> ChainInformationRef { | 65 | 1 | From::from(&self.inner) | 66 | 1 | } |
_RNvMs_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB4_21ValidChainInformation6as_ref Line | Count | Source | 64 | 273 | pub fn as_ref(&self) -> ChainInformationRef { | 65 | 273 | From::from(&self.inner) | 66 | 273 | } |
|
67 | | } |
68 | | |
69 | | impl<'a> From<ValidChainInformationRef<'a>> for ValidChainInformation { |
70 | 0 | fn from(info: ValidChainInformationRef<'a>) -> ValidChainInformation { |
71 | 0 | ValidChainInformation { |
72 | 0 | inner: info.inner.into(), |
73 | 0 | } |
74 | 0 | } Unexecuted instantiation: _RNvXs0_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB5_21ValidChainInformationINtNtCsaYZPK01V26L_4core7convert4FromNtB5_24ValidChainInformationRefE4from Unexecuted instantiation: _RNvXs0_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB5_21ValidChainInformationINtNtCsaYZPK01V26L_4core7convert4FromNtB5_24ValidChainInformationRefE4from |
75 | | } |
76 | | |
77 | | impl TryFrom<ChainInformation> for ValidChainInformation { |
78 | | type Error = ValidityError; |
79 | | |
80 | 45 | fn try_from(info: ChainInformation) -> Result<Self, Self::Error> { |
81 | 45 | ChainInformationRef::from(&info).validate()?0 ; |
82 | 45 | Ok(ValidChainInformation { inner: info }) |
83 | 45 | } _RNvXs1_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB5_21ValidChainInformationINtNtCsaYZPK01V26L_4core7convert7TryFromNtB5_16ChainInformationE8try_from Line | Count | Source | 80 | 3 | fn try_from(info: ChainInformation) -> Result<Self, Self::Error> { | 81 | 3 | ChainInformationRef::from(&info).validate()?0 ; | 82 | 3 | Ok(ValidChainInformation { inner: info }) | 83 | 3 | } |
_RNvXs1_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB5_21ValidChainInformationINtNtCsaYZPK01V26L_4core7convert7TryFromNtB5_16ChainInformationE8try_from Line | Count | Source | 80 | 42 | fn try_from(info: ChainInformation) -> Result<Self, Self::Error> { | 81 | 42 | ChainInformationRef::from(&info).validate()?0 ; | 82 | 42 | Ok(ValidChainInformation { inner: info }) | 83 | 42 | } |
|
84 | | } |
85 | | |
86 | | /// Information about the latest finalized block and state found in its ancestors. |
87 | | /// |
88 | | /// Similar to [`ChainInformationRef`], but guaranteed to be coherent. |
89 | | #[derive(Debug, Clone)] |
90 | | pub struct ValidChainInformationRef<'a> { |
91 | | inner: ChainInformationRef<'a>, |
92 | | } |
93 | | |
94 | | impl<'a> From<&'a ValidChainInformation> for ValidChainInformationRef<'a> { |
95 | 0 | fn from(info: &'a ValidChainInformation) -> ValidChainInformationRef<'a> { |
96 | 0 | ValidChainInformationRef { |
97 | 0 | inner: From::from(&info.inner), |
98 | 0 | } |
99 | 0 | } Unexecuted instantiation: _RNvXs2_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB5_24ValidChainInformationRefINtNtCsaYZPK01V26L_4core7convert4FromRNtB5_21ValidChainInformationE4from Unexecuted instantiation: _RNvXs2_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB5_24ValidChainInformationRefINtNtCsaYZPK01V26L_4core7convert4FromRNtB5_21ValidChainInformationE4from |
100 | | } |
101 | | |
102 | | impl<'a> TryFrom<ChainInformationRef<'a>> for ValidChainInformationRef<'a> { |
103 | | type Error = ValidityError; |
104 | | |
105 | 0 | fn try_from(info: ChainInformationRef<'a>) -> Result<Self, Self::Error> { |
106 | 0 | info.validate()?; |
107 | 0 | Ok(ValidChainInformationRef { inner: info }) |
108 | 0 | } Unexecuted instantiation: _RNvXs3_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB5_24ValidChainInformationRefINtNtCsaYZPK01V26L_4core7convert7TryFromNtB5_19ChainInformationRefE8try_from Unexecuted instantiation: _RNvXs3_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB5_24ValidChainInformationRefINtNtCsaYZPK01V26L_4core7convert7TryFromNtB5_19ChainInformationRefE8try_from |
109 | | } |
110 | | |
111 | | impl<'a> ValidChainInformationRef<'a> { |
112 | | /// Gives access to the information. |
113 | 0 | pub fn as_ref(&self) -> ChainInformationRef<'a> { |
114 | 0 | self.inner.clone() |
115 | 0 | } Unexecuted instantiation: _RNvMs4_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB5_24ValidChainInformationRef6as_ref Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB5_24ValidChainInformationRef6as_ref |
116 | | } |
117 | | |
118 | | /// Information about the latest finalized block and state found in its ancestors. |
119 | | #[derive(Debug, Clone)] |
120 | | pub struct ChainInformation { |
121 | | /// Header of the highest known finalized block. |
122 | | pub finalized_block_header: Box<header::Header>, |
123 | | |
124 | | /// Extra items that depend on the consensus engine. |
125 | | pub consensus: ChainInformationConsensus, |
126 | | |
127 | | /// Extra items that depend on the finality engine. |
128 | | pub finality: ChainInformationFinality, |
129 | | } |
130 | | |
131 | | impl<'a> From<ChainInformationRef<'a>> for ChainInformation { |
132 | 0 | fn from(info: ChainInformationRef<'a>) -> ChainInformation { |
133 | 0 | ChainInformation { |
134 | 0 | finalized_block_header: Box::new(info.finalized_block_header.into()), |
135 | 0 | consensus: match info.consensus { |
136 | 0 | ChainInformationConsensusRef::Unknown => ChainInformationConsensus::Unknown, |
137 | | ChainInformationConsensusRef::Aura { |
138 | 0 | finalized_authorities_list, |
139 | 0 | slot_duration, |
140 | 0 | } => ChainInformationConsensus::Aura { |
141 | 0 | finalized_authorities_list: finalized_authorities_list |
142 | 0 | .map(|a| a.into()) Unexecuted instantiation: _RNCNvXs5_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB7_16ChainInformationINtNtCsaYZPK01V26L_4core7convert4FromNtB7_19ChainInformationRefE4from0Bb_ Unexecuted instantiation: _RNCNvXs5_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB7_16ChainInformationINtNtCsaYZPK01V26L_4core7convert4FromNtB7_19ChainInformationRefE4from0Bb_ |
143 | 0 | .collect(), |
144 | 0 | slot_duration, |
145 | 0 | }, |
146 | | ChainInformationConsensusRef::Babe { |
147 | 0 | slots_per_epoch, |
148 | 0 | finalized_next_epoch_transition, |
149 | 0 | finalized_block_epoch_information, |
150 | 0 | } => ChainInformationConsensus::Babe { |
151 | 0 | slots_per_epoch, |
152 | 0 | finalized_block_epoch_information: finalized_block_epoch_information |
153 | 0 | .map(|i| Box::new(i.into())), Unexecuted instantiation: _RNCNvXs5_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB7_16ChainInformationINtNtCsaYZPK01V26L_4core7convert4FromNtB7_19ChainInformationRefE4froms_0Bb_ Unexecuted instantiation: _RNCNvXs5_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB7_16ChainInformationINtNtCsaYZPK01V26L_4core7convert4FromNtB7_19ChainInformationRefE4froms_0Bb_ |
154 | 0 | finalized_next_epoch_transition: Box::new( |
155 | 0 | finalized_next_epoch_transition.into(), |
156 | 0 | ), |
157 | 0 | }, |
158 | | }, |
159 | 0 | finality: info.finality.into(), |
160 | 0 | } |
161 | 0 | } Unexecuted instantiation: _RNvXs5_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB5_16ChainInformationINtNtCsaYZPK01V26L_4core7convert4FromNtB5_19ChainInformationRefE4from Unexecuted instantiation: _RNvXs5_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB5_16ChainInformationINtNtCsaYZPK01V26L_4core7convert4FromNtB5_19ChainInformationRefE4from |
162 | | } |
163 | | |
164 | | /// Extra items that depend on the consensus engine. |
165 | | #[derive(Debug, Clone)] |
166 | | pub enum ChainInformationConsensus { |
167 | | /// Any node on the chain is allowed to produce blocks. |
168 | | /// |
169 | | /// > **Note**: Be warned that this variant makes it possible for a huge number of blocks to |
170 | | /// > be produced. If this variant is used, the user is encouraged to limit, through |
171 | | /// > other means, the number of blocks being accepted. |
172 | | Unknown, |
173 | | |
174 | | /// Chain is using the Aura consensus engine. |
175 | | Aura { |
176 | | /// List of authorities that must validate children of the block referred to by |
177 | | /// [`ChainInformation::finalized_block_header`]. |
178 | | finalized_authorities_list: Vec<header::AuraAuthority>, |
179 | | |
180 | | /// Duration, in milliseconds, of an Aura slot. |
181 | | slot_duration: NonZeroU64, |
182 | | }, |
183 | | |
184 | | /// Chain is using the Babe consensus engine. |
185 | | Babe { |
186 | | /// Number of slots per epoch. Configured at the genesis block and never touched later. |
187 | | slots_per_epoch: NonZeroU64, |
188 | | |
189 | | /// Babe epoch information about the epoch the finalized block belongs to. |
190 | | /// |
191 | | /// If the finalized block belongs to epoch #0, which starts at block #1, then this must |
192 | | /// contain the information about the epoch #0, which can be found by calling the |
193 | | /// `BabeApi_configuration` runtime function. |
194 | | /// |
195 | | /// Must be `None` if and only if the finalized block is block #0. |
196 | | /// |
197 | | /// > **Note**: The information about the epoch the finalized block belongs to isn't |
198 | | /// > necessary, but the information about the epoch the children of the |
199 | | /// > finalized block belongs to *is*. However, due to possibility of missed |
200 | | /// > slots, it is often not possible to know in advance whether the children |
201 | | /// > of a block will belong to the same epoch as their parent. This is the |
202 | | /// > reason why the "parent" (i.e. finalized block)'s information are demanded. |
203 | | finalized_block_epoch_information: Option<Box<BabeEpochInformation>>, |
204 | | |
205 | | /// Babe epoch information about the epoch right after the one the finalized block belongs |
206 | | /// to. |
207 | | /// |
208 | | /// If [`ChainInformationConsensus::Babe::finalized_block_epoch_information`] is `Some`, |
209 | | /// this field must contain the epoch that follows. |
210 | | /// |
211 | | /// If the finalized block is block #0, then this must contain the information about the |
212 | | /// epoch #0, which can be found by calling the `BabeApi_configuration` runtime function. |
213 | | finalized_next_epoch_transition: Box<BabeEpochInformation>, |
214 | | }, |
215 | | } |
216 | | |
217 | | /// Information about a Babe epoch. |
218 | | #[derive(Debug, Clone)] |
219 | | pub struct BabeEpochInformation { |
220 | | /// Index of the epoch. |
221 | | /// |
222 | | /// Epoch number 0 starts at the slot number of block 1. Epoch indices increase one by one. |
223 | | pub epoch_index: u64, |
224 | | |
225 | | /// Slot at which the epoch starts. |
226 | | /// |
227 | | /// Must be `None` if and only if the context is |
228 | | /// [`ChainInformationConsensus::Babe::finalized_next_epoch_transition`] and |
229 | | /// [`BabeEpochInformation::epoch_index`] is 0. |
230 | | pub start_slot_number: Option<u64>, |
231 | | |
232 | | /// List of authorities allowed to author blocks during this epoch. |
233 | | pub authorities: Vec<header::BabeAuthority>, |
234 | | |
235 | | /// Randomness value for this epoch. |
236 | | /// |
237 | | /// Determined using the VRF output of the validators of the epoch before. |
238 | | pub randomness: [u8; 32], |
239 | | |
240 | | /// Value of the constant that allows determining the chances of a VRF being generated by a |
241 | | /// given slot. |
242 | | /// |
243 | | /// This constant represents a fraction, where the first element of the tuple is the numerator |
244 | | /// and the second element is the denominator. The fraction should always be `<= 1`, meaning |
245 | | /// that the numerator should always be inferior or equal to the denominator. |
246 | | pub c: (u64, u64), |
247 | | |
248 | | /// Types of blocks allowed for this epoch. |
249 | | pub allowed_slots: header::BabeAllowedSlots, |
250 | | } |
251 | | |
252 | | impl BabeEpochInformation { |
253 | | /// Checks whether the fields in this struct make sense. |
254 | 2 | pub fn validate(&self) -> Result<(), BabeValidityError> { |
255 | 2 | BabeEpochInformationRef::from(self).validate() |
256 | 2 | } _RNvMs6_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB5_20BabeEpochInformation8validate Line | Count | Source | 254 | 2 | pub fn validate(&self) -> Result<(), BabeValidityError> { | 255 | 2 | BabeEpochInformationRef::from(self).validate() | 256 | 2 | } |
Unexecuted instantiation: _RNvMs6_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB5_20BabeEpochInformation8validate |
257 | | } |
258 | | |
259 | | impl<'a> From<BabeEpochInformationRef<'a>> for BabeEpochInformation { |
260 | 0 | fn from(info: BabeEpochInformationRef<'a>) -> BabeEpochInformation { |
261 | 0 | BabeEpochInformation { |
262 | 0 | epoch_index: info.epoch_index, |
263 | 0 | start_slot_number: info.start_slot_number, |
264 | 0 | authorities: info.authorities.map(Into::into).collect(), |
265 | 0 | randomness: *info.randomness, |
266 | 0 | c: info.c, |
267 | 0 | allowed_slots: info.allowed_slots, |
268 | 0 | } |
269 | 0 | } Unexecuted instantiation: _RNvXs7_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB5_20BabeEpochInformationINtNtCsaYZPK01V26L_4core7convert4FromNtB5_23BabeEpochInformationRefE4from Unexecuted instantiation: _RNvXs7_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB5_20BabeEpochInformationINtNtCsaYZPK01V26L_4core7convert4FromNtB5_23BabeEpochInformationRefE4from |
270 | | } |
271 | | |
272 | | /// Extra items that depend on the finality engine. |
273 | | #[derive(Debug, Clone)] |
274 | | pub enum ChainInformationFinality { |
275 | | /// Blocks themselves don't contain any information concerning finality. Finality is provided |
276 | | /// by a mechanism that is entirely external to the chain. |
277 | | /// |
278 | | /// > **Note**: This is the mechanism used for parachains. Finality is provided entirely by |
279 | | /// > the relay chain. |
280 | | Outsourced, |
281 | | |
282 | | /// Chain uses the Grandpa finality algorithm. |
283 | | Grandpa { |
284 | | /// Grandpa authorities set ID of the block right after finalized block. |
285 | | /// |
286 | | /// If the finalized block is the genesis block, should be 0. Otherwise, must be |
287 | | /// incremented by one for every change in the Grandpa authorities reported by the |
288 | | /// headers since the genesis block. |
289 | | after_finalized_block_authorities_set_id: u64, |
290 | | |
291 | | /// List of GrandPa authorities that need to finalize the block right after the finalized |
292 | | /// block. |
293 | | finalized_triggered_authorities: Vec<header::GrandpaAuthority>, |
294 | | |
295 | | /// Change in the GrandPa authorities list that has been scheduled by a block that is already |
296 | | /// finalized, but the change is not triggered yet. These changes will for sure happen. |
297 | | /// Contains the block number where the changes are to be triggered. |
298 | | /// |
299 | | /// The block whose height is contained in this field must still be finalized using the |
300 | | /// authorities found in [`ChainInformationFinality::Grandpa::finalized_triggered_authorities`]. |
301 | | /// Only the next block and further use the new list of authorities. |
302 | | /// |
303 | | /// The block height must always be strictly superior to the height found in |
304 | | /// [`ChainInformation::finalized_block_header`]. |
305 | | /// |
306 | | /// > **Note**: When a header contains a GrandPa scheduled changes log item with a delay of N, |
307 | | /// > the block where the changes are triggered is |
308 | | /// > `height(block_with_log_item) + N`. If `N` is 0, then the block where the |
309 | | /// > change is triggered is the same as the one where it is scheduled. |
310 | | finalized_scheduled_change: Option<(u64, Vec<header::GrandpaAuthority>)>, |
311 | | }, |
312 | | } |
313 | | |
314 | | impl<'a> From<ChainInformationFinalityRef<'a>> for ChainInformationFinality { |
315 | 21 | fn from(finality: ChainInformationFinalityRef<'a>) -> ChainInformationFinality { |
316 | 21 | match finality { |
317 | 0 | ChainInformationFinalityRef::Outsourced => ChainInformationFinality::Outsourced, |
318 | | ChainInformationFinalityRef::Grandpa { |
319 | 21 | after_finalized_block_authorities_set_id, |
320 | 21 | finalized_triggered_authorities, |
321 | 21 | finalized_scheduled_change, |
322 | 21 | } => ChainInformationFinality::Grandpa { |
323 | 21 | after_finalized_block_authorities_set_id, |
324 | 21 | finalized_scheduled_change: finalized_scheduled_change.map(|(n, l)| (n, l.into())0 ), Unexecuted instantiation: _RNCNvXs8_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB7_24ChainInformationFinalityINtNtCsaYZPK01V26L_4core7convert4FromNtB7_27ChainInformationFinalityRefE4from0Bb_ Unexecuted instantiation: _RNCNvXs8_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB7_24ChainInformationFinalityINtNtCsaYZPK01V26L_4core7convert4FromNtB7_27ChainInformationFinalityRefE4from0Bb_ |
325 | 21 | finalized_triggered_authorities: finalized_triggered_authorities.into(), |
326 | 21 | }, |
327 | | } |
328 | 21 | } Unexecuted instantiation: _RNvXs8_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB5_24ChainInformationFinalityINtNtCsaYZPK01V26L_4core7convert4FromNtB5_27ChainInformationFinalityRefE4from _RNvXs8_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB5_24ChainInformationFinalityINtNtCsaYZPK01V26L_4core7convert4FromNtB5_27ChainInformationFinalityRefE4from Line | Count | Source | 315 | 21 | fn from(finality: ChainInformationFinalityRef<'a>) -> ChainInformationFinality { | 316 | 21 | match finality { | 317 | 0 | ChainInformationFinalityRef::Outsourced => ChainInformationFinality::Outsourced, | 318 | | ChainInformationFinalityRef::Grandpa { | 319 | 21 | after_finalized_block_authorities_set_id, | 320 | 21 | finalized_triggered_authorities, | 321 | 21 | finalized_scheduled_change, | 322 | 21 | } => ChainInformationFinality::Grandpa { | 323 | 21 | after_finalized_block_authorities_set_id, | 324 | 21 | finalized_scheduled_change: finalized_scheduled_change.map(|(n, l)| (n, l.into())), | 325 | 21 | finalized_triggered_authorities: finalized_triggered_authorities.into(), | 326 | 21 | }, | 327 | | } | 328 | 21 | } |
|
329 | | } |
330 | | |
331 | | /// Equivalent to a [`ChainInformation`] but referencing an existing structure. Cheap to copy. |
332 | | #[derive(Debug, Clone)] |
333 | | pub struct ChainInformationRef<'a> { |
334 | | /// See equivalent field in [`ChainInformation`]. |
335 | | pub finalized_block_header: header::HeaderRef<'a>, |
336 | | |
337 | | /// Extra items that depend on the consensus engine. |
338 | | pub consensus: ChainInformationConsensusRef<'a>, |
339 | | |
340 | | /// Extra items that depend on the finality engine. |
341 | | pub finality: ChainInformationFinalityRef<'a>, |
342 | | } |
343 | | |
344 | | impl<'a> ChainInformationRef<'a> { |
345 | | /// Checks whether the information is coherent. |
346 | 45 | pub fn validate(&self) -> Result<(), ValidityError> { |
347 | | if let ChainInformationConsensusRef::Babe { |
348 | 3 | finalized_next_epoch_transition, |
349 | 3 | finalized_block_epoch_information, |
350 | | .. |
351 | 45 | } = &self.consensus |
352 | | { |
353 | 3 | if let Err(err0 ) = finalized_next_epoch_transition.validate() { |
354 | 0 | return Err(ValidityError::InvalidBabe(err)); |
355 | 3 | } |
356 | 3 | |
357 | 3 | if finalized_next_epoch_transition.start_slot_number.is_some() |
358 | 0 | && (finalized_next_epoch_transition.epoch_index == 0) |
359 | | { |
360 | 0 | return Err(ValidityError::UnexpectedBabeSlotStartNumber); |
361 | 3 | } |
362 | 3 | if finalized_next_epoch_transition.start_slot_number.is_none() |
363 | 3 | && (finalized_next_epoch_transition.epoch_index != 0) |
364 | | { |
365 | 0 | return Err(ValidityError::MissingBabeSlotStartNumber); |
366 | 3 | } |
367 | | |
368 | 3 | if let Some(finalized_block_epoch_information0 ) = &finalized_block_epoch_information { |
369 | 0 | if let Err(err) = finalized_block_epoch_information.validate() { |
370 | 0 | return Err(ValidityError::InvalidBabe(err)); |
371 | 0 | } |
372 | 0 |
|
373 | 0 | if self.finalized_block_header.number == 0 { |
374 | 0 | return Err(ValidityError::UnexpectedBabeFinalizedEpoch); |
375 | 0 | } |
376 | | |
377 | 0 | if let Some(epoch_start_slot_number) = |
378 | 0 | finalized_block_epoch_information.start_slot_number |
379 | | { |
380 | 0 | if let Some(babe_preruntime) = |
381 | 0 | self.finalized_block_header.digest.babe_pre_runtime() |
382 | | { |
383 | 0 | if self.finalized_block_header.number == 0 { |
384 | 0 | return Err(ValidityError::ConsensusAlgorithmMismatch); |
385 | 0 | } |
386 | 0 | if babe_preruntime.slot_number() < epoch_start_slot_number { |
387 | 0 | return Err(ValidityError::HeaderBabeSlotInferiorToEpochStartSlot); |
388 | 0 | } |
389 | 0 | } else if self.finalized_block_header.number != 0 { |
390 | 0 | return Err(ValidityError::ConsensusAlgorithmMismatch); |
391 | 0 | } |
392 | 0 | if (self.finalized_block_header.digest.babe_seal().is_some() |
393 | 0 | != (self.finalized_block_header.number != 0)) |
394 | 0 | || self.finalized_block_header.digest.has_any_aura() |
395 | | { |
396 | 0 | return Err(ValidityError::ConsensusAlgorithmMismatch); |
397 | 0 | } |
398 | 0 | if let Some((epoch_change, _new_config)) = |
399 | 0 | self.finalized_block_header.digest.babe_epoch_information() |
400 | | { |
401 | 0 | if epoch_change.authorities != finalized_next_epoch_transition.authorities |
402 | 0 | || epoch_change.randomness != finalized_next_epoch_transition.randomness |
403 | | { |
404 | 0 | return Err(ValidityError::BabeEpochInfoMismatch); |
405 | 0 | } |
406 | 0 | } |
407 | | } else { |
408 | 0 | return Err(ValidityError::MissingBabeSlotStartNumber); |
409 | | } |
410 | 3 | } |
411 | | |
412 | 3 | if finalized_block_epoch_information.is_none() |
413 | 3 | && self.finalized_block_header.number != 0 |
414 | | { |
415 | 0 | return Err(ValidityError::NoBabeFinalizedEpoch); |
416 | 3 | } |
417 | 42 | } |
418 | | |
419 | 45 | if let ChainInformationConsensusRef::Aura { .. } = &self.consensus { |
420 | 42 | if (self |
421 | 42 | .finalized_block_header |
422 | 42 | .digest |
423 | 42 | .aura_pre_runtime() |
424 | 42 | .is_some() |
425 | 42 | != (self.finalized_block_header.number != 0)) |
426 | 42 | || (self.finalized_block_header.digest.aura_seal().is_some() |
427 | 42 | != (self.finalized_block_header.number != 0)) |
428 | 42 | || self.finalized_block_header.digest.has_any_babe() |
429 | | { |
430 | 0 | return Err(ValidityError::ConsensusAlgorithmMismatch); |
431 | 42 | } |
432 | 3 | } |
433 | | |
434 | | if let ChainInformationFinalityRef::Grandpa { |
435 | 45 | after_finalized_block_authorities_set_id, |
436 | 45 | finalized_scheduled_change, |
437 | | .. |
438 | 45 | } = &self.finality |
439 | | { |
440 | | // TODO: check consistency with the finalized block header |
441 | 45 | if let Some(change0 ) = finalized_scheduled_change.as_ref() { |
442 | 0 | if change.0 <= self.finalized_block_header.number { |
443 | 0 | return Err(ValidityError::ScheduledGrandPaChangeBeforeFinalized); |
444 | 0 | } |
445 | 45 | } |
446 | 45 | if self.finalized_block_header.number == 0 |
447 | 45 | && *after_finalized_block_authorities_set_id != 0 |
448 | | { |
449 | 0 | return Err(ValidityError::FinalizedZeroButNonZeroAuthoritiesSetId); |
450 | 45 | } |
451 | 0 | } |
452 | | |
453 | 45 | Ok(()) |
454 | 45 | } _RNvMs9_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB5_19ChainInformationRef8validate Line | Count | Source | 346 | 3 | pub fn validate(&self) -> Result<(), ValidityError> { | 347 | | if let ChainInformationConsensusRef::Babe { | 348 | 3 | finalized_next_epoch_transition, | 349 | 3 | finalized_block_epoch_information, | 350 | | .. | 351 | 3 | } = &self.consensus | 352 | | { | 353 | 3 | if let Err(err0 ) = finalized_next_epoch_transition.validate() { | 354 | 0 | return Err(ValidityError::InvalidBabe(err)); | 355 | 3 | } | 356 | 3 | | 357 | 3 | if finalized_next_epoch_transition.start_slot_number.is_some() | 358 | 0 | && (finalized_next_epoch_transition.epoch_index == 0) | 359 | | { | 360 | 0 | return Err(ValidityError::UnexpectedBabeSlotStartNumber); | 361 | 3 | } | 362 | 3 | if finalized_next_epoch_transition.start_slot_number.is_none() | 363 | 3 | && (finalized_next_epoch_transition.epoch_index != 0) | 364 | | { | 365 | 0 | return Err(ValidityError::MissingBabeSlotStartNumber); | 366 | 3 | } | 367 | | | 368 | 3 | if let Some(finalized_block_epoch_information0 ) = &finalized_block_epoch_information { | 369 | 0 | if let Err(err) = finalized_block_epoch_information.validate() { | 370 | 0 | return Err(ValidityError::InvalidBabe(err)); | 371 | 0 | } | 372 | 0 |
| 373 | 0 | if self.finalized_block_header.number == 0 { | 374 | 0 | return Err(ValidityError::UnexpectedBabeFinalizedEpoch); | 375 | 0 | } | 376 | | | 377 | 0 | if let Some(epoch_start_slot_number) = | 378 | 0 | finalized_block_epoch_information.start_slot_number | 379 | | { | 380 | 0 | if let Some(babe_preruntime) = | 381 | 0 | self.finalized_block_header.digest.babe_pre_runtime() | 382 | | { | 383 | 0 | if self.finalized_block_header.number == 0 { | 384 | 0 | return Err(ValidityError::ConsensusAlgorithmMismatch); | 385 | 0 | } | 386 | 0 | if babe_preruntime.slot_number() < epoch_start_slot_number { | 387 | 0 | return Err(ValidityError::HeaderBabeSlotInferiorToEpochStartSlot); | 388 | 0 | } | 389 | 0 | } else if self.finalized_block_header.number != 0 { | 390 | 0 | return Err(ValidityError::ConsensusAlgorithmMismatch); | 391 | 0 | } | 392 | 0 | if (self.finalized_block_header.digest.babe_seal().is_some() | 393 | 0 | != (self.finalized_block_header.number != 0)) | 394 | 0 | || self.finalized_block_header.digest.has_any_aura() | 395 | | { | 396 | 0 | return Err(ValidityError::ConsensusAlgorithmMismatch); | 397 | 0 | } | 398 | 0 | if let Some((epoch_change, _new_config)) = | 399 | 0 | self.finalized_block_header.digest.babe_epoch_information() | 400 | | { | 401 | 0 | if epoch_change.authorities != finalized_next_epoch_transition.authorities | 402 | 0 | || epoch_change.randomness != finalized_next_epoch_transition.randomness | 403 | | { | 404 | 0 | return Err(ValidityError::BabeEpochInfoMismatch); | 405 | 0 | } | 406 | 0 | } | 407 | | } else { | 408 | 0 | return Err(ValidityError::MissingBabeSlotStartNumber); | 409 | | } | 410 | 3 | } | 411 | | | 412 | 3 | if finalized_block_epoch_information.is_none() | 413 | 3 | && self.finalized_block_header.number != 0 | 414 | | { | 415 | 0 | return Err(ValidityError::NoBabeFinalizedEpoch); | 416 | 3 | } | 417 | 0 | } | 418 | | | 419 | 3 | if let ChainInformationConsensusRef::Aura { .. } = &self.consensus { | 420 | 0 | if (self | 421 | 0 | .finalized_block_header | 422 | 0 | .digest | 423 | 0 | .aura_pre_runtime() | 424 | 0 | .is_some() | 425 | 0 | != (self.finalized_block_header.number != 0)) | 426 | 0 | || (self.finalized_block_header.digest.aura_seal().is_some() | 427 | 0 | != (self.finalized_block_header.number != 0)) | 428 | 0 | || self.finalized_block_header.digest.has_any_babe() | 429 | | { | 430 | 0 | return Err(ValidityError::ConsensusAlgorithmMismatch); | 431 | 0 | } | 432 | 3 | } | 433 | | | 434 | | if let ChainInformationFinalityRef::Grandpa { | 435 | 3 | after_finalized_block_authorities_set_id, | 436 | 3 | finalized_scheduled_change, | 437 | | .. | 438 | 3 | } = &self.finality | 439 | | { | 440 | | // TODO: check consistency with the finalized block header | 441 | 3 | if let Some(change0 ) = finalized_scheduled_change.as_ref() { | 442 | 0 | if change.0 <= self.finalized_block_header.number { | 443 | 0 | return Err(ValidityError::ScheduledGrandPaChangeBeforeFinalized); | 444 | 0 | } | 445 | 3 | } | 446 | 3 | if self.finalized_block_header.number == 0 | 447 | 3 | && *after_finalized_block_authorities_set_id != 0 | 448 | | { | 449 | 0 | return Err(ValidityError::FinalizedZeroButNonZeroAuthoritiesSetId); | 450 | 3 | } | 451 | 0 | } | 452 | | | 453 | 3 | Ok(()) | 454 | 3 | } |
_RNvMs9_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB5_19ChainInformationRef8validate Line | Count | Source | 346 | 42 | pub fn validate(&self) -> Result<(), ValidityError> { | 347 | | if let ChainInformationConsensusRef::Babe { | 348 | 0 | finalized_next_epoch_transition, | 349 | 0 | finalized_block_epoch_information, | 350 | | .. | 351 | 42 | } = &self.consensus | 352 | | { | 353 | 0 | if let Err(err) = finalized_next_epoch_transition.validate() { | 354 | 0 | return Err(ValidityError::InvalidBabe(err)); | 355 | 0 | } | 356 | 0 |
| 357 | 0 | if finalized_next_epoch_transition.start_slot_number.is_some() | 358 | 0 | && (finalized_next_epoch_transition.epoch_index == 0) | 359 | | { | 360 | 0 | return Err(ValidityError::UnexpectedBabeSlotStartNumber); | 361 | 0 | } | 362 | 0 | if finalized_next_epoch_transition.start_slot_number.is_none() | 363 | 0 | && (finalized_next_epoch_transition.epoch_index != 0) | 364 | | { | 365 | 0 | return Err(ValidityError::MissingBabeSlotStartNumber); | 366 | 0 | } | 367 | | | 368 | 0 | if let Some(finalized_block_epoch_information) = &finalized_block_epoch_information { | 369 | 0 | if let Err(err) = finalized_block_epoch_information.validate() { | 370 | 0 | return Err(ValidityError::InvalidBabe(err)); | 371 | 0 | } | 372 | 0 |
| 373 | 0 | if self.finalized_block_header.number == 0 { | 374 | 0 | return Err(ValidityError::UnexpectedBabeFinalizedEpoch); | 375 | 0 | } | 376 | | | 377 | 0 | if let Some(epoch_start_slot_number) = | 378 | 0 | finalized_block_epoch_information.start_slot_number | 379 | | { | 380 | 0 | if let Some(babe_preruntime) = | 381 | 0 | self.finalized_block_header.digest.babe_pre_runtime() | 382 | | { | 383 | 0 | if self.finalized_block_header.number == 0 { | 384 | 0 | return Err(ValidityError::ConsensusAlgorithmMismatch); | 385 | 0 | } | 386 | 0 | if babe_preruntime.slot_number() < epoch_start_slot_number { | 387 | 0 | return Err(ValidityError::HeaderBabeSlotInferiorToEpochStartSlot); | 388 | 0 | } | 389 | 0 | } else if self.finalized_block_header.number != 0 { | 390 | 0 | return Err(ValidityError::ConsensusAlgorithmMismatch); | 391 | 0 | } | 392 | 0 | if (self.finalized_block_header.digest.babe_seal().is_some() | 393 | 0 | != (self.finalized_block_header.number != 0)) | 394 | 0 | || self.finalized_block_header.digest.has_any_aura() | 395 | | { | 396 | 0 | return Err(ValidityError::ConsensusAlgorithmMismatch); | 397 | 0 | } | 398 | 0 | if let Some((epoch_change, _new_config)) = | 399 | 0 | self.finalized_block_header.digest.babe_epoch_information() | 400 | | { | 401 | 0 | if epoch_change.authorities != finalized_next_epoch_transition.authorities | 402 | 0 | || epoch_change.randomness != finalized_next_epoch_transition.randomness | 403 | | { | 404 | 0 | return Err(ValidityError::BabeEpochInfoMismatch); | 405 | 0 | } | 406 | 0 | } | 407 | | } else { | 408 | 0 | return Err(ValidityError::MissingBabeSlotStartNumber); | 409 | | } | 410 | 0 | } | 411 | | | 412 | 0 | if finalized_block_epoch_information.is_none() | 413 | 0 | && self.finalized_block_header.number != 0 | 414 | | { | 415 | 0 | return Err(ValidityError::NoBabeFinalizedEpoch); | 416 | 0 | } | 417 | 42 | } | 418 | | | 419 | 42 | if let ChainInformationConsensusRef::Aura { .. } = &self.consensus { | 420 | 42 | if (self | 421 | 42 | .finalized_block_header | 422 | 42 | .digest | 423 | 42 | .aura_pre_runtime() | 424 | 42 | .is_some() | 425 | 42 | != (self.finalized_block_header.number != 0)) | 426 | 42 | || (self.finalized_block_header.digest.aura_seal().is_some() | 427 | 42 | != (self.finalized_block_header.number != 0)) | 428 | 42 | || self.finalized_block_header.digest.has_any_babe() | 429 | | { | 430 | 0 | return Err(ValidityError::ConsensusAlgorithmMismatch); | 431 | 42 | } | 432 | 0 | } | 433 | | | 434 | | if let ChainInformationFinalityRef::Grandpa { | 435 | 42 | after_finalized_block_authorities_set_id, | 436 | 42 | finalized_scheduled_change, | 437 | | .. | 438 | 42 | } = &self.finality | 439 | | { | 440 | | // TODO: check consistency with the finalized block header | 441 | 42 | if let Some(change0 ) = finalized_scheduled_change.as_ref() { | 442 | 0 | if change.0 <= self.finalized_block_header.number { | 443 | 0 | return Err(ValidityError::ScheduledGrandPaChangeBeforeFinalized); | 444 | 0 | } | 445 | 42 | } | 446 | 42 | if self.finalized_block_header.number == 0 | 447 | 42 | && *after_finalized_block_authorities_set_id != 0 | 448 | | { | 449 | 0 | return Err(ValidityError::FinalizedZeroButNonZeroAuthoritiesSetId); | 450 | 42 | } | 451 | 0 | } | 452 | | | 453 | 42 | Ok(()) | 454 | 42 | } |
|
455 | | } |
456 | | |
457 | | impl<'a> From<&'a ChainInformation> for ChainInformationRef<'a> { |
458 | 319 | fn from(info: &'a ChainInformation) -> ChainInformationRef<'a> { |
459 | 319 | ChainInformationRef { |
460 | 319 | finalized_block_header: (&*info.finalized_block_header).into(), |
461 | 319 | consensus: match &info.consensus { |
462 | 0 | ChainInformationConsensus::Unknown => ChainInformationConsensusRef::Unknown, |
463 | | ChainInformationConsensus::Aura { |
464 | 315 | finalized_authorities_list, |
465 | 315 | slot_duration, |
466 | 315 | } => ChainInformationConsensusRef::Aura { |
467 | 315 | finalized_authorities_list: header::AuraAuthoritiesIter::from_slice( |
468 | 315 | finalized_authorities_list, |
469 | 315 | ), |
470 | 315 | slot_duration: *slot_duration, |
471 | 315 | }, |
472 | | ChainInformationConsensus::Babe { |
473 | 4 | slots_per_epoch, |
474 | 4 | finalized_block_epoch_information, |
475 | 4 | finalized_next_epoch_transition, |
476 | 4 | } => ChainInformationConsensusRef::Babe { |
477 | 4 | slots_per_epoch: *slots_per_epoch, |
478 | 4 | finalized_block_epoch_information: finalized_block_epoch_information |
479 | 4 | .as_ref() |
480 | 4 | .map(|i| (&**i).into()0 ), Unexecuted instantiation: _RNCNvXsa_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB7_19ChainInformationRefINtNtCsaYZPK01V26L_4core7convert4FromRNtB7_16ChainInformationE4from0Bb_ Unexecuted instantiation: _RNCNvXsa_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB7_19ChainInformationRefINtNtCsaYZPK01V26L_4core7convert4FromRNtB7_16ChainInformationE4from0Bb_ |
481 | 4 | finalized_next_epoch_transition: (&**finalized_next_epoch_transition).into(), |
482 | 4 | }, |
483 | | }, |
484 | 319 | finality: (&info.finality).into(), |
485 | 319 | } |
486 | 319 | } _RNvXsa_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB5_19ChainInformationRefINtNtCsaYZPK01V26L_4core7convert4FromRNtB5_16ChainInformationE4from Line | Count | Source | 458 | 4 | fn from(info: &'a ChainInformation) -> ChainInformationRef<'a> { | 459 | 4 | ChainInformationRef { | 460 | 4 | finalized_block_header: (&*info.finalized_block_header).into(), | 461 | 4 | consensus: match &info.consensus { | 462 | 0 | ChainInformationConsensus::Unknown => ChainInformationConsensusRef::Unknown, | 463 | | ChainInformationConsensus::Aura { | 464 | 0 | finalized_authorities_list, | 465 | 0 | slot_duration, | 466 | 0 | } => ChainInformationConsensusRef::Aura { | 467 | 0 | finalized_authorities_list: header::AuraAuthoritiesIter::from_slice( | 468 | 0 | finalized_authorities_list, | 469 | 0 | ), | 470 | 0 | slot_duration: *slot_duration, | 471 | 0 | }, | 472 | | ChainInformationConsensus::Babe { | 473 | 4 | slots_per_epoch, | 474 | 4 | finalized_block_epoch_information, | 475 | 4 | finalized_next_epoch_transition, | 476 | 4 | } => ChainInformationConsensusRef::Babe { | 477 | 4 | slots_per_epoch: *slots_per_epoch, | 478 | 4 | finalized_block_epoch_information: finalized_block_epoch_information | 479 | 4 | .as_ref() | 480 | 4 | .map(|i| (&**i).into()), | 481 | 4 | finalized_next_epoch_transition: (&**finalized_next_epoch_transition).into(), | 482 | 4 | }, | 483 | | }, | 484 | 4 | finality: (&info.finality).into(), | 485 | 4 | } | 486 | 4 | } |
_RNvXsa_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB5_19ChainInformationRefINtNtCsaYZPK01V26L_4core7convert4FromRNtB5_16ChainInformationE4from Line | Count | Source | 458 | 315 | fn from(info: &'a ChainInformation) -> ChainInformationRef<'a> { | 459 | 315 | ChainInformationRef { | 460 | 315 | finalized_block_header: (&*info.finalized_block_header).into(), | 461 | 315 | consensus: match &info.consensus { | 462 | 0 | ChainInformationConsensus::Unknown => ChainInformationConsensusRef::Unknown, | 463 | | ChainInformationConsensus::Aura { | 464 | 315 | finalized_authorities_list, | 465 | 315 | slot_duration, | 466 | 315 | } => ChainInformationConsensusRef::Aura { | 467 | 315 | finalized_authorities_list: header::AuraAuthoritiesIter::from_slice( | 468 | 315 | finalized_authorities_list, | 469 | 315 | ), | 470 | 315 | slot_duration: *slot_duration, | 471 | 315 | }, | 472 | | ChainInformationConsensus::Babe { | 473 | 0 | slots_per_epoch, | 474 | 0 | finalized_block_epoch_information, | 475 | 0 | finalized_next_epoch_transition, | 476 | 0 | } => ChainInformationConsensusRef::Babe { | 477 | 0 | slots_per_epoch: *slots_per_epoch, | 478 | 0 | finalized_block_epoch_information: finalized_block_epoch_information | 479 | 0 | .as_ref() | 480 | 0 | .map(|i| (&**i).into()), | 481 | 0 | finalized_next_epoch_transition: (&**finalized_next_epoch_transition).into(), | 482 | 0 | }, | 483 | | }, | 484 | 315 | finality: (&info.finality).into(), | 485 | 315 | } | 486 | 315 | } |
|
487 | | } |
488 | | |
489 | | /// Extra items that depend on the consensus engine. |
490 | | #[derive(Debug, Clone)] |
491 | | pub enum ChainInformationConsensusRef<'a> { |
492 | | /// See [`ChainInformationConsensus::Unknown`]. |
493 | | Unknown, |
494 | | |
495 | | /// Chain is using the Aura consensus engine. |
496 | | Aura { |
497 | | /// See equivalent field in [`ChainInformationConsensus`]. |
498 | | finalized_authorities_list: header::AuraAuthoritiesIter<'a>, |
499 | | |
500 | | /// See equivalent field in [`ChainInformationConsensus`]. |
501 | | slot_duration: NonZeroU64, |
502 | | }, |
503 | | |
504 | | /// Chain is using the Babe consensus engine. |
505 | | Babe { |
506 | | /// See equivalent field in [`ChainInformationConsensus`]. |
507 | | slots_per_epoch: NonZeroU64, |
508 | | |
509 | | /// See equivalent field in [`ChainInformationConsensus`]. |
510 | | finalized_block_epoch_information: Option<BabeEpochInformationRef<'a>>, |
511 | | |
512 | | /// See equivalent field in [`ChainInformationConsensus`]. |
513 | | finalized_next_epoch_transition: BabeEpochInformationRef<'a>, |
514 | | }, |
515 | | } |
516 | | |
517 | | /// Information about a Babe epoch. |
518 | | #[derive(Debug, Clone)] |
519 | | pub struct BabeEpochInformationRef<'a> { |
520 | | /// See equivalent field in [`BabeEpochInformation`]. |
521 | | pub epoch_index: u64, |
522 | | |
523 | | /// See equivalent field in [`BabeEpochInformation`]. |
524 | | pub start_slot_number: Option<u64>, |
525 | | |
526 | | /// See equivalent field in [`BabeEpochInformation`]. |
527 | | pub authorities: header::BabeAuthoritiesIter<'a>, |
528 | | |
529 | | /// See equivalent field in [`BabeEpochInformation`]. |
530 | | pub randomness: &'a [u8; 32], |
531 | | |
532 | | /// See equivalent field in [`BabeEpochInformation`]. |
533 | | pub c: (u64, u64), |
534 | | |
535 | | /// See equivalent field in [`BabeEpochInformation`]. |
536 | | pub allowed_slots: header::BabeAllowedSlots, |
537 | | } |
538 | | |
539 | | impl<'a> BabeEpochInformationRef<'a> { |
540 | | /// Checks whether the fields in this struct make sense. |
541 | 5 | pub fn validate(&self) -> Result<(), BabeValidityError> { |
542 | 5 | if self.c.0 > self.c.1 { |
543 | 0 | return Err(BabeValidityError::InvalidConstant); |
544 | 5 | } |
545 | 5 | |
546 | 5 | Ok(()) |
547 | 5 | } _RNvMsb_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB5_23BabeEpochInformationRef8validate Line | Count | Source | 541 | 5 | pub fn validate(&self) -> Result<(), BabeValidityError> { | 542 | 5 | if self.c.0 > self.c.1 { | 543 | 0 | return Err(BabeValidityError::InvalidConstant); | 544 | 5 | } | 545 | 5 | | 546 | 5 | Ok(()) | 547 | 5 | } |
Unexecuted instantiation: _RNvMsb_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB5_23BabeEpochInformationRef8validate |
548 | | } |
549 | | |
550 | | impl<'a> From<&'a BabeEpochInformation> for BabeEpochInformationRef<'a> { |
551 | 12 | fn from(info: &'a BabeEpochInformation) -> BabeEpochInformationRef<'a> { |
552 | 12 | BabeEpochInformationRef { |
553 | 12 | epoch_index: info.epoch_index, |
554 | 12 | start_slot_number: info.start_slot_number, |
555 | 12 | authorities: header::BabeAuthoritiesIter::from_slice(&info.authorities), |
556 | 12 | randomness: &info.randomness, |
557 | 12 | c: info.c, |
558 | 12 | allowed_slots: info.allowed_slots, |
559 | 12 | } |
560 | 12 | } _RNvXsc_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB5_23BabeEpochInformationRefINtNtCsaYZPK01V26L_4core7convert4FromRNtB5_20BabeEpochInformationE4from Line | Count | Source | 551 | 12 | fn from(info: &'a BabeEpochInformation) -> BabeEpochInformationRef<'a> { | 552 | 12 | BabeEpochInformationRef { | 553 | 12 | epoch_index: info.epoch_index, | 554 | 12 | start_slot_number: info.start_slot_number, | 555 | 12 | authorities: header::BabeAuthoritiesIter::from_slice(&info.authorities), | 556 | 12 | randomness: &info.randomness, | 557 | 12 | c: info.c, | 558 | 12 | allowed_slots: info.allowed_slots, | 559 | 12 | } | 560 | 12 | } |
Unexecuted instantiation: _RNvXsc_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB5_23BabeEpochInformationRefINtNtCsaYZPK01V26L_4core7convert4FromRNtB5_20BabeEpochInformationE4from |
561 | | } |
562 | | |
563 | | /// Extra items that depend on the finality engine. |
564 | | #[derive(Debug, Clone)] |
565 | | pub enum ChainInformationFinalityRef<'a> { |
566 | | /// See equivalent variant in [`ChainInformationFinality`]. |
567 | | Outsourced, |
568 | | |
569 | | /// See equivalent variant in [`ChainInformationFinality`]. |
570 | | Grandpa { |
571 | | /// See equivalent field in [`ChainInformationFinality`]. |
572 | | after_finalized_block_authorities_set_id: u64, |
573 | | |
574 | | /// See equivalent field in [`ChainInformationFinality`]. |
575 | | finalized_triggered_authorities: &'a [header::GrandpaAuthority], |
576 | | |
577 | | /// See equivalent field in [`ChainInformationFinality`]. |
578 | | finalized_scheduled_change: Option<(u64, &'a [header::GrandpaAuthority])>, |
579 | | }, |
580 | | } |
581 | | |
582 | | impl<'a> From<&'a ChainInformationFinality> for ChainInformationFinalityRef<'a> { |
583 | 319 | fn from(finality: &'a ChainInformationFinality) -> ChainInformationFinalityRef<'a> { |
584 | 319 | match finality { |
585 | 0 | ChainInformationFinality::Outsourced => ChainInformationFinalityRef::Outsourced, |
586 | | ChainInformationFinality::Grandpa { |
587 | 319 | finalized_triggered_authorities, |
588 | 319 | after_finalized_block_authorities_set_id, |
589 | 319 | finalized_scheduled_change, |
590 | 319 | } => ChainInformationFinalityRef::Grandpa { |
591 | 319 | after_finalized_block_authorities_set_id: *after_finalized_block_authorities_set_id, |
592 | 319 | finalized_triggered_authorities, |
593 | 319 | finalized_scheduled_change: finalized_scheduled_change |
594 | 319 | .as_ref() |
595 | 319 | .map(|(n, l)| (*n, &l[..])0 ), Unexecuted instantiation: _RNCNvXsd_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB7_27ChainInformationFinalityRefINtNtCsaYZPK01V26L_4core7convert4FromRNtB7_24ChainInformationFinalityE4from0Bb_ Unexecuted instantiation: _RNCNvXsd_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB7_27ChainInformationFinalityRefINtNtCsaYZPK01V26L_4core7convert4FromRNtB7_24ChainInformationFinalityE4from0Bb_ |
596 | 319 | }, |
597 | | } |
598 | 319 | } _RNvXsd_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB5_27ChainInformationFinalityRefINtNtCsaYZPK01V26L_4core7convert4FromRNtB5_24ChainInformationFinalityE4from Line | Count | Source | 583 | 4 | fn from(finality: &'a ChainInformationFinality) -> ChainInformationFinalityRef<'a> { | 584 | 4 | match finality { | 585 | 0 | ChainInformationFinality::Outsourced => ChainInformationFinalityRef::Outsourced, | 586 | | ChainInformationFinality::Grandpa { | 587 | 4 | finalized_triggered_authorities, | 588 | 4 | after_finalized_block_authorities_set_id, | 589 | 4 | finalized_scheduled_change, | 590 | 4 | } => ChainInformationFinalityRef::Grandpa { | 591 | 4 | after_finalized_block_authorities_set_id: *after_finalized_block_authorities_set_id, | 592 | 4 | finalized_triggered_authorities, | 593 | 4 | finalized_scheduled_change: finalized_scheduled_change | 594 | 4 | .as_ref() | 595 | 4 | .map(|(n, l)| (*n, &l[..])), | 596 | 4 | }, | 597 | | } | 598 | 4 | } |
_RNvXsd_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB5_27ChainInformationFinalityRefINtNtCsaYZPK01V26L_4core7convert4FromRNtB5_24ChainInformationFinalityE4from Line | Count | Source | 583 | 315 | fn from(finality: &'a ChainInformationFinality) -> ChainInformationFinalityRef<'a> { | 584 | 315 | match finality { | 585 | 0 | ChainInformationFinality::Outsourced => ChainInformationFinalityRef::Outsourced, | 586 | | ChainInformationFinality::Grandpa { | 587 | 315 | finalized_triggered_authorities, | 588 | 315 | after_finalized_block_authorities_set_id, | 589 | 315 | finalized_scheduled_change, | 590 | 315 | } => ChainInformationFinalityRef::Grandpa { | 591 | 315 | after_finalized_block_authorities_set_id: *after_finalized_block_authorities_set_id, | 592 | 315 | finalized_triggered_authorities, | 593 | 315 | finalized_scheduled_change: finalized_scheduled_change | 594 | 315 | .as_ref() | 595 | 315 | .map(|(n, l)| (*n, &l[..])), | 596 | 315 | }, | 597 | | } | 598 | 315 | } |
|
599 | | } |
600 | | |
601 | | /// Error when turning a [`ChainInformation`] into a [`ValidChainInformation`]. |
602 | 0 | #[derive(Debug, derive_more::Display)] Unexecuted instantiation: _RNvXsz_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB5_13ValidityErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt Unexecuted instantiation: _RNvXsz_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB5_13ValidityErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt |
603 | | pub enum ValidityError { |
604 | | /// The finalized block doesn't use the same consensus algorithm as the one in the chain |
605 | | /// information. |
606 | | ConsensusAlgorithmMismatch, |
607 | | /// Found a Babe slot start number for future Babe epoch number 0. A future Babe epoch 0 has |
608 | | /// no known starting slot. |
609 | | UnexpectedBabeSlotStartNumber, |
610 | | /// Missing Babe slot start number for Babe epoch number other than future epoch 0. |
611 | | MissingBabeSlotStartNumber, |
612 | | /// Finalized block is block number 0, and a Babe epoch information has been provided. This |
613 | | /// would imply the existence of a block -1 and below. |
614 | | UnexpectedBabeFinalizedEpoch, |
615 | | /// Finalized block is not number 0, but no Babe epoch information has been provided. |
616 | | NoBabeFinalizedEpoch, |
617 | | /// The slot of the finalized block is inferior to the start slot of the epoch it belongs to. |
618 | | HeaderBabeSlotInferiorToEpochStartSlot, |
619 | | /// Mismatch between the finalized block header digest and the Babe next epoch information. |
620 | | BabeEpochInfoMismatch, |
621 | | /// Scheduled GrandPa authorities change is before finalized block. |
622 | | ScheduledGrandPaChangeBeforeFinalized, |
623 | | /// The finalized block is block number 0, but the GrandPa authorities set id is not 0. |
624 | | FinalizedZeroButNonZeroAuthoritiesSetId, |
625 | | /// Error in a Babe epoch information. |
626 | | #[display(fmt = "Error in a Babe epoch information: {_0}")] |
627 | | InvalidBabe(BabeValidityError), |
628 | | } |
629 | | |
630 | | /// Error when checking the validity of a Babe epoch. |
631 | 0 | #[derive(Debug, derive_more::Display)] Unexecuted instantiation: _RNvXsB_NtNtCsN16ciHI6Qf_7smoldot5chain17chain_informationNtB5_17BabeValidityErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt Unexecuted instantiation: _RNvXsB_NtNtCseuYC0Zibziv_7smoldot5chain17chain_informationNtB5_17BabeValidityErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt |
632 | | pub enum BabeValidityError { |
633 | | /// Babe constant should be a fraction where the numerator is inferior or equal to the |
634 | | /// denominator. |
635 | | InvalidConstant, |
636 | | } |