Change gas & related fields to unsigned integer type (#2839)
* Change gas & related fields to unsigned integer type * Implement AddUint64Overflow
This commit is contained in:
committed by
Jack Zampolin
parent
f525717054
commit
6e813ab3a8
+3
-1
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user