From 653ce307f5624be4bc0263faecce26df51170537 Mon Sep 17 00:00:00 2001 From: sahith-narahari Date: Fri, 5 Mar 2021 19:56:36 +0530 Subject: [PATCH 01/16] paginate grpc query --- proto/cosmos/bank/v1beta1/query.proto | 11 +- x/bank/client/cli/query.go | 7 +- x/bank/keeper/grpc_query.go | 9 +- x/bank/keeper/keeper.go | 26 ++- x/bank/keeper/querier.go | 17 +- x/bank/types/query.pb.go | 221 ++++++++++++++++++++------ x/bank/types/query.pb.gw.go | 18 +++ 7 files changed, 239 insertions(+), 70 deletions(-) diff --git a/proto/cosmos/bank/v1beta1/query.proto b/proto/cosmos/bank/v1beta1/query.proto index bc5e29137a9..e3a464f8baa 100644 --- a/proto/cosmos/bank/v1beta1/query.proto +++ b/proto/cosmos/bank/v1beta1/query.proto @@ -90,7 +90,13 @@ message QueryAllBalancesResponse { // QueryTotalSupplyRequest is the request type for the Query/TotalSupply RPC // method. -message QueryTotalSupplyRequest {} +message QueryTotalSupplyRequest { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 1; +} // QueryTotalSupplyResponse is the response type for the Query/TotalSupply RPC // method @@ -98,6 +104,9 @@ message QueryTotalSupplyResponse { // supply is the supply of the coins repeated cosmos.base.v1beta1.Coin supply = 1 [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; } // QuerySupplyOfRequest is the request type for the Query/SupplyOf RPC method. diff --git a/x/bank/client/cli/query.go b/x/bank/client/cli/query.go index a192c8deba1..4019bb738d9 100644 --- a/x/bank/client/cli/query.go +++ b/x/bank/client/cli/query.go @@ -183,8 +183,13 @@ To query for the total supply of a specific coin denomination use: queryClient := types.NewQueryClient(clientCtx) ctx := cmd.Context() + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } if denom == "" { - res, err := queryClient.TotalSupply(ctx, &types.QueryTotalSupplyRequest{}) + res, err := queryClient.TotalSupply(ctx, &types.QueryTotalSupplyRequest{Pagination: pageReq}) if err != nil { return err } diff --git a/x/bank/keeper/grpc_query.go b/x/bank/keeper/grpc_query.go index fa385e3cb46..356cc4596b0 100644 --- a/x/bank/keeper/grpc_query.go +++ b/x/bank/keeper/grpc_query.go @@ -77,11 +77,14 @@ func (k BaseKeeper) AllBalances(ctx context.Context, req *types.QueryAllBalances } // TotalSupply implements the Query/TotalSupply gRPC method -func (k BaseKeeper) TotalSupply(ctx context.Context, _ *types.QueryTotalSupplyRequest) (*types.QueryTotalSupplyResponse, error) { +func (k BaseKeeper) TotalSupply(ctx context.Context, req *types.QueryTotalSupplyRequest) (*types.QueryTotalSupplyResponse, error) { sdkCtx := sdk.UnwrapSDKContext(ctx) - totalSupply := k.GetTotalSupply(sdkCtx) + totalSupply, pageRes, err := k.GetPaginatedTotalSupply(sdkCtx, req.Pagination) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } - return &types.QueryTotalSupplyResponse{Supply: totalSupply}, nil + return &types.QueryTotalSupplyResponse{Supply: totalSupply, Pagination: pageRes}, nil } // SupplyOf implements the Query/SupplyOf gRPC method diff --git a/x/bank/keeper/keeper.go b/x/bank/keeper/keeper.go index 305665ee506..b4dfa8fab20 100644 --- a/x/bank/keeper/keeper.go +++ b/x/bank/keeper/keeper.go @@ -5,6 +5,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/query" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" vestexported "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported" "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -23,8 +24,8 @@ type Keeper interface { GetSupply(ctx sdk.Context, denom string) sdk.Coin GetTotalSupply(ctx sdk.Context) sdk.Coins + GetPaginatedTotalSupply(ctx sdk.Context, pagination *query.PageRequest) (sdk.Coins, *query.PageResponse, error) IterateTotalSupply(ctx sdk.Context, cb func(sdk.Coin) bool) - GetDenomMetaData(ctx sdk.Context, denom string) (types.Metadata, bool) SetDenomMetaData(ctx sdk.Context, denomMetaData types.Metadata) IterateAllDenomMetaData(ctx sdk.Context, cb func(types.Metadata) bool) @@ -53,6 +54,29 @@ type BaseKeeper struct { paramSpace paramtypes.Subspace } +func (k BaseKeeper) GetPaginatedTotalSupply(ctx sdk.Context, pagination *query.PageRequest) (sdk.Coins, *query.PageResponse, error) { + store := ctx.KVStore(k.storeKey) + supplyStore := prefix.NewStore(store, types.SupplyKey) + + supply := sdk.NewCoins() + + pageRes, err := query.Paginate(supplyStore, pagination, func(_, value []byte) error { + var result sdk.Coin + err := k.cdc.UnmarshalBinaryBare(value, &result) + if err != nil { + return err + } + supply = append(supply, result) + return nil + }) + + if err != nil { + return nil, nil, err + } + + return supply, pageRes, nil +} + func (k BaseKeeper) GetTotalSupply(ctx sdk.Context) sdk.Coins { balances := sdk.NewCoins() k.IterateTotalSupply(ctx, func(balance sdk.Coin) bool { diff --git a/x/bank/keeper/querier.go b/x/bank/keeper/querier.go index c2d6ca8a2f6..e69ca72cf9b 100644 --- a/x/bank/keeper/querier.go +++ b/x/bank/keeper/querier.go @@ -3,7 +3,6 @@ package keeper import ( abci "github.com/tendermint/tendermint/abci/types" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -77,24 +76,20 @@ func queryAllBalance(ctx sdk.Context, req abci.RequestQuery, k Keeper, legacyQue } func queryTotalSupply(ctx sdk.Context, req abci.RequestQuery, k Keeper, legacyQuerierCdc *codec.LegacyAmino) ([]byte, error) { - var params types.QueryTotalSupplyParams + var params types.QueryTotalSupplyRequest err := legacyQuerierCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } - //TODO: pagenate - totalSupply := k.GetTotalSupply(ctx) + totalSupply, pageRes, err := k.GetPaginatedTotalSupply(ctx, params.Pagination) - start, end := client.Paginate(len(totalSupply), params.Page, params.Limit, 100) - if start < 0 || end < 0 { - totalSupply = sdk.Coins{} - } else { - totalSupply = totalSupply[start:end] + supplyRes := &types.QueryTotalSupplyResponse{ + Supply: totalSupply, + Pagination: pageRes, } - - res, err := legacyQuerierCdc.MarshalJSON(totalSupply) + res, err := codec.MarshalJSONIndent(legacyQuerierCdc, supplyRes) if err != nil { return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) } diff --git a/x/bank/types/query.pb.go b/x/bank/types/query.pb.go index c4bedb0098c..5ad95812ba8 100644 --- a/x/bank/types/query.pb.go +++ b/x/bank/types/query.pb.go @@ -219,6 +219,8 @@ func (m *QueryAllBalancesResponse) GetPagination() *query.PageResponse { // QueryTotalSupplyRequest is the request type for the Query/TotalSupply RPC // method. type QueryTotalSupplyRequest struct { + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` } func (m *QueryTotalSupplyRequest) Reset() { *m = QueryTotalSupplyRequest{} } @@ -259,6 +261,8 @@ var xxx_messageInfo_QueryTotalSupplyRequest proto.InternalMessageInfo type QueryTotalSupplyResponse struct { // supply is the supply of the coins Supply github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,1,rep,name=supply,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"supply"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` } func (m *QueryTotalSupplyResponse) Reset() { *m = QueryTotalSupplyResponse{} } @@ -301,6 +305,13 @@ func (m *QueryTotalSupplyResponse) GetSupply() github_com_cosmos_cosmos_sdk_type return nil } +func (m *QueryTotalSupplyResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + // QuerySupplyOfRequest is the request type for the Query/SupplyOf RPC method. type QuerySupplyOfRequest struct { // denom is the coin denom to query balances for. @@ -690,59 +701,59 @@ func init() { func init() { proto.RegisterFile("cosmos/bank/v1beta1/query.proto", fileDescriptor_9c6fc1939682df13) } var fileDescriptor_9c6fc1939682df13 = []byte{ - // 824 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xcf, 0x6b, 0x13, 0x5b, - 0x14, 0xce, 0xed, 0x7b, 0x4d, 0xd3, 0x13, 0xde, 0x5b, 0xdc, 0xe6, 0xf1, 0xd2, 0xe9, 0x6b, 0xf2, - 0x98, 0x6a, 0x9b, 0xd6, 0x74, 0xa6, 0x69, 0x85, 0xa2, 0x1b, 0x69, 0x2a, 0xba, 0x10, 0x69, 0x8c, - 0xae, 0x04, 0x91, 0x9b, 0x64, 0x1c, 0x43, 0x93, 0xb9, 0xd3, 0xdc, 0x89, 0x58, 0x4a, 0x51, 0x04, - 0xc1, 0x95, 0x0a, 0x2e, 0x5c, 0xb8, 0xa9, 0x1b, 0x41, 0x97, 0xfe, 0x15, 0x5d, 0xb8, 0x28, 0xb8, - 0x71, 0xa5, 0xd2, 0xba, 0xf0, 0xcf, 0x90, 0xdc, 0x1f, 0xd3, 0x49, 0x32, 0x4d, 0x06, 0xd1, 0x55, - 0x66, 0xee, 0x3d, 0xe7, 0x3b, 0xdf, 0x77, 0xee, 0xb9, 0xdf, 0x04, 0xb2, 0x55, 0xca, 0x9a, 0x94, - 0x99, 0x15, 0xe2, 0x6c, 0x9a, 0xf7, 0x0a, 0x15, 0xcb, 0x23, 0x05, 0x73, 0xab, 0x6d, 0xb5, 0xb6, - 0x0d, 0xb7, 0x45, 0x3d, 0x8a, 0x27, 0x44, 0x80, 0xd1, 0x09, 0x30, 0x64, 0x80, 0xb6, 0xe0, 0x67, - 0x31, 0x4b, 0x44, 0xfb, 0xb9, 0x2e, 0xb1, 0xeb, 0x0e, 0xf1, 0xea, 0xd4, 0x11, 0x00, 0x5a, 0xca, - 0xa6, 0x36, 0xe5, 0x8f, 0x66, 0xe7, 0x49, 0xae, 0xfe, 0x67, 0x53, 0x6a, 0x37, 0x2c, 0x93, 0xb8, - 0x75, 0x93, 0x38, 0x0e, 0xf5, 0x78, 0x0a, 0x93, 0xbb, 0x99, 0x20, 0xbe, 0x42, 0xae, 0xd2, 0xba, - 0xd3, 0xb7, 0x1f, 0x60, 0xcd, 0x19, 0xf2, 0x7d, 0x7d, 0x03, 0x26, 0xae, 0x75, 0x58, 0x15, 0x49, - 0x83, 0x38, 0x55, 0xab, 0x6c, 0x6d, 0xb5, 0x2d, 0xe6, 0xe1, 0x34, 0x8c, 0x91, 0x5a, 0xad, 0x65, - 0x31, 0x96, 0x46, 0xff, 0xa3, 0xdc, 0x78, 0x59, 0xbd, 0xe2, 0x14, 0x8c, 0xd6, 0x2c, 0x87, 0x36, - 0xd3, 0x23, 0x7c, 0x5d, 0xbc, 0x9c, 0x4f, 0x3c, 0xd9, 0xcb, 0xc6, 0xbe, 0xef, 0x65, 0x63, 0xfa, - 0x15, 0x48, 0x75, 0x03, 0x32, 0x97, 0x3a, 0xcc, 0xc2, 0x2b, 0x30, 0x56, 0x11, 0x4b, 0x1c, 0x31, - 0xb9, 0x3c, 0x69, 0xf8, 0xfd, 0x62, 0x96, 0xea, 0x97, 0xb1, 0x4e, 0xeb, 0x4e, 0x59, 0x45, 0xea, - 0x8f, 0x11, 0xfc, 0xcb, 0xd1, 0xd6, 0x1a, 0x0d, 0x09, 0xc8, 0x86, 0x53, 0xbc, 0x04, 0x70, 0xdc, - 0x5b, 0xce, 0x33, 0xb9, 0x3c, 0xdb, 0x55, 0x4d, 0x1c, 0x9b, 0xaa, 0x59, 0x22, 0xb6, 0x12, 0x5e, - 0x0e, 0x64, 0x06, 0x44, 0x7d, 0x40, 0x90, 0xee, 0xe7, 0x21, 0x95, 0xd9, 0x90, 0x90, 0x7c, 0x3b, - 0x4c, 0xfe, 0x18, 0x28, 0xad, 0xb8, 0xb4, 0xff, 0x39, 0x1b, 0x7b, 0xf7, 0x25, 0x9b, 0xb3, 0xeb, - 0xde, 0xdd, 0x76, 0xc5, 0xa8, 0xd2, 0xa6, 0x29, 0x8f, 0x48, 0xfc, 0x2c, 0xb2, 0xda, 0xa6, 0xe9, - 0x6d, 0xbb, 0x16, 0xe3, 0x09, 0xac, 0xec, 0x83, 0xe3, 0xcb, 0x21, 0xba, 0xe6, 0x86, 0xea, 0x12, - 0x2c, 0x83, 0xc2, 0xf4, 0x49, 0xd9, 0xd5, 0x1b, 0xd4, 0x23, 0x8d, 0xeb, 0x6d, 0xd7, 0x6d, 0x6c, - 0x4b, 0xfd, 0xfa, 0x03, 0x29, 0xb4, 0x6b, 0x4b, 0x0a, 0xad, 0x42, 0x9c, 0xf1, 0x95, 0xdf, 0x21, - 0x53, 0x42, 0xeb, 0x79, 0x39, 0x3f, 0xa2, 0xf6, 0xc6, 0x1d, 0x75, 0xdc, 0xfe, 0xdc, 0xa1, 0xc0, - 0xdc, 0xe9, 0x25, 0xf8, 0xa7, 0x27, 0x5a, 0x72, 0x5d, 0x85, 0x38, 0x69, 0xd2, 0xb6, 0xe3, 0x0d, - 0x9d, 0xb6, 0xe2, 0x9f, 0x1d, 0xae, 0x65, 0x19, 0xae, 0xa7, 0x00, 0x73, 0xc4, 0x12, 0x69, 0x91, - 0xa6, 0x1a, 0x36, 0xbd, 0x24, 0xaf, 0x89, 0x5a, 0x95, 0x55, 0xce, 0x41, 0xdc, 0xe5, 0x2b, 0xb2, - 0xca, 0x94, 0x11, 0xe2, 0x01, 0x86, 0x48, 0x52, 0x75, 0x44, 0x82, 0x5e, 0x03, 0x8d, 0x23, 0x5e, - 0xec, 0xe8, 0x60, 0x57, 0x2d, 0x8f, 0xd4, 0x88, 0x47, 0x94, 0xda, 0xee, 0x11, 0x46, 0x3f, 0x3b, - 0xc2, 0xfa, 0x5b, 0x04, 0x53, 0xa1, 0x65, 0xa4, 0x80, 0x35, 0x18, 0x6f, 0xca, 0x35, 0x35, 0xbc, - 0xd3, 0xa1, 0x1a, 0x54, 0xa6, 0x54, 0x71, 0x9c, 0xf5, 0xeb, 0xa6, 0xb2, 0x00, 0x93, 0xc7, 0x54, - 0x7b, 0x1b, 0x12, 0x7e, 0xfc, 0xb7, 0x82, 0x4d, 0xec, 0x13, 0x77, 0x01, 0x12, 0x8a, 0xa6, 0x6c, - 0x61, 0x24, 0x6d, 0x7e, 0xd2, 0xf2, 0xfb, 0x04, 0x8c, 0x72, 0x7c, 0xfc, 0x12, 0xc1, 0x98, 0xbc, - 0xf8, 0x38, 0x17, 0x0a, 0x12, 0xe2, 0xa2, 0xda, 0x7c, 0x84, 0x48, 0xc1, 0x55, 0x5f, 0x7d, 0xf4, - 0xf1, 0xdb, 0x8b, 0x91, 0x02, 0x36, 0xcd, 0x70, 0xc3, 0x16, 0x16, 0x60, 0xee, 0x48, 0x8f, 0xdb, - 0x35, 0x77, 0x78, 0x07, 0x76, 0xf1, 0x2b, 0x04, 0xc9, 0x80, 0x2b, 0xe1, 0xfc, 0xc9, 0x35, 0xfb, - 0x4d, 0x54, 0x5b, 0x8c, 0x18, 0x2d, 0x59, 0x9a, 0x9c, 0xe5, 0x3c, 0x9e, 0x8b, 0xc8, 0x12, 0x3f, - 0x43, 0x90, 0x0c, 0x58, 0xc9, 0x20, 0x76, 0xfd, 0x66, 0x34, 0x88, 0x5d, 0x88, 0x3f, 0xe9, 0x33, - 0x9c, 0xdd, 0x34, 0x9e, 0x0a, 0x65, 0x27, 0xfc, 0x05, 0x3f, 0x45, 0x90, 0x50, 0x6e, 0x81, 0x07, - 0x1c, 0x50, 0x8f, 0xff, 0x68, 0x0b, 0x51, 0x42, 0x25, 0x91, 0x33, 0x9c, 0xc8, 0x69, 0x3c, 0x33, - 0x80, 0x88, 0x7f, 0x80, 0x0f, 0x11, 0xc4, 0x85, 0x43, 0xe0, 0xb9, 0x93, 0x6b, 0x74, 0xd9, 0x91, - 0x96, 0x1b, 0x1e, 0x18, 0xa9, 0x27, 0xc2, 0x8b, 0xf0, 0x1b, 0x04, 0x7f, 0x75, 0x5d, 0x21, 0x6c, - 0x9c, 0x5c, 0x20, 0xec, 0x7a, 0x6a, 0x66, 0xe4, 0x78, 0xc9, 0xeb, 0x2c, 0xe7, 0x65, 0xe0, 0x7c, - 0x28, 0x2f, 0xde, 0x1a, 0x76, 0x5b, 0x5d, 0x44, 0xbf, 0x57, 0xaf, 0x11, 0xfc, 0xdd, 0xed, 0x64, - 0x78, 0x58, 0xe5, 0x5e, 0x6b, 0xd5, 0x96, 0xa2, 0x27, 0x48, 0xae, 0x79, 0xce, 0x75, 0x16, 0x9f, - 0x8a, 0xc2, 0xb5, 0xb8, 0xbe, 0x7f, 0x98, 0x41, 0x07, 0x87, 0x19, 0xf4, 0xf5, 0x30, 0x83, 0x9e, - 0x1f, 0x65, 0x62, 0x07, 0x47, 0x99, 0xd8, 0xa7, 0xa3, 0x4c, 0xec, 0xe6, 0xfc, 0xc0, 0x8f, 0xe1, - 0x7d, 0x01, 0xcb, 0xbf, 0x89, 0x95, 0x38, 0xff, 0x77, 0xb6, 0xf2, 0x23, 0x00, 0x00, 0xff, 0xff, - 0xb4, 0xd4, 0xb0, 0xfc, 0x75, 0x0a, 0x00, 0x00, + // 825 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x4d, 0x6f, 0xd3, 0x58, + 0x14, 0xcd, 0xeb, 0x4c, 0xd3, 0xf4, 0x46, 0x33, 0x8b, 0xd7, 0x8c, 0x26, 0x75, 0xa7, 0xc9, 0xc8, + 0x9d, 0x69, 0xd3, 0x92, 0xda, 0x4d, 0x8b, 0x54, 0xc1, 0x06, 0x35, 0x45, 0xb0, 0x40, 0xa8, 0x21, + 0xb0, 0x42, 0x42, 0xe8, 0x25, 0x31, 0x26, 0x6a, 0xe2, 0xe7, 0xe6, 0x39, 0x88, 0xaa, 0xaa, 0x84, + 0x90, 0x90, 0x58, 0x01, 0x12, 0x0b, 0x16, 0x6c, 0xca, 0x06, 0x09, 0x96, 0xfc, 0x8a, 0x2e, 0x58, + 0x54, 0x62, 0xc3, 0x0a, 0x50, 0xcb, 0x82, 0x9f, 0x81, 0xf2, 0x3e, 0x5c, 0x27, 0x71, 0x13, 0x2f, + 0xc2, 0x2a, 0xf6, 0xf5, 0xfd, 0x38, 0xe7, 0x3c, 0xdf, 0xe3, 0x40, 0xb6, 0x4a, 0x59, 0x93, 0x32, + 0xb3, 0x42, 0x9c, 0x6d, 0xf3, 0x41, 0xa1, 0x62, 0x79, 0xa4, 0x60, 0xee, 0xb4, 0xad, 0xd6, 0xae, + 0xe1, 0xb6, 0xa8, 0x47, 0xf1, 0x94, 0x48, 0x30, 0x3a, 0x09, 0x86, 0x4c, 0xd0, 0x96, 0xfc, 0x2a, + 0x66, 0x89, 0x6c, 0xbf, 0xd6, 0x25, 0x76, 0xdd, 0x21, 0x5e, 0x9d, 0x3a, 0xa2, 0x81, 0x96, 0xb2, + 0xa9, 0x4d, 0xf9, 0xa5, 0xd9, 0xb9, 0x92, 0xd1, 0x7f, 0x6c, 0x4a, 0xed, 0x86, 0x65, 0x12, 0xb7, + 0x6e, 0x12, 0xc7, 0xa1, 0x1e, 0x2f, 0x61, 0xf2, 0x69, 0x26, 0xd8, 0x5f, 0x75, 0xae, 0xd2, 0xba, + 0xd3, 0xf7, 0x3c, 0x80, 0x9a, 0x23, 0xe4, 0xcf, 0xf5, 0x2d, 0x98, 0xba, 0xd1, 0x41, 0x55, 0x24, + 0x0d, 0xe2, 0x54, 0xad, 0xb2, 0xb5, 0xd3, 0xb6, 0x98, 0x87, 0xd3, 0x30, 0x41, 0x6a, 0xb5, 0x96, + 0xc5, 0x58, 0x1a, 0xfd, 0x8b, 0x72, 0x93, 0x65, 0x75, 0x8b, 0x53, 0x30, 0x5e, 0xb3, 0x1c, 0xda, + 0x4c, 0x8f, 0xf1, 0xb8, 0xb8, 0xb9, 0x98, 0x78, 0x7a, 0x90, 0x8d, 0xfd, 0x38, 0xc8, 0xc6, 0xf4, + 0x6b, 0x90, 0xea, 0x6e, 0xc8, 0x5c, 0xea, 0x30, 0x0b, 0xaf, 0xc1, 0x44, 0x45, 0x84, 0x78, 0xc7, + 0xe4, 0xea, 0xb4, 0xe1, 0xeb, 0xc5, 0x2c, 0xa5, 0x97, 0xb1, 0x49, 0xeb, 0x4e, 0x59, 0x65, 0xea, + 0x4f, 0x10, 0xfc, 0xcd, 0xbb, 0x6d, 0x34, 0x1a, 0xb2, 0x21, 0x1b, 0x0e, 0xf1, 0x0a, 0xc0, 0xa9, + 0xb6, 0x1c, 0x67, 0x72, 0x75, 0xbe, 0x6b, 0x9a, 0x38, 0x36, 0x35, 0xb3, 0x44, 0x6c, 0x45, 0xbc, + 0x1c, 0xa8, 0x0c, 0x90, 0xfa, 0x88, 0x20, 0xdd, 0x8f, 0x43, 0x32, 0xb3, 0x21, 0x21, 0xf1, 0x76, + 0x90, 0xfc, 0x36, 0x90, 0x5a, 0x71, 0xe5, 0xf0, 0x4b, 0x36, 0xf6, 0xfe, 0x6b, 0x36, 0x67, 0xd7, + 0xbd, 0xfb, 0xed, 0x8a, 0x51, 0xa5, 0x4d, 0x53, 0x1e, 0x91, 0xf8, 0x59, 0x66, 0xb5, 0x6d, 0xd3, + 0xdb, 0x75, 0x2d, 0xc6, 0x0b, 0x58, 0xd9, 0x6f, 0x8e, 0xaf, 0x86, 0xf0, 0x5a, 0x18, 0xca, 0x4b, + 0xa0, 0x0c, 0x12, 0xd3, 0xb7, 0xa5, 0xaa, 0xb7, 0xa8, 0x47, 0x1a, 0x37, 0xdb, 0xae, 0xdb, 0xd8, + 0x55, 0xaa, 0x76, 0x6b, 0x87, 0x46, 0xa0, 0xdd, 0xa1, 0xd2, 0xae, 0x6b, 0x9a, 0xd4, 0xae, 0x0a, + 0x71, 0xc6, 0x23, 0xbf, 0x42, 0x39, 0xd9, 0x7a, 0x74, 0xba, 0xe5, 0xe5, 0xbb, 0x2d, 0x48, 0x6c, + 0xdd, 0x53, 0xa2, 0xf9, 0x3b, 0x81, 0x02, 0x3b, 0xa1, 0x97, 0xe0, 0xaf, 0x9e, 0x6c, 0x49, 0x7a, + 0x1d, 0xe2, 0xa4, 0x49, 0xdb, 0x8e, 0x37, 0x74, 0x13, 0x8a, 0xbf, 0x77, 0x48, 0x97, 0x65, 0xba, + 0x9e, 0x02, 0xcc, 0x3b, 0x96, 0x48, 0x8b, 0x34, 0xd5, 0x22, 0xe8, 0x25, 0xb9, 0xc2, 0x2a, 0x2a, + 0xa7, 0x5c, 0x80, 0xb8, 0xcb, 0x23, 0x72, 0xca, 0x8c, 0x11, 0xe2, 0x4f, 0x86, 0x28, 0x52, 0x73, + 0x44, 0x81, 0x5e, 0x03, 0x8d, 0x77, 0xbc, 0xdc, 0xe1, 0xc1, 0xae, 0x5b, 0x1e, 0xa9, 0x11, 0x8f, + 0x8c, 0xf8, 0x15, 0xd1, 0xdf, 0x21, 0x98, 0x09, 0x1d, 0x23, 0x09, 0x6c, 0xc0, 0x64, 0x53, 0xc6, + 0xd4, 0x62, 0xcd, 0x86, 0x72, 0x50, 0x95, 0x92, 0xc5, 0x69, 0xd5, 0xe8, 0x4e, 0xbe, 0x00, 0xd3, + 0xa7, 0x50, 0x7b, 0x05, 0x09, 0x3f, 0xfe, 0x3b, 0x41, 0x11, 0xfb, 0xc8, 0x5d, 0x82, 0x84, 0x82, + 0x29, 0x25, 0x8c, 0xc4, 0xcd, 0x2f, 0x5a, 0xfd, 0x90, 0x80, 0x71, 0xde, 0x1f, 0xbf, 0x42, 0x30, + 0x21, 0x4d, 0x09, 0xe7, 0x42, 0x9b, 0x84, 0x38, 0xbc, 0xb6, 0x18, 0x21, 0x53, 0x60, 0xd5, 0xd7, + 0x1f, 0x7f, 0xfa, 0xfe, 0x72, 0xac, 0x80, 0x4d, 0x33, 0xfc, 0x63, 0x22, 0xec, 0xc9, 0xdc, 0x93, + 0xfe, 0xbb, 0x6f, 0xee, 0x71, 0x05, 0xf6, 0xf1, 0x6b, 0x04, 0xc9, 0x80, 0x63, 0xe2, 0xfc, 0xd9, + 0x33, 0xfb, 0x0d, 0x5e, 0x5b, 0x8e, 0x98, 0x2d, 0x51, 0x9a, 0x1c, 0xe5, 0x22, 0x5e, 0x88, 0x88, + 0x12, 0x3f, 0x47, 0x90, 0x0c, 0x78, 0xd2, 0x20, 0x74, 0xfd, 0x46, 0x39, 0x08, 0x5d, 0x88, 0xd1, + 0xe9, 0x73, 0x1c, 0xdd, 0x2c, 0x9e, 0x09, 0x45, 0x27, 0x8d, 0xea, 0x19, 0x82, 0x84, 0x72, 0x0b, + 0x3c, 0xe0, 0x80, 0x7a, 0xfc, 0x47, 0x5b, 0x8a, 0x92, 0x2a, 0x81, 0x9c, 0xe3, 0x40, 0xfe, 0xc7, + 0x73, 0x03, 0x80, 0xf8, 0x07, 0xf8, 0x08, 0x41, 0x5c, 0x38, 0x04, 0x5e, 0x38, 0x7b, 0x46, 0x97, + 0x1d, 0x69, 0xb9, 0xe1, 0x89, 0x91, 0x34, 0x11, 0x5e, 0x84, 0xdf, 0x22, 0xf8, 0xa3, 0x6b, 0x85, + 0xb0, 0x71, 0xf6, 0x80, 0xb0, 0xf5, 0xd4, 0xcc, 0xc8, 0xf9, 0x12, 0xd7, 0x79, 0x8e, 0xcb, 0xc0, + 0xf9, 0x50, 0x5c, 0x5c, 0x1a, 0x76, 0x57, 0x2d, 0xa2, 0xaf, 0xd5, 0x1b, 0x04, 0x7f, 0x76, 0x3b, + 0x19, 0x1e, 0x36, 0xb9, 0xd7, 0x5a, 0xb5, 0x95, 0xe8, 0x05, 0x12, 0x6b, 0x9e, 0x63, 0x9d, 0xc7, + 0xff, 0x45, 0xc1, 0x5a, 0xdc, 0x3c, 0x3c, 0xce, 0xa0, 0xa3, 0xe3, 0x0c, 0xfa, 0x76, 0x9c, 0x41, + 0x2f, 0x4e, 0x32, 0xb1, 0xa3, 0x93, 0x4c, 0xec, 0xf3, 0x49, 0x26, 0x76, 0x7b, 0x71, 0xe0, 0x57, + 0xf5, 0xa1, 0x68, 0xcb, 0x3f, 0xae, 0x95, 0x38, 0xff, 0xe7, 0xb8, 0xf6, 0x33, 0x00, 0x00, 0xff, + 0xff, 0xa0, 0xfe, 0xe2, 0x92, 0x11, 0x0b, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1238,6 +1249,18 @@ func (m *QueryTotalSupplyRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) _ = i var l int _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } return len(dAtA) - i, nil } @@ -1261,6 +1284,18 @@ func (m *QueryTotalSupplyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error _ = i var l int _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } if len(m.Supply) > 0 { for iNdEx := len(m.Supply) - 1; iNdEx >= 0; iNdEx-- { { @@ -1627,6 +1662,10 @@ func (m *QueryTotalSupplyRequest) Size() (n int) { } var l int _ = l + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } return n } @@ -1642,6 +1681,10 @@ func (m *QueryTotalSupplyResponse) Size() (n int) { n += 1 + l + sovQuery(uint64(l)) } } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } return n } @@ -2218,6 +2261,42 @@ func (m *QueryTotalSupplyRequest) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: QueryTotalSupplyRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -2302,6 +2381,42 @@ func (m *QueryTotalSupplyResponse) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) diff --git a/x/bank/types/query.pb.gw.go b/x/bank/types/query.pb.gw.go index 3dec93b8b36..8b8ed9a5260 100644 --- a/x/bank/types/query.pb.gw.go +++ b/x/bank/types/query.pb.gw.go @@ -179,10 +179,21 @@ func local_request_Query_AllBalances_0(ctx context.Context, marshaler runtime.Ma } +var ( + filter_Query_TotalSupply_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + func request_Query_TotalSupply_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryTotalSupplyRequest var metadata runtime.ServerMetadata + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_TotalSupply_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.TotalSupply(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err @@ -192,6 +203,13 @@ func local_request_Query_TotalSupply_0(ctx context.Context, marshaler runtime.Ma var protoReq QueryTotalSupplyRequest var metadata runtime.ServerMetadata + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_TotalSupply_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.TotalSupply(ctx, &protoReq) return msg, metadata, err From 9232a859722c20ad8bbaa21ce2a8bfb6387c56af Mon Sep 17 00:00:00 2001 From: sahith-narahari Date: Fri, 19 Mar 2021 14:24:12 +0530 Subject: [PATCH 02/16] fix lint --- x/bank/keeper/querier.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x/bank/keeper/querier.go b/x/bank/keeper/querier.go index e69ca72cf9b..e64321b6c0a 100644 --- a/x/bank/keeper/querier.go +++ b/x/bank/keeper/querier.go @@ -84,11 +84,15 @@ func queryTotalSupply(ctx sdk.Context, req abci.RequestQuery, k Keeper, legacyQu } totalSupply, pageRes, err := k.GetPaginatedTotalSupply(ctx, params.Pagination) + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) + } supplyRes := &types.QueryTotalSupplyResponse{ Supply: totalSupply, Pagination: pageRes, } + res, err := codec.MarshalJSONIndent(legacyQuerierCdc, supplyRes) if err != nil { return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) From 97c9c4403580fd2777b8d65ba76b3258cc76ed18 Mon Sep 17 00:00:00 2001 From: sahith-narahari Date: Fri, 19 Mar 2021 14:27:00 +0530 Subject: [PATCH 03/16] update tests --- x/bank/keeper/querier_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/bank/keeper/querier_test.go b/x/bank/keeper/querier_test.go index 3f1e2cb49e8..ddc18ff9a52 100644 --- a/x/bank/keeper/querier_test.go +++ b/x/bank/keeper/querier_test.go @@ -112,9 +112,9 @@ func (suite *IntegrationTestSuite) TestQuerier_QueryTotalSupply() { suite.Require().NoError(err) suite.Require().NotNil(res) - var resp sdk.Coins + var resp types.QueryTotalSupplyResponse suite.Require().NoError(legacyAmino.UnmarshalJSON(res, &resp)) - suite.Require().Equal(expectedTotalSupply, resp) + suite.Require().Equal(expectedTotalSupply, resp.Supply) } func (suite *IntegrationTestSuite) TestQuerier_QueryTotalSupplyOf() { From e352f58ac45ac3b7707e7c74261532da7d6972ac Mon Sep 17 00:00:00 2001 From: sahith-narahari Date: Fri, 19 Mar 2021 17:46:11 +0530 Subject: [PATCH 04/16] remove GetTotalSupply --- x/bank/client/cli/cli_test.go | 4 +++- x/bank/client/rest/grpc_query_test.go | 3 +++ x/bank/client/rest/query_test.go | 14 +++++++++----- x/bank/keeper/invariants.go | 7 ++++++- x/bank/keeper/keeper.go | 1 - 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/x/bank/client/cli/cli_test.go b/x/bank/client/cli/cli_test.go index 19325b430c1..af252fb2982 100644 --- a/x/bank/client/cli/cli_test.go +++ b/x/bank/client/cli/cli_test.go @@ -187,7 +187,9 @@ func (s *IntegrationTestSuite) TestGetCmdQueryTotalSupply() { Supply: sdk.NewCoins( sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), s.cfg.AccountTokens), sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(sdk.NewInt(10))), - )}, + ), + Pagination: &query.PageResponse{NextKey: nil, Total: 2}, + }, }, { name: "total supply of a specific denomination", diff --git a/x/bank/client/rest/grpc_query_test.go b/x/bank/client/rest/grpc_query_test.go index 438cca5294d..b32b9386d51 100644 --- a/x/bank/client/rest/grpc_query_test.go +++ b/x/bank/client/rest/grpc_query_test.go @@ -38,6 +38,9 @@ func (s *IntegrationTestSuite) TestTotalSupplyGRPCHandler() { sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), s.cfg.AccountTokens), sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(sdk.NewInt(10))), ), + Pagination: &query.PageResponse{ + Total: 2, + }, }, }, { diff --git a/x/bank/client/rest/query_test.go b/x/bank/client/rest/query_test.go index 0201e676312..a9e43a53db8 100644 --- a/x/bank/client/rest/query_test.go +++ b/x/bank/client/rest/query_test.go @@ -10,6 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/types/rest" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -155,11 +156,14 @@ func (s *IntegrationTestSuite) TestTotalSupplyHandlerFn() { { "total supply", fmt.Sprintf("%s/bank/total?height=1", baseURL), - &sdk.Coins{}, - sdk.NewCoins( - sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), s.cfg.AccountTokens), - sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(sdk.NewInt(10))), - ), + &types.QueryTotalSupplyResponse{}, + &types.QueryTotalSupplyResponse{ + Supply: sdk.NewCoins( + sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), s.cfg.AccountTokens), + sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(sdk.NewInt(10))), + ), + Pagination: &query.PageResponse{Total: 2}, + }, }, { "total supply of a specific denom", diff --git a/x/bank/keeper/invariants.go b/x/bank/keeper/invariants.go index 6b4716ecb36..08efdf823f6 100644 --- a/x/bank/keeper/invariants.go +++ b/x/bank/keeper/invariants.go @@ -4,6 +4,7 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -50,7 +51,11 @@ func NonnegativeBalanceInvariant(k ViewKeeper) sdk.Invariant { func TotalSupply(k Keeper) sdk.Invariant { return func(ctx sdk.Context) (string, bool) { expectedTotal := sdk.Coins{} - supply := k.GetTotalSupply(ctx) + supply, _, err := k.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + if err != nil { + return sdk.FormatInvariant(types.ModuleName, "query supply", + fmt.Sprintf("error querying total supply %v", err)), false + } k.IterateAllBalances(ctx, func(_ sdk.AccAddress, balance sdk.Coin) bool { expectedTotal = expectedTotal.Add(balance) diff --git a/x/bank/keeper/keeper.go b/x/bank/keeper/keeper.go index b4dfa8fab20..8ddfa8de9d9 100644 --- a/x/bank/keeper/keeper.go +++ b/x/bank/keeper/keeper.go @@ -23,7 +23,6 @@ type Keeper interface { ExportGenesis(sdk.Context) *types.GenesisState GetSupply(ctx sdk.Context, denom string) sdk.Coin - GetTotalSupply(ctx sdk.Context) sdk.Coins GetPaginatedTotalSupply(ctx sdk.Context, pagination *query.PageRequest) (sdk.Coins, *query.PageResponse, error) IterateTotalSupply(ctx sdk.Context, cb func(sdk.Coin) bool) GetDenomMetaData(ctx sdk.Context, denom string) (types.Metadata, bool) From 5340037a9938f06249e74ce861ecff504321290f Mon Sep 17 00:00:00 2001 From: sahith-narahari Date: Fri, 19 Mar 2021 18:13:05 +0530 Subject: [PATCH 05/16] fix test --- x/bank/keeper/keeper_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index ebc529984bc..aa309086194 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -1,6 +1,7 @@ package keeper_test import ( + "github.com/cosmos/cosmos-sdk/types/query" "testing" "time" @@ -93,7 +94,8 @@ func (suite *IntegrationTestSuite) TestSupply() { totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens)) suite.NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, totalSupply)) - total := app.BankKeeper.GetTotalSupply(ctx) + total, _, err := app.BankKeeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + suite.Require().NoError(err) suite.Require().Equal(totalSupply, total) } From 964d48af0a81bc7732b203609cff906f9f244bbc Mon Sep 17 00:00:00 2001 From: sahithn Date: Fri, 26 Mar 2021 00:15:46 +0530 Subject: [PATCH 06/16] remove GetTotalSupply --- x/bank/keeper/genesis.go | 8 +++++++- x/bank/keeper/genesis_test.go | 5 ++++- x/bank/keeper/keeper.go | 23 +++++++---------------- x/bank/keeper/keeper_test.go | 32 ++++++++++++++++++++++---------- x/bank/keeper/querier_test.go | 11 ++++++----- 5 files changed, 46 insertions(+), 33 deletions(-) diff --git a/x/bank/keeper/genesis.go b/x/bank/keeper/genesis.go index 375f44787df..c708781fa97 100644 --- a/x/bank/keeper/genesis.go +++ b/x/bank/keeper/genesis.go @@ -4,6 +4,7 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -42,10 +43,15 @@ func (k BaseKeeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) { // ExportGenesis returns the bank module's genesis state. func (k BaseKeeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { + totalSupply, _, err := k.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + if err != nil { + panic(fmt.Errorf("unable to fetch total supply %v", err)) + } + return types.NewGenesisState( k.GetParams(ctx), k.GetAccountsBalances(ctx), - k.GetTotalSupply(ctx), + totalSupply, k.GetAllDenomMetaData(ctx), ) } diff --git a/x/bank/keeper/genesis_test.go b/x/bank/keeper/genesis_test.go index 7793140396f..366584042c6 100644 --- a/x/bank/keeper/genesis_test.go +++ b/x/bank/keeper/genesis_test.go @@ -2,6 +2,7 @@ package keeper_test import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/x/bank/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) @@ -106,7 +107,9 @@ func (suite *IntegrationTestSuite) TestTotalSupply() { suite.PanicsWithError(tc.expPanicMsg, func() { suite.app.BankKeeper.InitGenesis(suite.ctx, tc.genesis) }) } else { suite.app.BankKeeper.InitGenesis(suite.ctx, tc.genesis) - suite.Require().Equal(tc.expSupply, suite.app.BankKeeper.GetTotalSupply(suite.ctx)) + totalSupply, _, err := suite.app.BankKeeper.GetPaginatedTotalSupply(suite.ctx, &query.PageRequest{}) + suite.Require().NoError(err) + suite.Require().Equal(tc.expSupply, totalSupply) } }) } diff --git a/x/bank/keeper/keeper.go b/x/bank/keeper/keeper.go index 17a45a86089..a7e651de9c7 100644 --- a/x/bank/keeper/keeper.go +++ b/x/bank/keeper/keeper.go @@ -1,6 +1,8 @@ package keeper import ( + "fmt" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" @@ -59,13 +61,12 @@ func (k BaseKeeper) GetPaginatedTotalSupply(ctx sdk.Context, pagination *query.P supply := sdk.NewCoins() - pageRes, err := query.Paginate(supplyStore, pagination, func(_, value []byte) error { - var result sdk.Coin - err := k.cdc.UnmarshalBinaryBare(value, &result) - if err != nil { - return err + pageRes, err := query.Paginate(supplyStore, pagination, func(key, value []byte) error { + amount, ok := sdk.NewIntFromString(string(value)) + if !ok { + return fmt.Errorf("unable to convert amount string to Int") } - supply = append(supply, result) + supply = append(supply, sdk.NewCoin(string(key), amount)) return nil }) @@ -76,16 +77,6 @@ func (k BaseKeeper) GetPaginatedTotalSupply(ctx sdk.Context, pagination *query.P return supply, pageRes, nil } -func (k BaseKeeper) GetTotalSupply(ctx sdk.Context) sdk.Coins { - balances := sdk.NewCoins() - k.IterateTotalSupply(ctx, func(balance sdk.Coin) bool { - balances = balances.Add(balance) - return false - }) - - return balances.Sort() -} - func NewBaseKeeper( cdc codec.BinaryMarshaler, storeKey sdk.StoreKey, ak types.AccountKeeper, paramSpace paramtypes.Subspace, blockedAddrs map[string]bool, diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index 3667269a5f1..52d32db4fc7 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -226,12 +226,13 @@ func (suite *IntegrationTestSuite) TestSupply_MintCoins() { authKeeper.SetModuleAccount(ctx, multiPermAcc) authKeeper.SetModuleAccount(ctx, randomPermAcc) - initialSupply := keeper.GetTotalSupply(ctx) + initialSupply, _, err := keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + suite.Require().NoError(err) suite.Require().Panics(func() { keeper.MintCoins(ctx, "", initCoins) }, "no module account") // nolint:errcheck suite.Require().Panics(func() { keeper.MintCoins(ctx, authtypes.Burner, initCoins) }, "invalid permission") // nolint:errcheck - err := keeper.MintCoins(ctx, authtypes.Minter, sdk.Coins{sdk.Coin{Denom: "denom", Amount: sdk.NewInt(-10)}}) + err = keeper.MintCoins(ctx, authtypes.Minter, sdk.Coins{sdk.Coin{Denom: "denom", Amount: sdk.NewInt(-10)}}) suite.Require().Error(err, "insufficient coins") suite.Require().Panics(func() { keeper.MintCoins(ctx, randomPerm, initCoins) }) // nolint:errcheck @@ -240,16 +241,22 @@ func (suite *IntegrationTestSuite) TestSupply_MintCoins() { suite.Require().NoError(err) suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, authtypes.Minter)) - suite.Require().Equal(initialSupply.Add(initCoins...), keeper.GetTotalSupply(ctx)) + totalSupply, _, err := keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + suite.Require().NoError(err) + + suite.Require().Equal(initialSupply.Add(initCoins...), totalSupply) // test same functionality on module account with multiple permissions - initialSupply = keeper.GetTotalSupply(ctx) + initialSupply, _, err = keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + suite.Require().NoError(err) err = keeper.MintCoins(ctx, multiPermAcc.GetName(), initCoins) suite.Require().NoError(err) + totalSupply, _, err = keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + suite.Require().NoError(err) suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, multiPermAcc.GetName())) - suite.Require().Equal(initialSupply.Add(initCoins...), keeper.GetTotalSupply(ctx)) + suite.Require().Equal(initialSupply.Add(initCoins...), totalSupply) suite.Require().Panics(func() { keeper.MintCoins(ctx, authtypes.Burner, initCoins) }) // nolint:errcheck } @@ -288,32 +295,37 @@ func (suite *IntegrationTestSuite) TestSupply_BurnCoins() { suite. Require(). NoError(keeper.MintCoins(ctx, authtypes.Minter, initCoins)) - supplyAfterInflation := keeper.GetTotalSupply(ctx) + supplyAfterInflation, _, err := keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) suite.Require().Panics(func() { keeper.BurnCoins(ctx, "", initCoins) }, "no module account") // nolint:errcheck suite.Require().Panics(func() { keeper.BurnCoins(ctx, authtypes.Minter, initCoins) }, "invalid permission") // nolint:errcheck suite.Require().Panics(func() { keeper.BurnCoins(ctx, randomPerm, supplyAfterInflation) }, "random permission") // nolint:errcheck - err := keeper.BurnCoins(ctx, authtypes.Burner, supplyAfterInflation) + err = keeper.BurnCoins(ctx, authtypes.Burner, supplyAfterInflation) suite.Require().Error(err, "insufficient coins") err = keeper.BurnCoins(ctx, authtypes.Burner, initCoins) suite.Require().NoError(err) + supplyAfterBurn, _, err := keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + suite.Require().NoError(err) suite.Require().Equal(sdk.NewCoins().String(), getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner).String()) - suite.Require().Equal(supplyAfterInflation.Sub(initCoins), keeper.GetTotalSupply(ctx)) + suite.Require().Equal(supplyAfterInflation.Sub(initCoins), supplyAfterBurn) // test same functionality on module account with multiple permissions suite. Require(). NoError(keeper.MintCoins(ctx, authtypes.Minter, initCoins)) - supplyAfterInflation = keeper.GetTotalSupply(ctx) + supplyAfterInflation, _, err = keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + suite.Require().NoError(err) suite.Require().NoError(keeper.SendCoins(ctx, authtypes.NewModuleAddress(authtypes.Minter), multiPermAcc.GetAddress(), initCoins)) authKeeper.SetModuleAccount(ctx, multiPermAcc) err = keeper.BurnCoins(ctx, multiPermAcc.GetName(), initCoins) + supplyAfterBurn, _, err = keeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + suite.Require().NoError(err) suite.Require().NoError(err) suite.Require().Equal(sdk.NewCoins().String(), getCoinsByName(ctx, keeper, authKeeper, multiPermAcc.GetName()).String()) - suite.Require().Equal(supplyAfterInflation.Sub(initCoins), keeper.GetTotalSupply(ctx)) + suite.Require().Equal(supplyAfterInflation.Sub(initCoins), supplyAfterBurn) } func (suite *IntegrationTestSuite) TestSendCoinsNewAccount() { diff --git a/x/bank/keeper/querier_test.go b/x/bank/keeper/querier_test.go index ddc18ff9a52..14270fbf0f8 100644 --- a/x/bank/keeper/querier_test.go +++ b/x/bank/keeper/querier_test.go @@ -3,16 +3,15 @@ package keeper_test import ( "fmt" - "github.com/cosmos/cosmos-sdk/simapp" - - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" - abci "github.com/tendermint/tendermint/abci/types" + "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/x/bank/keeper" "github.com/cosmos/cosmos-sdk/x/bank/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) func (suite *IntegrationTestSuite) TestQuerier_QueryBalance() { @@ -107,7 +106,9 @@ func (suite *IntegrationTestSuite) TestQuerier_QueryTotalSupply() { suite.Require().NotNil(err) suite.Require().Nil(res) - req.Data = legacyAmino.MustMarshalJSON(types.NewQueryTotalSupplyParams(1, 100)) + req.Data = legacyAmino.MustMarshalJSON(types.QueryTotalSupplyRequest{Pagination: &query.PageRequest{ + Limit: 100, + }}) res, err = querier(ctx, []string{types.QueryTotalSupply}, req) suite.Require().NoError(err) suite.Require().NotNil(res) From 5c5ec5e531bc097cd80116784271fb89b63f4652 Mon Sep 17 00:00:00 2001 From: sahithn Date: Fri, 26 Mar 2021 12:34:45 +0530 Subject: [PATCH 07/16] add changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17c70cb718f..13d9364c0d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,7 +77,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * `MsgCreateValidator.Pubkey` type changed from `string` to `codectypes.Any`. * (client) [\#8926](https://github.com/cosmos/cosmos-sdk/pull/8926) `client/tx.PrepareFactory` has been converted to a private function, as it's only used internally. * (auth/tx) [\#8926](https://github.com/cosmos/cosmos-sdk/pull/8926) The `ProtoTxProvider` interface used as a workaround for transaction simulation has been removed. - +* (bank/keeper) [\#8798](https://github.com/cosmos/cosmos-sdk/pull/8798) `GetTotalSupply` is removed in favour of `GetPaginatedTotalSupply` ### State Machine Breaking * (x/{bank,distrib,gov,slashing,staking}) [\#8363](https://github.com/cosmos/cosmos-sdk/issues/8363) Store keys have been modified to allow for variable-length addresses. From c806d8b2b781b84dedb765800ab64ee93da7c5d5 Mon Sep 17 00:00:00 2001 From: sahithn Date: Fri, 26 Mar 2021 12:50:54 +0530 Subject: [PATCH 08/16] update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13d9364c0d4..6092a7bcdd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,7 +77,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ * `MsgCreateValidator.Pubkey` type changed from `string` to `codectypes.Any`. * (client) [\#8926](https://github.com/cosmos/cosmos-sdk/pull/8926) `client/tx.PrepareFactory` has been converted to a private function, as it's only used internally. * (auth/tx) [\#8926](https://github.com/cosmos/cosmos-sdk/pull/8926) The `ProtoTxProvider` interface used as a workaround for transaction simulation has been removed. -* (bank/keeper) [\#8798](https://github.com/cosmos/cosmos-sdk/pull/8798) `GetTotalSupply` is removed in favour of `GetPaginatedTotalSupply` +* (x/bank) [\#8798](https://github.com/cosmos/cosmos-sdk/pull/8798) `GetTotalSupply` is removed in favour of `GetPaginatedTotalSupply` + ### State Machine Breaking * (x/{bank,distrib,gov,slashing,staking}) [\#8363](https://github.com/cosmos/cosmos-sdk/issues/8363) Store keys have been modified to allow for variable-length addresses. From 001e565ec3f16f4276036d6f449378766aa06907 Mon Sep 17 00:00:00 2001 From: sahithn Date: Fri, 26 Mar 2021 15:51:27 +0530 Subject: [PATCH 09/16] update rosetta data --- contrib/rosetta/configuration/bootstrap.json | 2 +- contrib/rosetta/node/data.tar.gz | Bin 37459 -> 36490 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/rosetta/configuration/bootstrap.json b/contrib/rosetta/configuration/bootstrap.json index f08dae661fa..28c4ba0e6d4 100644 --- a/contrib/rosetta/configuration/bootstrap.json +++ b/contrib/rosetta/configuration/bootstrap.json @@ -1,7 +1,7 @@ [ { "account_identifier": { - "address":"cosmos1gykh2dsytj0lde8wr9msl9xd2nyj88duvmsnn7" + "address":"cosmos1trf09zvqeuc722zyeg34pra8qaqll9ddw0qy8q" }, "currency":{ "symbol":"stake", diff --git a/contrib/rosetta/node/data.tar.gz b/contrib/rosetta/node/data.tar.gz index 342100ebccfd780cdb5c9e1077febe548524692b..a12ece5c9c579b527d9ca80d12665331e060dfdc 100644 GIT binary patch literal 36490 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 GTmk_4+8%xY literal 37459 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 From 3a0607d979ba194a31c88cf74271bac071cf25e5 Mon Sep 17 00:00:00 2001 From: sahithn Date: Sat, 3 Apr 2021 13:27:02 +0530 Subject: [PATCH 10/16] update limit --- x/bank/client/cli/cli_test.go | 2 +- x/bank/keeper/genesis_test.go | 4 +++- x/bank/keeper/invariants.go | 4 +++- x/bank/keeper/keeper_test.go | 3 ++- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/x/bank/client/cli/cli_test.go b/x/bank/client/cli/cli_test.go index af252fb2982..60b8c504b57 100644 --- a/x/bank/client/cli/cli_test.go +++ b/x/bank/client/cli/cli_test.go @@ -188,7 +188,7 @@ func (s *IntegrationTestSuite) TestGetCmdQueryTotalSupply() { sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), s.cfg.AccountTokens), sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(sdk.NewInt(10))), ), - Pagination: &query.PageResponse{NextKey: nil, Total: 2}, + Pagination: &query.PageResponse{Total: 2}, }, }, { diff --git a/x/bank/keeper/genesis_test.go b/x/bank/keeper/genesis_test.go index 366584042c6..7f48461d676 100644 --- a/x/bank/keeper/genesis_test.go +++ b/x/bank/keeper/genesis_test.go @@ -1,6 +1,8 @@ package keeper_test import ( + "math" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -107,7 +109,7 @@ func (suite *IntegrationTestSuite) TestTotalSupply() { suite.PanicsWithError(tc.expPanicMsg, func() { suite.app.BankKeeper.InitGenesis(suite.ctx, tc.genesis) }) } else { suite.app.BankKeeper.InitGenesis(suite.ctx, tc.genesis) - totalSupply, _, err := suite.app.BankKeeper.GetPaginatedTotalSupply(suite.ctx, &query.PageRequest{}) + totalSupply, _, err := suite.app.BankKeeper.GetPaginatedTotalSupply(suite.ctx, &query.PageRequest{Limit: math.MaxUint64}) suite.Require().NoError(err) suite.Require().Equal(tc.expSupply, totalSupply) } diff --git a/x/bank/keeper/invariants.go b/x/bank/keeper/invariants.go index 08efdf823f6..a2063c2eb2c 100644 --- a/x/bank/keeper/invariants.go +++ b/x/bank/keeper/invariants.go @@ -2,6 +2,7 @@ package keeper import ( "fmt" + "math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" @@ -51,7 +52,8 @@ func NonnegativeBalanceInvariant(k ViewKeeper) sdk.Invariant { func TotalSupply(k Keeper) sdk.Invariant { return func(ctx sdk.Context) (string, bool) { expectedTotal := sdk.Coins{} - supply, _, err := k.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + supply, _, err := k.GetPaginatedTotalSupply(ctx, &query.PageRequest{Limit: math.MaxUint64}) + if err != nil { return sdk.FormatInvariant(types.ModuleName, "query supply", fmt.Sprintf("error querying total supply %v", err)), false diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index 52d32db4fc7..840a18c7b1f 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -2,6 +2,7 @@ package keeper_test import ( "github.com/cosmos/cosmos-sdk/types/query" + "math" "testing" "time" @@ -94,7 +95,7 @@ func (suite *IntegrationTestSuite) TestSupply() { totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens)) suite.NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, totalSupply)) - total, _, err := app.BankKeeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + total, _, err := app.BankKeeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{Limit: math.MaxUint64}) suite.Require().NoError(err) suite.Require().Equal(totalSupply, total) } From ba44b064bca9179c153b785be1f2474c91c78f19 Mon Sep 17 00:00:00 2001 From: sahithn Date: Sat, 3 Apr 2021 14:09:55 +0530 Subject: [PATCH 11/16] update genesis --- x/bank/keeper/genesis.go | 3 ++- x/bank/keeper/keeper_test.go | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/x/bank/keeper/genesis.go b/x/bank/keeper/genesis.go index c708781fa97..b632ff2a0d9 100644 --- a/x/bank/keeper/genesis.go +++ b/x/bank/keeper/genesis.go @@ -2,6 +2,7 @@ package keeper import ( "fmt" + "math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" @@ -43,7 +44,7 @@ func (k BaseKeeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) { // ExportGenesis returns the bank module's genesis state. func (k BaseKeeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { - totalSupply, _, err := k.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) + totalSupply, _, err := k.GetPaginatedTotalSupply(ctx, &query.PageRequest{Limit: math.MaxUint64}) if err != nil { panic(fmt.Errorf("unable to fetch total supply %v", err)) } diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index 840a18c7b1f..52d32db4fc7 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -2,7 +2,6 @@ package keeper_test import ( "github.com/cosmos/cosmos-sdk/types/query" - "math" "testing" "time" @@ -95,7 +94,7 @@ func (suite *IntegrationTestSuite) TestSupply() { totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens)) suite.NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, totalSupply)) - total, _, err := app.BankKeeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{Limit: math.MaxUint64}) + total, _, err := app.BankKeeper.GetPaginatedTotalSupply(ctx, &query.PageRequest{}) suite.Require().NoError(err) suite.Require().Equal(totalSupply, total) } From d125062c22cab0c922946914f2a1884a3bc0583e Mon Sep 17 00:00:00 2001 From: sahithn Date: Mon, 5 Apr 2021 19:34:04 +0530 Subject: [PATCH 12/16] add max limit to query --- types/query/pagination.go | 5 +++++ x/bank/keeper/genesis.go | 4 +--- x/bank/keeper/genesis_test.go | 4 +--- x/bank/keeper/invariants.go | 4 +--- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/types/query/pagination.go b/types/query/pagination.go index 868571f861c..9110da92dd3 100644 --- a/types/query/pagination.go +++ b/types/query/pagination.go @@ -2,6 +2,7 @@ package query import ( "fmt" + "math" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -14,6 +15,10 @@ import ( // if the `limit` is not supplied, paginate will use `DefaultLimit` const DefaultLimit = 100 +// MaxLimit is the maximum limit the paginate function can handles +// which equals the maximum value that can be stored in uint64 +const MaxLimit = math.MaxUint64 + // ParsePagination validate PageRequest and returns page number & limit. func ParsePagination(pageReq *PageRequest) (page, limit int, err error) { offset := 0 diff --git a/x/bank/keeper/genesis.go b/x/bank/keeper/genesis.go index b632ff2a0d9..23d3d47109b 100644 --- a/x/bank/keeper/genesis.go +++ b/x/bank/keeper/genesis.go @@ -2,8 +2,6 @@ package keeper import ( "fmt" - "math" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -44,7 +42,7 @@ func (k BaseKeeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) { // ExportGenesis returns the bank module's genesis state. func (k BaseKeeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { - totalSupply, _, err := k.GetPaginatedTotalSupply(ctx, &query.PageRequest{Limit: math.MaxUint64}) + totalSupply, _, err := k.GetPaginatedTotalSupply(ctx, &query.PageRequest{Limit: query.MaxLimit}) if err != nil { panic(fmt.Errorf("unable to fetch total supply %v", err)) } diff --git a/x/bank/keeper/genesis_test.go b/x/bank/keeper/genesis_test.go index 7f48461d676..5adb2174133 100644 --- a/x/bank/keeper/genesis_test.go +++ b/x/bank/keeper/genesis_test.go @@ -1,8 +1,6 @@ package keeper_test import ( - "math" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -109,7 +107,7 @@ func (suite *IntegrationTestSuite) TestTotalSupply() { suite.PanicsWithError(tc.expPanicMsg, func() { suite.app.BankKeeper.InitGenesis(suite.ctx, tc.genesis) }) } else { suite.app.BankKeeper.InitGenesis(suite.ctx, tc.genesis) - totalSupply, _, err := suite.app.BankKeeper.GetPaginatedTotalSupply(suite.ctx, &query.PageRequest{Limit: math.MaxUint64}) + totalSupply, _, err := suite.app.BankKeeper.GetPaginatedTotalSupply(suite.ctx, &query.PageRequest{Limit: query.MaxLimit}) suite.Require().NoError(err) suite.Require().Equal(tc.expSupply, totalSupply) } diff --git a/x/bank/keeper/invariants.go b/x/bank/keeper/invariants.go index a2063c2eb2c..2bf9a781a27 100644 --- a/x/bank/keeper/invariants.go +++ b/x/bank/keeper/invariants.go @@ -2,8 +2,6 @@ package keeper import ( "fmt" - "math" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -52,7 +50,7 @@ func NonnegativeBalanceInvariant(k ViewKeeper) sdk.Invariant { func TotalSupply(k Keeper) sdk.Invariant { return func(ctx sdk.Context) (string, bool) { expectedTotal := sdk.Coins{} - supply, _, err := k.GetPaginatedTotalSupply(ctx, &query.PageRequest{Limit: math.MaxUint64}) + supply, _, err := k.GetPaginatedTotalSupply(ctx, &query.PageRequest{Limit: query.MaxLimit}) if err != nil { return sdk.FormatInvariant(types.ModuleName, "query supply", From ec14729871cca61fd1bb3a346a396bf7afb883d6 Mon Sep 17 00:00:00 2001 From: sahithn Date: Mon, 5 Apr 2021 19:51:53 +0530 Subject: [PATCH 13/16] fix lint --- x/bank/keeper/genesis.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x/bank/keeper/genesis.go b/x/bank/keeper/genesis.go index 23d3d47109b..712e2f5d19e 100644 --- a/x/bank/keeper/genesis.go +++ b/x/bank/keeper/genesis.go @@ -2,6 +2,7 @@ package keeper import ( "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/x/bank/types" From ce1e5ef0e0d3d889ffa4c365fd6ebb848583f7e9 Mon Sep 17 00:00:00 2001 From: sahithn Date: Mon, 5 Apr 2021 22:21:07 +0530 Subject: [PATCH 14/16] go imports --- x/bank/keeper/invariants.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x/bank/keeper/invariants.go b/x/bank/keeper/invariants.go index 2bf9a781a27..52da98381fc 100644 --- a/x/bank/keeper/invariants.go +++ b/x/bank/keeper/invariants.go @@ -2,6 +2,7 @@ package keeper import ( "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/x/bank/types" From a228af9b6421e34876f28db1d6ef916d1d295cad Mon Sep 17 00:00:00 2001 From: SaReN Date: Mon, 5 Apr 2021 22:21:31 +0530 Subject: [PATCH 15/16] Update types/query/pagination.go --- types/query/pagination.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/query/pagination.go b/types/query/pagination.go index 9110da92dd3..9d9431faba1 100644 --- a/types/query/pagination.go +++ b/types/query/pagination.go @@ -15,7 +15,7 @@ import ( // if the `limit` is not supplied, paginate will use `DefaultLimit` const DefaultLimit = 100 -// MaxLimit is the maximum limit the paginate function can handles +// MaxLimit is the maximum limit the paginate function can handle // which equals the maximum value that can be stored in uint64 const MaxLimit = math.MaxUint64 From b64c77bf3abc408bd35b44cb97c6f875a98c711c Mon Sep 17 00:00:00 2001 From: sahithn Date: Tue, 6 Apr 2021 19:38:11 +0530 Subject: [PATCH 16/16] update supply --- x/bank/keeper/keeper.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/x/bank/keeper/keeper.go b/x/bank/keeper/keeper.go index 4d737bd49fa..34eb434c6fb 100644 --- a/x/bank/keeper/keeper.go +++ b/x/bank/keeper/keeper.go @@ -62,9 +62,10 @@ func (k BaseKeeper) GetPaginatedTotalSupply(ctx sdk.Context, pagination *query.P supply := sdk.NewCoins() pageRes, err := query.Paginate(supplyStore, pagination, func(key, value []byte) error { - amount, ok := sdk.NewIntFromString(string(value)) - if !ok { - return fmt.Errorf("unable to convert amount string to Int") + var amount sdk.Int + err := amount.Unmarshal(value) + if err != nil { + return fmt.Errorf("unable to convert amount string to Int %v", err) } supply = append(supply, sdk.NewCoin(string(key), amount)) return nil