diff --git a/Cargo.lock b/Cargo.lock index 992a49306f18f..517b92c522d4b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9627,6 +9627,8 @@ dependencies = [ "serde", "sp-arithmetic", "sp-runtime", + "sp-std", + "sp-timestamp", ] [[package]] diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 4395718a6d680..fc7dc9b978df3 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -8,7 +8,6 @@ use sc_finality_grandpa::SharedVoterState; use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; -use sp_consensus::SlotData; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use std::{sync::Arc, time::Duration}; @@ -111,7 +110,7 @@ pub fn new_partial( telemetry.as_ref().map(|x| x.handle()), )?; - let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); + let slot_duration = sc_consensus_aura::slot_duration(&*client)?; let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { @@ -122,7 +121,7 @@ pub fn new_partial( let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); @@ -260,7 +259,6 @@ pub fn new_full(mut config: Configuration) -> Result sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let raw_slot_duration = slot_duration.slot_duration(); let aura = sc_consensus_aura::start_aura::( StartAuraParams { @@ -273,9 +271,9 @@ pub fn new_full(mut config: Configuration) -> Result let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, - raw_slot_duration, + slot_duration, ); Ok((timestamp, slot)) diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 81c68bf5d3aa7..10d39f278f5f3 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -212,7 +212,7 @@ pub fn new_partial( let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot = - sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration( + sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); @@ -419,7 +419,7 @@ pub fn new_full_base( let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot = - sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration( + sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); @@ -650,7 +650,10 @@ mod tests { .epoch_changes() .shared_data() .epoch_data(&epoch_descriptor, |slot| { - sc_consensus_babe::Epoch::genesis(&babe_link.config(), slot) + sc_consensus_babe::Epoch::genesis( + babe_link.config().genesis_config(), + slot, + ) }) .unwrap(); diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index 61c5610883149..d3a6b10589408 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -77,14 +77,11 @@ pub use sp_consensus::SyncOracle; pub use sp_consensus_aura::{ digests::CompatibleDigestItem, inherents::{InherentDataProvider, InherentType as AuraInherent, INHERENT_IDENTIFIER}, - AuraApi, ConsensusLog, AURA_ENGINE_ID, + AuraApi, ConsensusLog, SlotDuration, AURA_ENGINE_ID, }; type AuthorityId

=

::Public; -/// Slot duration type for Aura. -pub type SlotDuration = sc_consensus_slots::SlotDuration; - /// Get the slot duration for Aura. pub fn slot_duration(client: &C) -> CResult where @@ -94,9 +91,7 @@ where C::Api: AuraApi, { let best_block_id = BlockId::Hash(client.usage_info().chain.best_hash); - let slot_duration = client.runtime_api().slot_duration(&best_block_id)?; - - Ok(SlotDuration::new(slot_duration)) + client.runtime_api().slot_duration(&best_block_id).map_err(|err| err.into()) } /// Get slot author for given block along with authorities. @@ -574,7 +569,7 @@ mod tests { use sc_network_test::{Block as TestBlock, *}; use sp_application_crypto::key_types::AURA; use sp_consensus::{ - AlwaysCanAuthor, DisableProofRecording, NoNetwork as DummyOracle, Proposal, SlotData, + AlwaysCanAuthor, DisableProofRecording, NoNetwork as DummyOracle, Proposal, }; use sp_consensus_aura::sr25519::AuthorityPair; use sp_inherents::InherentData; @@ -672,14 +667,14 @@ mod tests { let client = client.as_client(); let slot_duration = slot_duration(&*client).expect("slot duration available"); - assert_eq!(slot_duration.slot_duration().as_millis() as u64, SLOT_DURATION); + assert_eq!(slot_duration.as_millis() as u64, SLOT_DURATION); import_queue::AuraVerifier::new( client, Box::new(|_, _| async { let timestamp = TimestampInherentDataProvider::from_system_time(); - let slot = InherentDataProvider::from_timestamp_and_duration( + let slot = InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, - Duration::from_secs(6), + SlotDuration::from_millis(6000), ); Ok((timestamp, slot)) @@ -762,9 +757,9 @@ mod tests { justification_sync_link: (), create_inherent_data_providers: |_, _| async { let timestamp = TimestampInherentDataProvider::from_system_time(); - let slot = InherentDataProvider::from_timestamp_and_duration( + let slot = InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, - Duration::from_secs(6), + SlotDuration::from_millis(6000), ); Ok((timestamp, slot)) diff --git a/client/consensus/babe/rpc/src/lib.rs b/client/consensus/babe/rpc/src/lib.rs index 88a176e2de10d..9dd6424a43a98 100644 --- a/client/consensus/babe/rpc/src/lib.rs +++ b/client/consensus/babe/rpc/src/lib.rs @@ -207,7 +207,7 @@ where &parent.hash(), parent.number().clone(), slot.into(), - |slot| Epoch::genesis(&babe_config, slot), + |slot| Epoch::genesis(babe_config.genesis_config(), slot), ) .map_err(|e| Error::Consensus(ConsensusError::ChainLookup(e.to_string())))? .ok_or(Error::Consensus(ConsensusError::InvalidAuthoritiesSet)) diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 19d9e37cf20ae..78fe506dbf341 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -66,9 +66,7 @@ #![forbid(unsafe_code)] #![warn(missing_docs)] -use std::{ - borrow::Cow, collections::HashMap, convert::TryInto, pin::Pin, sync::Arc, time::Duration, u64, -}; +use std::{borrow::Cow, collections::HashMap, convert::TryInto, pin::Pin, sync::Arc, u64}; use codec::{Decode, Encode}; use futures::{ @@ -106,10 +104,10 @@ use sp_block_builder::BlockBuilder as BlockBuilderApi; use sp_blockchain::{Error as ClientError, HeaderBackend, HeaderMetadata, Result as ClientResult}; use sp_consensus::{ BlockOrigin, CacheKeyId, CanAuthorWith, Environment, Error as ConsensusError, Proposer, - SelectChain, SlotData, + SelectChain, }; use sp_consensus_babe::inherents::BabeInherentData; -use sp_consensus_slots::Slot; +use sp_consensus_slots::{Slot, SlotDuration}; use sp_core::{crypto::ByteArray, ExecutionContext}; use sp_inherents::{CreateInherentDataProviders, InherentData, InherentDataProvider}; use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr}; @@ -328,17 +326,15 @@ pub struct BabeIntermediate { /// Intermediate key for Babe engine. pub static INTERMEDIATE_KEY: &[u8] = b"babe1"; -/// A slot duration. -/// -/// Create with [`Self::get`]. -// FIXME: Once Rust has higher-kinded types, the duplication between this -// and `super::babe::Config` can be eliminated. -// https://github.com/paritytech/substrate/issues/2434 +/// Configuration for BABE used for defining block verification parameters as +/// well as authoring (e.g. the slot duration). #[derive(Clone)] -pub struct Config(sc_consensus_slots::SlotDuration); +pub struct Config { + genesis_config: BabeGenesisConfiguration, +} impl Config { - /// Fetch the config from the runtime. + /// Create a new config by reading the genesis configuration from the runtime. pub fn get(client: &C) -> ClientResult where C: AuxStore + ProvideRuntimeApi + UsageProvider, @@ -355,7 +351,7 @@ impl Config { let version = runtime_api.api_version::>(&best_block_id)?; - let slot_duration = if version == Some(1) { + let genesis_config = if version == Some(1) { #[allow(deprecated)] { runtime_api.configuration_before_version_2(&best_block_id)?.into() @@ -368,20 +364,17 @@ impl Config { )) }; - Ok(Self(sc_consensus_slots::SlotDuration::new(slot_duration))) + Ok(Config { genesis_config }) } - /// Get the inner slot duration - pub fn slot_duration(&self) -> Duration { - self.0.slot_duration() + /// Get the genesis configuration. + pub fn genesis_config(&self) -> &BabeGenesisConfiguration { + &self.genesis_config } -} -impl std::ops::Deref for Config { - type Target = BabeGenesisConfiguration; - - fn deref(&self) -> &BabeGenesisConfiguration { - &*self.0 + /// Get the slot duration defined in the genesis configuration. + pub fn slot_duration(&self) -> SlotDuration { + SlotDuration::from_millis(self.genesis_config.slot_duration) } } @@ -488,7 +481,6 @@ where { const HANDLE_BUFFER_SIZE: usize = 1024; - let config = babe_link.config; let slot_notification_sinks = Arc::new(Mutex::new(Vec::new())); let worker = BabeSlotWorker { @@ -502,7 +494,7 @@ where keystore, epoch_changes: babe_link.epoch_changes.clone(), slot_notification_sinks: slot_notification_sinks.clone(), - config: config.clone(), + config: babe_link.config.clone(), block_proposal_slot_portion, max_block_proposal_slot_portion, telemetry, @@ -510,7 +502,7 @@ where info!(target: "babe", "👶 Starting BABE Authorship worker"); let inner = sc_consensus_slots::start_slot_worker( - config.0.clone(), + babe_link.config.slot_duration(), select_chain, worker, sync_oracle, @@ -521,7 +513,8 @@ where let (worker_tx, worker_rx) = channel(HANDLE_BUFFER_SIZE); let answer_requests = - answer_requests(worker_rx, config.0, client, babe_link.epoch_changes.clone()); + answer_requests(worker_rx, babe_link.config, client, babe_link.epoch_changes.clone()); + Ok(BabeWorker { inner: Box::pin(future::join(inner, answer_requests).map(|_| ())), slot_notification_sinks, @@ -531,7 +524,7 @@ where async fn answer_requests( mut request_rx: Receiver>, - genesis_config: sc_consensus_slots::SlotDuration, + config: Config, client: Arc, epoch_changes: SharedEpochChanges, ) where @@ -561,7 +554,7 @@ async fn answer_requests( let viable_epoch = epoch_changes .viable_epoch(&epoch_descriptor, |slot| { - Epoch::genesis(&genesis_config, slot) + Epoch::genesis(&config.genesis_config, slot) }) .ok_or_else(|| Error::::FetchEpoch(parent_hash))?; @@ -720,7 +713,9 @@ where fn authorities_len(&self, epoch_descriptor: &Self::EpochData) -> Option { self.epoch_changes .shared_data() - .viable_epoch(&epoch_descriptor, |slot| Epoch::genesis(&self.config, slot)) + .viable_epoch(&epoch_descriptor, |slot| { + Epoch::genesis(&self.config.genesis_config, slot) + }) .map(|epoch| epoch.as_ref().authorities.len()) } @@ -735,7 +730,9 @@ where slot, self.epoch_changes .shared_data() - .viable_epoch(&epoch_descriptor, |slot| Epoch::genesis(&self.config, slot))? + .viable_epoch(&epoch_descriptor, |slot| { + Epoch::genesis(&self.config.genesis_config, slot) + })? .as_ref(), &self.keystore, ); @@ -1165,7 +1162,9 @@ where .map_err(|e| Error::::ForkTree(Box::new(e)))? .ok_or_else(|| Error::::FetchEpoch(parent_hash))?; let viable_epoch = epoch_changes - .viable_epoch(&epoch_descriptor, |slot| Epoch::genesis(&self.config, slot)) + .viable_epoch(&epoch_descriptor, |slot| { + Epoch::genesis(&self.config.genesis_config, slot) + }) .ok_or_else(|| Error::::FetchEpoch(parent_hash))?; // We add one to the current slot to allow for some small drift. @@ -1498,7 +1497,9 @@ where old_epoch_changes = Some((*epoch_changes).clone()); let viable_epoch = epoch_changes - .viable_epoch(&epoch_descriptor, |slot| Epoch::genesis(&self.config, slot)) + .viable_epoch(&epoch_descriptor, |slot| { + Epoch::genesis(&self.config.genesis_config, slot) + }) .ok_or_else(|| { ConsensusError::ClientImport(Error::::FetchEpoch(parent_hash).into()) })?; @@ -1684,7 +1685,8 @@ pub fn block_import( where Client: AuxStore + HeaderBackend + HeaderMetadata, { - let epoch_changes = aux_schema::load_epoch_changes::(&*client, &config)?; + let epoch_changes = + aux_schema::load_epoch_changes::(&*client, &config.genesis_config)?; let link = BabeLink { epoch_changes: epoch_changes.clone(), config: config.clone() }; // NOTE: this isn't entirely necessary, but since we didn't use to prune the diff --git a/client/consensus/babe/src/tests.rs b/client/consensus/babe/src/tests.rs index 7c04dc03c2f24..d38d57b84f5e1 100644 --- a/client/consensus/babe/src/tests.rs +++ b/client/consensus/babe/src/tests.rs @@ -143,7 +143,7 @@ impl DummyProposer { &self.parent_hash, self.parent_number, this_slot, - |slot| Epoch::genesis(&self.factory.config, slot), + |slot| Epoch::genesis(self.factory.config.genesis_config(), slot), ) .expect("client has data to find epoch") .expect("can compute epoch for baked block"); @@ -336,9 +336,9 @@ impl TestNetFactory for BabeTestNet { select_chain: longest_chain, create_inherent_data_providers: Box::new(|_, _| async { let timestamp = TimestampInherentDataProvider::from_system_time(); - let slot = InherentDataProvider::from_timestamp_and_duration( + let slot = InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, - Duration::from_secs(6), + SlotDuration::from_millis(6000), ); Ok((timestamp, slot)) @@ -449,9 +449,9 @@ fn run_one_test(mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + 'static sync_oracle: DummyOracle, create_inherent_data_providers: Box::new(|_, _| async { let timestamp = TimestampInherentDataProvider::from_system_time(); - let slot = InherentDataProvider::from_timestamp_and_duration( + let slot = InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, - Duration::from_secs(6), + SlotDuration::from_millis(6000), ); Ok((timestamp, slot)) @@ -699,12 +699,12 @@ fn importing_block_one_sets_genesis_epoch() { &mut block_import, ); - let genesis_epoch = Epoch::genesis(&data.link.config, 999.into()); + let genesis_epoch = Epoch::genesis(data.link.config.genesis_config(), 999.into()); let epoch_changes = data.link.epoch_changes.shared_data(); let epoch_for_second_block = epoch_changes .epoch_data_for_child_of(descendent_query(&*client), &block_hash, 1, 1000.into(), |slot| { - Epoch::genesis(&data.link.config, slot) + Epoch::genesis(data.link.config.genesis_config(), slot) }) .unwrap() .unwrap(); diff --git a/client/consensus/manual-seal/src/consensus/aura.rs b/client/consensus/manual-seal/src/consensus/aura.rs index 4497a94bdd429..7b5d6720562be 100644 --- a/client/consensus/manual-seal/src/consensus/aura.rs +++ b/client/consensus/manual-seal/src/consensus/aura.rs @@ -22,13 +22,12 @@ use crate::{ConsensusDataProvider, Error}; use sc_client_api::{AuxStore, UsageProvider}; use sc_consensus::BlockImportParams; -use sc_consensus_aura::slot_duration; use sp_api::{ProvideRuntimeApi, TransactionFor}; use sp_blockchain::{HeaderBackend, HeaderMetadata}; use sp_consensus_aura::{ digests::CompatibleDigestItem, sr25519::{AuthorityId, AuthoritySignature}, - AuraApi, + AuraApi, Slot, SlotDuration, }; use sp_inherents::InherentData; use sp_runtime::{traits::Block as BlockT, Digest, DigestItem}; @@ -37,8 +36,8 @@ use std::{marker::PhantomData, sync::Arc}; /// Consensus data provider for Aura. pub struct AuraConsensusDataProvider { - // slot duration in milliseconds - slot_duration: u64, + // slot duration + slot_duration: SlotDuration, // phantom data for required generics _phantom: PhantomData<(B, C)>, } @@ -52,8 +51,8 @@ where /// Creates a new instance of the [`AuraConsensusDataProvider`], requires that `client` /// implements [`sp_consensus_aura::AuraApi`] pub fn new(client: Arc) -> Self { - let slot_duration = - (*slot_duration(&*client).expect("slot_duration is always present; qed.")).get(); + let slot_duration = sc_consensus_aura::slot_duration(&*client) + .expect("slot_duration is always present; qed."); Self { slot_duration, _phantom: PhantomData } } @@ -76,13 +75,15 @@ where _parent: &B::Header, inherents: &InherentData, ) -> Result { - let time_stamp = - *inherents.timestamp_inherent_data()?.expect("Timestamp is always present; qed"); + let timestamp = + inherents.timestamp_inherent_data()?.expect("Timestamp is always present; qed"); + // we always calculate the new slot number based on the current time-stamp and the slot // duration. let digest_item = >::aura_pre_digest( - (time_stamp / self.slot_duration).into(), + Slot::from_timestamp(timestamp, self.slot_duration), ); + Ok(Digest { logs: vec![digest_item] }) } diff --git a/client/consensus/manual-seal/src/consensus/babe.rs b/client/consensus/manual-seal/src/consensus/babe.rs index dd3f9a253478a..53cc58df30a36 100644 --- a/client/consensus/manual-seal/src/consensus/babe.rs +++ b/client/consensus/manual-seal/src/consensus/babe.rs @@ -169,7 +169,9 @@ where .ok_or_else(|| sp_consensus::Error::InvalidAuthoritiesSet)?; let epoch = epoch_changes - .viable_epoch(&epoch_descriptor, |slot| Epoch::genesis(&self.config, slot)) + .viable_epoch(&epoch_descriptor, |slot| { + Epoch::genesis(self.config.genesis_config(), slot) + }) .ok_or_else(|| { log::info!(target: "babe", "create_digest: no viable_epoch :("); sp_consensus::Error::InvalidAuthoritiesSet @@ -283,15 +285,17 @@ where let timestamp = inherents .timestamp_inherent_data()? .ok_or_else(|| Error::StringError("No timestamp inherent data".into()))?; - let slot = *timestamp / self.config.slot_duration; + + let slot = Slot::from_timestamp(timestamp, self.config.slot_duration()); + // manually hard code epoch descriptor epoch_descriptor = match epoch_descriptor { ViableEpochDescriptor::Signaled(identifier, _header) => ViableEpochDescriptor::Signaled( identifier, EpochHeader { - start_slot: slot.into(), - end_slot: (slot * self.config.epoch_length).into(), + start_slot: slot, + end_slot: (*slot * self.config.genesis_config().epoch_length).into(), }, ), _ => unreachable!( diff --git a/client/consensus/manual-seal/src/consensus/timestamp.rs b/client/consensus/manual-seal/src/consensus/timestamp.rs index 908d218da05ac..e7f4e709ab996 100644 --- a/client/consensus/manual-seal/src/consensus/timestamp.rs +++ b/client/consensus/manual-seal/src/consensus/timestamp.rs @@ -21,8 +21,6 @@ use crate::Error; use sc_client_api::{AuxStore, UsageProvider}; -use sc_consensus_aura::slot_duration; -use sc_consensus_babe::Config; use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; use sp_consensus_aura::{ @@ -30,6 +28,7 @@ use sp_consensus_aura::{ AuraApi, }; use sp_consensus_babe::BabeApi; +use sp_consensus_slots::{Slot, SlotDuration}; use sp_inherents::{InherentData, InherentDataProvider, InherentIdentifier}; use sp_runtime::{ generic::BlockId, @@ -53,7 +52,7 @@ pub struct SlotTimestampProvider { // holds the unix millisecnd timestamp for the most recent block unix_millis: atomic::AtomicU64, // configured slot_duration in the runtime - slot_duration: u64, + slot_duration: SlotDuration, } impl SlotTimestampProvider { @@ -64,7 +63,7 @@ impl SlotTimestampProvider { C: AuxStore + HeaderBackend + ProvideRuntimeApi + UsageProvider, C::Api: BabeApi, { - let slot_duration = Config::get(&*client)?.slot_duration; + let slot_duration = sc_consensus_babe::Config::get(&*client)?.slot_duration(); let time = Self::with_header(&client, slot_duration, |header| { let slot_number = *sc_consensus_babe::find_pre_digest::(&header) @@ -83,7 +82,7 @@ impl SlotTimestampProvider { C: AuxStore + HeaderBackend + ProvideRuntimeApi + UsageProvider, C::Api: AuraApi, { - let slot_duration = (*slot_duration(&*client)?).get(); + let slot_duration = sc_consensus_aura::slot_duration(&*client)?; let time = Self::with_header(&client, slot_duration, |header| { let slot_number = *sc_consensus_aura::find_pre_digest::(&header) @@ -94,7 +93,11 @@ impl SlotTimestampProvider { Ok(Self { unix_millis: atomic::AtomicU64::new(time), slot_duration }) } - fn with_header(client: &Arc, slot_duration: u64, func: F) -> Result + fn with_header( + client: &Arc, + slot_duration: SlotDuration, + func: F, + ) -> Result where B: BlockT, C: AuxStore + HeaderBackend + UsageProvider, @@ -110,7 +113,7 @@ impl SlotTimestampProvider { .ok_or_else(|| "best header not found in the db!".to_string())?; let slot = func(header)?; // add the slot duration so there's no collision of slots - (slot * slot_duration) + slot_duration + (slot * slot_duration.as_millis() as u64) + slot_duration.as_millis() as u64 } else { // this is the first block, use the correct time. let now = SystemTime::now(); @@ -123,8 +126,11 @@ impl SlotTimestampProvider { } /// Get the current slot number - pub fn slot(&self) -> u64 { - self.unix_millis.load(atomic::Ordering::SeqCst) / self.slot_duration + pub fn slot(&self) -> Slot { + Slot::from_timestamp( + self.unix_millis.load(atomic::Ordering::SeqCst).into(), + self.slot_duration, + ) } /// Gets the current time stamp. @@ -140,8 +146,10 @@ impl InherentDataProvider for SlotTimestampProvider { inherent_data: &mut InherentData, ) -> Result<(), sp_inherents::Error> { // we update the time here. - let new_time: InherentType = - self.unix_millis.fetch_add(self.slot_duration, atomic::Ordering::SeqCst).into(); + let new_time: InherentType = self + .unix_millis + .fetch_add(self.slot_duration.as_millis() as u64, atomic::Ordering::SeqCst) + .into(); inherent_data.put_data(INHERENT_IDENTIFIER, &new_time)?; Ok(()) } diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index 094d065a1c07c..f6129943b2411 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -32,15 +32,14 @@ pub use aux_schema::{check_equivocation, MAX_SLOT_CAPACITY, PRUNING_BOUND}; pub use slots::SlotInfo; use slots::Slots; -use codec::{Decode, Encode}; use futures::{future::Either, Future, TryFutureExt}; use futures_timer::Delay; -use log::{debug, error, info, warn}; +use log::{debug, info, warn}; use sc_consensus::{BlockImport, JustificationSyncLink}; use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_INFO, CONSENSUS_WARN}; use sp_arithmetic::traits::BaseArithmetic; -use sp_consensus::{CanAuthorWith, Proposer, SelectChain, SlotData, SyncOracle}; -use sp_consensus_slots::Slot; +use sp_consensus::{CanAuthorWith, Proposer, SelectChain, SyncOracle}; +use sp_consensus_slots::{Slot, SlotDuration}; use sp_inherents::CreateInherentDataProviders; use sp_runtime::{ generic::BlockId, @@ -459,8 +458,8 @@ impl_inherent_data_provider_ext_tuple!(T, S, A, B, C, D, E, F, G, H, I, J); /// /// Every time a new slot is triggered, `worker.on_slot` is called and the future it returns is /// polled until completion, unless we are major syncing. -pub async fn start_slot_worker( - slot_duration: SlotDuration, +pub async fn start_slot_worker( + slot_duration: SlotDuration, client: C, mut worker: W, mut sync_oracle: SO, @@ -471,15 +470,11 @@ pub async fn start_slot_worker( C: SelectChain, W: SlotWorker, SO: SyncOracle + Send, - T: SlotData + Clone, CIDP: CreateInherentDataProviders + Send, CIDP::InherentDataProviders: InherentDataProviderExt + Send, CAW: CanAuthorWith + Send, { - let SlotDuration(slot_duration) = slot_duration; - - let mut slots = - Slots::new(slot_duration.slot_duration(), create_inherent_data_providers, client); + let mut slots = Slots::new(slot_duration.as_duration(), create_inherent_data_providers, client); loop { let slot_info = match slots.next_slot().await { @@ -523,45 +518,6 @@ pub enum CheckedHeader { Checked(H, S), } -#[derive(Debug, thiserror::Error)] -#[allow(missing_docs)] -pub enum Error -where - T: Debug, -{ - #[error("Slot duration is invalid: {0:?}")] - SlotDurationInvalid(SlotDuration), -} - -/// A slot duration. Create with [`Self::new`]. -#[derive(Clone, Copy, Debug, Encode, Decode, Hash, PartialOrd, Ord, PartialEq, Eq)] -pub struct SlotDuration(T); - -impl Deref for SlotDuration { - type Target = T; - fn deref(&self) -> &T { - &self.0 - } -} - -impl SlotData for SlotDuration { - fn slot_duration(&self) -> std::time::Duration { - self.0.slot_duration() - } -} - -impl SlotDuration { - /// Create a new instance of `Self`. - pub fn new(val: T) -> Self { - Self(val) - } - - /// Returns slot data value. - pub fn get(&self) -> T { - self.0.clone() - } -} - /// A unit type wrapper to express the proportion of a slot. pub struct SlotProportion(f32); diff --git a/primitives/consensus/aura/src/inherents.rs b/primitives/consensus/aura/src/inherents.rs index c3fa43bec02b8..ce3d832c78ee9 100644 --- a/primitives/consensus/aura/src/inherents.rs +++ b/primitives/consensus/aura/src/inherents.rs @@ -58,12 +58,11 @@ impl InherentDataProvider { /// Creates the inherent data provider by calculating the slot from the given /// `timestamp` and `duration`. - pub fn from_timestamp_and_duration( + pub fn from_timestamp_and_slot_duration( timestamp: sp_timestamp::Timestamp, - duration: std::time::Duration, + slot_duration: sp_consensus_slots::SlotDuration, ) -> Self { - let slot = - InherentType::from((timestamp.as_duration().as_millis() / duration.as_millis()) as u64); + let slot = InherentType::from_timestamp(timestamp, slot_duration); Self { slot } } diff --git a/primitives/consensus/aura/src/lib.rs b/primitives/consensus/aura/src/lib.rs index cec89d0449d8e..3e47adf0bf92f 100644 --- a/primitives/consensus/aura/src/lib.rs +++ b/primitives/consensus/aura/src/lib.rs @@ -62,7 +62,7 @@ pub mod ed25519 { pub type AuthorityId = app_ed25519::Public; } -pub use sp_consensus_slots::Slot; +pub use sp_consensus_slots::{Slot, SlotDuration}; /// The `ConsensusEngineId` of AuRa. pub const AURA_ENGINE_ID: ConsensusEngineId = [b'a', b'u', b'r', b'a']; @@ -93,28 +93,3 @@ sp_api::decl_runtime_apis! { fn authorities() -> Vec; } } - -/// Aura slot duration. -/// -/// Internally stored as milliseconds. -#[derive(sp_runtime::RuntimeDebug, Encode, Decode, PartialEq, Clone, Copy)] -pub struct SlotDuration(u64); - -impl SlotDuration { - /// Initialize from the given milliseconds. - pub fn from_millis(val: u64) -> Self { - Self(val) - } - - /// Returns the slot duration in milli seconds. - pub fn get(&self) -> u64 { - self.0 - } -} - -#[cfg(feature = "std")] -impl sp_consensus::SlotData for SlotDuration { - fn slot_duration(&self) -> std::time::Duration { - std::time::Duration::from_millis(self.0) - } -} diff --git a/primitives/consensus/babe/src/inherents.rs b/primitives/consensus/babe/src/inherents.rs index 1eadfd85d1147..c26dc514ae158 100644 --- a/primitives/consensus/babe/src/inherents.rs +++ b/primitives/consensus/babe/src/inherents.rs @@ -18,7 +18,6 @@ //! Inherents for BABE use sp_inherents::{Error, InherentData, InherentIdentifier}; - use sp_std::result::Result; /// The BABE inherent identifier. @@ -60,12 +59,11 @@ impl InherentDataProvider { /// Creates the inherent data provider by calculating the slot from the given /// `timestamp` and `duration`. - pub fn from_timestamp_and_duration( + pub fn from_timestamp_and_slot_duration( timestamp: sp_timestamp::Timestamp, - duration: std::time::Duration, + slot_duration: sp_consensus_slots::SlotDuration, ) -> Self { - let slot = - InherentType::from((timestamp.as_duration().as_millis() / duration.as_millis()) as u64); + let slot = InherentType::from_timestamp(timestamp, slot_duration); Self { slot } } diff --git a/primitives/consensus/babe/src/lib.rs b/primitives/consensus/babe/src/lib.rs index e7dfc100825d6..492d1a9a7238f 100644 --- a/primitives/consensus/babe/src/lib.rs +++ b/primitives/consensus/babe/src/lib.rs @@ -79,7 +79,7 @@ pub const MEDIAN_ALGORITHM_CARDINALITY: usize = 1200; // arbitrary suggestion by /// The index of an authority. pub type AuthorityIndex = u32; -pub use sp_consensus_slots::Slot; +pub use sp_consensus_slots::{Slot, SlotDuration}; /// An equivocation proof for multiple block authorships on the same slot (i.e. double vote). pub type EquivocationProof = sp_consensus_slots::EquivocationProof; @@ -237,13 +237,6 @@ impl AllowedSlots { } } -#[cfg(feature = "std")] -impl sp_consensus::SlotData for BabeGenesisConfiguration { - fn slot_duration(&self) -> std::time::Duration { - std::time::Duration::from_millis(self.slot_duration) - } -} - /// Configuration data used by the BABE consensus engine. #[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, MaxEncodedLen, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] diff --git a/primitives/consensus/common/src/lib.rs b/primitives/consensus/common/src/lib.rs index edf393fa229ad..59bbf7618dfc3 100644 --- a/primitives/consensus/common/src/lib.rs +++ b/primitives/consensus/common/src/lib.rs @@ -327,9 +327,3 @@ impl CanAuthorWith for NeverCanAuthor { Err("Authoring is always disabled.".to_string()) } } - -/// A type from which a slot duration can be obtained. -pub trait SlotData { - /// Gets the slot duration. - fn slot_duration(&self) -> sp_std::time::Duration; -} diff --git a/primitives/consensus/slots/Cargo.toml b/primitives/consensus/slots/Cargo.toml index 18506980ae85d..aed2265bddca6 100644 --- a/primitives/consensus/slots/Cargo.toml +++ b/primitives/consensus/slots/Cargo.toml @@ -16,8 +16,10 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", features = ["derive"], optional = true } -sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } sp-arithmetic = { version = "4.0.0", default-features = false, path = "../../arithmetic" } +sp-runtime = { version = "5.0.0", default-features = false, path = "../../runtime" } +sp-std = { version = "4.0.0", default-features = false, path = "../../std" } +sp-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../timestamp" } [features] default = ["std"] @@ -25,6 +27,8 @@ std = [ "codec/std", "scale-info/std", "serde", - "sp-runtime/std", "sp-arithmetic/std", + "sp-runtime/std", + "sp-std/std", + "sp-timestamp/std", ] diff --git a/primitives/consensus/slots/src/lib.rs b/primitives/consensus/slots/src/lib.rs index e8ab98399414b..21b3cad1e7167 100644 --- a/primitives/consensus/slots/src/lib.rs +++ b/primitives/consensus/slots/src/lib.rs @@ -21,6 +21,7 @@ use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; +use sp_timestamp::Timestamp; /// Unit type wrapper that represents a slot. #[derive(Debug, Encode, MaxEncodedLen, Decode, Eq, Clone, Copy, Default, Ord, TypeInfo)] @@ -64,6 +65,11 @@ impl + Copy> core::cmp::PartialOrd for Slot { } impl Slot { + /// Create a new slot by calculating it from the given timestamp and slot duration. + pub const fn from_timestamp(timestamp: Timestamp, slot_duration: SlotDuration) -> Self { + Slot(timestamp.as_millis() / slot_duration.as_millis()) + } + /// Saturating addition. pub fn saturating_add>(self, rhs: T) -> Self { Self(self.0.saturating_add(rhs.into())) @@ -94,6 +100,32 @@ impl From for u64 { } } +/// A slot duration defined in milliseconds. +#[derive(Clone, Copy, Debug, Encode, Decode, Hash, PartialOrd, Ord, PartialEq, Eq, TypeInfo)] +pub struct SlotDuration(u64); + +impl SlotDuration { + /// Initialize from the given milliseconds. + pub const fn from_millis(millis: u64) -> Self { + Self(millis) + } +} + +impl SlotDuration { + /// Returns `self` as a `u64` representing the duration in milliseconds. + pub const fn as_millis(&self) -> u64 { + self.0 + } +} + +#[cfg(feature = "std")] +impl SlotDuration { + /// Returns `self` as [`sp_std::time::Duration`]. + pub const fn as_duration(&self) -> sp_std::time::Duration { + sp_std::time::Duration::from_millis(self.0) + } +} + /// Represents an equivocation proof. An equivocation happens when a validator /// produces more than one block on the same slot. The proof of equivocation /// are the given distinct headers that were signed by the validator and which diff --git a/primitives/timestamp/src/lib.rs b/primitives/timestamp/src/lib.rs index 76725e28ac825..b98a87c37f69d 100644 --- a/primitives/timestamp/src/lib.rs +++ b/primitives/timestamp/src/lib.rs @@ -42,10 +42,16 @@ impl Timestamp { } /// Returns `self` as [`Duration`]. - pub fn as_duration(self) -> Duration { + pub const fn as_duration(self) -> Duration { Duration::from_millis(self.0) } + /// Returns `self` as a `u64` representing the elapsed time since the UNIX_EPOCH in + /// milliseconds. + pub const fn as_millis(&self) -> u64 { + self.0 + } + /// Checked subtraction that returns `None` on an underflow. pub fn checked_sub(self, other: Self) -> Option { self.0.checked_sub(other.0).map(Self)