mirror of
https://github.com/0glabs/0g-chain.git
synced 2025-01-12 08:15:18 +00:00
Override original community-pool query service (#1430)
* initial version * override x/distribution community-pool query * test subset of original x/distribution queries Co-authored-by: rhuairahrighairigh <ruaridh.odonnell@gmail.com>
This commit is contained in:
parent
4c1524d7bc
commit
ad0d1f80c8
25
app/app.go
25
app/app.go
@ -90,6 +90,7 @@ import (
|
|||||||
|
|
||||||
"github.com/kava-labs/kava/app/ante"
|
"github.com/kava-labs/kava/app/ante"
|
||||||
kavaparams "github.com/kava-labs/kava/app/params"
|
kavaparams "github.com/kava-labs/kava/app/params"
|
||||||
|
kavadistrquery "github.com/kava-labs/kava/app/query/distribution"
|
||||||
"github.com/kava-labs/kava/x/auction"
|
"github.com/kava-labs/kava/x/auction"
|
||||||
auctionkeeper "github.com/kava-labs/kava/x/auction/keeper"
|
auctionkeeper "github.com/kava-labs/kava/x/auction/keeper"
|
||||||
auctiontypes "github.com/kava-labs/kava/x/auction/types"
|
auctiontypes "github.com/kava-labs/kava/x/auction/types"
|
||||||
@ -898,7 +899,7 @@ func NewApp(
|
|||||||
app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino)
|
app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino)
|
||||||
|
|
||||||
app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
|
app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
|
||||||
app.mm.RegisterServices(app.configurator)
|
app.RegisterServices(app.configurator)
|
||||||
|
|
||||||
// RegisterUpgradeHandlers is used for registering any on-chain upgrades.
|
// RegisterUpgradeHandlers is used for registering any on-chain upgrades.
|
||||||
// It needs to be called after `app.mm` and `app.configurator` are set.
|
// It needs to be called after `app.mm` and `app.configurator` are set.
|
||||||
@ -971,6 +972,28 @@ func NewApp(
|
|||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (app *App) RegisterServices(cfg module.Configurator) {
|
||||||
|
// Register services from all unmodified modules
|
||||||
|
for _, module := range app.mm.Modules {
|
||||||
|
// skip registration of distribution services
|
||||||
|
if module.Name() == distrtypes.ModuleName {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
module.RegisterServices(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// register ditribution services except query server
|
||||||
|
distrtypes.RegisterMsgServer(cfg.MsgServer(), distrkeeper.NewMsgServerImpl(app.distrKeeper))
|
||||||
|
cfg.RegisterMigration(
|
||||||
|
distrtypes.ModuleName,
|
||||||
|
1,
|
||||||
|
distrkeeper.NewMigrator(app.distrKeeper).Migrate1to2,
|
||||||
|
)
|
||||||
|
|
||||||
|
// register fake distribution query server
|
||||||
|
distrtypes.RegisterQueryServer(cfg.QueryServer(), kavadistrquery.NewQueryServer(app.distrKeeper, app.communityKeeper))
|
||||||
|
}
|
||||||
|
|
||||||
// BeginBlocker contains app specific logic for the BeginBlock abci call.
|
// BeginBlocker contains app specific logic for the BeginBlock abci call.
|
||||||
func (app *App) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
|
func (app *App) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
|
||||||
return app.mm.BeginBlock(ctx, req)
|
return app.mm.BeginBlock(ctx, req)
|
||||||
|
10
app/query/distribution/expected_keepers.go
Normal file
10
app/query/distribution/expected_keepers.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package distribution
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CommunityKeeper defines the contract needed to be fulfilled for community module dependencies.
|
||||||
|
type CommunityKeeper interface {
|
||||||
|
GetModuleAccountBalance(sdk.Context) sdk.Coins
|
||||||
|
}
|
38
app/query/distribution/query.go
Normal file
38
app/query/distribution/query.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package distribution
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
||||||
|
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ distrtypes.QueryServer = &queryServer{}
|
||||||
|
|
||||||
|
type queryServer struct {
|
||||||
|
distrkeeper.Keeper
|
||||||
|
|
||||||
|
communityKeeper CommunityKeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewQueryServer returns a grpc query server for the distribution module.
|
||||||
|
// It forwards most requests to the distribution keeper, except for the community pool request
|
||||||
|
// which is mapped to the kava community module.
|
||||||
|
func NewQueryServer(distrKeeper distrkeeper.Keeper, commKeeper CommunityKeeper) distrtypes.QueryServer {
|
||||||
|
return &queryServer{
|
||||||
|
Keeper: distrKeeper,
|
||||||
|
communityKeeper: commKeeper,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommunityPool queries the kava community module
|
||||||
|
// The original community pool, which is a separately accounted for portion of x/auth's fee pool
|
||||||
|
// is replaces with the x/community module account.
|
||||||
|
// TODO: implement legacy community pool balance query in x/community
|
||||||
|
// To query the original community pool, including historical values, use x/community's LegacyCommunityPoolBalance
|
||||||
|
func (q queryServer) CommunityPool(c context.Context, req *distrtypes.QueryCommunityPoolRequest) (*distrtypes.QueryCommunityPoolResponse, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(c)
|
||||||
|
balance := q.communityKeeper.GetModuleAccountBalance(ctx)
|
||||||
|
return &distrtypes.QueryCommunityPoolResponse{Pool: sdk.NewDecCoinsFromCoins(balance...)}, nil
|
||||||
|
}
|
170
app/query/distribution/query_test.go
Normal file
170
app/query/distribution/query_test.go
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
package distribution_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||||
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||||
|
tmtime "github.com/tendermint/tendermint/types/time"
|
||||||
|
|
||||||
|
"github.com/kava-labs/kava/app"
|
||||||
|
distrquery "github.com/kava-labs/kava/app/query/distribution"
|
||||||
|
communitytypes "github.com/kava-labs/kava/x/community/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type queryTestSuite struct {
|
||||||
|
suite.Suite
|
||||||
|
|
||||||
|
App app.TestApp
|
||||||
|
Ctx sdk.Context
|
||||||
|
|
||||||
|
queryClient distrtypes.QueryClient
|
||||||
|
communityPoolAddress sdk.AccAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *queryTestSuite) SetupTest() {
|
||||||
|
app.SetSDKConfig()
|
||||||
|
tApp := app.NewTestApp()
|
||||||
|
ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: tmtime.Now()})
|
||||||
|
|
||||||
|
tApp.InitializeFromGenesisStates()
|
||||||
|
|
||||||
|
suite.App = tApp
|
||||||
|
suite.Ctx = ctx
|
||||||
|
|
||||||
|
queryHelper := baseapp.NewQueryServerTestHelper(suite.Ctx, suite.App.InterfaceRegistry())
|
||||||
|
distrtypes.RegisterQueryServer(queryHelper, distrquery.NewQueryServer(
|
||||||
|
tApp.GetDistrKeeper(),
|
||||||
|
tApp.GetCommunityKeeper(),
|
||||||
|
))
|
||||||
|
suite.queryClient = distrtypes.NewQueryClient(queryHelper)
|
||||||
|
suite.communityPoolAddress = tApp.GetAccountKeeper().GetModuleAddress(communitytypes.ModuleAccountName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGRPQueryTestSuite(t *testing.T) {
|
||||||
|
suite.Run(t, new(queryTestSuite))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite queryTestSuite) FundCommunityPool(amt sdk.Coins) {
|
||||||
|
err := suite.App.FundModuleAccount(suite.Ctx, communitytypes.ModuleAccountName, amt)
|
||||||
|
suite.NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite queryTestSuite) CheckCommunityPoolBalance(expected sdk.Coins, result sdk.DecCoins) {
|
||||||
|
actual := suite.App.GetBankKeeper().GetAllBalances(suite.Ctx, suite.communityPoolAddress)
|
||||||
|
// check that account was properly funded
|
||||||
|
suite.Equal(expected, actual, "unexpected community pool balance")
|
||||||
|
|
||||||
|
// transform the expected values to DecCoins to compare with result
|
||||||
|
decCoins := sdk.NewDecCoinsFromCoins(expected...)
|
||||||
|
suite.True(decCoins.IsEqual(result), "unexpected community pool query response")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *queryTestSuite) Test_CommunityPoolOverride() {
|
||||||
|
singleDenom := sdk.NewCoins(sdk.NewInt64Coin("ukava", 1e10))
|
||||||
|
multiDenom := singleDenom.Add(sdk.NewInt64Coin("other-denom", 1e9))
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
funds sdk.Coins
|
||||||
|
}{
|
||||||
|
{"single denom", singleDenom},
|
||||||
|
{"multiple denoms", multiDenom},
|
||||||
|
{"no balance", sdk.NewCoins()},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("queries the correct balance - %s", tc.name), func() {
|
||||||
|
suite.SetupTest()
|
||||||
|
|
||||||
|
// init community pool funds
|
||||||
|
if !tc.funds.IsZero() {
|
||||||
|
suite.FundCommunityPool(tc.funds)
|
||||||
|
}
|
||||||
|
|
||||||
|
// query the overridden endpoint
|
||||||
|
balance, err := suite.queryClient.CommunityPool(
|
||||||
|
context.Background(),
|
||||||
|
&distrtypes.QueryCommunityPoolRequest{},
|
||||||
|
)
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.CheckCommunityPoolBalance(tc.funds, balance.Pool)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// modified from sdk test of distribution querier
|
||||||
|
func (suite *queryTestSuite) Test_OGDistributionQueries() {
|
||||||
|
suite.SetupTest()
|
||||||
|
|
||||||
|
ctx, distrKeeper, stakingKeeper := suite.Ctx, suite.App.GetDistrKeeper(), suite.App.GetStakingKeeper()
|
||||||
|
|
||||||
|
// setup a validator
|
||||||
|
addr := app.RandomAddress()
|
||||||
|
valAddr := sdk.ValAddress(addr)
|
||||||
|
bondDenom := stakingKeeper.BondDenom(ctx)
|
||||||
|
|
||||||
|
// test param queries
|
||||||
|
params := distrtypes.Params{
|
||||||
|
CommunityTax: sdk.ZeroDec(),
|
||||||
|
BaseProposerReward: sdk.NewDecWithPrec(2, 1),
|
||||||
|
BonusProposerReward: sdk.NewDecWithPrec(1, 1),
|
||||||
|
WithdrawAddrEnabled: true,
|
||||||
|
}
|
||||||
|
distrKeeper.SetParams(ctx, params)
|
||||||
|
r1, err := suite.queryClient.Params(context.Background(), &distrtypes.QueryParamsRequest{})
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.Equal(params, r1.Params)
|
||||||
|
|
||||||
|
// test outstanding rewards query
|
||||||
|
outstandingRewards := sdk.NewDecCoins(sdk.NewInt64DecCoin(bondDenom, 100), sdk.NewInt64DecCoin("other", 10))
|
||||||
|
distrKeeper.SetValidatorOutstandingRewards(ctx, valAddr, distrtypes.ValidatorOutstandingRewards{Rewards: outstandingRewards})
|
||||||
|
r2, err := suite.queryClient.ValidatorOutstandingRewards(context.Background(), &distrtypes.QueryValidatorOutstandingRewardsRequest{ValidatorAddress: valAddr.String()})
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.Equal(outstandingRewards, r2.Rewards.Rewards)
|
||||||
|
|
||||||
|
// test validator commission query
|
||||||
|
commission := sdk.DecCoins{{Denom: "token1", Amount: sdk.NewDec(4)}, {Denom: "token2", Amount: sdk.NewDec(2)}}
|
||||||
|
distrKeeper.SetValidatorAccumulatedCommission(ctx, valAddr, distrtypes.ValidatorAccumulatedCommission{Commission: commission})
|
||||||
|
r3, err := suite.queryClient.ValidatorCommission(context.Background(), &distrtypes.QueryValidatorCommissionRequest{ValidatorAddress: valAddr.String()})
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.Equal(commission, r3.Commission.Commission)
|
||||||
|
|
||||||
|
// test delegator's total rewards query
|
||||||
|
r4, err := suite.queryClient.DelegationTotalRewards(context.Background(), &distrtypes.QueryDelegationTotalRewardsRequest{DelegatorAddress: addr.String()})
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.Equal(&distrtypes.QueryDelegationTotalRewardsResponse{}, r4)
|
||||||
|
|
||||||
|
// test validator slashes query with height range
|
||||||
|
slashOne := distrtypes.NewValidatorSlashEvent(3, sdk.NewDecWithPrec(5, 1))
|
||||||
|
slashTwo := distrtypes.NewValidatorSlashEvent(7, sdk.NewDecWithPrec(6, 1))
|
||||||
|
distrKeeper.SetValidatorSlashEvent(ctx, valAddr, 3, 0, slashOne)
|
||||||
|
distrKeeper.SetValidatorSlashEvent(ctx, valAddr, 7, 0, slashTwo)
|
||||||
|
slashes := suite.getQueriedValidatorSlashes(valAddr, 0, 2)
|
||||||
|
suite.Equal(0, len(slashes))
|
||||||
|
slashes = suite.getQueriedValidatorSlashes(valAddr, 0, 5)
|
||||||
|
suite.Equal([]distrtypes.ValidatorSlashEvent{slashOne}, slashes)
|
||||||
|
slashes = suite.getQueriedValidatorSlashes(valAddr, 0, 10)
|
||||||
|
suite.Equal([]distrtypes.ValidatorSlashEvent{slashOne, slashTwo}, slashes)
|
||||||
|
|
||||||
|
// non-zero delegator reward queries are not tested here.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *queryTestSuite) getQueriedValidatorSlashes(validatorAddr sdk.ValAddress, startHeight uint64, endHeight uint64) (slashes []distrtypes.ValidatorSlashEvent) {
|
||||||
|
result, err := suite.queryClient.ValidatorSlashes(
|
||||||
|
context.Background(),
|
||||||
|
&distrtypes.QueryValidatorSlashesRequest{
|
||||||
|
ValidatorAddress: validatorAddr.String(),
|
||||||
|
StartingHeight: startHeight,
|
||||||
|
EndingHeight: endHeight,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
suite.NoError(err)
|
||||||
|
return result.Slashes
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user