Module: btccheckpoint
Description
The btccheckpoint module is responsible for recording and managing Babylon's state as checkpoints on the Bitcoin network.
Its main functionalities include the following:
Handling raw checkpoint submission requests
Processing Bitcoin SPV proofs for submitted checkpoints
Managing the life cycle of checkpoints (
SEALED
,SUBMITTED
,CONFIRMED
,FINALIZED
)Verifying and finalizing checkpoints
Distributing rewards for successfully submitted checkpoints
Actively updating checkpoint states whenever the btclightclient module receives a new header
Messages
MsgInsertBTCSpvProof
This message is processed by the btclightclient module and is used by a vigilante reporter to save a new checkpoint in the state.
When a Babylon node receives the MsgInsertBTCSpvProof
message, it performs the following steps:
Parse the raw checkpoint data from the proof. The structure of the raw checkpoint consists of the following types:
type RawCheckpointSubmission struct {
Reporter sdk.AccAddress
Proof1 ParsedProof
Proof2 ParsedProof
CheckpointData btctxformatter.RawBtcCheckpoint
}
type ParsedProof struct {
BlockHash types.BTCHeaderHashBytes
Transaction *btcutil.Tx
TransactionBytes []byte
TransactionIdx uint32
OpReturnData []byte
}
type RawBtcCheckpoint struct {
Epoch uint64
BlockHash []byte
BitMap []byte
SubmitterAddress []byte
BlsSig []byte
}
The node ensures that two proofs are included in a checkpoint submission due to the Bitcoin network's OP_RETURN
data-length limit. It performs Merkle proof verification for each proof based on the Bitcoin-related data provided by the user.
It verifies that the transaction for each proof contains valid OP_RETURN
data related to the checkpoint, specifically checking the tag specified by the Babylon chain and a version that meets or exceeds the required version. If all validity checks pass, generate the RawCheckpointSubmission
.
Validate against previously submitted data. The node extracts a
SubmissionKey
from theRawCheckpointSubmission
and checks if theSubmissionKey
has already been submitted; if so, it rejects the message.
Return submission information. The node retrieves and returns the block depths of the submitted transactions, the most recent block hash, and the index of the submission within the most recent block. It verifies that the block hash of each submission exists in the btclightclient module.
Verify checkpoint data. The node checks whether the checkpoint originates from a forked chain or is invalid. It validates if the checkpoint matches any stored checkpoint in the
PreBlocker
and is not in theAccumulating
(voting) state. If so, it is considered a verified checkpoint. If not, assume it originates from a forked chain or is still in theAccumulating
state.It uses the
VerifyRawCheckpoint
function to confirm 1) the checkpoint has valid validator signatures for the epoch, 2) validator power exceeds two-thirds of the total power, and 3) the BLS signature is valid. It compares the block hash indicated by the raw check. If not, it assumes it originates from a forked chain and is invalid.Check ancestors. Once the checkpoint is validated, the node calls the
checkAncestors
function to ensure it is older than the latest transaction submitted to the Bitcoin network for the previous epoch.
If all checks pass, the message execution proceeds with the following two actions:
Save the block hashes and checkpoint submission data to the state along with the epoch number.
Update the status of the previously stored checkpoint from
SEALED
toSUBMITTED
.
MsgUpdateParams
This message is used to update parameters of the btccheckpoint module and can only be executed through a governance proposal.
ABCI++ handler
EndBlocker
This function is called every time a new Bitcoin network block header is added to the btclightclient module and is used to check and update checkpoint states for each epoch.
When a Babylon node triggers the checkCheckpoints
function, it performs the following steps:
Retrieve the most recently finalized epoch and iterate forward. The function starts by identifying the latest finalized epoch and then proceeds to evaluate all epochs up to the most recent one.
Verify epoch-finalization status. If the current epoch's status is
Finalized
, the node retrieves the submission for that epoch. (A finalized epoch should only have one submission.)Handle invalid parent epochs. If this process is on its second pass (the second loop) and the previous epoch has no
bestSubmission
, the current epoch is marked as invalid and its status is updated toSEALED
.Determine submissions to keep or delete. Submissions whose block hashes cannot be found in the btclightclient module (indicating a forked or invalid chain) are deleted. Submissions where the youngest block of the current epoch is older than the oldest block of the previous epoch are deleted.
Handle epochs without valid submissions. If no submissions remain after the deletions, the epoch is marked as invalid and its status is set to
SEALED
.Determine the epoch status. The height of the oldest submission’s block is compared with the latest block height. Based on this comparison, the epoch can be classified as
Submitted
,Confirmed
, orFinalized
.Finalize epochs. If the epoch is determined to be
Finalized
, only the oldest valid submission is retained, and all others are deleted.Remove invalid submissions. If the epoch is not
Finalized
, only the submissions identified as invalid or outdated are removed.
By enforcing these conditions, the checkCheckpoints
function ensures that each epoch’s status is correctly maintained and that invalid or forked submissions do not remain in the system.
Test coverage
The x/btccheckpoint package has moderate test coverage (60.0%), with the keeper module having higher coverage (70.6%), while the types module remains mostly untested (3.5%).
ok github.com/babylonlabs-io/babylon/x/btccheckpoint (cached) coverage: 60.0% of statements
ok github.com/babylonlabs-io/babylon/x/btccheckpoint/keeper (cached) coverage: 70.6% of statements
ok github.com/babylonlabs-io/babylon/x/btccheckpoint/types (cached) coverage: 3.5% of statements
Attack surface
The attack surface exposed by btccheckpoint
module is the MsgInsertBTCSpvProof
. The possible issues are invalid checkpoints, which are not on the current active BTC fork; the incorrect finalization of checkpoints that would skip a phase in the checkpoint life cycle; and the incorrect distribution of rewards.