Skip to content

Block Builder Selection

This document specifies the block builder (proposer) selection policy and its guarantees.

Block builder selection in this chain is handled by the Commonware Simplex BFT consensus protocol. The selection is:

  • Deterministic: Given the same epoch, view, and validator set, the selected leader is always the same
  • Round-robin: Leaders rotate through the validator set based on view number
  • Epoch-scoped: Each epoch has a fixed, ordered validator set
leader_index = view % num_validators
leader = validators[leader_index]

Where:

  • view is the current consensus view/round number
  • num_validators is the size of the active validator set for the epoch
  • validators is an ordered list of validator public keys

The validator set ordering is determined by:

  1. Genesis: Initial participant list from configuration (lexicographically sorted by public key)
  2. DKG Output: Per-epoch DKG produces an ordered participant set
  3. Scheme Construction: Scheme::new(participants, polynomial, share) preserves input order

The ordering is consensus-critical - all nodes must agree on the same ordering for the same epoch.

EventEffect on Leader Selection
Epoch boundaryNew validator set takes effect
DKG completionNew epoch’s participant ordering established
View timeoutSame validator set, next leader in rotation
EquivocationValidator remains in rotation until epoch ends
  1. Next leader: Given current view and validator set, the next N leaders are computable
  2. Leader schedule: The full rotation schedule for an epoch is deterministic
  3. Epoch validator set: Once DKG completes, the epoch’s validator set is fixed
  1. View number at future time: Network conditions affect how quickly views advance
  2. Exact block production time: Depends on transaction volume and leader availability
  3. Future epoch validator sets: Depends on DKG output (derived from threshold signatures)
// Epoch scheme provider manages per-epoch BLS schemes
pub struct EpochSchemeProvider {
schemes: BTreeMap<Epoch, Scheme>,
current_epoch: AtomicU64,
}
// Scheme contains the ordered participant list
pub type Scheme = bls12381_threshold::Scheme<PublicKey, MinSig>;
// Scheme exposes participants in order
impl Scheme {
pub fn participants(&self) -> &Set<PublicKey> { ... }
}
pub struct BlockHeader {
// ... other fields ...
pub proposer: Address, // Block builder's address
pub epoch: u64, // Epoch during which block was produced
pub view: u64, // View/round in which block was produced
}

The ExecContext passed to block building includes:

pub struct ExecContext {
pub timestamp: u64,
pub validator_set_id: ValidatorSetId,
pub epoch: u64,
pub view: u64,
pub parent_vrf_output: Hash,
pub proposer: Address, // Fee recipient
}

The proposer address in ExecContext receives:

  • Transaction base fees
  • Priority fees (if implemented)
  • MEV rewards (future)
  1. Determinism test: Same inputs produce same leader selection
  2. Rotation test: Leaders cycle through validator set correctly
  3. Epoch boundary test: New validator set takes effect at boundary
  1. Multi-node agreement: All nodes select the same leader for the same view
  2. View timeout handling: Leader rotation continues correctly after timeouts
  3. DKG integration: New epoch uses new participant ordering

Q: Can a validator refuse to produce blocks?

A: Yes, but the view timeout mechanism advances to the next leader. The refusing validator loses their slot’s rewards.

Q: How is the initial validator set ordered?

A: By lexicographic sort of public key bytes. This ensures all nodes produce the same genesis ordering.

Q: What if DKG produces different orderings on different nodes?

A: This would be a consensus failure. DKG outputs are deterministic given the same inputs and messages. Nodes that produce different orderings would fork.

Q: Can the leader selection be gamed?

A: The rotation is deterministic but the view number progression is not fully predictable. A malicious leader cannot control who follows them, but they can observe when they will lead.