From dd453b314369bde893943f9d281098dfb9fe2c63 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 19 Jul 2018 01:46:32 -0400 Subject: [PATCH 1/5] changelog --- PENDING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PENDING.md b/PENDING.md index f297e6a4a..40a2b34c5 100644 --- a/PENDING.md +++ b/PENDING.md @@ -3,6 +3,7 @@ BREAKING CHANGES * [baseapp] Msgs are no longer run on CheckTx, removed `ctx.IsCheckTx()` * [x/stake] Fixed the period check for the inflation calculation +* [x/stake] Inflation doesn't use rationals in calculation (performance boost) FEATURES * [lcd] Can now query governance proposals by ProposalStatus From df46339a45b94f83f07d84d92727fac04d2ef0a3 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 19 Jul 2018 19:26:40 -0400 Subject: [PATCH 2/5] benchmarking --- x/stake/types/inflation_test.go | 48 ++++++++++++++++++++++++++++++--- x/stake/types/pool.go | 2 +- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/x/stake/types/inflation_test.go b/x/stake/types/inflation_test.go index 555408853..f2149593f 100644 --- a/x/stake/types/inflation_test.go +++ b/x/stake/types/inflation_test.go @@ -82,6 +82,41 @@ func TestProcessProvisions(t *testing.T) { checkFinalPoolValues(t, pool, sdk.NewRat(initialTotalTokens), cumulativeExpProvs) } +// Benchmark precision +func BenchmarkProcessProvisions10000(b *testing.B) { + precision = 10000 + pool := InitialPool() + params := DefaultParams() + + var initialTotalTokens int64 = 550000000 + var cumulativeExpProvs = sdk.ZeroRat() + pool.LooseTokens = sdk.NewRat(initialTotalTokens) + + // process the provisions for a year + for hr := 0; hr < b.N; hr++ { + var expProvisions sdk.Rat + _, expProvisions, pool, _ = updateProvisionsBare(pool, params, hr) + cumulativeExpProvs = cumulativeExpProvs.Add(expProvisions) + } +} + +func BenchmarkProcessProvisions100000000000(b *testing.B) { + precision = 100000000000 + pool := InitialPool() + params := DefaultParams() + + var initialTotalTokens int64 = 550000000 + var cumulativeExpProvs = sdk.ZeroRat() + pool.LooseTokens = sdk.NewRat(initialTotalTokens) + + // process the provisions for a year + for hr := 0; hr < b.N; hr++ { + var expProvisions sdk.Rat + _, expProvisions, pool, _ = updateProvisionsBare(pool, params, hr) + cumulativeExpProvs = cumulativeExpProvs.Add(expProvisions) + } +} + //_________________________________________________________________________________________ ////////////////////////////////HELPER FUNCTIONS BELOW///////////////////////////////////// @@ -94,10 +129,7 @@ func checkFinalPoolValues(t *testing.T, pool Pool, initialTotalTokens, cumulativ // Processes provisions are added to the pool correctly every hour // Returns expected Provisions, expected Inflation, and pool, to help with cumulative calculations back in main Tests func updateProvisions(t *testing.T, pool Pool, params Params, hr int) (sdk.Rat, sdk.Rat, Pool) { - expInflation := pool.NextInflation(params) - expProvisions := expInflation.Mul(pool.TokenSupply()).Quo(hrsPerYrRat) - startTotalSupply := pool.TokenSupply() - pool = pool.ProcessProvisions(params) + expInflation, expProvisions, pool, startTotalSupply := updateProvisionsBare(pool, params, hr) //check provisions were added to pool require.True(sdk.RatEq(t, startTotalSupply.Add(expProvisions), pool.TokenSupply())) @@ -105,6 +137,14 @@ func updateProvisions(t *testing.T, pool Pool, params Params, hr int) (sdk.Rat, return expInflation, expProvisions, pool } +func updateProvisionsBare(pool Pool, params Params, hr int) (sdk.Rat, sdk.Rat, Pool, sdk.Rat) { + expInflation := pool.NextInflation(params) + expProvisions := expInflation.Mul(pool.TokenSupply()).Quo(hrsPerYrRat) + startTotalSupply := pool.TokenSupply() + pool = pool.ProcessProvisions(params) + return expInflation, expProvisions, pool, startTotalSupply +} + // Checks that The inflation will correctly increase or decrease after an update to the pool // nolint: gocyclo func checkInflation(t *testing.T, pool Pool, previousInflation, updatedInflation sdk.Rat, msg string) { diff --git a/x/stake/types/pool.go b/x/stake/types/pool.go index 01dfacada..6e82005bb 100644 --- a/x/stake/types/pool.go +++ b/x/stake/types/pool.go @@ -80,7 +80,7 @@ func (p Pool) bondedTokensToLoose(bondedTokens sdk.Rat) Pool { //_______________________________________________________________________ // Inflation -const precision = 100000000000 // increased to this precision for accuracy +var precision int64 = 100000000000 // increased to this precision for accuracy var hrsPerYrRat = sdk.NewRat(8766) // as defined by a julian year of 365.25 days // process provisions for an hour period From accce5c7d80b8e508ebeb4ad29a370046fe36470 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 20 Jul 2018 11:24:03 -0400 Subject: [PATCH 3/5] lower rounding --- x/stake/types/inflation_test.go | 53 +++++---------------------------- x/stake/types/pool.go | 11 +++++-- 2 files changed, 15 insertions(+), 49 deletions(-) diff --git a/x/stake/types/inflation_test.go b/x/stake/types/inflation_test.go index f2149593f..0114b1e05 100644 --- a/x/stake/types/inflation_test.go +++ b/x/stake/types/inflation_test.go @@ -39,11 +39,11 @@ func TestGetInflation(t *testing.T) { // test 7% minimum stop (testing with 100% bonded) {"test 4", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(7, 100), sdk.ZeroRat()}, - {"test 5", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(70001, 1000000), sdk.NewRat(-1, 1000000).Round(precision)}, + {"test 5", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(70001, 1000000), sdk.NewRat(-1, 1000000)}, // test 20% maximum stop (testing with 0% bonded) {"test 6", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(20, 100), sdk.ZeroRat()}, - {"test 7", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(199999, 1000000), sdk.NewRat(1, 1000000).Round(precision)}, + {"test 7", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(199999, 1000000), sdk.NewRat(1, 1000000)}, // perfect balance shouldn't change inflation {"test 8", sdk.NewRat(67), sdk.NewRat(33), sdk.NewRat(15, 100), sdk.ZeroRat()}, @@ -82,41 +82,6 @@ func TestProcessProvisions(t *testing.T) { checkFinalPoolValues(t, pool, sdk.NewRat(initialTotalTokens), cumulativeExpProvs) } -// Benchmark precision -func BenchmarkProcessProvisions10000(b *testing.B) { - precision = 10000 - pool := InitialPool() - params := DefaultParams() - - var initialTotalTokens int64 = 550000000 - var cumulativeExpProvs = sdk.ZeroRat() - pool.LooseTokens = sdk.NewRat(initialTotalTokens) - - // process the provisions for a year - for hr := 0; hr < b.N; hr++ { - var expProvisions sdk.Rat - _, expProvisions, pool, _ = updateProvisionsBare(pool, params, hr) - cumulativeExpProvs = cumulativeExpProvs.Add(expProvisions) - } -} - -func BenchmarkProcessProvisions100000000000(b *testing.B) { - precision = 100000000000 - pool := InitialPool() - params := DefaultParams() - - var initialTotalTokens int64 = 550000000 - var cumulativeExpProvs = sdk.ZeroRat() - pool.LooseTokens = sdk.NewRat(initialTotalTokens) - - // process the provisions for a year - for hr := 0; hr < b.N; hr++ { - var expProvisions sdk.Rat - _, expProvisions, pool, _ = updateProvisionsBare(pool, params, hr) - cumulativeExpProvs = cumulativeExpProvs.Add(expProvisions) - } -} - //_________________________________________________________________________________________ ////////////////////////////////HELPER FUNCTIONS BELOW///////////////////////////////////// @@ -129,7 +94,11 @@ func checkFinalPoolValues(t *testing.T, pool Pool, initialTotalTokens, cumulativ // Processes provisions are added to the pool correctly every hour // Returns expected Provisions, expected Inflation, and pool, to help with cumulative calculations back in main Tests func updateProvisions(t *testing.T, pool Pool, params Params, hr int) (sdk.Rat, sdk.Rat, Pool) { - expInflation, expProvisions, pool, startTotalSupply := updateProvisionsBare(pool, params, hr) + + expInflation := pool.NextInflation(params) + expProvisions := expInflation.Mul(pool.TokenSupply().Round(precision)).Quo(hrsPerYrRat) + startTotalSupply := pool.TokenSupply() + pool = pool.ProcessProvisions(params) //check provisions were added to pool require.True(sdk.RatEq(t, startTotalSupply.Add(expProvisions), pool.TokenSupply())) @@ -137,14 +106,6 @@ func updateProvisions(t *testing.T, pool Pool, params Params, hr int) (sdk.Rat, return expInflation, expProvisions, pool } -func updateProvisionsBare(pool Pool, params Params, hr int) (sdk.Rat, sdk.Rat, Pool, sdk.Rat) { - expInflation := pool.NextInflation(params) - expProvisions := expInflation.Mul(pool.TokenSupply()).Quo(hrsPerYrRat) - startTotalSupply := pool.TokenSupply() - pool = pool.ProcessProvisions(params) - return expInflation, expProvisions, pool, startTotalSupply -} - // Checks that The inflation will correctly increase or decrease after an update to the pool // nolint: gocyclo func checkInflation(t *testing.T, pool Pool, previousInflation, updatedInflation sdk.Rat, msg string) { diff --git a/x/stake/types/pool.go b/x/stake/types/pool.go index 6e82005bb..6ddadf94b 100644 --- a/x/stake/types/pool.go +++ b/x/stake/types/pool.go @@ -80,13 +80,15 @@ func (p Pool) bondedTokensToLoose(bondedTokens sdk.Rat) Pool { //_______________________________________________________________________ // Inflation -var precision int64 = 100000000000 // increased to this precision for accuracy +const precision = 10000 // increased to this precision for accuracy var hrsPerYrRat = sdk.NewRat(8766) // as defined by a julian year of 365.25 days // process provisions for an hour period func (p Pool) ProcessProvisions(params Params) Pool { p.Inflation = p.NextInflation(params) - provisions := p.Inflation.Mul(p.TokenSupply()).Quo(hrsPerYrRat) + provisions := p.Inflation. + Mul(p.TokenSupply().Round(precision)). + Quo(hrsPerYrRat) // TODO add to the fees provisions p.LooseTokens = p.LooseTokens.Add(provisions) @@ -103,7 +105,10 @@ func (p Pool) NextInflation(params Params) (inflation sdk.Rat) { // 7% and 20%. // (1 - bondedRatio/GoalBonded) * InflationRateChange - inflationRateChangePerYear := sdk.OneRat().Sub(p.BondedRatio().Quo(params.GoalBonded)).Mul(params.InflationRateChange) + inflationRateChangePerYear := sdk.OneRat(). + Sub(p.BondedRatio().Round(precision). + Quo(params.GoalBonded)). + Mul(params.InflationRateChange) inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYrRat) // increase the new annual inflation for this next cycle From 9e5a78fc7a92eb9416160851cdec9f382b95eb8f Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 20 Jul 2018 11:35:13 -0400 Subject: [PATCH 4/5] less stake endblock processing --- cmd/gaia/app/app.go | 2 +- x/slashing/tick.go | 1 + x/stake/handler.go | 10 ++++------ 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index ab8a27e6c..b0995da96 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -143,8 +143,8 @@ func (app *GaiaApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) ab // application updates every end block // nolint: unparam func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { - validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper) + validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper) tags, _ := gov.EndBlocker(ctx, app.govKeeper) return abci.ResponseEndBlock{ diff --git a/x/slashing/tick.go b/x/slashing/tick.go index 01984f870..da157ca7a 100644 --- a/x/slashing/tick.go +++ b/x/slashing/tick.go @@ -11,6 +11,7 @@ import ( // slashing begin block functionality func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, sk Keeper) (tags sdk.Tags) { + // Tag the height heightBytes := make([]byte, 8) binary.LittleEndian.PutUint64(heightBytes, uint64(req.Header.Height)) diff --git a/x/stake/handler.go b/x/stake/handler.go index 14fb4f7bf..922c1bc48 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -34,19 +34,17 @@ func NewHandler(k keeper.Keeper) sdk.Handler { // Called every block, process inflation, update validator set func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Validator) { - pool := k.GetPool(ctx) - params := k.GetParams(ctx) - // Process types.Validator Provisions + // Process provision inflation blockTime := ctx.BlockHeader().Time if blockTime-pool.InflationLastTime >= 3600 { + params := k.GetParams(ctx) + pool := k.GetPool(ctx) pool.InflationLastTime = blockTime pool = pool.ProcessProvisions(params) + k.SetPool(ctx, pool) } - // save the params - k.SetPool(ctx, pool) - // reset the intra-transaction counter k.SetIntraTxCounter(ctx, 0) From 5686d6692a950869dfa21572a779d52c09c3b1e4 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 20 Jul 2018 11:39:29 -0400 Subject: [PATCH 5/5] ... --- x/stake/handler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/stake/handler.go b/x/stake/handler.go index 922c1bc48..3cc122e4c 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -34,12 +34,12 @@ func NewHandler(k keeper.Keeper) sdk.Handler { // Called every block, process inflation, update validator set func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Validator) { + pool := k.GetPool(ctx) // Process provision inflation blockTime := ctx.BlockHeader().Time if blockTime-pool.InflationLastTime >= 3600 { params := k.GetParams(ctx) - pool := k.GetPool(ctx) pool.InflationLastTime = blockTime pool = pool.ProcessProvisions(params) k.SetPool(ctx, pool)