diff --git a/simapp/mint_fn.go b/simapp/mint_fn.go index 9f2ee70ca57b..dcb9f96c7ff6 100644 --- a/simapp/mint_fn.go +++ b/simapp/mint_fn.go @@ -60,20 +60,19 @@ func ProvideExampleMintFn(bankKeeper MintBankKeeper) minttypes.MintFn { minter.AnnualProvisions = minter.NextAnnualProvisions(mintParams.Params, stakingTokenSupply.Amount) // to get a more accurate amount of tokens minted, we get, and later store, last minting time. - // if this is the first time minting, we initialize the minter.Data with the current time - 60s // to mint tokens at the beginning. Note: this is a custom behavior to avoid breaking tests. if minter.Data == nil { minter.Data = make([]byte, 8) - binary.BigEndian.PutUint64(minter.Data, (uint64)(env.HeaderService.HeaderInfo(ctx).Time.Unix()-60)) + binary.BigEndian.PutUint64(minter.Data, (uint64)(env.HeaderService.HeaderInfo(ctx).Time.UnixMilli()-60000)) } lastMint := binary.BigEndian.Uint64(minter.Data) - binary.BigEndian.PutUint64(minter.Data, (uint64)(env.HeaderService.HeaderInfo(ctx).Time.Unix())) + binary.BigEndian.PutUint64(minter.Data, (uint64)(env.HeaderService.HeaderInfo(ctx).Time.UnixMilli())) - // calculate the amount of tokens to mint, based on the time since the last mint - secsSinceLastMint := env.HeaderService.HeaderInfo(ctx).Time.Unix() - (int64)(lastMint) - provisionAmt := minter.AnnualProvisions.QuoInt64(31536000).MulInt64(secsSinceLastMint) // 31536000 = seconds in a year + // calculate the amount of tokens to mint, based on the time since the last mint. + msSinceLastMint := env.HeaderService.HeaderInfo(ctx).Time.UnixMilli() - (int64)(lastMint) + provisionAmt := minter.AnnualProvisions.QuoInt64(31536000000).MulInt64(msSinceLastMint) // 31536000000 = milliseconds in a year mintedCoin := sdk.NewCoin(mintParams.Params.MintDenom, provisionAmt.TruncateInt()) maxSupply := mintParams.Params.MaxSupply totalSupply := stakingTokenSupply.Amount diff --git a/x/mint/epoch_hooks.go b/x/mint/epoch_hooks.go index 28ae5a26b195..2a63245036e6 100644 --- a/x/mint/epoch_hooks.go +++ b/x/mint/epoch_hooks.go @@ -20,11 +20,17 @@ func (am AppModule) BeforeEpochStart(ctx context.Context, epochIdentifier string return err } + oldMinter := minter + err = am.mintFn(ctx, am.keeper.Environment, &minter, epochIdentifier, epochNumber) if err != nil { return err } + if minter.IsEqual(oldMinter) { + return nil + } + return am.keeper.Minter.Set(ctx, minter) } diff --git a/x/mint/keeper/abci.go b/x/mint/keeper/abci.go index 8fbeb4050f83..e59eb1747894 100644 --- a/x/mint/keeper/abci.go +++ b/x/mint/keeper/abci.go @@ -18,6 +18,8 @@ func (k Keeper) BeginBlocker(ctx context.Context, mintFn types.MintFn) error { return err } + oldMinter := minter + // we pass -1 as epoch number to indicate that this is not an epoch minting, // but a regular block minting. Same with epoch id "block". err = mintFn(ctx, k.Environment, &minter, "block", -1) @@ -25,5 +27,9 @@ func (k Keeper) BeginBlocker(ctx context.Context, mintFn types.MintFn) error { return err } + if minter.IsEqual(oldMinter) { + return nil + } + return k.Minter.Set(ctx, minter) } diff --git a/x/mint/keeper/keeper_test.go b/x/mint/keeper/keeper_test.go index 971ce5c830b1..d3d0281c7563 100644 --- a/x/mint/keeper/keeper_test.go +++ b/x/mint/keeper/keeper_test.go @@ -1,11 +1,13 @@ package keeper_test import ( + "context" "testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/suite" + "cosmossdk.io/core/appmodule" "cosmossdk.io/log" "cosmossdk.io/math" storetypes "cosmossdk.io/store/types" @@ -152,6 +154,17 @@ func (s *KeeperTestSuite) TestBeginBlocker() { newMinter, err := s.mintKeeper.Minter.Get(s.ctx) s.NoError(err) s.NotEqual(minter, newMinter) + + // now use a mintfn that doesn't do anything + err = s.mintKeeper.BeginBlocker(s.ctx, func(ctx context.Context, env appmodule.Environment, minter *types.Minter, epochId string, epochNumber int64) error { + return nil + }) + s.NoError(err) + + // get minter again and compare + unchangedMinter, err := s.mintKeeper.Minter.Get(s.ctx) + s.NoError(err) + s.Equal(newMinter, unchangedMinter) } func (s *KeeperTestSuite) TestMigrator() { diff --git a/x/mint/types/minter.go b/x/mint/types/minter.go index 349198a43462..84be5698df4a 100644 --- a/x/mint/types/minter.go +++ b/x/mint/types/minter.go @@ -1,6 +1,7 @@ package types import ( + "bytes" "fmt" "cosmossdk.io/math" @@ -80,3 +81,20 @@ func (m Minter) BlockProvision(params Params) sdk.Coin { provisionAmt := m.AnnualProvisions.QuoInt(math.NewInt(int64(params.BlocksPerYear))) return sdk.NewCoin(params.MintDenom, provisionAmt.TruncateInt()) } + +// IsEqual returns true if two minters are equal, it checks all the fields +func (m Minter) IsEqual(minter Minter) bool { + if !m.Inflation.Equal(minter.Inflation) { + return false + } + + if !m.AnnualProvisions.Equal(minter.AnnualProvisions) { + return false + } + + if !bytes.Equal(m.Data, minter.Data) { + return false + } + + return true +}