referrerpolicy=no-referrer-when-downgrade

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, DecodeWithMemTracking, 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, TypeInfo)]
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(
223	Clone,
224	Copy,
225	PartialEq,
226	Eq,
227	Encode,
228	Decode,
229	DecodeWithMemTracking,
230	RuntimeDebug,
231	MaxEncodedLen,
232	TypeInfo,
233)]
234#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
235pub enum AllowedSlots {
236	/// Only allow primary slots.
237	PrimarySlots,
238	/// Allow primary and secondary plain slots.
239	PrimaryAndSecondaryPlainSlots,
240	/// Allow primary and secondary VRF slots.
241	PrimaryAndSecondaryVRFSlots,
242}
243
244impl AllowedSlots {
245	/// Whether plain secondary slots are allowed.
246	pub fn is_secondary_plain_slots_allowed(&self) -> bool {
247		*self == Self::PrimaryAndSecondaryPlainSlots
248	}
249
250	/// Whether VRF secondary slots are allowed.
251	pub fn is_secondary_vrf_slots_allowed(&self) -> bool {
252		*self == Self::PrimaryAndSecondaryVRFSlots
253	}
254}
255
256/// Configuration data used by the BABE consensus engine that may change with epochs.
257#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, MaxEncodedLen, TypeInfo)]
258#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
259pub struct BabeEpochConfiguration {
260	/// A constant value that is used in the threshold calculation formula.
261	/// Expressed as a rational where the first member of the tuple is the
262	/// numerator and the second is the denominator. The rational should
263	/// represent a value between 0 and 1.
264	/// In the threshold formula calculation, `1 - c` represents the probability
265	/// of a slot being empty.
266	pub c: (u64, u64),
267
268	/// Whether this chain should run with secondary slots, which are assigned
269	/// in round-robin manner.
270	pub allowed_slots: AllowedSlots,
271}
272
273impl Default for BabeEpochConfiguration {
274	fn default() -> Self {
275		Self { c: (1, 4), allowed_slots: AllowedSlots::PrimaryAndSecondaryVRFSlots }
276	}
277}
278
279/// Verifies the equivocation proof by making sure that: both headers have
280/// different hashes, are targeting the same slot, and have valid signatures by
281/// the same authority.
282pub fn check_equivocation_proof<H>(proof: EquivocationProof<H>) -> bool
283where
284	H: Header,
285{
286	use digests::*;
287	use sp_application_crypto::RuntimeAppPublic;
288
289	let find_pre_digest =
290		|header: &H| header.digest().logs().iter().find_map(|log| log.as_babe_pre_digest());
291
292	let verify_seal_signature = |mut header: H, offender: &AuthorityId| {
293		let seal = header.digest_mut().pop()?.as_babe_seal()?;
294		let pre_hash = header.hash();
295
296		if !offender.verify(&pre_hash.as_ref(), &seal) {
297			return None
298		}
299
300		Some(())
301	};
302
303	let verify_proof = || {
304		// we must have different headers for the equivocation to be valid
305		if proof.first_header.hash() == proof.second_header.hash() {
306			return None
307		}
308
309		let first_pre_digest = find_pre_digest(&proof.first_header)?;
310		let second_pre_digest = find_pre_digest(&proof.second_header)?;
311
312		// both headers must be targeting the same slot and it must
313		// be the same as the one in the proof.
314		if proof.slot != first_pre_digest.slot() ||
315			first_pre_digest.slot() != second_pre_digest.slot()
316		{
317			return None
318		}
319
320		// both headers must have been authored by the same authority
321		if first_pre_digest.authority_index() != second_pre_digest.authority_index() {
322			return None
323		}
324
325		// we finally verify that the expected authority has signed both headers and
326		// that the signature is valid.
327		verify_seal_signature(proof.first_header, &proof.offender)?;
328		verify_seal_signature(proof.second_header, &proof.offender)?;
329
330		Some(())
331	};
332
333	// NOTE: we isolate the verification code into an helper function that
334	// returns `Option<()>` so that we can use `?` to deal with any intermediate
335	// errors and discard the proof as invalid.
336	verify_proof().is_some()
337}
338
339/// An opaque type used to represent the key ownership proof at the runtime API
340/// boundary. The inner value is an encoded representation of the actual key
341/// ownership proof which will be parameterized when defining the runtime. At
342/// the runtime API boundary this type is unknown and as such we keep this
343/// opaque representation, implementors of the runtime API will have to make
344/// sure that all usages of `OpaqueKeyOwnershipProof` refer to the same type.
345#[derive(Decode, Encode, PartialEq, TypeInfo)]
346pub struct OpaqueKeyOwnershipProof(Vec<u8>);
347impl OpaqueKeyOwnershipProof {
348	/// Create a new `OpaqueKeyOwnershipProof` using the given encoded
349	/// representation.
350	pub fn new(inner: Vec<u8>) -> OpaqueKeyOwnershipProof {
351		OpaqueKeyOwnershipProof(inner)
352	}
353
354	/// Try to decode this `OpaqueKeyOwnershipProof` into the given concrete key
355	/// ownership proof type.
356	pub fn decode<T: Decode>(self) -> Option<T> {
357		Decode::decode(&mut &self.0[..]).ok()
358	}
359}
360
361/// BABE epoch information
362#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)]
363pub struct Epoch {
364	/// The epoch index.
365	pub epoch_index: u64,
366	/// The starting slot of the epoch.
367	pub start_slot: Slot,
368	/// The duration of this epoch.
369	pub duration: u64,
370	/// The authorities and their weights.
371	pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
372	/// Randomness for this epoch.
373	pub randomness: Randomness,
374	/// Configuration of the epoch.
375	pub config: BabeEpochConfiguration,
376}
377
378/// Returns the epoch index the given slot belongs to.
379pub fn epoch_index(slot: Slot, genesis_slot: Slot, epoch_duration: u64) -> u64 {
380	*slot.saturating_sub(genesis_slot) / epoch_duration
381}
382
383/// Returns the first slot at the given epoch index.
384pub fn epoch_start_slot(epoch_index: u64, genesis_slot: Slot, epoch_duration: u64) -> Slot {
385	// (epoch_index * epoch_duration) + genesis_slot
386
387	const PROOF: &str = "slot number is u64; it should relate in some way to wall clock time; \
388						 if u64 is not enough we should crash for safety; qed.";
389
390	epoch_index
391		.checked_mul(epoch_duration)
392		.and_then(|slot| slot.checked_add(*genesis_slot))
393		.expect(PROOF)
394		.into()
395}
396
397sp_api::decl_runtime_apis! {
398	/// API necessary for block authorship with BABE.
399	#[api_version(2)]
400	pub trait BabeApi {
401		/// Return the configuration for BABE.
402		fn configuration() -> BabeConfiguration;
403
404		/// Return the configuration for BABE. Version 1.
405		#[changed_in(2)]
406		fn configuration() -> BabeConfigurationV1;
407
408		/// Returns the slot that started the current epoch.
409		fn current_epoch_start() -> Slot;
410
411		/// Returns information regarding the current epoch.
412		fn current_epoch() -> Epoch;
413
414		/// Returns information regarding the next epoch (which was already
415		/// previously announced).
416		fn next_epoch() -> Epoch;
417
418		/// Generates a proof of key ownership for the given authority in the
419		/// current epoch. An example usage of this module is coupled with the
420		/// session historical module to prove that a given authority key is
421		/// tied to a given staking identity during a specific session. Proofs
422		/// of key ownership are necessary for submitting equivocation reports.
423		/// NOTE: even though the API takes a `slot` as parameter the current
424		/// implementations ignores this parameter and instead relies on this
425		/// method being called at the correct block height, i.e. any point at
426		/// which the epoch for the given slot is live on-chain. Future
427		/// implementations will instead use indexed data through an offchain
428		/// worker, not requiring older states to be available.
429		fn generate_key_ownership_proof(
430			slot: Slot,
431			authority_id: AuthorityId,
432		) -> Option<OpaqueKeyOwnershipProof>;
433
434		/// Submits an unsigned extrinsic to report an equivocation. The caller
435		/// must provide the equivocation proof and a key ownership proof
436		/// (should be obtained using `generate_key_ownership_proof`). The
437		/// extrinsic will be unsigned and should only be accepted for local
438		/// authorship (not to be broadcast to the network). This method returns
439		/// `None` when creation of the extrinsic fails, e.g. if equivocation
440		/// reporting is disabled for the given runtime (i.e. this method is
441		/// hardcoded to return `None`). Only useful in an offchain context.
442		fn submit_report_equivocation_unsigned_extrinsic(
443			equivocation_proof: EquivocationProof<Block::Header>,
444			key_owner_proof: OpaqueKeyOwnershipProof,
445		) -> Option<()>;
446	}
447}