smoldot/chain_spec/
light_sync_state.rs

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
18use super::{ParseError, ParseErrorInner};
19use crate::header::BabeNextConfig;
20
21use alloc::{collections::BTreeMap, format, string::String, vec::Vec};
22use serde::{Deserialize, Serialize};
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
25#[serde(rename_all = "camelCase")]
26#[serde(deny_unknown_fields)]
27pub(super) struct LightSyncState {
28    babe_epoch_changes: HexString,
29    babe_finalized_block_weight: u32,
30    finalized_block_header: HexString,
31    grandpa_authority_set: HexString,
32}
33
34impl LightSyncState {
35    pub(super) fn decode(
36        &self,
37        block_number_bytes: usize,
38    ) -> Result<DecodedLightSyncState, ParseError> {
39        // We don't use `all_consuming` in order to remain compatible in case new fields are added
40        // in Substrate to these data structures.
41        // This really should be solved by having a proper format for checkpoints, but
42        // there isn't.
43        let grandpa_authority_set = match nom::Finish::finish(nom::Parser::parse(
44            &mut nom::combinator::complete(authority_set::<nom::error::Error<&[u8]>>),
45            &self.grandpa_authority_set.0[..],
46        )) {
47            Ok((_, v)) => v,
48            Err(_err) => return Err(ParseError(ParseErrorInner::Other)),
49        };
50        let babe_epoch_changes = match nom::Finish::finish(nom::Parser::parse(
51            &mut nom::combinator::complete(epoch_changes::<nom::error::Error<&[u8]>>),
52            &self.babe_epoch_changes.0[..],
53        )) {
54            Ok((_, v)) => v,
55            Err(_err) => return Err(ParseError(ParseErrorInner::Other)),
56        };
57
58        Ok(DecodedLightSyncState {
59            finalized_block_header: crate::header::decode(
60                &self.finalized_block_header.0[..],
61                block_number_bytes,
62            )
63            .map_err(|_| ParseError(ParseErrorInner::Other))?
64            .into(),
65            grandpa_authority_set,
66            babe_epoch_changes,
67        })
68    }
69}
70
71#[derive(Debug)]
72pub(super) struct DecodedLightSyncState {
73    pub(super) babe_epoch_changes: EpochChanges,
74    pub(super) finalized_block_header: crate::header::Header,
75    pub(super) grandpa_authority_set: AuthoritySet,
76}
77
78#[derive(Debug)]
79pub(super) struct EpochChanges {
80    _inner: ForkTree<PersistedEpochHeader>,
81    pub(super) epochs: BTreeMap<([u8; 32], u32), PersistedEpoch>,
82    // TODO: Substrate has added the field below to the checkpoints format ; it is commented out
83    //       right now in order to maintain compatibility with checkpoints that were generated
84    //       a long time ago
85    // gap: Option<GapEpochs>,
86}
87
88fn epoch_changes<'a, E: nom::error::ParseError<&'a [u8]>>(
89    bytes: &'a [u8],
90) -> nom::IResult<&'a [u8], EpochChanges, E> {
91    nom::Parser::parse(
92        &mut nom::combinator::map(
93            (
94                fork_tree(&mut persisted_epoch_header),
95                nom::combinator::flat_map(crate::util::nom_scale_compact_usize, move |num_elems| {
96                    nom::multi::many_m_n(
97                        num_elems,
98                        num_elems,
99                        (
100                            nom::bytes::streaming::take(32u32),
101                            nom::number::streaming::le_u32,
102                            persisted_epoch,
103                        ),
104                    )
105                }),
106            ),
107            move |(inner, epochs)| EpochChanges {
108                _inner: inner,
109                epochs: epochs
110                    .into_iter()
111                    .map(|(h, n, e)| ((*<&[u8; 32]>::try_from(h).unwrap(), n), e))
112                    .collect(),
113            },
114        ),
115        bytes,
116    )
117}
118
119#[allow(unused)]
120#[derive(Debug)]
121pub(super) struct GapEpochs {
122    current: ([u8; 32], u32, PersistedEpoch),
123    next: Option<([u8; 32], u32, BabeEpoch)>,
124}
125
126#[allow(unused)]
127fn gap_epochs<'a, E: nom::error::ParseError<&'a [u8]>>(
128    bytes: &'a [u8],
129) -> nom::IResult<&'a [u8], GapEpochs, E> {
130    nom::Parser::parse(
131        &mut nom::combinator::map(
132            (
133                (
134                    nom::combinator::map(nom::bytes::streaming::take(32u32), |b| {
135                        *<&[u8; 32]>::try_from(b).unwrap()
136                    }),
137                    nom::number::streaming::le_u32,
138                    persisted_epoch,
139                ),
140                crate::util::nom_option_decode((
141                    nom::combinator::map(nom::bytes::streaming::take(32u32), |b| {
142                        *<&[u8; 32]>::try_from(b).unwrap()
143                    }),
144                    nom::number::streaming::le_u32,
145                    babe_epoch,
146                )),
147            ),
148            move |(current, next)| GapEpochs { current, next },
149        ),
150        bytes,
151    )
152}
153
154#[derive(Debug)]
155#[allow(dead_code)] // Necessary to silence warnings about unused fields.
156pub(super) enum PersistedEpochHeader {
157    Genesis(EpochHeader, EpochHeader),
158    Regular(EpochHeader),
159}
160
161fn persisted_epoch_header<'a, E: nom::error::ParseError<&'a [u8]>>(
162    bytes: &'a [u8],
163) -> nom::IResult<&'a [u8], PersistedEpochHeader, E> {
164    nom::Parser::parse(
165        &mut nom::branch::alt((
166            nom::combinator::map(
167                nom::sequence::preceded(
168                    nom::bytes::streaming::tag(&[0][..]),
169                    (epoch_header, epoch_header),
170                ),
171                |(a, b)| PersistedEpochHeader::Genesis(a, b),
172            ),
173            nom::combinator::map(
174                nom::sequence::preceded(nom::bytes::streaming::tag(&[1][..]), epoch_header),
175                PersistedEpochHeader::Regular,
176            ),
177        )),
178        bytes,
179    )
180}
181
182#[derive(Debug)]
183pub(super) struct EpochHeader {
184    _start_slot: u64,
185    _end_slot: u64,
186}
187
188fn epoch_header<'a, E: nom::error::ParseError<&'a [u8]>>(
189    bytes: &'a [u8],
190) -> nom::IResult<&'a [u8], EpochHeader, E> {
191    nom::Parser::parse(
192        &mut nom::combinator::map(
193            (
194                nom::number::streaming::le_u64,
195                nom::number::streaming::le_u64,
196            ),
197            move |(start_slot, end_slot)| EpochHeader {
198                _start_slot: start_slot,
199                _end_slot: end_slot,
200            },
201        ),
202        bytes,
203    )
204}
205
206#[derive(Debug)]
207#[allow(dead_code)] // Necessary to silence warnings about unused fields.
208pub(super) enum PersistedEpoch {
209    Genesis(BabeEpoch, BabeEpoch),
210    Regular(BabeEpoch),
211}
212
213fn persisted_epoch<'a, E: nom::error::ParseError<&'a [u8]>>(
214    bytes: &'a [u8],
215) -> nom::IResult<&'a [u8], PersistedEpoch, E> {
216    nom::Parser::parse(
217        &mut nom::branch::alt((
218            nom::combinator::map(
219                nom::sequence::preceded(
220                    nom::bytes::streaming::tag(&[0][..]),
221                    (babe_epoch, babe_epoch),
222                ),
223                |(a, b)| PersistedEpoch::Genesis(a, b),
224            ),
225            nom::combinator::map(
226                nom::sequence::preceded(nom::bytes::streaming::tag(&[1][..]), babe_epoch),
227                PersistedEpoch::Regular,
228            ),
229        )),
230        bytes,
231    )
232}
233
234#[derive(Debug)]
235pub(super) struct BabeEpoch {
236    pub(super) epoch_index: u64,
237    pub(super) slot_number: u64,
238    pub(super) duration: u64,
239    pub(super) authorities: Vec<BabeAuthority>,
240    pub(super) randomness: [u8; 32],
241    pub(super) config: BabeNextConfig,
242}
243
244fn babe_epoch<'a, E: nom::error::ParseError<&'a [u8]>>(
245    bytes: &'a [u8],
246) -> nom::IResult<&'a [u8], BabeEpoch, E> {
247    nom::Parser::parse(
248        &mut nom::combinator::map(
249            (
250                nom::number::streaming::le_u64,
251                nom::number::streaming::le_u64,
252                nom::number::streaming::le_u64,
253                nom::combinator::flat_map(crate::util::nom_scale_compact_usize, move |num_elems| {
254                    nom::multi::many_m_n(num_elems, num_elems, babe_authority)
255                }),
256                nom::bytes::streaming::take(32u32),
257                |b| {
258                    BabeNextConfig::from_slice(b)
259                        .map(|c| (&b[17..], c)) // TODO: hacky to use a constant
260                        .map_err(|_| {
261                            nom::Err::Error(nom::error::make_error(
262                                b,
263                                nom::error::ErrorKind::MapOpt,
264                            ))
265                        })
266                },
267            ),
268            move |(epoch_index, slot_number, duration, authorities, randomness, config)| {
269                BabeEpoch {
270                    epoch_index,
271                    slot_number,
272                    duration,
273                    authorities,
274                    randomness: *<&[u8; 32]>::try_from(randomness).unwrap(),
275                    config,
276                }
277            },
278        ),
279        bytes,
280    )
281}
282
283#[derive(Debug, Copy, Clone, PartialEq, Eq)]
284pub struct BabeAuthority {
285    /// Sr25519 public key.
286    pub public_key: [u8; 32],
287    /// Arbitrary number indicating the weight of the authority.
288    ///
289    /// This value can only be compared to other weight values.
290    // TODO: should be NonZero<u64>; requires deep changes in decoding code though
291    pub weight: u64,
292}
293
294fn babe_authority<'a, E: nom::error::ParseError<&'a [u8]>>(
295    bytes: &'a [u8],
296) -> nom::IResult<&'a [u8], BabeAuthority, E> {
297    nom::Parser::parse(
298        &mut nom::combinator::map(
299            (
300                nom::bytes::streaming::take(32u32),
301                nom::number::streaming::le_u64,
302            ),
303            move |(public_key, weight)| BabeAuthority {
304                public_key: *<&[u8; 32]>::try_from(public_key).unwrap(),
305                weight,
306            },
307        ),
308        bytes,
309    )
310}
311
312#[derive(Debug)]
313pub(super) struct AuthoritySet {
314    pub(super) current_authorities: Vec<GrandpaAuthority>,
315    pub(super) set_id: u64,
316    _pending_standard_changes: ForkTree<PendingChange>,
317    _pending_forced_changes: Vec<PendingChange>,
318    /// Note: this field didn't exist in Substrate before 2021-01-20. Light sync states that are
319    /// older than that are missing it.
320    _authority_set_changes: Vec<(u64, u32)>,
321}
322
323fn authority_set<'a, E: nom::error::ParseError<&'a [u8]>>(
324    bytes: &'a [u8],
325) -> nom::IResult<&'a [u8], AuthoritySet, E> {
326    nom::Parser::parse(
327        &mut nom::combinator::map(
328            (
329                nom::combinator::flat_map(crate::util::nom_scale_compact_usize, move |num_elems| {
330                    nom::multi::many_m_n(num_elems, num_elems, grandpa_authority)
331                }),
332                nom::number::streaming::le_u64,
333                fork_tree(&mut pending_change),
334                nom::combinator::flat_map(crate::util::nom_scale_compact_usize, move |num_elems| {
335                    nom::multi::many_m_n(num_elems, num_elems, pending_change)
336                }),
337                nom::combinator::flat_map(crate::util::nom_scale_compact_usize, move |num_elems| {
338                    nom::multi::many_m_n(
339                        num_elems,
340                        num_elems,
341                        (
342                            nom::number::streaming::le_u64,
343                            nom::number::streaming::le_u32,
344                        ),
345                    )
346                }),
347            ),
348            move |(
349                current_authorities,
350                set_id,
351                pending_standard_changes,
352                pending_forced_changes,
353                authority_set_changes,
354            )| AuthoritySet {
355                current_authorities,
356                set_id,
357                _pending_standard_changes: pending_standard_changes,
358                _pending_forced_changes: pending_forced_changes,
359                _authority_set_changes: authority_set_changes,
360            },
361        ),
362        bytes,
363    )
364}
365
366#[derive(Debug)]
367pub(super) struct PendingChange {
368    _next_authorities: Vec<GrandpaAuthority>,
369    _delay: u32,
370    _canon_height: u32,
371    _canon_hash: [u8; 32],
372    _delay_kind: DelayKind,
373}
374
375fn pending_change<'a, E: nom::error::ParseError<&'a [u8]>>(
376    bytes: &'a [u8],
377) -> nom::IResult<&'a [u8], PendingChange, E> {
378    nom::Parser::parse(
379        &mut nom::combinator::map(
380            (
381                nom::combinator::flat_map(crate::util::nom_scale_compact_usize, move |num_elems| {
382                    nom::multi::many_m_n(num_elems, num_elems, grandpa_authority)
383                }),
384                nom::number::streaming::le_u32,
385                nom::number::streaming::le_u32,
386                nom::bytes::streaming::take(32u32),
387                delay_kind,
388            ),
389            move |(next_authorities, delay, canon_height, canon_hash, delay_kind)| PendingChange {
390                _next_authorities: next_authorities,
391                _delay: delay,
392                _canon_height: canon_height,
393                _canon_hash: *<&[u8; 32]>::try_from(canon_hash).unwrap(),
394                _delay_kind: delay_kind,
395            },
396        ),
397        bytes,
398    )
399}
400
401#[derive(Debug)]
402pub(super) enum DelayKind {
403    Finalized,
404    Best { _median_last_finalized: u32 },
405}
406
407fn delay_kind<'a, E: nom::error::ParseError<&'a [u8]>>(
408    bytes: &'a [u8],
409) -> nom::IResult<&'a [u8], DelayKind, E> {
410    nom::Parser::parse(
411        &mut nom::branch::alt((
412            nom::combinator::map(nom::bytes::streaming::tag(&[0][..]), |_| {
413                DelayKind::Finalized
414            }),
415            nom::combinator::map(
416                nom::sequence::preceded(
417                    nom::bytes::streaming::tag(&[1][..]),
418                    nom::number::streaming::le_u32,
419                ),
420                |median_last_finalized| DelayKind::Best {
421                    _median_last_finalized: median_last_finalized,
422                },
423            ),
424        )),
425        bytes,
426    )
427}
428
429#[derive(Debug, Copy, Clone, PartialEq, Eq)]
430pub struct GrandpaAuthority {
431    /// Ed25519 public key.
432    pub public_key: [u8; 32],
433
434    /// Arbitrary number indicating the weight of the authority.
435    ///
436    /// This value can only be compared to other weight values.
437    // TODO: should be NonZero<u64>; requires deep changes in decoding code though
438    pub weight: u64,
439}
440
441fn grandpa_authority<'a, E: nom::error::ParseError<&'a [u8]>>(
442    bytes: &'a [u8],
443) -> nom::IResult<&'a [u8], GrandpaAuthority, E> {
444    nom::Parser::parse(
445        &mut nom::combinator::map(
446            (
447                nom::bytes::streaming::take(32u32),
448                nom::number::streaming::le_u64,
449            ),
450            move |(public_key, weight)| GrandpaAuthority {
451                public_key: *<&[u8; 32]>::try_from(public_key).unwrap(),
452                weight,
453            },
454        ),
455        bytes,
456    )
457}
458
459#[derive(Debug)]
460pub(super) struct ForkTree<T> {
461    _roots: Vec<ForkTreeNode<T>>,
462    _best_finalized_number: Option<u32>,
463}
464
465fn fork_tree<'a, T, E: nom::error::ParseError<&'a [u8]>>(
466    inner: &mut impl nom::Parser<&'a [u8], Output = T, Error = E>,
467) -> impl nom::Parser<&'a [u8], Output = ForkTree<T>, Error = E> {
468    nom::combinator::map(
469        (
470            // We do parsing manually due to borrow checking troubles regarding `inner`.
471            move |mut bytes| {
472                let (bytes_rest, num_roots) = match crate::util::nom_scale_compact_usize(bytes) {
473                    Ok(d) => d,
474                    Err(err) => return Err(err),
475                };
476                bytes = bytes_rest;
477
478                let mut roots = Vec::with_capacity(num_roots);
479                for _ in 0..num_roots {
480                    let (bytes_rest, child) =
481                        match nom::Parser::parse(&mut fork_tree_node(inner), bytes) {
482                            Ok(d) => d,
483                            Err(err) => return Err(err),
484                        };
485                    bytes = bytes_rest;
486                    roots.push(child);
487                }
488
489                Ok((bytes, roots))
490            },
491            crate::util::nom_option_decode(nom::number::streaming::le_u32),
492        ),
493        |(roots, best_finalized_number)| ForkTree {
494            _roots: roots,
495            _best_finalized_number: best_finalized_number,
496        },
497    )
498}
499
500#[derive(Debug)]
501pub(super) struct ForkTreeNode<T> {
502    _hash: [u8; 32],
503    _number: u32,
504    _data: T,
505    _children: Vec<Self>,
506}
507
508fn fork_tree_node<'a, T, E: nom::error::ParseError<&'a [u8]>>(
509    inner: &mut impl nom::Parser<&'a [u8], Output = T, Error = E>,
510) -> impl nom::Parser<&'a [u8], Output = ForkTreeNode<T>, Error = E> {
511    nom::combinator::map(
512        (
513            nom::bytes::streaming::take(32u32),
514            nom::number::streaming::le_u32,
515            // We do parsing manually due to borrow checking troubles regarding `inner`.
516            move |mut bytes| {
517                let (bytes_rest, data) = match nom::Parser::parse(inner, bytes) {
518                    Ok(d) => d,
519                    Err(err) => return Err(err),
520                };
521                bytes = bytes_rest;
522
523                let (bytes_rest, num_children) = match crate::util::nom_scale_compact_usize(bytes) {
524                    Ok(d) => d,
525                    Err(err) => return Err(err),
526                };
527                bytes = bytes_rest;
528
529                let mut children = Vec::with_capacity(num_children);
530                for _ in 0..num_children {
531                    let (bytes_rest, child) =
532                        match nom::Parser::parse(&mut fork_tree_node(inner), bytes) {
533                            Ok(d) => d,
534                            Err(err) => return Err(err),
535                        };
536                    bytes = bytes_rest;
537                    children.push(child);
538                }
539
540                Ok((bytes, (data, children)))
541            },
542        ),
543        |(hash, number, (data, children))| ForkTreeNode {
544            _hash: *<&[u8; 32]>::try_from(hash).unwrap(),
545            _number: number,
546            _data: data,
547            _children: children,
548        },
549    )
550}
551
552#[derive(Debug, Clone, PartialEq, Eq, Hash)]
553pub(super) struct HexString(pub(super) Vec<u8>);
554
555impl serde::Serialize for HexString {
556    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
557    where
558        S: serde::Serializer,
559    {
560        format!("0x{}", hex::encode(&self.0[..])).serialize(serializer)
561    }
562}
563
564impl<'a> serde::Deserialize<'a> for HexString {
565    fn deserialize<D>(deserializer: D) -> Result<HexString, D::Error>
566    where
567        D: serde::Deserializer<'a>,
568    {
569        let string = String::deserialize(deserializer)?;
570
571        if !string.starts_with("0x") {
572            return Err(serde::de::Error::custom(
573                "hexadecimal string doesn't start with 0x",
574            ));
575        }
576
577        let bytes = hex::decode(&string[2..]).map_err(serde::de::Error::custom)?;
578        Ok(HexString(bytes))
579    }
580}