refactor(x/mint)!: avoid writing same minter and use millisecond precision for minting (#20747)
This commit is contained in:
parent
ae9116aff1
commit
4bda5d6a4e
@ -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
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user