BABE block production and GRANDPA finality in Avail
Avail uses a hybrid consensus mechanism inherited from Substrate, combining BABE (Blind Assignment for Blockchain Extension) for block production with GRANDPA (GHOST-based Recursive Ancestor Deriving Prefix Agreement) for finality.
BABE is a slot-based block production mechanism where time is divided into epochs, and epochs are divided into slots.
Slot Duration: 20 seconds (runtime/src/constants.rs) Epoch Duration: 4 hours (720 slots) Primary Probability: Validators have a probability-based chance to produce a block in each slot
The BABE pallet configuration in runtime/src/lib.rs:
runtime/src/lib.rs
impl pallet_babe::Config for Runtime { type EpochDuration = EpochDuration; type ExpectedBlockTime = ExpectedBlockTime; type EpochChangeTrigger = pallet_babe::ExternalTrigger; type DisabledValidators = Session; type WeightInfo = (); type MaxAuthorities = MaxAuthorities; type MaxNominators = MaxNominatorRewardedPerValidator; type KeyOwnerProof = <Historical as KeyOwnerProofSystem<_>>::Proof; type EquivocationReportSystem = pallet_babe::EquivocationReportSystem< Self, Offences, Historical, ReportLongevity, >;}
GRANDPA is a Byzantine fault-tolerant finality gadget that finalizes chains rather than individual blocks. It can finalize multiple blocks in a single round of voting.
impl pallet_grandpa::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); type MaxAuthorities = MaxAuthorities; type MaxNominators = MaxNominatorRewardedPerValidator; type MaxSetIdSessionEntries = ConstU64<0>; type KeyOwnerProof = <Historical as KeyOwnerProofSystem<_>>::Proof; type EquivocationReportSystem = pallet_grandpa::EquivocationReportSystem< Self, Offences, Historical, ReportLongevity, >;}
The Session pallet (runtime/src/lib.rs:11) manages validator set rotations:
impl pallet_session::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ValidatorId = AccountId; type ValidatorIdOf = pallet_staking::StashOf<Self>; type ShouldEndSession = Babe; type NextSessionRotation = Babe; type SessionManager = pallet_session::historical::NoteHistoricalRoot<Self, Staking>; type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders; type Keys = SessionKeys; type WeightInfo = pallet_session::weights::SubstrateWeight<Runtime>;}
The ImOnline pallet (runtime/src/lib.rs:20) ensures validators are online and participating.
impl pallet_im_online::Config for Runtime { type AuthorityId = ImOnlineId; type RuntimeEvent = RuntimeEvent; type NextSessionRotation = Babe; type ValidatorSet = Historical; type ReportUnresponsiveness = Offences; type UnsignedPriority = ImOnlineUnsignedPriority; type WeightInfo = pallet_im_online::weights::SubstrateWeight<Runtime>; type MaxKeys = MaxKeys; type MaxPeerInHeartbeat = MaxPeerInHeartbeat;}
Validators send heartbeat transactions every session. Failure to send heartbeats results in:
If DA checks pass, block is passed to BABE/GRANDPA for consensus verification.
This DA block import layer ensures that blocks without valid Kate commitments are rejected before reaching consensus, providing cryptographic proof of data availability.