sc_service/client/block_rules.rs
1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! Client fixed chain specification rules
20
21use std::collections::{HashMap, HashSet};
22
23use sp_runtime::traits::{Block as BlockT, NumberFor};
24
25use sc_client_api::{BadBlocks, ForkBlocks};
26
27/// Chain specification rules lookup result.
28pub enum LookupResult<B: BlockT> {
29 /// Specification rules do not contain any special rules about this block
30 NotSpecial,
31 /// The block is known to be bad and should not be imported
32 KnownBad,
33 /// There is a specified canonical block hash for the given height
34 Expected(B::Hash),
35}
36
37/// Chain-specific block filtering rules.
38///
39/// This holds known bad blocks and known good forks, and
40/// is usually part of the chain spec.
41pub struct BlockRules<B: BlockT> {
42 bad: HashSet<B::Hash>,
43 forks: HashMap<NumberFor<B>, B::Hash>,
44}
45
46impl<B: BlockT> BlockRules<B> {
47 /// New block rules with provided black and white lists.
48 pub fn new(fork_blocks: ForkBlocks<B>, bad_blocks: BadBlocks<B>) -> Self {
49 Self {
50 bad: bad_blocks.unwrap_or_default(),
51 forks: fork_blocks.unwrap_or_default().into_iter().collect(),
52 }
53 }
54
55 /// Mark a new block as bad.
56 pub fn mark_bad(&mut self, hash: B::Hash) {
57 self.bad.insert(hash);
58 }
59
60 /// Check if there's any rule affecting the given block.
61 pub fn lookup(&self, number: NumberFor<B>, hash: &B::Hash) -> LookupResult<B> {
62 if let Some(hash_for_height) = self.forks.get(&number) {
63 if hash_for_height != hash {
64 return LookupResult::Expected(*hash_for_height)
65 }
66 }
67
68 if self.bad.contains(hash) {
69 return LookupResult::KnownBad
70 }
71
72 LookupResult::NotSpecial
73 }
74}