referrerpolicy=no-referrer-when-downgrade

sp_consensus/
block_validation.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Block announcement validation.
19
20use crate::BlockStatus;
21use futures::FutureExt as _;
22use sp_runtime::traits::Block;
23use std::{error::Error, future::Future, pin::Pin, sync::Arc};
24
25/// A type which provides access to chain information.
26pub trait Chain<B: Block> {
27	/// Retrieve the status of the block denoted by the given [`Block::Hash`].
28	fn block_status(&self, hash: B::Hash) -> Result<BlockStatus, Box<dyn Error + Send>>;
29}
30
31impl<T: Chain<B>, B: Block> Chain<B> for Arc<T> {
32	fn block_status(&self, hash: B::Hash) -> Result<BlockStatus, Box<dyn Error + Send>> {
33		(&**self).block_status(hash)
34	}
35}
36
37/// Result of `BlockAnnounceValidator::validate`.
38#[derive(Debug, PartialEq, Eq)]
39pub enum Validation {
40	/// Valid block announcement.
41	Success {
42		/// Is this the new best block of the node?
43		is_new_best: bool,
44	},
45	/// Invalid block announcement.
46	Failure {
47		/// Should we disconnect from this peer?
48		///
49		/// This should be used if the peer for example send junk to spam us.
50		disconnect: bool,
51	},
52}
53
54/// Type which checks incoming block announcements.
55pub trait BlockAnnounceValidator<B: Block> {
56	/// Validate the announced header and its associated data.
57	///
58	/// # Note
59	///
60	/// Returning [`Validation::Failure`] will lead to a decrease of the
61	/// peers reputation as it sent us invalid data.
62	///
63	/// The returned future should only resolve to an error if there was an internal error
64	/// validating the block announcement. If the block announcement itself is invalid, this should
65	/// *always* return [`Validation::Failure`].
66	fn validate(
67		&mut self,
68		header: &B::Header,
69		data: &[u8],
70	) -> Pin<Box<dyn Future<Output = Result<Validation, Box<dyn Error + Send>>> + Send>>;
71}
72
73/// Default implementation of `BlockAnnounceValidator`.
74#[derive(Debug)]
75pub struct DefaultBlockAnnounceValidator;
76
77impl<B: Block> BlockAnnounceValidator<B> for DefaultBlockAnnounceValidator {
78	fn validate(
79		&mut self,
80		_: &B::Header,
81		data: &[u8],
82	) -> Pin<Box<dyn Future<Output = Result<Validation, Box<dyn Error + Send>>> + Send>> {
83		let is_empty = data.is_empty();
84
85		async move {
86			if !is_empty {
87				log::debug!(
88					target: "sync",
89					"Received unknown data alongside the block announcement.",
90				);
91				Ok(Validation::Failure { disconnect: true })
92			} else {
93				Ok(Validation::Success { is_new_best: false })
94			}
95		}
96		.boxed()
97	}
98}