/__w/smoldot/smoldot/repo/lib/src/sync/para.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 | | //! Parachains and parathreads syncing. |
19 | | //! |
20 | | //! A parachain is a blockchain whose best and finalized blocks are determined by looking at the |
21 | | //! storage of a different chain called the relay chain. |
22 | | //! |
23 | | //! In order to obtain the current best block of a parachain, you must obtain the parachains |
24 | | //! persisted validation data from the relay chain. This is done by calling the |
25 | | //! `ParachainHost_persisted_validation_data` runtime function. The runtime function returns |
26 | | //! an opaque set of bytes called the "head data" whose meaning depends on the parachain. Most of |
27 | | //! the time, it is a block hash. |
28 | | //! |
29 | | //! In order to obtain the current finalized block of a parachain, do the same but on the current |
30 | | //! finalized block of the relay chain. |
31 | | //! |
32 | | //! See the [`persisted_validation_data_parameters`] to obtain the input to pass to the runtime |
33 | | //! function. The first parameter is a `para_id` found in the chain specification of the |
34 | | //! parachain of parathread. |
35 | | |
36 | | /// Produces the input to pass to the `ParachainHost_persisted_validation_data` runtime call. |
37 | 0 | pub fn persisted_validation_data_parameters( |
38 | 0 | para_id: u32, |
39 | 0 | assumption: OccupiedCoreAssumption, |
40 | 0 | ) -> impl Iterator<Item = impl AsRef<[u8]>> + Clone { |
41 | 0 | [ |
42 | 0 | either::Left(para_id.to_le_bytes()), |
43 | 0 | either::Right(assumption.scale_encoded()), |
44 | 0 | ] |
45 | 0 | .into_iter() |
46 | 0 | } Unexecuted instantiation: _RNvNtNtCsN16ciHI6Qf_7smoldot4sync4para36persisted_validation_data_parameters Unexecuted instantiation: _RNvNtNtCseuYC0Zibziv_7smoldot4sync4para36persisted_validation_data_parameters |
47 | | |
48 | | /// Name of the runtime function to call in order to obtain the parachain heads. |
49 | | pub const PERSISTED_VALIDATION_FUNCTION_NAME: &str = "ParachainHost_persisted_validation_data"; |
50 | | |
51 | | /// An assumption being made about the state of an occupied core. |
52 | | // TODO: what does that mean? |
53 | | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
54 | | pub enum OccupiedCoreAssumption { |
55 | | /// The candidate occupying the core was made available and included to free the core. |
56 | | Included, |
57 | | /// The candidate occupying the core timed out and freed the core without advancing the para. |
58 | | TimedOut, |
59 | | /// The core was not occupied to begin with. |
60 | | Free, |
61 | | } |
62 | | |
63 | | impl OccupiedCoreAssumption { |
64 | | /// Returns the SCALE encoding of this type. |
65 | 0 | pub fn scale_encoded(&self) -> impl AsRef<[u8]> + Clone { |
66 | 0 | match self { |
67 | 0 | OccupiedCoreAssumption::Included => [0], |
68 | 0 | OccupiedCoreAssumption::TimedOut => [1], |
69 | 0 | OccupiedCoreAssumption::Free => [2], |
70 | | } |
71 | 0 | } Unexecuted instantiation: _RNvMNtNtCsN16ciHI6Qf_7smoldot4sync4paraNtB2_22OccupiedCoreAssumption13scale_encoded Unexecuted instantiation: _RNvMNtNtCseuYC0Zibziv_7smoldot4sync4paraNtB2_22OccupiedCoreAssumption13scale_encoded |
72 | | } |
73 | | |
74 | | /// Attempt to decode the return value of the `ParachainHost_persisted_validation_data` runtime |
75 | | /// call. |
76 | 1 | pub fn decode_persisted_validation_data_return_value( |
77 | 1 | scale_encoded: &[u8], |
78 | 1 | block_number_bytes: usize, |
79 | 1 | ) -> Result<Option<PersistedValidationDataRef>, Error> { |
80 | 1 | let res: Result<_, nom::Err<nom::error::Error<_>>> = nom::combinator::all_consuming( |
81 | 1 | crate::util::nom_option_decode(persisted_validation_data(block_number_bytes)), |
82 | 1 | )(scale_encoded); |
83 | 0 | match res { |
84 | 1 | Ok((_, data)) => Ok(data), |
85 | 0 | Err(nom::Err::Error(err) | nom::Err::Failure(err)) => Err(Error(err.code)), |
86 | 0 | Err(_) => unreachable!(), |
87 | | } |
88 | 1 | } _RNvNtNtCsN16ciHI6Qf_7smoldot4sync4para45decode_persisted_validation_data_return_value Line | Count | Source | 76 | 1 | pub fn decode_persisted_validation_data_return_value( | 77 | 1 | scale_encoded: &[u8], | 78 | 1 | block_number_bytes: usize, | 79 | 1 | ) -> Result<Option<PersistedValidationDataRef>, Error> { | 80 | 1 | let res: Result<_, nom::Err<nom::error::Error<_>>> = nom::combinator::all_consuming( | 81 | 1 | crate::util::nom_option_decode(persisted_validation_data(block_number_bytes)), | 82 | 1 | )(scale_encoded); | 83 | 0 | match res { | 84 | 1 | Ok((_, data)) => Ok(data), | 85 | 0 | Err(nom::Err::Error(err) | nom::Err::Failure(err)) => Err(Error(err.code)), | 86 | 0 | Err(_) => unreachable!(), | 87 | | } | 88 | 1 | } |
Unexecuted instantiation: _RNvNtNtCseuYC0Zibziv_7smoldot4sync4para45decode_persisted_validation_data_return_value |
89 | | |
90 | | /// Error that can happen during the decoding. |
91 | 0 | #[derive(Debug, derive_more::Display)] Unexecuted instantiation: _RNvXs7_NtNtCsN16ciHI6Qf_7smoldot4sync4paraNtB5_5ErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt Unexecuted instantiation: _RNvXs7_NtNtCseuYC0Zibziv_7smoldot4sync4paraNtB5_5ErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt |
92 | | #[display(fmt = "Error decoding persisted validation data")] |
93 | | pub struct Error(nom::error::ErrorKind); |
94 | | |
95 | | /// Decoded persisted validation data. |
96 | | // TODO: document and explain |
97 | | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
98 | | pub struct PersistedValidationDataRef<'a> { |
99 | | /// Opaque data representing the best block (or similar concept) of the parachain/parathread. |
100 | | /// |
101 | | /// The meaning of this data depends on the chain, but for chains built on top of Cumulus |
102 | | /// (i.e. the vast majority of chains) this consists in a block header. |
103 | | pub parent_head: &'a [u8], |
104 | | pub relay_parent_number: u64, |
105 | | pub relay_parent_storage_root: &'a [u8; 32], |
106 | | |
107 | | /// Maximum legal size of a POV block, in bytes. |
108 | | pub max_pov_size: u32, |
109 | | } |
110 | | |
111 | | /// `Nom` combinator that parses a [`PersistedValidationDataRef`]. |
112 | 1 | fn persisted_validation_data<'a, E: nom::error::ParseError<&'a [u8]>>( |
113 | 1 | block_number_bytes: usize, |
114 | 1 | ) -> impl FnMut(&'a [u8]) -> nom::IResult<&[u8], PersistedValidationDataRef, E> { |
115 | 1 | nom::combinator::map( |
116 | 1 | nom::sequence::tuple(( |
117 | 1 | crate::util::nom_bytes_decode, |
118 | 1 | crate::util::nom_varsize_number_decode_u64(block_number_bytes), |
119 | 1 | nom::bytes::streaming::take(32u32), |
120 | 1 | nom::number::streaming::le_u32, |
121 | 1 | )), |
122 | 1 | |(parent_head, relay_parent_number, relay_parent_storage_root, max_pov_size)| { |
123 | 1 | PersistedValidationDataRef { |
124 | 1 | parent_head, |
125 | 1 | relay_parent_number, |
126 | 1 | relay_parent_storage_root: <&[u8; 32]>::try_from(relay_parent_storage_root) |
127 | 1 | .unwrap(), |
128 | 1 | max_pov_size, |
129 | 1 | } |
130 | 1 | }, _RNCINvNtNtCsN16ciHI6Qf_7smoldot4sync4para25persisted_validation_dataINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEE0B8_ Line | Count | Source | 122 | 1 | |(parent_head, relay_parent_number, relay_parent_storage_root, max_pov_size)| { | 123 | 1 | PersistedValidationDataRef { | 124 | 1 | parent_head, | 125 | 1 | relay_parent_number, | 126 | 1 | relay_parent_storage_root: <&[u8; 32]>::try_from(relay_parent_storage_root) | 127 | 1 | .unwrap(), | 128 | 1 | max_pov_size, | 129 | 1 | } | 130 | 1 | }, |
Unexecuted instantiation: _RNCINvNtNtCseuYC0Zibziv_7smoldot4sync4para25persisted_validation_dataINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEE0B8_ |
131 | 1 | ) |
132 | 1 | } _RINvNtNtCsN16ciHI6Qf_7smoldot4sync4para25persisted_validation_dataINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEEB6_ Line | Count | Source | 112 | 1 | fn persisted_validation_data<'a, E: nom::error::ParseError<&'a [u8]>>( | 113 | 1 | block_number_bytes: usize, | 114 | 1 | ) -> impl FnMut(&'a [u8]) -> nom::IResult<&[u8], PersistedValidationDataRef, E> { | 115 | 1 | nom::combinator::map( | 116 | 1 | nom::sequence::tuple(( | 117 | 1 | crate::util::nom_bytes_decode, | 118 | 1 | crate::util::nom_varsize_number_decode_u64(block_number_bytes), | 119 | 1 | nom::bytes::streaming::take(32u32), | 120 | 1 | nom::number::streaming::le_u32, | 121 | 1 | )), | 122 | 1 | |(parent_head, relay_parent_number, relay_parent_storage_root, max_pov_size)| { | 123 | | PersistedValidationDataRef { | 124 | | parent_head, | 125 | | relay_parent_number, | 126 | | relay_parent_storage_root: <&[u8; 32]>::try_from(relay_parent_storage_root) | 127 | | .unwrap(), | 128 | | max_pov_size, | 129 | | } | 130 | 1 | }, | 131 | 1 | ) | 132 | 1 | } |
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4sync4para25persisted_validation_dataINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEEB6_ |
133 | | |
134 | | #[cfg(test)] |
135 | | mod tests { |
136 | | #[test] |
137 | 1 | fn basic_decode() { |
138 | 1 | let encoded = [ |
139 | 1 | 1, 233, 2, 22, 207, 102, 211, 103, 223, 185, 141, 222, 102, 202, 83, 47, 68, 220, 233, |
140 | 1 | 136, 252, 151, 156, 190, 127, 178, 126, 69, 0, 176, 226, 54, 174, 2, 100, 26, 176, 149, |
141 | 1 | 0, 51, 178, 156, 151, 115, 34, 137, 183, 125, 44, 36, 155, 24, 27, 225, 97, 213, 118, |
142 | 1 | 100, 6, 42, 26, 94, 247, 4, 39, 46, 159, 44, 211, 102, 99, 155, 215, 16, 175, 12, 245, |
143 | 1 | 124, 60, 237, 51, 48, 68, 207, 77, 12, 7, 167, 106, 166, 110, 29, 77, 220, 206, 138, |
144 | 1 | 24, 168, 136, 247, 153, 227, 237, 8, 6, 97, 117, 114, 97, 32, 43, 60, 58, 8, 0, 0, 0, |
145 | 1 | 0, 5, 97, 117, 114, 97, 1, 1, 172, 118, 69, 16, 88, 154, 84, 2, 85, 206, 148, 69, 115, |
146 | 1 | 132, 204, 88, 113, 101, 26, 4, 1, 7, 28, 130, 119, 6, 112, 220, 22, 242, 128, 29, 5, |
147 | 1 | 151, 192, 57, 31, 159, 23, 159, 84, 155, 91, 207, 147, 191, 222, 231, 28, 75, 157, 111, |
148 | 1 | 200, 192, 160, 235, 111, 59, 238, 81, 72, 169, 102, 136, 160, 62, 175, 0, 118, 200, |
149 | 1 | 227, 89, 55, 136, 85, 177, 69, 145, 143, 221, 59, 214, 173, 221, 247, 145, 76, 245, 93, |
150 | 1 | 96, 108, 165, 183, 228, 200, 20, 171, 213, 194, 14, 0, 0, 80, 0, |
151 | 1 | ]; |
152 | 1 | |
153 | 1 | let expected = Some(super::PersistedValidationDataRef { |
154 | 1 | parent_head: &[ |
155 | 1 | 22, 207, 102, 211, 103, 223, 185, 141, 222, 102, 202, 83, 47, 68, 220, 233, 136, |
156 | 1 | 252, 151, 156, 190, 127, 178, 126, 69, 0, 176, 226, 54, 174, 2, 100, 26, 176, 149, |
157 | 1 | 0, 51, 178, 156, 151, 115, 34, 137, 183, 125, 44, 36, 155, 24, 27, 225, 97, 213, |
158 | 1 | 118, 100, 6, 42, 26, 94, 247, 4, 39, 46, 159, 44, 211, 102, 99, 155, 215, 16, 175, |
159 | 1 | 12, 245, 124, 60, 237, 51, 48, 68, 207, 77, 12, 7, 167, 106, 166, 110, 29, 77, 220, |
160 | 1 | 206, 138, 24, 168, 136, 247, 153, 227, 237, 8, 6, 97, 117, 114, 97, 32, 43, 60, 58, |
161 | 1 | 8, 0, 0, 0, 0, 5, 97, 117, 114, 97, 1, 1, 172, 118, 69, 16, 88, 154, 84, 2, 85, |
162 | 1 | 206, 148, 69, 115, 132, 204, 88, 113, 101, 26, 4, 1, 7, 28, 130, 119, 6, 112, 220, |
163 | 1 | 22, 242, 128, 29, 5, 151, 192, 57, 31, 159, 23, 159, 84, 155, 91, 207, 147, 191, |
164 | 1 | 222, 231, 28, 75, 157, 111, 200, 192, 160, 235, 111, 59, 238, 81, 72, 169, 102, |
165 | 1 | 136, |
166 | 1 | ], |
167 | 1 | relay_parent_number: 11484832, |
168 | 1 | relay_parent_storage_root: &[ |
169 | 1 | 118, 200, 227, 89, 55, 136, 85, 177, 69, 145, 143, 221, 59, 214, 173, 221, 247, |
170 | 1 | 145, 76, 245, 93, 96, 108, 165, 183, 228, 200, 20, 171, 213, 194, 14, |
171 | 1 | ], |
172 | 1 | max_pov_size: 5242880, |
173 | 1 | }); |
174 | 1 | |
175 | 1 | assert_eq!( |
176 | 1 | super::decode_persisted_validation_data_return_value(&encoded, 4).unwrap(), |
177 | 1 | expected |
178 | 1 | ); |
179 | 1 | } |
180 | | } |