Skip to content

Commit 87886ad

Browse files
authored
fix: fix ante handler for correct gas consumption (#11)
* fix: fix ante handler for correct gas consumption * fixes * fixes * linting
1 parent a399de6 commit 87886ad

File tree

6 files changed

+80
-19
lines changed

6 files changed

+80
-19
lines changed

x/gnovm/ante/ante.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package ante
22

33
import (
4+
"fmt"
5+
46
storetypes "cosmossdk.io/store/types"
57
sdk "github.com/cosmos/cosmos-sdk/types"
8+
69
"github.com/ignite/gnovm/x/gnovm/types"
710
)
811

@@ -12,21 +15,31 @@ func NewAnteHandler() sdk.AnteDecorator {
1215

1316
type gnoAnteHandler struct{}
1417

15-
func (*gnoAnteHandler) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
18+
func (gnoAnteHandler) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
1619
msgs := tx.GetMsgs()
20+
21+
gnoVMCount := 0
22+
nonGnoVMCount := 0
23+
1724
for _, msg := range msgs {
1825
switch {
1926
case sdk.MsgTypeURL(msg) == sdk.MsgTypeURL(&types.MsgRun{}) ||
2027
sdk.MsgTypeURL(msg) == sdk.MsgTypeURL(&types.MsgAddPackage{}) ||
2128
sdk.MsgTypeURL(msg) == sdk.MsgTypeURL(&types.MsgCall{}):
22-
// Use infinite gas meter for GnoVM transactions because the VM has its own
23-
// internal gas tracking mechanism through the transaction store. Using the
24-
// Cosmos SDK gas meter would result in double-counting gas consumption.
25-
// The VM prevents infinite execution through its own gas limits.
26-
ctx = ctx.WithGasMeter(storetypes.NewInfiniteGasMeter())
27-
return ctx, nil
29+
gnoVMCount++
30+
default:
31+
nonGnoVMCount++
2832
}
2933
}
3034

31-
return ctx, nil
35+
// Reject transactions that mix GnoVM and non-GnoVM messages
36+
if gnoVMCount > 0 && nonGnoVMCount > 0 {
37+
return ctx, fmt.Errorf("cannot mix GnoVM messages with non-GnoVM messages in the same transaction")
38+
}
39+
40+
if gnoVMCount > 0 && simulate {
41+
newCtx = ctx.WithGasMeter(storetypes.NewInfiniteGasMeter())
42+
}
43+
44+
return next(newCtx, tx, simulate)
3245
}

x/gnovm/keeper/keeper.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ func (k *Keeper) initializeVMKeeper(sdkCtx sdk.Context) error {
118118
gnostore.NewStoreKey(k.memStoreKey.Name()),
119119
)
120120

121-
chainID := sdkCtx.HeaderInfo().ChainID
121+
chainID := sdkCtx.ChainID()
122122
if chainID == "" {
123123
k.logger.Warn("chainID is empty when building gno context, using default", "fallback", defaultChainID)
124124
chainID = defaultChainID
@@ -182,7 +182,7 @@ func (k *Keeper) BuildGnoContext(sdkCtx sdk.Context) (gnosdk.Context, error) {
182182
gnostore.NewStoreKey(k.memStoreKey.Name()),
183183
)
184184

185-
chainID := sdkCtx.HeaderInfo().ChainID
185+
chainID := sdkCtx.ChainID()
186186
if chainID == "" {
187187
k.logger.Warn("chainID is empty when building gno context, using default", "fallback", defaultChainID)
188188
chainID = defaultChainID

x/gnovm/keeper/msg_server_add_package.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ package keeper
33
import (
44
"context"
55
"encoding/json"
6+
"fmt"
67

78
errorsmod "cosmossdk.io/errors"
9+
storetypes "cosmossdk.io/store/types"
810
sdk "github.com/cosmos/cosmos-sdk/types"
9-
"github.com/gnolang/gno/gno.land/pkg/sdk/vm"
11+
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
1012

13+
"github.com/gnolang/gno/gno.land/pkg/sdk/vm"
1114
"github.com/gnolang/gno/tm2/pkg/std"
1215

1316
"github.com/ignite/gnovm/x/gnovm/types"
@@ -42,12 +45,28 @@ func (k msgServer) AddPackage(ctx context.Context, msg *types.MsgAddPackage) (*t
4245
Send: send,
4346
MaxDeposit: maxDep,
4447
}
48+
49+
defer func() {
50+
if r := recover(); r != nil {
51+
switch rType := r.(type) {
52+
case storetypes.ErrorOutOfGas:
53+
log := fmt.Sprintf(
54+
"out of gas from VM usage in location: %v; gasUsed: %d",
55+
rType.Descriptor, sdkCtx.GasMeter().GasConsumed())
56+
57+
err = errorsmod.Wrap(sdkerrors.ErrOutOfGas, log)
58+
default:
59+
err = fmt.Errorf("panic while calling VM: %v (%v)", r, rType)
60+
}
61+
} else {
62+
// this commits the changes to the module store (that is only committed later)
63+
k.VMKeeper.CommitGnoTransactionStore(gnoCtx)
64+
}
65+
}()
66+
4567
if err := k.VMKeeper.AddPackage(gnoCtx, vmMsg); err != nil {
4668
return nil, errorsmod.Wrap(err, "failed to add package")
4769
}
4870

49-
// this commits the changes to the module store (that is only committed later)
50-
k.VMKeeper.CommitGnoTransactionStore(gnoCtx)
51-
5271
return &types.MsgAddPackageResponse{}, nil
5372
}

x/gnovm/keeper/msg_server_call.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import (
55
"fmt"
66

77
errorsmod "cosmossdk.io/errors"
8+
storetypes "cosmossdk.io/store/types"
89
sdk "github.com/cosmos/cosmos-sdk/types"
10+
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
911
"github.com/gnolang/gno/gno.land/pkg/sdk/vm"
1012

1113
"github.com/ignite/gnovm/x/gnovm/types"
@@ -31,9 +33,19 @@ func (k msgServer) Call(ctx context.Context, msg *types.MsgCall) (resp *types.Ms
3133
Func: msg.Function,
3234
Args: msg.Args,
3335
}
36+
3437
defer func() {
3538
if r := recover(); r != nil {
36-
err = fmt.Errorf("panic while calling VM: %v", r)
39+
switch rType := r.(type) {
40+
case storetypes.ErrorOutOfGas:
41+
log := fmt.Sprintf(
42+
"out of gas from VM usage in location: %v; gasUsed: %d",
43+
rType.Descriptor, sdkCtx.GasMeter().GasConsumed())
44+
45+
err = errorsmod.Wrap(sdkerrors.ErrOutOfGas, log)
46+
default:
47+
err = fmt.Errorf("panic while calling VM: %v (%v)", r, rType)
48+
}
3749
} else {
3850
// this commits the changes to the module store (that is only committed later)
3951
k.VMKeeper.CommitGnoTransactionStore(gnoCtx)

x/gnovm/keeper/msg_server_run.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ package keeper
33
import (
44
"context"
55
"encoding/json"
6+
"fmt"
67

78
errorsmod "cosmossdk.io/errors"
9+
storetypes "cosmossdk.io/store/types"
810
sdk "github.com/cosmos/cosmos-sdk/types"
11+
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
912
"github.com/gnolang/gno/gno.land/pkg/sdk/vm"
1013
"github.com/gnolang/gno/tm2/pkg/std"
1114

@@ -35,6 +38,24 @@ func (k msgServer) Run(ctx context.Context, msg *types.MsgRun) (*types.MsgRunRes
3538
return nil, errorsmod.Wrap(err, "invalid package")
3639
}
3740

41+
defer func() {
42+
if r := recover(); r != nil {
43+
switch rType := r.(type) {
44+
case storetypes.ErrorOutOfGas:
45+
log := fmt.Sprintf(
46+
"out of gas from VM usage in location: %v; gasUsed: %d",
47+
rType.Descriptor, sdkCtx.GasMeter().GasConsumed())
48+
49+
err = errorsmod.Wrap(sdkerrors.ErrOutOfGas, log)
50+
default:
51+
err = fmt.Errorf("panic while calling VM: %v (%v)", r, rType)
52+
}
53+
} else {
54+
// this commits the changes to the module store (that is only committed later)
55+
k.VMKeeper.CommitGnoTransactionStore(gnoCtx)
56+
}
57+
}()
58+
3859
resp, err := k.VMKeeper.Run(
3960
gnoCtx,
4061
vm.MsgRun{
@@ -48,9 +69,6 @@ func (k msgServer) Run(ctx context.Context, msg *types.MsgRun) (*types.MsgRunRes
4869
return nil, errorsmod.Wrap(err, "failed to run VM")
4970
}
5071

51-
// this commits the changes to the module store (that is only committed later)
52-
k.VMKeeper.CommitGnoTransactionStore(gnoCtx)
53-
5472
return &types.MsgRunResponse{
5573
Result: string(resp),
5674
}, nil

x/gnovm/keeper/msg_server_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,6 @@ func TestMsgCall_Transfer(t *testing.T) {
332332
send, _ = sdk.ParseCoinsNormalized("2000stake")
333333

334334
maxDeposit, _ = sdk.ParseCoinsNormalized("0stake") // no storage deposit
335-
deposit, _ = sdk.ParseCoinsNormalized("0stake") // no storage deposit
336335
// Expected SendCoins for the send parameter
337336
f.bankKeeper.EXPECT().SendCoins(f.ctx, creatorBytes, pkgAddr, send)
338337
// Expected SendCoins for the transfer realm

0 commit comments

Comments
 (0)