Skip to main content
Bor is the block production layer of Polygon PoS. It is based on the Clique consensus protocol, described in EIP-225. Block producers take turns generating blocks within defined time windows, and sign their blocks using secp256k1.

Proposers and producers selection

Block producers for Bor are a committee selected from the validator pool based on stake. Selection happens at regular intervals, called spans, and is governed by validator governance parameters. A validator’s probability of being selected as a block producer is proportional to their stake. Selection process:
  1. Validators are assigned slots proportionally to their stake.
  2. Historical Ethereum block data is used as a seed to shuffle the validator array.
  3. Based on the producer count (maintained by validator governance), validators are taken from the top of the shuffled array.
  4. CometBFT’s proposer selection algorithm is applied to choose a producer for every sprint within a Bor span.

Spans

A span is a defined set of blocks during which a specific subset of validators is selected from the broader validator pool. Within a span, each validator is assigned voting power. The probability of a validator being chosen as a block producer is proportional to their voting power.

Sprints

Within a span, a sprint is a smaller subset of blocks. For each sprint, a single block producer is selected to generate blocks. The sprint size is a fraction of the overall span size. Bor also designates backup producers, ready to step in if the primary producer is unable to fulfill its role.

Block authorization

Block producers sign the hash of the block header (excluding the signature itself) using secp256k1. The signature is appended to the extraData field of the block header. Each block is assigned a difficulty level:
  • Blocks signed in-turn by the designated producer receive DIFF_INTURN (higher difficulty).
  • Out-of-turn blocks from backup producers receive DIFF_NOTURN (lower difficulty).

Handling out-of-turn signing

When the designated producer fails to generate a block (due to technical issues, intentional withholding, or network disruption), backup producers step in. Activation is based on a sequential order of validators and a predefined delay called “wiggle time.” Wiggle time is the delay a backup producer waits before generating a block. It is calculated based on the last block’s production time, a variable Period parameter, and the backup producer’s position in the validator sequence relative to the designated producer.

Fork resolution

When backup producers generate blocks, forks can occur. Bor resolves forks by selecting the chain with the highest cumulative difficulty, favoring in-turn block production. A longer sequence of in-turn blocks produces higher cumulative difficulty and thus represents the canonical chain.

View change and span commitment

At the end of each span, Bor performs a view change: it makes an HTTP call to the Heimdall node to retrieve new span data, then calls commitSpan on the BorValidatorSet genesis contract. Block headers in Bor include producer bytes to aid fast-syncing.

State synchronization with Ethereum

Bor synchronizes specific events from Ethereum through a state sync mechanism:
  1. Contracts on Ethereum emit the StateSynced event via StateSender.sol.
  2. Heimdall monitors these events and proposes state changes through StateReceiver.sol.
  3. At the start of every sprint, Bor commits these state changes, keeping Bor state consistent with Ethereum.
This mechanism ensures that deposits from Ethereum are reflected in Bor’s state. For the full state sync flow, see State sync.