From 0fd948dd755820e70bf56703cb9245ad804b5c72 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Thu, 22 Aug 2024 15:42:00 +0800 Subject: [PATCH] feat(ADR-024): Exclude voting power for fps who do not have timestamped pub rand (#23) This closes the second part of #8. In particular, this PR: * Implemented `HasTimestampedPubRand` in the finality keeper to check whether a pub rand at a given height is BTC-timestamped * Added expected finality keeper to btcstaking keeper so that `HasTimestampedPubRand` can be called within the module * When signing voting power to fps in `btcstaking`'s begin blocker, if the fp does not have timestamped pub rand, voting power will not be assigned Note that this PR introduced circular dependency between the btc staking module and finality module, which should be addressed by moving the voting power table to the finality module, tracked by issue #24 --- app/keepers/keepers.go | 6 + proto/babylon/btcstaking/v1/incentive.proto | 9 + test/e2e/btc_staking_e2e_test.go | 2 +- testutil/datagen/incentive.go | 4 +- testutil/keeper/btcstaking.go | 2 + x/btcstaking/genesis_test.go | 2 +- x/btcstaking/keeper/bench_test.go | 3 +- x/btcstaking/keeper/btc_height_index_test.go | 2 +- x/btcstaking/keeper/grpc_query_test.go | 16 +- x/btcstaking/keeper/incentive_test.go | 10 +- x/btcstaking/keeper/keeper.go | 11 +- x/btcstaking/keeper/keeper_test.go | 10 +- x/btcstaking/keeper/msg_server_test.go | 30 ++-- x/btcstaking/keeper/params_test.go | 6 +- x/btcstaking/keeper/power_dist_change.go | 26 ++- x/btcstaking/keeper/power_dist_change_test.go | 12 +- x/btcstaking/keeper/query_params_test.go | 4 +- .../keeper/voting_power_table_test.go | 35 ++-- x/btcstaking/types/btcstaking.go | 12 +- x/btcstaking/types/expected_keepers.go | 4 + x/btcstaking/types/incentive.go | 52 ++++-- x/btcstaking/types/incentive.pb.go | 159 ++++++++++++------ x/btcstaking/types/mocked_keepers.go | 37 ++++ x/finality/keeper/msg_server.go | 11 +- x/finality/keeper/public_randomness.go | 27 ++- x/finality/keeper/tallying.go | 6 +- x/finality/types/errors.go | 15 +- 27 files changed, 365 insertions(+), 148 deletions(-) diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 13198157..17c9a522 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -528,6 +528,9 @@ func (ak *AppKeepers) InitKeepers( runtime.NewKVStoreService(keys[btcstakingtypes.StoreKey]), &btclightclientKeeper, &btcCheckpointKeeper, + // setting the finality keeper as nil for now + // need to set it after finality keeper is initiated + nil, btcNetParams, authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) @@ -543,6 +546,9 @@ func (ak *AppKeepers) InitKeepers( ) ak.BTCStakingKeeper = *ak.BTCStakingKeeper.SetHooks(btcstakingtypes.NewMultiBtcStakingHooks(ak.FinalityKeeper.Hooks())) ak.FinalityKeeper = *ak.FinalityKeeper.SetHooks(finalitytypes.NewMultiFinalityHooks(ak.BTCStakingKeeper.Hooks())) + // TODO this introduces circular dependency between the finality module and + // the btcstaking modules, need refactoring + ak.BTCStakingKeeper.FinalityKeeper = ak.FinalityKeeper // create evidence keeper with router evidenceKeeper := evidencekeeper.NewKeeper( diff --git a/proto/babylon/btcstaking/v1/incentive.proto b/proto/babylon/btcstaking/v1/incentive.proto index 7dcde01f..0a5561d0 100644 --- a/proto/babylon/btcstaking/v1/incentive.proto +++ b/proto/babylon/btcstaking/v1/incentive.proto @@ -9,9 +9,15 @@ option go_package = "github.com/babylonlabs-io/babylon/x/btcstaking/types"; // VotingPowerDistCache is the cache for voting power distribution of finality providers // and their BTC delegations at a height message VotingPowerDistCache { + option (gogoproto.goproto_getters) = false; + // total_voting_power is the total voting power of all the finality providers + // in the cache uint64 total_voting_power = 1; // finality_providers is a list of finality providers' voting power information repeated FinalityProviderDistInfo finality_providers = 2; + // num_active_fps is the number of finality providers that have positive voting power + // as well as timestamped public randomness + uint32 num_active_fps = 3; } // FinalityProviderDistInfo is the reward distribution of a finality provider and its BTC delegations @@ -30,6 +36,9 @@ message FinalityProviderDistInfo { uint64 total_voting_power = 4; // btc_dels is a list of BTC delegations' voting power information under this finality provider repeated BTCDelDistInfo btc_dels = 5; + // is_timestamped indicates whether the finality provider + // has timestamped public randomness committed + bool is_timestamped = 6; } // BTCDelDistInfo contains the information related to reward distribution for a BTC delegation diff --git a/test/e2e/btc_staking_e2e_test.go b/test/e2e/btc_staking_e2e_test.go index 4b6676ac..d8b73351 100644 --- a/test/e2e/btc_staking_e2e_test.go +++ b/test/e2e/btc_staking_e2e_test.go @@ -355,7 +355,7 @@ func (s *BTCStakingTestSuite) Test3CommitPublicRandomnessAndSubmitFinalitySignat s.Eventually(func() bool { finalizedBlocks = nonValidatorNode.QueryListBlocks(ftypes.QueriedBlockStatus_FINALIZED) return len(finalizedBlocks) > 0 - }, time.Minute, time.Second*5) + }, time.Minute, time.Second) s.Equal(activatedHeight, finalizedBlocks[0].Height) s.Equal(appHash.Bytes(), finalizedBlocks[0].AppHash) diff --git a/testutil/datagen/incentive.go b/testutil/datagen/incentive.go index 2cd0e10b..d379e82b 100644 --- a/testutil/datagen/incentive.go +++ b/testutil/datagen/incentive.go @@ -4,10 +4,11 @@ import ( "math/rand" sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + btcctypes "github.com/babylonlabs-io/babylon/x/btccheckpoint/types" bstypes "github.com/babylonlabs-io/babylon/x/btcstaking/types" itypes "github.com/babylonlabs-io/babylon/x/incentive/types" - sdk "github.com/cosmos/cosmos-sdk/types" ) const ( @@ -105,6 +106,7 @@ func GenRandomFinalityProviderDistInfo(r *rand.Rand) (*bstypes.FinalityProviderD } fpDistInfo.BtcDels = append(fpDistInfo.BtcDels, btcDelDistInfo) fpDistInfo.TotalVotingPower += btcDelDistInfo.VotingPower + fpDistInfo.IsTimestamped = true } return fpDistInfo, nil } diff --git a/testutil/keeper/btcstaking.go b/testutil/keeper/btcstaking.go index d12d3282..a3bcad46 100644 --- a/testutil/keeper/btcstaking.go +++ b/testutil/keeper/btcstaking.go @@ -27,6 +27,7 @@ func BTCStakingKeeper( t testing.TB, btclcKeeper types.BTCLightClientKeeper, btccKeeper types.BtcCheckpointKeeper, + finalityKeeper types.FinalityKeeper, ) (*keeper.Keeper, sdk.Context) { storeKey := storetypes.NewKVStoreKey(types.StoreKey) @@ -43,6 +44,7 @@ func BTCStakingKeeper( runtime.NewKVStoreService(storeKey), btclcKeeper, btccKeeper, + finalityKeeper, &chaincfg.SimNetParams, authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) diff --git a/x/btcstaking/genesis_test.go b/x/btcstaking/genesis_test.go index 805650c8..2ab7d793 100644 --- a/x/btcstaking/genesis_test.go +++ b/x/btcstaking/genesis_test.go @@ -17,7 +17,7 @@ func TestGenesis(t *testing.T) { Params: []*types.Params{&p}, } - k, ctx := keepertest.BTCStakingKeeper(t, nil, nil) + k, ctx := keepertest.BTCStakingKeeper(t, nil, nil, nil) btcstaking.InitGenesis(ctx, *k, genesisState) got := btcstaking.ExportGenesis(ctx, *k) require.NotNil(t, got) diff --git a/x/btcstaking/keeper/bench_test.go b/x/btcstaking/keeper/bench_test.go index e32acbef..3a41a8e1 100644 --- a/x/btcstaking/keeper/bench_test.go +++ b/x/btcstaking/keeper/bench_test.go @@ -24,7 +24,8 @@ func benchBeginBlock(b *testing.B, numFPs int, numDelsUnderFP int) { defer ctrl.Finish() btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(b, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + h := NewHelper(b, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters covenantSKs, _ := h.GenAndApplyParams(r) changeAddress, err := datagen.GenRandomBTCAddress(r, h.Net) diff --git a/x/btcstaking/keeper/btc_height_index_test.go b/x/btcstaking/keeper/btc_height_index_test.go index 326fdf39..a099df26 100644 --- a/x/btcstaking/keeper/btc_height_index_test.go +++ b/x/btcstaking/keeper/btc_height_index_test.go @@ -23,7 +23,7 @@ func FuzzBTCHeightIndex(f *testing.F) { // mock BTC light client btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) - keeper, ctx := keepertest.BTCStakingKeeper(t, btclcKeeper, nil) + keeper, ctx := keepertest.BTCStakingKeeper(t, btclcKeeper, nil, nil) // randomise Babylon height and BTC height babylonHeight := datagen.RandomInt(r, 100) diff --git a/x/btcstaking/keeper/grpc_query_test.go b/x/btcstaking/keeper/grpc_query_test.go index 2b7596b2..4b841edc 100644 --- a/x/btcstaking/keeper/grpc_query_test.go +++ b/x/btcstaking/keeper/grpc_query_test.go @@ -28,7 +28,7 @@ func FuzzActivatedHeight(f *testing.F) { r := rand.New(rand.NewSource(seed)) // Setup keeper and context - keeper, ctx := testkeeper.BTCStakingKeeper(t, nil, nil) + keeper, ctx := testkeeper.BTCStakingKeeper(t, nil, nil, nil) ctx = sdk.UnwrapSDKContext(ctx) // not activated yet @@ -53,7 +53,7 @@ func FuzzFinalityProviders(f *testing.F) { r := rand.New(rand.NewSource(seed)) // Setup keeper and context - keeper, ctx := testkeeper.BTCStakingKeeper(t, nil, nil) + keeper, ctx := testkeeper.BTCStakingKeeper(t, nil, nil, nil) ctx = sdk.UnwrapSDKContext(ctx) // Generate random finality providers and add them to kv store @@ -118,7 +118,7 @@ func FuzzFinalityProvider(f *testing.F) { f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) // Setup keeper and context - keeper, ctx := testkeeper.BTCStakingKeeper(t, nil, nil) + keeper, ctx := testkeeper.BTCStakingKeeper(t, nil, nil, nil) ctx = sdk.UnwrapSDKContext(ctx) // Generate random finality providers and add them to kv store @@ -174,7 +174,7 @@ func FuzzPendingBTCDelegations(f *testing.F) { btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) btccKeeper.EXPECT().GetParams(gomock.Any()).Return(btcctypes.DefaultParams()).AnyTimes() - keeper, ctx := testkeeper.BTCStakingKeeper(t, btclcKeeper, btccKeeper) + keeper, ctx := testkeeper.BTCStakingKeeper(t, btclcKeeper, btccKeeper, nil) // covenant and slashing addr covenantSKs, covenantPKs, covenantQuorum := datagen.GenCovenantCommittee(r) @@ -276,7 +276,7 @@ func FuzzFinalityProviderPowerAtHeight(f *testing.F) { r := rand.New(rand.NewSource(seed)) // Setup keeper and context - keeper, ctx := testkeeper.BTCStakingKeeper(t, nil, nil) + keeper, ctx := testkeeper.BTCStakingKeeper(t, nil, nil, nil) // random finality provider fp, err := datagen.GenRandomFinalityProvider(r) @@ -325,7 +325,7 @@ func FuzzFinalityProviderCurrentVotingPower(f *testing.F) { r := rand.New(rand.NewSource(seed)) // Setup keeper and context - keeper, ctx := testkeeper.BTCStakingKeeper(t, nil, nil) + keeper, ctx := testkeeper.BTCStakingKeeper(t, nil, nil, nil) // random finality provider fp, err := datagen.GenRandomFinalityProvider(r) @@ -377,7 +377,7 @@ func FuzzActiveFinalityProvidersAtHeight(f *testing.F) { btclcKeeper.EXPECT().GetTipInfo(gomock.Any()).Return(&btclctypes.BTCHeaderInfo{Height: 10}).AnyTimes() btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) btccKeeper.EXPECT().GetParams(gomock.Any()).Return(btcctypes.DefaultParams()).AnyTimes() - keeper, ctx := testkeeper.BTCStakingKeeper(t, btclcKeeper, btccKeeper) + keeper, ctx := testkeeper.BTCStakingKeeper(t, btclcKeeper, btccKeeper, nil) // covenant and slashing addr covenantSKs, covenantPKs, covenantQuorum := datagen.GenCovenantCommittee(r) @@ -496,7 +496,7 @@ func FuzzFinalityProviderDelegations(f *testing.F) { btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) btccKeeper.EXPECT().GetParams(gomock.Any()).Return(btcctypes.DefaultParams()).AnyTimes() - keeper, ctx := testkeeper.BTCStakingKeeper(t, btclcKeeper, btccKeeper) + keeper, ctx := testkeeper.BTCStakingKeeper(t, btclcKeeper, btccKeeper, nil) // covenant and slashing addr covenantSKs, covenantPKs, covenantQuorum := datagen.GenCovenantCommittee(r) diff --git a/x/btcstaking/keeper/incentive_test.go b/x/btcstaking/keeper/incentive_test.go index 9b49da27..3ebfa9af 100644 --- a/x/btcstaking/keeper/incentive_test.go +++ b/x/btcstaking/keeper/incentive_test.go @@ -23,7 +23,9 @@ func FuzzRecordVotingPowerDistCache(f *testing.F) { // mock BTC light client and BTC checkpoint modules btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + finalityKeeper.EXPECT().HasTimestampedPubRand(gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes() + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters covenantSKs, _ := h.GenAndApplyParams(r) @@ -42,7 +44,8 @@ func FuzzRecordVotingPowerDistCache(f *testing.F) { } } - // for the first numFpsWithVotingPower finality providers, generate a random number of BTC delegations and add covenant signatures to activate them + // for the first numFpsWithVotingPower finality providers, generate a random number of BTC + // delegations and add covenant signatures to activate them numBTCDels := datagen.RandomInt(r, 10) + 1 stakingValue := datagen.RandomInt(r, 100000) + 100000 for _, fp := range fpsWithVotingPowerMap { @@ -70,8 +73,7 @@ func FuzzRecordVotingPowerDistCache(f *testing.F) { require.NoError(t, err) require.NotNil(t, dc) require.Equal(t, dc.TotalVotingPower, numFpsWithVotingPower*numBTCDels*stakingValue) - maxNumFps := h.BTCStakingKeeper.GetParams(h.Ctx).MaxActiveFinalityProviders - activeFPs := dc.GetActiveFinalityProviderSet(maxNumFps) + activeFPs := dc.GetActiveFinalityProviderSet() for _, fpDistInfo := range activeFPs { require.Equal(t, fpDistInfo.TotalVotingPower, numBTCDels*stakingValue) fp, ok := fpsWithVotingPowerMap[fpDistInfo.Addr] diff --git a/x/btcstaking/keeper/keeper.go b/x/btcstaking/keeper/keeper.go index 51515ae6..e1d38689 100644 --- a/x/btcstaking/keeper/keeper.go +++ b/x/btcstaking/keeper/keeper.go @@ -19,8 +19,9 @@ type ( cdc codec.BinaryCodec storeService corestoretypes.KVStoreService - btclcKeeper types.BTCLightClientKeeper - btccKeeper types.BtcCheckpointKeeper + btclcKeeper types.BTCLightClientKeeper + btccKeeper types.BtcCheckpointKeeper + FinalityKeeper types.FinalityKeeper hooks types.BtcStakingHooks @@ -37,6 +38,7 @@ func NewKeeper( btclcKeeper types.BTCLightClientKeeper, btccKeeper types.BtcCheckpointKeeper, + finalityKeeper types.FinalityKeeper, btcNet *chaincfg.Params, authority string, @@ -45,8 +47,9 @@ func NewKeeper( cdc: cdc, storeService: storeService, - btclcKeeper: btclcKeeper, - btccKeeper: btccKeeper, + btclcKeeper: btclcKeeper, + btccKeeper: btccKeeper, + FinalityKeeper: finalityKeeper, hooks: nil, diff --git a/x/btcstaking/keeper/keeper_test.go b/x/btcstaking/keeper/keeper_test.go index 4084eacc..ef00fc59 100644 --- a/x/btcstaking/keeper/keeper_test.go +++ b/x/btcstaking/keeper/keeper_test.go @@ -33,13 +33,19 @@ type Helper struct { BTCStakingKeeper *keeper.Keeper BTCLightClientKeeper *types.MockBTCLightClientKeeper BTCCheckpointKeeper *types.MockBtcCheckpointKeeper + FinalityKeeper *types.MockFinalityKeeper BTCStakingHooks *types.MockBtcStakingHooks MsgServer types.MsgServer Net *chaincfg.Params } -func NewHelper(t testing.TB, btclcKeeper *types.MockBTCLightClientKeeper, btccKeeper *types.MockBtcCheckpointKeeper) *Helper { - k, ctx := keepertest.BTCStakingKeeper(t, btclcKeeper, btccKeeper) +func NewHelper( + t testing.TB, + btclcKeeper *types.MockBTCLightClientKeeper, + btccKeeper *types.MockBtcCheckpointKeeper, + finalityKeeper *types.MockFinalityKeeper, +) *Helper { + k, ctx := keepertest.BTCStakingKeeper(t, btclcKeeper, btccKeeper, finalityKeeper) ctx = ctx.WithHeaderInfo(header.Info{Height: 1}) msgSrvr := keeper.NewMsgServerImpl(*k) diff --git a/x/btcstaking/keeper/msg_server_test.go b/x/btcstaking/keeper/msg_server_test.go index a8e7fbcc..ec2e537a 100644 --- a/x/btcstaking/keeper/msg_server_test.go +++ b/x/btcstaking/keeper/msg_server_test.go @@ -37,7 +37,8 @@ func FuzzMsgCreateFinalityProvider(f *testing.F) { // mock BTC light client and BTC checkpoint modules btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters h.GenAndApplyParams(r) @@ -143,7 +144,8 @@ func FuzzCreateBTCDelegation(f *testing.F) { // mock BTC light client and BTC checkpoint modules btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters h.GenAndApplyParams(r) @@ -187,7 +189,8 @@ func TestProperVersionInDelegation(t *testing.T) { // mock BTC light client and BTC checkpoint modules btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters h.GenAndApplyParams(r) @@ -254,7 +257,8 @@ func FuzzAddCovenantSigs(f *testing.F) { // mock BTC light client and BTC checkpoint modules btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters covenantSKs, _ := h.GenAndApplyParams(r) @@ -318,7 +322,8 @@ func FuzzBTCUndelegate(f *testing.F) { // mock BTC light client and BTC checkpoint modules btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters covenantSKs, _ := h.GenAndApplyParams(r) @@ -390,7 +395,8 @@ func FuzzSelectiveSlashing(f *testing.F) { // mock BTC light client and BTC checkpoint modules btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters covenantSKs, _ := h.GenAndApplyParams(r) @@ -456,7 +462,8 @@ func FuzzSelectiveSlashing_StakingTx(f *testing.F) { // mock BTC light client and BTC checkpoint modules btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters covenantSKs, _ := h.GenAndApplyParams(r) @@ -532,7 +539,8 @@ func TestDoNotAllowDelegationWithoutFinalityProvider(t *testing.T) { btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) btccKeeper.EXPECT().GetParams(gomock.Any()).Return(btcctypes.DefaultParams()).AnyTimes() - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set covenant PK to params _, covenantPKs := h.GenAndApplyParams(r) @@ -699,7 +707,8 @@ func TestCorrectUnbondingTimeInDelegation(t *testing.T) { // mock BTC light client and BTC checkpoint modules btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters _, _ = h.GenAndApplyCustomParams(r, tt.finalizationTimeout, tt.minUnbondingTime) @@ -771,7 +780,8 @@ func TestMinimalUnbondingRate(t *testing.T) { // mock BTC light client and BTC checkpoint modules btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters, by default minimal unbonding value is 80% of staking value _, _ = h.GenAndApplyParams(r) diff --git a/x/btcstaking/keeper/params_test.go b/x/btcstaking/keeper/params_test.go index fc484dd3..fcd589bd 100644 --- a/x/btcstaking/keeper/params_test.go +++ b/x/btcstaking/keeper/params_test.go @@ -13,7 +13,7 @@ import ( ) func TestGetParams(t *testing.T) { - k, ctx := testkeeper.BTCStakingKeeper(t, nil, nil) + k, ctx := testkeeper.BTCStakingKeeper(t, nil, nil, nil) params := types.DefaultParams() err := k.SetParams(ctx, params) @@ -23,7 +23,7 @@ func TestGetParams(t *testing.T) { } func TestGetParamsVersions(t *testing.T) { - k, ctx := testkeeper.BTCStakingKeeper(t, nil, nil) + k, ctx := testkeeper.BTCStakingKeeper(t, nil, nil, nil) params := types.DefaultParams() pv := k.GetParamsWithVersion(ctx) @@ -56,7 +56,7 @@ func FuzzParamsVersioning(f *testing.F) { datagen.AddRandomSeedsToFuzzer(f, 10) f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) - k, ctx := testkeeper.BTCStakingKeeper(t, nil, nil) + k, ctx := testkeeper.BTCStakingKeeper(t, nil, nil, nil) numVersionsToGenerate := r.Intn(100) + 1 params0 := k.GetParams(ctx) var generatedParams []*types.Params diff --git a/x/btcstaking/keeper/power_dist_change.go b/x/btcstaking/keeper/power_dist_change.go index bde774ce..2b42b174 100644 --- a/x/btcstaking/keeper/power_dist_change.go +++ b/x/btcstaking/keeper/power_dist_change.go @@ -35,7 +35,7 @@ func (k Keeper) UpdatePowerDist(ctx context.Context) { if len(events) == 0 { if dc != nil { // map everything in prev height to this height - k.recordVotingPowerAndCache(ctx, dc, maxActiveFps) + k.recordVotingPowerAndCache(ctx, dc) } return } @@ -57,7 +57,7 @@ func (k Keeper) UpdatePowerDist(ctx context.Context) { newDc := k.ProcessAllPowerDistUpdateEvents(ctx, dc, events, maxActiveFps) // find newly bonded finality providers and execute the hooks - newBondedFinalityProviders := newDc.FindNewActiveFinalityProviders(dc, maxActiveFps) + newBondedFinalityProviders := newDc.FindNewActiveFinalityProviders(dc) for _, fp := range newBondedFinalityProviders { if err := k.hooks.AfterFinalityProviderActivated(ctx, fp.BtcPk); err != nil { panic(fmt.Errorf("failed to execute after finality provider %s bonded", fp.BtcPk.MarshalHex())) @@ -65,28 +65,27 @@ func (k Keeper) UpdatePowerDist(ctx context.Context) { } // record voting power and cache for this height - k.recordVotingPowerAndCache(ctx, newDc, maxActiveFps) + k.recordVotingPowerAndCache(ctx, newDc) // record metrics - k.recordMetrics(newDc, maxActiveFps) + k.recordMetrics(newDc) } -func (k Keeper) recordVotingPowerAndCache(ctx context.Context, dc *types.VotingPowerDistCache, maxActiveFps uint32) { +func (k Keeper) recordVotingPowerAndCache(ctx context.Context, dc *types.VotingPowerDistCache) { babylonTipHeight := uint64(sdk.UnwrapSDKContext(ctx).HeaderInfo().Height) // set voting power table for this height - for i := uint32(0); i < dc.GetNumActiveFPs(maxActiveFps); i++ { + for i := uint32(0); i < dc.NumActiveFps; i++ { fp := dc.FinalityProviders[i] k.SetVotingPower(ctx, fp.BtcPk.MustMarshal(), babylonTipHeight, fp.TotalVotingPower) - } // set the voting power distribution cache of the current height k.setVotingPowerDistCache(ctx, babylonTipHeight, dc) } -func (k Keeper) recordMetrics(dc *types.VotingPowerDistCache, maxActiveFps uint32) { +func (k Keeper) recordMetrics(dc *types.VotingPowerDistCache) { // number of active FPs - numActiveFPs := int(dc.GetNumActiveFPs(maxActiveFps)) + numActiveFPs := int(dc.NumActiveFps) types.RecordActiveFinalityProviders(numActiveFPs) // number of inactive FPs numInactiveFPs := len(dc.FinalityProviders) - numActiveFPs @@ -113,6 +112,7 @@ func (k Keeper) ProcessAllPowerDistUpdateEvents( events []*types.EventPowerDistUpdate, maxActiveFps uint32, ) *types.VotingPowerDistCache { + height := uint64(sdk.UnwrapSDKContext(ctx).HeaderInfo().Height) // a map where key is finality provider's BTC PK hex and value is a list // of BTC delegations that newly become active under this provider activeBTCDels := map[string][]*types.BTCDelegation{} @@ -236,6 +236,14 @@ func (k Keeper) ProcessAllPowerDistUpdateEvents( } } + // label fps that does not have timestamped pub rand + for _, fp := range newDc.FinalityProviders { + // TODO calling HasTimestampedPubRand potentially iterates + // all the pub rand committed by the fp, which might slow down + // the process, need optimization + fp.IsTimestamped = k.FinalityKeeper.HasTimestampedPubRand(ctx, fp.BtcPk, height) + } + // filter out the top N finality providers and their total voting power, and // record them in the new cache newDc.ApplyActiveFinalityProviders(maxActiveFps) diff --git a/x/btcstaking/keeper/power_dist_change_test.go b/x/btcstaking/keeper/power_dist_change_test.go index 373063aa..0016ca9c 100644 --- a/x/btcstaking/keeper/power_dist_change_test.go +++ b/x/btcstaking/keeper/power_dist_change_test.go @@ -24,7 +24,9 @@ func FuzzProcessAllPowerDistUpdateEvents_Determinism(f *testing.F) { // mock BTC light client and BTC checkpoint modules btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + finalityKeeper.EXPECT().HasTimestampedPubRand(gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes() + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters h.GenAndApplyParams(r) @@ -75,7 +77,9 @@ func FuzzFinalityProviderEvents(f *testing.F) { // mock BTC light client and BTC checkpoint modules btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + finalityKeeper.EXPECT().HasTimestampedPubRand(gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes() + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters covenantSKs, _ := h.GenAndApplyParams(r) @@ -152,7 +156,9 @@ func FuzzBTCDelegationEvents(f *testing.F) { // mock BTC light client and BTC checkpoint modules btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + finalityKeeper.EXPECT().HasTimestampedPubRand(gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes() + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters covenantSKs, _ := h.GenAndApplyParams(r) diff --git a/x/btcstaking/keeper/query_params_test.go b/x/btcstaking/keeper/query_params_test.go index a4a4282a..1e4624c4 100644 --- a/x/btcstaking/keeper/query_params_test.go +++ b/x/btcstaking/keeper/query_params_test.go @@ -10,7 +10,7 @@ import ( ) func TestParamsQuery(t *testing.T) { - keeper, ctx := testkeeper.BTCStakingKeeper(t, nil, nil) + keeper, ctx := testkeeper.BTCStakingKeeper(t, nil, nil, nil) params := types.DefaultParams() err := keeper.SetParams(ctx, params) @@ -22,7 +22,7 @@ func TestParamsQuery(t *testing.T) { } func TestParamsByVersionQuery(t *testing.T) { - keeper, ctx := testkeeper.BTCStakingKeeper(t, nil, nil) + keeper, ctx := testkeeper.BTCStakingKeeper(t, nil, nil, nil) // starting with `1` as BTCStakingKeeper creates params with version 0 params1 := types.DefaultParams() diff --git a/x/btcstaking/keeper/voting_power_table_test.go b/x/btcstaking/keeper/voting_power_table_test.go index 48a68ff1..a76ee2e8 100644 --- a/x/btcstaking/keeper/voting_power_table_test.go +++ b/x/btcstaking/keeper/voting_power_table_test.go @@ -24,7 +24,9 @@ func FuzzVotingPowerTable(f *testing.F) { // mock BTC light client and BTC checkpoint modules btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + finalityKeeper.EXPECT().HasTimestampedPubRand(gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes() + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters covenantSKs, _ := h.GenAndApplyParams(r) @@ -162,7 +164,8 @@ func FuzzVotingPowerTable_ActiveFinalityProviders(f *testing.F) { // mock BTC light client and BTC checkpoint modules btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters covenantSKs, _ := h.GenAndApplyParams(r) @@ -172,6 +175,7 @@ func FuzzVotingPowerTable_ActiveFinalityProviders(f *testing.F) { // generate a random batch of finality providers, each with a BTC delegation with random power fpsWithMeta := []*types.FinalityProviderDistInfo{} numFps := datagen.RandomInt(r, 300) + 1 + noTimestampedFps := map[string]bool{} for i := uint64(0); i < numFps; i++ { // generate finality provider _, _, fp := h.CreateFinalityProvider(r) @@ -187,17 +191,26 @@ func FuzzVotingPowerTable_ActiveFinalityProviders(f *testing.F) { ) h.CreateCovenantSigs(r, covenantSKs, delMsg, del) + // 30 percent not have timestamped randomness, which causes + // zero voting power in the table + fpDistInfo := &types.FinalityProviderDistInfo{BtcPk: fp.BtcPk, TotalVotingPower: stakingValue} + if r.Intn(10) <= 2 { + finalityKeeper.EXPECT().HasTimestampedPubRand(gomock.Any(), fp.BtcPk, gomock.Any()).Return(false).AnyTimes() + noTimestampedFps[fp.BtcPk.MarshalHex()] = true + fpDistInfo.IsTimestamped = false + } else { + finalityKeeper.EXPECT().HasTimestampedPubRand(gomock.Any(), fp.BtcPk, gomock.Any()).Return(true).AnyTimes() + fpDistInfo.IsTimestamped = true + } + // record voting power - fpsWithMeta = append(fpsWithMeta, &types.FinalityProviderDistInfo{ - BtcPk: fp.BtcPk, - TotalVotingPower: stakingValue, - }) + fpsWithMeta = append(fpsWithMeta, fpDistInfo) } maxActiveFpsParam := h.BTCStakingKeeper.GetParams(h.Ctx).MaxActiveFinalityProviders // get a map of expected active finality providers - types.SortFinalityProviders(fpsWithMeta) - expectedActiveFps := fpsWithMeta[:min(uint32(len(fpsWithMeta)), maxActiveFpsParam)] + types.SortFinalityProvidersWithTimestamping(fpsWithMeta) + expectedActiveFps := fpsWithMeta[:min(uint32(len(fpsWithMeta)-len(noTimestampedFps)), maxActiveFpsParam)] expectedActiveFpsMap := map[string]uint64{} for _, fp := range expectedActiveFps { expectedActiveFpsMap[fp.BtcPk.MarshalHex()] = fp.TotalVotingPower @@ -210,7 +223,7 @@ func FuzzVotingPowerTable_ActiveFinalityProviders(f *testing.F) { err = h.BTCStakingKeeper.BeginBlocker(h.Ctx) require.NoError(t, err) - // only finality providers in expectedActiveFpsMap have voting power + // only finality providers in expectedActiveFpsMap have voting power for _, fp := range fpsWithMeta { power := h.BTCStakingKeeper.GetVotingPower(h.Ctx, fp.BtcPk.MustMarshal(), babylonHeight) if expectedPower, ok := expectedActiveFpsMap[fp.BtcPk.MarshalHex()]; ok { @@ -246,7 +259,9 @@ func FuzzVotingPowerTable_ActiveFinalityProviderRotation(f *testing.F) { // mock BTC light client and BTC checkpoint modules btclcKeeper := types.NewMockBTCLightClientKeeper(ctrl) btccKeeper := types.NewMockBtcCheckpointKeeper(ctrl) - h := NewHelper(t, btclcKeeper, btccKeeper) + finalityKeeper := types.NewMockFinalityKeeper(ctrl) + finalityKeeper.EXPECT().HasTimestampedPubRand(gomock.Any(), gomock.Any(), gomock.Any()).Return(true).AnyTimes() + h := NewHelper(t, btclcKeeper, btccKeeper, finalityKeeper) // set all parameters covenantSKs, _ := h.GenAndApplyParams(r) diff --git a/x/btcstaking/types/btcstaking.go b/x/btcstaking/types/btcstaking.go index 456950a4..1bd3bb7b 100644 --- a/x/btcstaking/types/btcstaking.go +++ b/x/btcstaking/types/btcstaking.go @@ -42,10 +42,18 @@ func (fp *FinalityProvider) ValidateBasic() error { return nil } -// SortFinalityProviders sorts the finality providers slice, +// SortFinalityProvidersWithTimestamping sorts the finality providers slice, // from higher to lower voting power -func SortFinalityProviders(fps []*FinalityProviderDistInfo) { +// finality providers that are timestamped come higher than +// those are not +func SortFinalityProvidersWithTimestamping(fps []*FinalityProviderDistInfo) { sort.SliceStable(fps, func(i, j int) bool { + if fps[i].IsTimestamped && !fps[j].IsTimestamped { + return true + } + if !fps[i].IsTimestamped && fps[j].IsTimestamped { + return false + } return fps[i].TotalVotingPower > fps[j].TotalVotingPower }) } diff --git a/x/btcstaking/types/expected_keepers.go b/x/btcstaking/types/expected_keepers.go index bf6bc12a..3f4a1262 100644 --- a/x/btcstaking/types/expected_keepers.go +++ b/x/btcstaking/types/expected_keepers.go @@ -18,6 +18,10 @@ type BtcCheckpointKeeper interface { GetParams(ctx context.Context) (p btcctypes.Params) } +type FinalityKeeper interface { + HasTimestampedPubRand(ctx context.Context, fpBtcPK *bbn.BIP340PubKey, height uint64) bool +} + type BtcStakingHooks interface { AfterFinalityProviderActivated(ctx context.Context, fpPk *bbn.BIP340PubKey) error } diff --git a/x/btcstaking/types/incentive.go b/x/btcstaking/types/incentive.go index 7dd02089..e6955ee2 100644 --- a/x/btcstaking/types/incentive.go +++ b/x/btcstaking/types/incentive.go @@ -20,9 +20,9 @@ func (dc *VotingPowerDistCache) AddFinalityProviderDistInfo(v *FinalityProviderD dc.FinalityProviders = append(dc.FinalityProviders, v) } -func (dc *VotingPowerDistCache) FindNewActiveFinalityProviders(prevDc *VotingPowerDistCache, maxActiveFPs uint32) []*FinalityProviderDistInfo { - activeFps := dc.GetActiveFinalityProviderSet(maxActiveFPs) - prevActiveFps := prevDc.GetActiveFinalityProviderSet(maxActiveFPs) +func (dc *VotingPowerDistCache) FindNewActiveFinalityProviders(prevDc *VotingPowerDistCache) []*FinalityProviderDistInfo { + activeFps := dc.GetActiveFinalityProviderSet() + prevActiveFps := prevDc.GetActiveFinalityProviderSet() newActiveFps := make([]*FinalityProviderDistInfo, 0) for pk, fp := range activeFps { @@ -36,28 +36,44 @@ func (dc *VotingPowerDistCache) FindNewActiveFinalityProviders(prevDc *VotingPow } // ApplyActiveFinalityProviders sorts all finality providers, counts the total voting -// power of top N finality providers, and records them in cache +// power of top N finality providers, excluding those who don't have timestamped pub rand +// and records them in cache func (dc *VotingPowerDistCache) ApplyActiveFinalityProviders(maxActiveFPs uint32) { - // reset total voting power - dc.TotalVotingPower = 0 - // sort finality providers - SortFinalityProviders(dc.FinalityProviders) - // calculate voting power of top N finality providers - numActiveFPs := dc.GetNumActiveFPs(maxActiveFPs) + // sort finality providers with timestamping considered + SortFinalityProvidersWithTimestamping(dc.FinalityProviders) + + numActiveFPs := uint32(0) + + // finality providers are in the descending order of voting power + // and timestamped ones come in the last + for _, fp := range dc.FinalityProviders { + if numActiveFPs == maxActiveFPs { + break + } + if fp.TotalVotingPower == 0 { + break + } + if !fp.IsTimestamped { + break + } + numActiveFPs++ + } + + totalVotingPower := uint64(0) + for i := uint32(0); i < numActiveFPs; i++ { - dc.TotalVotingPower += dc.FinalityProviders[i].TotalVotingPower + totalVotingPower += dc.FinalityProviders[i].TotalVotingPower } -} -func (dc *VotingPowerDistCache) GetNumActiveFPs(maxActiveFPs uint32) uint32 { - return min(maxActiveFPs, uint32(len(dc.FinalityProviders))) + dc.TotalVotingPower = totalVotingPower + dc.NumActiveFps = numActiveFPs } // GetActiveFinalityProviderSet returns a set of active finality providers // keyed by the hex string of the finality provider's BTC public key // i.e., top N of them in terms of voting power -func (dc *VotingPowerDistCache) GetActiveFinalityProviderSet(maxActiveFPs uint32) map[string]*FinalityProviderDistInfo { - numActiveFPs := dc.GetNumActiveFPs(maxActiveFPs) +func (dc *VotingPowerDistCache) GetActiveFinalityProviderSet() map[string]*FinalityProviderDistInfo { + numActiveFPs := dc.NumActiveFps activeFps := make(map[string]*FinalityProviderDistInfo) @@ -71,8 +87,8 @@ func (dc *VotingPowerDistCache) GetActiveFinalityProviderSet(maxActiveFPs uint32 // FilterVotedDistCache filters out a voting power distribution cache // with finality providers that have voted according to a map of given // voters, and their total voted power. -func (dc *VotingPowerDistCache) FilterVotedDistCache(maxActiveFPs uint32, voterBTCPKs map[string]struct{}) *VotingPowerDistCache { - activeFPs := dc.GetActiveFinalityProviderSet(maxActiveFPs) +func (dc *VotingPowerDistCache) FilterVotedDistCache(voterBTCPKs map[string]struct{}) *VotingPowerDistCache { + activeFPs := dc.GetActiveFinalityProviderSet() var filteredFps []*FinalityProviderDistInfo totalVotingPower := uint64(0) for k, v := range activeFPs { diff --git a/x/btcstaking/types/incentive.pb.go b/x/btcstaking/types/incentive.pb.go index e1234e07..098ad0cb 100644 --- a/x/btcstaking/types/incentive.pb.go +++ b/x/btcstaking/types/incentive.pb.go @@ -29,9 +29,14 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // VotingPowerDistCache is the cache for voting power distribution of finality providers // and their BTC delegations at a height type VotingPowerDistCache struct { + // total_voting_power is the total voting power of all the finality providers + // in the cache TotalVotingPower uint64 `protobuf:"varint,1,opt,name=total_voting_power,json=totalVotingPower,proto3" json:"total_voting_power,omitempty"` // finality_providers is a list of finality providers' voting power information FinalityProviders []*FinalityProviderDistInfo `protobuf:"bytes,2,rep,name=finality_providers,json=finalityProviders,proto3" json:"finality_providers,omitempty"` + // num_active_fps is the number of finality providers that have positive voting power + // as well as timestamped public randomness + NumActiveFps uint32 `protobuf:"varint,3,opt,name=num_active_fps,json=numActiveFps,proto3" json:"num_active_fps,omitempty"` } func (m *VotingPowerDistCache) Reset() { *m = VotingPowerDistCache{} } @@ -67,20 +72,6 @@ func (m *VotingPowerDistCache) XXX_DiscardUnknown() { var xxx_messageInfo_VotingPowerDistCache proto.InternalMessageInfo -func (m *VotingPowerDistCache) GetTotalVotingPower() uint64 { - if m != nil { - return m.TotalVotingPower - } - return 0 -} - -func (m *VotingPowerDistCache) GetFinalityProviders() []*FinalityProviderDistInfo { - if m != nil { - return m.FinalityProviders - } - return nil -} - // FinalityProviderDistInfo is the reward distribution of a finality provider and its BTC delegations type FinalityProviderDistInfo struct { // btc_pk is the Bitcoin secp256k1 PK of this finality provider @@ -94,6 +85,9 @@ type FinalityProviderDistInfo struct { TotalVotingPower uint64 `protobuf:"varint,4,opt,name=total_voting_power,json=totalVotingPower,proto3" json:"total_voting_power,omitempty"` // btc_dels is a list of BTC delegations' voting power information under this finality provider BtcDels []*BTCDelDistInfo `protobuf:"bytes,5,rep,name=btc_dels,json=btcDels,proto3" json:"btc_dels,omitempty"` + // is_timestamped indicates whether the finality provider + // has timestamped public randomness committed + IsTimestamped bool `protobuf:"varint,6,opt,name=is_timestamped,json=isTimestamped,proto3" json:"is_timestamped,omitempty"` } func (m *FinalityProviderDistInfo) Reset() { *m = FinalityProviderDistInfo{} } @@ -150,6 +144,13 @@ func (m *FinalityProviderDistInfo) GetBtcDels() []*BTCDelDistInfo { return nil } +func (m *FinalityProviderDistInfo) GetIsTimestamped() bool { + if m != nil { + return m.IsTimestamped + } + return false +} + // BTCDelDistInfo contains the information related to reward distribution for a BTC delegation type BTCDelDistInfo struct { // btc_pk is the Bitcoin secp256k1 PK of this BTC delegation @@ -228,39 +229,43 @@ func init() { } var fileDescriptor_ac354c3bd6d7a66b = []byte{ - // 504 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x93, 0x4f, 0x6f, 0xd3, 0x30, - 0x18, 0xc6, 0x9b, 0xae, 0x1b, 0xe0, 0x8e, 0x7f, 0x56, 0x91, 0xc2, 0x90, 0xb2, 0x52, 0x69, 0xa8, - 0x87, 0x35, 0x61, 0x6c, 0x07, 0xb8, 0x41, 0x16, 0x21, 0x26, 0xfe, 0x45, 0x61, 0xe2, 0xc0, 0x81, - 0xc8, 0x76, 0xdc, 0xc4, 0x6a, 0x12, 0x57, 0xb1, 0x17, 0x9a, 0x6f, 0xc1, 0x87, 0xe0, 0x23, 0xec, - 0x43, 0x70, 0x9c, 0x76, 0x9a, 0x76, 0x98, 0x50, 0x7b, 0xe0, 0x6b, 0xa0, 0x38, 0x81, 0x15, 0xb4, - 0x4a, 0x3d, 0x70, 0xb3, 0xfd, 0x3c, 0xaf, 0xdf, 0xf7, 0xf9, 0x49, 0x2f, 0xd8, 0xc2, 0x08, 0x17, - 0x31, 0x4f, 0x2d, 0x2c, 0x89, 0x90, 0x68, 0xc4, 0xd2, 0xd0, 0xca, 0x77, 0x2c, 0x96, 0x12, 0x9a, - 0x4a, 0x96, 0x53, 0x73, 0x9c, 0x71, 0xc9, 0xe1, 0xbd, 0xda, 0x66, 0x5e, 0xda, 0xcc, 0x7c, 0x67, - 0xa3, 0x13, 0xf2, 0x90, 0x2b, 0x87, 0x55, 0x9e, 0x2a, 0xf3, 0xc6, 0x7d, 0xc2, 0x45, 0xc2, 0x85, - 0x5f, 0x09, 0xd5, 0xa5, 0x92, 0x7a, 0xdf, 0x34, 0xd0, 0xf9, 0xc8, 0x25, 0x4b, 0x43, 0x97, 0x7f, - 0xa1, 0x99, 0xc3, 0x84, 0xdc, 0x47, 0x24, 0xa2, 0x70, 0x1b, 0x40, 0xc9, 0x25, 0x8a, 0xfd, 0x5c, - 0xa9, 0xfe, 0xb8, 0x94, 0x75, 0xad, 0xab, 0xf5, 0x5b, 0xde, 0x1d, 0xa5, 0xcc, 0x95, 0xc1, 0xcf, - 0x00, 0x0e, 0x59, 0x8a, 0x62, 0x26, 0x8b, 0xb2, 0x4b, 0xce, 0x02, 0x9a, 0x09, 0xbd, 0xd9, 0x5d, - 0xe9, 0xb7, 0x9f, 0x58, 0xe6, 0x95, 0xb3, 0x9a, 0x2f, 0xeb, 0x02, 0xb7, 0xf6, 0x97, 0xbd, 0x0f, - 0xd2, 0x21, 0xf7, 0xee, 0x0e, 0xff, 0x51, 0x44, 0xef, 0xac, 0x09, 0xf4, 0x45, 0x7e, 0xf8, 0x1e, - 0xac, 0x61, 0x49, 0xfc, 0xf1, 0x48, 0x8d, 0xb7, 0x6e, 0x3f, 0x3d, 0xbf, 0xd8, 0xdc, 0x0b, 0x99, - 0x8c, 0x8e, 0xb0, 0x49, 0x78, 0x62, 0xd5, 0xed, 0x63, 0x84, 0xc5, 0x80, 0xf1, 0xdf, 0x57, 0x4b, - 0x16, 0x63, 0x2a, 0x4c, 0xfb, 0xc0, 0xdd, 0xdd, 0x7b, 0xec, 0x1e, 0xe1, 0xd7, 0xb4, 0xf0, 0x56, - 0xb1, 0x24, 0xee, 0x08, 0x6e, 0x83, 0x16, 0x0a, 0x82, 0x4c, 0x6f, 0x76, 0xb5, 0xfe, 0x0d, 0x5b, - 0x3f, 0x3d, 0x1e, 0x74, 0x6a, 0x68, 0x2f, 0x82, 0x20, 0xa3, 0x42, 0x7c, 0x90, 0x19, 0x4b, 0x43, - 0x4f, 0xb9, 0xe0, 0x5b, 0x00, 0x08, 0x4f, 0x12, 0x26, 0x04, 0xe3, 0xa9, 0xbe, 0xa2, 0x6a, 0x06, - 0xe7, 0x17, 0x9b, 0x0f, 0xaa, 0x1a, 0x11, 0x8c, 0x4c, 0xc6, 0xad, 0x04, 0xc9, 0xc8, 0x7c, 0x43, - 0x43, 0x44, 0x0a, 0x87, 0x92, 0xd3, 0xe3, 0x01, 0xa8, 0xbf, 0x74, 0x28, 0xf1, 0xe6, 0x3e, 0x58, - 0x00, 0xbe, 0xb5, 0x00, 0xfc, 0x73, 0x70, 0xbd, 0xcc, 0x1e, 0xd0, 0x58, 0xe8, 0xab, 0x0a, 0xf7, - 0xd6, 0x02, 0xdc, 0xf6, 0xe1, 0xbe, 0x43, 0xe3, 0x3f, 0x90, 0xaf, 0x61, 0x49, 0x1c, 0x1a, 0x8b, - 0xde, 0x4f, 0x0d, 0xdc, 0xfa, 0x5b, 0xfb, 0xff, 0x40, 0x9f, 0x81, 0x76, 0x39, 0x09, 0xcd, 0xfc, - 0xa5, 0xb8, 0x82, 0xca, 0x5c, 0x3e, 0xc2, 0x47, 0xe0, 0x76, 0x1d, 0xc2, 0x97, 0x13, 0x3f, 0x42, - 0x22, 0xaa, 0x10, 0x7b, 0x37, 0xeb, 0xe7, 0xc3, 0xc9, 0x2b, 0x24, 0x22, 0xf8, 0x10, 0xac, 0x5f, - 0x01, 0xac, 0x9d, 0x5f, 0xb2, 0xb2, 0xdf, 0x7d, 0x9f, 0x1a, 0xda, 0xc9, 0xd4, 0xd0, 0x7e, 0x4c, - 0x0d, 0xed, 0xeb, 0xcc, 0x68, 0x9c, 0xcc, 0x8c, 0xc6, 0xd9, 0xcc, 0x68, 0x7c, 0x5a, 0x22, 0xdc, - 0x64, 0x7e, 0x21, 0x55, 0x52, 0xbc, 0xa6, 0x56, 0x68, 0xf7, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x84, 0x61, 0x20, 0xde, 0xb3, 0x03, 0x00, 0x00, + // 565 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x53, 0xcd, 0x6e, 0xd3, 0x4c, + 0x14, 0x8d, 0xdb, 0x34, 0x5f, 0x3b, 0xf9, 0xf9, 0x60, 0x14, 0x24, 0x53, 0x24, 0x27, 0x44, 0x04, + 0x65, 0xd1, 0xd8, 0x94, 0x76, 0x01, 0xac, 0xa8, 0x1b, 0x55, 0x54, 0xfc, 0x45, 0x26, 0x62, 0xc1, + 0x02, 0x6b, 0x3c, 0x9e, 0xd8, 0xa3, 0xd8, 0x1e, 0xcb, 0x33, 0x31, 0xc9, 0x1b, 0xb0, 0xe4, 0x11, + 0x78, 0x88, 0x3e, 0x04, 0xcb, 0xa8, 0x2b, 0xd4, 0x45, 0x85, 0x92, 0x05, 0x8f, 0x01, 0xf2, 0x0f, + 0x24, 0xa0, 0x46, 0xea, 0x82, 0xdd, 0xcc, 0x3d, 0xe7, 0xde, 0xb9, 0xe7, 0x1c, 0x0d, 0x68, 0x5b, + 0xc8, 0x9a, 0x7a, 0x2c, 0xd0, 0x2c, 0x81, 0xb9, 0x40, 0x23, 0x1a, 0x38, 0x5a, 0xbc, 0xaf, 0xd1, + 0x00, 0x93, 0x40, 0xd0, 0x98, 0xa8, 0x61, 0xc4, 0x04, 0x83, 0xb7, 0x72, 0x9a, 0xba, 0xa4, 0xa9, + 0xf1, 0xfe, 0x6e, 0xdd, 0x61, 0x0e, 0x4b, 0x19, 0x5a, 0x72, 0xca, 0xc8, 0xbb, 0xb7, 0x31, 0xe3, + 0x3e, 0xe3, 0x66, 0x06, 0x64, 0x97, 0x0c, 0x6a, 0xcd, 0x24, 0x50, 0x7f, 0xcb, 0x04, 0x0d, 0x9c, + 0x3e, 0xfb, 0x40, 0xa2, 0x1e, 0xe5, 0xe2, 0x18, 0x61, 0x97, 0xc0, 0x3d, 0x00, 0x05, 0x13, 0xc8, + 0x33, 0xe3, 0x14, 0x35, 0xc3, 0x04, 0x96, 0xa5, 0xa6, 0xd4, 0x29, 0x1a, 0x37, 0x52, 0x64, 0xa5, + 0x0d, 0xbe, 0x07, 0x70, 0x48, 0x03, 0xe4, 0x51, 0x31, 0x4d, 0x5e, 0x89, 0xa9, 0x4d, 0x22, 0x2e, + 0x6f, 0x34, 0x37, 0x3b, 0xe5, 0x87, 0x9a, 0x7a, 0xe5, 0xae, 0xea, 0x49, 0xde, 0xd0, 0xcf, 0xf9, + 0xc9, 0xdb, 0xa7, 0xc1, 0x90, 0x19, 0x37, 0x87, 0x7f, 0x21, 0x1c, 0xde, 0x03, 0xb5, 0x60, 0xec, + 0x9b, 0x08, 0x27, 0x16, 0x98, 0xc3, 0x90, 0xcb, 0x9b, 0x4d, 0xa9, 0x53, 0x35, 0x2a, 0xc1, 0xd8, + 0x3f, 0x4a, 0x8b, 0x27, 0x21, 0x7f, 0x52, 0xfc, 0xf8, 0xb9, 0x51, 0x68, 0xfd, 0xd8, 0x00, 0xf2, + 0xba, 0xd9, 0xf0, 0x35, 0x28, 0x59, 0x02, 0x9b, 0xe1, 0x28, 0x95, 0x52, 0xd1, 0x1f, 0x5d, 0x5c, + 0x36, 0x0e, 0x1d, 0x2a, 0xdc, 0xb1, 0xa5, 0x62, 0xe6, 0x6b, 0xf9, 0xaa, 0x1e, 0xb2, 0x78, 0x97, + 0xb2, 0x5f, 0x57, 0x4d, 0x4c, 0x43, 0xc2, 0x55, 0xfd, 0xb4, 0x7f, 0x70, 0xf8, 0xa0, 0x3f, 0xb6, + 0x9e, 0x93, 0xa9, 0xb1, 0x65, 0x09, 0xdc, 0x1f, 0xc1, 0x3d, 0x50, 0x44, 0xb6, 0x1d, 0xc9, 0x1b, + 0x4d, 0xa9, 0xb3, 0xa3, 0xcb, 0xe7, 0x67, 0xdd, 0x7a, 0x6e, 0xf0, 0x91, 0x6d, 0x47, 0x84, 0xf3, + 0x37, 0x22, 0xa2, 0x81, 0x63, 0xa4, 0x2c, 0xf8, 0x12, 0x00, 0xcc, 0x7c, 0x9f, 0x72, 0x4e, 0x59, + 0x90, 0x6a, 0xd8, 0xd1, 0xbb, 0x17, 0x97, 0x8d, 0x3b, 0x59, 0x0f, 0xb7, 0x47, 0x2a, 0x65, 0x9a, + 0x8f, 0x84, 0xab, 0xbe, 0x20, 0x0e, 0xc2, 0xd3, 0x1e, 0xc1, 0xe7, 0x67, 0x5d, 0x90, 0x8f, 0xec, + 0x11, 0x6c, 0xac, 0x0c, 0x58, 0x13, 0x52, 0x71, 0x4d, 0x48, 0x4f, 0xc1, 0x76, 0xa2, 0xdd, 0x26, + 0x1e, 0x97, 0xb7, 0xd2, 0x68, 0xda, 0x6b, 0xa2, 0xd1, 0x07, 0xc7, 0x3d, 0xe2, 0xfd, 0x0e, 0xe4, + 0x3f, 0x4b, 0xe0, 0x1e, 0xf1, 0x38, 0x6c, 0x83, 0x1a, 0xe5, 0xa6, 0xa0, 0x3e, 0xe1, 0x02, 0xf9, + 0x21, 0xb1, 0xe5, 0x52, 0x53, 0xea, 0x6c, 0x1b, 0x55, 0xca, 0x07, 0xcb, 0x62, 0xeb, 0xbb, 0x04, + 0x6a, 0x7f, 0x8e, 0xf8, 0xf7, 0xbe, 0x3f, 0x06, 0xe5, 0x64, 0x61, 0x12, 0x99, 0xd7, 0xb2, 0x1f, + 0x64, 0xe4, 0xa4, 0x08, 0xef, 0x83, 0xff, 0x73, 0xad, 0xa6, 0x98, 0x98, 0x2e, 0xe2, 0x6e, 0x96, + 0x84, 0x51, 0xcd, 0xcb, 0x83, 0xc9, 0x33, 0xc4, 0x5d, 0x78, 0x17, 0x54, 0xae, 0xf0, 0xb5, 0x1c, + 0x2f, 0x2d, 0xd5, 0x5f, 0x7d, 0x99, 0x2b, 0xd2, 0x6c, 0xae, 0x48, 0xdf, 0xe6, 0x8a, 0xf4, 0x69, + 0xa1, 0x14, 0x66, 0x0b, 0xa5, 0xf0, 0x75, 0xa1, 0x14, 0xde, 0x5d, 0x43, 0xdc, 0x64, 0xf5, 0x8f, + 0xa7, 0x4a, 0xad, 0x52, 0xfa, 0x2b, 0x0f, 0x7e, 0x06, 0x00, 0x00, 0xff, 0xff, 0x8d, 0x88, 0x9d, + 0x74, 0x06, 0x04, 0x00, 0x00, } func (m *VotingPowerDistCache) Marshal() (dAtA []byte, err error) { @@ -283,6 +288,11 @@ func (m *VotingPowerDistCache) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.NumActiveFps != 0 { + i = encodeVarintIncentive(dAtA, i, uint64(m.NumActiveFps)) + i-- + dAtA[i] = 0x18 + } if len(m.FinalityProviders) > 0 { for iNdEx := len(m.FinalityProviders) - 1; iNdEx >= 0; iNdEx-- { { @@ -325,6 +335,16 @@ func (m *FinalityProviderDistInfo) MarshalToSizedBuffer(dAtA []byte) (int, error _ = i var l int _ = l + if m.IsTimestamped { + i-- + if m.IsTimestamped { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x30 + } if len(m.BtcDels) > 0 { for iNdEx := len(m.BtcDels) - 1; iNdEx >= 0; iNdEx-- { { @@ -458,6 +478,9 @@ func (m *VotingPowerDistCache) Size() (n int) { n += 1 + l + sovIncentive(uint64(l)) } } + if m.NumActiveFps != 0 { + n += 1 + sovIncentive(uint64(m.NumActiveFps)) + } return n } @@ -488,6 +511,9 @@ func (m *FinalityProviderDistInfo) Size() (n int) { n += 1 + l + sovIncentive(uint64(l)) } } + if m.IsTimestamped { + n += 2 + } return n } @@ -603,6 +629,25 @@ func (m *VotingPowerDistCache) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NumActiveFps", wireType) + } + m.NumActiveFps = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIncentive + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.NumActiveFps |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipIncentive(dAtA[iNdEx:]) @@ -809,6 +854,26 @@ func (m *FinalityProviderDistInfo) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IsTimestamped", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIncentive + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.IsTimestamped = bool(v != 0) default: iNdEx = preIndex skippy, err := skipIncentive(dAtA[iNdEx:]) diff --git a/x/btcstaking/types/mocked_keepers.go b/x/btcstaking/types/mocked_keepers.go index d8fcc177..2b7cfc3e 100644 --- a/x/btcstaking/types/mocked_keepers.go +++ b/x/btcstaking/types/mocked_keepers.go @@ -116,6 +116,43 @@ func (mr *MockBtcCheckpointKeeperMockRecorder) GetParams(ctx interface{}) *gomoc return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetParams", reflect.TypeOf((*MockBtcCheckpointKeeper)(nil).GetParams), ctx) } +// MockFinalityKeeper is a mock of FinalityKeeper interface. +type MockFinalityKeeper struct { + ctrl *gomock.Controller + recorder *MockFinalityKeeperMockRecorder +} + +// MockFinalityKeeperMockRecorder is the mock recorder for MockFinalityKeeper. +type MockFinalityKeeperMockRecorder struct { + mock *MockFinalityKeeper +} + +// NewMockFinalityKeeper creates a new mock instance. +func NewMockFinalityKeeper(ctrl *gomock.Controller) *MockFinalityKeeper { + mock := &MockFinalityKeeper{ctrl: ctrl} + mock.recorder = &MockFinalityKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockFinalityKeeper) EXPECT() *MockFinalityKeeperMockRecorder { + return m.recorder +} + +// HasTimestampedPubRand mocks base method. +func (m *MockFinalityKeeper) HasTimestampedPubRand(ctx context.Context, fpBtcPK *types.BIP340PubKey, height uint64) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HasTimestampedPubRand", ctx, fpBtcPK, height) + ret0, _ := ret[0].(bool) + return ret0 +} + +// HasTimestampedPubRand indicates an expected call of HasTimestampedPubRand. +func (mr *MockFinalityKeeperMockRecorder) HasTimestampedPubRand(ctx, fpBtcPK, height interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasTimestampedPubRand", reflect.TypeOf((*MockFinalityKeeper)(nil).HasTimestampedPubRand), ctx, fpBtcPK, height) +} + // MockBtcStakingHooks is a mock of BtcStakingHooks interface. type MockBtcStakingHooks struct { ctrl *gomock.Controller diff --git a/x/finality/keeper/msg_server.go b/x/finality/keeper/msg_server.go index 8282074f..7fdb6172 100644 --- a/x/finality/keeper/msg_server.go +++ b/x/finality/keeper/msg_server.go @@ -97,18 +97,11 @@ func (ms msgServer) AddFinalitySig(goCtx context.Context, req *types.MsgAddFinal return &types.MsgAddFinalitySigResponse{}, nil } - // find the public randomness commitment for this height from this finality provider - prCommit, err := ms.GetPubRandCommitForHeight(ctx, req.FpBtcPk, req.BlockHeight) + // find the timestamped public randomness commitment for this height from this finality provider + prCommit, err := ms.GetTimestampedPubRandCommitForHeight(ctx, req.FpBtcPk, req.BlockHeight) if err != nil { return nil, err } - // ensure the finality provider's last randomness commit is already finalised by BTC timestamping - finalizedEpoch := ms.GetLastFinalizedEpoch(ctx) - if finalizedEpoch < prCommit.EpochNum { - return nil, types.ErrPubRandCommitNotBTCTimestamped. - Wrapf("the finality provider %s last committed epoch number: %d, last finalized epoch number: %d", - fp.BtcPk.MarshalHex(), prCommit.EpochNum, finalizedEpoch) - } // verify the finality signature message w.r.t. the public randomness commitment // including the public randomness inclusion proof and the finality signature diff --git a/x/finality/keeper/public_randomness.go b/x/finality/keeper/public_randomness.go index 68cb87e8..1fef0066 100644 --- a/x/finality/keeper/public_randomness.go +++ b/x/finality/keeper/public_randomness.go @@ -7,9 +7,10 @@ import ( "github.com/cosmos/cosmos-sdk/runtime" "cosmossdk.io/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + bbn "github.com/babylonlabs-io/babylon/types" "github.com/babylonlabs-io/babylon/x/finality/types" - sdk "github.com/cosmos/cosmos-sdk/types" ) /* @@ -33,6 +34,30 @@ func (k Keeper) GetPubRandCommitForHeight(ctx context.Context, fpBtcPK *bbn.BIP3 return nil, types.ErrPubRandNotFound } +// GetTimestampedPubRandCommitForHeight finds the public randomness commitment that includes the given +// height for the given finality provider +func (k Keeper) GetTimestampedPubRandCommitForHeight(ctx context.Context, fpBtcPK *bbn.BIP340PubKey, height uint64) (*types.PubRandCommit, error) { + prCommit, err := k.GetPubRandCommitForHeight(ctx, fpBtcPK, height) + if err != nil { + return nil, err + } + + // ensure the finality provider's last randomness commit is already finalised by BTC timestamping + finalizedEpoch := k.GetLastFinalizedEpoch(ctx) + if finalizedEpoch < prCommit.EpochNum { + return nil, types.ErrPubRandCommitNotBTCTimestamped. + Wrapf("the finality provider %s last committed epoch number: %d, last finalized epoch number: %d", + fpBtcPK.MarshalHex(), prCommit.EpochNum, finalizedEpoch) + } + + return prCommit, nil +} + +func (k Keeper) HasTimestampedPubRand(ctx context.Context, fpBtcPK *bbn.BIP340PubKey, height uint64) bool { + _, err := k.GetTimestampedPubRandCommitForHeight(ctx, fpBtcPK, height) + return err != nil +} + // SetPubRandCommit adds the given public randomness commitment for the given public key func (k Keeper) SetPubRandCommit(ctx context.Context, fpBtcPK *bbn.BIP340PubKey, prCommit *types.PubRandCommit) { store := k.pubRandCommitFpStore(ctx, fpBtcPK) diff --git a/x/finality/keeper/tallying.go b/x/finality/keeper/tallying.go index 9af4c6fe..efc2ef4e 100644 --- a/x/finality/keeper/tallying.go +++ b/x/finality/keeper/tallying.go @@ -4,8 +4,9 @@ import ( "context" "fmt" - "github.com/babylonlabs-io/babylon/x/finality/types" sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/babylonlabs-io/babylon/x/finality/types" ) // TallyBlocks tries to finalise all blocks that are non-finalised AND have a non-nil @@ -89,8 +90,7 @@ func (k Keeper) finalizeBlock(ctx context.Context, block *types.IndexedBlock, vo panic(err) } // filter out voted finality providers - maxActiveFPs := k.BTCStakingKeeper.GetParams(ctx).MaxActiveFinalityProviders - filteredDc := dc.FilterVotedDistCache(maxActiveFPs, voterBTCPKs) + filteredDc := dc.FilterVotedDistCache(voterBTCPKs) // reward voted finality providers k.IncentiveKeeper.RewardBTCStaking(ctx, block.Height, filteredDc) // remove reward distribution cache afterwards diff --git a/x/finality/types/errors.go b/x/finality/types/errors.go index 6e3b89ee..12a2966d 100644 --- a/x/finality/types/errors.go +++ b/x/finality/types/errors.go @@ -10,12 +10,11 @@ var ( ErrVoteNotFound = errorsmod.Register(ModuleName, 1101, "vote is not found") ErrHeightTooHigh = errorsmod.Register(ModuleName, 1102, "the chain has not reached the given height yet") ErrPubRandNotFound = errorsmod.Register(ModuleName, 1103, "public randomness is not found") - ErrPubRandCommitNotFound = errorsmod.Register(ModuleName, 1104, "public randomness commitment is not found") - ErrNoPubRandYet = errorsmod.Register(ModuleName, 1105, "the finality provider has not committed any public randomness yet") - ErrTooFewPubRand = errorsmod.Register(ModuleName, 1106, "the request contains too few public randomness") - ErrInvalidPubRand = errorsmod.Register(ModuleName, 1107, "the public randomness list is invalid") - ErrEvidenceNotFound = errorsmod.Register(ModuleName, 1108, "evidence is not found") - ErrInvalidFinalitySig = errorsmod.Register(ModuleName, 1109, "finality signature is not valid") - ErrNoSlashableEvidence = errorsmod.Register(ModuleName, 1110, "there is no slashable evidence") - ErrPubRandCommitNotBTCTimestamped = errorsmod.Register(ModuleName, 1111, "the public randomness commit is not BTC timestamped yet") + ErrNoPubRandYet = errorsmod.Register(ModuleName, 1104, "the finality provider has not committed any public randomness yet") + ErrTooFewPubRand = errorsmod.Register(ModuleName, 1105, "the request contains too few public randomness") + ErrInvalidPubRand = errorsmod.Register(ModuleName, 1106, "the public randomness list is invalid") + ErrEvidenceNotFound = errorsmod.Register(ModuleName, 1107, "evidence is not found") + ErrInvalidFinalitySig = errorsmod.Register(ModuleName, 1108, "finality signature is not valid") + ErrNoSlashableEvidence = errorsmod.Register(ModuleName, 1109, "there is no slashable evidence") + ErrPubRandCommitNotBTCTimestamped = errorsmod.Register(ModuleName, 1110, "the public randomness commit is not BTC timestamped yet") )