From 2e3c52bae1010766174e02524085ea5d8709431e Mon Sep 17 00:00:00 2001 From: colin axner Date: Thu, 1 Aug 2019 11:56:50 -0700 Subject: [PATCH] Merge PR #4788: Query genesis transactions --- .../improvements/rest/3867-Allow-querying- | 1 + simapp/app.go | 2 +- x/auth/client/rest/query.go | 34 ++++++++++----- x/auth/client/rest/rest.go | 2 +- x/distribution/keeper/test_common.go | 2 +- x/genutil/client/rest/query.go | 41 +++++++++++++++++++ x/gov/test_common.go | 2 +- x/mint/internal/keeper/common_test.go | 2 +- x/slashing/app_test.go | 2 +- x/slashing/internal/keeper/test_common.go | 2 +- x/staking/app_test.go | 2 +- x/staking/keeper/pool.go | 2 +- x/staking/keeper/test_common.go | 6 +-- x/staking/types/expected_keepers.go | 3 +- x/supply/exported/exported.go | 20 ++++++++- x/supply/genesis.go | 6 ++- x/supply/internal/keeper/bank.go | 5 ++- x/supply/internal/keeper/bank_test.go | 16 ++++---- x/supply/internal/keeper/common_test.go | 2 +- x/supply/internal/keeper/invariants.go | 4 +- x/supply/internal/keeper/keeper.go | 8 ++-- x/supply/internal/keeper/keeper_test.go | 2 +- x/supply/internal/keeper/querier.go | 7 +++- x/supply/internal/types/codec.go | 2 + x/supply/internal/types/genesis.go | 8 +++- x/supply/internal/types/supply.go | 31 +++++++++++--- x/supply/internal/types/supply_test.go | 2 +- 27 files changed, 158 insertions(+), 58 deletions(-) create mode 100644 .pending/improvements/rest/3867-Allow-querying- create mode 100644 x/genutil/client/rest/query.go diff --git a/.pending/improvements/rest/3867-Allow-querying- b/.pending/improvements/rest/3867-Allow-querying- new file mode 100644 index 000000000000..2681ec8b56b8 --- /dev/null +++ b/.pending/improvements/rest/3867-Allow-querying- @@ -0,0 +1 @@ +# 3867 Allow querying for genesis transaction when height query param is set to zero. diff --git a/simapp/app.go b/simapp/app.go index aeca5e346345..5fe65516f27d 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -142,7 +142,7 @@ func NewSimApp( // add keepers app.accountKeeper = auth.NewAccountKeeper(app.cdc, keys[auth.StoreKey], authSubspace, auth.ProtoBaseAccount) app.bankKeeper = bank.NewBaseKeeper(app.accountKeeper, bankSubspace, bank.DefaultCodespace, app.ModuleAccountAddrs()) - app.supplyKeeper = supply.NewKeeper(app.cdc, keys[supply.StoreKey], app.accountKeeper, app.bankKeeper, supply.DefaultCodespace, maccPerms) + app.supplyKeeper = supply.NewKeeper(app.cdc, keys[supply.StoreKey], app.accountKeeper, app.bankKeeper, maccPerms) stakingKeeper := staking.NewKeeper(app.cdc, keys[staking.StoreKey], tkeys[staking.TStoreKey], app.supplyKeeper, stakingSubspace, staking.DefaultCodespace) app.mintKeeper = mint.NewKeeper(app.cdc, keys[mint.StoreKey], mintSubspace, &stakingKeeper, app.supplyKeeper, auth.FeeCollectorName) diff --git a/x/auth/client/rest/query.go b/x/auth/client/rest/query.go index 8c65d3441889..daf4d34e22d6 100644 --- a/x/auth/client/rest/query.go +++ b/x/auth/client/rest/query.go @@ -3,6 +3,7 @@ package rest import ( "fmt" "net/http" + "strconv" "strings" "github.com/gorilla/mux" @@ -12,6 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/rest" "github.com/cosmos/cosmos-sdk/x/auth/client/utils" "github.com/cosmos/cosmos-sdk/x/auth/types" + genutilrest "github.com/cosmos/cosmos-sdk/x/genutil/client/rest" ) // query accountREST Handler @@ -50,16 +52,11 @@ func QueryAccountRequestHandlerFn(storeName string, cliCtx context.CLIContext) h } } -// QueryTxsByEventsRequestHandlerFn implements a REST handler that searches for -// transactions by events. -func QueryTxsByEventsRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { +// QueryTxsHandlerFn implements a REST handler that searches for transactions. +// Genesis transactions are returned if the height parameter is set to zero, +// otherwise the transactions are searched for by events. +func QueryTxsRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var ( - tags []string - txs []sdk.TxResponse - page, limit int - ) - err := r.ParseForm() if err != nil { rest.WriteErrorResponse(w, http.StatusBadRequest, @@ -67,6 +64,21 @@ func QueryTxsByEventsRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFun return } + // if the height query param is set to zero, query for genesis transactions + heightStr := r.FormValue("height") + if heightStr != "" { + if height, err := strconv.ParseInt(heightStr, 10, 64); err == nil && height == 0 { + genutilrest.QueryGenesisTxs(cliCtx, w) + return + } + } + + var ( + events []string + txs []sdk.TxResponse + page, limit int + ) + cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) if !ok { return @@ -77,13 +89,13 @@ func QueryTxsByEventsRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFun return } - tags, page, limit, err = rest.ParseHTTPArgs(r) + events, page, limit, err = rest.ParseHTTPArgs(r) if err != nil { rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } - searchResult, err := utils.QueryTxsByEvents(cliCtx, tags, page, limit) + searchResult, err := utils.QueryTxsByEvents(cliCtx, events, page, limit) if err != nil { rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return diff --git a/x/auth/client/rest/rest.go b/x/auth/client/rest/rest.go index a93d48c620fc..99acd4e5d441 100644 --- a/x/auth/client/rest/rest.go +++ b/x/auth/client/rest/rest.go @@ -16,7 +16,7 @@ func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, storeName string) // RegisterTxRoutes registers all transaction routes on the provided router. func RegisterTxRoutes(cliCtx context.CLIContext, r *mux.Router) { r.HandleFunc("/txs/{hash}", QueryTxRequestHandlerFn(cliCtx)).Methods("GET") - r.HandleFunc("/txs", QueryTxsByEventsRequestHandlerFn(cliCtx)).Methods("GET") + r.HandleFunc("/txs", QueryTxsRequestHandlerFn(cliCtx)).Methods("GET") r.HandleFunc("/txs", BroadcastTxRequest(cliCtx)).Methods("POST") r.HandleFunc("/txs/encode", EncodeTxRequestHandlerFn(cliCtx)).Methods("POST") } diff --git a/x/distribution/keeper/test_common.go b/x/distribution/keeper/test_common.go index ec4bb171a6e3..e541da76db05 100644 --- a/x/distribution/keeper/test_common.go +++ b/x/distribution/keeper/test_common.go @@ -138,7 +138,7 @@ func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initPower int64, staking.NotBondedPoolName: {supply.Burner, supply.Staking}, staking.BondedPoolName: {supply.Burner, supply.Staking}, } - supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bankKeeper, supply.DefaultCodespace, maccPerms) + supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bankKeeper, maccPerms) sk := staking.NewKeeper(cdc, keyStaking, tkeyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace), staking.DefaultCodespace) sk.SetParams(ctx, staking.DefaultParams()) diff --git a/x/genutil/client/rest/query.go b/x/genutil/client/rest/query.go new file mode 100644 index 000000000000..157384dcaaf6 --- /dev/null +++ b/x/genutil/client/rest/query.go @@ -0,0 +1,41 @@ +package rest + +import ( + "net/http" + + "github.com/cosmos/cosmos-sdk/client/context" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/rest" + "github.com/cosmos/cosmos-sdk/x/genutil/types" +) + +// QueryGenesisTxs writes the genesis transactions to the response if no error +// occurs. +func QueryGenesisTxs(cliCtx context.CLIContext, w http.ResponseWriter) { + resultGenesis, err := cliCtx.Client.Genesis() + if err != nil { + rest.WriteErrorResponse(w, http.StatusInternalServerError, + sdk.AppendMsgToErr("could not retrieve genesis from client", err.Error())) + return + } + + appState, err := types.GenesisStateFromGenDoc(cliCtx.Codec, *resultGenesis.Genesis) + if err != nil { + rest.WriteErrorResponse(w, http.StatusInternalServerError, + sdk.AppendMsgToErr("could not decode genesis doc", err.Error())) + return + } + + genState := types.GetGenesisStateFromAppState(cliCtx.Codec, appState) + genTxs := make([]sdk.Tx, len(genState.GenTxs)) + for i, tx := range genState.GenTxs { + err := cliCtx.Codec.UnmarshalJSON(tx, &genTxs[i]) + if err != nil { + rest.WriteErrorResponse(w, http.StatusInternalServerError, + sdk.AppendMsgToErr("could not decode genesis transaction", err.Error())) + return + } + } + + rest.PostProcessResponse(w, cliCtx, genTxs) +} diff --git a/x/gov/test_common.go b/x/gov/test_common.go index 7fad65a16527..63ac76f19d03 100644 --- a/x/gov/test_common.go +++ b/x/gov/test_common.go @@ -74,7 +74,7 @@ func getMockApp(t *testing.T, numGenAccs int, genState GenesisState, genAccs []a staking.NotBondedPoolName: {supply.Burner, supply.Staking}, staking.BondedPoolName: {supply.Burner, supply.Staking}, } - supplyKeeper := supply.NewKeeper(mApp.Cdc, keySupply, mApp.AccountKeeper, bk, supply.DefaultCodespace, maccPerms) + supplyKeeper := supply.NewKeeper(mApp.Cdc, keySupply, mApp.AccountKeeper, bk, maccPerms) sk := staking.NewKeeper(mApp.Cdc, keyStaking, tKeyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace), staking.DefaultCodespace) keeper := NewKeeper(mApp.Cdc, keyGov, pk, pk.Subspace(DefaultParamspace), supplyKeeper, sk, DefaultCodespace, rtr) diff --git a/x/mint/internal/keeper/common_test.go b/x/mint/internal/keeper/common_test.go index 807ead3e9063..0c2488621baa 100644 --- a/x/mint/internal/keeper/common_test.go +++ b/x/mint/internal/keeper/common_test.go @@ -74,7 +74,7 @@ func newTestInput(t *testing.T) testInput { staking.NotBondedPoolName: {supply.Burner, supply.Staking}, staking.BondedPoolName: {supply.Burner, supply.Staking}, } - supplyKeeper := supply.NewKeeper(types.ModuleCdc, keySupply, accountKeeper, bankKeeper, supply.DefaultCodespace, maccPerms) + supplyKeeper := supply.NewKeeper(types.ModuleCdc, keySupply, accountKeeper, bankKeeper, maccPerms) supplyKeeper.SetSupply(ctx, supply.NewSupply(sdk.Coins{})) stakingKeeper := staking.NewKeeper( diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index da3b886867ba..a1ce02fef0cd 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -53,7 +53,7 @@ func getMockApp(t *testing.T) (*mock.App, staking.Keeper, Keeper) { staking.NotBondedPoolName: {supply.Burner, supply.Staking}, staking.BondedPoolName: {supply.Burner, supply.Staking}, } - supplyKeeper := supply.NewKeeper(mapp.Cdc, keySupply, mapp.AccountKeeper, bankKeeper, supply.DefaultCodespace, maccPerms) + supplyKeeper := supply.NewKeeper(mapp.Cdc, keySupply, mapp.AccountKeeper, bankKeeper, maccPerms) stakingKeeper := staking.NewKeeper(mapp.Cdc, keyStaking, tkeyStaking, supplyKeeper, mapp.ParamsKeeper.Subspace(staking.DefaultParamspace), staking.DefaultCodespace) keeper := NewKeeper(mapp.Cdc, keySlashing, stakingKeeper, mapp.ParamsKeeper.Subspace(DefaultParamspace), DefaultCodespace) mapp.Router().AddRoute(staking.RouterKey, staking.NewHandler(stakingKeeper)) diff --git a/x/slashing/internal/keeper/test_common.go b/x/slashing/internal/keeper/test_common.go index 66287366885c..d8456dc401ff 100644 --- a/x/slashing/internal/keeper/test_common.go +++ b/x/slashing/internal/keeper/test_common.go @@ -99,7 +99,7 @@ func CreateTestInput(t *testing.T, defaults types.Params) (sdk.Context, bank.Kee staking.NotBondedPoolName: {supply.Burner, supply.Staking}, staking.BondedPoolName: {supply.Burner, supply.Staking}, } - supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bk, supply.DefaultCodespace, maccPerms) + supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bk, maccPerms) totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, InitTokens.MulRaw(int64(len(Addrs))))) supplyKeeper.SetSupply(ctx, supply.NewSupply(totalSupply)) diff --git a/x/staking/app_test.go b/x/staking/app_test.go index 0f34cf21b48d..1f148de06bdc 100644 --- a/x/staking/app_test.go +++ b/x/staking/app_test.go @@ -41,7 +41,7 @@ func getMockApp(t *testing.T) (*mock.App, Keeper) { types.NotBondedPoolName: {supply.Burner, supply.Staking}, types.BondedPoolName: {supply.Burner, supply.Staking}, } - supplyKeeper := supply.NewKeeper(mApp.Cdc, keySupply, mApp.AccountKeeper, bankKeeper, supply.DefaultCodespace, maccPerms) + supplyKeeper := supply.NewKeeper(mApp.Cdc, keySupply, mApp.AccountKeeper, bankKeeper, maccPerms) keeper := NewKeeper(mApp.Cdc, keyStaking, tkeyStaking, supplyKeeper, mApp.ParamsKeeper.Subspace(DefaultParamspace), DefaultCodespace) mApp.Router().AddRoute(RouterKey, NewHandler(keeper)) diff --git a/x/staking/keeper/pool.go b/x/staking/keeper/pool.go index 0c6cfcafe8ef..4ceb02446d93 100644 --- a/x/staking/keeper/pool.go +++ b/x/staking/keeper/pool.go @@ -62,7 +62,7 @@ func (k Keeper) TotalBondedTokens(ctx sdk.Context) sdk.Int { // StakingTokenSupply staking tokens from the total supply func (k Keeper) StakingTokenSupply(ctx sdk.Context) sdk.Int { - return k.supplyKeeper.GetSupply(ctx).Total.AmountOf(k.BondDenom(ctx)) + return k.supplyKeeper.GetSupply(ctx).GetTotal().AmountOf(k.BondDenom(ctx)) } // BondedRatio the fraction of the staking tokens which are currently bonded diff --git a/x/staking/keeper/test_common.go b/x/staking/keeper/test_common.go index 14b26be4874d..413a762158c4 100644 --- a/x/staking/keeper/test_common.go +++ b/x/staking/keeper/test_common.go @@ -24,7 +24,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/params" "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/cosmos/cosmos-sdk/x/supply" - "github.com/cosmos/cosmos-sdk/x/supply/exported" ) // dummy addresses used for testing @@ -70,8 +69,7 @@ func MakeTestCodec() *codec.Codec { // Register AppAccount cdc.RegisterInterface((*auth.Account)(nil), nil) cdc.RegisterConcrete(&auth.BaseAccount{}, "test/staking/BaseAccount", nil) - cdc.RegisterInterface((*exported.ModuleAccountI)(nil), nil) - cdc.RegisterConcrete(&supply.ModuleAccount{}, "test/staking/ModuleAccount", nil) + supply.RegisterCodec(cdc) codec.RegisterCrypto(cdc) return cdc @@ -139,7 +137,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initPower int64) (sdk.Context types.NotBondedPoolName: {supply.Burner, supply.Staking}, types.BondedPoolName: {supply.Burner, supply.Staking}, } - supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bk, supply.DefaultCodespace, maccPerms) + supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bk, maccPerms) initTokens := sdk.TokensFromConsensusPower(initPower) initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens)) diff --git a/x/staking/types/expected_keepers.go b/x/staking/types/expected_keepers.go index e172d5a86835..d3faecf820f7 100644 --- a/x/staking/types/expected_keepers.go +++ b/x/staking/types/expected_keepers.go @@ -4,7 +4,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authexported "github.com/cosmos/cosmos-sdk/x/auth/exported" stakingexported "github.com/cosmos/cosmos-sdk/x/staking/exported" - "github.com/cosmos/cosmos-sdk/x/supply" supplyexported "github.com/cosmos/cosmos-sdk/x/supply/exported" ) @@ -21,7 +20,7 @@ type AccountKeeper interface { // SupplyKeeper defines the expected supply Keeper (noalias) type SupplyKeeper interface { - GetSupply(ctx sdk.Context) supply.Supply + GetSupply(ctx sdk.Context) supplyexported.SupplyI GetModuleAddress(name string) sdk.AccAddress GetModuleAccount(ctx sdk.Context, moduleName string) supplyexported.ModuleAccountI diff --git a/x/supply/exported/exported.go b/x/supply/exported/exported.go index 3139836d9555..e872e1deabd1 100644 --- a/x/supply/exported/exported.go +++ b/x/supply/exported/exported.go @@ -1,11 +1,29 @@ package exported -import "github.com/cosmos/cosmos-sdk/x/auth/exported" +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/auth/exported" +) // ModuleAccountI defines an account interface for modules that hold tokens in an escrow type ModuleAccountI interface { exported.Account + GetName() string GetPermissions() []string HasPermission(string) bool } + +// SupplyI defines an inflationary supply interface for modules that handle +// token supply. +type SupplyI interface { + GetTotal() sdk.Coins + SetTotal(total sdk.Coins) SupplyI + + Inflate(amount sdk.Coins) SupplyI + Deflate(amount sdk.Coins) SupplyI + + String() string + ValidateBasic() error +} diff --git a/x/supply/genesis.go b/x/supply/genesis.go index ddef251166ef..36e928d3835f 100644 --- a/x/supply/genesis.go +++ b/x/supply/genesis.go @@ -11,7 +11,7 @@ import ( // CONTRACT: all types of accounts must have been already initialized/created func InitGenesis(ctx sdk.Context, keeper Keeper, ak types.AccountKeeper, data GenesisState) { // manually set the total supply based on accounts if not provided - if data.Supply.Total.Empty() { + if data.Supply.GetTotal().Empty() { var totalSupply sdk.Coins ak.IterateAccounts(ctx, func(acc authexported.Account) (stop bool) { @@ -19,8 +19,10 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, ak types.AccountKeeper, data Ge return false }, ) - data.Supply.Total = totalSupply + + data.Supply = data.Supply.SetTotal(totalSupply) } + keeper.SetSupply(ctx, data.Supply) } diff --git a/x/supply/internal/keeper/bank.go b/x/supply/internal/keeper/bank.go index fa91b9b30eb3..60efbc4c3df5 100644 --- a/x/supply/internal/keeper/bank.go +++ b/x/supply/internal/keeper/bank.go @@ -105,7 +105,8 @@ func (k Keeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk // update total supply supply := k.GetSupply(ctx) - supply.Inflate(amt) + supply = supply.Inflate(amt) + k.SetSupply(ctx, supply) logger := k.Logger(ctx) @@ -135,7 +136,7 @@ func (k Keeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk // update total supply supply := k.GetSupply(ctx) - supply.Deflate(amt) + supply = supply.Deflate(amt) k.SetSupply(ctx, supply) logger := k.Logger(ctx) diff --git a/x/supply/internal/keeper/bank_test.go b/x/supply/internal/keeper/bank_test.go index a21c90eb47e5..c331e1e277c2 100644 --- a/x/supply/internal/keeper/bank_test.go +++ b/x/supply/internal/keeper/bank_test.go @@ -94,7 +94,7 @@ func TestMintCoins(t *testing.T) { err := keeper.MintCoins(ctx, types.Minter, initCoins) require.NoError(t, err) require.Equal(t, initCoins, getCoinsByName(ctx, keeper, types.Minter)) - require.Equal(t, initialSupply.Total.Add(initCoins), keeper.GetSupply(ctx).Total) + require.Equal(t, initialSupply.GetTotal().Add(initCoins), keeper.GetSupply(ctx).GetTotal()) // test same functionality on module account with multiple permissions initialSupply = keeper.GetSupply(ctx) @@ -102,7 +102,7 @@ func TestMintCoins(t *testing.T) { err = keeper.MintCoins(ctx, multiPermAcc.GetName(), initCoins) require.NoError(t, err) require.Equal(t, initCoins, getCoinsByName(ctx, keeper, multiPermAcc.GetName())) - require.Equal(t, initialSupply.Total.Add(initCoins), keeper.GetSupply(ctx).Total) + require.Equal(t, initialSupply.GetTotal().Add(initCoins), keeper.GetSupply(ctx).GetTotal()) require.Panics(t, func() { keeper.MintCoins(ctx, types.Burner, initCoins) }) } @@ -115,22 +115,22 @@ func TestBurnCoins(t *testing.T) { keeper.SetModuleAccount(ctx, burnerAcc) initialSupply := keeper.GetSupply(ctx) - initialSupply.Inflate(initCoins) + initialSupply = initialSupply.Inflate(initCoins) keeper.SetSupply(ctx, initialSupply) require.Error(t, keeper.BurnCoins(ctx, "", initCoins), "no module account") require.Panics(t, func() { keeper.BurnCoins(ctx, types.Minter, initCoins) }, "invalid permission") - require.Panics(t, func() { keeper.BurnCoins(ctx, randomPerm, initialSupply.Total) }, "random permission") - require.Panics(t, func() { keeper.BurnCoins(ctx, types.Burner, initialSupply.Total) }, "insufficient coins") + require.Panics(t, func() { keeper.BurnCoins(ctx, randomPerm, initialSupply.GetTotal()) }, "random permission") + require.Panics(t, func() { keeper.BurnCoins(ctx, types.Burner, initialSupply.GetTotal()) }, "insufficient coins") err := keeper.BurnCoins(ctx, types.Burner, initCoins) require.NoError(t, err) require.Equal(t, sdk.Coins(nil), getCoinsByName(ctx, keeper, types.Burner)) - require.Equal(t, initialSupply.Total.Sub(initCoins), keeper.GetSupply(ctx).Total) + require.Equal(t, initialSupply.GetTotal().Sub(initCoins), keeper.GetSupply(ctx).GetTotal()) // test same functionality on module account with multiple permissions initialSupply = keeper.GetSupply(ctx) - initialSupply.Inflate(initCoins) + initialSupply = initialSupply.Inflate(initCoins) keeper.SetSupply(ctx, initialSupply) require.NoError(t, multiPermAcc.SetCoins(initCoins)) @@ -139,5 +139,5 @@ func TestBurnCoins(t *testing.T) { err = keeper.BurnCoins(ctx, multiPermAcc.GetName(), initCoins) require.NoError(t, err) require.Equal(t, sdk.Coins(nil), getCoinsByName(ctx, keeper, multiPermAcc.GetName())) - require.Equal(t, initialSupply.Total.Sub(initCoins), keeper.GetSupply(ctx).Total) + require.Equal(t, initialSupply.GetTotal().Sub(initCoins), keeper.GetSupply(ctx).GetTotal()) } diff --git a/x/supply/internal/keeper/common_test.go b/x/supply/internal/keeper/common_test.go index 807a84a158bd..3c78349bdcc9 100644 --- a/x/supply/internal/keeper/common_test.go +++ b/x/supply/internal/keeper/common_test.go @@ -88,7 +88,7 @@ func createTestInput(t *testing.T, isCheckTx bool, initPower int64, nAccs int64) multiPerm: {types.Minter, types.Burner, types.Staking}, randomPerm: {"random"}, } - keeper := NewKeeper(cdc, keySupply, ak, bk, DefaultCodespace, maccPerms) + keeper := NewKeeper(cdc, keySupply, ak, bk, maccPerms) totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, valTokens.MulRaw(nAccs))) keeper.SetSupply(ctx, types.NewSupply(totalSupply)) diff --git a/x/supply/internal/keeper/invariants.go b/x/supply/internal/keeper/invariants.go index 20ef76c8ff75..9a4ebb2a79a3 100644 --- a/x/supply/internal/keeper/invariants.go +++ b/x/supply/internal/keeper/invariants.go @@ -31,12 +31,12 @@ func TotalSupply(k Keeper) sdk.Invariant { return false }) - broken := !expectedTotal.IsEqual(supply.Total) + broken := !expectedTotal.IsEqual(supply.GetTotal()) return sdk.FormatInvariant(types.ModuleName, "total supply", fmt.Sprintf( "\tsum of accounts coins: %v\n"+ "\tsupply.Total: %v\n", - expectedTotal, supply.Total), broken) + expectedTotal, supply.GetTotal()), broken) } } diff --git a/x/supply/internal/keeper/keeper.go b/x/supply/internal/keeper/keeper.go index c2208df2ee8e..b071f878db33 100644 --- a/x/supply/internal/keeper/keeper.go +++ b/x/supply/internal/keeper/keeper.go @@ -21,9 +21,7 @@ type Keeper struct { } // NewKeeper creates a new Keeper instance -func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, ak types.AccountKeeper, bk types.BankKeeper, - codespace sdk.CodespaceType, maccPerms map[string][]string) Keeper { - +func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, ak types.AccountKeeper, bk types.BankKeeper, maccPerms map[string][]string) Keeper { // set the addresses permAddrs := make(map[string]types.PermissionsForAddress) for name, perms := range maccPerms { @@ -45,7 +43,7 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { } // GetSupply retrieves the Supply from store -func (k Keeper) GetSupply(ctx sdk.Context) (supply types.Supply) { +func (k Keeper) GetSupply(ctx sdk.Context) (supply exported.SupplyI) { store := ctx.KVStore(k.storeKey) b := store.Get(SupplyKey) if b == nil { @@ -56,7 +54,7 @@ func (k Keeper) GetSupply(ctx sdk.Context) (supply types.Supply) { } // SetSupply sets the Supply to store -func (k Keeper) SetSupply(ctx sdk.Context, supply types.Supply) { +func (k Keeper) SetSupply(ctx sdk.Context, supply exported.SupplyI) { store := ctx.KVStore(k.storeKey) b := k.cdc.MustMarshalBinaryLengthPrefixed(supply) store.Set(SupplyKey, b) diff --git a/x/supply/internal/keeper/keeper_test.go b/x/supply/internal/keeper/keeper_test.go index 18fcb96757ac..61e0afa596ae 100644 --- a/x/supply/internal/keeper/keeper_test.go +++ b/x/supply/internal/keeper/keeper_test.go @@ -16,7 +16,7 @@ func TestSupply(t *testing.T) { ctx, _, keeper := createTestInput(t, false, initialPower, nAccs) - total := keeper.GetSupply(ctx).Total + total := keeper.GetSupply(ctx).GetTotal() expectedTotal := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens.MulRaw(nAccs))) require.Equal(t, expectedTotal, total) diff --git a/x/supply/internal/keeper/querier.go b/x/supply/internal/keeper/querier.go index 575c5fbd875b..9b74a45ccbe6 100644 --- a/x/supply/internal/keeper/querier.go +++ b/x/supply/internal/keeper/querier.go @@ -14,10 +14,13 @@ import ( func NewQuerier(k Keeper) sdk.Querier { return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { switch path[0] { + case types.QueryTotalSupply: return queryTotalSupply(ctx, req, k) + case types.QuerySupplyOf: return querySupplyOf(ctx, req, k) + default: return nil, sdk.ErrUnknownRequest("unknown supply query endpoint") } @@ -32,7 +35,7 @@ func queryTotalSupply(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) } - totalSupply := k.GetSupply(ctx).Total + totalSupply := k.GetSupply(ctx).GetTotal() start, end := client.Paginate(len(totalSupply), params.Page, params.Limit, 100) if start < 0 || end < 0 { @@ -57,7 +60,7 @@ func querySupplyOf(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sd return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) } - supply := k.GetSupply(ctx).Total.AmountOf(params.Denom) + supply := k.GetSupply(ctx).GetTotal().AmountOf(params.Denom) res, err := supply.MarshalJSON() if err != nil { diff --git a/x/supply/internal/types/codec.go b/x/supply/internal/types/codec.go index 1b9c9183cb3a..89bc9a2ffcf3 100644 --- a/x/supply/internal/types/codec.go +++ b/x/supply/internal/types/codec.go @@ -8,7 +8,9 @@ import ( // RegisterCodec registers the account types and interface func RegisterCodec(cdc *codec.Codec) { cdc.RegisterInterface((*exported.ModuleAccountI)(nil), nil) + cdc.RegisterInterface((*exported.SupplyI)(nil), nil) cdc.RegisterConcrete(&ModuleAccount{}, "cosmos-sdk/ModuleAccount", nil) + cdc.RegisterConcrete(&Supply{}, "cosmos-sdk/Supply", nil) } // ModuleCdc generic sealed codec to be used throughout module diff --git a/x/supply/internal/types/genesis.go b/x/supply/internal/types/genesis.go index e2e690cfd2a3..27f8b3ff1b92 100644 --- a/x/supply/internal/types/genesis.go +++ b/x/supply/internal/types/genesis.go @@ -1,12 +1,16 @@ package types +import ( + "github.com/cosmos/cosmos-sdk/x/supply/exported" +) + // GenesisState is the supply state that must be provided at genesis. type GenesisState struct { - Supply Supply `json:"supply" yaml:"supply"` + Supply exported.SupplyI `json:"supply" yaml:"supply"` } // NewGenesisState creates a new genesis state. -func NewGenesisState(supply Supply) GenesisState { +func NewGenesisState(supply exported.SupplyI) GenesisState { return GenesisState{supply} } diff --git a/x/supply/internal/types/supply.go b/x/supply/internal/types/supply.go index 434a72626053..4fecd57b6d8a 100644 --- a/x/supply/internal/types/supply.go +++ b/x/supply/internal/types/supply.go @@ -3,30 +3,51 @@ package types import ( "fmt" - yaml "gopkg.in/yaml.v2" + "gopkg.in/yaml.v2" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/supply/exported" ) +// Implements Delegation interface +var _ exported.SupplyI = Supply{} + // Supply represents a struct that passively keeps track of the total supply amounts in the network type Supply struct { Total sdk.Coins `json:"total" yaml:"total"` // total supply of tokens registered on the chain } +// SetTotal sets the total supply. +func (supply Supply) SetTotal(total sdk.Coins) exported.SupplyI { + supply.Total = total + return supply +} + +// GetTotal returns the supply total. +func (supply Supply) GetTotal() sdk.Coins { + return supply.Total +} + // NewSupply creates a new Supply instance -func NewSupply(total sdk.Coins) Supply { return Supply{total} } +func NewSupply(total sdk.Coins) exported.SupplyI { + return Supply{total} +} // DefaultSupply creates an empty Supply -func DefaultSupply() Supply { return NewSupply(sdk.NewCoins()) } +func DefaultSupply() exported.SupplyI { + return NewSupply(sdk.NewCoins()) +} // Inflate adds coins to the total supply -func (supply *Supply) Inflate(amount sdk.Coins) { +func (supply Supply) Inflate(amount sdk.Coins) exported.SupplyI { supply.Total = supply.Total.Add(amount) + return supply } // Deflate subtracts coins from the total supply -func (supply *Supply) Deflate(amount sdk.Coins) { +func (supply Supply) Deflate(amount sdk.Coins) exported.SupplyI { supply.Total = supply.Total.Sub(amount) + return supply } // String returns a human readable string representation of a supplier. diff --git a/x/supply/internal/types/supply_test.go b/x/supply/internal/types/supply_test.go index 4af49d362fd1..e99e1e5aea49 100644 --- a/x/supply/internal/types/supply_test.go +++ b/x/supply/internal/types/supply_test.go @@ -14,7 +14,7 @@ import ( func TestSupplyMarshalYAML(t *testing.T) { supply := DefaultSupply() coins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt())) - supply.Inflate(coins) + supply = supply.Inflate(coins) bz, err := yaml.Marshal(supply) require.NoError(t, err)