Babylon modules
x/btccheckpoint
This module is used to track checkpoints in Bitcoin.
MsgInsertBTCSpvProof
The MsgInsertBTCSpvProof
message is used to submit information regarding Babylon checkpoints that have been submitted to the Bitcoin ledger. The structure of the message is as follows:
type MsgInsertBTCSpvProof struct {
Submitter string `protobuf:"bytes,1,opt,name=submitter,proto3" json:"submitter,omitempty"`
Proofs []*BTCSpvProof `protobuf:"bytes,2,rep,name=proofs,proto3" json:"proofs,omitempty"`
}
type BTCSpvProof struct {
// Valid bitcoin transaction containing OP_RETURN opcode.
BtcTransaction []byte `protobuf:"bytes,1,opt,name=btc_transaction,json=btcTransaction,proto3" json:"btc_transaction,omitempty"`
// Index of transaction within the block. Index is needed to determine if
// currently hashed node is left or right.
BtcTransactionIndex uint32 `protobuf:"varint,2,opt,name=btc_transaction_index,json=btcTransactionIndex,proto3" json:"btc_transaction_index,omitempty"`
// List of concatenated intermediate merkle tree nodes, without root node and
// leaf node against which we calculate the proof. Each node has 32 byte
// length. Example proof can look like: 32_bytes_of_node1 || 32_bytes_of_node2
// || 32_bytes_of_node3 so the length of the proof will always be divisible
// by 32.
MerkleNodes []byte `protobuf:"bytes,3,opt,name=merkle_nodes,json=merkleNodes,proto3" json:"merkle_nodes,omitempty"`
// Valid btc header which confirms btc_transaction.
// Should have exactly 80 bytes
ConfirmingBtcHeader *github_com_babylonchain_babylon_types.BTCHeaderBytes `protobuf:"bytes,4,opt,name=confirming_btc_header,json=confirmingBtcHeader,proto3,customtype=github.com/babylonchain/babylon/types.BTCHeaderBytes" json:"confirming_btc_header,omitempty"`
}
Each valid checkpoint submission consists of two instances of the BTCSpvProof
structure, which tracks the following:
BtcTransaction
— the BTC transaction itself, which must contain anOP_RETURN
BtcTransactionIndex
— the index of the transaction in the BTC blockMerkleNodes
— a list of Merkle tree nodes used to calculate a Merkle proof that can be used to verify the existence of this transaction in this BTC blockConfirmingBtcHeader
— The block header of the BTC block, used in conjunction withMerkleNodes
to confirm that theBtcTransaction
exists in this block
The x/btclightclient module is used when handling this message. The light client module keeps track of the state of the Bitcoin ledger and can thus be used to verify that the block denoted by ConfirmingBtcHeader
is indeed part of the Bitcoin chain.
The x/checkpointing module is also used when handling this message. The checkpointing module understands the rules that make a checkpoint valid. These rules are not visible to the x/btccheckpoint module, and thus the checkpointing module is consulted to verify that the checkpoint follows the rules correctly. See the x/checkpointing module section for more details.
The MsgInsertBTCSpvProof
message handler otherwise only validates the following:
The new submission must not be a duplicate of a previous submission.
Both transactions must contain the
OP_RETURN
opcode.All the data in the message must be in the correct format (the transactions, the header, the proofs, etc.).
The Merkle proof provided must be valid and prove that the transactions exist in the specified BTC block.
The previous epoch must have valid submissions that are deeper (i.e., more confirmations) than the currently submitted checkpoint in the current epoch.
EndBlocker
The EndBlocker
function has logic that first checks if the light client was updated during the current block execution. An update in this context is the light client's view of the BTC chain either rolling forward (i.e., maintaining the current tip) or rolling backwards (i.e., a new fork with more work has been established).
Each time the light client is updated, the checkpoint module will check the status of all checkpoint submissions and update them accordingly. This will then determine whether the checkpoints are confirmed, finalized, or abandoned.
When checkpoints are finalized, the x/incentives module is used to reward submitters accordingly.
x/btclightclient
This module maintains a chain of Bitcoin blocks and their headers. These are then used to identify the canonical Bitcoin chain, which can be used to verify the inclusion of checkpoints.
MsgInsertHeaders
This MsgInsertHeaders
message is used to submit new BTC block headers to Babylon. The structure of the message is as follows:
type MsgInsertHeaders struct {
Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"`
Headers []github_com_babylonchain_babylon_types.BTCHeaderBytes `protobuf:"bytes,2,rep,name=headers,proto3,customtype=github.com/babylonchain/babylon/types.BTCHeaderBytes" json:"headers,omitempty"`
}
Only specific reporters can submit BTC headers, although if there are no reporters set, then anyone can submit BTC headers.
There are certain validations done on the headers:
The headers being submitted must form a chain.
The headers must extend from the current tip of chain (tracked by the light client).
If the headers do not extend from the tip of chain, then they are for a fork. The light-client state is rolled back to this fork only if it conforms to the following rules:
The parent hash of the very first header must be known to the light client.
The amount of work done for this fork must be larger than the work done at the current tip of chain.
x/btcstaking
This module is responsible for maintaining information about finality providers and BTC delegations under them.
MsgCreateFinalityProvider
The MsgCreateFinalityProvider
message is used to create a finality provider. The structure of the message is as follows:
type MsgCreateFinalityProvider struct {
Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"`
// description defines the description terms for the finality provider
Description *types.Description `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
// commission defines the commission rate of the finality provider
Commission *cosmossdk_io_math.LegacyDec `protobuf:"bytes,3,opt,name=commission,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"commission,omitempty"`
// babylon_pk is the Babylon secp256k1 PK of this finality provider
BabylonPk *secp256k1.PubKey `protobuf:"bytes,4,opt,name=babylon_pk,json=babylonPk,proto3" json:"babylon_pk,omitempty"`
// btc_pk is the Bitcoin secp256k1 PK of this finality provider
// the PK follows encoding in BIP-340 spec
BtcPk *github_com_babylonchain_babylon_types.BIP340PubKey `protobuf:"bytes,5,opt,name=btc_pk,json=btcPk,proto3,customtype=github.com/babylonchain/babylon/types.BIP340PubKey" json:"btc_pk,omitempty"`
// pop is the proof of possession of babylon_pk and btc_pk
Pop *ProofOfPossession `protobuf:"bytes,6,opt,name=pop,proto3" json:"pop,omitempty"`
// master_pub_rand is the master public randomness of the finality provider
// encoded as a base58 string
MasterPubRand string `protobuf:"bytes,7,opt,name=master_pub_rand,json=masterPubRand,proto3" json:"master_pub_rand,omitempty"`
}
A few things are validated when adding a finality provider:
There must not be a duplicate finality provider already added.
The
BtcPk
andBabylonPk
are verified to be owned by theSigner
. This is done by verifying thePop
(proof of possession), specifically by validating that a message has been signed by both these keys.The
Commission
rate must be within a set limit.The
MasterPubRand
number must be a valid random number that corresponds to a public Bitcoin hierarchical deterministic extended key. Thebtcd
library is used for this. See BIP-0032.
If all these conditions are met, the finality provider is added.
MsgEditFinalityProvider
The MsgEditFinalityProvider
message is used to edit an already added finality provider. Only the commission rate and description can be updated. The structure of the message is as follows:
type MsgEditFinalityProvider struct {
// NOTE: this signer needs to correspond to babylon_pk of the finality provider
Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"`
// btc_pk is the Bitcoin secp256k1 PK of the finality provider to be edited
BtcPk []byte `protobuf:"bytes,2,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"`
// description defines the updated description terms for the finality provider
Description *types.Description `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
// commission defines the updated commission rate of the finality provider
Commission *cosmossdk_io_math.LegacyDec `protobuf:"bytes,4,opt,name=commission,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"commission,omitempty"`
}
The commission rate must be within a set limit.
MsgCreateBTCDelegation
The MsgCreateBTCDelegation
message is used to delegate BTC to a finality provider. The structure of this message is massive, so we have removed all developer-added comments from the following excerpt:
type MsgCreateBTCDelegation struct {
Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"`
BabylonPk *secp256k1.PubKey `protobuf:"bytes,2,opt,name=babylon_pk,json=babylonPk,proto3" json:"babylon_pk,omitempty"`
Pop *ProofOfPossession `protobuf:"bytes,3,opt,name=pop,proto3" json:"pop,omitempty"`
BtcPk *github_com_babylonchain_babylon_types.BIP340PubKey `protobuf:"bytes,4,opt,name=btc_pk,json=btcPk,proto3,customtype=github.com/babylonchain/babylon/types.BIP340PubKey" json:"btc_pk,omitempty"`
FpBtcPkList []github_com_babylonchain_babylon_types.BIP340PubKey `protobuf:"bytes,5,rep,name=fp_btc_pk_list,json=fpBtcPkList,proto3,customtype=github.com/babylonchain/babylon/types.BIP340PubKey" json:"fp_btc_pk_list,omitempty"`
StakingTime uint32 `protobuf:"varint,6,opt,name=staking_time,json=stakingTime,proto3" json:"staking_time,omitempty"`
StakingValue int64 `protobuf:"varint,7,opt,name=staking_value,json=stakingValue,proto3" json:"staking_value,omitempty"`
StakingTx *types1.TransactionInfo `protobuf:"bytes,8,opt,name=staking_tx,json=stakingTx,proto3" json:"staking_tx,omitempty"`
SlashingTx *BTCSlashingTx `protobuf:"bytes,9,opt,name=slashing_tx,json=slashingTx,proto3,customtype=BTCSlashingTx" json:"slashing_tx,omitempty"`
DelegatorSlashingSig *github_com_babylonchain_babylon_types.BIP340Signature `protobuf:"bytes,10,opt,name=delegator_slashing_sig,json=delegatorSlashingSig,proto3,customtype=github.com/babylonchain/babylon/types.BIP340Signature" json:"delegator_slashing_sig,omitempty"`
UnbondingTime uint32 `protobuf:"varint,11,opt,name=unbonding_time,json=unbondingTime,proto3" json:"unbonding_time,omitempty"`
UnbondingTx []byte `protobuf:"bytes,12,opt,name=unbonding_tx,json=unbondingTx,proto3" json:"unbonding_tx,omitempty"`
UnbondingValue int64 `protobuf:"varint,13,opt,name=unbonding_value,json=unbondingValue,proto3" json:"unbonding_value,omitempty"`
UnbondingSlashingTx *BTCSlashingTx `protobuf:"bytes,14,opt,name=unbonding_slashing_tx,json=unbondingSlashingTx,proto3,customtype=BTCSlashingTx" json:"unbonding_slashing_tx,omitempty"`
DelegatorUnbondingSlashingSig *github_com_babylonchain_babylon_types.BIP340Signature `protobuf:"bytes,15,opt,name=delegator_unbonding_slashing_sig,json=delegatorUnbondingSlashingSig,proto3,customtype=github.com/babylonchain/babylon/types.BIP340Signature" json:"delegator_unbonding_slashing_sig,omitempty"`
}
There are extensive checks here prior to a delegation being successful.
The
UnbondingTime
must be greater than a preset minimum.Both
BabylonPk
andBtcPk
are checked for proof of possession against thePop
, similar toMsgCreateFinalityProvider
.Ensure all finality providers in
FpBtcPkList
are known to Babylon (i.e., have been created before).Ensure none of the finality providers are currently slashed and that the epoch they were created in is finalized.
The
StakingTx
must be unique (i.e., there must not be a delegation using this staking TX already).The
StakingValue
must match the output of theStakingTx
.The
btclightclient
module must be aware of the block that theStakingTx
claims to be in.The
StakingTx
must bek
confirmations deep (this is configurable).The
StakingTx
time lock must have more than a certain amount of BTC blocks left.The
StakingTx
is then verified to actually be included in the BTC block that it claims to be in.The
SlashingTx
is verified to be consistent with theStakingTx
. These checks boil down to the following:It must have exactly one input, which points to the staking transaction.
It is nonreplaceable (see replace-by-fee↗).
The lock time must be zero.
It must have exactly two outputs — one that pays to the slashing address and one that pays to an unspendable taproot address, which effectively locks the funds.
It must have a transaction fee larger than a preset minimum.
The
DelegatorSlashingSig
is verified to be a valid signature that signs theStakingTx
's slashing path.The
UnbondingTx
's first input is verified to be pointing to theStakingTx
, similar to theSlashingTx
.The
StakingTx
's output index must match theUnbondingTx
's input's output index. This seems mostly to be a sanity check because the previous check is enough here.The
UnbondingTx
is then verified to be consistent with theUnbondingSlashingTx
. This is the same verification done onSlashingTx
.The
DelegatorUnbondingSlashingSig
is verified to be a valid signature that signs theUnbondingTx
's slashing path.The
UnbondingTx
's output is verified to be greater than zero and greater than a set percentage of theStakingTx
's output value.
Once all of these extensive checks pass, the BTC delegation is successfully created and stored.
MsgAddCovenantSigs
The MsgAddCovenantSigs
message is used by covenant members to add covenant signatures to BTC delegations. Without enough covenant signatures to reach quorum, the BTC delegations can never become active.
The structure of the message is as follows:
type MsgAddCovenantSigs struct {
Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"`
// pk is the BTC public key of the covenant member
Pk *github_com_babylonchain_babylon_types.BIP340PubKey `protobuf:"bytes,2,opt,name=pk,proto3,customtype=github.com/babylonchain/babylon/types.BIP340PubKey" json:"pk,omitempty"`
// staking_tx_hash is the hash of the staking tx.
// It uniquely identifies a BTC delegation
StakingTxHash string `protobuf:"bytes,3,opt,name=staking_tx_hash,json=stakingTxHash,proto3" json:"staking_tx_hash,omitempty"`
// sigs is a list of adaptor signatures of the covenant
// the order of sigs should respect the order of finality providers
// of the corresponding delegation
SlashingTxSigs [][]byte `protobuf:"bytes,4,rep,name=slashing_tx_sigs,json=slashingTxSigs,proto3" json:"slashing_tx_sigs,omitempty"`
// unbonding_tx_sig is the signature of the covenant on the unbonding tx submitted to babylon
// the signature follows encoding in BIP-340 spec
UnbondingTxSig *github_com_babylonchain_babylon_types.BIP340Signature `protobuf:"bytes,5,opt,name=unbonding_tx_sig,json=unbondingTxSig,proto3,customtype=github.com/babylonchain/babylon/types.BIP340Signature" json:"unbonding_tx_sig,omitempty"`
// slashing_unbonding_tx_sigs is a list of adaptor signatures of the covenant
// on slashing tx corresponding to unbonding tx submitted to babylon
// the order of sigs should respect the order of finality providers
// of the corresponding delegation
SlashingUnbondingTxSigs [][]byte `protobuf:"bytes,6,rep,name=slashing_unbonding_tx_sigs,json=slashingUnbondingTxSigs,proto3" json:"slashing_unbonding_tx_sigs,omitempty"`
}
The checks performed here are as follows:
The
Pk
must be a covenant PK. This is stored in the module parameters.The BTC delegation specified by
StakingTxHash
must not already be signed by thisPk
.The BTC delegation specified by
StakingTxHash
must not have already reached quorum.The BTC delegation specified by
StakingTxHash
must not have already expired.The number of
SlashingTxSigs
must match the number of finality providers on the BTC delegation.The number of
SlashingUnbondingTxSigs
must match the number of finality providers on the BTC delegation.Each signature is verified over the BTC delegation's staking TX's slashing path.
Each signature is verified over the BTC delegation's unbonding TX's slashing path.
Once these checks succeed, the covenant signatures are added to the BTC delegation specified by StakingTxHash
.
MsgBTCUndelegate
The MsgBTCUndelegate
message is used to trigger unbonding on an active BTC delegation. The structure of the message is as follows:
type MsgBTCUndelegate struct {
Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"`
// staking_tx_hash is the hash of the staking tx.
// It uniquely identifies a BTC delegation
StakingTxHash string `protobuf:"bytes,2,opt,name=staking_tx_hash,json=stakingTxHash,proto3" json:"staking_tx_hash,omitempty"`
// unbonding_tx_sig is the signature of the staker on the unbonding tx submitted to babylon
// the signature follows encoding in BIP-340 spec
UnbondingTxSig *github_com_babylonchain_babylon_types.BIP340Signature `protobuf:"bytes,3,opt,name=unbonding_tx_sig,json=unbondingTxSig,proto3,customtype=github.com/babylonchain/babylon/types.BIP340Signature" json:"unbonding_tx_sig,omitempty"`
}
There are only two main checks performed here:
The BTC delegation specified by
StakingTxHash
must be in the active state.The
UnbondingTxSig
must be a valid signature for the unbonding transaction.
If both of these checks pass, then the BTC delegation is unbonded.
MsgSelectiveSlashingEvidence
The MsgSelectiveSlashingEvidence
message is used to handle evidence of selective slashing that is triggered by a finality provider. The structure of the message is as follows:
type MsgSelectiveSlashingEvidence struct {
Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"`
// staking_tx_hash is the hash of the staking tx.
// It uniquely identifies a BTC delegation
StakingTxHash string `protobuf:"bytes,2,opt,name=staking_tx_hash,json=stakingTxHash,proto3" json:"staking_tx_hash,omitempty"`
// recovered_fp_btc_sk is the BTC SK of the finality provider who
// launches the selective slashing offence. The SK is recovered by
// using a covenant adaptor signature and the corresponding Schnorr
// signature
RecoveredFpBtcSk []byte `protobuf:"bytes,3,opt,name=recovered_fp_btc_sk,json=recoveredFpBtcSk,proto3" json:"recovered_fp_btc_sk,omitempty"`
}
Selective slashing in this case is when a finality provider becomes adversarial and decides to selectively slash a BTC delegation incorrectly. The covenant can then decide to slash the finality provider using this message.
BeginBlocker
The BeginBlocker
function for the x/btcstaking module does two main things:
Index the BTC height. For every Babylon block, the
BeginBlocker
function maps the Babylon block height to the current tip BTC block height.Update voting power distribution. For every Babylon block, there are voting power changes based on new finality providers being created, BTC delegations being added and unbonded, and finality providers being slashed. These voting power changes are recorded and saved in the
BeginBlocker
function at the start of every block.
x/checkpointing
This module is responsible for maintaining the status of Babylon Bitcoin checkpoints. It handles requests for registering validators with BLS keys and constructing checkpoints out of BLS signatures provided by these validators.
MsgWrappedCreateValidator
The MsgWrappedCreateValidator
message is a wrapped version of the Cosmos SDK's x/staking module's MsgCreateValidator
message. This wrapped version performs an extra BLS key registration and has the following structure:
type MsgWrappedCreateValidator struct {
Key *BlsKey `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
MsgCreateValidator *types.MsgCreateValidator `protobuf:"bytes,2,opt,name=msg_create_validator,json=msgCreateValidator,proto3" json:"msg_create_validator,omitempty"`
}
Refer to the x/staking module in the Cosmos SDK to see how that message handler works. The BLS key registration has the following checks:
The same validator must not be able to register multiple BLS public keys.
Two different validators must not be able to register the same BLS public key.
If these two checks pass, then a validator is successfully added using the x/staking message handler. This message handler is triggered by the x/epoching module's EndBlocker
later on.
Checkpoint checks
The x/btccheckpoint module delegates a lot of the checkpoint verification to the x/checkpointing module. These checks are done through the VerifyCheckpoint()
function.
First, the checkpoint structure is as follows:
// RawCheckpoint wraps the BLS multi sig with metadata
type RawCheckpoint struct {
// epoch_num defines the epoch number the raw checkpoint is for
EpochNum uint64 `protobuf:"varint,1,opt,name=epoch_num,json=epochNum,proto3" json:"epoch_num,omitempty"`
// block_hash defines the 'BlockID.Hash', which is the hash of
// the block that individual BLS sigs are signed on
BlockHash *BlockHash `protobuf:"bytes,2,opt,name=block_hash,json=blockHash,proto3,customtype=BlockHash" json:"block_hash,omitempty"`
// bitmap defines the bitmap that indicates the signers of the BLS multi sig
Bitmap []byte `protobuf:"bytes,3,opt,name=bitmap,proto3" json:"bitmap,omitempty"`
// bls_multi_sig defines the multi sig that is aggregated from individual BLS
// sigs
BlsMultiSig *github_com_babylonchain_babylon_crypto_bls12381.Signature `protobuf:"bytes,4,opt,name=bls_multi_sig,json=blsMultiSig,proto3,customtype=github.com/babylonchain/babylon/crypto/bls12381.Signature" json:"bls_multi_sig,omitempty"`
}
The checks on this are as follows:
The
BlockHash
must be a byte array of size 32 and must not benil
.The
BlsMultiSig
must be a byte array of size 48 and must not benil
.If this checkpoint is the same as the locally stored checkpoint and the local checkpoint's status is not waiting for BLS signatures to be accumulated, then the checkpoint is saved as is.
Otherwise, the validator set for the current epoch is fetched, and it ensures that the
BlsMultiSig
is a valid signature and that enough voting power has been accumulated.If the above check passes but the
BlockHash
does not match the current local checkpoint, then the checkpoint is conflicting and rejected. This indicates the existence of a fork.
BeginBlocker
The BeginBlocker
function for the x/checkpointing module is really simple — if the current Babylon block is the first block of a new epoch, then it initializes the new epoch's validator set and stores it in the blockchain.
x/epoching
The x/epoching module handles epoched staking. This reduces the frequency of needing to update the validator set (which otherwise updates every block in Cosmos).
This module introduces five messages that are wrapped versions of messages in the Cosmos SDK's x/staking module:
MsgDelegate
for delegating coins from a delegator to a validatorMsgBeginRedelegate
for redelegating coins from a delegator and source validator to a destination validatorMsgUndelegate
for undelegating from a delegator and a validatorMsgCancelUnbondingDelegation
for canceling an unbonding delegation of a delegator
The module prevents these messages from being used directly using an AnteHandler. However, this AnteHandler is not sufficient to prevent these messages from being used. See Finding ref↗ for more details.
BeginBlocker
The BeginBlocker
function for this module handles a few things. Note that all of these are only done if the current block is the first block of a new epoch.
It increments the epoch counter.
It records the block hash of the last block of the previous epoch.
It initializes the message queue for the new epoch.
It resets the slashed voting power for the new epoch.
It initializes the new validator set.
EndBlocker
The EndBlocker
function for this module handles a few things. Note that all of these are only done if the current block is the last block of the current epoch.
It records the block-header time of this last epoch block.
It handles all queued messages. These are the wrapped versions of the staking-related messages discussed above, which are only intended to be handled once per epoch.
It commits any validator-set changes to the store so the
BeginBlocker
for the next block (i.e., the first block of the new epoch) can take them into account.
x/finality
The x/finality module maintains finality of blocks and handles slashing of finality providers that equivocate (i.e., vote for finality on two blocks at the same height).
MsgAddFinalitySig
The MsgAddFinalitySig
message is used to add a finality vote on a specific block. The structure of the message is as follows:
type MsgAddFinalitySig struct {
Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"`
// fp_btc_pk is the BTC PK of the finality provider that casts this vote
FpBtcPk *github_com_babylonchain_babylon_types.BIP340PubKey `protobuf:"bytes,2,opt,name=fp_btc_pk,json=fpBtcPk,proto3,customtype=github.com/babylonchain/babylon/types.BIP340PubKey" json:"fp_btc_pk,omitempty"`
// block_height is the height of the voted block
BlockHeight uint64 `protobuf:"varint,3,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"`
// pub_rand is the public randomness committed at this height
PubRand *github_com_babylonchain_babylon_types.SchnorrPubRand `protobuf:"bytes,4,opt,name=pub_rand,json=pubRand,proto3,customtype=github.com/babylonchain/babylon/types.SchnorrPubRand" json:"pub_rand,omitempty"`
// proof is the proof that the given public randomness is committed under the commitment
Proof *crypto.Proof `protobuf:"bytes,5,opt,name=proof,proto3" json:"proof,omitempty"`
// block_app_hash is the AppHash of the voted block
BlockAppHash []byte `protobuf:"bytes,6,opt,name=block_app_hash,json=blockAppHash,proto3" json:"block_app_hash,omitempty"`
// finality_sig is the finality signature to this block
// where finality signature is an EOTS signature, i.e.,
// the `s` in a Schnorr signature `(r, s)`
// `r` is the public randomness that is already committed by the finality provider
FinalitySig *github_com_babylonchain_babylon_types.SchnorrEOTSSig `protobuf:"bytes,7,opt,name=finality_sig,json=finalitySig,proto3,customtype=github.com/babylonchain/babylon/types.SchnorrEOTSSig" json:"finality_sig,omitempty"`
}
In order to add a finality vote, the following checks must pass:
The finality provider denoted by
FpBtcPk
must exist and have voting power in the current block height.The finality provider must not have cast a vote for this block height already.
The public randomness committment denoted by
PubRand
must match the committed public randomness at the current block height. This is verified using theFinalitySig
signature.The finality provider must not be voting for a known forked block. Otherwise, they are slashed.
The finality provider must not have already voted for a fork in the current block height. If they have (and they are now voting for the nonforked block), then they are slashed again.
The fifth step might seem redundant since slashing in Step 4 is supposed to remove the voting power for the finality provider. However, the voting power is actually removed in the BeginBlock
function of the next block (which is where the slash event is handled), which is why Step 5 is still necessary.
MsgCommitPubRandList
The MsgCommitPubRandList
is used by a finality provider to commit a list of EOTS public randomness. See the MsgAddFinalitySig
message to see how these are used.
The structure of the message is as follows:
type MsgCommitPubRandList struct {
Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"`
// fp_btc_pk is the BTC PK of the finality provider that commits the public randomness
FpBtcPk *github_com_babylonchain_babylon_types.BIP340PubKey `protobuf:"bytes,2,opt,name=fp_btc_pk,json=fpBtcPk,proto3,customtype=github.com/babylonchain/babylon/types.BIP340PubKey" json:"fp_btc_pk,omitempty"`
// start_height is the start block height of the list of public randomness
StartHeight uint64 `protobuf:"varint,3,opt,name=start_height,json=startHeight,proto3" json:"start_height,omitempty"`
// num_pub_rand is the number of public randomness committed
NumPubRand uint64 `protobuf:"varint,4,opt,name=num_pub_rand,json=numPubRand,proto3" json:"num_pub_rand,omitempty"`
// commitment is the commitment of these public randomness
// currently it's the root of the Merkle tree that includes these public randomness
Commitment []byte `protobuf:"bytes,5,opt,name=commitment,proto3" json:"commitment,omitempty"`
// sig is the signature on (start_height || num_pub_rand || commitment) signed by
// SK corresponding to fp_btc_pk. This prevents others to commit public
// randomness on behalf of fp_btc_pk
// TODO: another option is to restrict signer to correspond to fp_btc_pk. This restricts
// the tx submitter to be the holder of fp_btc_pk. Decide this later
Sig *github_com_babylonchain_babylon_types.BIP340Signature `protobuf:"bytes,6,opt,name=sig,proto3,customtype=github.com/babylonchain/babylon/types.BIP340Signature" json:"sig,omitempty"`
}
The message handler has these checks:
The
NumPubRand
must be greater than the minimum number of public randomness required. This is a chain parameter.The finality provider specified by
FpBtcPk
must be valid and registered.The
Sig
must be valid and verified over theCommitment
.If this is the first time this finality provider is committing public randomness, then nothing else needs to be done. Otherwise, the previous public randomness needs to be checked to ensure that the
StartHeight
is higher than the ending height of the previous randomness.
EndBlocker
The EndBlocker
function for the x/finality module essentially checks if there are enough votes for blocks that are to be finalized. If there are, the blocks are set as finalized and stored. If there are not enough votes, the blocks are left unfinalized and the process continues on for each Babylon block.
x/incentive
The x/incentive module handles distributing rewards to the stakeholders. The stakeholders in this context are the following:
Submitters — These stakeholders submit Babylon checkpoints to Bitcoin as Bitcoin transactions.
Reporters — These stakeholders automatically report Bitcoin headers and information about submitted Babylon checkpoints back to Babylon using Babylon transactions.
Finality Providers — These stakeholders participate in voting for finality on blocks.
BTC delegators — These stakeholders delegate their BTC to finality providers.
MsgWithdrawReward
The MsgWithdrawReward
message can be used by the aforementioned stakeholders to withdraw any accrued reward. The structure of this message is as follows:
// MsgWithdrawReward defines a message for withdrawing reward of a stakeholder.
type MsgWithdrawReward struct {
// {submitter, reporter, finality_provider, btc_delegation}
Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
// address is the address of the stakeholder in bech32 string
// signer of this msg has to be this address
Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"`
}
The module keeps track of rewards using gauges. Each stakeholder type gets its own reward gauge, which has the following structure:
// RewardGauge is an object that stores rewards distributed to a BTC staking/timestamping stakeholder
// code adapted from https://github.com/osmosis-labs/osmosis/blob/v18.0.0/proto/osmosis/incentives/gauge.proto
type RewardGauge struct {
// coins are coins that have been in the gauge
// Can have multiple coin denoms
Coins github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,1,rep,name=coins,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"coins"`
// withdrawn_coins are coins that have been withdrawn by the stakeholder already
WithdrawnCoins github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,2,rep,name=withdrawn_coins,json=withdrawnCoins,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"withdrawn_coins"`
}
Each stakeholder can use the MsgWithdrawReward
message to withdraw their share of the rewards (assuming there are any rewards accrued).
BeginBlocker
The BeginBlocker
function is short and simple — it takes a portion of coins in the fee-collector account and distributes them out to the Bitcoin stakers through a rewards gauge.
x/monitor
The x/monitor module is responsible for maintaining certain monitoring-related functionality. These include the following:
Monitoring when checkpoints are received at specific block heights
Monitoring the x/btclightclient height at the end of an epoch
Updating the x/btclightclient height at the end of an epoch
The module otherwise does not have any messages, begin blockers, or end blockers.
x/zoneconcierge
The x/zoneconcierge module is responsible for generating BTC time stamps of headers from other POS blockchains. This allows these other POS chains to integrate with Babylon, because forking these other POS blockchains will be just as hard as forking Bitcoin.
The module receives IBC packets containing the POS blockchain's headers. It uses these headers to construct a BTCTimestamp
structure, which is shown below:
type BTCTimestamp struct {
// header is the last CZ header in the finalized Babylon epoch
Header *IndexedHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
// btc_headers is BTC headers between
// - the block AFTER the common ancestor of BTC tip at epoch `lastFinalizedEpoch-1` and BTC tip at epoch `lastFinalizedEpoch`
// - BTC tip at epoch `lastFinalizedEpoch`
// where `lastFinalizedEpoch` is the last finalised epoch in Babylon
BtcHeaders []*types.BTCHeaderInfo `protobuf:"bytes,2,rep,name=btc_headers,json=btcHeaders,proto3" json:"btc_headers,omitempty"`
// epoch_info is the metadata of the sealed epoch
EpochInfo *types1.Epoch `protobuf:"bytes,3,opt,name=epoch_info,json=epochInfo,proto3" json:"epoch_info,omitempty"`
// raw_checkpoint is the raw checkpoint that seals this epoch
RawCheckpoint *types2.RawCheckpoint `protobuf:"bytes,4,opt,name=raw_checkpoint,json=rawCheckpoint,proto3" json:"raw_checkpoint,omitempty"`
// btc_submission_key is position of two BTC txs that include the raw checkpoint of this epoch
BtcSubmissionKey *types3.SubmissionKey `protobuf:"bytes,5,opt,name=btc_submission_key,json=btcSubmissionKey,proto3" json:"btc_submission_key,omitempty"`
//
//Proofs that the header is finalized
Proof *ProofFinalizedChainInfo `protobuf:"bytes,6,opt,name=proof,proto3" json:"proof,omitempty"`
}
This BTCTimestamp
structure is then sent to other Cosmos zones (i.e., other POS chains). This is essentially a way for the other POS chains to checkpoint themselves to Babylon, as Babylon then knows that the block headers from those POS blockchains are finalized with the same degree of security as Bitcoin.