Merge PR #5032: Add Events to ABCIMessageLog

This commit is contained in:
Alexander Bezobchuk 2019-09-12 11:05:27 -04:00 committed by GitHub
parent 5bcab79e8a
commit 9eb5375fda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 12 deletions

View File

@ -93,6 +93,9 @@ and tx hash will be returned for specific Tendermint errors:
caching through `CommitKVStoreCacheManager`. Any application wishing to utilize an inter-block cache caching through `CommitKVStoreCacheManager`. Any application wishing to utilize an inter-block cache
must set it in their app via a `BaseApp` option. The `BaseApp` docs have been drastically improved must set it in their app via a `BaseApp` option. The `BaseApp` docs have been drastically improved
to detail this new feature and how state transitions occur. to detail this new feature and how state transitions occur.
* [\#4990](https://github.com/cosmos/cosmos-sdk/issues/4990) Add `Events` to the `ABCIMessageLog` to
provide context and grouping of events based on the messages they correspond to. The `Events` field
in `TxResponse` is deprecated and will be removed in the next major release.
### Bug Fixes ### Bug Fixes

View File

@ -16,7 +16,6 @@ import (
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db" dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/store"
storetypes "github.com/cosmos/cosmos-sdk/store/types" storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
@ -630,7 +629,7 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
// runMsgs iterates through all the messages and executes them. // runMsgs iterates through all the messages and executes them.
// nolint: gocyclo // nolint: gocyclo
func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (result sdk.Result) { func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (result sdk.Result) {
idxLogs := make([]sdk.ABCIMessageLog, 0, len(msgs)) // a list of JSON-encoded logs with msg index msgLogs := make(sdk.ABCIMessageLogs, 0, len(msgs))
var ( var (
data []byte data []byte
@ -664,28 +663,23 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (re
events = events.AppendEvent(sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyAction, msg.Type()))) events = events.AppendEvent(sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyAction, msg.Type())))
events = events.AppendEvents(msgResult.Events) events = events.AppendEvents(msgResult.Events)
idxLog := sdk.ABCIMessageLog{MsgIndex: uint16(i), Log: msgResult.Log}
// stop execution and return on first failed message // stop execution and return on first failed message
if !msgResult.IsOK() { if !msgResult.IsOK() {
idxLog.Success = false msgLogs = append(msgLogs, sdk.NewABCIMessageLog(uint16(i), false, msgResult.Log, events))
idxLogs = append(idxLogs, idxLog)
code = msgResult.Code code = msgResult.Code
codespace = msgResult.Codespace codespace = msgResult.Codespace
break break
} }
idxLog.Success = true msgLogs = append(msgLogs, sdk.NewABCIMessageLog(uint16(i), true, msgResult.Log, events))
idxLogs = append(idxLogs, idxLog)
} }
logJSON := codec.Cdc.MustMarshalJSON(idxLogs)
result = sdk.Result{ result = sdk.Result{
Code: code, Code: code,
Codespace: codespace, Codespace: codespace,
Data: data, Data: data,
Log: strings.TrimSpace(string(logJSON)), Log: strings.TrimSpace(msgLogs.String()),
GasUsed: ctx.GasMeter().GasConsumed(), GasUsed: ctx.GasMeter().GasConsumed(),
Events: events, Events: events,
} }

View File

@ -7,6 +7,8 @@ import (
"math" "math"
"strings" "strings"
"github.com/cosmos/cosmos-sdk/codec"
ctypes "github.com/tendermint/tendermint/rpc/core/types" ctypes "github.com/tendermint/tendermint/rpc/core/types"
) )
@ -50,12 +52,25 @@ type ABCIMessageLog struct {
MsgIndex uint16 `json:"msg_index"` MsgIndex uint16 `json:"msg_index"`
Success bool `json:"success"` Success bool `json:"success"`
Log string `json:"log"` Log string `json:"log"`
// Events contains a slice of Event objects that were emitted during some
// execution.
Events StringEvents `json:"events"`
}
func NewABCIMessageLog(i uint16, success bool, log string, events Events) ABCIMessageLog {
return ABCIMessageLog{
MsgIndex: i,
Success: success,
Log: log,
Events: StringifyEvents(events.ToABCIEvents()),
}
} }
// String implements the fmt.Stringer interface for the ABCIMessageLogs type. // String implements the fmt.Stringer interface for the ABCIMessageLogs type.
func (logs ABCIMessageLogs) String() (str string) { func (logs ABCIMessageLogs) String() (str string) {
if logs != nil { if logs != nil {
raw, err := json.Marshal(logs) raw, err := codec.Cdc.MarshalJSON(logs)
if err == nil { if err == nil {
str = string(raw) str = string(raw)
} }
@ -76,10 +91,13 @@ type TxResponse struct {
Info string `json:"info,omitempty"` Info string `json:"info,omitempty"`
GasWanted int64 `json:"gas_wanted,omitempty"` GasWanted int64 `json:"gas_wanted,omitempty"`
GasUsed int64 `json:"gas_used,omitempty"` GasUsed int64 `json:"gas_used,omitempty"`
Events StringEvents `json:"events,omitempty"`
Codespace string `json:"codespace,omitempty"` Codespace string `json:"codespace,omitempty"`
Tx Tx `json:"tx,omitempty"` Tx Tx `json:"tx,omitempty"`
Timestamp string `json:"timestamp,omitempty"` Timestamp string `json:"timestamp,omitempty"`
// DEPRECATED: Remove in the next next major release in favor of using the
// ABCIMessageLog.Events field.
Events StringEvents `json:"events,omitempty"`
} }
// NewResponseResultTx returns a TxResponse given a ResultTx from tendermint // NewResponseResultTx returns a TxResponse given a ResultTx from tendermint

View File

@ -3,6 +3,7 @@ package types
import ( import (
"testing" "testing"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -27,3 +28,13 @@ func TestParseABCILog(t *testing.T) {
require.Equal(t, res[0].MsgIndex, uint16(1)) require.Equal(t, res[0].MsgIndex, uint16(1))
require.True(t, res[0].Success) require.True(t, res[0].Success)
} }
func TestABCIMessageLog(t *testing.T) {
events := Events{NewEvent("transfer", NewAttribute("sender", "foo"))}
msgLog := NewABCIMessageLog(0, true, "", events)
msgLogs := ABCIMessageLogs{msgLog}
bz, err := codec.Cdc.MarshalJSON(msgLogs)
require.NoError(t, err)
require.Equal(t, string(bz), msgLogs.String())
}