Skip to content

Commit 90edeb6

Browse files
fedekunzeAlessio Tregliaamaury1093
authored
feat: add RefundGas function to GasMeter (cosmos#9403)
* 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>
1 parent 33c045c commit 90edeb6

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,9 @@ if input key is empty, or input data contains empty key.
128128

129129
### Improvements
130130

131+
* (store) [\#9403](https://github.com/cosmos/cosmos-sdk/pull/9403) Add `RefundGas` function to `GasMeter` interface
132+
* (baseapp, types) [\#9390](https://github.com/cosmos/cosmos-sdk/pull/9390) Add current block header hash to `Context`
131133
* (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.
132-
* (baseapp, types) [#\9390](https://github.com/cosmos/cosmos-sdk/pull/9390) Add current block header hash to `Context`
133134
* (x/bank) [\#8614](https://github.com/cosmos/cosmos-sdk/issues/8614) Add `Name` and `Symbol` fields to denom metadata
134135
* (x/auth) [\#8522](https://github.com/cosmos/cosmos-sdk/pull/8522) Allow to query all stored accounts
135136
* (crypto/types) [\#8600](https://github.com/cosmos/cosmos-sdk/pull/8600) `CompactBitArray`: optimize the `NumTrueBitsBefore` method and add an `Equal` method.

store/types/gas.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ const (
2020
// Gas measured by the SDK
2121
type Gas = uint64
2222

23+
// ErrorNegativeGasConsumed defines an error thrown when the amount of gas refunded results in a
24+
// negative gas consumed amount.
25+
type ErrorNegativeGasConsumed struct {
26+
Descriptor string
27+
}
28+
2329
// ErrorOutOfGas defines an error thrown when an action results in out of gas.
2430
type ErrorOutOfGas struct {
2531
Descriptor string
@@ -37,6 +43,7 @@ type GasMeter interface {
3743
GasConsumedToLimit() Gas
3844
Limit() Gas
3945
ConsumeGas(amount Gas, descriptor string)
46+
RefundGas(amount Gas, descriptor string)
4047
IsPastLimit() bool
4148
IsOutOfGas() bool
4249
String() string
@@ -91,7 +98,20 @@ func (g *basicGasMeter) ConsumeGas(amount Gas, descriptor string) {
9198
if g.consumed > g.limit {
9299
panic(ErrorOutOfGas{descriptor})
93100
}
101+
}
102+
103+
// RefundGas will deduct the given amount from the gas consumed. If the amount is greater than the
104+
// gas consumed, the function will panic.
105+
//
106+
// Use case: This functionality enables refunding gas to the transaction or block gas pools so that
107+
// EVM-compatible chains can fully support the go-ethereum StateDb interface.
108+
// See https://github.com/cosmos/cosmos-sdk/pull/9403 for reference.
109+
func (g *basicGasMeter) RefundGas(amount Gas, descriptor string) {
110+
if g.consumed < amount {
111+
panic(ErrorNegativeGasConsumed{Descriptor: descriptor})
112+
}
94113

114+
g.consumed -= amount
95115
}
96116

97117
func (g *basicGasMeter) IsPastLimit() bool {
@@ -138,6 +158,20 @@ func (g *infiniteGasMeter) ConsumeGas(amount Gas, descriptor string) {
138158
}
139159
}
140160

161+
// RefundGas will deduct the given amount from the gas consumed. If the amount is greater than the
162+
// gas consumed, the function will panic.
163+
//
164+
// Use case: This functionality enables refunding gas to the trasaction or block gas pools so that
165+
// EVM-compatible chains can fully support the go-ethereum StateDb interface.
166+
// See https://github.com/cosmos/cosmos-sdk/pull/9403 for reference.
167+
func (g *infiniteGasMeter) RefundGas(amount Gas, descriptor string) {
168+
if g.consumed < amount {
169+
panic(ErrorNegativeGasConsumed{Descriptor: descriptor})
170+
}
171+
172+
g.consumed -= amount
173+
}
174+
141175
func (g *infiniteGasMeter) IsPastLimit() bool {
142176
return false
143177
}

store/types/gas_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@ func TestInfiniteGasMeter(t *testing.T) {
1616
meter.ConsumeGas(10, "consume 10")
1717
require.Equal(t, uint64(10), meter.GasConsumed())
1818
require.Equal(t, uint64(10), meter.GasConsumedToLimit())
19+
meter.RefundGas(1, "refund 1")
20+
require.Equal(t, uint64(9), meter.GasConsumed())
1921
require.False(t, meter.IsPastLimit())
2022
require.False(t, meter.IsOutOfGas())
2123
meter.ConsumeGas(Gas(math.MaxUint64/2), "consume half max uint64")
2224
require.Panics(t, func() { meter.ConsumeGas(Gas(math.MaxUint64/2)+2, "panic") })
25+
require.Panics(t, func() { meter.RefundGas(meter.GasConsumed()+1, "refund greater than consumed") })
2326
}
2427

2528
func TestGasMeter(t *testing.T) {
@@ -57,6 +60,11 @@ func TestGasMeter(t *testing.T) {
5760
require.Panics(t, func() { meter.ConsumeGas(1, "") }, "Exceeded but not panicked. tc #%d", tcnum)
5861
require.Equal(t, meter.GasConsumedToLimit(), meter.Limit(), "Gas consumption (to limit) not match limit")
5962
require.Equal(t, meter.GasConsumed(), meter.Limit()+1, "Gas consumption not match limit+1")
63+
64+
require.NotPanics(t, func() { meter.RefundGas(1, "refund 1") })
65+
require.Equal(t, meter.GasConsumed(), meter.Limit(), "Gas consumption not match limit+1")
66+
require.Panics(t, func() { meter.RefundGas(meter.GasConsumed()+1, "refund greater than consumed") })
67+
6068
meter2 := NewGasMeter(math.MaxUint64)
6169
meter2.ConsumeGas(Gas(math.MaxUint64/2), "consume half max uint64")
6270
require.Panics(t, func() { meter2.ConsumeGas(Gas(math.MaxUint64/2)+2, "panic") })

0 commit comments

Comments
 (0)