1
// Copyright Moonsong Labs
2
// This file is part of Moonkit.
3

            
4
// Moonkit is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Moonkit is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Moonkit.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
//! Nimbus Consensus Primitives
18
//!
19
//! Primitive types and traits for working with the Nimbus consensus framework.
20
//! This code can be built to no_std for use in the runtime
21

            
22
#![cfg_attr(not(feature = "std"), no_std)]
23

            
24
use sp_application_crypto::KeyTypeId;
25
use sp_runtime::generic::DigestItem;
26
use sp_runtime::traits::BlockNumberProvider;
27
use sp_runtime::ConsensusEngineId;
28
#[cfg(feature = "runtime-benchmarks")]
29
use sp_std::vec::Vec;
30

            
31
pub mod digests;
32
mod inherents;
33

            
34
pub use digests::CompatibleDigestItem;
35

            
36
pub use inherents::{InherentDataProvider, INHERENT_IDENTIFIER};
37

            
38
pub trait DigestsProvider<Id, BlockHash> {
39
	type Digests: IntoIterator<Item = DigestItem>;
40
	fn provide_digests(&self, id: Id, parent: BlockHash) -> Self::Digests;
41
}
42

            
43
impl<Id, BlockHash> DigestsProvider<Id, BlockHash> for () {
44
	type Digests = [DigestItem; 0];
45
	fn provide_digests(&self, _id: Id, _parent: BlockHash) -> Self::Digests {
46
		[]
47
	}
48
}
49

            
50
impl<F, Id, BlockHash, D> DigestsProvider<Id, BlockHash> for F
51
where
52
	F: Fn(Id, BlockHash) -> D,
53
	D: IntoIterator<Item = DigestItem>,
54
{
55
	type Digests = D;
56

            
57
	fn provide_digests(&self, id: Id, parent: BlockHash) -> Self::Digests {
58
		(*self)(id, parent)
59
	}
60
}
61

            
62
/// The given account ID is the author of the current block.
63
pub trait EventHandler<Author> {
64
	//TODO should we be tking ownership here?
65
	fn note_author(author: Author);
66
}
67

            
68
impl<T> EventHandler<T> for () {
69
	fn note_author(_author: T) {}
70
}
71

            
72
/// A mechanism for determining the current slot.
73
/// For now we use u32 as the slot type everywhere. Let's see how long we can get away with that.
74
pub trait SlotBeacon {
75
	fn slot() -> u32;
76
	#[cfg(feature = "runtime-benchmarks")]
77
	fn set_slot(_slot: u32) {}
78
}
79

            
80
/// Anything that can provide a block height can be used as a slot beacon. This could be
81
/// used in at least two realistic ways.
82
/// 1. Use your own chain's height as the slot number
83
/// 2. If you're a parachain, use the relay chain's height as the slot number.
84
impl<T: BlockNumberProvider<BlockNumber = u32>> SlotBeacon for T {
85
	fn slot() -> u32 {
86
		Self::current_block_number()
87
	}
88
	#[cfg(feature = "runtime-benchmarks")]
89
	fn set_slot(slot: u32) {
90
		Self::set_block_number(slot);
91
	}
92
}
93

            
94
/// Trait to determine whether this author is eligible to author in this slot.
95
/// This is the primary trait your nimbus filter needs to implement.
96
///
97
/// This is the proposition-logic variant.
98
/// That is to say the caller specifies an author an author and the implementation
99
/// replies whether that author is eligible. This is useful in many cases and is
100
/// particularly useful when the active set is unbounded.
101
/// There may be another variant where the caller only supplies a slot and the
102
/// implementation replies with a complete set of eligible authors.
103
pub trait CanAuthor<AuthorId> {
104
	#[cfg(feature = "try-runtime")]
105
	// With `try-runtime` the local author should always be able to author a block.
106
	fn can_author(_author: &AuthorId, _slot: &u32) -> bool {
107
		true
108
	}
109
	#[cfg(not(feature = "try-runtime"))]
110
	fn can_author(author: &AuthorId, slot: &u32) -> bool;
111
	#[cfg(feature = "runtime-benchmarks")]
112
	fn get_authors(_slot: &u32) -> Vec<AuthorId> {
113
		Vec::new()
114
	}
115
	#[cfg(feature = "runtime-benchmarks")]
116
	fn set_eligible_author(_slot: &u32) {}
117
}
118
/// Default implementation where anyone can author.
119
///
120
/// This is identical to Cumulus's RelayChainConsensus
121
impl<T> CanAuthor<T> for () {
122
	fn can_author(_: &T, _: &u32) -> bool {
123
		true
124
	}
125
}
126

            
127
/// A Trait to lookup runtime AccountIds from AuthorIds (probably NimbusIds)
128
/// The trait is generic over the AccountId, becuase different runtimes use
129
/// different notions of AccoutId. It is also generic over the AuthorId to
130
/// support the usecase where the author inherent is used for beneficiary info
131
/// and contains an AccountId directly.
132
pub trait AccountLookup<AccountId> {
133
	fn lookup_account(author: &NimbusId) -> Option<AccountId>;
134
}
135

            
136
// A dummy impl used in simple tests
137
impl<AccountId> AccountLookup<AccountId> for () {
138
	fn lookup_account(_: &NimbusId) -> Option<AccountId> {
139
		None
140
	}
141
}
142

            
143
/// The ConsensusEngineId for nimbus consensus
144
/// this same identifier will be used regardless of the filters installed
145
pub const NIMBUS_ENGINE_ID: ConsensusEngineId = *b"nmbs";
146

            
147
/// The KeyTypeId used in the Nimbus consensus framework regardles of wat filters are in place.
148
/// If this gets well adopted, we could move this definition to sp_core to avoid conflicts.
149
pub const NIMBUS_KEY_ID: KeyTypeId = KeyTypeId(*b"nmbs");
150

            
151
// The strongly-typed crypto wrappers to be used by Nimbus in the keystore
152
mod nimbus_crypto {
153
	use sp_application_crypto::{app_crypto, sr25519};
154
	app_crypto!(sr25519, crate::NIMBUS_KEY_ID);
155
}
156

            
157
/// A nimbus author identifier (A public key).
158
pub type NimbusId = nimbus_crypto::Public;
159

            
160
/// A nimbus signature.
161
pub type NimbusSignature = nimbus_crypto::Signature;
162

            
163
sp_application_crypto::with_pair! {
164
	/// A nimbus keypair
165
	pub type NimbusPair = nimbus_crypto::Pair;
166
}
167

            
168
sp_api::decl_runtime_apis! {
169
	/// The runtime api used to predict whether a Nimbus author will be eligible in the given slot
170
	pub trait NimbusApi {
171
		fn can_author(author: NimbusId, relay_parent: u32, parent_header: &Block::Header) -> bool;
172
	}
173
}