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