Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add validation that there is only one fp key in delegation #270

Merged
merged 2 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)

## Unreleased


### Bug fixes

- [#270](https://github.com/babylonlabs-io/babylon/pull/270) Validate there is only
one finality provider key in the staking request

## v0.16.0

### Improvements
Expand Down
4 changes: 4 additions & 0 deletions x/btcstaking/types/create_delegation_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,10 @@ func ParseCreateDelegationMessage(msg *MsgCreateBTCDelegation) (*ParsedCreateDel
return nil, ErrDuplicatedFp
}

if len(fpPKs.PublicKeysBbnFormat) != 1 {
return nil, ErrTooManyFpKeys
}

// 7. Parse staker public key
stakerPK, err := NewParsedPublicKey(msg.BtcPk)

Expand Down
15 changes: 8 additions & 7 deletions x/btcstaking/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ var (
ErrInvalidDelegationState = errorsmod.Register(ModuleName, 1113, "Unexpected delegation state")
ErrInvalidUnbondingTx = errorsmod.Register(ModuleName, 1114, "the BTC unbonding tx is not valid")
ErrEmptyFpList = errorsmod.Register(ModuleName, 1115, "the finality provider list is empty")
ErrInvalidProofOfPossession = errorsmod.Register(ModuleName, 1116, "the proof of possession is not valid")
ErrDuplicatedFp = errorsmod.Register(ModuleName, 1117, "the staking request contains duplicated finality provider public key")
ErrInvalidBTCUndelegateReq = errorsmod.Register(ModuleName, 1118, "invalid undelegation request")
ErrParamsNotFound = errorsmod.Register(ModuleName, 1119, "the parameters are not found")
ErrFpAlreadyJailed = errorsmod.Register(ModuleName, 1120, "the finality provider has already been jailed")
ErrFpNotJailed = errorsmod.Register(ModuleName, 1121, "the finality provider is not jailed")
ErrDuplicatedCovenantSig = errorsmod.Register(ModuleName, 1122, "the covenant signature is already submitted")
ErrTooManyFpKeys = errorsmod.Register(ModuleName, 1116, "the finality provider list contains too many public keys, it must contain exactly one")
ErrInvalidProofOfPossession = errorsmod.Register(ModuleName, 1117, "the proof of possession is not valid")
ErrDuplicatedFp = errorsmod.Register(ModuleName, 1118, "the staking request contains duplicated finality provider public key")
ErrInvalidBTCUndelegateReq = errorsmod.Register(ModuleName, 1119, "invalid undelegation request")
ErrParamsNotFound = errorsmod.Register(ModuleName, 1120, "the parameters are not found")
ErrFpAlreadyJailed = errorsmod.Register(ModuleName, 1121, "the finality provider has already been jailed")
ErrFpNotJailed = errorsmod.Register(ModuleName, 1122, "the finality provider is not jailed")
ErrDuplicatedCovenantSig = errorsmod.Register(ModuleName, 1123, "the covenant signature is already submitted")
)
119 changes: 89 additions & 30 deletions x/btcstaking/types/validate_parsed_message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,10 @@ func createMsgDelegationForParams(

func TestValidateParsedMessageAgainstTheParams(t *testing.T) {
tests := []struct {
name string
fn func(r *rand.Rand, t *testing.T) (*types.MsgCreateBTCDelegation, *types.Params, *btcckpttypes.Params)
err error
name string
fn func(r *rand.Rand, t *testing.T) (*types.MsgCreateBTCDelegation, *types.Params, *btcckpttypes.Params)
errParsing error
errValidation error
}{
{
name: "valid create delegation message",
Expand All @@ -246,7 +247,36 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: nil,
errParsing: nil,
errValidation: nil,
},
{
name: "empty finality provider list",
fn: func(r *rand.Rand, t *testing.T) (*types.MsgCreateBTCDelegation, *types.Params, *btcckpttypes.Params) {
params := testStakingParams(r, t)
checkpointParams := testCheckpointParams()
msg, _ := createMsgDelegationForParams(r, t, params, checkpointParams)

msg.FpBtcPkList = []bbn.BIP340PubKey{}

return msg, params, checkpointParams
},
errParsing: types.ErrEmptyFpList,
errValidation: nil,
},
{
name: "too many finality providers",
fn: func(r *rand.Rand, t *testing.T) (*types.MsgCreateBTCDelegation, *types.Params, *btcckpttypes.Params) {
params := testStakingParams(r, t)
checkpointParams := testCheckpointParams()
msg, _ := createMsgDelegationForParams(r, t, params, checkpointParams)

msg.FpBtcPkList = append(msg.FpBtcPkList, *msg.BtcPk)

return msg, params, checkpointParams
},
errParsing: types.ErrTooManyFpKeys,
errValidation: nil,
},
{
name: "too low unbonding time",
Expand All @@ -259,7 +289,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidUnbondingTx,
errParsing: nil,
errValidation: types.ErrInvalidUnbondingTx,
},
{
name: "Msg.BtcPk do not match pk in staking transaction",
Expand All @@ -277,7 +308,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidStakingTx,
errParsing: nil,
errValidation: types.ErrInvalidStakingTx,
},
{
name: "Msg.StakingTime do not match staking time committed in staking transaction",
Expand All @@ -290,7 +322,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidStakingTx,
errParsing: nil,
errValidation: types.ErrInvalidStakingTx,
},
{
name: "Msg.StakingValue do not match staking value committed in staking transaction",
Expand All @@ -303,7 +336,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidStakingTx.Wrap("staking tx does not contain expected staking output"),
errParsing: nil,
errValidation: types.ErrInvalidStakingTx.Wrap("staking tx does not contain expected staking output"),
},
{
name: "Msg.StakingValue is lower than params.MinStakingValueSat",
Expand All @@ -316,7 +350,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidStakingTx,
errParsing: nil,
errValidation: types.ErrInvalidStakingTx,
},
{
name: "Msg.StakingValue is higher than params.MinStakingValueSat",
Expand All @@ -329,7 +364,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidStakingTx,
errParsing: nil,
errValidation: types.ErrInvalidStakingTx,
},
{
name: "Msg.StakingTime is lower than params.MinStakingTimeBlocks",
Expand Down Expand Up @@ -369,7 +405,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidStakingTx,
errParsing: nil,
errValidation: types.ErrInvalidStakingTx,
},
{
name: "Msg.StakingTime is higher than params.MinStakingTimeBlocks",
Expand Down Expand Up @@ -409,7 +446,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidStakingTx,
errParsing: nil,
errValidation: types.ErrInvalidStakingTx,
},
{
name: "Msg.StakingValue is lower than params.MinStakingValueSat",
Expand All @@ -435,7 +473,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidStakingTx,
errParsing: nil,
errValidation: types.ErrInvalidStakingTx,
},
{
name: "Msg.StakingValue is higher than params.MaxStakingValueSat",
Expand All @@ -461,7 +500,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidStakingTx,
errParsing: nil,
errValidation: types.ErrInvalidStakingTx,
},
{
name: "Msg.SlashingTx have invalid pk script",
Expand All @@ -487,7 +527,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidStakingTx,
errParsing: nil,
errValidation: types.ErrInvalidStakingTx,
},
{
name: "Msg.SlashingTx does not point to staking tx hash",
Expand All @@ -514,7 +555,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidStakingTx,
errParsing: nil,
errValidation: types.ErrInvalidStakingTx,
},
{
name: "Msg.SlashingTx does not point to staking tx output index",
Expand All @@ -534,7 +576,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidStakingTx,
errParsing: nil,
errValidation: types.ErrInvalidStakingTx,
},
{
name: "Msg.DelegatorSlashingSig is invalid signature",
Expand All @@ -557,7 +600,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidSlashingTx,
errParsing: nil,
errValidation: types.ErrInvalidSlashingTx,
},
{
name: "Msg.UnbondingSlashingTx does not point to unbonding tx hash",
Expand All @@ -584,7 +628,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidUnbondingTx,
errParsing: nil,
errValidation: types.ErrInvalidUnbondingTx,
},
{
name: "Msg.UnbondingSlashingTx does not point to unbonding tx output index",
Expand All @@ -604,7 +649,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidUnbondingTx,
errParsing: nil,
errValidation: types.ErrInvalidUnbondingTx,
},
{
name: "Msg.UnbondingSlashingTx have invalid pk script",
Expand All @@ -630,7 +676,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidUnbondingTx,
errParsing: nil,
errValidation: types.ErrInvalidUnbondingTx,
},
{
name: "Msg.DelegatorUnbondingSlashingSig is invalid signature",
Expand All @@ -653,7 +700,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidSlashingTx,
errParsing: nil,
errValidation: types.ErrInvalidSlashingTx,
},
{
name: "Msg.UnbondingTx does not point to staking tx hash",
Expand Down Expand Up @@ -691,7 +739,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidUnbondingTx,
errParsing: nil,
errValidation: types.ErrInvalidUnbondingTx,
},
{
name: "Msg.UnbondingTx does not point to staking tx output index",
Expand Down Expand Up @@ -722,7 +771,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidUnbondingTx,
errParsing: nil,
errValidation: types.ErrInvalidUnbondingTx,
},
{
name: "Msg.UnbondingTx does not have required fee",
Expand Down Expand Up @@ -756,7 +806,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidUnbondingTx,
errParsing: nil,
errValidation: types.ErrInvalidUnbondingTx,
},
{
name: "Msg.UnbondingTx has more than one output",
Expand All @@ -778,7 +829,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidUnbondingTx.Wrap("unbonding tx is not a valid pre-signed transaction: tx must have exactly 1 outputs"),
errParsing: nil,
errValidation: types.ErrInvalidUnbondingTx.Wrap("unbonding tx is not a valid pre-signed transaction: tx must have exactly 1 outputs"),
},
{
name: "Msg.UnbondingTx unbonding value in the msg does not match the output value in the unbonding tx",
Expand Down Expand Up @@ -811,7 +863,8 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {

return msg, params, checkpointParams
},
err: types.ErrInvalidUnbondingTx.Wrap("the unbonding output value is not expected"),
errParsing: nil,
errValidation: types.ErrInvalidUnbondingTx.Wrap("the unbonding output value is not expected"),
},
}
for _, tt := range tests {
Expand All @@ -821,18 +874,24 @@ func TestValidateParsedMessageAgainstTheParams(t *testing.T) {
msg, params, checkpointParams := tt.fn(r, t)

parsed, err := types.ParseCreateDelegationMessage(msg)
require.NoError(t, err)

if tt.errParsing != nil {
require.Error(t, err)
require.ErrorAs(t, err, &tt.errParsing)
return
}

require.NoError(t, err)
got, err := types.ValidateParsedMessageAgainstTheParams(
parsed,
params,
checkpointParams,
&chaincfg.MainNetParams,
)

if tt.err != nil {
if tt.errValidation != nil {
require.Error(t, err)
require.ErrorAs(t, err, &tt.err)
require.ErrorAs(t, err, &tt.errValidation)
} else {
require.NoError(t, err)
require.NotNil(t, got)
Expand Down