Coverage Report

Created: 2024-05-16 12:16

/__w/smoldot/smoldot/repo/lib/src/chain/blocks_tree/finality.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
//! Extension module containing the API and implementation of everything related to finality.
19
20
use super::*;
21
use crate::finality::{decode, verify};
22
23
use core::cmp;
24
25
impl<T> NonFinalizedTree<T> {
26
    /// Returns a list of blocks (by their height and hash) that need to be finalized before any
27
    /// of their descendants can be finalized.
28
    ///
29
    /// In other words, blocks in the [`NonFinalizedTree`] can be immediately finalized by call
30
    /// to [`NonFinalizedTree::verify_justification`] or
31
    /// [`NonFinalizedTree::verify_grandpa_commit_message`], unless they descend from any of the
32
    /// blocks returned by this function, in which case that block must be finalized beforehand.
33
43
    pub fn finality_checkpoints(&self) -> impl Iterator<Item = (u64, &[u8; 32])> {
34
43
        // Note that the code below assumes that GrandPa is the only finality algorithm currently
35
43
        // supported.
36
43
        debug_assert!(
37
43
            self.blocks_trigger_gp_change.is_empty()
38
0
                || !matches!(self.finality, Finality::Outsourced)
39
        );
40
41
43
        self.blocks_trigger_gp_change
42
43
            .range((
43
43
                ops::Bound::Excluded((
44
43
                    Some(self.finalized_block_number),
45
43
                    fork_tree::NodeIndex::MAX,
46
43
                )),
47
43
                ops::Bound::Unbounded,
48
43
            ))
49
43
            .map(|(_prev_auth_change_trigger_number, block_index)| {
50
0
                debug_assert!(_prev_auth_change_trigger_number
51
0
                    .map_or(false, |n| n > self.finalized_block_number));
Unexecuted instantiation: _RNCNCNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB8_16NonFinalizedTreepE20finality_checkpoints0s_0Bc_
Unexecuted instantiation: _RNCNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB8_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionuEE20finality_checkpoints0s_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB8_16NonFinalizedTreepE20finality_checkpoints0s_0Bc_
Unexecuted instantiation: _RNCNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB8_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE20finality_checkpoints0s_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB8_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE20finality_checkpoints0s_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB8_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE20finality_checkpoints0s_0CsibGXYHQB8Ea_25json_rpc_general_requests
52
0
                let block = self
53
0
                    .blocks
54
0
                    .get(*block_index)
55
0
                    .unwrap_or_else(|| unreachable!());
Unexecuted instantiation: _RNCNCNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB8_16NonFinalizedTreepE20finality_checkpoints00Bc_
Unexecuted instantiation: _RNCNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB8_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionuEE20finality_checkpoints00CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB8_16NonFinalizedTreepE20finality_checkpoints00Bc_
Unexecuted instantiation: _RNCNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB8_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE20finality_checkpoints00CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB8_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE20finality_checkpoints00CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB8_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE20finality_checkpoints00CsibGXYHQB8Ea_25json_rpc_general_requests
56
0
                (block.number, &block.hash)
57
43
            })
Unexecuted instantiation: _RNCNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE20finality_checkpoints0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionuEE20finality_checkpoints0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE20finality_checkpoints0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE20finality_checkpoints0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE20finality_checkpoints0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE20finality_checkpoints0CsibGXYHQB8Ea_25json_rpc_general_requests
58
43
    }
Unexecuted instantiation: _RNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreepE20finality_checkpointsB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionuEE20finality_checkpointsCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreepE20finality_checkpointsB8_
_RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE20finality_checkpointsCsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
33
4
    pub fn finality_checkpoints(&self) -> impl Iterator<Item = (u64, &[u8; 32])> {
34
4
        // Note that the code below assumes that GrandPa is the only finality algorithm currently
35
4
        // supported.
36
4
        debug_assert!(
37
4
            self.blocks_trigger_gp_change.is_empty()
38
0
                || !matches!(self.finality, Finality::Outsourced)
39
        );
40
41
4
        self.blocks_trigger_gp_change
42
4
            .range((
43
4
                ops::Bound::Excluded((
44
4
                    Some(self.finalized_block_number),
45
4
                    fork_tree::NodeIndex::MAX,
46
4
                )),
47
4
                ops::Bound::Unbounded,
48
4
            ))
49
4
            .map(|(_prev_auth_change_trigger_number, block_index)| {
50
                debug_assert!(_prev_auth_change_trigger_number
51
                    .map_or(false, |n| n > self.finalized_block_number));
52
                let block = self
53
                    .blocks
54
                    .get(*block_index)
55
                    .unwrap_or_else(|| unreachable!());
56
                (block.number, &block.hash)
57
4
            })
58
4
    }
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE20finality_checkpointsCscDgN54JpMGG_6author
_RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE20finality_checkpointsCsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
33
39
    pub fn finality_checkpoints(&self) -> impl Iterator<Item = (u64, &[u8; 32])> {
34
39
        // Note that the code below assumes that GrandPa is the only finality algorithm currently
35
39
        // supported.
36
39
        debug_assert!(
37
39
            self.blocks_trigger_gp_change.is_empty()
38
0
                || !matches!(self.finality, Finality::Outsourced)
39
        );
40
41
39
        self.blocks_trigger_gp_change
42
39
            .range((
43
39
                ops::Bound::Excluded((
44
39
                    Some(self.finalized_block_number),
45
39
                    fork_tree::NodeIndex::MAX,
46
39
                )),
47
39
                ops::Bound::Unbounded,
48
39
            ))
49
39
            .map(|(_prev_auth_change_trigger_number, block_index)| {
50
                debug_assert!(_prev_auth_change_trigger_number
51
                    .map_or(false, |n| n > self.finalized_block_number));
52
                let block = self
53
                    .blocks
54
                    .get(*block_index)
55
                    .unwrap_or_else(|| unreachable!());
56
                (block.number, &block.hash)
57
39
            })
58
39
    }
59
60
    /// Verifies the given justification.
61
    ///
62
    /// The verification is performed in the context of the chain. In particular, the
63
    /// verification will fail if the target block isn't already in the chain.
64
    ///
65
    /// If the verification succeeds, a [`FinalityApply`] object will be returned which can
66
    /// be used to apply the finalization.
67
    ///
68
    /// A randomness seed must be provided and will be used during the verification. Note that the
69
    /// verification is nonetheless deterministic.
70
    // TODO: expand the documentation about how blocks with authorities changes have to be finalized before any further block can be finalized
71
0
    pub fn verify_justification(
72
0
        &mut self,
73
0
        consensus_engine_id: [u8; 4],
74
0
        scale_encoded_justification: &[u8],
75
0
        randomness_seed: [u8; 32],
76
0
    ) -> Result<FinalityApply<T>, JustificationVerifyError> {
77
0
        match (&self.finality, &consensus_engine_id) {
78
            (Finality::Grandpa { .. }, b"FRNK") => {
79
                // Turn justification into a strongly-typed struct.
80
0
                let decoded = decode::decode_grandpa_justification(
81
0
                    scale_encoded_justification,
82
0
                    self.block_number_bytes,
83
0
                )
84
0
                .map_err(JustificationVerifyError::InvalidJustification)?;
85
86
                // Delegate the first step to the other function.
87
0
                let (block_index, authorities_set_id, authorities_list) = self
88
0
                    .verify_grandpa_finality_inner(decoded.target_hash, decoded.target_number)
89
0
                    .map_err(JustificationVerifyError::FinalityVerify)?;
90
91
0
                verify::verify_justification(verify::JustificationVerifyConfig {
92
0
                    justification: scale_encoded_justification,
93
0
                    block_number_bytes: self.block_number_bytes,
94
0
                    authorities_set_id,
95
0
                    authorities_list,
96
0
                    randomness_seed,
97
0
                })
98
0
                .map_err(JustificationVerifyError::VerificationFailed)?;
99
100
                // Justification has been successfully verified!
101
0
                Ok(FinalityApply {
102
0
                    chain: self,
103
0
                    to_finalize: block_index,
104
0
                })
105
            }
106
0
            _ => Err(JustificationVerifyError::JustificationEngineMismatch),
107
        }
108
0
    }
Unexecuted instantiation: _RNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreepE20verify_justificationB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionuEE20verify_justificationCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreepE20verify_justificationB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE20verify_justificationCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE20verify_justificationCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE20verify_justificationCsibGXYHQB8Ea_25json_rpc_general_requests
109
110
    /// Verifies the given Grandpa commit message.
111
    ///
112
    /// The verification is performed in the context of the chain. In particular, the
113
    /// verification will fail if the target block isn't already in the chain or if one of the
114
    /// voted blocks is unknown locally.
115
    ///
116
    /// If the verification succeeds, a [`FinalityApply`] object will be returned which can
117
    /// be used to apply the finalization.
118
    ///
119
    /// A randomness seed must be provided and will be used during the verification. Note that the
120
    /// verification is nonetheless deterministic.
121
0
    pub fn verify_grandpa_commit_message(
122
0
        &mut self,
123
0
        scale_encoded_commit: &[u8],
124
0
        randomness_seed: [u8; 32],
125
0
    ) -> Result<FinalityApply<T>, CommitVerifyError> {
126
        // The code below would panic if the chain doesn't use Grandpa.
127
0
        if !matches!(self.finality, Finality::Grandpa { .. }) {
128
0
            return Err(CommitVerifyError::NotGrandpa);
129
0
        }
130
131
0
        let decoded_commit =
132
0
            decode::decode_grandpa_commit(scale_encoded_commit, self.block_number_bytes)
133
0
                .map_err(|_| CommitVerifyError::InvalidCommit)?;
Unexecuted instantiation: _RNCNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE29verify_grandpa_commit_message0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionuEE29verify_grandpa_commit_message0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE29verify_grandpa_commit_message0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_commit_message0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_commit_message0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_commit_message0CsibGXYHQB8Ea_25json_rpc_general_requests
134
135
        // Delegate the first step to the other function.
136
0
        let (block_index, expected_authorities_set_id, authorities_list) = self
137
0
            .verify_grandpa_finality_inner(decoded_commit.target_hash, decoded_commit.target_number)
138
0
            .map_err(CommitVerifyError::FinalityVerify)?;
139
140
0
        let mut verification = verify::verify_commit(verify::CommitVerifyConfig {
141
0
            commit: scale_encoded_commit,
142
0
            block_number_bytes: self.block_number_bytes,
143
0
            expected_authorities_set_id,
144
0
            num_authorities: u32::try_from(authorities_list.clone().count()).unwrap(),
145
0
            randomness_seed,
146
0
        });
147
148
        loop {
149
0
            match verification {
150
                verify::CommitVerify::Finished(Ok(())) => {
151
0
                    drop(authorities_list);
152
0
                    return Ok(FinalityApply {
153
0
                        chain: self,
154
0
                        to_finalize: block_index,
155
0
                    });
156
                }
157
                verify::CommitVerify::FinishedUnknown => {
158
0
                    return Err(CommitVerifyError::NotEnoughKnownBlocks {
159
0
                        target_block_number: decoded_commit.target_number,
160
0
                    })
161
                }
162
0
                verify::CommitVerify::Finished(Err(error)) => {
163
0
                    return Err(CommitVerifyError::VerificationFailed(error))
164
                }
165
0
                verify::CommitVerify::IsAuthority(is_authority) => {
166
0
                    let to_find = is_authority.authority_public_key();
167
0
                    let result = authorities_list.clone().any(|a| a == to_find);
Unexecuted instantiation: _RNCNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE29verify_grandpa_commit_messages_0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionuEE29verify_grandpa_commit_messages_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE29verify_grandpa_commit_messages_0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_commit_messages_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_commit_messages_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_commit_messages_0CsibGXYHQB8Ea_25json_rpc_general_requests
168
0
                    verification = is_authority.resume(result);
169
0
                }
170
0
                verify::CommitVerify::IsParent(is_parent) => {
171
0
                    // Find in the list of non-finalized blocks the target of the check.
172
0
                    match self.blocks_by_hash.get(is_parent.block_hash()) {
173
0
                        Some(idx) => {
174
0
                            let result = self.blocks.is_ancestor(block_index, *idx);
175
0
                            verification = is_parent.resume(Some(result));
176
0
                        }
177
0
                        None => {
178
0
                            verification = is_parent.resume(None);
179
0
                        }
180
                    };
181
                }
182
            }
183
        }
184
0
    }
Unexecuted instantiation: _RNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreepE29verify_grandpa_commit_messageB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionuEE29verify_grandpa_commit_messageCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreepE29verify_grandpa_commit_messageB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_commit_messageCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_commit_messageCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_commit_messageCsibGXYHQB8Ea_25json_rpc_general_requests
185
186
    /// Sets the latest known finalized block. Trying to verify a block that isn't a descendant of
187
    /// that block will fail.
188
    ///
189
    /// The block must have been passed to [`NonFinalizedTree::verify_header`].
190
    ///
191
    /// Returns an iterator containing the now-finalized blocks and the pruned blocks in "reverse
192
    /// hierarchical order". Each block is yielded by the iterator before its parent.
193
    ///
194
    /// > **Note**: This function returns blocks in this order, because any other ordering would
195
    /// >           incur a performance cost. While returning blocks in hierarchical order would
196
    /// >           often be more convenient, the overhead of doing so is moved to the user.
197
    ///
198
    /// The pruning is completely performed, even if the iterator is dropped eagerly.
199
    ///
200
    /// If necessary, the current best block will be updated to be a descendant of the
201
    /// newly-finalized block.
202
0
    pub fn set_finalized_block(
203
0
        &mut self,
204
0
        block_hash: &[u8; 32],
205
0
    ) -> Result<SetFinalizedBlockIter<T>, SetFinalizedError> {
206
0
        let block_index = match self.blocks_by_hash.get(block_hash) {
207
0
            Some(idx) => *idx,
208
0
            None => return Err(SetFinalizedError::UnknownBlock),
209
        };
210
211
0
        Ok(self.set_finalized_block_inner(block_index))
212
0
    }
Unexecuted instantiation: _RNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreepE19set_finalized_blockB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreepE19set_finalized_blockB8_
213
214
    /// Common function for verifying GrandPa-finality-related messages.
215
    ///
216
    /// Returns the index of the possibly finalized block, the expected authorities set id, and
217
    /// an iterator to the list of authorities.
218
    ///
219
    /// # Panic
220
    ///
221
    /// Panics if the finality algorithm of the chain isn't Grandpa.
222
    ///
223
0
    fn verify_grandpa_finality_inner(
224
0
        &'_ self,
225
0
        target_hash: &[u8; 32],
226
0
        target_number: u64,
227
0
    ) -> Result<
228
0
        (
229
0
            fork_tree::NodeIndex,
230
0
            u64,
231
0
            impl Iterator<Item = &'_ [u8]> + Clone + '_,
232
0
        ),
233
0
        FinalityVerifyError,
234
0
    > {
235
0
        match &self.finality {
236
0
            Finality::Outsourced => panic!(),
237
            Finality::Grandpa {
238
0
                after_finalized_block_authorities_set_id,
239
0
                finalized_scheduled_change,
240
0
                finalized_triggered_authorities,
241
0
            } => {
242
0
                match target_number.cmp(&self.finalized_block_number) {
243
0
                    cmp::Ordering::Equal if *target_hash == self.finalized_block_hash => {
244
0
                        return Err(FinalityVerifyError::EqualToFinalized)
245
                    }
246
                    cmp::Ordering::Equal => {
247
0
                        return Err(FinalityVerifyError::EqualFinalizedHeightButInequalHash)
248
                    }
249
0
                    cmp::Ordering::Less => return Err(FinalityVerifyError::BelowFinalized),
250
0
                    _ => {}
251
                }
252
253
                // Find in the list of non-finalized blocks the one targeted by the justification.
254
0
                let block_index = match self.blocks_by_hash.get(target_hash) {
255
0
                    Some(idx) => *idx,
256
                    None => {
257
0
                        return Err(FinalityVerifyError::UnknownTargetBlock {
258
0
                            block_number: target_number,
259
0
                            block_hash: *target_hash,
260
0
                        });
261
                    }
262
                };
263
264
                // If any block between the latest finalized one and the target block triggers any
265
                // GrandPa authorities change, then we need to finalize that triggering block
266
                // before finalizing the one targeted by the justification.
267
                if let BlockFinality::Grandpa {
268
0
                    ref prev_auth_change_trigger_number,
269
                    ..
270
0
                } = self.blocks.get(block_index).unwrap().finality
271
                {
272
0
                    if let Some(prev_auth_change_trigger_number) = prev_auth_change_trigger_number {
273
0
                        if *prev_auth_change_trigger_number > self.finalized_block_number {
274
0
                            return Err(FinalityVerifyError::TooFarAhead {
275
0
                                justification_block_number: target_number,
276
0
                                justification_block_hash: *target_hash,
277
0
                                block_to_finalize_number: *prev_auth_change_trigger_number,
278
0
                            });
279
0
                        }
280
0
                    }
281
                } else {
282
0
                    unreachable!()
283
                }
284
285
                // Find which authorities are supposed to finalize the target block.
286
0
                let authorities_list = finalized_scheduled_change
287
0
                    .as_ref()
288
0
                    .filter(|(trigger_height, _)| *trigger_height < target_number)
Unexecuted instantiation: _RNCNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE29verify_grandpa_finality_inner0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionuEE29verify_grandpa_finality_inner0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE29verify_grandpa_finality_inner0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_finality_inner0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_finality_inner0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_finality_inner0CsibGXYHQB8Ea_25json_rpc_general_requests
289
0
                    .map_or(finalized_triggered_authorities, |(_, list)| list);
Unexecuted instantiation: _RNCNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE29verify_grandpa_finality_inners_0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionuEE29verify_grandpa_finality_inners_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE29verify_grandpa_finality_inners_0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_finality_inners_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_finality_inners_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_finality_inners_0CsibGXYHQB8Ea_25json_rpc_general_requests
290
0
291
0
                // As per above check, we know that the authorities of the target block are either
292
0
                // the same as the ones of the latest finalized block, or the ones contained in
293
0
                // the header of the latest finalized block.
294
0
295
0
                // First verification step complete.
296
0
                Ok((
297
0
                    block_index,
298
0
                    *after_finalized_block_authorities_set_id,
299
0
                    authorities_list.iter().map(|a| &a.public_key[..]),
Unexecuted instantiation: _RNCNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE29verify_grandpa_finality_inners0_0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionuEE29verify_grandpa_finality_inners0_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE29verify_grandpa_finality_inners0_0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_finality_inners0_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_finality_inners0_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_finality_inners0_0CsibGXYHQB8Ea_25json_rpc_general_requests
300
0
                ))
301
            }
302
        }
303
0
    }
Unexecuted instantiation: _RNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreepE29verify_grandpa_finality_innerB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionuEE29verify_grandpa_finality_innerCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreepE29verify_grandpa_finality_innerB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_finality_innerCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_finality_innerCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE29verify_grandpa_finality_innerCsibGXYHQB8Ea_25json_rpc_general_requests
304
305
    /// Implementation of [`NonFinalizedTree::set_finalized_block`].
306
    ///
307
    /// # Panic
308
    ///
309
    /// Panics if `block_index_to_finalize` isn't a valid node in the tree.
310
    ///
311
0
    fn set_finalized_block_inner(
312
0
        &mut self,
313
0
        block_index_to_finalize: fork_tree::NodeIndex,
314
0
    ) -> SetFinalizedBlockIter<T> {
315
0
        let new_finalized_block = self.blocks.get_mut(block_index_to_finalize).unwrap();
316
0
317
0
        // Update `self.finality`.
318
0
        match (&mut self.finality, &new_finalized_block.finality) {
319
0
            (Finality::Outsourced, BlockFinality::Outsourced) => {}
320
            (
321
                Finality::Grandpa {
322
0
                    after_finalized_block_authorities_set_id,
323
0
                    finalized_scheduled_change,
324
0
                    finalized_triggered_authorities,
325
0
                },
326
0
                BlockFinality::Grandpa {
327
0
                    after_block_authorities_set_id,
328
0
                    triggered_authorities,
329
0
                    scheduled_change,
330
0
                    ..
331
0
                },
332
0
            ) => {
333
0
                // Some sanity checks.
334
0
                debug_assert!(
335
0
                    *after_finalized_block_authorities_set_id <= *after_block_authorities_set_id
336
                );
337
0
                debug_assert!(scheduled_change
338
0
                    .as_ref()
339
0
                    .map_or(true, |(n, _)| *n > new_finalized_block.number));
Unexecuted instantiation: _RNCNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE25set_finalized_block_inners0_0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionuEE25set_finalized_block_inners0_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE25set_finalized_block_inners0_0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE25set_finalized_block_inners0_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE25set_finalized_block_inners0_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE25set_finalized_block_inners0_0CsibGXYHQB8Ea_25json_rpc_general_requests
340
341
0
                *after_finalized_block_authorities_set_id = *after_block_authorities_set_id;
342
0
                *finalized_triggered_authorities = triggered_authorities.clone();
343
0
                *finalized_scheduled_change = scheduled_change.clone();
344
            }
345
346
            // Mismatch between chain finality algorithm and block finality algorithm. Should never
347
            // happen.
348
0
            _ => unreachable!(),
349
        }
350
351
        // If the best block isn't a descendant of the block being finalized, then the best
352
        // block will change to a different block.
353
        // TODO: this is `O(n)`, does the user really need to know ahead of time whether the best block is updated?
354
0
        let updates_best_block = {
355
0
            let current_best: Option<fork_tree::NodeIndex> = self
356
0
                .blocks_by_best_score
357
0
                .last_key_value()
358
0
                .map(|(_, idx)| *idx);
Unexecuted instantiation: _RNCNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE25set_finalized_block_inner0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionuEE25set_finalized_block_inner0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE25set_finalized_block_inner0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE25set_finalized_block_inner0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE25set_finalized_block_inner0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE25set_finalized_block_inner0CsibGXYHQB8Ea_25json_rpc_general_requests
359
0
            Some(block_index_to_finalize) == current_best
360
0
                || current_best.map_or(true, |current_best| {
361
0
                    !self
362
0
                        .blocks
363
0
                        .is_ancestor(block_index_to_finalize, current_best)
364
0
                })
Unexecuted instantiation: _RNCNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE25set_finalized_block_inners_0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionuEE25set_finalized_block_inners_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreepE25set_finalized_block_inners_0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE25set_finalized_block_inners_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE25set_finalized_block_inners_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE25set_finalized_block_inners_0CsibGXYHQB8Ea_25json_rpc_general_requests
365
        };
366
367
0
        let new_finalized_block = self.blocks.get_mut(block_index_to_finalize).unwrap();
368
0
369
0
        // Update `self.finalized_consensus`.
370
0
        match (
371
0
            &mut self.finalized_consensus,
372
0
            &new_finalized_block.consensus,
373
        ) {
374
            (
375
                FinalizedConsensus::Aura {
376
0
                    authorities_list, ..
377
0
                },
378
0
                BlockConsensus::Aura {
379
0
                    authorities_list: new_list,
380
0
                },
381
0
            ) => {
382
0
                *authorities_list = new_list.clone();
383
0
            }
384
            (
385
                FinalizedConsensus::Babe {
386
0
                    block_epoch_information,
387
0
                    next_epoch_transition,
388
0
                    ..
389
0
                },
390
0
                BlockConsensus::Babe {
391
0
                    current_epoch,
392
0
                    next_epoch,
393
0
                },
394
0
            ) => {
395
0
                *block_epoch_information = current_epoch.clone();
396
0
                *next_epoch_transition = next_epoch.clone();
397
0
            }
398
            // Any mismatch of consensus engines between the chain and the newly-finalized block
399
            // should have been detected when the block got added to the chain.
400
0
            _ => unreachable!(),
401
        }
402
403
        // Update `self.finalized_block_header`, `self.finalized_block_hash`,
404
        // `self.finalized_block_number`, and `self.finalized_best_score`.
405
0
        mem::swap(
406
0
            &mut self.finalized_block_header,
407
0
            &mut new_finalized_block.header,
408
0
        );
409
0
        self.finalized_block_hash = new_finalized_block.hash;
410
0
        self.finalized_block_number = new_finalized_block.number;
411
0
        self.finalized_best_score = new_finalized_block.best_score;
412
0
413
0
        debug_assert_eq!(self.blocks.len(), self.blocks_by_hash.len());
414
0
        debug_assert_eq!(self.blocks.len(), self.blocks_by_best_score.len());
415
0
        debug_assert!(self.blocks.len() >= self.blocks_trigger_gp_change.len());
416
0
        SetFinalizedBlockIter {
417
0
            iter: self.blocks.prune_ancestors(block_index_to_finalize),
418
0
            blocks_by_hash: &mut self.blocks_by_hash,
419
0
            blocks_by_best_score: &mut self.blocks_by_best_score,
420
0
            blocks_trigger_gp_change: &mut self.blocks_trigger_gp_change,
421
0
            updates_best_block,
422
0
        }
423
0
    }
Unexecuted instantiation: _RNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreepE25set_finalized_block_innerB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionuEE25set_finalized_block_innerCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreepE25set_finalized_block_innerB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE25set_finalized_block_innerCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE25set_finalized_block_innerCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_16NonFinalizedTreeINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE25set_finalized_block_innerCsibGXYHQB8Ea_25json_rpc_general_requests
424
}
425
426
/// Returned by [`NonFinalizedTree::verify_justification`] and
427
/// [`NonFinalizedTree::verify_grandpa_commit_message`] on success.
428
///
429
/// As long as [`FinalityApply::apply`] isn't called, the underlying [`NonFinalizedTree`]
430
/// isn't modified.
431
#[must_use]
432
pub struct FinalityApply<'c, T> {
433
    chain: &'c mut NonFinalizedTree<T>,
434
    to_finalize: fork_tree::NodeIndex,
435
}
436
437
impl<'c, T> FinalityApply<'c, T> {
438
    /// Applies the justification, finalizing the given block.
439
    ///
440
    /// This function, including its return type, behaves in the same way as
441
    /// [`NonFinalizedTree::set_finalized_block`].
442
0
    pub fn apply(self) -> SetFinalizedBlockIter<'c, T> {
443
0
        self.chain.set_finalized_block_inner(self.to_finalize)
444
0
    }
Unexecuted instantiation: _RNvMs_NtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB4_13FinalityApplypE5applyBa_
Unexecuted instantiation: _RNvMs_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_13FinalityApplyINtNtCsaYZPK01V26L_4core6option6OptionuEE5applyCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_13FinalityApplypE5applyBa_
Unexecuted instantiation: _RNvMs_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_13FinalityApplyINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE5applyCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_13FinalityApplyINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE5applyCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_13FinalityApplyINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE5applyCsibGXYHQB8Ea_25json_rpc_general_requests
445
446
    /// Returns the user data of the block about to be justified.
447
0
    pub fn block_user_data(&mut self) -> &mut T {
448
0
        &mut self
449
0
            .chain
450
0
            .blocks
451
0
            .get_mut(self.to_finalize)
452
0
            .unwrap()
453
0
            .user_data
454
0
    }
Unexecuted instantiation: _RNvMs_NtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB4_13FinalityApplypE15block_user_dataBa_
Unexecuted instantiation: _RNvMs_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_13FinalityApplypE15block_user_dataBa_
455
456
    /// Returns true if the block to be finalized is the current best block.
457
0
    pub fn is_current_best_block(&self) -> bool {
458
0
        Some(self.to_finalize)
459
0
            == self
460
0
                .chain
461
0
                .blocks_by_best_score
462
0
                .last_key_value()
463
0
                .map(|(_, idx)| *idx)
Unexecuted instantiation: _RNCNvMs_NtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB6_13FinalityApplypE21is_current_best_block0Bc_
Unexecuted instantiation: _RNCNvMs_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB6_13FinalityApplypE21is_current_best_block0Bc_
464
0
    }
Unexecuted instantiation: _RNvMs_NtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB4_13FinalityApplypE21is_current_best_blockBa_
Unexecuted instantiation: _RNvMs_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB4_13FinalityApplypE21is_current_best_blockBa_
465
}
466
467
impl<'c, T> fmt::Debug for FinalityApply<'c, T> {
468
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
469
0
        f.debug_tuple("FinalityApply").finish()
470
0
    }
Unexecuted instantiation: _RNvXININtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalitys0_0pEINtB5_13FinalityApplypENtNtCsaYZPK01V26L_4core3fmt5Debug3fmtBb_
Unexecuted instantiation: _RNvXININtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalitys0_0pEINtB5_13FinalityApplypENtNtCsaYZPK01V26L_4core3fmt5Debug3fmtBb_
471
}
472
473
/// Error that can happen when verifying a justification.
474
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXs5_NtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityNtB5_24JustificationVerifyErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs5_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityNtB5_24JustificationVerifyErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
475
pub enum JustificationVerifyError {
476
    /// Type of the justification doesn't match the finality mechanism used by the chain.
477
    ///
478
    /// > **Note**: If the chain's finality mechanism doesn't use justifications, this error is
479
    /// >           always returned.
480
    JustificationEngineMismatch,
481
    /// Error while decoding the justification.
482
    #[display(fmt = "Error while decoding the justification: {_0}")]
483
    InvalidJustification(decode::JustificationDecodeError),
484
    /// The justification verification has failed. The justification is invalid and should be
485
    /// thrown away.
486
    #[display(fmt = "{_0}")]
487
    VerificationFailed(verify::JustificationVerifyError),
488
    /// Error while verifying the finality in the context of the chain.
489
    #[display(fmt = "{_0}")]
490
    FinalityVerify(FinalityVerifyError),
491
}
492
493
/// Error that can happen when verifying a Grandpa commit.
494
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXs7_NtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityNtB5_17CommitVerifyErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs7_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityNtB5_17CommitVerifyErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
495
pub enum CommitVerifyError {
496
    /// Chain doesn't use the GrandPa algorithm.
497
    NotGrandpa,
498
    /// Error while decoding the commit.
499
    InvalidCommit,
500
    /// Error while verifying the finality in the context of the chain.
501
    #[display(fmt = "{_0}")]
502
    FinalityVerify(FinalityVerifyError),
503
    /// Not enough blocks are known by the tree to verify this commit.
504
    ///
505
    /// This doesn't mean that the commit is bad, but that it can't be verified without adding
506
    /// more blocks to the tree.
507
    #[display(fmt = "Not enough blocks are known to verify this commit")]
508
    NotEnoughKnownBlocks {
509
        /// Block number that the commit targets.
510
        target_block_number: u64,
511
    },
512
    /// The commit verification has failed. The commit is invalid and should be thrown away.
513
    #[display(fmt = "{_0}")]
514
    VerificationFailed(verify::CommitVerifyError),
515
}
516
517
/// Error that can happen when verifying a proof of finality.
518
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXs9_NtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityNtB5_19FinalityVerifyErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs9_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityNtB5_19FinalityVerifyErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
519
pub enum FinalityVerifyError {
520
    /// The target block height and hash are the same as the block that is already finalized.
521
    /// While the proof couldn't be verified, nothing could be gained from actually verifying it.
522
    EqualToFinalized,
523
    /// The target block height is the same as the finalized block, but its hash is different.
524
    /// This means that the proof can't possibly be correct.
525
    EqualFinalizedHeightButInequalHash,
526
    /// The target block height is strictly inferior to the finalized block height.
527
    BelowFinalized,
528
    /// Finality proof targets a block that isn't in the chain.
529
    #[display(fmt = "Justification targets a block (#{block_number}) that isn't in the chain.")]
530
    UnknownTargetBlock {
531
        /// Number of the block that isn't in the chain.
532
        block_number: u64,
533
        /// Hash of the block that isn't in the chain.
534
        block_hash: [u8; 32],
535
    },
536
    /// There exists a block in-between the latest finalized block and the block targeted by the
537
    /// justification that must first be finalized.
538
    #[display(
539
        fmt = "There exists a block in-between the latest finalized block and the block \
540
                     targeted by the justification that must first be finalized"
541
    )]
542
    TooFarAhead {
543
        /// Number of the block contained in the justification.
544
        justification_block_number: u64,
545
        /// Hash of the block contained in the justification.
546
        justification_block_hash: [u8; 32],
547
        /// Number of the block to finalize first.
548
        block_to_finalize_number: u64,
549
    },
550
}
551
552
/// Iterator producing the newly-finalized blocks removed from the state when the finalized block
553
/// is updated.
554
pub struct SetFinalizedBlockIter<'a, T> {
555
    iter: fork_tree::PruneAncestorsIter<'a, Block<T>>,
556
    blocks_by_hash: &'a mut HashMap<[u8; 32], fork_tree::NodeIndex, fnv::FnvBuildHasher>,
557
    blocks_by_best_score: &'a mut BTreeMap<BestScore, fork_tree::NodeIndex>,
558
    blocks_trigger_gp_change: &'a mut BTreeSet<(Option<u64>, fork_tree::NodeIndex)>,
559
    updates_best_block: bool,
560
}
561
562
impl<'a, T> SetFinalizedBlockIter<'a, T> {
563
    /// Returns true if the finalization process modifies the best block of the chain.
564
0
    pub fn updates_best_block(&self) -> bool {
565
0
        self.updates_best_block
566
0
    }
Unexecuted instantiation: _RNvMs1_NtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityINtB5_21SetFinalizedBlockIterpE18updates_best_blockBb_
Unexecuted instantiation: _RNvMs1_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB5_21SetFinalizedBlockIterINtNtCsaYZPK01V26L_4core6option6OptionuEE18updates_best_blockCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs1_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB5_21SetFinalizedBlockIterpE18updates_best_blockBb_
Unexecuted instantiation: _RNvMs1_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB5_21SetFinalizedBlockIterINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE18updates_best_blockCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs1_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB5_21SetFinalizedBlockIterINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE18updates_best_blockCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs1_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB5_21SetFinalizedBlockIterINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEE18updates_best_blockCsibGXYHQB8Ea_25json_rpc_general_requests
567
}
568
569
impl<'a, T> Iterator for SetFinalizedBlockIter<'a, T> {
570
    type Item = RemovedBlock<T>;
571
572
0
    fn next(&mut self) -> Option<Self::Item> {
573
0
        let pruned = self.iter.next()?;
574
0
        let _removed = self.blocks_by_hash.remove(&pruned.user_data.hash);
575
0
        debug_assert_eq!(_removed, Some(pruned.index));
576
0
        let _removed = self
577
0
            .blocks_by_best_score
578
0
            .remove(&pruned.user_data.best_score);
579
0
        debug_assert_eq!(_removed, Some(pruned.index));
580
        if let BlockFinality::Grandpa {
581
0
            prev_auth_change_trigger_number,
582
            triggers_change: true,
583
            ..
584
0
        } = pruned.user_data.finality
585
        {
586
0
            let _removed = self
587
0
                .blocks_trigger_gp_change
588
0
                .remove(&(prev_auth_change_trigger_number, pruned.index));
589
0
            debug_assert!(_removed);
590
0
        }
591
592
        Some(RemovedBlock {
593
0
            block_hash: pruned.user_data.hash,
594
0
            block_number: pruned.user_data.number,
595
0
            scale_encoded_header: pruned.user_data.header,
596
0
            user_data: pruned.user_data.user_data,
597
0
            ty: if pruned.is_prune_target_ancestor {
598
0
                RemovedBlockType::Finalized
599
            } else {
600
0
                RemovedBlockType::Pruned
601
            },
602
        })
603
0
    }
Unexecuted instantiation: _RNvXININtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalitys2_0pEINtB5_21SetFinalizedBlockIterpENtNtNtNtCsaYZPK01V26L_4core4iter6traits8iterator8Iterator4nextBb_
Unexecuted instantiation: _RNvXs2_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB5_21SetFinalizedBlockIterINtNtCsaYZPK01V26L_4core6option6OptionuEENtNtNtNtB1x_4iter6traits8iterator8Iterator4nextCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvXININtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalitys2_0pEINtB5_21SetFinalizedBlockIterpENtNtNtNtCsaYZPK01V26L_4core4iter6traits8iterator8Iterator4nextBb_
Unexecuted instantiation: _RNvXs2_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB5_21SetFinalizedBlockIterINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEENtNtNtNtB1x_4iter6traits8iterator8Iterator4nextCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvXs2_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB5_21SetFinalizedBlockIterINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEENtNtNtNtB1x_4iter6traits8iterator8Iterator4nextCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvXs2_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB5_21SetFinalizedBlockIterINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEENtNtNtNtB1x_4iter6traits8iterator8Iterator4nextCsibGXYHQB8Ea_25json_rpc_general_requests
604
605
0
    fn size_hint(&self) -> (usize, Option<usize>) {
606
0
        self.iter.size_hint()
607
0
    }
Unexecuted instantiation: _RNvXININtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalitys2_0pEINtB5_21SetFinalizedBlockIterpENtNtNtNtCsaYZPK01V26L_4core4iter6traits8iterator8Iterator9size_hintBb_
Unexecuted instantiation: _RNvXININtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalitys2_0pEINtB5_21SetFinalizedBlockIterpENtNtNtNtCsaYZPK01V26L_4core4iter6traits8iterator8Iterator9size_hintBb_
608
}
609
610
impl<'a, T> Drop for SetFinalizedBlockIter<'a, T> {
611
0
    fn drop(&mut self) {
612
        // Make sure the iteration goes to the end.
613
0
        for _ in self {}
614
0
    }
Unexecuted instantiation: _RNvXININtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalitys3_0pEINtB5_21SetFinalizedBlockIterpENtNtNtCsaYZPK01V26L_4core3ops4drop4Drop4dropBb_
Unexecuted instantiation: _RNvXs3_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB5_21SetFinalizedBlockIterINtNtCsaYZPK01V26L_4core6option6OptionuEENtNtNtB1x_3ops4drop4Drop4dropCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvXININtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalitys3_0pEINtB5_21SetFinalizedBlockIterpENtNtNtCsaYZPK01V26L_4core3ops4drop4Drop4dropBb_
Unexecuted instantiation: _RNvXs3_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB5_21SetFinalizedBlockIterINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEENtNtNtB1x_3ops4drop4Drop4dropCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvXs3_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB5_21SetFinalizedBlockIterINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEENtNtNtB1x_3ops4drop4Drop4dropCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvXs3_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityINtB5_21SetFinalizedBlockIterINtNtCsaYZPK01V26L_4core6option6OptionNtNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service17NonFinalizedBlockEENtNtNtB1x_3ops4drop4Drop4dropCsibGXYHQB8Ea_25json_rpc_general_requests
615
}
616
617
/// Error that can happen when setting the finalized block.
618
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXsb_NtNtNtCsN16ciHI6Qf_7smoldot5chain11blocks_tree8finalityNtB5_17SetFinalizedErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsb_NtNtNtCseuYC0Zibziv_7smoldot5chain11blocks_tree8finalityNtB5_17SetFinalizedErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
619
pub enum SetFinalizedError {
620
    /// Block must have been passed to [`NonFinalizedTree::insert_verified_header`] in the past.
621
    UnknownBlock,
622
}
623
624
/// Block removed from the [`NonFinalizedTree`] by a [`SetFinalizedBlockIter`].
625
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
626
pub struct RemovedBlock<T> {
627
    /// Hash of the block.
628
    pub block_hash: [u8; 32],
629
    /// Height of the block.
630
    pub block_number: u64,
631
    /// User data that was associated with that block in the [`NonFinalizedTree`].
632
    pub user_data: T,
633
    /// Reason why the block was removed.
634
    pub ty: RemovedBlockType,
635
    /// SCALE-encoded header of the block.
636
    pub scale_encoded_header: Vec<u8>,
637
}
638
639
/// Reason why a block was removed from the [`NonFinalizedTree`] by a [`SetFinalizedBlockIter`].
640
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
641
pub enum RemovedBlockType {
642
    /// Block is now part of the finalized chain.
643
    Finalized,
644
    /// Block is not a descendant of the new finalized block.
645
    Pruned,
646
}