Skip to content

Commit

Permalink
feat: add RefundGas function to GasMeter (#9403)
Browse files Browse the repository at this point in the history
* feat: add RefundGas function to GasMeter

* changelog

* add comment about use case

* Apply suggestions from code review

Co-authored-by: Alessio Treglia <alessio@tendermint.com>
Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com>
(cherry picked from commit 90edeb6)

# Conflicts:
#	CHANGELOG.md
  • Loading branch information
fedekunze authored and mergify-bot committed Jun 17, 2021
1 parent 35e9e7a commit a7b5fa5
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 0 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,23 @@ Ref: https://keepachangelog.com/en/1.0.0/
* [\#9383](https://github.com/cosmos/cosmos-sdk/pull/9383) New CLI command `query ibc-transfer escrow-address <port> <channel id>` to get the escrow address for a channel; can be used to then query balance of escrowed tokens


<<<<<<< HEAD
## [v0.42.5](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.42.5) - 2021-05-18
=======
### Improvements

* (store) [\#9403](https://github.com/cosmos/cosmos-sdk/pull/9403) Add `RefundGas` function to `GasMeter` interface
* (baseapp, types) [\#9390](https://github.com/cosmos/cosmos-sdk/pull/9390) Add current block header hash to `Context`
* (x/staking) [\#9423](https://github.com/cosmos/cosmos-sdk/pull/9423) Staking delegations now returns empty list instead of rpc error when no records found.
* (x/bank) [\#8614](https://github.com/cosmos/cosmos-sdk/issues/8614) Add `Name` and `Symbol` fields to denom metadata
* (x/auth) [\#8522](https://github.com/cosmos/cosmos-sdk/pull/8522) Allow to query all stored accounts
* (crypto/types) [\#8600](https://github.com/cosmos/cosmos-sdk/pull/8600) `CompactBitArray`: optimize the `NumTrueBitsBefore` method and add an `Equal` method.
* (x/upgrade) [\#8743](https://github.com/cosmos/cosmos-sdk/pull/8743) Add tracking module versions as per ADR-041
* (types) [\#8962](https://github.com/cosmos/cosmos-sdk/issues/8962) Add `Abs()` method to `sdk.Int`.
* (x/bank) [\#8950](https://github.com/cosmos/cosmos-sdk/pull/8950) Improve efficiency on supply updates.
* (store) [\#8012](https://github.com/cosmos/cosmos-sdk/pull/8012) Implementation of ADR-038 WriteListener and listen.KVStore
* (makefile) [\#7933](https://github.com/cosmos/cosmos-sdk/issues/7933) Use Docker to generate swagger files.
>>>>>>> 90edeb67e (feat: add `RefundGas` function to `GasMeter` (#9403))
### Bug Fixes

Expand Down
34 changes: 34 additions & 0 deletions store/types/gas.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ const (
// Gas measured by the SDK
type Gas = uint64

// ErrorNegativeGasConsumed defines an error thrown when the amount of gas refunded results in a
// negative gas consumed amount.
type ErrorNegativeGasConsumed struct {
Descriptor string
}

// ErrorOutOfGas defines an error thrown when an action results in out of gas.
type ErrorOutOfGas struct {
Descriptor string
Expand All @@ -37,6 +43,7 @@ type GasMeter interface {
GasConsumedToLimit() Gas
Limit() Gas
ConsumeGas(amount Gas, descriptor string)
RefundGas(amount Gas, descriptor string)
IsPastLimit() bool
IsOutOfGas() bool
String() string
Expand Down Expand Up @@ -91,7 +98,20 @@ func (g *basicGasMeter) ConsumeGas(amount Gas, descriptor string) {
if g.consumed > g.limit {
panic(ErrorOutOfGas{descriptor})
}
}

// RefundGas will deduct the given amount from the gas consumed. If the amount is greater than the
// gas consumed, the function will panic.
//
// Use case: This functionality enables refunding gas to the transaction or block gas pools so that
// EVM-compatible chains can fully support the go-ethereum StateDb interface.
// See https://github.com/cosmos/cosmos-sdk/pull/9403 for reference.
func (g *basicGasMeter) RefundGas(amount Gas, descriptor string) {
if g.consumed < amount {
panic(ErrorNegativeGasConsumed{Descriptor: descriptor})
}

g.consumed -= amount
}

func (g *basicGasMeter) IsPastLimit() bool {
Expand Down Expand Up @@ -138,6 +158,20 @@ func (g *infiniteGasMeter) ConsumeGas(amount Gas, descriptor string) {
}
}

// RefundGas will deduct the given amount from the gas consumed. If the amount is greater than the
// gas consumed, the function will panic.
//
// Use case: This functionality enables refunding gas to the trasaction or block gas pools so that
// EVM-compatible chains can fully support the go-ethereum StateDb interface.
// See https://github.com/cosmos/cosmos-sdk/pull/9403 for reference.
func (g *infiniteGasMeter) RefundGas(amount Gas, descriptor string) {
if g.consumed < amount {
panic(ErrorNegativeGasConsumed{Descriptor: descriptor})
}

g.consumed -= amount
}

func (g *infiniteGasMeter) IsPastLimit() bool {
return false
}
Expand Down
8 changes: 8 additions & 0 deletions store/types/gas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ func TestInfiniteGasMeter(t *testing.T) {
meter.ConsumeGas(10, "consume 10")
require.Equal(t, uint64(10), meter.GasConsumed())
require.Equal(t, uint64(10), meter.GasConsumedToLimit())
meter.RefundGas(1, "refund 1")
require.Equal(t, uint64(9), meter.GasConsumed())
require.False(t, meter.IsPastLimit())
require.False(t, meter.IsOutOfGas())
meter.ConsumeGas(Gas(math.MaxUint64/2), "consume half max uint64")
require.Panics(t, func() { meter.ConsumeGas(Gas(math.MaxUint64/2)+2, "panic") })
require.Panics(t, func() { meter.RefundGas(meter.GasConsumed()+1, "refund greater than consumed") })
}

func TestGasMeter(t *testing.T) {
Expand Down Expand Up @@ -57,6 +60,11 @@ func TestGasMeter(t *testing.T) {
require.Panics(t, func() { meter.ConsumeGas(1, "") }, "Exceeded but not panicked. tc #%d", tcnum)
require.Equal(t, meter.GasConsumedToLimit(), meter.Limit(), "Gas consumption (to limit) not match limit")
require.Equal(t, meter.GasConsumed(), meter.Limit()+1, "Gas consumption not match limit+1")

require.NotPanics(t, func() { meter.RefundGas(1, "refund 1") })
require.Equal(t, meter.GasConsumed(), meter.Limit(), "Gas consumption not match limit+1")
require.Panics(t, func() { meter.RefundGas(meter.GasConsumed()+1, "refund greater than consumed") })

meter2 := NewGasMeter(math.MaxUint64)
meter2.ConsumeGas(Gas(math.MaxUint64/2), "consume half max uint64")
require.Panics(t, func() { meter2.ConsumeGas(Gas(math.MaxUint64/2)+2, "panic") })
Expand Down

0 comments on commit a7b5fa5

Please sign in to comment.