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

feat(ADR-025): Enable jailing and unjailing #80

Merged
merged 3 commits into from
Sep 19, 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
1 change: 0 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,6 @@ func (app *BabylonApp) setupUpgradeHandlers() {
upgrade.CreateUpgradeHandler(
app.ModuleManager,
app.configurator,
app.BaseApp,
app.AppKeepers,
),
)
Expand Down
5 changes: 3 additions & 2 deletions app/upgrades/signetlaunch/btcstaking_params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ package signetlaunch_test
import (
"testing"

"github.com/stretchr/testify/require"

"github.com/babylonlabs-io/babylon/app"
v1 "github.com/babylonlabs-io/babylon/app/upgrades/signetlaunch"
"github.com/stretchr/testify/require"
)

func TestHardCodedParamsAreValid(t *testing.T) {
func TestHardCodedBtcStakingParamsAreValid(t *testing.T) {
bbnApp := app.NewTmpBabylonApp()
loadedParamas, err := v1.LoadBtcStakingParamsFromData(bbnApp.AppCodec())
require.NoError(t, err)
Expand Down
11 changes: 11 additions & 0 deletions app/upgrades/signetlaunch/finality_params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package signetlaunch

// TODO Some default parameters. Consider how to switch those depending on network:
// mainnet, testnet, devnet etc.
const FinalityParamStr = `{
"signed_blocks_window": 100,
"finality_sig_timeout": 3,
"min_signed_per_window": "0.1",
"min_pub_rand": 100,
"jail_duration": "86400s"
}`
17 changes: 17 additions & 0 deletions app/upgrades/signetlaunch/finality_params_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package signetlaunch_test

import (
"testing"

"github.com/stretchr/testify/require"

"github.com/babylonlabs-io/babylon/app"
v1 "github.com/babylonlabs-io/babylon/app/upgrades/signetlaunch"
)

func TestHardCodedFinalityParamsAreValid(t *testing.T) {
bbnApp := app.NewTmpBabylonApp()
loadedParamas, err := v1.LoadFinalityParamsFromData(bbnApp.AppCodec())
require.NoError(t, err)
require.NoError(t, loadedParamas.Validate())
}
36 changes: 35 additions & 1 deletion app/upgrades/signetlaunch/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import (
btclighttypes "github.com/babylonlabs-io/babylon/x/btclightclient/types"
btcstkkeeper "github.com/babylonlabs-io/babylon/x/btcstaking/keeper"
btcstktypes "github.com/babylonlabs-io/babylon/x/btcstaking/types"
finalitykeeper "github.com/babylonlabs-io/babylon/x/finality/keeper"
finalitytypes "github.com/babylonlabs-io/babylon/x/finality/types"
)

var Upgrade = upgrades.Upgrade{
Expand All @@ -42,7 +44,6 @@ type DataSignedFps struct {
func CreateUpgradeHandler(
mm *module.Manager,
cfg module.Configurator,
app upgrades.BaseAppParamManager,
keepers *keepers.AppKeepers,
) upgradetypes.UpgradeHandler {
return func(context context.Context, _plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
Expand All @@ -58,6 +59,10 @@ func CreateUpgradeHandler(
panic(err)
}

if err := upgradeFinalityParameters(ctx, keepers.EncCfg, &keepers.FinalityKeeper); err != nil {
panic(err)
}

if err := propLaunch(ctx, keepers.EncCfg, &keepers.BTCLightClientKeeper, &keepers.BTCStakingKeeper); err != nil {
panic(err)
}
Expand All @@ -78,6 +83,18 @@ func LoadBtcStakingParamsFromData(cdc codec.Codec) (btcstktypes.Params, error) {
return params, nil
}

func LoadFinalityParamsFromData(cdc codec.Codec) (finalitytypes.Params, error) {
buff := bytes.NewBufferString(FinalityParamStr)

var params finalitytypes.Params
err := cdc.UnmarshalJSON(buff.Bytes(), &params)
if err != nil {
return finalitytypes.Params{}, err
}

return params, nil
}

func upgradeBtcStakingParameters(
ctx sdk.Context,
e *appparams.EncodingConfig,
Expand All @@ -97,6 +114,23 @@ func upgradeBtcStakingParameters(
return k.OverwriteParamsAtVersion(ctx, 0, params)
}

func upgradeFinalityParameters(
ctx sdk.Context,
e *appparams.EncodingConfig,
k *finalitykeeper.Keeper,
) error {

cdc := e.Codec

params, err := LoadFinalityParamsFromData(cdc)

if err != nil {
return err
}

return k.SetParams(ctx, params)
}

// propLaunch runs the proposal of launch that is meant to insert new BTC Headers.
func propLaunch(
ctx sdk.Context,
Expand Down
29 changes: 19 additions & 10 deletions app/upgrades/signetlaunch/upgrades_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import (
"cosmossdk.io/core/header"
"cosmossdk.io/x/upgrade"
upgradetypes "cosmossdk.io/x/upgrade/types"
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/suite"

"github.com/babylonlabs-io/babylon/app"
v1 "github.com/babylonlabs-io/babylon/app/upgrades/signetlaunch"
"github.com/babylonlabs-io/babylon/x/btclightclient"
btclighttypes "github.com/babylonlabs-io/babylon/x/btclightclient/types"
"github.com/babylonlabs-io/babylon/x/btcstaking/types"
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/suite"
)

const (
Expand Down Expand Up @@ -75,10 +76,14 @@ func (s *UpgradeTestSuite) TestUpgrade() {
oldFPsLen = len(resp.FinalityProviders)

// Before upgrade, the params should be different
paramsFromUpgrade, err := v1.LoadBtcStakingParamsFromData(s.app.AppCodec())
bsParamsFromUpgrade, err := v1.LoadBtcStakingParamsFromData(s.app.AppCodec())
s.NoError(err)
moduleParams := s.app.BTCStakingKeeper.GetParams(s.ctx)
s.NotEqualValues(moduleParams, paramsFromUpgrade)
bsModuleParams := s.app.BTCStakingKeeper.GetParams(s.ctx)
s.NotEqualValues(bsModuleParams, bsParamsFromUpgrade)
fParamsFromUpgrade, err := v1.LoadFinalityParamsFromData(s.app.AppCodec())
s.NoError(err)
fModuleParams := s.app.FinalityKeeper.GetParams(s.ctx)
s.NotEqualValues(fModuleParams, fParamsFromUpgrade)
},
func() {
// inject upgrade plan
Expand Down Expand Up @@ -135,11 +140,15 @@ func (s *UpgradeTestSuite) TestUpgrade() {
s.EqualValues(fpFromKeeper.Pop.String(), fpInserted.Pop.String())
}

// Afer upgrade, the params should be the same
paramsFromUpgrade, err := v1.LoadBtcStakingParamsFromData(s.app.AppCodec())
// After upgrade, the params should be the same
bsParamsFromUpgrade, err := v1.LoadBtcStakingParamsFromData(s.app.AppCodec())
s.NoError(err)
bsModuleParams := s.app.BTCStakingKeeper.GetParams(s.ctx)
s.EqualValues(bsModuleParams, bsParamsFromUpgrade)
fParamsFromUpgrade, err := v1.LoadFinalityParamsFromData(s.app.AppCodec())
s.NoError(err)
moduleParams := s.app.BTCStakingKeeper.GetParams(s.ctx)
s.EqualValues(moduleParams, paramsFromUpgrade)
fModuleParams := s.app.FinalityKeeper.GetParams(s.ctx)
s.EqualValues(fModuleParams, fParamsFromUpgrade)
},
},
}
Expand Down
2 changes: 1 addition & 1 deletion app/upgrades/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type Upgrade struct {
UpgradeName string

// CreateUpgradeHandler defines the function that creates an upgrade handler
CreateUpgradeHandler func(*module.Manager, module.Configurator, BaseAppParamManager, *keepers.AppKeepers) upgradetypes.UpgradeHandler
CreateUpgradeHandler func(*module.Manager, module.Configurator, *keepers.AppKeepers) upgradetypes.UpgradeHandler

// Store upgrades, should be used for any new modules introduced, new modules deleted, or store names renamed.
StoreUpgrades store.StoreUpgrades
Expand Down
8 changes: 4 additions & 4 deletions proto/babylon/btcstaking/v1/btcstaking.proto
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ message FinalityProvider {
// the finality provider is slashed.
// if it's 0 then the finality provider is not slashed
uint64 slashed_btc_height = 7;
// sluggish defines whether the finality provider is detected sluggish
bool sluggish = 8;
// jailed defines whether the finality provider is jailed
bool jailed = 8;
}

// FinalityProviderWithMeta wraps the FinalityProvider with metadata.
Expand All @@ -54,8 +54,8 @@ message FinalityProviderWithMeta {
// the finality provider is slashed.
// if it's 0 then the finality provider is not slashed
uint64 slashed_btc_height = 5;
// sluggish defines whether the finality provider is detected sluggish
bool sluggish = 6;
// jailed defines whether the finality provider is detected jailed
bool jailed = 6;
}

// BTCDelegation defines a BTC delegation
Expand Down
18 changes: 17 additions & 1 deletion proto/babylon/btcstaking/v1/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,27 @@ message EventPowerDistUpdate {
bytes pk = 1 [ (gogoproto.customtype) = "github.com/babylonlabs-io/babylon/types.BIP340PubKey" ];
}

// EventJailedFinalityProvider defines an event that a finality provider
// is jailed after being detected sluggish
message EventJailedFinalityProvider {
bytes pk = 1 [ (gogoproto.customtype) = "github.com/babylonlabs-io/babylon/types.BIP340PubKey" ];
}

// EventUnjailedFinalityProvider defines an event that a jailed finality provider
// is unjailed after the jailing period is passed
message EventUnjailedFinalityProvider {
bytes pk = 1 [ (gogoproto.customtype) = "github.com/babylonlabs-io/babylon/types.BIP340PubKey" ];
}

// ev is the event that affects voting power distribution
oneof ev {
// slashed_fp means a finality provider is slashed
EventSlashedFinalityProvider slashed_fp = 1;
// jailed_fp means a finality provider is jailed
EventJailedFinalityProvider jailed_fp = 2;
// unjailed_fp means a jailed finality provider is unjailed
EventUnjailedFinalityProvider unjailed_fp = 3;
// btc_del_state_update means a BTC delegation's state is updated
EventBTCDelegationStateUpdate btc_del_state_update = 2;
EventBTCDelegationStateUpdate btc_del_state_update = 4;
}
}
3 changes: 3 additions & 0 deletions proto/babylon/btcstaking/v1/incentive.proto
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ message FinalityProviderDistInfo {
// is_timestamped indicates whether the finality provider
// has timestamped public randomness committed
bool is_timestamped = 6;
// is_jailed indicates whether the finality provider
// is jailed, if so, it should not be assigned voting power
bool is_jailed = 7;
}

// BTCDelDistInfo contains the information related to reward distribution for a BTC delegation
Expand Down
4 changes: 2 additions & 2 deletions proto/babylon/btcstaking/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,6 @@ message FinalityProviderResponse {
uint64 height = 8;
// voting_power is the voting power of this finality provider at the given height
uint64 voting_power = 9;
// sluggish defines whether the finality provider is detected sluggish
bool sluggish = 10;
// jailed defines whether the finality provider is jailed
bool jailed = 10;
}
13 changes: 3 additions & 10 deletions proto/babylon/finality/v1/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,9 @@ message EventSlashedFinalityProvider {
Evidence evidence = 1;
}

// EventSluggishFinalityProviderDetected is the event emitted when a finality provider is
// detected as sluggish
message EventSluggishFinalityProviderDetected {
// public_key is the BTC public key of the finality provider
string public_key = 1;
}

// EventSluggishFinalityProviderReverted is the event emitted when a sluggish finality
// provider is no longer considered sluggish
message EventSluggishFinalityProviderReverted {
// EventJailedFinalityProvider is the event emitted when a finality provider is
// jailed due to inactivity
message EventJailedFinalityProvider {
// public_key is the BTC public key of the finality provider
string public_key = 1;
}
5 changes: 5 additions & 0 deletions proto/babylon/finality/v1/finality.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ package babylon.finality.v1;
option go_package = "github.com/babylonlabs-io/babylon/x/finality/types";

import "gogoproto/gogo.proto";
import "amino/amino.proto";
import "google/protobuf/timestamp.proto";

// IndexedBlock is the necessary metadata and finalization status of a block
message IndexedBlock {
Expand Down Expand Up @@ -64,4 +66,7 @@ message FinalityProviderSigningInfo {
// missed_blocks_counter defines a counter to avoid unnecessary array reads.
// Note that `Sum(MissedBlocksBitArray)` always equals `MissedBlocksCounter`.
int64 missed_blocks_counter = 3;
// Timestamp until which the validator is jailed due to liveness downtime.
google.protobuf.Timestamp jailed_until = 4
[(gogoproto.stdtime) = true, (gogoproto.nullable) = false, (amino.dont_omitempty) = true];
}
6 changes: 5 additions & 1 deletion proto/babylon/finality/v1/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package babylon.finality.v1;
import "gogoproto/gogo.proto";
import "amino/amino.proto";
import "cosmos_proto/cosmos.proto";
import "google/protobuf/duration.proto";

option go_package = "github.com/babylonlabs-io/babylon/x/finality/types";

Expand All @@ -16,7 +17,7 @@ message Params {
// vote before being judged as missing their voting turn on the given block
int64 finality_sig_timeout = 2;
// min_signed_per_window defines the minimum number of blocks that a finality provider is required to sign
// within the sliding window to avoid being detected as sluggish
// within the sliding window to avoid being jailed
bytes min_signed_per_window = 3 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
Expand All @@ -26,4 +27,7 @@ message Params {
// min_pub_rand is the minimum number of public randomness each
// message should commit
uint64 min_pub_rand = 4;
// jail_duration is the minimum period of time that a finality provider remains jailed
google.protobuf.Duration jail_duration = 5
[(gogoproto.nullable) = false, (amino.dont_omitempty) = true, (gogoproto.stdduration) = true];
}
22 changes: 19 additions & 3 deletions proto/babylon/finality/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ service Msg {
// TODO: msg for evidence of equivocation. this is not specified yet
// UpdateParams updates the finality module parameters.
rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse);
// UnjailFinalityProvider defines a method for unjailing a jailed
// finality provider, thus it can receive voting power
rpc UnjailFinalityProvider(MsgUnjailFinalityProvider) returns (MsgUnjailFinalityProviderResponse);
}

// MsgCommitPubRandList defines a message for committing a list of public randomness for EOTS
Expand All @@ -36,7 +39,7 @@ message MsgCommitPubRandList {
// commitment is the commitment of these public randomness
// currently it's the root of the Merkle tree that includes these public randomness
bytes commitment = 5;
// sig is the signature on (start_height || num_pub_rand || commitment) signed by
// 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
Expand Down Expand Up @@ -73,17 +76,30 @@ message MsgAddFinalitySigResponse{}
// MsgUpdateParams defines a message for updating finality module parameters.
message MsgUpdateParams {
option (cosmos.msg.v1.signer) = "authority";

// authority is the address of the governance account.
// just FYI: cosmos.AddressString marks that this field should use type alias
// for AddressString instead of string, but the functionality is not yet implemented
// in cosmos-proto
string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];

// params defines the finality parameters to update.
//
// NOTE: All parameters must be supplied.
Params params = 2 [(gogoproto.nullable) = false];
}
// MsgUpdateParamsResponse is the response to the MsgUpdateParams message.
message MsgUpdateParamsResponse {}

// MsgUnjailFinalityProvider defines the Msg/UnjailFinalityProvider request type
message MsgUnjailFinalityProvider {
option (gogoproto.goproto_getters) = false;
option (cosmos.msg.v1.signer) = "signer";

string signer = 1;
// fp_btc_pk is the BTC PK of the finality provider that commits the public randomness
bytes fp_btc_pk = 2 [ (gogoproto.customtype) = "github.com/babylonlabs-io/babylon/types.BIP340PubKey" ];
}

// MsgUnjailFinalityProviderResponse defines the Msg/UnjailFinalityProvider response type
message MsgUnjailFinalityProviderResponse {}
11 changes: 11 additions & 0 deletions test/e2e/configurer/chain/queries_btcstaking.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ func (n *NodeConfig) QueryBTCStakingParams() *bstypes.Params {
return &resp.Params
}

func (n *NodeConfig) QueryFinalityParams() *ftypes.Params {
bz, err := n.QueryGRPCGateway("/babylon/finality/v1/params", url.Values{})
require.NoError(n.t, err)

var resp ftypes.QueryParamsResponse
err = util.Cdc.UnmarshalJSON(bz, &resp)
require.NoError(n.t, err)

return &resp.Params
}

func (n *NodeConfig) QueryFinalityProviders() []*bstypes.FinalityProviderResponse {
bz, err := n.QueryGRPCGateway("/babylon/btcstaking/v1/finality_providers", url.Values{})
require.NoError(n.t, err)
Expand Down
Loading
Loading