mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-21 03:55:40 +00:00
Sassafras Consensus Pallet (#1577)
This PR introduces the pallet for Sassafras consensus. ## Non Goals The pallet delivers only the bare-bones and doesn't deliver support for auxiliary functionalities such as equivocation report and support for epoch change via session pallet. These functionalities were drafted in the [main PR](https://github.com/paritytech/polkadot-sdk/pull/1336), but IMO is better to introduce this auxiliary stuff in a follow up PR and after client code. ## Potential follow ups https://github.com/paritytech/polkadot-sdk/issues/2364 --------- Co-authored-by: Sebastian Kunert <skunert49@gmail.com> Co-authored-by: Koute <koute@users.noreply.github.com> Co-authored-by: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com> Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> Co-authored-by: Bastian Köcher <git@kchr.de>
This commit is contained in:
@@ -48,11 +48,11 @@ pub struct SlotClaim {
|
||||
/// This is mandatory in the first block of each epoch.
|
||||
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)]
|
||||
pub struct NextEpochDescriptor {
|
||||
/// Randomness value.
|
||||
pub randomness: Randomness,
|
||||
/// Authorities list.
|
||||
pub authorities: Vec<AuthorityId>,
|
||||
/// Epoch randomness.
|
||||
pub randomness: Randomness,
|
||||
/// Epoch configurable parameters.
|
||||
/// Epoch configuration.
|
||||
///
|
||||
/// If not present previous epoch parameters are used.
|
||||
pub config: Option<EpochConfiguration>,
|
||||
|
||||
@@ -80,33 +80,43 @@ pub type EquivocationProof<H> = sp_consensus_slots::EquivocationProof<H, Authori
|
||||
/// Randomness required by some protocol's operations.
|
||||
pub type Randomness = [u8; RANDOMNESS_LENGTH];
|
||||
|
||||
/// Configuration data that can be modified on epoch change.
|
||||
/// Protocol configuration that can be modified on epoch change.
|
||||
///
|
||||
/// Mostly tweaks to the ticketing system parameters.
|
||||
#[derive(
|
||||
Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, MaxEncodedLen, TypeInfo, Default,
|
||||
)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct EpochConfiguration {
|
||||
/// Tickets threshold redundancy factor.
|
||||
/// Tickets redundancy factor.
|
||||
///
|
||||
/// Expected ratio between epoch's slots and the cumulative number of tickets which can
|
||||
/// be submitted by the set of epoch validators.
|
||||
pub redundancy_factor: u32,
|
||||
/// Tickets attempts for each validator.
|
||||
/// Tickets max attempts for each validator.
|
||||
///
|
||||
/// Influences the anonymity of block producers. As all published tickets have a public
|
||||
/// attempt number less than `attempts_number` if two tickets share an attempt number
|
||||
/// then they must belong to two different validators, which reduces anonymity late as
|
||||
/// we approach the epoch tail.
|
||||
///
|
||||
/// This anonymity loss already becomes small when `attempts_number = 64` or `128`.
|
||||
pub attempts_number: u32,
|
||||
}
|
||||
|
||||
/// Sassafras epoch information
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, TypeInfo)]
|
||||
pub struct Epoch {
|
||||
/// The epoch index.
|
||||
pub epoch_idx: u64,
|
||||
/// The starting slot of the epoch.
|
||||
pub start_slot: Slot,
|
||||
/// Slot duration in milliseconds.
|
||||
pub slot_duration: SlotDuration,
|
||||
/// Duration of epoch in slots.
|
||||
pub epoch_duration: u64,
|
||||
/// Authorities for the epoch.
|
||||
pub authorities: Vec<AuthorityId>,
|
||||
/// Randomness for the epoch.
|
||||
/// Epoch index.
|
||||
pub index: u64,
|
||||
/// Starting slot of the epoch.
|
||||
pub start: Slot,
|
||||
/// Number of slots in the epoch.
|
||||
pub length: u32,
|
||||
/// Randomness value.
|
||||
pub randomness: Randomness,
|
||||
/// Authorities list.
|
||||
pub authorities: Vec<AuthorityId>,
|
||||
/// Epoch configuration.
|
||||
pub config: EpochConfiguration,
|
||||
}
|
||||
|
||||
@@ -62,10 +62,10 @@ pub struct TicketClaim {
|
||||
pub erased_signature: EphemeralSignature,
|
||||
}
|
||||
|
||||
/// Computes ticket-id maximum allowed value for a given epoch.
|
||||
/// Computes a boundary for [`TicketId`] maximum allowed value for a given epoch.
|
||||
///
|
||||
/// Only ticket identifiers below this threshold should be considered for slot
|
||||
/// assignment.
|
||||
/// Only ticket identifiers below this threshold should be considered as candidates
|
||||
/// for slot assignment.
|
||||
///
|
||||
/// The value is computed as `TicketId::MAX*(redundancy*slots)/(attempts*validators)`
|
||||
///
|
||||
@@ -76,16 +76,51 @@ pub struct TicketClaim {
|
||||
/// - `validators`: number of validators in epoch.
|
||||
///
|
||||
/// If `attempts * validators = 0` then we return 0.
|
||||
///
|
||||
/// For details about the formula and implications refer to
|
||||
/// [*probabilities an parameters*](https://research.web3.foundation/Polkadot/protocols/block-production/SASSAFRAS#probabilities-and-parameters)
|
||||
/// paragraph of the w3f introduction to the protocol.
|
||||
// TODO: replace with [RFC-26](https://github.com/polkadot-fellows/RFCs/pull/26)
|
||||
// "Tickets Threshold" paragraph once is merged
|
||||
pub fn ticket_id_threshold(
|
||||
redundancy: u32,
|
||||
slots: u32,
|
||||
attempts: u32,
|
||||
validators: u32,
|
||||
) -> TicketId {
|
||||
let den = attempts as u64 * validators as u64;
|
||||
let num = redundancy as u64 * slots as u64;
|
||||
let den = attempts as u64 * validators as u64;
|
||||
TicketId::max_value()
|
||||
.checked_div(den.into())
|
||||
.unwrap_or_default()
|
||||
.saturating_mul(num.into())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// This is a trivial example/check which just better explain explains the rationale
|
||||
// behind the threshold.
|
||||
//
|
||||
// After this reading the formula should become obvious.
|
||||
#[test]
|
||||
fn ticket_id_threshold_trivial_check() {
|
||||
// For an epoch with `s` slots we want to accept a number of tickets equal to ~s·r
|
||||
let redundancy = 2;
|
||||
let slots = 1000;
|
||||
let attempts = 100;
|
||||
let validators = 500;
|
||||
|
||||
let threshold = ticket_id_threshold(redundancy, slots, attempts, validators);
|
||||
let threshold = threshold as f64 / TicketId::MAX as f64;
|
||||
|
||||
// We expect that the total number of tickets allowed to be submited
|
||||
// is slots*redundancy
|
||||
let avt = ((attempts * validators) as f64 * threshold) as u32;
|
||||
assert_eq!(avt, slots * redundancy);
|
||||
|
||||
println!("threshold: {}", threshold);
|
||||
println!("avt = {}", avt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ use sp_consensus_slots::Slot;
|
||||
use sp_std::vec::Vec;
|
||||
|
||||
pub use sp_core::bandersnatch::{
|
||||
ring_vrf::{RingContext, RingProver, RingVerifier, RingVrfSignature},
|
||||
ring_vrf::{RingContext, RingProver, RingVerifier, RingVerifierData, RingVrfSignature},
|
||||
vrf::{VrfInput, VrfOutput, VrfSignData, VrfSignature},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user