::from(
+ "Unable to produce collation",
+ ))
+ }
+ }
+
+ /// Get the underlying collator service.
+ pub fn collator_service(&self) -> &CS {
+ &self.collator_service
+ }
+}
+
+/// A claim on an Aura slot.
+pub struct SlotClaim {
+ author_id: NimbusId,
+ timestamp: Timestamp,
+}
+
+impl SlotClaim {
+ /// Create a slot-claim from the given author public key, slot, and timestamp.
+ ///
+ /// This does not check whether the author actually owns the slot or the timestamp
+ /// falls within the slot.
+ pub fn unchecked(author_id: NimbusId, timestamp: Timestamp) -> Self
+ where
+ P: Pair,
+ P::Public: Codec,
+ P::Signature: Codec,
+ {
+ SlotClaim {
+ author_id,
+ timestamp,
+ }
+ }
+
+ /// Get the timestamp corresponding to the relay-chain slot this claim was
+ /// generated against.
+ pub fn timestamp(&self) -> Timestamp {
+ self.timestamp
+ }
+
+ /// Get the timestamp corresponding to the relay-chain slot this claim was
+ /// generated against.
+ pub fn author_id(&self) -> NimbusId {
+ self.author_id.clone()
+ }
+}
+
+/// Seal a block with a signature in the header.
+pub fn seal(
+ pre_sealed: B,
+ storage_changes: StorageChanges>,
+ author_pub: &P::Public,
+ keystore: &KeystorePtr,
+) -> Result, Box>
+where
+ P: Pair,
+ P::Signature: Codec + TryFrom>,
+ P::Public: AppPublic,
+{
+ let (pre_header, body) = pre_sealed.deconstruct();
+ let pre_hash = pre_header.hash();
+ let block_number = *pre_header.number();
+
+ // seal the block.
+ let block_import_params = {
+ //let seal_digest = aura_internal::seal::<_, P>(&pre_hash, &author_pub, keystore).map_err(Box::new)?;
+ let seal_digest = crate::collators::seal_header::(
+ &pre_header,
+ keystore,
+ &author_pub.to_raw_vec(),
+ &sp_core::sr25519::CRYPTO_ID,
+ );
+ let mut block_import_params = BlockImportParams::new(BlockOrigin::Own, pre_header);
+ block_import_params.post_digests.push(seal_digest);
+ block_import_params.body = Some(body);
+ block_import_params.state_action =
+ StateAction::ApplyChanges(sc_consensus::StorageChanges::Changes(storage_changes));
+ block_import_params.fork_choice = Some(ForkChoiceStrategy::LongestChain);
+ block_import_params
+ };
+ let post_hash = block_import_params.post_hash();
+
+ tracing::info!(
+ target: crate::LOG_TARGET,
+ "🔖 Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.",
+ block_number,
+ post_hash,
+ pre_hash,
+ );
+
+ Ok(block_import_params)
+}
diff --git a/client/consensus/nimbus-consensus/src/collators.rs b/client/consensus/nimbus-consensus/src/collators.rs
index 5d3c252..c336693 100644
--- a/client/consensus/nimbus-consensus/src/collators.rs
+++ b/client/consensus/nimbus-consensus/src/collators.rs
@@ -17,157 +17,48 @@
//! Stock, pure Nimbus collators.
//!
//! This includes the [`basic`] collator, which only builds on top of the most recently
-//! included parachain block, as well as the [`lookahead`] collator, which prospectively
-//! builds on parachain blocks which have not yet been included in the relay chain.
+//! included parachain block, the [`lookahead`] collator, which prospectively builds on
+//! parachain blocks which have not yet been included in the relay chain, and the
+//! [`slot_based`] collator, which uses a slot-based block production approach with a
+//! separate block builder task that is timed by the parachain's slot duration.
pub mod basic;
pub mod lookahead;
+pub mod slot_based;
-use crate::*;
-use cumulus_client_collator::service::ServiceInterface as CollatorServiceInterface;
-use cumulus_client_consensus_common::{ParachainBlockImportMarker, ParachainCandidate};
-use cumulus_client_consensus_proposer::ProposerInterface;
+use crate::{collator::SlotClaim, *};
+use async_backing_primitives::Slot;
+use async_backing_primitives::UnincludedSegmentApi;
+use cumulus_client_consensus_common::{ParentSearchParams, PotentialParent};
use cumulus_primitives_core::{
- relay_chain::{OccupiedCoreAssumption, ValidationCodeHash},
- ParachainBlockData,
+ relay_chain::{Header as RelayHeader, OccupiedCoreAssumption, ValidationCodeHash},
+ ParaId,
};
-use cumulus_primitives_parachain_inherent::ParachainInherentData;
-use futures::prelude::*;
-use log::{debug, info};
-use nimbus_primitives::{CompatibleDigestItem, DigestsProvider, NimbusId, NIMBUS_KEY_ID};
-use polkadot_node_primitives::{Collation, MaybeCompressedPoV};
+use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface};
+use log::debug;
+use nimbus_primitives::{CompatibleDigestItem, NimbusId, NIMBUS_KEY_ID};
+use parity_scale_codec::Codec;
+use polkadot_node_subsystem::messages::{CollatorProtocolMessage, RuntimeApiRequest};
+use polkadot_node_subsystem_util::runtime::ClaimQueueSnapshot;
use polkadot_primitives::Hash as RelayHash;
-use sc_consensus::{BlockImport, BlockImportParams};
-use sp_application_crypto::ByteArray;
-use sp_consensus::{BlockOrigin, Proposal};
-use sp_core::{crypto::CryptoTypeId, sr25519};
-use sp_inherents::InherentData;
-use sp_keystore::Keystore;
+use sp_api::{ApiExt, RuntimeApiInfo};
+use sp_core::crypto::CryptoTypeId;
+use sp_keystore::{Keystore, KeystorePtr};
use sp_runtime::{
traits::{Block as BlockT, Header as HeaderT},
DigestItem,
};
+use sp_timestamp::Timestamp;
use std::convert::TryInto;
-use std::error::Error;
-use std::time::Duration;
-/// Propose, seal, and import a block, packaging it into a collation.
-///
-/// Provide the slot to build at as well as any other necessary pre-digest logs,
-/// the inherent data, and the proposal duration and PoV size limits.
-///
-/// The Aura pre-digest should not be explicitly provided and is set internally.
-///
-/// This does not announce the collation to the parachain network or the relay chain.
-pub(crate) async fn collate(
- additional_digests_provider: &ADP,
- author_id: NimbusId,
- block_import: &mut BI,
- collator_service: &CS,
- keystore: &dyn Keystore,
- parent_header: &Block::Header,
- proposer: &mut Proposer,
- inherent_data: (ParachainInherentData, InherentData),
- proposal_duration: Duration,
- max_pov_size: usize,
-) -> Result