Coverage Report

Created: 2024-05-16 12:16

/__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
}