Assessment reports>Babylon Genesis Chain>Design>Module: checkpointing

Module: checkpointing

Description

Babylon checkpoints record the state of the Babylon chain at the end of a specific epoch. These checkpoints are created to be included in the BTC Network as a measure to protect the Babylon chain and connected chains from long-range attacks. If blocks in the BTC Network with sufficient resistance to reorg include data related to the checkpoint, it provides an immutable record of the Babylon state up to the epoch in which the checkpoint was created. This also helps determine the valid main branch of the Babylon chain.

A checkpoint contains a unique committed identifier and the BLS signatures of the validator set corresponding to that state. BLS signatures were chosen for their ability to aggregate signatures, allowing checkpoints to remain verifiable and compact. To enable this, each validator must maintain a BLS key pair and register their BLS public key on the Babylon chain. Validators use their BLS private keys to sign the last block ID of the epoch and submit their signatures via the ABCI++ vote-extension interface. Valid BLS signatures are aggregated into the checkpoint included in the next block proposal. Prior to , BLS private keys were stored unencrypted at rest; subsequently, they are stored in a passphrase-protected ERC-2335 keystore file, with the migrate-bls-key command added to convert to the new format.

Once a valid checkpoint is created, it is committed to the Bitcoin ledger via an off-chain program called the vigilante submitter. This program constructs Bitcoin transactions with outputs using OP_RETURN script codes to include checkpoint data in the Bitcoin ledger. Due to OP_RETURN's data-size limitations, two transactions are generated to include the entire checkpoint data. Once included, another off-chain program, the vigilante reporter, submits inclusion proofs to the btccheckpoint module, which monitors confirmation status and reports it to the checkpointing module. If two conflicting checkpoints with valid BLS multi-signatures are observed, it indicates a fork, and a warning is raised. In such cases, the checkpoint included first in the Bitcoin ledger determines the valid main branch of the Babylon chain.

Messages

MsgWrappedCreateValidator

This message wraps the Cosmos SDK MsgCreateValidator with a BLS public key. It is used to register new validators on the Babylon chain and store their BLS public keys.

When a Babylon node receives MsgWrappedCreateValidator, it checks the following conditions:

  • The signer of the MsgWrappedCreateValidator is verified.

  • The ownership of the BLS public key included in the message is verified.

  • The same BLS public key cannot be registered by multiple validators, and a single validator cannot register more than one BLS public key.

If all conditions are met, the message performs the following steps:

  1. Extract and validate the underlying MsgCreateValidator.

  2. Extract the BLS public key and store it in both the address-to-key and key-to-address mappings.

  3. Add the MsgCreateValidator to a designated queue in the epoching module.

  4. The epoching module processes the messages in the queue during the last block of the current epoch, effectively blocking the default Cosmos SDK staking-module messages (such as MsgCreateValidator, MsgDelegate, MsgUndelegate, MsgBeginRedelegate, and MsgCancelUnbondingDelegation) from executing normally via the AnteHandler.

ABCI++ handler

These handlers support the voting process for Babylon checkpoints and are called in the following sequence:

  1. ExtendVote (executed in the last block of the previous epoch)

  2. VerifyVoteExtension (executed in the last block of the previous epoch)

  3. PrepareProposal (executed in the first block of the current epoch)

  4. ProcessProposal (executed in the first block of the current epoch)

  5. PreBlock (executed in the first block of the current epoch)

  6. BeginBlock (executed in the first block of the current epoch)

ExtendVote

The ExtendVote function is invoked during the final voting phase of CometBFT consensus in the last block of the epoch. It checks 1) whether the signer of the vote is part of the current epoch's validator set and 2) whether the validator can correctly sign the block ID and epoch number using its BLS key.

If these checks succeed, ExtendVote generates a vote extension containing the BLS signature, attaching it to the validator's precommit vote.

VerifyVoteExtension

The VerifyVoteExtension function validates the vote extensions created by other validators. It checks the following:

  • The epoch number in the vote extension matches the current epoch.

  • The validator address sending the vote extension matches the address embedded in the BLS signature.

  • The current block hash in VerifyVoteExtension matches the block hash referenced by the BLS signature in the vote extension.

  • The BLS signature itself is valid.

If all checks pass, the vote extension is considered valid and is included in the list passed to the PrepareProposal function of the subsequent block.

PrepareProposal

When the proposed block is the first block of the next epoch, the validator chosen as the proposer by CometBFT gathers the valid vote extensions from the previous block, constructs a checkpoint, and includes it as the first transaction in the block.

ProcessProposal

The ProcessProposal function evaluates the integrity of the block that includes the checkpoint transaction created in PrepareProposal. If the block is the first block of the next epoch, it checks the following:

  • Whether the first transaction in the block corresponds to a checkpoint

  • Whether the vote extensions within the checkpoint match the data collected from the previous epoch

  • Whether each BLS signature is valid when referencing the block ID from the prior epoch

  • Whether the cumulative voting power of the validators who signed the vote extensions exceeds two-thirds of the total epoch voting power

If these conditions are satisfied, the checkpoint is considered valid.

PreBlock

The PreBlock function records the checkpoint from the special transaction injected into the first block of the epoch. Since ProcessProposal already verifies the checkpoint, PreBlock simply persists the data to the application state without additional checks.

BeginBlock

The BeginBlock function initializes the validator set with their BLS public keys if the proposed block is the first block of a new epoch. It is invoked immediately after PreBlock during block finalization. This step retrieves the validator set for the epoch from the epoching module and associates each validator with its corresponding BLS public key.

Test coverage

The x/checkpointing package has high test coverage (75.0%), with the keeper module slightly lower (68.2%), while the types module remains mostly untested (7.1%).

ok      github.com/babylonlabs-io/babylon/x/checkpointing       9.132s  coverage: 75.0% of statements
ok      github.com/babylonlabs-io/babylon/x/checkpointing/keeper        3.953s  coverage: 68.2% of statements
ok      github.com/babylonlabs-io/babylon/x/checkpointing/types 2.298s  coverage: 7.1% of statements

Attack surface

The attack surface exposed by the checkpointing module are the wrapped x/staking validator messages — any issues in the wrapped messages that would allow an arbitrary creation of validators. Other issues include the proposal preparation/processing and the vote-extension process, which could result in nondeterminism and/or DOS in the consensus process.

Zellic © 2025Back to top ↑