Babe is another slote based consensus, but unlike Aura, Babe is using VRF PRNG to randomly select a validator to produce block.
Babe startup
Code can be found in node_cli::service.
- block_import: grandpa
- consensus: babe
- import_queue: base BasicQueue
let (grandpa_block_import, grandpa_link) = grandpa::block_import(
client.clone(),
&(client.clone() as Arc<_>),
select_chain.clone(),
telemetry.as_ref().map(|x| x.handle()),
)?;
let justification_import = grandpa_block_import.clone();
let (block_import, babe_link) = sc_consensus_babe::block_import(
sc_consensus_babe::Config::get_or_compute(&*client)?,
grandpa_block_import,
client.clone(),
)?;
let slot_duration = babe_link.config().slot_duration();
let import_queue = sc_consensus_babe::import_queue(
babe_link.clone(),
block_import.clone(),
Some(Box::new(justification_import)),
client.clone(),
select_chain.clone(),
move |_, ()| async move {
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
let slot =
sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration(
*timestamp,
slot_duration,
);
let uncles =
sp_authorship::InherentDataProvider::<<Block as BlockT>::Header>::check_inherents();
Ok((timestamp, slot, uncles))
},
&task_manager.spawn_essential_handle(),
config.prometheus_registry(),
sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),
telemetry.as_ref().map(|x| x.handle()),
)?;
After that node_cli will start babe when role is Role::Authroty:
let babe = sc_consensus_babe::start_babe(babe_config)?;
task_manager.spawn_essential_handle().spawn_blocking("babe-proposer", babe);
Babe SlotWorker
It implements the trait SimpleLotWorker, responsible for authoring blocks.
struct BabeSlotWorker<B: BlockT, C, E, I, SO, L, BS> {
client: Arc<C>,
block_import: I,
env: E,
sync_oracle: SO,
justification_sync_link: L,
force_authoring: bool,
backoff_authoring_blocks: Option<BS>,
keystore: SyncCryptoStorePtr,
epoch_changes: SharedEpochChanges<B, Epoch>,
slot_notification_sinks: SlotNotificationSinks<B>,
config: Config,
block_proposal_slot_portion: SlotProportion,
max_block_proposal_slot_portion: Option<SlotProportion>,
telemetry: Option<TelemetryHandle>,
}
Babe RPC
Provides rpc methods for interacting with Babe.
#[rpc]
pub trait BabeApi {
/// Returns data about which slots (primary or secondary) can be claimed in the current epoch
/// with the keys in the keystore.
#[rpc(name = "babe_epochAuthorship")]
fn epoch_authorship(&self) -> FutureResult<HashMap<AuthorityId, EpochAuthorship>>;
}
RPC ‘babe_epochAuthorship’ will to delegated by RPC handler.
BlockImport
Babe also implements tarit BlockImport. It scans each imported block for epoch change signals. The signals are tracked in a tree (of all forks), and the import logic validates all epoch change transitions, i.e. whether a given epoch change is expected or whether it is missing.
The Babe BlockImport will be used to construct the import queue which will be ‘polled’ in network worker.
Import Queue
Babe creates the import queue, which is polled by Network worker later.
/// Start an import queue for the BABE consensus algorithm.
///
/// This method returns the import queue, some data that needs to be passed to the block authoring
/// logic (BabeLink
), and a future that must be run to
/// completion and is responsible for listening to finality notifications and
/// pruning the epoch changes tree.
///
/// The block import object provided must be the BabeBlockImport
or a wrapper
/// of it, otherwise crucial import logic will be omitted.