sp_consensus_babe/
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//! Primitives for BABE.
19#![deny(warnings)]
20#![forbid(unsafe_code, missing_docs, unused_variables, unused_imports)]
21#![cfg_attr(not(feature = "std"), no_std)]
22
23extern crate alloc;
24
25pub mod digests;
26pub mod inherents;
27
28#[cfg(not(feature = "std"))]
29use alloc::vec::Vec;
30use codec::{Decode, Encode, MaxEncodedLen};
31use scale_info::TypeInfo;
32#[cfg(feature = "serde")]
33use serde::{Deserialize, Serialize};
34use sp_runtime::{traits::Header, ConsensusEngineId, RuntimeDebug};
35
36use crate::digests::{NextConfigDescriptor, NextEpochDescriptor};
37
38pub use sp_core::sr25519::vrf::{
39	VrfInput, VrfPreOutput, VrfProof, VrfSignData, VrfSignature, VrfTranscript,
40};
41
42/// Key type for BABE module.
43pub const KEY_TYPE: sp_core::crypto::KeyTypeId = sp_application_crypto::key_types::BABE;
44
45mod app {
46	use sp_application_crypto::{app_crypto, key_types::BABE, sr25519};
47	app_crypto!(sr25519, BABE);
48}
49
50/// VRF context used for per-slot randomness generation.
51pub const RANDOMNESS_VRF_CONTEXT: &[u8] = b"BabeVRFInOutContext";
52
53/// VRF output length for per-slot randomness.
54pub const RANDOMNESS_LENGTH: usize = 32;
55
56/// Randomness type required by BABE operations.
57pub type Randomness = [u8; RANDOMNESS_LENGTH];
58
59/// A Babe authority keypair. Necessarily equivalent to the schnorrkel public key used in
60/// the main Babe module. If that ever changes, then this must, too.
61#[cfg(feature = "std")]
62pub type AuthorityPair = app::Pair;
63
64/// A Babe authority signature.
65pub type AuthoritySignature = app::Signature;
66
67/// A Babe authority identifier. Necessarily equivalent to the schnorrkel public key used in
68/// the main Babe module. If that ever changes, then this must, too.
69pub type AuthorityId = app::Public;
70
71/// The `ConsensusEngineId` of BABE.
72pub const BABE_ENGINE_ID: ConsensusEngineId = *b"BABE";
73
74/// The length of the public key
75pub const PUBLIC_KEY_LENGTH: usize = 32;
76
77/// How many blocks to wait before running the median algorithm for relative time
78/// This will not vary from chain to chain as it is not dependent on slot duration
79/// or epoch length.
80pub const MEDIAN_ALGORITHM_CARDINALITY: usize = 1200; // arbitrary suggestion by w3f-research.
81
82/// The index of an authority.
83pub type AuthorityIndex = u32;
84
85pub use sp_consensus_slots::{Slot, SlotDuration};
86
87/// An equivocation proof for multiple block authorships on the same slot (i.e. double vote).
88pub type EquivocationProof<H> = sp_consensus_slots::EquivocationProof<H, AuthorityId>;
89
90/// The weight of an authority.
91// NOTE: we use a unique name for the weight to avoid conflicts with other
92//       `Weight` types, since the metadata isn't able to disambiguate.
93pub type BabeAuthorityWeight = u64;
94
95/// The cumulative weight of a BABE block, i.e. sum of block weights starting
96/// at this block until the genesis block.
97///
98/// Primary blocks have a weight of 1 whereas secondary blocks have a weight
99/// of 0 (regardless of whether they are plain or vrf secondary blocks).
100pub type BabeBlockWeight = u32;
101
102/// Make VRF input suitable for BABE's randomness generation.
103pub fn make_vrf_transcript(randomness: &Randomness, slot: Slot, epoch: u64) -> VrfInput {
104	VrfInput::new(
105		&BABE_ENGINE_ID,
106		&[
107			(b"slot number", &slot.to_le_bytes()),
108			(b"current epoch", &epoch.to_le_bytes()),
109			(b"chain randomness", randomness),
110		],
111	)
112}
113
114/// Make VRF signing data suitable for BABE's protocol.
115pub fn make_vrf_sign_data(randomness: &Randomness, slot: Slot, epoch: u64) -> VrfSignData {
116	make_vrf_transcript(randomness, slot, epoch).into()
117}
118
119/// An consensus log item for BABE.
120#[derive(Decode, Encode, Clone, PartialEq, Eq)]
121pub enum ConsensusLog {
122	/// The epoch has changed. This provides information about the _next_
123	/// epoch - information about the _current_ epoch (i.e. the one we've just
124	/// entered) should already be available earlier in the chain.
125	#[codec(index = 1)]
126	NextEpochData(NextEpochDescriptor),
127	/// Disable the authority with given index.
128	#[codec(index = 2)]
129	OnDisabled(AuthorityIndex),
130	/// The epoch has changed, and the epoch after the current one will
131	/// enact different epoch configurations.
132	#[codec(index = 3)]
133	NextConfigData(NextConfigDescriptor),
134}
135
136/// Configuration data used by the BABE consensus engine.
137#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)]
138pub struct BabeConfigurationV1 {
139	/// The slot duration in milliseconds for BABE. Currently, only
140	/// the value provided by this type at genesis will be used.
141	///
142	/// Dynamic slot duration may be supported in the future.
143	pub slot_duration: u64,
144
145	/// The duration of epochs in slots.
146	pub epoch_length: u64,
147
148	/// A constant value that is used in the threshold calculation formula.
149	/// Expressed as a rational where the first member of the tuple is the
150	/// numerator and the second is the denominator. The rational should
151	/// represent a value between 0 and 1.
152	/// In the threshold formula calculation, `1 - c` represents the probability
153	/// of a slot being empty.
154	pub c: (u64, u64),
155
156	/// The authorities for the genesis epoch.
157	pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
158
159	/// The randomness for the genesis epoch.
160	pub randomness: Randomness,
161
162	/// Whether this chain should run with secondary slots, which are assigned
163	/// in round-robin manner.
164	pub secondary_slots: bool,
165}
166
167impl From<BabeConfigurationV1> for BabeConfiguration {
168	fn from(v1: BabeConfigurationV1) -> Self {
169		Self {
170			slot_duration: v1.slot_duration,
171			epoch_length: v1.epoch_length,
172			c: v1.c,
173			authorities: v1.authorities,
174			randomness: v1.randomness,
175			allowed_slots: if v1.secondary_slots {
176				AllowedSlots::PrimaryAndSecondaryPlainSlots
177			} else {
178				AllowedSlots::PrimarySlots
179			},
180		}
181	}
182}
183
184/// Configuration data used by the BABE consensus engine.
185#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
186pub struct BabeConfiguration {
187	/// The slot duration in milliseconds for BABE. Currently, only
188	/// the value provided by this type at genesis will be used.
189	///
190	/// Dynamic slot duration may be supported in the future.
191	pub slot_duration: u64,
192
193	/// The duration of epochs in slots.
194	pub epoch_length: u64,
195
196	/// A constant value that is used in the threshold calculation formula.
197	/// Expressed as a rational where the first member of the tuple is the
198	/// numerator and the second is the denominator. The rational should
199	/// represent a value between 0 and 1.
200	/// In the threshold formula calculation, `1 - c` represents the probability
201	/// of a slot being empty.
202	pub c: (u64, u64),
203
204	/// The authorities
205	pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
206
207	/// The randomness
208	pub randomness: Randomness,
209
210	/// Type of allowed slots.
211	pub allowed_slots: AllowedSlots,
212}
213
214impl BabeConfiguration {
215	/// Convenience method to get the slot duration as a `SlotDuration` value.
216	pub fn slot_duration(&self) -> SlotDuration {
217		SlotDuration::from_millis(self.slot_duration)
218	}
219}
220
221/// Types of allowed slots.
222#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, RuntimeDebug, MaxEncodedLen, TypeInfo)]
223#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
224pub enum AllowedSlots {
225	/// Only allow primary slots.
226	PrimarySlots,
227	/// Allow primary and secondary plain slots.
228	PrimaryAndSecondaryPlainSlots,
229	/// Allow primary and secondary VRF slots.
230	PrimaryAndSecondaryVRFSlots,
231}
232
233impl AllowedSlots {
234	/// Whether plain secondary slots are allowed.
235	pub fn is_secondary_plain_slots_allowed(&self) -> bool {
236		*self == Self::PrimaryAndSecondaryPlainSlots
237	}
238
239	/// Whether VRF secondary slots are allowed.
240	pub fn is_secondary_vrf_slots_allowed(&self) -> bool {
241		*self == Self::PrimaryAndSecondaryVRFSlots
242	}
243}
244
245/// Configuration data used by the BABE consensus engine that may change with epochs.
246#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, MaxEncodedLen, TypeInfo)]
247#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
248pub struct BabeEpochConfiguration {
249	/// A constant value that is used in the threshold calculation formula.
250	/// Expressed as a rational where the first member of the tuple is the
251	/// numerator and the second is the denominator. The rational should
252	/// represent a value between 0 and 1.
253	/// In the threshold formula calculation, `1 - c` represents the probability
254	/// of a slot being empty.
255	pub c: (u64, u64),
256
257	/// Whether this chain should run with secondary slots, which are assigned
258	/// in round-robin manner.
259	pub allowed_slots: AllowedSlots,
260}
261
262impl Default for BabeEpochConfiguration {
263	fn default() -> Self {
264		Self { c: (1, 4), allowed_slots: AllowedSlots::PrimaryAndSecondaryVRFSlots }
265	}
266}
267
268/// Verifies the equivocation proof by making sure that: both headers have
269/// different hashes, are targeting the same slot, and have valid signatures by
270/// the same authority.
271pub fn check_equivocation_proof<H>(proof: EquivocationProof<H>) -> bool
272where
273	H: Header,
274{
275	use digests::*;
276	use sp_application_crypto::RuntimeAppPublic;
277
278	let find_pre_digest =
279		|header: &H| header.digest().logs().iter().find_map(|log| log.as_babe_pre_digest());
280
281	let verify_seal_signature = |mut header: H, offender: &AuthorityId| {
282		let seal = header.digest_mut().pop()?.as_babe_seal()?;
283		let pre_hash = header.hash();
284
285		if !offender.verify(&pre_hash.as_ref(), &seal) {
286			return None
287		}
288
289		Some(())
290	};
291
292	let verify_proof = || {
293		// we must have different headers for the equivocation to be valid
294		if proof.first_header.hash() == proof.second_header.hash() {
295			return None
296		}
297
298		let first_pre_digest = find_pre_digest(&proof.first_header)?;
299		let second_pre_digest = find_pre_digest(&proof.second_header)?;
300
301		// both headers must be targeting the same slot and it must
302		// be the same as the one in the proof.
303		if proof.slot != first_pre_digest.slot() ||
304			first_pre_digest.slot() != second_pre_digest.slot()
305		{
306			return None
307		}
308
309		// both headers must have been authored by the same authority
310		if first_pre_digest.authority_index() != second_pre_digest.authority_index() {
311			return None
312		}
313
314		// we finally verify that the expected authority has signed both headers and
315		// that the signature is valid.
316		verify_seal_signature(proof.first_header, &proof.offender)?;
317		verify_seal_signature(proof.second_header, &proof.offender)?;
318
319		Some(())
320	};
321
322	// NOTE: we isolate the verification code into an helper function that
323	// returns `Option<()>` so that we can use `?` to deal with any intermediate
324	// errors and discard the proof as invalid.
325	verify_proof().is_some()
326}
327
328/// An opaque type used to represent the key ownership proof at the runtime API
329/// boundary. The inner value is an encoded representation of the actual key
330/// ownership proof which will be parameterized when defining the runtime. At
331/// the runtime API boundary this type is unknown and as such we keep this
332/// opaque representation, implementors of the runtime API will have to make
333/// sure that all usages of `OpaqueKeyOwnershipProof` refer to the same type.
334#[derive(Decode, Encode, PartialEq, TypeInfo)]
335pub struct OpaqueKeyOwnershipProof(Vec<u8>);
336impl OpaqueKeyOwnershipProof {
337	/// Create a new `OpaqueKeyOwnershipProof` using the given encoded
338	/// representation.
339	pub fn new(inner: Vec<u8>) -> OpaqueKeyOwnershipProof {
340		OpaqueKeyOwnershipProof(inner)
341	}
342
343	/// Try to decode this `OpaqueKeyOwnershipProof` into the given concrete key
344	/// ownership proof type.
345	pub fn decode<T: Decode>(self) -> Option<T> {
346		Decode::decode(&mut &self.0[..]).ok()
347	}
348}
349
350/// BABE epoch information
351#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)]
352pub struct Epoch {
353	/// The epoch index.
354	pub epoch_index: u64,
355	/// The starting slot of the epoch.
356	pub start_slot: Slot,
357	/// The duration of this epoch.
358	pub duration: u64,
359	/// The authorities and their weights.
360	pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
361	/// Randomness for this epoch.
362	pub randomness: Randomness,
363	/// Configuration of the epoch.
364	pub config: BabeEpochConfiguration,
365}
366
367/// Returns the epoch index the given slot belongs to.
368pub fn epoch_index(slot: Slot, genesis_slot: Slot, epoch_duration: u64) -> u64 {
369	*slot.saturating_sub(genesis_slot) / epoch_duration
370}
371
372/// Returns the first slot at the given epoch index.
373pub fn epoch_start_slot(epoch_index: u64, genesis_slot: Slot, epoch_duration: u64) -> Slot {
374	// (epoch_index * epoch_duration) + genesis_slot
375
376	const PROOF: &str = "slot number is u64; it should relate in some way to wall clock time; \
377						 if u64 is not enough we should crash for safety; qed.";
378
379	epoch_index
380		.checked_mul(epoch_duration)
381		.and_then(|slot| slot.checked_add(*genesis_slot))
382		.expect(PROOF)
383		.into()
384}
385
386sp_api::decl_runtime_apis! {
387	/// API necessary for block authorship with BABE.
388	#[api_version(2)]
389	pub trait BabeApi {
390		/// Return the configuration for BABE.
391		fn configuration() -> BabeConfiguration;
392
393		/// Return the configuration for BABE. Version 1.
394		#[changed_in(2)]
395		fn configuration() -> BabeConfigurationV1;
396
397		/// Returns the slot that started the current epoch.
398		fn current_epoch_start() -> Slot;
399
400		/// Returns information regarding the current epoch.
401		fn current_epoch() -> Epoch;
402
403		/// Returns information regarding the next epoch (which was already
404		/// previously announced).
405		fn next_epoch() -> Epoch;
406
407		/// Generates a proof of key ownership for the given authority in the
408		/// current epoch. An example usage of this module is coupled with the
409		/// session historical module to prove that a given authority key is
410		/// tied to a given staking identity during a specific session. Proofs
411		/// of key ownership are necessary for submitting equivocation reports.
412		/// NOTE: even though the API takes a `slot` as parameter the current
413		/// implementations ignores this parameter and instead relies on this
414		/// method being called at the correct block height, i.e. any point at
415		/// which the epoch for the given slot is live on-chain. Future
416		/// implementations will instead use indexed data through an offchain
417		/// worker, not requiring older states to be available.
418		fn generate_key_ownership_proof(
419			slot: Slot,
420			authority_id: AuthorityId,
421		) -> Option<OpaqueKeyOwnershipProof>;
422
423		/// Submits an unsigned extrinsic to report an equivocation. The caller
424		/// must provide the equivocation proof and a key ownership proof
425		/// (should be obtained using `generate_key_ownership_proof`). The
426		/// extrinsic will be unsigned and should only be accepted for local
427		/// authorship (not to be broadcast to the network). This method returns
428		/// `None` when creation of the extrinsic fails, e.g. if equivocation
429		/// reporting is disabled for the given runtime (i.e. this method is
430		/// hardcoded to return `None`). Only useful in an offchain context.
431		fn submit_report_equivocation_unsigned_extrinsic(
432			equivocation_proof: EquivocationProof<Block::Header>,
433			key_owner_proof: OpaqueKeyOwnershipProof,
434		) -> Option<()>;
435	}
436}