From 8788b8633c555af439810a5d6c4e31c05a64f742 Mon Sep 17 00:00:00 2001 From: chengwenxi Date: Tue, 13 Aug 2019 16:05:45 +0800 Subject: [PATCH 1/6] Decrease gas consumption by logarithm --- app/v1/auth/ante.go | 3 ++- types/gas.go | 17 +++++++++++++++++ types/gas_test.go | 25 +++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/app/v1/auth/ante.go b/app/v1/auth/ante.go index 37bac7e73..f50f8d750 100644 --- a/app/v1/auth/ante.go +++ b/app/v1/auth/ante.go @@ -22,6 +22,7 @@ const ( gasPerUnitCost = 1000 // max total number of sigs per tx txSigLimit = 7 + gasLog = 1.1 // gas logarithm ) // NewAnteHandler returns an AnteHandler that checks @@ -308,7 +309,7 @@ func setGasMeter(simulate bool, ctx sdk.Context, gasLimit uint64) sdk.Context { if simulate || ctx.BlockHeight() == 0 { return ctx.WithGasMeter(sdk.NewInfiniteGasMeter()) } - return ctx.WithGasMeter(sdk.NewGasMeter(gasLimit)) + return ctx.WithGasMeter(sdk.NewGasMeterWithLog(gasLimit, gasLog)) } func getSignBytesList(chainID string, stdTx StdTx, stdSigs []StdSignature) (signatureBytesList [][]byte) { diff --git a/types/gas.go b/types/gas.go index 3b34d40e8..32ed4b1b0 100644 --- a/types/gas.go +++ b/types/gas.go @@ -1,5 +1,9 @@ package types +import ( + "math" +) + // Gas consumption descriptors. const ( GasIterNextCostFlatDesc = "IterNextFlat" @@ -44,6 +48,7 @@ type GasMeter interface { type basicGasMeter struct { limit Gas consumed Gas + log float64 } // NewGasMeter returns a reference to a new basicGasMeter. @@ -54,6 +59,14 @@ func NewGasMeter(limit Gas) GasMeter { } } +func NewGasMeterWithLog(limit Gas, log float64) GasMeter { + return &basicGasMeter{ + limit: limit, + consumed: 0, + log: log, + } +} + func (g *basicGasMeter) GasConsumed() Gas { return g.consumed } @@ -70,6 +83,10 @@ func (g *basicGasMeter) GasConsumedToLimit() Gas { func (g *basicGasMeter) ConsumeGas(amount Gas, descriptor string) { var overflow bool + if g.log > 1 && amount > 0 && amount < math.MaxInt64 && + (descriptor == GasWritePerByteDesc || descriptor == GasReadPerByteDesc) { + amount = uint64(math.Log(float64(int64(amount))) / math.Log(g.log)) + } // TODO: Should we set the consumed field after overflow checking? g.consumed, overflow = AddUint64Overflow(g.consumed, amount) if overflow { diff --git a/types/gas_test.go b/types/gas_test.go index 5f862dccd..a5b9db96f 100644 --- a/types/gas_test.go +++ b/types/gas_test.go @@ -43,3 +43,28 @@ func TestGasMeter(t *testing.T) { } } + +func TestGasMeterWithLog(t *testing.T) { + cases := []struct { + limit Gas + usage Gas + log float64 + desc string + expect Gas + }{ + {1000, 100, 10, GasWritePerByteDesc, 2}, + {1000, 100, 10, GasReadPerByteDesc, 2}, + {1000, 100, 10, "", 100}, + {1000, 100, 1, GasWritePerByteDesc, 100}, + {1000, 100, 0, GasWritePerByteDesc, 100}, + {1000, 100, 0.99, GasWritePerByteDesc, 100}, + {1000, 100, -0.1, GasWritePerByteDesc, 100}, + } + + for tcnum, tc := range cases { + meter := NewGasMeterWithLog(tc.limit, tc.log) + + meter.ConsumeGas(tc.usage, tc.desc) + require.Equal(t, tc.expect, meter.GasConsumed(), "Gas consumption not match. tc #%d", tcnum) + } +} From 95ca668184780ee795f7a132c15cb269a6aff0f1 Mon Sep 17 00:00:00 2001 From: chengwenxi Date: Tue, 13 Aug 2019 18:10:39 +0800 Subject: [PATCH 2/6] Remove unused constants --- app/v1/auth/ante.go | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/app/v1/auth/ante.go b/app/v1/auth/ante.go index f50f8d750..05b316759 100644 --- a/app/v1/auth/ante.go +++ b/app/v1/auth/ante.go @@ -14,15 +14,9 @@ import ( ) const ( - BlockStoreCostPerByte = 10 - ed25519VerifyCost = 59 - secp256k1VerifyCost = 100 - maxMemoCharacters = 100 - // how much gas = 1 atom - gasPerUnitCost = 1000 - // max total number of sigs per tx - txSigLimit = 7 - gasLog = 1.1 // gas logarithm + ed25519VerifyCost = 59 + secp256k1VerifyCost = 100 + gasLog = 1.1 // gas logarithm ) // NewAnteHandler returns an AnteHandler that checks From 2a00573881033156a75c1dd173983b4aa056a629 Mon Sep 17 00:00:00 2001 From: chengwenxi Date: Thu, 15 Aug 2019 19:17:25 +0800 Subject: [PATCH 3/6] Adjust gas consumption --- app/v1/auth/ante.go | 7 +++++-- types/gas.go | 14 +++++++++----- types/gas_test.go | 2 +- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/app/v1/auth/ante.go b/app/v1/auth/ante.go index 05b316759..c70f7628c 100644 --- a/app/v1/auth/ante.go +++ b/app/v1/auth/ante.go @@ -16,7 +16,10 @@ import ( const ( ed25519VerifyCost = 59 secp256k1VerifyCost = 100 - gasLog = 1.1 // gas logarithm + + // gas = log(gas-gasOffset)/log(gasBase) + gasBase = 1.03 // gas logarithm base + gasOffset = 90 // gas logarithm offset ) // NewAnteHandler returns an AnteHandler that checks @@ -303,7 +306,7 @@ func setGasMeter(simulate bool, ctx sdk.Context, gasLimit uint64) sdk.Context { if simulate || ctx.BlockHeight() == 0 { return ctx.WithGasMeter(sdk.NewInfiniteGasMeter()) } - return ctx.WithGasMeter(sdk.NewGasMeterWithLog(gasLimit, gasLog)) + return ctx.WithGasMeter(sdk.NewGasMeterWithBase(gasLimit, gasBase, gasOffset)) } func getSignBytesList(chainID string, stdTx StdTx, stdSigs []StdSignature) (signatureBytesList [][]byte) { diff --git a/types/gas.go b/types/gas.go index 32ed4b1b0..a7cd46601 100644 --- a/types/gas.go +++ b/types/gas.go @@ -48,7 +48,8 @@ type GasMeter interface { type basicGasMeter struct { limit Gas consumed Gas - log float64 + base float64 + offset uint64 } // NewGasMeter returns a reference to a new basicGasMeter. @@ -59,11 +60,12 @@ func NewGasMeter(limit Gas) GasMeter { } } -func NewGasMeterWithLog(limit Gas, log float64) GasMeter { +func NewGasMeterWithBase(limit Gas, base float64, offset uint64) GasMeter { return &basicGasMeter{ limit: limit, consumed: 0, - log: log, + base: base, + offset: offset, } } @@ -83,9 +85,11 @@ func (g *basicGasMeter) GasConsumedToLimit() Gas { func (g *basicGasMeter) ConsumeGas(amount Gas, descriptor string) { var overflow bool - if g.log > 1 && amount > 0 && amount < math.MaxInt64 && + + // amount = log(amount-g.offset)/log(g.base) + if g.base > 1 && amount > g.offset && amount < math.MaxInt64 && (descriptor == GasWritePerByteDesc || descriptor == GasReadPerByteDesc) { - amount = uint64(math.Log(float64(int64(amount))) / math.Log(g.log)) + amount = uint64(math.Log(float64(int64(amount-g.offset))) / math.Log(g.base)) } // TODO: Should we set the consumed field after overflow checking? g.consumed, overflow = AddUint64Overflow(g.consumed, amount) diff --git a/types/gas_test.go b/types/gas_test.go index a5b9db96f..902ef6feb 100644 --- a/types/gas_test.go +++ b/types/gas_test.go @@ -62,7 +62,7 @@ func TestGasMeterWithLog(t *testing.T) { } for tcnum, tc := range cases { - meter := NewGasMeterWithLog(tc.limit, tc.log) + meter := NewGasMeterWithBase(tc.limit, tc.log, 0) meter.ConsumeGas(tc.usage, tc.desc) require.Equal(t, tc.expect, meter.GasConsumed(), "Gas consumption not match. tc #%d", tcnum) From 117ac0f415910b3218f6ebe9f6f2b537a9dc11f2 Mon Sep 17 00:00:00 2001 From: chengwenxi Date: Thu, 15 Aug 2019 19:23:29 +0800 Subject: [PATCH 4/6] Replace offset with shift --- app/v1/auth/ante.go | 8 ++++---- types/gas.go | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/v1/auth/ante.go b/app/v1/auth/ante.go index c70f7628c..b397d05be 100644 --- a/app/v1/auth/ante.go +++ b/app/v1/auth/ante.go @@ -17,9 +17,9 @@ const ( ed25519VerifyCost = 59 secp256k1VerifyCost = 100 - // gas = log(gas-gasOffset)/log(gasBase) - gasBase = 1.03 // gas logarithm base - gasOffset = 90 // gas logarithm offset + // gas = log(gas-gasShift)/log(gasBase) + gasBase = 1.03 // gas logarithm base + gasShift = 90 // gas logarithm shift ) // NewAnteHandler returns an AnteHandler that checks @@ -306,7 +306,7 @@ func setGasMeter(simulate bool, ctx sdk.Context, gasLimit uint64) sdk.Context { if simulate || ctx.BlockHeight() == 0 { return ctx.WithGasMeter(sdk.NewInfiniteGasMeter()) } - return ctx.WithGasMeter(sdk.NewGasMeterWithBase(gasLimit, gasBase, gasOffset)) + return ctx.WithGasMeter(sdk.NewGasMeterWithBase(gasLimit, gasBase, gasShift)) } func getSignBytesList(chainID string, stdTx StdTx, stdSigs []StdSignature) (signatureBytesList [][]byte) { diff --git a/types/gas.go b/types/gas.go index a7cd46601..a4bdf265c 100644 --- a/types/gas.go +++ b/types/gas.go @@ -49,7 +49,7 @@ type basicGasMeter struct { limit Gas consumed Gas base float64 - offset uint64 + shift uint64 } // NewGasMeter returns a reference to a new basicGasMeter. @@ -60,12 +60,12 @@ func NewGasMeter(limit Gas) GasMeter { } } -func NewGasMeterWithBase(limit Gas, base float64, offset uint64) GasMeter { +func NewGasMeterWithBase(limit Gas, base float64, shift uint64) GasMeter { return &basicGasMeter{ limit: limit, consumed: 0, base: base, - offset: offset, + shift: shift, } } @@ -86,10 +86,10 @@ func (g *basicGasMeter) GasConsumedToLimit() Gas { func (g *basicGasMeter) ConsumeGas(amount Gas, descriptor string) { var overflow bool - // amount = log(amount-g.offset)/log(g.base) - if g.base > 1 && amount > g.offset && amount < math.MaxInt64 && + // amount = log(amount-g.shift)/log(g.base) + if g.base > 1 && amount > g.shift && amount < math.MaxInt64 && (descriptor == GasWritePerByteDesc || descriptor == GasReadPerByteDesc) { - amount = uint64(math.Log(float64(int64(amount-g.offset))) / math.Log(g.base)) + amount = uint64(math.Log(float64(int64(amount-g.shift))) / math.Log(g.base)) } // TODO: Should we set the consumed field after overflow checking? g.consumed, overflow = AddUint64Overflow(g.consumed, amount) From 2f5373a73daaea22d50bf73b213d4ce2f639ee3a Mon Sep 17 00:00:00 2001 From: chengwenxi Date: Fri, 16 Aug 2019 09:54:51 +0800 Subject: [PATCH 5/6] Fix consumption --- app/v1/auth/ante.go | 5 +++-- types/gas.go | 4 ++-- types/gas_test.go | 23 ++++++++++++++--------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/app/v1/auth/ante.go b/app/v1/auth/ante.go index b397d05be..00d1db2e9 100644 --- a/app/v1/auth/ante.go +++ b/app/v1/auth/ante.go @@ -17,9 +17,10 @@ const ( ed25519VerifyCost = 59 secp256k1VerifyCost = 100 - // gas = log(gas-gasShift)/log(gasBase) + // if gas > gasShift, gas = log(gas)/log(gasBase) + // else gasConsumed = gas gasBase = 1.03 // gas logarithm base - gasShift = 90 // gas logarithm shift + gasShift = 174 // gas logarithm shift ) // NewAnteHandler returns an AnteHandler that checks diff --git a/types/gas.go b/types/gas.go index a4bdf265c..e2ed32028 100644 --- a/types/gas.go +++ b/types/gas.go @@ -86,10 +86,10 @@ func (g *basicGasMeter) GasConsumedToLimit() Gas { func (g *basicGasMeter) ConsumeGas(amount Gas, descriptor string) { var overflow bool - // amount = log(amount-g.shift)/log(g.base) + // amount = log(gas)/log(gasBase) if g.base > 1 && amount > g.shift && amount < math.MaxInt64 && (descriptor == GasWritePerByteDesc || descriptor == GasReadPerByteDesc) { - amount = uint64(math.Log(float64(int64(amount-g.shift))) / math.Log(g.base)) + amount = uint64(math.Log(float64(int64(amount))) / math.Log(g.base)) } // TODO: Should we set the consumed field after overflow checking? g.consumed, overflow = AddUint64Overflow(g.consumed, amount) diff --git a/types/gas_test.go b/types/gas_test.go index 902ef6feb..d65fb50bc 100644 --- a/types/gas_test.go +++ b/types/gas_test.go @@ -48,21 +48,26 @@ func TestGasMeterWithLog(t *testing.T) { cases := []struct { limit Gas usage Gas - log float64 + base float64 + shift uint64 desc string expect Gas }{ - {1000, 100, 10, GasWritePerByteDesc, 2}, - {1000, 100, 10, GasReadPerByteDesc, 2}, - {1000, 100, 10, "", 100}, - {1000, 100, 1, GasWritePerByteDesc, 100}, - {1000, 100, 0, GasWritePerByteDesc, 100}, - {1000, 100, 0.99, GasWritePerByteDesc, 100}, - {1000, 100, -0.1, GasWritePerByteDesc, 100}, + {1000, 100, 10, 0, GasWritePerByteDesc, 2}, + {1000, 174, 1.03, 174, GasWritePerByteDesc, 174}, + {1000, 175, 1.03, 174, GasWritePerByteDesc, 174}, + {1000, 177, 1.03, 174, GasWritePerByteDesc, 175}, + {1000, 100, 10, 100, GasWritePerByteDesc, 100}, + {1000, 100, 10, 0, GasReadPerByteDesc, 2}, + {1000, 100, 10, 0, "", 100}, + {1000, 100, 1, 0, GasWritePerByteDesc, 100}, + {1000, 100, 0, 0, GasWritePerByteDesc, 100}, + {1000, 100, 0.99, 0, GasWritePerByteDesc, 100}, + {1000, 100, -0.1, 0, GasWritePerByteDesc, 100}, } for tcnum, tc := range cases { - meter := NewGasMeterWithBase(tc.limit, tc.log, 0) + meter := NewGasMeterWithBase(tc.limit, tc.base, tc.shift) meter.ConsumeGas(tc.usage, tc.desc) require.Equal(t, tc.expect, meter.GasConsumed(), "Gas consumption not match. tc #%d", tcnum) From c51043fec7d0a0c65552658f422957eba0d651d0 Mon Sep 17 00:00:00 2001 From: chengwenxi Date: Fri, 16 Aug 2019 12:53:39 +0800 Subject: [PATCH 6/6] Modify gasBase to 1.02 --- app/v1/auth/ante.go | 4 ++-- types/gas_test.go | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/v1/auth/ante.go b/app/v1/auth/ante.go index 00d1db2e9..9446453e9 100644 --- a/app/v1/auth/ante.go +++ b/app/v1/auth/ante.go @@ -19,8 +19,8 @@ const ( // if gas > gasShift, gas = log(gas)/log(gasBase) // else gasConsumed = gas - gasBase = 1.03 // gas logarithm base - gasShift = 174 // gas logarithm shift + gasBase = 1.02 // gas logarithm base + gasShift = 285 // gas logarithm shift ) // NewAnteHandler returns an AnteHandler that checks diff --git a/types/gas_test.go b/types/gas_test.go index d65fb50bc..e5b6716e0 100644 --- a/types/gas_test.go +++ b/types/gas_test.go @@ -54,9 +54,10 @@ func TestGasMeterWithLog(t *testing.T) { expect Gas }{ {1000, 100, 10, 0, GasWritePerByteDesc, 2}, - {1000, 174, 1.03, 174, GasWritePerByteDesc, 174}, - {1000, 175, 1.03, 174, GasWritePerByteDesc, 174}, - {1000, 177, 1.03, 174, GasWritePerByteDesc, 175}, + {1000, 285, 1.02, 285, GasWritePerByteDesc, 285}, + {1000, 286, 1.02, 285, GasWritePerByteDesc, 285}, + {1000, 288, 1.02, 285, GasWritePerByteDesc, 285}, + {1000, 289, 1.02, 285, GasWritePerByteDesc, 286}, {1000, 100, 10, 100, GasWritePerByteDesc, 100}, {1000, 100, 10, 0, GasReadPerByteDesc, 2}, {1000, 100, 10, 0, "", 100},