From 94465b0d9c502f8e831c279f4a1b3e22cf3ddd0b Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Thu, 18 Mar 2021 12:22:53 -0400 Subject: [PATCH 1/3] Fix genesis supply handling --- proto/cosmos/bank/v1beta1/genesis.proto | 3 ++- x/bank/keeper/genesis.go | 10 ++++++---- x/bank/types/genesis.go | 19 +++++++++++++++++-- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/proto/cosmos/bank/v1beta1/genesis.proto b/proto/cosmos/bank/v1beta1/genesis.proto index 25c80a38b5ab..8fd7329a0a5d 100644 --- a/proto/cosmos/bank/v1beta1/genesis.proto +++ b/proto/cosmos/bank/v1beta1/genesis.proto @@ -15,7 +15,8 @@ message GenesisState { // balances is an array containing the balances of all the accounts. repeated Balance balances = 2 [(gogoproto.nullable) = false]; - // supply represents the total supply. + // supply represents the total supply. If it is left empty, then supply will be calculated based on the provided + // balances. Otherwise, it will be used to validate that the sum of the balances equals this amount. repeated cosmos.base.v1beta1.Coin supply = 3 [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false]; diff --git a/x/bank/keeper/genesis.go b/x/bank/keeper/genesis.go index dc73ae0b0632..b3e8fb64c335 100644 --- a/x/bank/keeper/genesis.go +++ b/x/bank/keeper/genesis.go @@ -11,7 +11,7 @@ import ( func (k BaseKeeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) { k.SetParams(ctx, genState.Params) - var totalSupply sdk.Coins + totalSupply := sdk.Coins{} genState.Balances = types.SanitizeGenesisBalances(genState.Balances) for _, balance := range genState.Balances { @@ -27,11 +27,13 @@ func (k BaseKeeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) { totalSupply = totalSupply.Add(balance.Coins...) } - if genState.Supply.Empty() { - genState.Supply = totalSupply + if !genState.Supply.Empty() { + if !genState.Supply.IsEqual(totalSupply) { + panic(fmt.Errorf("genesis supply is incorrect, expected %v, got %v", genState.Supply, totalSupply)) + } } - k.setSupply(ctx, genState.Supply) + k.setSupply(ctx, totalSupply) for _, meta := range genState.DenomMetadata { k.SetDenomMetaData(ctx, meta) diff --git a/x/bank/types/genesis.go b/x/bank/types/genesis.go index 03f4be4abd63..d40093126f2b 100644 --- a/x/bank/types/genesis.go +++ b/x/bank/types/genesis.go @@ -18,6 +18,8 @@ func (gs GenesisState) Validate() error { seenBalances := make(map[string]bool) seenMetadatas := make(map[string]bool) + totalSupply := sdk.Coins{} + for _, balance := range gs.Balances { if seenBalances[balance.Address] { return fmt.Errorf("duplicate balance for address %s", balance.Address) @@ -28,6 +30,8 @@ func (gs GenesisState) Validate() error { } seenBalances[balance.Address] = true + + totalSupply = totalSupply.Add(balance.Coins...) } for _, metadata := range gs.DenomMetadata { @@ -42,8 +46,19 @@ func (gs GenesisState) Validate() error { seenMetadatas[metadata.Base] = true } - // NOTE: this errors if supply for any given coin is zero - return gs.Supply.Validate() + if !gs.Supply.Empty() { + // NOTE: this errors if supply for any given coin is zero + err := gs.Supply.Validate() + if err != nil { + return err + } + + if !gs.Supply.IsEqual(totalSupply) { + return fmt.Errorf("genesis supply is incorrect, expected %v, got %v", gs.Supply, totalSupply) + } + } + + return nil } // NewGenesisState creates a new genesis state. From d135f086e14ae67269ba53b9d4c791c6794c5000 Mon Sep 17 00:00:00 2001 From: Amaury M <1293565+amaurym@users.noreply.github.com> Date: Fri, 19 Mar 2021 11:19:45 +0100 Subject: [PATCH 2/3] Add test --- x/bank/keeper/genesis_test.go | 47 +++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/x/bank/keeper/genesis_test.go b/x/bank/keeper/genesis_test.go index 6b148a006c02..494907ca309e 100644 --- a/x/bank/keeper/genesis_test.go +++ b/x/bank/keeper/genesis_test.go @@ -64,3 +64,50 @@ func (suite *IntegrationTestSuite) TestInitGenesis() { suite.Require().True(found) suite.Require().Equal(m, m2) } + +func (suite *IntegrationTestSuite) TestTotalSupply() { + // Prepare some test data. + defaultGenesis := types.DefaultGenesisState() + balances := []types.Balance{ + {Coins: sdk.NewCoins(sdk.NewCoin("foocoin", sdk.NewInt(1))), Address: "cosmos1f9xjhxm0plzrh9cskf4qee4pc2xwp0n0556gh0"}, + {Coins: sdk.NewCoins(sdk.NewCoin("barcoin", sdk.NewInt(1))), Address: "cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh"}, + {Coins: sdk.NewCoins(sdk.NewCoin("foocoin", sdk.NewInt(10)), sdk.NewCoin("barcoin", sdk.NewInt(20))), Address: "cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q"}, + } + totalSupply := sdk.NewCoins(sdk.NewCoin("foocoin", sdk.NewInt(11)), sdk.NewCoin("barcoin", sdk.NewInt(21))) + + testcases := []struct { + name string + genesis *types.GenesisState + expSupply sdk.Coins + expPanic bool + expPanicMsg string + }{ + { + "calculation NOT matching genesis Supply field", + types.NewGenesisState(defaultGenesis.Params, balances, sdk.NewCoins(sdk.NewCoin("wrongcoin", sdk.NewInt(1))), defaultGenesis.DenomMetadata), + nil, true, "genesis supply is incorrect, expected 1wrongcoin, got 21barcoin,11foocoin", + }, + { + "calculation matches genesis Supply field", + types.NewGenesisState(defaultGenesis.Params, balances, totalSupply, defaultGenesis.DenomMetadata), + totalSupply, false, "", + }, + { + "calculation is correct, empty genesis Supply field", + types.NewGenesisState(defaultGenesis.Params, balances, nil, defaultGenesis.DenomMetadata), + totalSupply, false, "", + }, + } + + for _, tc := range testcases { + tc := tc + suite.Run(tc.name, func() { + if tc.expPanic { + 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)) + } + }) + } +} From 0eb10f290584e7fd6c0352e5de6e3b5fade7d1f1 Mon Sep 17 00:00:00 2001 From: Amaury M <1293565+amaurym@users.noreply.github.com> Date: Fri, 19 Mar 2021 15:04:53 +0100 Subject: [PATCH 3/3] Fix nit --- x/bank/keeper/genesis.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/x/bank/keeper/genesis.go b/x/bank/keeper/genesis.go index b3e8fb64c335..f0c680b24a74 100644 --- a/x/bank/keeper/genesis.go +++ b/x/bank/keeper/genesis.go @@ -27,10 +27,8 @@ func (k BaseKeeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) { totalSupply = totalSupply.Add(balance.Coins...) } - if !genState.Supply.Empty() { - if !genState.Supply.IsEqual(totalSupply) { - panic(fmt.Errorf("genesis supply is incorrect, expected %v, got %v", genState.Supply, totalSupply)) - } + if !genState.Supply.Empty() && !genState.Supply.IsEqual(totalSupply) { + panic(fmt.Errorf("genesis supply is incorrect, expected %v, got %v", genState.Supply, totalSupply)) } k.setSupply(ctx, totalSupply)