Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: emit ante events even for the failed txs #10631

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ Ref: https://keepachangelog.com/en/1.0.0/

## [Unreleased]

### Improvements
* (baseapp) [\#10631](https://github.com/cosmos/cosmos-sdk/pull/10631) Emit ante events even for the failed txs.

## [v0.44.4](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.44.4) - 2021-11-25

### Improvements
Expand Down
8 changes: 4 additions & 4 deletions baseapp/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,9 @@ func (app *BaseApp) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx {
panic(fmt.Sprintf("unknown RequestCheckTx type: %s", req.Type))
}

gInfo, result, err := app.runTx(mode, req.Tx)
gInfo, result, anteEvents, err := app.runTx(mode, req.Tx)
yun-yeo marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return sdkerrors.ResponseCheckTx(err, gInfo.GasWanted, gInfo.GasUsed, app.trace)
return sdkerrors.ResponseCheckTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, anteEvents, app.trace)
}

return abci.ResponseCheckTx{
Expand Down Expand Up @@ -272,10 +272,10 @@ func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx
telemetry.SetGauge(float32(gInfo.GasWanted), "tx", "gas", "wanted")
}()

gInfo, result, err := app.runTx(runTxModeDeliver, req.Tx)
gInfo, result, anteEvents, err := app.runTx(runTxModeDeliver, req.Tx)
if err != nil {
resultStr = "failed"
return sdkerrors.ResponseDeliverTx(err, gInfo.GasWanted, gInfo.GasUsed, app.trace)
return sdkerrors.ResponseDeliverTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, anteEvents, app.trace)
}

return abci.ResponseDeliverTx{
Expand Down
20 changes: 10 additions & 10 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ func (app *BaseApp) cacheTxContext(ctx sdk.Context, txBytes []byte) (sdk.Context
// Note, gas execution info is always returned. A reference to a Result is
// returned if the tx does not run out of gas and if all the messages are valid
// and execute successfully. An error is returned otherwise.
func (app *BaseApp) runTx(mode runTxMode, txBytes []byte) (gInfo sdk.GasInfo, result *sdk.Result, err error) {
func (app *BaseApp) runTx(mode runTxMode, txBytes []byte) (gInfo sdk.GasInfo, result *sdk.Result, anteEvents []abci.Event, err error) {
// NOTE: GasWanted should be returned by the AnteHandler. GasUsed is
// determined by the GasMeter. We need access to the context to get the gas
// meter so we initialize upfront.
Expand All @@ -584,7 +584,7 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte) (gInfo sdk.GasInfo, re
// only run the tx if there is block gas remaining
if mode == runTxModeDeliver && ctx.BlockGasMeter().IsOutOfGas() {
gInfo = sdk.GasInfo{GasUsed: ctx.BlockGasMeter().GasConsumed()}
return gInfo, nil, sdkerrors.Wrap(sdkerrors.ErrOutOfGas, "no block gas left to run tx")
return gInfo, nil, nil, sdkerrors.Wrap(sdkerrors.ErrOutOfGas, "no block gas left to run tx")
}

var startingGas uint64
Expand Down Expand Up @@ -620,15 +620,14 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte) (gInfo sdk.GasInfo, re

tx, err := app.txDecoder(txBytes)
if err != nil {
return sdk.GasInfo{}, nil, err
return sdk.GasInfo{}, nil, nil, err
}

msgs := tx.GetMsgs()
if err := validateBasicTxMsgs(msgs); err != nil {
return sdk.GasInfo{}, nil, err
return sdk.GasInfo{}, nil, nil, err
}

var events sdk.Events
if app.anteHandler != nil {
var (
anteCtx sdk.Context
Expand Down Expand Up @@ -656,16 +655,17 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte) (gInfo sdk.GasInfo, re
ctx = newCtx.WithMultiStore(ms)
}

events = ctx.EventManager().Events()
events := ctx.EventManager().Events()

// GasMeter expected to be set in AnteHandler
gasWanted = ctx.GasMeter().Limit()

if err != nil {
return gInfo, nil, err
return gInfo, nil, nil, err
}

msCache.Write()
anteEvents = events.ToABCIEvents()
}

// Create a new Context based off of the existing Context with a MultiStore branch
Expand All @@ -680,13 +680,13 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte) (gInfo sdk.GasInfo, re
if err == nil && mode == runTxModeDeliver {
msCache.Write()

if len(events) > 0 {
if len(anteEvents) > 0 {
// append the events in the order of occurrence
result.Events = append(events.ToABCIEvents(), result.Events...)
result.Events = append(anteEvents, result.Events...)
}
}

return gInfo, result, err
return gInfo, result, anteEvents, err
}

// runMsgs iterates through a list of messages and executes them with the provided
Expand Down
3 changes: 2 additions & 1 deletion baseapp/baseapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1543,7 +1543,8 @@ func TestBaseAppAnteHandler(t *testing.T) {
require.NoError(t, err)

res = app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
require.Empty(t, res.Events)
// should emit ante event
require.NotEmpty(t, res.Events)
require.False(t, res.IsOK(), fmt.Sprintf("%v", res))

ctx = app.getState(runTxModeDeliver).ctx
Expand Down
9 changes: 6 additions & 3 deletions baseapp/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ func (app *BaseApp) Check(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk
if err != nil {
return sdk.GasInfo{}, nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "%s", err)
}
return app.runTx(runTxModeCheck, bz)
gasInfo, result, _, err := app.runTx(runTxModeCheck, bz)
return gasInfo, result, err
}

func (app *BaseApp) Simulate(txBytes []byte) (sdk.GasInfo, *sdk.Result, error) {
return app.runTx(runTxModeSimulate, txBytes)
gasInfo, result, _, err := app.runTx(runTxModeSimulate, txBytes)
return gasInfo, result, err
}

func (app *BaseApp) Deliver(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) {
Expand All @@ -28,7 +30,8 @@ func (app *BaseApp) Deliver(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *s
if err != nil {
return sdk.GasInfo{}, nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "%s", err)
}
return app.runTx(runTxModeDeliver, bz)
gasInfo, result, _, err := app.runTx(runTxModeDeliver, bz)
return gasInfo, result, err
}

// Context with current {check, deliver}State of the app used by tests.
Expand Down
28 changes: 28 additions & 0 deletions types/errors/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@ func ResponseCheckTx(err error, gw, gu uint64, debug bool) abci.ResponseCheckTx
}
}

// ResponseCheckTxWithEvents returns an ABCI ResponseCheckTx object with fields filled in
// from the given error, gas values and events.
func ResponseCheckTxWithEvents(err error, gw, gu uint64, events []abci.Event, debug bool) abci.ResponseCheckTx {
space, code, log := ABCIInfo(err, debug)
return abci.ResponseCheckTx{
Codespace: space,
Code: code,
Log: log,
GasWanted: int64(gw),
GasUsed: int64(gu),
Events: events,
}
}

// ResponseDeliverTx returns an ABCI ResponseDeliverTx object with fields filled in
// from the given error and gas values.
func ResponseDeliverTx(err error, gw, gu uint64, debug bool) abci.ResponseDeliverTx {
Expand All @@ -65,6 +79,20 @@ func ResponseDeliverTx(err error, gw, gu uint64, debug bool) abci.ResponseDelive
}
}

// ResponseDeliverTxWithEvents returns an ABCI ResponseDeliverTx object with fields filled in
// from the given error, gas values and events.
func ResponseDeliverTxWithEvents(err error, gw, gu uint64, events []abci.Event, debug bool) abci.ResponseDeliverTx {
space, code, log := ABCIInfo(err, debug)
return abci.ResponseDeliverTx{
Codespace: space,
Code: code,
Log: log,
GasWanted: int64(gw),
GasUsed: int64(gu),
Events: events,
}
}

// QueryResult returns a ResponseQuery from an error. It will try to parse ABCI
// info from the error.
func QueryResult(err error) abci.ResponseQuery {
Expand Down