Change gas & related fields to unsigned integer type (#2839)

* Change gas & related fields to unsigned integer type
* Implement AddUint64Overflow
This commit is contained in:
Alexander Bezobchuk
2018-11-19 09:13:45 -08:00
committed by Jack Zampolin
parent f525717054
commit 6e813ab3a8
25 changed files with 127 additions and 68 deletions
+3 -1
View File
@@ -203,8 +203,10 @@ func (c Context) WithConsensusParams(params *abci.ConsensusParams) Context {
if params == nil {
return c
}
// TODO: Do we need to handle invalid MaxGas values?
return c.withValue(contextKeyConsensusParams, params).
WithGasMeter(NewGasMeter(params.BlockSize.MaxGas))
WithGasMeter(NewGasMeter(uint64(params.BlockSize.MaxGas)))
}
func (c Context) WithChainID(chainID string) Context { return c.withValue(contextKeyChainID, chainID) }
+22 -3
View File
@@ -18,13 +18,19 @@ var (
)
// Gas measured by the SDK
type Gas = int64
type Gas = uint64
// ErrorOutOfGas defines an error thrown when an action results in out of gas.
type ErrorOutOfGas struct {
Descriptor string
}
// ErrorGasOverflow defines an error thrown when an action results gas consumption
// unsigned integer overflow.
type ErrorGasOverflow struct {
Descriptor string
}
// GasMeter interface to track gas consumption
type GasMeter interface {
GasConsumed() Gas
@@ -49,7 +55,14 @@ func (g *basicGasMeter) GasConsumed() Gas {
}
func (g *basicGasMeter) ConsumeGas(amount Gas, descriptor string) {
g.consumed += amount
var overflow bool
// TODO: Should we set the consumed field after overflow checking?
g.consumed, overflow = AddUint64Overflow(g.consumed, amount)
if overflow {
panic(ErrorGasOverflow{descriptor})
}
if g.consumed > g.limit {
panic(ErrorOutOfGas{descriptor})
}
@@ -71,7 +84,13 @@ func (g *infiniteGasMeter) GasConsumed() Gas {
}
func (g *infiniteGasMeter) ConsumeGas(amount Gas, descriptor string) {
g.consumed += amount
var overflow bool
// TODO: Should we set the consumed field after overflow checking?
g.consumed, overflow = AddUint64Overflow(g.consumed, amount)
if overflow {
panic(ErrorGasOverflow{descriptor})
}
}
// GasConfig defines gas cost for each operation on KVStores
+1 -1
View File
@@ -21,7 +21,7 @@ func TestGasMeter(t *testing.T) {
for tcnum, tc := range cases {
meter := NewGasMeter(tc.limit)
used := int64(0)
used := uint64(0)
for unum, usage := range tc.usage {
used += usage
+11
View File
@@ -2,6 +2,7 @@ package types
import (
"encoding/json"
"math"
"testing"
"math/big"
@@ -529,6 +530,16 @@ func (i *Uint) UnmarshalJSON(bz []byte) error {
//__________________________________________________________________________
// AddUint64Overflow performs the addition operation on two uint64 integers and
// returns a boolean on whether or not the result overflows.
func AddUint64Overflow(a, b uint64) (uint64, bool) {
if math.MaxUint64-a < b {
return 0, true
}
return a + b, false
}
// intended to be used with require/assert: require.True(IntEq(...))
func IntEq(t *testing.T, exp, got Int) (*testing.T, bool, string, string, string) {
return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp.String(), got.String()
+25
View File
@@ -590,3 +590,28 @@ func TestEncodingTableUint(t *testing.T) {
require.Equal(t, tc.i, i, "Unmarshaled value is different from expected. tc #%d", tcnum)
}
}
func TestAddUint64Overflow(t *testing.T) {
testCases := []struct {
a, b uint64
result uint64
overflow bool
}{
{0, 0, 0, false},
{100, 100, 200, false},
{math.MaxUint64 / 2, math.MaxUint64/2 + 1, math.MaxUint64, false},
{math.MaxUint64 / 2, math.MaxUint64/2 + 2, 0, true},
}
for i, tc := range testCases {
res, overflow := AddUint64Overflow(tc.a, tc.b)
require.Equal(
t, tc.overflow, overflow,
"invalid overflow result; tc: #%d, a: %d, b: %d", i, tc.a, tc.b,
)
require.Equal(
t, tc.result, res,
"invalid uint64 result; tc: #%d, a: %d, b: %d", i, tc.a, tc.b,
)
}
}
+2 -2
View File
@@ -16,10 +16,10 @@ type Result struct {
Log string
// GasWanted is the maximum units of work we allow this tx to perform.
GasWanted int64
GasWanted uint64
// GasUsed is the amount of gas actually consumed. NOTE: unimplemented
GasUsed int64
GasUsed uint64
// Tx fee amount and denom.
FeeAmount int64