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