Skip to main content

soil_client/consensus/
mod.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//! Common utilities for building and using consensus engines in substrate.
8//!
9//! Much of this crate is _unstable_ and thus the API is likely to undergo
10//! change. Implementors of traits should not rely on the interfaces to remain
11//! the same.
12
13use std::{sync::Arc, time::Duration};
14
15use futures::prelude::*;
16use subsoil::api::ProofRecorder;
17use subsoil::externalities::Extensions;
18use subsoil::runtime::{
19	traits::{Block as BlockT, HashingFor},
20	Digest,
21};
22
23pub mod block_validation;
24pub mod error;
25mod select_chain;
26
27pub use self::error::Error;
28pub use select_chain::SelectChain;
29pub use subsoil::inherents::InherentData;
30pub use subsoil::state_machine::Backend as StateBackend;
31
32/// Block status.
33#[derive(Debug, PartialEq, Eq, Clone)]
34pub enum BlockStatus {
35	/// Added to the import queue.
36	Queued,
37	/// Already in the blockchain and the state is available.
38	InChainWithState,
39	/// In the blockchain, but the state is not available.
40	InChainPruned,
41	/// Block or parent is known to be bad.
42	KnownBad,
43	/// Not in the queue or the blockchain.
44	Unknown,
45}
46
47/// Block data origin.
48#[derive(Debug, PartialEq, Eq, Clone, Copy)]
49pub enum BlockOrigin {
50	/// Genesis block built into the client.
51	Genesis,
52	/// Block is part of the initial sync with the network.
53	NetworkInitialSync,
54	/// Block was broadcasted on the network.
55	NetworkBroadcast,
56	/// Block that was received from the network and validated in the consensus process.
57	ConsensusBroadcast,
58	/// Block that was collated by this node.
59	Own,
60	/// Block was imported from a file.
61	File,
62	/// Block from warp sync proof, already cryptographically verified.
63	///
64	/// These blocks have been verified through the warp sync protocol's finality proofs
65	/// and are part of the finalized chain. As such, certain consensus verification steps
66	/// can be safely skipped during import. These are the blocks that are used to verify the era
67	/// changes and not the target block to which the node is warp syncing to.
68	WarpSync,
69	/// Block imported during gap sync to fill historical gaps.
70	///
71	/// Gap sync occurs after warp sync completes, downloading blocks between genesis
72	/// and the warp sync target to fill in the historical chain.
73	GapSync,
74}
75
76/// Environment for a Consensus instance.
77///
78/// Creates proposer instance.
79pub trait Environment<B: BlockT> {
80	/// The proposer type this creates.
81	type Proposer: Proposer<B> + Send + 'static;
82	/// A future that resolves to the proposer.
83	type CreateProposer: Future<Output = Result<Self::Proposer, Self::Error>>
84		+ Send
85		+ Unpin
86		+ 'static;
87	/// Error which can occur upon creation.
88	type Error: From<Error> + Send + Sync + std::error::Error + 'static;
89
90	/// Initialize the proposal logic on top of a specific header. Provide
91	/// the authorities at that header.
92	fn init(&mut self, parent_header: &B::Header) -> Self::CreateProposer;
93}
94
95/// A proposal that is created by a [`Proposer`].
96pub struct Proposal<Block: BlockT> {
97	/// The block that was build.
98	pub block: Block,
99	/// The storage changes while building this block.
100	pub storage_changes: subsoil::state_machine::StorageChanges<HashingFor<Block>>,
101}
102
103/// Arguments for [`Proposer::propose`].
104pub struct ProposeArgs<B: BlockT> {
105	/// The inherent data to pass to the block production.
106	pub inherent_data: InherentData,
107	/// The inherent digests to include in the produced block.
108	pub inherent_digests: Digest,
109	/// Max duration for building the block.
110	pub max_duration: Duration,
111	/// Optional size limit for the produced block.
112	///
113	/// When set, block production ends before hitting this limit. The limit includes the storage
114	/// proof, when proof recording is activated.
115	pub block_size_limit: Option<usize>,
116	/// Optional proof recorder for recording storage proofs during block production.
117	///
118	/// When `Some`, the recorder will be used on block production to record all storage accesses.
119	pub storage_proof_recorder: Option<ProofRecorder<B>>,
120	/// Extra extensions for the runtime environment.
121	pub extra_extensions: Extensions,
122}
123
124impl<B: BlockT> Default for ProposeArgs<B> {
125	fn default() -> Self {
126		Self {
127			inherent_data: Default::default(),
128			inherent_digests: Default::default(),
129			max_duration: Default::default(),
130			block_size_limit: Default::default(),
131			storage_proof_recorder: Default::default(),
132			extra_extensions: Default::default(),
133		}
134	}
135}
136
137/// Logic for a proposer.
138///
139/// This will encapsulate creation and evaluation of proposals at a specific
140/// block.
141///
142/// Proposers are generic over bits of "consensus data" which are engine-specific.
143pub trait Proposer<B: BlockT> {
144	/// Error type which can occur when proposing or evaluating.
145	type Error: From<Error> + Send + Sync + std::error::Error + 'static;
146	/// Future that resolves to a committed proposal with an optional proof.
147	type Proposal: Future<Output = Result<Proposal<B>, Self::Error>> + Send + Unpin + 'static;
148
149	/// Create a proposal.
150	///
151	/// Takes a [`ProposeArgs`] struct containing all the necessary parameters for block production
152	/// including inherent data, digests, duration limits, storage proof recorder, and extensions.
153	///
154	/// # Return
155	///
156	/// Returns a future that resolves to a [`Proposal`] or to [`Error`].
157	fn propose(self, args: ProposeArgs<B>) -> Self::Proposal;
158}
159
160/// An oracle for when major synchronization work is being undertaken.
161///
162/// Generally, consensus authoring work isn't undertaken while well behind
163/// the head of the chain.
164pub trait SyncOracle {
165	/// Whether the synchronization service is undergoing major sync.
166	/// Returns true if so.
167	fn is_major_syncing(&self) -> bool;
168	/// Whether the synchronization service is offline.
169	/// Returns true if so.
170	fn is_offline(&self) -> bool;
171}
172
173/// A synchronization oracle for when there is no network.
174#[derive(Clone, Copy, Debug)]
175pub struct NoNetwork;
176
177impl SyncOracle for NoNetwork {
178	fn is_major_syncing(&self) -> bool {
179		false
180	}
181	fn is_offline(&self) -> bool {
182		false
183	}
184}
185
186impl<T> SyncOracle for Arc<T>
187where
188	T: ?Sized,
189	T: SyncOracle,
190{
191	fn is_major_syncing(&self) -> bool {
192		T::is_major_syncing(self)
193	}
194
195	fn is_offline(&self) -> bool {
196		T::is_offline(self)
197	}
198}