Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New minter formula #163

Merged
merged 11 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ linters:
- goimports
- misspell
- whitespace
- unused
- ineffassign

output:
# Sort results by: filepath, line and column.
Expand Down
4 changes: 2 additions & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import (
"github.com/Nolus-Protocol/nolus-core/app/keepers"
appparams "github.com/Nolus-Protocol/nolus-core/app/params"
"github.com/Nolus-Protocol/nolus-core/app/upgrades"
v064 "github.com/Nolus-Protocol/nolus-core/app/upgrades/v064"
v065 "github.com/Nolus-Protocol/nolus-core/app/upgrades/v065"
"github.com/Nolus-Protocol/nolus-core/docs"

wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
Expand All @@ -67,7 +67,7 @@ const (
var (
DefaultNodeHome string

Upgrades = []upgrades.Upgrade{v064.Upgrade}
Upgrades = []upgrades.Upgrade{v065.Upgrade}
)

var (
Expand Down
19 changes: 19 additions & 0 deletions app/upgrades/v065/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package v065

import (
store "cosmossdk.io/store/types"
"github.com/Nolus-Protocol/nolus-core/app/upgrades"
)

const (
// UpgradeName defines the on-chain upgrades name.
UpgradeName = "v0.6.5"
)

var Upgrade = upgrades.Upgrade{
UpgradeName: UpgradeName,
CreateUpgradeHandler: CreateUpgradeHandler,
StoreUpgrades: store.StoreUpgrades{
Added: []string{},
},
}
33 changes: 33 additions & 0 deletions app/upgrades/v065/upgrades.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package v065

import (
"context"
"fmt"

"github.com/Nolus-Protocol/nolus-core/app/keepers"

upgradetypes "cosmossdk.io/x/upgrade/types"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
)

func CreateUpgradeHandler(
mm *module.Manager,
configurator module.Configurator,
keepers *keepers.AppKeepers,
codec codec.Codec,
) upgradetypes.UpgradeHandler {
return func(c context.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
ctx := sdk.UnwrapSDKContext(c)

ctx.Logger().Info("Starting module migrations...")
vm, err := mm.RunMigrations(ctx, configurator, vm) //nolint:contextcheck
if err != nil {
return vm, err
}

ctx.Logger().Info(fmt.Sprintf("Migration {%s} applied", UpgradeName))
return vm, nil
}
}
2 changes: 1 addition & 1 deletion cmd/nolusd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ var (
{
Section: "consensus",
Key: "timeout_commit",
Value: "2s",
Value: "3s",
},
{
Section: "consensus",
Expand Down
8 changes: 4 additions & 4 deletions proto/buf.lock
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ deps:
- remote: buf.build
owner: cosmos
repository: ibc
commit: d7191877c70143938cf411467cebf39a
digest: shake256:b397f418dc751326dd35100c5200c56e1fd7fd24746e39f3ae4d6c86b175e48fe12207867f0912eb31e98f695e9a8afdec7cb4076502d3998026501a88641a9d
commit: 41fbc441e4d645119d275150719c5441
digest: shake256:a61d3e152909abddc91dcc1aec8ac997007bebd48a7921bc243681c708e6c9068f6484aa7ed4e6ff60101d3422c98744a4a5294bbda6aacdba07f1dfa4291020
- remote: buf.build
owner: cosmos
repository: ics23
Expand All @@ -29,5 +29,5 @@ deps:
- remote: buf.build
owner: googleapis
repository: googleapis
commit: f0e53af8f2fc4556b94f482688b57223
digest: shake256:de26a277fc28b8b411ecf58729d78d32fcf15090ffd998a4469225b17889bfb51442eaab04bb7a8d88d203ecdf0a9febd4ffd52c18ed1c2229160c7bd353ca95
commit: e7f8d366f5264595bcc4cd4139af9973
digest: shake256:e5e5f1c12f82e028ea696faa43b4f9dc6258a6d1226282962a8c8b282e10946281d815884f574bd279ebd9cd7588629beb3db17b892af6c33b56f92f8f67f509
105 changes: 27 additions & 78 deletions x/mint/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,14 @@ import (
)

var (
normInitialTotal = types.CalcTokensByIntegral(types.NormOffset)
nanoSecondsInMonth = sdkmath.LegacyNewDec(time.Hour.Nanoseconds() * 24 * 30)
nanoSecondsInFormula = types.MonthsInFormula.Mul(nanoSecondsInMonth)
twelveMonths = sdkmath.LegacyMustNewDecFromStr("12.0")
nanoSecondsInMonth = sdkmath.LegacyNewDec(time.Hour.Nanoseconds() * 24 * 30)
twelveMonths = sdkmath.LegacyMustNewDecFromStr("12.0")

errTimeInFutureBeforeTimePassed = errors.New("time in future can not be before passed time")
errNegativeBlockTime = errors.New("block time can not be less then zero")
)

func calcFunctionIncrement(nanoSecondsPassed sdkmath.Uint) sdkmath.LegacyDec {
return types.NormMonthsRange.Mul(calcFixedIncrement(nanoSecondsPassed))
}

func calcFixedIncrement(nanoSecondsPassed sdkmath.Uint) sdkmath.LegacyDec {
func calcFractionOfMonth(nanoSecondsPassed sdkmath.Uint) sdkmath.LegacyDec {
return types.DecFromUint(nanoSecondsPassed).Quo(nanoSecondsInMonth)
}

Expand All @@ -47,10 +41,6 @@ func calcTimeDifference(blockTime, prevBlockTime, maxMintableSeconds sdkmath.Uin
}

func calcTokens(blockTime sdkmath.Uint, minter *types.Minter, maxMintableSeconds sdkmath.Uint) sdkmath.Uint {
if minter.TotalMinted.GTE(types.MintingCap) {
return sdkmath.ZeroUint()
}

if minter.PrevBlockTimestamp.IsZero() {
// we do not know how much time has passed since the previous block, thus nothing will be mined
minter.PrevBlockTimestamp = blockTime
Expand All @@ -59,114 +49,73 @@ func calcTokens(blockTime sdkmath.Uint, minter *types.Minter, maxMintableSeconds

nsecPassed := calcTimeDifference(blockTime, minter.PrevBlockTimestamp, maxMintableSeconds)
if minter.NormTimePassed.LT(types.MonthsInFormula) {
// First 96 months follow the minting formula
// As the integral starts from NormOffset (ie > 0), previous total needs to be incremented by predetermined amount
previousTotal := minter.TotalMinted.Add(normInitialTotal)
newNormTime := minter.NormTimePassed.Add(calcFunctionIncrement(nsecPassed))
nextTotal := types.CalcTokensByIntegral(newNormTime)

delta := nextTotal.Sub(previousTotal)
newTime := minter.NormTimePassed.Add(calcFractionOfMonth(nsecPassed))

return updateMinter(minter, blockTime, newNormTime, delta)
} else {
// After reaching 96 normalized time, mint fixed amount of tokens per month until we reach the minting cap
normIncrement := calcFixedIncrement(nsecPassed)
delta := sdkmath.NewUint((normIncrement.Mul(types.DecFromUint(types.FixedMintedAmount))).TruncateInt().Uint64())
// First 120 months follow the minting formula
calcWithLastNormTimePassed := types.CalcTokensByIntegral(minter.NormTimePassed)
calcWithNewTimePassed := types.CalcTokensByIntegral(newTime)

if minter.TotalMinted.Add(delta).GT(types.MintingCap) {
// Trim off excess tokens if the cap is reached
delta = types.MintingCap.Sub(minter.TotalMinted)
}
delta := calcWithNewTimePassed.Sub(calcWithLastNormTimePassed)

return updateMinter(minter, blockTime, minter.NormTimePassed.Add(normIncrement), delta)
return updateMinter(minter, blockTime, newTime, delta)
} else {
// After 120 months, we don't mint any more tokens.
return sdkmath.ZeroUint()
}
}

func updateMinter(minter *types.Minter, blockTime sdkmath.Uint, newNormTime sdkmath.LegacyDec, newlyMinted sdkmath.Uint) sdkmath.Uint {
func updateMinter(minter *types.Minter, blockTime sdkmath.Uint, newTimePassed sdkmath.LegacyDec, newlyMinted sdkmath.Uint) sdkmath.Uint {
if newlyMinted.LT(sdkmath.ZeroUint()) {
// Sanity check, should not happen. However, if this were to happen,
// do not update the minter state (primary the previous block timestamp)
// and wait for a new block which should increase the minted amount
return sdkmath.ZeroUint()
}
minter.NormTimePassed = newNormTime
minter.NormTimePassed = newTimePassed
minter.PrevBlockTimestamp = blockTime
minter.TotalMinted = minter.TotalMinted.Add(newlyMinted)
return newlyMinted
}

// Returns the amount of tokens that should be minted by the integral formula
// for the period between normTimePassed and the timeInFuture.
func predictMintedByIntegral(totalMinted sdkmath.Uint, normTimePassed, timeAhead sdkmath.LegacyDec) (sdkmath.Uint, error) {
func predictMintedByIntegral(timePassed, timeAhead sdkmath.LegacyDec) (sdkmath.Uint, error) {
timeAheadNs := timeAhead.Mul(nanoSecondsInMonth).TruncateInt()
normTimeInFuture := normTimePassed.Add(calcFunctionIncrement(sdkmath.Uint(timeAheadNs)))
if normTimePassed.GT(normTimeInFuture) {
timeInFuture := timePassed.Add(calcFractionOfMonth(sdkmath.Uint(timeAheadNs)))
if timePassed.GT(timeInFuture) {
return sdkmath.ZeroUint(), errTimeInFutureBeforeTimePassed
}

if normTimePassed.GTE(types.MonthsInFormula) {
if timePassed.GTE(types.MonthsInFormula) {
return sdkmath.ZeroUint(), nil
}

// integral minting is caped to the 96th month
if normTimeInFuture.GT(types.MonthsInFormula) {
normTimeInFuture = types.MonthsInFormula
// integral minting is caped to the 120th month
if timeInFuture.GT(types.MonthsInFormula) {
timeInFuture = types.MonthsInFormula
}

return types.CalcTokensByIntegral(normTimeInFuture).Sub(normInitialTotal).Sub(totalMinted), nil
}
calcTokensTimePassed := types.CalcTokensByIntegral(timePassed)

// Returns the amount of tokens that should be minted during the fixed amount period
// for the period between NormTimePassed and the timeInFuture.
func predictMintedByFixedAmount(totalMinted sdkmath.Uint, normTimePassed, timeAhead sdkmath.LegacyDec) (sdkmath.Uint, error) {
timeAheadNs := timeAhead.Mul(nanoSecondsInMonth).TruncateInt()

normTimeInFuture := normTimePassed.Add(calcFunctionIncrement(sdkmath.Uint(timeAheadNs)))
if normTimePassed.GT(normTimeInFuture) {
return sdkmath.ZeroUint(), errTimeInFutureBeforeTimePassed
}

normFixedPeriod := normTimeInFuture.Sub(calcFunctionIncrement(sdkmath.Uint(nanoSecondsInFormula.TruncateInt())))
if normFixedPeriod.LTE(sdkmath.LegacyZeroDec()) {
return sdkmath.ZeroUint(), nil
}

// convert norm time to non norm time
fixedPeriod := normFixedPeriod.Sub(types.NormOffset).Quo(types.NormMonthsRange)

newlyMinted := fixedPeriod.MulInt(sdkmath.Int(types.FixedMintedAmount))
// Trim off excess tokens if the cap is reached
if totalMinted.Add(sdkmath.Uint(newlyMinted.TruncateInt())).GT(types.MintingCap) {
return types.MintingCap.Sub(totalMinted), nil
}

return sdkmath.Uint(newlyMinted.TruncateInt()), nil
return types.CalcTokensByIntegral(timeInFuture).Sub(calcTokensTimePassed), nil
}

// Returns the amount of tokens that should be minted
// between the NormTimePassed and the timeAhead
// timeAhead expects months represented in decimal form.
func predictTotalMinted(totalMinted sdkmath.Uint, normTimePassed, timeAhead sdkmath.LegacyDec) sdkmath.Uint {
integralAmount, err := predictMintedByIntegral(totalMinted, normTimePassed, timeAhead)
if err != nil {
return sdkmath.ZeroUint()
}

fixedAmount, err := predictMintedByFixedAmount(totalMinted, normTimePassed, timeAhead)
func predictTotalMinted(timePassed, timeAhead sdkmath.LegacyDec) sdkmath.Uint {
integralAmount, err := predictMintedByIntegral(timePassed, timeAhead)
if err != nil {
return sdkmath.ZeroUint()
}

return fixedAmount.Add(integralAmount)
return integralAmount
}

// BeginBlocker mints new tokens for the previous block.
func BeginBlocker(ctx context.Context, k keeper.Keeper) error {
c := sdk.UnwrapSDKContext(ctx)
minter := k.GetMinter(ctx)
if minter.TotalMinted.GTE(types.MintingCap) {
return errors.New("minting cap has been reached")
}

defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker)

Expand All @@ -177,7 +126,7 @@ func BeginBlocker(ctx context.Context, k keeper.Keeper) error {
}

coinAmount := calcTokens(sdkmath.NewUint(uint64(blockTime)), &minter, params.MaxMintableNanoseconds)
minter.AnnualInflation = predictTotalMinted(minter.TotalMinted, minter.NormTimePassed, twelveMonths)
minter.AnnualInflation = predictTotalMinted(minter.NormTimePassed, twelveMonths)
c.Logger().Debug(fmt.Sprintf("miner: %v total, %v norm time, %v minted", minter.TotalMinted.String(), minter.NormTimePassed.String(), coinAmount.String()))
err := k.SetMinter(ctx, minter)
if err != nil {
Expand Down
Loading
Loading