Skip to main content

soil_client/consensus/
block_validation.rs

1// This file is part of Soil.
2
3// Copyright (C) Soil contributors.
4// Copyright (C) Parity Technologies (UK) Ltd.
5// SPDX-License-Identifier: Apache-2.0 OR GPL-3.0-or-later WITH Classpath-exception-2.0
6
7//! Block announcement validation.
8
9use super::BlockStatus;
10use futures::FutureExt as _;
11use std::{error::Error, future::Future, pin::Pin, sync::Arc};
12use subsoil::runtime::traits::Block;
13
14/// A type which provides access to chain information.
15pub trait Chain<B: Block> {
16	/// Retrieve the status of the block denoted by the given [`Block::Hash`].
17	fn block_status(&self, hash: B::Hash) -> Result<BlockStatus, Box<dyn Error + Send>>;
18}
19
20impl<T: Chain<B>, B: Block> Chain<B> for Arc<T> {
21	fn block_status(&self, hash: B::Hash) -> Result<BlockStatus, Box<dyn Error + Send>> {
22		(&**self).block_status(hash)
23	}
24}
25
26/// Result of `BlockAnnounceValidator::validate`.
27#[derive(Debug, PartialEq, Eq)]
28pub enum Validation {
29	/// Valid block announcement.
30	Success {
31		/// Is this the new best block of the node?
32		is_new_best: bool,
33	},
34	/// Invalid block announcement.
35	Failure {
36		/// Should we disconnect from this peer?
37		///
38		/// This should be used if the peer for example send junk to spam us.
39		disconnect: bool,
40	},
41}
42
43/// Type which checks incoming block announcements.
44pub trait BlockAnnounceValidator<B: Block> {
45	/// Validate the announced header and its associated data.
46	///
47	/// # Note
48	///
49	/// Returning [`Validation::Failure`] will lead to a decrease of the
50	/// peers reputation as it sent us invalid data.
51	///
52	/// The returned future should only resolve to an error if there was an internal error
53	/// validating the block announcement. If the block announcement itself is invalid, this should
54	/// *always* return [`Validation::Failure`].
55	fn validate(
56		&mut self,
57		header: &B::Header,
58		data: &[u8],
59	) -> Pin<Box<dyn Future<Output = Result<Validation, Box<dyn Error + Send>>> + Send>>;
60}
61
62/// Default implementation of `BlockAnnounceValidator`.
63#[derive(Debug)]
64pub struct DefaultBlockAnnounceValidator;
65
66impl<B: Block> BlockAnnounceValidator<B> for DefaultBlockAnnounceValidator {
67	fn validate(
68		&mut self,
69		_: &B::Header,
70		data: &[u8],
71	) -> Pin<Box<dyn Future<Output = Result<Validation, Box<dyn Error + Send>>> + Send>> {
72		let is_empty = data.is_empty();
73
74		async move {
75			if !is_empty {
76				log::debug!(
77					target: "sync",
78					"Received unknown data alongside the block announcement.",
79				);
80				Ok(Validation::Failure { disconnect: true })
81			} else {
82				Ok(Validation::Success { is_new_best: false })
83			}
84		}
85		.boxed()
86	}
87}