referrerpolicy=no-referrer-when-downgrade

sp_consensus_sassafras/
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 Sassafras consensus.
19
20#![deny(warnings)]
21#![forbid(unsafe_code, missing_docs, unused_variables, unused_imports)]
22#![cfg_attr(not(feature = "std"), no_std)]
23
24extern crate alloc;
25
26use alloc::vec::Vec;
27use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
28use scale_info::TypeInfo;
29use sp_core::crypto::KeyTypeId;
30use sp_runtime::{ConsensusEngineId, RuntimeDebug};
31
32pub use sp_consensus_slots::{Slot, SlotDuration};
33
34#[cfg(feature = "serde")]
35use serde::{Deserialize, Serialize};
36
37pub mod digests;
38pub mod ticket;
39pub mod vrf;
40
41pub use ticket::{
42	ticket_id_threshold, EphemeralPublic, EphemeralSignature, TicketBody, TicketClaim,
43	TicketEnvelope, TicketId,
44};
45
46mod app {
47	use sp_application_crypto::{app_crypto, bandersnatch, key_types::SASSAFRAS};
48	app_crypto!(bandersnatch, SASSAFRAS);
49}
50
51/// Key type identifier.
52pub const KEY_TYPE: KeyTypeId = sp_application_crypto::key_types::SASSAFRAS;
53
54/// Consensus engine identifier.
55pub const SASSAFRAS_ENGINE_ID: ConsensusEngineId = *b"SASS";
56
57/// VRF output length for per-slot randomness.
58pub const RANDOMNESS_LENGTH: usize = 32;
59
60/// Index of an authority.
61pub type AuthorityIndex = u32;
62
63/// Sassafras authority keypair. Necessarily equivalent to the schnorrkel public key used in
64/// the main Sassafras module. If that ever changes, then this must, too.
65#[cfg(feature = "std")]
66pub type AuthorityPair = app::Pair;
67
68/// Sassafras authority signature.
69pub type AuthoritySignature = app::Signature;
70
71/// Sassafras authority identifier. Necessarily equivalent to the schnorrkel public key used in
72/// the main Sassafras module. If that ever changes, then this must, too.
73pub type AuthorityId = app::Public;
74
75/// Weight of a Sassafras block.
76/// Primary blocks have a weight of 1 whereas secondary blocks have a weight of 0.
77pub type SassafrasBlockWeight = u32;
78
79/// An equivocation proof for multiple block authorships on the same slot (i.e. double vote).
80pub type EquivocationProof<H> = sp_consensus_slots::EquivocationProof<H, AuthorityId>;
81
82/// Randomness required by some protocol's operations.
83pub type Randomness = [u8; RANDOMNESS_LENGTH];
84
85/// Protocol configuration that can be modified on epoch change.
86///
87/// Mostly tweaks to the ticketing system parameters.
88#[derive(
89	Copy,
90	Clone,
91	PartialEq,
92	Eq,
93	Encode,
94	Decode,
95	DecodeWithMemTracking,
96	RuntimeDebug,
97	MaxEncodedLen,
98	TypeInfo,
99	Default,
100)]
101#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
102pub struct EpochConfiguration {
103	/// Tickets redundancy factor.
104	///
105	/// Expected ratio between epoch's slots and the cumulative number of tickets which can
106	/// be submitted by the set of epoch validators.
107	pub redundancy_factor: u32,
108	/// Tickets max attempts for each validator.
109	///
110	/// Influences the anonymity of block producers. As all published tickets have a public
111	/// attempt number less than `attempts_number` if two tickets share an attempt number
112	/// then they must belong to two different validators, which reduces anonymity late as
113	/// we approach the epoch tail.
114	///
115	/// This anonymity loss already becomes small when `attempts_number = 64` or `128`.
116	pub attempts_number: u32,
117}
118
119/// Sassafras epoch information
120#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, TypeInfo)]
121pub struct Epoch {
122	/// Epoch index.
123	pub index: u64,
124	/// Starting slot of the epoch.
125	pub start: Slot,
126	/// Number of slots in the epoch.
127	pub length: u32,
128	/// Randomness value.
129	pub randomness: Randomness,
130	/// Authorities list.
131	pub authorities: Vec<AuthorityId>,
132	/// Epoch configuration.
133	pub config: EpochConfiguration,
134}
135
136/// An opaque type used to represent the key ownership proof at the runtime API boundary.
137///
138/// The inner value is an encoded representation of the actual key ownership proof which will be
139/// parameterized when defining the runtime. At the runtime API boundary this type is unknown and
140/// as such we keep this opaque representation, implementors of the runtime API will have to make
141/// sure that all usages of `OpaqueKeyOwnershipProof` refer to the same type.
142#[derive(Decode, Encode, PartialEq, TypeInfo)]
143#[repr(transparent)]
144pub struct OpaqueKeyOwnershipProof(Vec<u8>);
145
146// Runtime API.
147sp_api::decl_runtime_apis! {
148	/// API necessary for block authorship with Sassafras.
149	pub trait SassafrasApi {
150		/// Get ring context to be used for ticket construction and verification.
151		fn ring_context() -> Option<vrf::RingContext>;
152
153		/// Submit next epoch validator tickets via an unsigned extrinsic.
154		/// This method returns `false` when creation of the extrinsics fails.
155		fn submit_tickets_unsigned_extrinsic(tickets: Vec<TicketEnvelope>) -> bool;
156
157		/// Get ticket id associated to the given slot.
158		fn slot_ticket_id(slot: Slot) -> Option<TicketId>;
159
160		/// Get ticket id and data associated to the given slot.
161		fn slot_ticket(slot: Slot) -> Option<(TicketId, TicketBody)>;
162
163		/// Current epoch information.
164		fn current_epoch() -> Epoch;
165
166		/// Next epoch information.
167		fn next_epoch() -> Epoch;
168
169		/// Generates a proof of key ownership for the given authority in the current epoch.
170		///
171		/// An example usage of this module is coupled with the session historical module to prove
172		/// that a given authority key is tied to a given staking identity during a specific
173		/// session.
174		///
175		/// Proofs of key ownership are necessary for submitting equivocation reports.
176		fn generate_key_ownership_proof(authority_id: AuthorityId) -> Option<OpaqueKeyOwnershipProof>;
177
178		/// Submits an unsigned extrinsic to report an equivocation.
179		///
180		/// The caller must provide the equivocation proof and a key ownership proof (should be
181		/// obtained using `generate_key_ownership_proof`). The extrinsic will be unsigned and
182		/// should only be accepted for local authorship (not to be broadcast to the network). This
183		/// method returns `false` when creation of the extrinsic fails.
184		///
185		/// Only useful in an offchain context.
186		fn submit_report_equivocation_unsigned_extrinsic(
187			equivocation_proof: EquivocationProof<Block::Header>,
188			key_owner_proof: OpaqueKeyOwnershipProof,
189		) -> bool;
190	}
191}