refactor: middleware refactor to change tx.Handler interface (#10527)

<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->

## Description

Closes: #10484 

This PR makes the following big changes:

### 1. Change the tx.Handler interface

```diff
-	CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error)
+	CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error)
// same for Deliver and Simulate
```
 where:

```go
type Response struct {
	GasWanted uint64
	GasUsed   uint64
	// MsgResponses is an array containing each Msg service handler's response
	// type, packed in an Any. This will get proto-serialized into the `Data` field
	// in the ABCI Check/DeliverTx responses.
	MsgResponses []*codectypes.Any
	Log          string
	Events       []abci.Event
}
```

### 2. Change what gets passed into the ABCI Check/DeliverTx `Data` field

Before, we were passing the concatenation of MsgResponse bytes into the `Data`. Now we are passing the proto-serialiazation of this struct:

```proto
message TxMsgData {
  repeated google.protobuf.Any msg_responses = 2;
}
```

<!-- Add a description of the changes that this PR introduces and the files that
are the most critical to review. -->

---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed 
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
This commit is contained in:
atheeshp 2021-12-02 12:24:38 +05:30 committed by GitHub
parent 25f3af2f0a
commit 5d86db3ce5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 884 additions and 570 deletions

View File

@ -21,6 +21,7 @@ import (
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx"
)
// InitChain implements the ABCI interface. It runs the initialization logic
@ -249,18 +250,23 @@ func (app *BaseApp) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx {
panic(fmt.Sprintf("unknown RequestCheckTx type: %s", req.Type))
}
tx, err := app.txDecoder(req.Tx)
reqTx, err := app.txDecoder(req.Tx)
if err != nil {
return sdkerrors.ResponseCheckTx(err, 0, 0, app.trace)
}
ctx := app.getContextForTx(mode, req.Tx)
res, err := app.txHandler.CheckTx(ctx, tx, req)
res, checkRes, err := app.txHandler.CheckTx(ctx, tx.Request{Tx: reqTx, TxBytes: req.Tx}, tx.RequestCheckTx{Type: req.Type})
if err != nil {
return sdkerrors.ResponseCheckTx(err, uint64(res.GasUsed), uint64(res.GasWanted), app.trace)
}
return res
abciRes, err := convertTxResponseToCheckTx(res, checkRes)
if err != nil {
return sdkerrors.ResponseCheckTx(err, uint64(res.GasUsed), uint64(res.GasWanted), app.trace)
}
return abciRes
}
// DeliverTx implements the ABCI interface and executes a tx in DeliverTx mode.
@ -271,28 +277,34 @@ func (app *BaseApp) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx {
func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx {
defer telemetry.MeasureSince(time.Now(), "abci", "deliver_tx")
var res abci.ResponseDeliverTx
var abciRes abci.ResponseDeliverTx
defer func() {
for _, streamingListener := range app.abciListeners {
if err := streamingListener.ListenDeliverTx(app.deliverState.ctx, req, res); err != nil {
if err := streamingListener.ListenDeliverTx(app.deliverState.ctx, req, abciRes); err != nil {
app.logger.Error("DeliverTx listening hook failed", "err", err)
}
}
}()
tx, err := app.txDecoder(req.Tx)
reqTx, err := app.txDecoder(req.Tx)
if err != nil {
res = sdkerrors.ResponseDeliverTx(err, 0, 0, app.trace)
return res
abciRes = sdkerrors.ResponseDeliverTx(err, 0, 0, app.trace)
return abciRes
}
ctx := app.getContextForTx(runTxModeDeliver, req.Tx)
res, err = app.txHandler.DeliverTx(ctx, tx, req)
res, err := app.txHandler.DeliverTx(ctx, tx.Request{Tx: reqTx, TxBytes: req.Tx})
if err != nil {
res = sdkerrors.ResponseDeliverTx(err, uint64(res.GasUsed), uint64(res.GasWanted), app.trace)
return res
abciRes = sdkerrors.ResponseDeliverTx(err, uint64(res.GasUsed), uint64(res.GasWanted), app.trace)
return abciRes
}
return res
abciRes, err = convertTxResponseToDeliverTx(res)
if err != nil {
return sdkerrors.ResponseDeliverTx(err, uint64(res.GasUsed), uint64(res.GasWanted), app.trace)
}
return abciRes
}
// Commit implements the ABCI interface. It will commit all state that exists in
@ -894,3 +906,37 @@ func splitPath(requestPath string) (path []string) {
return path
}
// makeABCIData generates the Data field to be sent to ABCI Check/DeliverTx.
func makeABCIData(txRes tx.Response) ([]byte, error) {
return proto.Marshal(&sdk.TxMsgData{MsgResponses: txRes.MsgResponses})
}
// convertTxResponseToCheckTx converts a tx.Response into a abci.ResponseCheckTx.
func convertTxResponseToCheckTx(txRes tx.Response, checkRes tx.ResponseCheckTx) (abci.ResponseCheckTx, error) {
data, err := makeABCIData(txRes)
if err != nil {
return abci.ResponseCheckTx{}, nil
}
return abci.ResponseCheckTx{
Data: data,
Log: txRes.Log,
Events: txRes.Events,
Priority: checkRes.Priority,
}, nil
}
// convertTxResponseToDeliverTx converts a tx.Response into a abci.ResponseDeliverTx.
func convertTxResponseToDeliverTx(txRes tx.Response) (abci.ResponseDeliverTx, error) {
data, err := makeABCIData(txRes)
if err != nil {
return abci.ResponseDeliverTx{}, nil
}
return abci.ResponseDeliverTx{
Data: data,
Log: txRes.Log,
Events: txRes.Events,
}, nil
}

View File

@ -23,6 +23,7 @@ import (
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/snapshots"
snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types"
"github.com/cosmos/cosmos-sdk/store/rootmulti"
@ -148,7 +149,14 @@ func setupBaseAppWithSnapshots(t *testing.T, blocks uint, blockTxs int, options
legacyRouter.AddRoute(sdk.NewRoute(routeMsgKeyValue, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
kv := msg.(*msgKeyValue)
bapp.CMS().GetCommitKVStore(capKey2).Set(kv.Key, kv.Value)
return &sdk.Result{}, nil
any, err := codectypes.NewAnyWithValue(msg)
if err != nil {
return nil, err
}
return &sdk.Result{
MsgResponses: []*codectypes.Any{any},
}, nil
}))
txHandler := testTxHandler(
middleware.TxHandlerOptions{
@ -716,7 +724,7 @@ func (tx *txTest) setFailOnAnte(fail bool) {
func (tx *txTest) setFailOnHandler(fail bool) {
for i, msg := range tx.Msgs {
tx.Msgs[i] = msgCounter{msg.(msgCounter).Counter, fail}
tx.Msgs[i] = &msgCounter{msg.(*msgCounter).Counter, fail}
}
}
@ -744,16 +752,16 @@ type msgCounter struct {
}
// dummy implementation of proto.Message
func (msg msgCounter) Reset() {}
func (msg msgCounter) String() string { return "TODO" }
func (msg msgCounter) ProtoMessage() {}
func (msg *msgCounter) Reset() {}
func (msg *msgCounter) String() string { return "TODO" }
func (msg *msgCounter) ProtoMessage() {}
// Implements Msg
func (msg msgCounter) Route() string { return routeMsgCounter }
func (msg msgCounter) Type() string { return "counter1" }
func (msg msgCounter) GetSignBytes() []byte { return nil }
func (msg msgCounter) GetSigners() []sdk.AccAddress { return nil }
func (msg msgCounter) ValidateBasic() error {
func (msg *msgCounter) Route() string { return routeMsgCounter }
func (msg *msgCounter) Type() string { return "counter1" }
func (msg *msgCounter) GetSignBytes() []byte { return nil }
func (msg *msgCounter) GetSigners() []sdk.AccAddress { return nil }
func (msg *msgCounter) ValidateBasic() error {
if msg.Counter >= 0 {
return nil
}
@ -763,7 +771,7 @@ func (msg msgCounter) ValidateBasic() error {
func newTxCounter(counter int64, msgCounters ...int64) txTest {
msgs := make([]sdk.Msg, 0, len(msgCounters))
for _, c := range msgCounters {
msgs = append(msgs, msgCounter{c, false})
msgs = append(msgs, &msgCounter{c, false})
}
return txTest{msgs, counter, false, math.MaxUint64}
@ -903,6 +911,14 @@ func handlerMsgCounter(t *testing.T, capKey storetypes.StoreKey, deliverKey []by
}
res.Events = ctx.EventManager().Events().ToABCIEvents()
any, err := codectypes.NewAnyWithValue(msg)
if err != nil {
return nil, err
}
res.MsgResponses = []*codectypes.Any{any}
return res, nil
}
}
@ -1153,7 +1169,15 @@ func TestSimulateTx(t *testing.T) {
legacyRouter := middleware.NewLegacyRouter()
r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
ctx.GasMeter().ConsumeGas(gasConsumed, "test")
return &sdk.Result{}, nil
// Return dummy MsgResponse for msgCounter.
any, err := codectypes.NewAnyWithValue(&testdata.Dog{})
if err != nil {
return nil, err
}
return &sdk.Result{
MsgResponses: []*codectypes.Any{any},
}, nil
})
legacyRouter.AddRoute(r)
txHandler := testTxHandler(
@ -1221,7 +1245,14 @@ func TestRunInvalidTransaction(t *testing.T) {
txHandlerOpt := func(bapp *baseapp.BaseApp) {
legacyRouter := middleware.NewLegacyRouter()
r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
return &sdk.Result{}, nil
any, err := codectypes.NewAnyWithValue(msg)
if err != nil {
return nil, err
}
return &sdk.Result{
MsgResponses: []*codectypes.Any{any},
}, nil
})
legacyRouter.AddRoute(r)
txHandler := testTxHandler(
@ -1269,7 +1300,7 @@ func TestRunInvalidTransaction(t *testing.T) {
for _, testCase := range testCases {
tx := testCase.tx
_, result, err := app.SimDeliver(aminoTxEncoder(), tx)
_, _, err := app.SimDeliver(aminoTxEncoder(), tx)
if testCase.fail {
require.Error(t, err)
@ -1278,14 +1309,14 @@ func TestRunInvalidTransaction(t *testing.T) {
require.EqualValues(t, sdkerrors.ErrInvalidSequence.Codespace(), space, err)
require.EqualValues(t, sdkerrors.ErrInvalidSequence.ABCICode(), code, err)
} else {
require.NotNil(t, result)
require.NoError(t, err)
}
}
}
// transaction with no known route
{
unknownRouteTx := txTest{[]sdk.Msg{msgNoRoute{}}, 0, false, math.MaxUint64}
unknownRouteTx := txTest{[]sdk.Msg{&msgNoRoute{}}, 0, false, math.MaxUint64}
_, result, err := app.SimDeliver(aminoTxEncoder(), unknownRouteTx)
require.Error(t, err)
require.Nil(t, result)
@ -1294,7 +1325,7 @@ func TestRunInvalidTransaction(t *testing.T) {
require.EqualValues(t, sdkerrors.ErrUnknownRequest.Codespace(), space, err)
require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), code, err)
unknownRouteTx = txTest{[]sdk.Msg{msgCounter{}, msgNoRoute{}}, 0, false, math.MaxUint64}
unknownRouteTx = txTest{[]sdk.Msg{&msgCounter{}, &msgNoRoute{}}, 0, false, math.MaxUint64}
_, result, err = app.SimDeliver(aminoTxEncoder(), unknownRouteTx)
require.Error(t, err)
require.Nil(t, result)
@ -1307,7 +1338,7 @@ func TestRunInvalidTransaction(t *testing.T) {
// Transaction with an unregistered message
{
tx := newTxCounter(0, 0)
tx.Msgs = append(tx.Msgs, msgNoDecode{})
tx.Msgs = append(tx.Msgs, &msgNoDecode{})
// new codec so we can encode the tx, but we shouldn't be able to decode
newCdc := codec.NewLegacyAmino()
@ -1336,9 +1367,16 @@ func TestTxGasLimits(t *testing.T) {
txHandlerOpt := func(bapp *baseapp.BaseApp) {
legacyRouter := middleware.NewLegacyRouter()
r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
count := msg.(msgCounter).Counter
count := msg.(*msgCounter).Counter
ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler")
return &sdk.Result{}, nil
any, err := codectypes.NewAnyWithValue(msg)
if err != nil {
return nil, err
}
return &sdk.Result{
MsgResponses: []*codectypes.Any{any},
}, nil
})
legacyRouter.AddRoute(r)
txHandler := testTxHandler(
@ -1415,9 +1453,17 @@ func TestMaxBlockGasLimits(t *testing.T) {
txHandlerOpt := func(bapp *baseapp.BaseApp) {
legacyRouter := middleware.NewLegacyRouter()
r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
count := msg.(msgCounter).Counter
count := msg.(*msgCounter).Counter
ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler")
return &sdk.Result{}, nil
any, err := codectypes.NewAnyWithValue(msg)
if err != nil {
return nil, err
}
return &sdk.Result{
MsgResponses: []*codectypes.Any{any},
}, nil
})
legacyRouter.AddRoute(r)
txHandler := testTxHandler(
@ -1595,7 +1641,7 @@ func TestGasConsumptionBadTx(t *testing.T) {
txHandlerOpt := func(bapp *baseapp.BaseApp) {
legacyRouter := middleware.NewLegacyRouter()
r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
count := msg.(msgCounter).Counter
count := msg.(*msgCounter).Counter
ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler")
return &sdk.Result{}, nil
})
@ -1651,7 +1697,14 @@ func TestQuery(t *testing.T) {
r := sdk.NewRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
store := ctx.KVStore(capKey1)
store.Set(key, value)
return &sdk.Result{}, nil
any, err := codectypes.NewAnyWithValue(msg)
if err != nil {
return nil, err
}
return &sdk.Result{
MsgResponses: []*codectypes.Any{any},
}, nil
})
legacyRouter.AddRoute(r)
txHandler := testTxHandler(

View File

@ -6,7 +6,6 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/tmhash"
)
@ -31,33 +30,33 @@ func CustomTxHandlerMiddleware(handler handlerFun) tx.Middleware {
}
// CheckTx implements tx.Handler.CheckTx method.
func (txh customTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
sdkCtx, err := txh.runHandler(ctx, tx, req.Tx, false)
func (txh customTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
sdkCtx, err := txh.runHandler(ctx, req.Tx, req.TxBytes, false)
if err != nil {
return abci.ResponseCheckTx{}, err
return tx.Response{}, tx.ResponseCheckTx{}, err
}
return txh.next.CheckTx(sdk.WrapSDKContext(sdkCtx), tx, req)
return txh.next.CheckTx(sdk.WrapSDKContext(sdkCtx), req, checkReq)
}
// DeliverTx implements tx.Handler.DeliverTx method.
func (txh customTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
sdkCtx, err := txh.runHandler(ctx, tx, req.Tx, false)
func (txh customTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
sdkCtx, err := txh.runHandler(ctx, req.Tx, req.TxBytes, false)
if err != nil {
return abci.ResponseDeliverTx{}, err
return tx.Response{}, err
}
return txh.next.DeliverTx(sdk.WrapSDKContext(sdkCtx), tx, req)
return txh.next.DeliverTx(sdk.WrapSDKContext(sdkCtx), req)
}
// SimulateTx implements tx.Handler.SimulateTx method.
func (txh customTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
sdkCtx, err := txh.runHandler(ctx, sdkTx, req.TxBytes, true)
func (txh customTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
sdkCtx, err := txh.runHandler(ctx, req.Tx, req.TxBytes, true)
if err != nil {
return tx.ResponseSimulateTx{}, err
return tx.Response{}, err
}
return txh.next.SimulateTx(sdk.WrapSDKContext(sdkCtx), sdkTx, req)
return txh.next.SimulateTx(sdk.WrapSDKContext(sdkCtx), req)
}
func (txh customTxHandler) runHandler(ctx context.Context, tx sdk.Tx, txBytes []byte, isSimulate bool) (sdk.Context, error) {

View File

@ -10,23 +10,28 @@ import (
)
// SimCheck defines a CheckTx helper function that used in tests and simulations.
func (app *BaseApp) SimCheck(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) {
func (app *BaseApp) SimCheck(txEncoder sdk.TxEncoder, sdkTx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) {
// CheckTx expects tx bytes as argument, so we encode the tx argument into
// bytes. Note that CheckTx will actually decode those bytes again. But since
// this helper is only used in tests/simulation, it's fine.
bz, err := txEncoder(tx)
bz, err := txEncoder(sdkTx)
if err != nil {
return sdk.GasInfo{}, nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "%s", err)
}
ctx := app.getContextForTx(runTxModeDeliver, bz)
res, err := app.txHandler.CheckTx(ctx, tx, abci.RequestCheckTx{Tx: bz, Type: abci.CheckTxType_New})
res, _, err := app.txHandler.CheckTx(ctx, tx.Request{Tx: sdkTx, TxBytes: bz}, tx.RequestCheckTx{Type: abci.CheckTxType_New})
gInfo := sdk.GasInfo{GasWanted: uint64(res.GasWanted), GasUsed: uint64(res.GasUsed)}
if err != nil {
return gInfo, nil, err
}
return gInfo, &sdk.Result{Data: res.Data, Log: res.Log, Events: res.Events}, nil
data, err := makeABCIData(res)
if err != nil {
return gInfo, nil, err
}
return gInfo, &sdk.Result{Data: data, Log: res.Log, Events: res.Events, MsgResponses: res.MsgResponses}, nil
}
// Simulate executes a tx in simulate mode to get result and gas info.
@ -37,31 +42,45 @@ func (app *BaseApp) Simulate(txBytes []byte) (sdk.GasInfo, *sdk.Result, error) {
}
ctx := app.getContextForTx(runTxModeSimulate, txBytes)
res, err := app.txHandler.SimulateTx(ctx, sdkTx, tx.RequestSimulateTx{TxBytes: txBytes})
res, err := app.txHandler.SimulateTx(ctx, tx.Request{Tx: sdkTx, TxBytes: txBytes})
gasInfo := sdk.GasInfo{
GasWanted: res.GasWanted,
GasUsed: res.GasUsed,
}
if err != nil {
return res.GasInfo, nil, err
return gasInfo, nil, err
}
return res.GasInfo, res.Result, nil
data, err := makeABCIData(res)
if err != nil {
return gasInfo, nil, err
}
return gasInfo, &sdk.Result{Data: data, Log: res.Log, Events: res.Events, MsgResponses: res.MsgResponses}, nil
}
// SimDeliver defines a DeliverTx helper function that used in tests and
// simulations.
func (app *BaseApp) SimDeliver(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) {
func (app *BaseApp) SimDeliver(txEncoder sdk.TxEncoder, sdkTx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) {
// See comment for Check().
bz, err := txEncoder(tx)
bz, err := txEncoder(sdkTx)
if err != nil {
return sdk.GasInfo{}, nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "%s", err)
}
ctx := app.getContextForTx(runTxModeDeliver, bz)
res, err := app.txHandler.DeliverTx(ctx, tx, abci.RequestDeliverTx{Tx: bz})
res, err := app.txHandler.DeliverTx(ctx, tx.Request{Tx: sdkTx, TxBytes: bz})
gInfo := sdk.GasInfo{GasWanted: uint64(res.GasWanted), GasUsed: uint64(res.GasUsed)}
if err != nil {
return gInfo, nil, err
}
return gInfo, &sdk.Result{Data: res.Data, Log: res.Log, Events: res.Events}, nil
data, err := makeABCIData(res)
if err != nil {
return gInfo, nil, err
}
return gInfo, &sdk.Result{Data: data, Log: res.Log, Events: res.Events, MsgResponses: res.MsgResponses}, nil
}
// Context with current {check, deliver}State of the app used by tests.

View File

@ -2318,9 +2318,12 @@ Result is the union of ResponseFormat and ResponseCheckTx.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `data` | [bytes](#bytes) | | Data is any data returned from message or handler execution. It MUST be length prefixed in order to separate data from multiple message executions. |
| `data` | [bytes](#bytes) | | **Deprecated.** Data is any data returned from message or handler execution. It MUST be length prefixed in order to separate data from multiple message executions. Deprecated. This field is still populated, but prefer msg_response instead because it also contains the Msg response typeURL. |
| `log` | [string](#string) | | Log contains the log information from message or handler execution. |
| `events` | [tendermint.abci.Event](#tendermint.abci.Event) | repeated | Events contains a slice of Event objects that were emitted during message or handler execution. |
| `msg_responses` | [google.protobuf.Any](#google.protobuf.Any) | repeated | msg_responses contains the Msg handler responses type packed in Anys.
Since: cosmos-sdk 0.45 |
@ -2390,7 +2393,10 @@ for each message.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | |
| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | **Deprecated.** data field is deprecated and not populated. |
| `msg_responses` | [google.protobuf.Any](#google.protobuf.Any) | repeated | msg_responses contains the Msg handler responses packed into Anys.
Since: cosmos-sdk 0.45 |

View File

@ -91,7 +91,9 @@ message Result {
// Data is any data returned from message or handler execution. It MUST be
// length prefixed in order to separate data from multiple message executions.
bytes data = 1;
// Deprecated. This field is still populated, but prefer msg_response instead
// because it also contains the Msg response typeURL.
bytes data = 1 [deprecated = true];
// Log contains the log information from message or handler execution.
string log = 2;
@ -99,6 +101,11 @@ message Result {
// Events contains a slice of Event objects that were emitted during message
// or handler execution.
repeated tendermint.abci.Event events = 3 [(gogoproto.nullable) = false];
// msg_responses contains the Msg handler responses type packed in Anys.
//
// Since: cosmos-sdk 0.45
repeated google.protobuf.Any msg_responses = 4;
}
// SimulationResponse defines the response generated when a transaction is
@ -111,6 +118,7 @@ message SimulationResponse {
// MsgData defines the data returned in a Result object during message
// execution.
message MsgData {
option deprecated = true;
option (gogoproto.stringer) = true;
string msg_type = 1;
@ -122,7 +130,13 @@ message MsgData {
message TxMsgData {
option (gogoproto.stringer) = true;
repeated MsgData data = 1;
// data field is deprecated and not populated.
repeated MsgData data = 1 [deprecated = true];
// msg_responses contains the Msg handler responses packed into Anys.
//
// Since: cosmos-sdk 0.45
repeated google.protobuf.Any msg_responses = 2;
}
// SearchTxsResult defines a structure for querying txs pageable

View File

@ -12,6 +12,7 @@ import (
bam "github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/simapp"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -74,7 +75,7 @@ func NewApp(rootDir string, logger log.Logger) (abci.Application, error) {
// them to the db
func KVStoreHandler(storeKey storetypes.StoreKey) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
dTx, ok := msg.(kvstoreTx)
dTx, ok := msg.(*kvstoreTx)
if !ok {
return nil, errors.New("KVStoreHandler should only receive kvstoreTx")
}
@ -86,8 +87,14 @@ func KVStoreHandler(storeKey storetypes.StoreKey) sdk.Handler {
store := ctx.KVStore(storeKey)
store.Set(key, value)
any, err := codectypes.NewAnyWithValue(msg)
if err != nil {
return nil, err
}
return &sdk.Result{
Log: fmt.Sprintf("set %s=%s", key, value),
Log: fmt.Sprintf("set %s=%s", key, value),
MsgResponses: []*codectypes.Any{any},
}, nil
}
}

View File

@ -21,13 +21,13 @@ type kvstoreTx struct {
}
// dummy implementation of proto.Message
func (msg kvstoreTx) Reset() {}
func (msg kvstoreTx) String() string { return "TODO" }
func (msg kvstoreTx) ProtoMessage() {}
func (msg *kvstoreTx) Reset() {}
func (msg *kvstoreTx) String() string { return "TODO" }
func (msg *kvstoreTx) ProtoMessage() {}
var _ sdk.Tx = kvstoreTx{}
var _ sdk.Msg = kvstoreTx{}
var _ middleware.GasTx = kvstoreTx{}
var _ sdk.Tx = &kvstoreTx{}
var _ sdk.Msg = &kvstoreTx{}
var _ middleware.GasTx = &kvstoreTx{}
func NewTx(key, value string) kvstoreTx {
bytes := fmt.Sprintf("%s=%s", key, value)
@ -46,7 +46,7 @@ func (tx kvstoreTx) Type() string {
return "kvstore_tx"
}
func (tx kvstoreTx) GetMsgs() []sdk.Msg {
func (tx *kvstoreTx) GetMsgs() []sdk.Msg {
return []sdk.Msg{tx}
}
@ -79,10 +79,10 @@ func decodeTx(txBytes []byte) (sdk.Tx, error) {
split := bytes.Split(txBytes, []byte("="))
if len(split) == 1 {
k := split[0]
tx = kvstoreTx{k, k, txBytes}
tx = &kvstoreTx{k, k, txBytes}
} else if len(split) == 2 {
k, v := split[0], split[1]
tx = kvstoreTx{k, v, txBytes}
tx = &kvstoreTx{k, v, txBytes}
} else {
return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "too many '='")
}

View File

@ -324,12 +324,18 @@ func (m *GasInfo) GetGasUsed() uint64 {
type Result struct {
// Data is any data returned from message or handler execution. It MUST be
// length prefixed in order to separate data from multiple message executions.
Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
// Deprecated. This field is still populated, but prefer msg_response instead
// because it also contains the Msg response typeURL.
Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` // Deprecated: Do not use.
// Log contains the log information from message or handler execution.
Log string `protobuf:"bytes,2,opt,name=log,proto3" json:"log,omitempty"`
// Events contains a slice of Event objects that were emitted during message
// or handler execution.
Events []types1.Event `protobuf:"bytes,3,rep,name=events,proto3" json:"events"`
// msg_responses contains the Msg handler responses type packed in Anys.
//
// Since: cosmos-sdk 0.45
MsgResponses []*types.Any `protobuf:"bytes,4,rep,name=msg_responses,json=msgResponses,proto3" json:"msg_responses,omitempty"`
}
func (m *Result) Reset() { *m = Result{} }
@ -412,6 +418,8 @@ func (m *SimulationResponse) GetResult() *Result {
// MsgData defines the data returned in a Result object during message
// execution.
//
// Deprecated: Do not use.
type MsgData struct {
MsgType string `protobuf:"bytes,1,opt,name=msg_type,json=msgType,proto3" json:"msg_type,omitempty"`
Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
@ -466,7 +474,12 @@ func (m *MsgData) GetData() []byte {
// TxMsgData defines a list of MsgData. A transaction will have a MsgData object
// for each message.
type TxMsgData struct {
Data []*MsgData `protobuf:"bytes,1,rep,name=data,proto3" json:"data,omitempty"`
// data field is deprecated and not populated.
Data []*MsgData `protobuf:"bytes,1,rep,name=data,proto3" json:"data,omitempty"` // Deprecated: Do not use.
// msg_responses contains the Msg handler responses packed into Anys.
//
// Since: cosmos-sdk 0.45
MsgResponses []*types.Any `protobuf:"bytes,2,rep,name=msg_responses,json=msgResponses,proto3" json:"msg_responses,omitempty"`
}
func (m *TxMsgData) Reset() { *m = TxMsgData{} }
@ -501,6 +514,7 @@ func (m *TxMsgData) XXX_DiscardUnknown() {
var xxx_messageInfo_TxMsgData proto.InternalMessageInfo
// Deprecated: Do not use.
func (m *TxMsgData) GetData() []*MsgData {
if m != nil {
return m.Data
@ -508,6 +522,13 @@ func (m *TxMsgData) GetData() []*MsgData {
return nil
}
func (m *TxMsgData) GetMsgResponses() []*types.Any {
if m != nil {
return m.MsgResponses
}
return nil
}
// SearchTxsResult defines a structure for querying txs pageable
type SearchTxsResult struct {
// Count of all txs
@ -616,63 +637,65 @@ func init() {
}
var fileDescriptor_4e37629bc7eb0df8 = []byte{
// 881 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0xbd, 0x8f, 0x1b, 0x45,
0x14, 0xf7, 0xda, 0xce, 0xfa, 0xf6, 0xf9, 0x2e, 0x87, 0x46, 0xa7, 0x64, 0x2f, 0x01, 0xdb, 0x38,
0x41, 0x72, 0x93, 0x35, 0xb9, 0x04, 0x84, 0x28, 0x10, 0xf1, 0xf1, 0x91, 0x93, 0x12, 0x8a, 0x39,
0x47, 0x48, 0x34, 0xd6, 0xd8, 0x9e, 0x8c, 0x97, 0x78, 0x77, 0xac, 0x9d, 0xd9, 0xbb, 0xbd, 0x8e,
0x92, 0x0a, 0x51, 0x51, 0x50, 0x51, 0xf3, 0x97, 0xa4, 0xa0, 0xb8, 0x32, 0x05, 0x32, 0x70, 0xd7,
0xe5, 0xaf, 0x40, 0xf3, 0x66, 0xfc, 0x71, 0x44, 0x8e, 0x44, 0xe5, 0xf7, 0xf1, 0x9b, 0x37, 0xef,
0xf7, 0x7b, 0xcf, 0xb3, 0x70, 0x67, 0x24, 0x55, 0x22, 0x55, 0x77, 0xc8, 0x14, 0xef, 0xb2, 0xe1,
0x28, 0xee, 0x9e, 0xdc, 0x1f, 0x72, 0xcd, 0xee, 0xa3, 0x13, 0xcd, 0x32, 0xa9, 0x25, 0x09, 0x2d,
0x28, 0x32, 0xa0, 0x08, 0xe3, 0x0e, 0x74, 0x6b, 0x4f, 0x48, 0x21, 0x11, 0xd4, 0x35, 0x96, 0xc5,
0xdf, 0xba, 0xad, 0x79, 0x3a, 0xe6, 0x59, 0x12, 0xa7, 0xda, 0xd6, 0xd4, 0x67, 0x33, 0xae, 0x5c,
0x72, 0x5f, 0x48, 0x29, 0xa6, 0xbc, 0x8b, 0xde, 0x30, 0x7f, 0xde, 0x65, 0xe9, 0x99, 0x4d, 0xb5,
0xff, 0xa8, 0x00, 0xf4, 0x0b, 0xca, 0xd5, 0x4c, 0xa6, 0x8a, 0x93, 0x1b, 0xe0, 0x4f, 0x78, 0x2c,
0x26, 0x3a, 0xf4, 0x5a, 0x5e, 0xa7, 0x42, 0x9d, 0x47, 0xda, 0xe0, 0xeb, 0x62, 0xc2, 0xd4, 0x24,
0x2c, 0xb7, 0xbc, 0x4e, 0xd0, 0x83, 0x8b, 0x79, 0xd3, 0xef, 0x17, 0x8f, 0x99, 0x9a, 0x50, 0x97,
0x21, 0xef, 0x42, 0x30, 0x92, 0x63, 0xae, 0x66, 0x6c, 0xc4, 0xc3, 0x8a, 0x81, 0xd1, 0x55, 0x80,
0x10, 0xa8, 0x1a, 0x27, 0xac, 0xb6, 0xbc, 0xce, 0x0e, 0x45, 0xdb, 0xc4, 0xc6, 0x4c, 0xb3, 0xf0,
0x1a, 0x82, 0xd1, 0x26, 0x37, 0xa1, 0x96, 0xb1, 0xd3, 0xc1, 0x54, 0x8a, 0xd0, 0xc7, 0xb0, 0x9f,
0xb1, 0xd3, 0x27, 0x52, 0x90, 0x67, 0x50, 0x9d, 0x4a, 0xa1, 0xc2, 0x5a, 0xab, 0xd2, 0xa9, 0x1f,
0x74, 0xa2, 0x4d, 0x02, 0x45, 0x8f, 0x7a, 0x87, 0x47, 0x4f, 0xb9, 0x52, 0x4c, 0xf0, 0x27, 0x52,
0xf4, 0x6e, 0xbe, 0x9c, 0x37, 0x4b, 0xbf, 0xff, 0xd5, 0xdc, 0xbd, 0x1a, 0x57, 0x14, 0xcb, 0x99,
0x1e, 0xe2, 0xf4, 0xb9, 0x0c, 0xb7, 0x6c, 0x0f, 0xc6, 0x26, 0xef, 0x01, 0x08, 0xa6, 0x06, 0xa7,
0x2c, 0xd5, 0x7c, 0x1c, 0x06, 0xa8, 0x44, 0x20, 0x98, 0xfa, 0x16, 0x03, 0x64, 0x1f, 0xb6, 0x4c,
0x3a, 0x57, 0x7c, 0x1c, 0x02, 0x26, 0x6b, 0x82, 0xa9, 0x67, 0x8a, 0x8f, 0xc9, 0x5d, 0x28, 0xeb,
0x22, 0xac, 0xb7, 0xbc, 0x4e, 0xfd, 0x60, 0x2f, 0xb2, 0xb2, 0x47, 0x0b, 0xd9, 0xa3, 0x47, 0xe9,
0x19, 0x2d, 0xeb, 0xc2, 0x28, 0xa5, 0xe3, 0x84, 0x2b, 0xcd, 0x92, 0x59, 0xb8, 0x6d, 0x95, 0x5a,
0x06, 0xc8, 0x43, 0xf0, 0xf9, 0x09, 0x4f, 0xb5, 0x0a, 0x77, 0x90, 0xea, 0x8d, 0x68, 0x35, 0x5b,
0xcb, 0xf4, 0x4b, 0x93, 0xee, 0x55, 0x0d, 0x31, 0xea, 0xb0, 0x9f, 0x56, 0x7f, 0xfc, 0xad, 0x59,
0x6a, 0xff, 0xea, 0xc1, 0xf5, 0xab, 0x3c, 0xc9, 0x6d, 0x08, 0x12, 0x25, 0x06, 0x71, 0x3a, 0xe6,
0x05, 0x4e, 0x75, 0x87, 0x6e, 0x25, 0x4a, 0x1c, 0x19, 0x9f, 0xbc, 0x03, 0x15, 0xa3, 0x34, 0x0e,
0x95, 0x1a, 0x93, 0x1c, 0x2f, 0x6f, 0xaf, 0xe0, 0xed, 0x1f, 0x6c, 0x16, 0xfa, 0x58, 0x67, 0x71,
0x2a, 0x6c, 0x33, 0x7b, 0x4e, 0xe5, 0xed, 0xb5, 0xa0, 0x5a, 0x35, 0xf7, 0xc3, 0x9f, 0x2d, 0xaf,
0x9d, 0x41, 0x7d, 0x2d, 0x6b, 0x94, 0x37, 0x4b, 0x8a, 0x3d, 0x05, 0x14, 0x6d, 0x72, 0x04, 0xc0,
0xb4, 0xce, 0xe2, 0x61, 0xae, 0xb9, 0x0a, 0xcb, 0xd8, 0xc1, 0x9d, 0xb7, 0x8c, 0x7a, 0x81, 0x75,
0x62, 0xac, 0x1d, 0x76, 0x77, 0x3e, 0x80, 0x60, 0x09, 0x32, 0x6c, 0x5f, 0xf0, 0x33, 0x77, 0xa1,
0x31, 0xc9, 0x1e, 0x5c, 0x3b, 0x61, 0xd3, 0x9c, 0x3b, 0x05, 0xac, 0xd3, 0x3e, 0x84, 0xda, 0xd7,
0x4c, 0x1d, 0xbd, 0xb9, 0x0a, 0xe6, 0x64, 0x75, 0xd3, 0x2a, 0x94, 0x31, 0xb9, 0x58, 0x85, 0xf6,
0xf7, 0xe0, 0x53, 0xae, 0xf2, 0xa9, 0x5e, 0xae, 0xb9, 0x39, 0xbd, 0xed, 0xd6, 0xfc, 0x4d, 0xe1,
0x1f, 0xfe, 0x47, 0xf8, 0xff, 0x33, 0xf6, 0x5f, 0x3c, 0x20, 0xc7, 0x71, 0x92, 0x4f, 0x99, 0x8e,
0x65, 0xba, 0xfc, 0x37, 0x7f, 0x65, 0xbb, 0xc3, 0xfd, 0xf6, 0x70, 0x27, 0xdf, 0xdf, 0xac, 0xa5,
0x63, 0xdc, 0xdb, 0x32, 0xf5, 0xcf, 0xe7, 0x4d, 0x0f, 0xa9, 0xa0, 0x08, 0x9f, 0x80, 0x9f, 0x21,
0x15, 0xec, 0xb7, 0x7e, 0xd0, 0xda, 0x5c, 0xc5, 0x52, 0xa6, 0x0e, 0xdf, 0xfe, 0x0c, 0x6a, 0x4f,
0x95, 0xf8, 0xc2, 0x30, 0xde, 0x07, 0xb3, 0x76, 0x83, 0xb5, 0x91, 0xd7, 0x12, 0x25, 0xfa, 0x66,
0xea, 0x0b, 0x81, 0xca, 0x2b, 0x81, 0xdc, 0xf8, 0x1e, 0x43, 0xd0, 0x2f, 0x16, 0x15, 0x3e, 0x5a,
0xea, 0x58, 0x79, 0x3b, 0x15, 0x77, 0xe0, 0x4a, 0xa5, 0x9f, 0xca, 0xb0, 0x7b, 0xcc, 0x59, 0x36,
0x9a, 0xf4, 0x0b, 0xe5, 0x06, 0xf3, 0x21, 0xd4, 0xb5, 0xd4, 0x6c, 0x3a, 0x18, 0xc9, 0x3c, 0xb5,
0x4f, 0x5e, 0xb5, 0xb7, 0xfb, 0x7a, 0xde, 0x5c, 0x0f, 0x53, 0x40, 0xe7, 0xd0, 0xd8, 0x66, 0x5f,
0x2c, 0xd6, 0x0e, 0xdb, 0x3a, 0xa6, 0xce, 0x8c, 0x09, 0x3e, 0x48, 0xf3, 0x64, 0xc8, 0x33, 0x7c,
0xfb, 0x5c, 0x9d, 0xb5, 0x30, 0x05, 0xe3, 0x7c, 0x83, 0x36, 0xb9, 0x07, 0xe8, 0x0d, 0xb0, 0x34,
0xbe, 0x89, 0xd5, 0xde, 0xf5, 0xd7, 0xf3, 0xe6, 0x5a, 0x94, 0x06, 0xc6, 0xee, 0x1b, 0xd3, 0x5c,
0x3b, 0x8d, 0x93, 0x58, 0xe3, 0x4b, 0x59, 0xa5, 0xd6, 0x21, 0x1f, 0x43, 0x45, 0x17, 0x2a, 0xf4,
0x51, 0x8e, 0xbb, 0x9b, 0xe5, 0x58, 0xbd, 0xef, 0xd4, 0x1c, 0xb0, 0x82, 0xf4, 0x3e, 0x7f, 0xf5,
0x4f, 0xa3, 0xf4, 0xf2, 0xa2, 0xe1, 0x9d, 0x5f, 0x34, 0xbc, 0xbf, 0x2f, 0x1a, 0xde, 0xcf, 0x97,
0x8d, 0xd2, 0xf9, 0x65, 0xa3, 0xf4, 0xea, 0xb2, 0x51, 0xfa, 0xae, 0x2d, 0x62, 0x3d, 0xc9, 0x87,
0xd1, 0x48, 0x26, 0x5d, 0xf7, 0xbd, 0xb2, 0x3f, 0xf7, 0xd4, 0xf8, 0x85, 0xfd, 0xb8, 0x0c, 0x7d,
0x7c, 0xd8, 0x1e, 0xfc, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xed, 0x2a, 0x80, 0xd1, 0x06, 0x00,
0x00,
// 924 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0x3f, 0x6f, 0x1b, 0x37,
0x14, 0xd7, 0x49, 0x97, 0x93, 0xf5, 0x24, 0xc7, 0x05, 0x61, 0x38, 0x74, 0xd2, 0x4a, 0xaa, 0x92,
0x02, 0x5a, 0x72, 0x6a, 0x9c, 0xa0, 0x68, 0x32, 0x25, 0x72, 0xff, 0x19, 0x48, 0x3a, 0x9c, 0x15,
0x14, 0xe8, 0x22, 0x50, 0x12, 0x43, 0x1d, 0xa2, 0x3b, 0x0a, 0x47, 0xca, 0x3e, 0x6f, 0xdd, 0xda,
0xa9, 0xe8, 0xd4, 0xa1, 0x53, 0xd7, 0xf6, 0x93, 0x64, 0xe8, 0xe0, 0x31, 0x43, 0xa1, 0xb6, 0xf6,
0x96, 0x4f, 0x51, 0xf0, 0x91, 0x92, 0x95, 0xba, 0x0a, 0x3c, 0xdd, 0xfb, 0xc7, 0xc7, 0xf7, 0x7e,
0xef, 0x77, 0x8f, 0x70, 0x7b, 0x28, 0x55, 0x22, 0x55, 0x67, 0xc0, 0x14, 0xef, 0xb0, 0xc1, 0x30,
0xee, 0x1c, 0xdd, 0x1b, 0x70, 0xcd, 0xee, 0xa1, 0x12, 0x4e, 0x33, 0xa9, 0x25, 0xa1, 0x36, 0x28,
0x34, 0x41, 0x21, 0xda, 0x5d, 0xd0, 0xcd, 0x6d, 0x21, 0x85, 0xc4, 0xa0, 0x8e, 0x91, 0x6c, 0xfc,
0xcd, 0x5b, 0x9a, 0xa7, 0x23, 0x9e, 0x25, 0x71, 0xaa, 0x6d, 0x4e, 0x7d, 0x32, 0xe5, 0xca, 0x39,
0x77, 0x85, 0x94, 0x62, 0xc2, 0x3b, 0xa8, 0x0d, 0x66, 0x2f, 0x3a, 0x2c, 0x3d, 0xb1, 0xae, 0xd6,
0x1f, 0x25, 0x80, 0x5e, 0x1e, 0x71, 0x35, 0x95, 0xa9, 0xe2, 0x64, 0x07, 0x82, 0x31, 0x8f, 0xc5,
0x58, 0x53, 0xaf, 0xe9, 0xb5, 0x4b, 0x91, 0xd3, 0x48, 0x0b, 0x02, 0x9d, 0x8f, 0x99, 0x1a, 0xd3,
0x62, 0xd3, 0x6b, 0x57, 0xba, 0x70, 0x36, 0x6f, 0x04, 0xbd, 0xfc, 0x2b, 0xa6, 0xc6, 0x91, 0xf3,
0x90, 0xf7, 0xa1, 0x32, 0x94, 0x23, 0xae, 0xa6, 0x6c, 0xc8, 0x69, 0xc9, 0x84, 0x45, 0x17, 0x06,
0x42, 0xc0, 0x37, 0x0a, 0xf5, 0x9b, 0x5e, 0x7b, 0x33, 0x42, 0xd9, 0xd8, 0x46, 0x4c, 0x33, 0x7a,
0x0d, 0x83, 0x51, 0x26, 0x37, 0xa0, 0x9c, 0xb1, 0xe3, 0xfe, 0x44, 0x0a, 0x1a, 0xa0, 0x39, 0xc8,
0xd8, 0xf1, 0x53, 0x29, 0xc8, 0x73, 0xf0, 0x27, 0x52, 0x28, 0x5a, 0x6e, 0x96, 0xda, 0xd5, 0xbd,
0x76, 0xb8, 0x0e, 0xa0, 0xf0, 0x49, 0x77, 0xff, 0xe0, 0x19, 0x57, 0x8a, 0x09, 0xfe, 0x54, 0x8a,
0xee, 0x8d, 0x57, 0xf3, 0x46, 0xe1, 0xf7, 0xbf, 0x1a, 0x5b, 0x6f, 0xdb, 0x55, 0x84, 0xe9, 0x4c,
0x0d, 0x71, 0xfa, 0x42, 0xd2, 0x0d, 0x5b, 0x83, 0x91, 0xc9, 0x07, 0x00, 0x82, 0xa9, 0xfe, 0x31,
0x4b, 0x35, 0x1f, 0xd1, 0x0a, 0x22, 0x51, 0x11, 0x4c, 0x7d, 0x83, 0x06, 0xb2, 0x0b, 0x1b, 0xc6,
0x3d, 0x53, 0x7c, 0x44, 0x01, 0x9d, 0x65, 0xc1, 0xd4, 0x73, 0xc5, 0x47, 0xe4, 0x0e, 0x14, 0x75,
0x4e, 0xab, 0x4d, 0xaf, 0x5d, 0xdd, 0xdb, 0x0e, 0x2d, 0xec, 0xe1, 0x02, 0xf6, 0xf0, 0x49, 0x7a,
0x12, 0x15, 0x75, 0x6e, 0x90, 0xd2, 0x71, 0xc2, 0x95, 0x66, 0xc9, 0x94, 0xd6, 0x2c, 0x52, 0x4b,
0x03, 0x79, 0x00, 0x01, 0x3f, 0xe2, 0xa9, 0x56, 0x74, 0x13, 0x5b, 0xdd, 0x09, 0x2f, 0x66, 0x6b,
0x3b, 0xfd, 0xdc, 0xb8, 0xbb, 0xbe, 0x69, 0x2c, 0x72, 0xb1, 0x8f, 0xfc, 0x1f, 0x7e, 0x6d, 0x14,
0x5a, 0xbf, 0x78, 0x70, 0xfd, 0xed, 0x3e, 0xc9, 0x2d, 0xa8, 0x24, 0x4a, 0xf4, 0xe3, 0x74, 0xc4,
0x73, 0x9c, 0xea, 0x66, 0xb4, 0x91, 0x28, 0x71, 0x60, 0x74, 0xf2, 0x1e, 0x94, 0x0c, 0xd2, 0x38,
0xd4, 0xc8, 0x88, 0xe4, 0x70, 0x79, 0x7b, 0x09, 0x6f, 0xff, 0x68, 0x3d, 0xd0, 0x87, 0x3a, 0x8b,
0x53, 0x61, 0x8b, 0xd9, 0x76, 0x28, 0xd7, 0x56, 0x8c, 0xea, 0xa2, 0xb8, 0xef, 0xfe, 0x6c, 0x7a,
0xad, 0x0c, 0xaa, 0x2b, 0x5e, 0x83, 0xbc, 0x21, 0x29, 0xd6, 0x54, 0x89, 0x50, 0x26, 0x07, 0x00,
0x4c, 0xeb, 0x2c, 0x1e, 0xcc, 0x34, 0x57, 0xb4, 0x88, 0x15, 0xdc, 0x7e, 0xc7, 0xa8, 0x17, 0xb1,
0x0e, 0x8c, 0x95, 0xc3, 0xee, 0xce, 0xfb, 0x50, 0x59, 0x06, 0x99, 0x6e, 0x5f, 0xf2, 0x13, 0x77,
0xa1, 0x11, 0xc9, 0x36, 0x5c, 0x3b, 0x62, 0x93, 0x19, 0x77, 0x08, 0x58, 0xa5, 0xb5, 0x0f, 0xe5,
0x2f, 0x99, 0x3a, 0xb8, 0x4c, 0x05, 0x73, 0xd2, 0x5f, 0x47, 0x85, 0x22, 0x3a, 0x17, 0x54, 0x68,
0xfd, 0xe6, 0x41, 0x10, 0x71, 0x35, 0x9b, 0x68, 0xb2, 0xe3, 0x78, 0x6e, 0x8e, 0xd7, 0xba, 0x45,
0xea, 0x39, 0xae, 0x5f, 0x46, 0xff, 0xc1, 0x7f, 0xd0, 0xbf, 0xd2, 0xec, 0xc9, 0x43, 0xd8, 0x34,
0x23, 0xce, 0xdc, 0x5f, 0xac, 0xa8, 0x8f, 0x87, 0xff, 0x9f, 0x80, 0xb5, 0x44, 0x89, 0xc5, 0xff,
0xbe, 0xa0, 0xcd, 0xcf, 0x1e, 0x90, 0xc3, 0x38, 0x99, 0x4d, 0x98, 0x8e, 0x65, 0xba, 0xdc, 0x06,
0x5f, 0xd8, 0xee, 0xf0, 0xff, 0xf0, 0x90, 0xd3, 0x1f, 0xae, 0x9f, 0x85, 0x43, 0xac, 0xbb, 0x61,
0x4a, 0x3b, 0x9d, 0x37, 0x3c, 0x84, 0x02, 0x41, 0xfc, 0x14, 0x82, 0x0c, 0x91, 0xc0, 0x56, 0xab,
0x7b, 0xcd, 0xf5, 0x59, 0x2c, 0x62, 0x91, 0x8b, 0x6f, 0x3d, 0x86, 0xf2, 0x33, 0x25, 0x3e, 0x33,
0x60, 0xed, 0x82, 0xa1, 0x6d, 0x7f, 0x85, 0x32, 0xe5, 0x44, 0x89, 0x9e, 0x61, 0xcd, 0x62, 0x8f,
0x98, 0xec, 0x35, 0x8b, 0xed, 0xa3, 0xc0, 0x8c, 0x9f, 0x7a, 0xad, 0xef, 0x3d, 0xa8, 0xf4, 0xf2,
0x45, 0x92, 0x87, 0xcb, 0x49, 0x94, 0xde, 0xdd, 0x8d, 0x3b, 0xb0, 0x32, 0xac, 0x4b, 0x20, 0x17,
0xaf, 0x0e, 0x32, 0x52, 0xf1, 0xc7, 0x22, 0x6c, 0x1d, 0x72, 0x96, 0x0d, 0xc7, 0xbd, 0x5c, 0x39,
0x66, 0x7c, 0x0c, 0x55, 0x2d, 0x35, 0x9b, 0xf4, 0x87, 0x72, 0x96, 0xda, 0xa5, 0xeb, 0x77, 0xb7,
0xde, 0xcc, 0x1b, 0xab, 0xe6, 0x08, 0x50, 0xd9, 0x37, 0xb2, 0x61, 0xac, 0x8d, 0xb5, 0x74, 0xb3,
0x8a, 0xc9, 0x33, 0x65, 0x82, 0xf7, 0xd3, 0x59, 0x32, 0xe0, 0x19, 0x6e, 0x5f, 0x97, 0x67, 0xc5,
0x1c, 0x81, 0x51, 0xbe, 0x46, 0x99, 0xdc, 0x05, 0xd4, 0xfa, 0x98, 0x1a, 0xb7, 0xb2, 0xdf, 0xbd,
0xfe, 0x66, 0xde, 0x58, 0xb1, 0x46, 0x15, 0x23, 0xf7, 0x8c, 0x68, 0xae, 0x9d, 0xc4, 0x49, 0xac,
0x71, 0x57, 0xfb, 0x91, 0x55, 0xc8, 0x27, 0x50, 0xd2, 0xb9, 0xa2, 0x01, 0x22, 0x71, 0x67, 0x3d,
0x9a, 0x17, 0x2f, 0x4c, 0x64, 0x0e, 0x58, 0x40, 0xba, 0x8f, 0x5f, 0xff, 0x53, 0x2f, 0xbc, 0x3a,
0xab, 0x7b, 0xa7, 0x67, 0x75, 0xef, 0xef, 0xb3, 0xba, 0xf7, 0xd3, 0x79, 0xbd, 0x70, 0x7a, 0x5e,
0x2f, 0xbc, 0x3e, 0xaf, 0x17, 0xbe, 0x6d, 0x89, 0x58, 0x8f, 0x67, 0x83, 0x70, 0x28, 0x93, 0x8e,
0x7b, 0x31, 0xed, 0xe7, 0xae, 0x1a, 0xbd, 0xb4, 0xcf, 0xdb, 0x20, 0x40, 0xd0, 0xef, 0xff, 0x1b,
0x00, 0x00, 0xff, 0xff, 0x41, 0x3c, 0xca, 0x00, 0x53, 0x07, 0x00, 0x00,
}
func (m *TxResponse) Marshal() (dAtA []byte, err error) {
@ -983,6 +1006,20 @@ func (m *Result) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if len(m.MsgResponses) > 0 {
for iNdEx := len(m.MsgResponses) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.MsgResponses[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintAbci(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x22
}
}
if len(m.Events) > 0 {
for iNdEx := len(m.Events) - 1; iNdEx >= 0; iNdEx-- {
{
@ -1116,6 +1153,20 @@ func (m *TxMsgData) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if len(m.MsgResponses) > 0 {
for iNdEx := len(m.MsgResponses) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.MsgResponses[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintAbci(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
}
}
if len(m.Data) > 0 {
for iNdEx := len(m.Data) - 1; iNdEx >= 0; iNdEx-- {
{
@ -1360,6 +1411,12 @@ func (m *Result) Size() (n int) {
n += 1 + l + sovAbci(uint64(l))
}
}
if len(m.MsgResponses) > 0 {
for _, e := range m.MsgResponses {
l = e.Size()
n += 1 + l + sovAbci(uint64(l))
}
}
return n
}
@ -1407,6 +1464,12 @@ func (m *TxMsgData) Size() (n int) {
n += 1 + l + sovAbci(uint64(l))
}
}
if len(m.MsgResponses) > 0 {
for _, e := range m.MsgResponses {
l = e.Size()
n += 1 + l + sovAbci(uint64(l))
}
}
return n
}
@ -1499,8 +1562,14 @@ func (this *TxMsgData) String() string {
repeatedStringForData += strings.Replace(f.String(), "MsgData", "MsgData", 1) + ","
}
repeatedStringForData += "}"
repeatedStringForMsgResponses := "[]*Any{"
for _, f := range this.MsgResponses {
repeatedStringForMsgResponses += strings.Replace(fmt.Sprintf("%v", f), "Any", "types.Any", 1) + ","
}
repeatedStringForMsgResponses += "}"
s := strings.Join([]string{`&TxMsgData{`,
`Data:` + repeatedStringForData + `,`,
`MsgResponses:` + repeatedStringForMsgResponses + `,`,
`}`,
}, "")
return s
@ -2537,6 +2606,40 @@ func (m *Result) Unmarshal(dAtA []byte) error {
return err
}
iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field MsgResponses", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAbci
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthAbci
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthAbci
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.MsgResponses = append(m.MsgResponses, &types.Any{})
if err := m.MsgResponses[len(m.MsgResponses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipAbci(dAtA[iNdEx:])
@ -2856,6 +2959,40 @@ func (m *TxMsgData) Unmarshal(dAtA []byte) error {
return err
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field MsgResponses", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAbci
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthAbci
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthAbci
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.MsgResponses = append(m.MsgResponses, &types.Any{})
if err := m.MsgResponses[len(m.MsgResponses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipAbci(dAtA[iNdEx:])

View File

@ -1,44 +1,73 @@
package msgservice
import (
"context"
"bytes"
"compress/gzip"
"fmt"
"io/ioutil"
"reflect"
"github.com/gogo/protobuf/proto"
"google.golang.org/grpc"
proto2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protodesc"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/types/descriptorpb"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx"
)
// RegisterMsgServiceDesc registers all type_urls from Msg services described
// in `sd` into the registry.
func RegisterMsgServiceDesc(registry codectypes.InterfaceRegistry, sd *grpc.ServiceDesc) {
// Adds a top-level type_url based on the Msg service name.
for _, method := range sd.Methods {
fqMethod := fmt.Sprintf("/%s/%s", sd.ServiceName, method.MethodName)
methodHandler := method.Handler
fdBytesUnzipped := unzip(proto.FileDescriptor(sd.Metadata.(string)))
if fdBytesUnzipped == nil {
panic(fmt.Errorf("error unzipping file description for MsgService %s", sd.ServiceName))
}
// NOTE: This is how we pull the concrete request type for each handler for registering in the InterfaceRegistry.
// This approach is maybe a bit hacky, but less hacky than reflecting on the handler object itself.
// We use a no-op interceptor to avoid actually calling into the handler itself.
_, _ = methodHandler(nil, context.Background(), func(i interface{}) error {
msg, ok := i.(sdk.Msg)
if !ok {
// We panic here because there is no other alternative and the app cannot be initialized correctly
// this should only happen if there is a problem with code generation in which case the app won't
// work correctly anyway.
panic(fmt.Errorf("can't register request type %T for service method %s", i, fqMethod))
}
fdRaw := &descriptorpb.FileDescriptorProto{}
err := proto2.Unmarshal(fdBytesUnzipped, fdRaw)
if err != nil {
panic(err)
}
registry.RegisterImplementations((*sdk.Msg)(nil), msg)
fd, err := protodesc.FileOptions{
AllowUnresolvable: true,
}.New(fdRaw, nil)
if err != nil {
panic(err)
}
return nil
}, noopInterceptor)
prefSd := fd.Services().ByName(protoreflect.FullName(sd.ServiceName).Name())
for i := 0; i < prefSd.Methods().Len(); i++ {
md := prefSd.Methods().Get(i)
requestDesc := md.Input()
responseDesc := md.Output()
reqTyp := proto.MessageType(string(requestDesc.FullName()))
respTyp := proto.MessageType(string(responseDesc.FullName()))
// Register sdk.Msg and sdk.MsgResponse to the registry.
registry.RegisterImplementations((*sdk.Msg)(nil), reflect.New(reqTyp).Elem().Interface().(proto.Message))
registry.RegisterImplementations((*tx.MsgResponse)(nil), reflect.New(respTyp).Elem().Interface().(proto.Message))
}
}
// gRPC NOOP interceptor
func noopInterceptor(_ context.Context, _ interface{}, _ *grpc.UnaryServerInfo, _ grpc.UnaryHandler) (interface{}, error) {
return nil, nil
func unzip(b []byte) []byte {
if b == nil {
return nil
}
r, err := gzip.NewReader(bytes.NewReader(b))
if err != nil {
panic(err)
}
unzipped, err := ioutil.ReadAll(r)
if err != nil {
panic(err)
}
return unzipped
}

View File

@ -238,6 +238,11 @@ func WrapServiceResult(ctx Context, res proto.Message, err error) (*Result, erro
return nil, err
}
any, err := codectypes.NewAnyWithValue(res)
if err != nil {
return nil, err
}
var data []byte
if res != nil {
data, err = proto.Marshal(res)
@ -252,7 +257,8 @@ func WrapServiceResult(ctx Context, res proto.Message, err error) (*Result, erro
}
return &Result{
Data: data,
Events: events,
Data: data,
Events: events,
MsgResponses: []*codectypes.Any{any},
}, nil
}

View File

@ -229,14 +229,14 @@ func TestWrapServiceResult(t *testing.T) {
require.Nil(t, res)
require.NotNil(t, err)
res, err = sdk.WrapServiceResult(ctx, nil, nil)
res, err = sdk.WrapServiceResult(ctx, &testdata.Dog{}, nil)
require.NotNil(t, res)
require.Nil(t, err)
require.Empty(t, res.Events)
ctx = ctx.WithEventManager(sdk.NewEventManager())
ctx.EventManager().EmitEvent(sdk.NewEvent("test"))
res, err = sdk.WrapServiceResult(ctx, nil, nil)
res, err = sdk.WrapServiceResult(ctx, &testdata.Dog{}, nil)
require.NotNil(t, res)
require.Nil(t, err)
require.Len(t, res.Events, 1)

View File

@ -3,6 +3,7 @@ package tx
import (
context "context"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -21,12 +22,42 @@ type ResponseSimulateTx struct {
Result *sdk.Result
}
// Response is the tx response type used in middlewares.
type Response struct {
GasWanted uint64
GasUsed uint64
// MsgResponses is an array containing each Msg service handler's response
// type, packed in an Any. This will get proto-serialized into the `Data` field
// in the ABCI Check/DeliverTx responses.
MsgResponses []*codectypes.Any
Log string
Events []abci.Event
}
// Request is the tx request type used in middlewares.
type Request struct {
Tx sdk.Tx
TxBytes []byte
}
// RequestCheckTx is the additional request type used in middlewares CheckTx
// method.
type RequestCheckTx struct {
Type abci.CheckTxType
}
// RequestCheckTx is the additional response type used in middlewares CheckTx
// method.
type ResponseCheckTx struct {
Priority int64
}
// TxHandler defines the baseapp's CheckTx, DeliverTx and Simulate respective
// handlers. It is designed as a middleware stack.
type Handler interface {
CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error)
DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error)
SimulateTx(ctx context.Context, tx sdk.Tx, req RequestSimulateTx) (ResponseSimulateTx, error)
CheckTx(ctx context.Context, req Request, checkReq RequestCheckTx) (Response, ResponseCheckTx, error)
DeliverTx(ctx context.Context, req Request) (Response, error)
SimulateTx(ctx context.Context, req Request) (Response, error)
}
// TxMiddleware defines one layer of the TxHandler middleware stack.

View File

@ -7,6 +7,15 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
const (
msgResponseInterfaceProtoName = "cosmos.tx.v1beta1.MsgResponse"
)
// MsgResponse is the interface all Msg server handlers' response types need to
// implement. It's the interface that's representing all Msg responses packed
// in Anys.
type MsgResponse interface{}
// SetMsgs takes a slice of sdk.Msg's and turn them into Any's.
func SetMsgs(msgs []sdk.Msg) ([]*types.Any, error) {
anys := make([]*types.Any, len(msgs))

View File

@ -192,8 +192,12 @@ func (m *SignerInfo) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
return unpacker.UnpackAny(m.PublicKey, new(cryptotypes.PubKey))
}
// RegisterInterfaces registers the sdk.Tx interface.
// RegisterInterfaces registers the sdk.Tx and MsgResponse interfaces.
// Note: the registration of sdk.Msg is done in sdk.RegisterInterfaces, but it
// could be moved inside this function.
func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
registry.RegisterInterface(msgResponseInterfaceProtoName, (*MsgResponse)(nil))
registry.RegisterInterface("cosmos.tx.v1beta1.Tx", (*sdk.Tx)(nil))
registry.RegisterImplementations((*sdk.Tx)(nil), &Tx{})
}

View File

@ -49,47 +49,47 @@ func validateBasicTxMsgs(msgs []sdk.Msg) error {
}
// CheckTx implements tx.Handler.CheckTx.
func (txh validateBasicTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
func (txh validateBasicTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
// no need to validate basic on recheck tx, call next middleware
if req.Type == abci.CheckTxType_Recheck {
return txh.next.CheckTx(ctx, tx, req)
if checkReq.Type == abci.CheckTxType_Recheck {
return txh.next.CheckTx(ctx, req, checkReq)
}
if err := validateBasicTxMsgs(tx.GetMsgs()); err != nil {
return abci.ResponseCheckTx{}, err
if err := validateBasicTxMsgs(req.Tx.GetMsgs()); err != nil {
return tx.Response{}, tx.ResponseCheckTx{}, err
}
if err := tx.ValidateBasic(); err != nil {
return abci.ResponseCheckTx{}, err
if err := req.Tx.ValidateBasic(); err != nil {
return tx.Response{}, tx.ResponseCheckTx{}, err
}
return txh.next.CheckTx(ctx, tx, req)
return txh.next.CheckTx(ctx, req, checkReq)
}
// DeliverTx implements tx.Handler.DeliverTx.
func (txh validateBasicTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
if err := tx.ValidateBasic(); err != nil {
return abci.ResponseDeliverTx{}, err
func (txh validateBasicTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := req.Tx.ValidateBasic(); err != nil {
return tx.Response{}, err
}
if err := validateBasicTxMsgs(tx.GetMsgs()); err != nil {
return abci.ResponseDeliverTx{}, err
if err := validateBasicTxMsgs(req.Tx.GetMsgs()); err != nil {
return tx.Response{}, err
}
return txh.next.DeliverTx(ctx, tx, req)
return txh.next.DeliverTx(ctx, req)
}
// SimulateTx implements tx.Handler.SimulateTx.
func (txh validateBasicTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
if err := sdkTx.ValidateBasic(); err != nil {
return tx.ResponseSimulateTx{}, err
func (txh validateBasicTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := req.Tx.ValidateBasic(); err != nil {
return tx.Response{}, err
}
if err := validateBasicTxMsgs(sdkTx.GetMsgs()); err != nil {
return tx.ResponseSimulateTx{}, err
if err := validateBasicTxMsgs(req.Tx.GetMsgs()); err != nil {
return tx.Response{}, err
}
return txh.next.SimulateTx(ctx, sdkTx, req)
return txh.next.SimulateTx(ctx, req)
}
var _ tx.Handler = txTimeoutHeightTxHandler{}
@ -124,30 +124,30 @@ func checkTimeout(ctx context.Context, tx sdk.Tx) error {
}
// CheckTx implements tx.Handler.CheckTx.
func (txh txTimeoutHeightTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
if err := checkTimeout(ctx, tx); err != nil {
return abci.ResponseCheckTx{}, err
func (txh txTimeoutHeightTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
if err := checkTimeout(ctx, req.Tx); err != nil {
return tx.Response{}, tx.ResponseCheckTx{}, err
}
return txh.next.CheckTx(ctx, tx, req)
return txh.next.CheckTx(ctx, req, checkReq)
}
// DeliverTx implements tx.Handler.DeliverTx.
func (txh txTimeoutHeightTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
if err := checkTimeout(ctx, tx); err != nil {
return abci.ResponseDeliverTx{}, err
func (txh txTimeoutHeightTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := checkTimeout(ctx, req.Tx); err != nil {
return tx.Response{}, err
}
return txh.next.DeliverTx(ctx, tx, req)
return txh.next.DeliverTx(ctx, req)
}
// SimulateTx implements tx.Handler.SimulateTx.
func (txh txTimeoutHeightTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
if err := checkTimeout(ctx, sdkTx); err != nil {
return tx.ResponseSimulateTx{}, err
func (txh txTimeoutHeightTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := checkTimeout(ctx, req.Tx); err != nil {
return tx.Response{}, err
}
return txh.next.SimulateTx(ctx, sdkTx, req)
return txh.next.SimulateTx(ctx, req)
}
type validateMemoTxHandler struct {
@ -190,30 +190,30 @@ func (vmm validateMemoTxHandler) checkForValidMemo(ctx context.Context, tx sdk.T
}
// CheckTx implements tx.Handler.CheckTx method.
func (vmm validateMemoTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
if err := vmm.checkForValidMemo(ctx, tx); err != nil {
return abci.ResponseCheckTx{}, err
func (vmm validateMemoTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
if err := vmm.checkForValidMemo(ctx, req.Tx); err != nil {
return tx.Response{}, tx.ResponseCheckTx{}, err
}
return vmm.next.CheckTx(ctx, tx, req)
return vmm.next.CheckTx(ctx, req, checkReq)
}
// DeliverTx implements tx.Handler.DeliverTx method.
func (vmm validateMemoTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
if err := vmm.checkForValidMemo(ctx, tx); err != nil {
return abci.ResponseDeliverTx{}, err
func (vmm validateMemoTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := vmm.checkForValidMemo(ctx, req.Tx); err != nil {
return tx.Response{}, err
}
return vmm.next.DeliverTx(ctx, tx, req)
return vmm.next.DeliverTx(ctx, req)
}
// SimulateTx implements tx.Handler.SimulateTx method.
func (vmm validateMemoTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
if err := vmm.checkForValidMemo(ctx, sdkTx); err != nil {
return tx.ResponseSimulateTx{}, err
func (vmm validateMemoTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := vmm.checkForValidMemo(ctx, req.Tx); err != nil {
return tx.Response{}, err
}
return vmm.next.SimulateTx(ctx, sdkTx, req)
return vmm.next.SimulateTx(ctx, req)
}
var _ tx.Handler = consumeTxSizeGasTxHandler{}
@ -305,34 +305,34 @@ func (cgts consumeTxSizeGasTxHandler) consumeTxSizeGas(ctx context.Context, _ sd
}
// CheckTx implements tx.Handler.CheckTx.
func (cgts consumeTxSizeGasTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
if err := cgts.consumeTxSizeGas(ctx, tx, req.GetTx()); err != nil {
return abci.ResponseCheckTx{}, err
func (cgts consumeTxSizeGasTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
if err := cgts.consumeTxSizeGas(ctx, req.Tx, req.TxBytes); err != nil {
return tx.Response{}, tx.ResponseCheckTx{}, err
}
return cgts.next.CheckTx(ctx, tx, req)
return cgts.next.CheckTx(ctx, req, checkReq)
}
// DeliverTx implements tx.Handler.DeliverTx.
func (cgts consumeTxSizeGasTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
if err := cgts.consumeTxSizeGas(ctx, tx, req.GetTx()); err != nil {
return abci.ResponseDeliverTx{}, err
func (cgts consumeTxSizeGasTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := cgts.consumeTxSizeGas(ctx, req.Tx, req.TxBytes); err != nil {
return tx.Response{}, err
}
return cgts.next.DeliverTx(ctx, tx, req)
return cgts.next.DeliverTx(ctx, req)
}
// SimulateTx implements tx.Handler.SimulateTx.
func (cgts consumeTxSizeGasTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
if err := cgts.consumeTxSizeGas(ctx, sdkTx, req.TxBytes); err != nil {
return tx.ResponseSimulateTx{}, err
func (cgts consumeTxSizeGasTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := cgts.consumeTxSizeGas(ctx, req.Tx, req.TxBytes); err != nil {
return tx.Response{}, err
}
if err := cgts.simulateSigGasCost(ctx, sdkTx); err != nil {
return tx.ResponseSimulateTx{}, err
if err := cgts.simulateSigGasCost(ctx, req.Tx); err != nil {
return tx.Response{}, err
}
return cgts.next.SimulateTx(ctx, sdkTx, req)
return cgts.next.SimulateTx(ctx, req)
}
// isIncompleteSignature tests whether SignatureData is fully filled in for simulation purposes

View File

@ -10,7 +10,6 @@ import (
"github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/middleware"
"github.com/tendermint/tendermint/abci/types"
)
func (s *MWTestSuite) TestValidateBasic() {
@ -34,21 +33,21 @@ func (s *MWTestSuite) TestValidateBasic() {
invalidTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
s.Require().NoError(err)
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), invalidTx, types.RequestDeliverTx{})
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: invalidTx})
s.Require().NotNil(err, "Did not error on invalid tx")
privs, accNums, accSeqs = []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
validTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
s.Require().NoError(err)
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), validTx, types.RequestDeliverTx{})
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: validTx})
s.Require().Nil(err, "ValidateBasicMiddleware returned error on valid tx. err: %v", err)
// test middleware skips on recheck
ctx = ctx.WithIsReCheckTx(true)
// middleware should skip processing invalidTx on recheck and thus return nil-error
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), invalidTx, types.RequestDeliverTx{})
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: invalidTx})
s.Require().Nil(err, "ValidateBasicMiddleware ran on ReCheck")
}
@ -74,7 +73,7 @@ func (s *MWTestSuite) TestValidateMemo() {
s.Require().NoError(err)
// require that long memos get rejected
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), invalidTx, types.RequestDeliverTx{})
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: invalidTx})
s.Require().NotNil(err, "Did not error on tx with high memo")
@ -83,7 +82,7 @@ func (s *MWTestSuite) TestValidateMemo() {
s.Require().NoError(err)
// require small memos pass ValidateMemo middleware
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), validTx, types.RequestDeliverTx{})
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: validTx})
s.Require().Nil(err, "ValidateBasicMiddleware returned error on valid tx. err: %v", err)
}
@ -137,7 +136,7 @@ func (s *MWTestSuite) TestConsumeGasForTxSize() {
expectedGas += afterGas - beforeGas
beforeGas = ctx.GasMeter().GasConsumed()
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), testTx, types.RequestDeliverTx{Tx: txBytes})
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx, TxBytes: txBytes})
s.Require().Nil(err, "ConsumeTxSizeGasMiddleware returned error: %v", err)
@ -162,7 +161,7 @@ func (s *MWTestSuite) TestConsumeGasForTxSize() {
beforeSimGas := ctx.GasMeter().GasConsumed()
// run txhandler in simulate mode
_, err = txHandler.SimulateTx(sdk.WrapSDKContext(ctx), testTx, tx.RequestSimulateTx{TxBytes: simTxBytes})
_, err = txHandler.SimulateTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx, TxBytes: simTxBytes})
consumedSimGas := ctx.GasMeter().GasConsumed() - beforeSimGas
// require that txhandler passes and does not underestimate middleware cost
@ -215,7 +214,7 @@ func (s *MWTestSuite) TestTxHeightTimeoutMiddleware() {
s.Require().NoError(err)
ctx := ctx.WithBlockHeight(tc.height)
_, err = txHandler.SimulateTx(sdk.WrapSDKContext(ctx), testTx, tx.RequestSimulateTx{})
_, err = txHandler.SimulateTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx})
s.Require().Equal(tc.expectErr, err != nil, err)
})
}

View File

@ -3,8 +3,6 @@ package middleware
import (
"context"
abci "github.com/tendermint/tendermint/abci/types"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
@ -44,28 +42,28 @@ func checkExtOpts(tx sdk.Tx) error {
}
// CheckTx implements tx.Handler.CheckTx.
func (txh rejectExtensionOptionsTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
if err := checkExtOpts(tx); err != nil {
return abci.ResponseCheckTx{}, err
func (txh rejectExtensionOptionsTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
if err := checkExtOpts(req.Tx); err != nil {
return tx.Response{}, tx.ResponseCheckTx{}, err
}
return txh.next.CheckTx(ctx, tx, req)
return txh.next.CheckTx(ctx, req, checkReq)
}
// DeliverTx implements tx.Handler.DeliverTx.
func (txh rejectExtensionOptionsTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
if err := checkExtOpts(tx); err != nil {
return abci.ResponseDeliverTx{}, err
func (txh rejectExtensionOptionsTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := checkExtOpts(req.Tx); err != nil {
return tx.Response{}, err
}
return txh.next.DeliverTx(ctx, tx, req)
return txh.next.DeliverTx(ctx, req)
}
// SimulateTx implements tx.Handler.SimulateTx method.
func (txh rejectExtensionOptionsTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
if err := checkExtOpts(sdkTx); err != nil {
return tx.ResponseSimulateTx{}, err
func (txh rejectExtensionOptionsTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := checkExtOpts(req.Tx); err != nil {
return tx.Response{}, err
}
return txh.next.SimulateTx(ctx, sdkTx, req)
return txh.next.SimulateTx(ctx, req)
}

View File

@ -4,9 +4,9 @@ import (
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
typestx "github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/x/auth/middleware"
"github.com/cosmos/cosmos-sdk/x/auth/tx"
abci "github.com/tendermint/tendermint/abci/types"
)
func (s *MWTestSuite) TestRejectExtensionOptionsMiddleware() {
@ -17,7 +17,7 @@ func (s *MWTestSuite) TestRejectExtensionOptionsMiddleware() {
// no extension options should not trigger an error
theTx := txBuilder.GetTx()
_, err := txHandler.CheckTx(sdk.WrapSDKContext(ctx), theTx, abci.RequestCheckTx{})
_, _, err := txHandler.CheckTx(sdk.WrapSDKContext(ctx), typestx.Request{Tx: theTx}, typestx.RequestCheckTx{})
s.Require().NoError(err)
extOptsTxBldr, ok := txBuilder.(tx.ExtensionOptionsTxBuilder)
@ -31,6 +31,6 @@ func (s *MWTestSuite) TestRejectExtensionOptionsMiddleware() {
s.Require().NoError(err)
extOptsTxBldr.SetExtensionOptions(any)
theTx = txBuilder.GetTx()
_, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), theTx, abci.RequestCheckTx{})
_, _, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), typestx.Request{Tx: theTx}, typestx.RequestCheckTx{})
s.Require().EqualError(err, "unknown extension options")
}

View File

@ -4,8 +4,6 @@ import (
"context"
"fmt"
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx"
@ -36,12 +34,12 @@ func MempoolFeeMiddleware(txh tx.Handler) tx.Handler {
// and the transaction does not meet the minimum, the transaction is rejected.
//
// Recall, a transaction's fee is determined by ceil(minGasPrice * gasLimit).
func (txh mempoolFeeTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
func (txh mempoolFeeTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
feeTx, ok := tx.(sdk.FeeTx)
feeTx, ok := req.Tx.(sdk.FeeTx)
if !ok {
return abci.ResponseCheckTx{}, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
}
feeCoins := feeTx.GetFee()
@ -63,21 +61,21 @@ func (txh mempoolFeeTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.
}
if !feeCoins.IsAnyGTE(requiredFees) {
return abci.ResponseCheckTx{}, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees)
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees)
}
}
return txh.next.CheckTx(ctx, tx, req)
return txh.next.CheckTx(ctx, req, checkReq)
}
// DeliverTx implements tx.Handler.DeliverTx.
func (txh mempoolFeeTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
return txh.next.DeliverTx(ctx, tx, req)
func (txh mempoolFeeTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
return txh.next.DeliverTx(ctx, req)
}
// SimulateTx implements tx.Handler.SimulateTx.
func (txh mempoolFeeTxHandler) SimulateTx(ctx context.Context, tx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
return txh.next.SimulateTx(ctx, tx, req)
func (txh mempoolFeeTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
return txh.next.SimulateTx(ctx, req)
}
var _ tx.Handler = deductFeeTxHandler{}
@ -104,9 +102,9 @@ func DeductFeeMiddleware(ak AccountKeeper, bk types.BankKeeper, fk FeegrantKeepe
}
}
func (dfd deductFeeTxHandler) checkDeductFee(ctx context.Context, tx sdk.Tx) error {
func (dfd deductFeeTxHandler) checkDeductFee(ctx context.Context, sdkTx sdk.Tx) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
feeTx, ok := tx.(sdk.FeeTx)
feeTx, ok := sdkTx.(sdk.FeeTx)
if !ok {
return sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
}
@ -127,7 +125,7 @@ func (dfd deductFeeTxHandler) checkDeductFee(ctx context.Context, tx sdk.Tx) err
if dfd.feegrantKeeper == nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "fee grants are not enabled")
} else if !feeGranter.Equals(feePayer) {
err := dfd.feegrantKeeper.UseGrantedFees(sdkCtx, feeGranter, feePayer, fee, tx.GetMsgs())
err := dfd.feegrantKeeper.UseGrantedFees(sdkCtx, feeGranter, feePayer, fee, sdkTx.GetMsgs())
if err != nil {
return sdkerrors.Wrapf(err, "%s not allowed to pay fees from %s", feeGranter, feePayer)
@ -159,29 +157,29 @@ func (dfd deductFeeTxHandler) checkDeductFee(ctx context.Context, tx sdk.Tx) err
}
// CheckTx implements tx.Handler.CheckTx.
func (dfd deductFeeTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
if err := dfd.checkDeductFee(ctx, tx); err != nil {
return abci.ResponseCheckTx{}, err
func (dfd deductFeeTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
if err := dfd.checkDeductFee(ctx, req.Tx); err != nil {
return tx.Response{}, tx.ResponseCheckTx{}, err
}
return dfd.next.CheckTx(ctx, tx, req)
return dfd.next.CheckTx(ctx, req, checkReq)
}
// DeliverTx implements tx.Handler.DeliverTx.
func (dfd deductFeeTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
if err := dfd.checkDeductFee(ctx, tx); err != nil {
return abci.ResponseDeliverTx{}, err
func (dfd deductFeeTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := dfd.checkDeductFee(ctx, req.Tx); err != nil {
return tx.Response{}, err
}
return dfd.next.DeliverTx(ctx, tx, req)
return dfd.next.DeliverTx(ctx, req)
}
func (dfd deductFeeTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
if err := dfd.checkDeductFee(ctx, sdkTx); err != nil {
return tx.ResponseSimulateTx{}, err
func (dfd deductFeeTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := dfd.checkDeductFee(ctx, req.Tx); err != nil {
return tx.Response{}, err
}
return dfd.next.SimulateTx(ctx, sdkTx, req)
return dfd.next.SimulateTx(ctx, req)
}
// DeductFees deducts fees from the given account.

View File

@ -4,9 +4,9 @@ import (
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/x/auth/middleware"
"github.com/cosmos/cosmos-sdk/x/bank/testutil"
abci "github.com/tendermint/tendermint/abci/types"
)
func (s *MWTestSuite) TestEnsureMempoolFees() {
@ -27,7 +27,7 @@ func (s *MWTestSuite) TestEnsureMempoolFees() {
txBuilder.SetGasLimit(gasLimit)
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
tx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
testTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
s.Require().NoError(err)
// Set high gas price so standard test fee fails
@ -36,18 +36,18 @@ func (s *MWTestSuite) TestEnsureMempoolFees() {
ctx = ctx.WithMinGasPrices(highGasPrice)
// txHandler errors with insufficient fees
_, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx, abci.RequestCheckTx{})
_, _, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{})
s.Require().NotNil(err, "Middleware should have errored on too low fee for local gasPrice")
// txHandler should not error since we do not check minGasPrice in DeliverTx
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx, abci.RequestDeliverTx{})
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx})
s.Require().Nil(err, "MempoolFeeMiddleware returned error in DeliverTx")
atomPrice = sdk.NewDecCoinFromDec("atom", sdk.NewDec(0).Quo(sdk.NewDec(100000)))
lowGasPrice := []sdk.DecCoin{atomPrice}
ctx = ctx.WithMinGasPrices(lowGasPrice)
_, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx, abci.RequestCheckTx{})
_, _, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{})
s.Require().Nil(err, "Middleware should not have errored on fee higher than local gasPrice")
}
@ -75,7 +75,7 @@ func (s *MWTestSuite) TestDeductFees() {
txBuilder.SetGasLimit(gasLimit)
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
tx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
testTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
s.Require().NoError(err)
// Set account with insufficient funds
@ -85,7 +85,7 @@ func (s *MWTestSuite) TestDeductFees() {
err = testutil.FundAccount(s.app.BankKeeper, ctx, addr1, coins)
s.Require().NoError(err)
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx, abci.RequestDeliverTx{})
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx})
s.Require().NotNil(err, "Tx did not error when fee payer had insufficient funds")
// Set account with sufficient funds
@ -93,7 +93,7 @@ func (s *MWTestSuite) TestDeductFees() {
err = testutil.FundAccount(s.app.BankKeeper, ctx, addr1, sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(200))))
s.Require().NoError(err)
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx, abci.RequestDeliverTx{})
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx})
s.Require().Nil(err, "Tx errored after account has been set with sufficient funds")
}

View File

@ -5,7 +5,6 @@ import (
"testing"
"time"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto"
"github.com/cosmos/cosmos-sdk/client"
@ -15,6 +14,7 @@ import (
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/simulation"
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/middleware"
authsign "github.com/cosmos/cosmos-sdk/x/auth/signing"
@ -145,11 +145,11 @@ func (s *MWTestSuite) TestDeductFeesNoDelegation() {
accNums, seqs = []uint64{acc.GetAccountNumber()}, []uint64{acc.GetSequence()}
}
tx, err := genTxWithFeeGranter(protoTxCfg, msgs, fee, helpers.DefaultGenTxGas, ctx.ChainID(), accNums, seqs, tc.feeAccount, privs...)
testTx, err := genTxWithFeeGranter(protoTxCfg, msgs, fee, helpers.DefaultGenTxGas, ctx.ChainID(), accNums, seqs, tc.feeAccount, privs...)
s.Require().NoError(err)
// tests only feegrant middleware
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx, abci.RequestDeliverTx{})
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), txtypes.Request{Tx: testTx})
if tc.valid {
s.Require().NoError(err)
} else {
@ -157,7 +157,7 @@ func (s *MWTestSuite) TestDeductFeesNoDelegation() {
}
// tests while stack
_, err = s.txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx, abci.RequestDeliverTx{})
_, err = s.txHandler.DeliverTx(sdk.WrapSDKContext(ctx), txtypes.Request{Tx: testTx})
if tc.valid {
s.Require().NoError(err)
} else {

View File

@ -3,8 +3,6 @@ package middleware
import (
"context"
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx"
@ -30,47 +28,47 @@ func GasTxMiddleware(txh tx.Handler) tx.Handler {
var _ tx.Handler = gasTxHandler{}
// CheckTx implements tx.Handler.CheckTx.
func (txh gasTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
sdkCtx, err := gasContext(sdk.UnwrapSDKContext(ctx), tx, false)
func (txh gasTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
sdkCtx, err := gasContext(sdk.UnwrapSDKContext(ctx), req.Tx, false)
if err != nil {
return abci.ResponseCheckTx{}, err
return tx.Response{}, tx.ResponseCheckTx{}, err
}
res, err := txh.next.CheckTx(sdk.WrapSDKContext(sdkCtx), tx, req)
res.GasUsed = int64(sdkCtx.GasMeter().GasConsumed())
res.GasWanted = int64(sdkCtx.GasMeter().Limit())
res, resCheckTx, err := txh.next.CheckTx(sdk.WrapSDKContext(sdkCtx), req, checkReq)
return res, err
return populateGas(res, sdkCtx), resCheckTx, err
}
// DeliverTx implements tx.Handler.DeliverTx.
func (txh gasTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
sdkCtx, err := gasContext(sdk.UnwrapSDKContext(ctx), tx, false)
func (txh gasTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
sdkCtx, err := gasContext(sdk.UnwrapSDKContext(ctx), req.Tx, false)
if err != nil {
return abci.ResponseDeliverTx{}, err
return tx.Response{}, err
}
res, err := txh.next.DeliverTx(sdk.WrapSDKContext(sdkCtx), tx, req)
res.GasUsed = int64(sdkCtx.GasMeter().GasConsumed())
res.GasWanted = int64(sdkCtx.GasMeter().Limit())
res, err := txh.next.DeliverTx(sdk.WrapSDKContext(sdkCtx), req)
return res, err
return populateGas(res, sdkCtx), err
}
// SimulateTx implements tx.Handler.SimulateTx method.
func (txh gasTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
sdkCtx, err := gasContext(sdk.UnwrapSDKContext(ctx), sdkTx, true)
func (txh gasTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
sdkCtx, err := gasContext(sdk.UnwrapSDKContext(ctx), req.Tx, true)
if err != nil {
return tx.ResponseSimulateTx{}, err
return tx.Response{}, err
}
res, err := txh.next.SimulateTx(sdk.WrapSDKContext(sdkCtx), sdkTx, req)
res.GasInfo = sdk.GasInfo{
GasWanted: sdkCtx.GasMeter().Limit(),
GasUsed: sdkCtx.GasMeter().GasConsumed(),
}
res, err := txh.next.SimulateTx(sdk.WrapSDKContext(sdkCtx), req)
return res, err
return populateGas(res, sdkCtx), err
}
// populateGas returns a new tx.Response with gas fields populated.
func populateGas(res tx.Response, sdkCtx sdk.Context) tx.Response {
res.GasWanted = sdkCtx.GasMeter().Limit()
res.GasUsed = sdkCtx.GasMeter().GasConsumed()
return res
}
// gasContext returns a new context with a gas meter set from a given context.

View File

@ -4,8 +4,6 @@ import (
"context"
"errors"
abci "github.com/tendermint/tendermint/abci/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -51,7 +49,7 @@ func (s *MWTestSuite) setupGasTx() (signing.Tx, []byte, sdk.Context, uint64) {
}
func (s *MWTestSuite) TestSetup() {
tx, _, ctx, gasLimit := s.setupGasTx()
testTx, _, ctx, gasLimit := s.setupGasTx()
txHandler := middleware.ComposeMiddlewares(noopTxHandler{}, middleware.GasTxMiddleware)
testcases := []struct {
@ -62,11 +60,11 @@ func (s *MWTestSuite) TestSetup() {
errorStr string
}{
{"not a gas tx", txTest{}, 0, true, "Tx must be GasTx: tx parse error"},
{"tx with its own gas limit", tx, gasLimit, false, ""},
{"tx with its own gas limit", testTx, gasLimit, false, ""},
}
for _, tc := range testcases {
s.Run(tc.name, func() {
res, err := txHandler.CheckTx(sdk.WrapSDKContext(ctx), tc.tx, abci.RequestCheckTx{})
res, _, err := txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: tc.tx}, tx.RequestCheckTx{})
if tc.expErr {
s.Require().EqualError(err, tc.errorStr)
} else {
@ -78,15 +76,17 @@ func (s *MWTestSuite) TestSetup() {
}
func (s *MWTestSuite) TestRecoverPanic() {
tx, txBytes, ctx, gasLimit := s.setupGasTx()
testTx, txBytes, ctx, gasLimit := s.setupGasTx()
txHandler := middleware.ComposeMiddlewares(outOfGasTxHandler{}, middleware.GasTxMiddleware, middleware.RecoveryTxMiddleware)
res, err := txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx, abci.RequestCheckTx{Tx: txBytes})
res, _, err := txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx, TxBytes: txBytes}, tx.RequestCheckTx{})
s.Require().Error(err, "Did not return error on OutOfGas panic")
s.Require().True(errors.Is(sdkerrors.ErrOutOfGas, err), "Returned error is not an out of gas error")
s.Require().Equal(gasLimit, uint64(res.GasWanted))
txHandler = middleware.ComposeMiddlewares(outOfGasTxHandler{}, middleware.GasTxMiddleware)
s.Require().Panics(func() { txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx, abci.RequestCheckTx{Tx: txBytes}) }, "Recovered from non-Out-of-Gas panic")
s.Require().Panics(func() {
txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx, TxBytes: txBytes}, tx.RequestCheckTx{})
}, "Recovered from non-Out-of-Gas panic")
}
// outOfGasTxHandler is a test middleware that will throw OutOfGas panic.
@ -94,7 +94,7 @@ type outOfGasTxHandler struct{}
var _ tx.Handler = outOfGasTxHandler{}
func (txh outOfGasTxHandler) DeliverTx(ctx context.Context, _ sdk.Tx, _ abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
func (txh outOfGasTxHandler) DeliverTx(ctx context.Context, _ tx.Request) (tx.Response, error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
overLimit := sdkCtx.GasMeter().Limit() + 1
@ -103,7 +103,7 @@ func (txh outOfGasTxHandler) DeliverTx(ctx context.Context, _ sdk.Tx, _ abci.Req
panic("not reached")
}
func (txh outOfGasTxHandler) CheckTx(ctx context.Context, _ sdk.Tx, _ abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
func (txh outOfGasTxHandler) CheckTx(ctx context.Context, _ tx.Request, _ tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
overLimit := sdkCtx.GasMeter().Limit() + 1
@ -112,7 +112,7 @@ func (txh outOfGasTxHandler) CheckTx(ctx context.Context, _ sdk.Tx, _ abci.Reque
panic("not reached")
}
func (txh outOfGasTxHandler) SimulateTx(ctx context.Context, _ sdk.Tx, _ tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
func (txh outOfGasTxHandler) SimulateTx(ctx context.Context, _ tx.Request) (tx.Response, error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
overLimit := sdkCtx.GasMeter().Limit() + 1
@ -127,12 +127,12 @@ type noopTxHandler struct{}
var _ tx.Handler = noopTxHandler{}
func (txh noopTxHandler) CheckTx(_ context.Context, _ sdk.Tx, _ abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
return abci.ResponseCheckTx{}, nil
func (txh noopTxHandler) CheckTx(_ context.Context, _ tx.Request, _ tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
return tx.Response{}, tx.ResponseCheckTx{}, nil
}
func (txh noopTxHandler) SimulateTx(_ context.Context, _ sdk.Tx, _ tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
return tx.ResponseSimulateTx{}, nil
func (txh noopTxHandler) SimulateTx(_ context.Context, _ tx.Request) (tx.Response, error) {
return tx.Response{}, nil
}
func (txh noopTxHandler) DeliverTx(ctx context.Context, _ sdk.Tx, _ abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
return abci.ResponseDeliverTx{}, nil
func (txh noopTxHandler) DeliverTx(ctx context.Context, _ tx.Request) (tx.Response, error) {
return tx.Response{}, nil
}

View File

@ -3,8 +3,6 @@ package middleware
import (
"context"
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx"
)
@ -13,7 +11,7 @@ type indexEventsTxHandler struct {
// indexEvents defines the set of events in the form {eventType}.{attributeKey},
// which informs Tendermint what to index. If empty, all events will be indexed.
indexEvents map[string]struct{}
inner tx.Handler
next tx.Handler
}
// NewIndexEventsTxMiddleware defines a middleware to optionally only index a
@ -22,7 +20,7 @@ func NewIndexEventsTxMiddleware(indexEvents map[string]struct{}) tx.Middleware {
return func(txHandler tx.Handler) tx.Handler {
return indexEventsTxHandler{
indexEvents: indexEvents,
inner: txHandler,
next: txHandler,
}
}
}
@ -30,19 +28,19 @@ func NewIndexEventsTxMiddleware(indexEvents map[string]struct{}) tx.Middleware {
var _ tx.Handler = indexEventsTxHandler{}
// CheckTx implements tx.Handler.CheckTx method.
func (txh indexEventsTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
res, err := txh.inner.CheckTx(ctx, tx, req)
func (txh indexEventsTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
res, resCheckTx, err := txh.next.CheckTx(ctx, req, checkReq)
if err != nil {
return res, err
return res, tx.ResponseCheckTx{}, err
}
res.Events = sdk.MarkEventsToIndex(res.Events, txh.indexEvents)
return res, nil
return res, resCheckTx, nil
}
// DeliverTx implements tx.Handler.DeliverTx method.
func (txh indexEventsTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
res, err := txh.inner.DeliverTx(ctx, tx, req)
func (txh indexEventsTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
res, err := txh.next.DeliverTx(ctx, req)
if err != nil {
return res, err
}
@ -52,12 +50,12 @@ func (txh indexEventsTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req ab
}
// SimulateTx implements tx.Handler.SimulateTx method.
func (txh indexEventsTxHandler) SimulateTx(ctx context.Context, tx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
res, err := txh.inner.SimulateTx(ctx, tx, req)
func (txh indexEventsTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
res, err := txh.next.SimulateTx(ctx, req)
if err != nil {
return res, err
}
res.Result.Events = sdk.MarkEventsToIndex(res.Result.Events, txh.indexEvents)
res.Events = sdk.MarkEventsToIndex(res.Events, txh.indexEvents)
return res, nil
}

View File

@ -50,15 +50,15 @@ type TxHandlerOptions struct {
// for most applications.
func NewDefaultTxHandler(options TxHandlerOptions) (tx.Handler, error) {
if options.AccountKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for compose middlewares")
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for middlewares")
}
if options.BankKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for compose middlewares")
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for middlewares")
}
if options.SignModeHandler == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for compose middlewares")
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for middlewares")
}
var sigGasConsumer = options.SigGasConsumer
@ -89,7 +89,7 @@ func NewDefaultTxHandler(options TxHandlerOptions) (tx.Handler, error) {
ValidateMemoMiddleware(options.AccountKeeper),
ConsumeTxSizeGasMiddleware(options.AccountKeeper),
DeductFeeMiddleware(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper),
TxPriorityHandler,
TxPriorityMiddleware,
SetPubKeyMiddleware(options.AccountKeeper),
ValidateSigCountMiddleware(options.AccountKeeper),
SigGasConsumeMiddleware(options.AccountKeeper, sigGasConsumer),

View File

@ -14,6 +14,7 @@ import (
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/middleware"
"github.com/cosmos/cosmos-sdk/x/auth/types"
@ -853,14 +854,14 @@ func (s *MWTestSuite) TestTxHandlerSetPubKey() {
txBuilder.SetGasLimit(gasLimit)
// Manually create tx, and remove signature.
tx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
testTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
s.Require().NoError(err)
txBuilder, err := s.clientCtx.TxConfig.WrapTxBuilder(tx)
txBuilder, err := s.clientCtx.TxConfig.WrapTxBuilder(testTx)
s.Require().NoError(err)
s.Require().NoError(txBuilder.SetSignatures())
// Run txHandler manually, expect ErrNoSignatures.
_, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), txBuilder.GetTx(), abci.RequestCheckTx{})
_, _, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: txBuilder.GetTx()}, tx.RequestCheckTx{})
s.Require().Error(err)
s.Require().True(errors.Is(err, sdkerrors.ErrNoSignatures))
@ -1059,9 +1060,9 @@ func (s *MWTestSuite) TestCustomSignatureVerificationGasConsumer() {
s.Run(fmt.Sprintf("Case %s", tc.desc), func() {
tc.malleate()
tx, txBytes, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
testTx, txBytes, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
s.Require().NoError(err)
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx, abci.RequestDeliverTx{Tx: txBytes})
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx, TxBytes: txBytes})
s.Require().Error(err)
s.Require().True(errors.Is(err, tc.expErr))
})
@ -1090,21 +1091,21 @@ func (s *MWTestSuite) TestTxHandlerReCheck() {
// test that operations skipped on recheck do not run
privs, accNums, accSeqs := []cryptotypes.PrivKey{accounts[0].priv}, []uint64{0}, []uint64{0}
tx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
testTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
s.Require().NoError(err)
// make signature array empty which would normally cause ValidateBasicMiddleware and SigVerificationMiddleware fail
// since these middlewares don't run on recheck, the tx should pass the middleware
txBuilder, err = s.clientCtx.TxConfig.WrapTxBuilder(tx)
txBuilder, err = s.clientCtx.TxConfig.WrapTxBuilder(testTx)
s.Require().NoError(err)
s.Require().NoError(txBuilder.SetSignatures())
_, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), txBuilder.GetTx(), abci.RequestCheckTx{Type: abci.CheckTxType_Recheck})
_, _, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: txBuilder.GetTx()}, tx.RequestCheckTx{Type: abci.CheckTxType_Recheck})
s.Require().Nil(err, "TxHandler errored on recheck unexpectedly: %v", err)
tx, _, err = s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
testTx, _, err = s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
s.Require().NoError(err)
txBytes, err := json.Marshal(tx)
txBytes, err := json.Marshal(testTx)
s.Require().Nil(err, "Error marshalling tx: %v", err)
ctx = ctx.WithTxBytes(txBytes)
@ -1122,7 +1123,7 @@ func (s *MWTestSuite) TestTxHandlerReCheck() {
// set testcase parameters
s.app.AccountKeeper.SetParams(ctx, tc.params)
_, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx, abci.RequestCheckTx{Tx: txBytes, Type: abci.CheckTxType_Recheck})
_, _, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx, TxBytes: txBytes}, tx.RequestCheckTx{Type: abci.CheckTxType_Recheck})
s.Require().NotNil(err, "tx does not fail on recheck with updated params in test case: %s", tc.name)
@ -1136,7 +1137,7 @@ func (s *MWTestSuite) TestTxHandlerReCheck() {
Denom: "dnecoin", // fee does not have this denom
Amount: sdk.NewDec(5),
}})
_, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx, abci.RequestCheckTx{})
_, _, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{})
s.Require().NotNil(err, "txhandler on recheck did not fail when mingasPrice was changed")
// reset min gasprice
@ -1148,6 +1149,6 @@ func (s *MWTestSuite) TestTxHandlerReCheck() {
err = s.app.BankKeeper.SendCoinsFromAccountToModule(ctx, accounts[0].acc.GetAddress(), minttypes.ModuleName, balances)
s.Require().NoError(err)
_, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx, abci.RequestCheckTx{})
_, _, err = s.txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{})
s.Require().NotNil(err, "txhandler on recheck did not fail once feePayer no longer has sufficient funds")
}

View File

@ -3,8 +3,6 @@ package middleware
import (
"context"
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx"
@ -16,10 +14,10 @@ type txPriorityHandler struct {
next tx.Handler
}
// TxPriorityHandler implements tx handling middleware that determines a
// TxPriorityMiddleware implements tx handling middleware that determines a
// transaction's priority via a naive mechanism -- the total sum of fees provided.
// It sets the Priority in ResponseCheckTx only.
func TxPriorityHandler(txh tx.Handler) tx.Handler {
func TxPriorityMiddleware(txh tx.Handler) tx.Handler {
return txPriorityHandler{next: txh}
}
@ -28,26 +26,26 @@ func TxPriorityHandler(txh tx.Handler) tx.Handler {
// fees included. Applications that need more sophisticated mempool ordering
// should look to implement their own fee handling middleware instead of using
// TxPriorityHandler.
func (h txPriorityHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
feeTx, ok := tx.(sdk.FeeTx)
func (h txPriorityHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
feeTx, ok := req.Tx.(sdk.FeeTx)
if !ok {
return abci.ResponseCheckTx{}, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
}
feeCoins := feeTx.GetFee()
res, err := h.next.CheckTx(ctx, tx, req)
res.Priority = GetTxPriority(feeCoins)
res, checkRes, err := h.next.CheckTx(ctx, req, checkReq)
checkRes.Priority = GetTxPriority(feeCoins)
return res, err
return res, checkRes, err
}
func (h txPriorityHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
return h.next.DeliverTx(ctx, tx, req)
func (h txPriorityHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
return h.next.DeliverTx(ctx, req)
}
func (h txPriorityHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
return h.next.SimulateTx(ctx, sdkTx, req)
func (h txPriorityHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
return h.next.SimulateTx(ctx, req)
}
// GetTxPriority returns a naive tx priority based on the amount of the smallest denomination of the fee

View File

@ -4,15 +4,15 @@ import (
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/x/auth/middleware"
abci "github.com/tendermint/tendermint/abci/types"
)
func (s *MWTestSuite) TestPriority() {
ctx := s.SetupTest(true) // setup
txBuilder := s.clientCtx.TxConfig.NewTxBuilder()
txHandler := middleware.ComposeMiddlewares(noopTxHandler{}, middleware.TxPriorityHandler)
txHandler := middleware.ComposeMiddlewares(noopTxHandler{}, middleware.TxPriorityMiddleware)
// keys and addresses
priv1, _, addr1 := testdata.KeyTestPubAddr()
@ -28,11 +28,11 @@ func (s *MWTestSuite) TestPriority() {
txBuilder.SetGasLimit(gasLimit)
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
tx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
testTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
s.Require().NoError(err)
// txHandler errors with insufficient fees
res, err := txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx, abci.RequestCheckTx{})
_, checkTxRes, err := txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{})
s.Require().NoError(err, "Middleware should not have errored on too low fee for local gasPrice")
s.Require().Equal(atomCoin.Amount.Int64(), res.Priority, "priority should be atom amount")
s.Require().Equal(atomCoin.Amount.Int64(), checkTxRes.Priority, "priority should be atom amount")
}

View File

@ -4,8 +4,6 @@ import (
"context"
"runtime/debug"
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx"
@ -26,7 +24,7 @@ func RecoveryTxMiddleware(txh tx.Handler) tx.Handler {
var _ tx.Handler = recoveryTxHandler{}
// CheckTx implements tx.Handler.CheckTx method.
func (txh recoveryTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (res abci.ResponseCheckTx, err error) {
func (txh recoveryTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (res tx.Response, resCheckTx tx.ResponseCheckTx, err error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
// Panic recovery.
defer func() {
@ -35,11 +33,11 @@ func (txh recoveryTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.Re
}
}()
return txh.next.CheckTx(ctx, tx, req)
return txh.next.CheckTx(ctx, req, checkReq)
}
// DeliverTx implements tx.Handler.DeliverTx method.
func (txh recoveryTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (res abci.ResponseDeliverTx, err error) {
func (txh recoveryTxHandler) DeliverTx(ctx context.Context, req tx.Request) (res tx.Response, err error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
// only run the tx if there is block gas remaining
if sdkCtx.BlockGasMeter().IsOutOfGas() {
@ -71,11 +69,11 @@ func (txh recoveryTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.
}
}()
return txh.next.DeliverTx(ctx, tx, req)
return txh.next.DeliverTx(ctx, req)
}
// SimulateTx implements tx.Handler.SimulateTx method.
func (txh recoveryTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (res tx.ResponseSimulateTx, err error) {
func (txh recoveryTxHandler) SimulateTx(ctx context.Context, req tx.Request) (res tx.Response, err error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
// Panic recovery.
defer func() {
@ -84,7 +82,7 @@ func (txh recoveryTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req t
}
}()
return txh.next.SimulateTx(ctx, sdkTx, req)
return txh.next.SimulateTx(ctx, req)
}
func handleRecovery(r interface{}, sdkCtx sdk.Context) error {

View File

@ -5,10 +5,9 @@ import (
"fmt"
"strings"
"github.com/gogo/protobuf/proto"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/tmhash"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx"
@ -30,37 +29,19 @@ func NewRunMsgsTxHandler(msr *MsgServiceRouter, legacyRouter sdk.Router) tx.Hand
var _ tx.Handler = runMsgsTxHandler{}
// CheckTx implements tx.Handler.CheckTx method.
func (txh runMsgsTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
func (txh runMsgsTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
// Don't run Msgs during CheckTx.
return abci.ResponseCheckTx{}, nil
return tx.Response{}, tx.ResponseCheckTx{}, nil
}
// DeliverTx implements tx.Handler.DeliverTx method.
func (txh runMsgsTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
res, err := txh.runMsgs(sdk.UnwrapSDKContext(ctx), tx.GetMsgs(), req.Tx)
if err != nil {
return abci.ResponseDeliverTx{}, err
}
return abci.ResponseDeliverTx{
// GasInfo will be populated by the Gas middleware.
Log: res.Log,
Data: res.Data,
Events: res.Events,
}, nil
func (txh runMsgsTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
return txh.runMsgs(sdk.UnwrapSDKContext(ctx), req.Tx.GetMsgs(), req.TxBytes)
}
// SimulateTx implements tx.Handler.SimulateTx method.
func (txh runMsgsTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
res, err := txh.runMsgs(sdk.UnwrapSDKContext(ctx), sdkTx.GetMsgs(), req.TxBytes)
if err != nil {
return tx.ResponseSimulateTx{}, err
}
return tx.ResponseSimulateTx{
// GasInfo will be populated by the Gas middleware.
Result: res,
}, nil
func (txh runMsgsTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
return txh.runMsgs(sdk.UnwrapSDKContext(ctx), req.Tx.GetMsgs(), req.TxBytes)
}
// runMsgs iterates through a list of messages and executes them with the provided
@ -68,7 +49,7 @@ func (txh runMsgsTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx
// and DeliverTx. An error is returned if any single message fails or if a
// Handler does not exist for a given message route. Otherwise, a reference to a
// Result is returned. The caller must not commit state if an error is returned.
func (txh runMsgsTxHandler) runMsgs(sdkCtx sdk.Context, msgs []sdk.Msg, txBytes []byte) (*sdk.Result, error) {
func (txh runMsgsTxHandler) runMsgs(sdkCtx sdk.Context, msgs []sdk.Msg, txBytes []byte) (tx.Response, error) {
// Create a new Context based off of the existing Context with a MultiStore branch
// in case message processing fails. At this point, the MultiStore
// is a branch of a branch.
@ -79,9 +60,7 @@ func (txh runMsgsTxHandler) runMsgs(sdkCtx sdk.Context, msgs []sdk.Msg, txBytes
// Result if any single message fails or does not have a registered Handler.
msgLogs := make(sdk.ABCIMessageLogs, 0, len(msgs))
events := sdkCtx.EventManager().Events()
txMsgData := &sdk.TxMsgData{
Data: make([]*sdk.MsgData, 0, len(msgs)),
}
msgResponses := make([]*codectypes.Any, len(msgs))
// NOTE: GasWanted is determined by the Gas TxHandler and GasUsed by the GasMeter.
for i, msg := range msgs {
@ -105,16 +84,16 @@ func (txh runMsgsTxHandler) runMsgs(sdkCtx sdk.Context, msgs []sdk.Msg, txBytes
eventMsgName = legacyMsg.Type()
handler := txh.legacyRouter.Route(sdkCtx, msgRoute)
if handler == nil {
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message route: %s; message index: %d", msgRoute, i)
return tx.Response{}, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message route: %s; message index: %d", msgRoute, i)
}
msgResult, err = handler(sdkCtx, msg)
} else {
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "can't route message %+v", msg)
return tx.Response{}, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "can't route message %+v", msg)
}
if err != nil {
return nil, sdkerrors.Wrapf(err, "failed to execute message; message index: %d", i)
return tx.Response{}, sdkerrors.Wrapf(err, "failed to execute message; message index: %d", i)
}
msgEvents := sdk.Events{
@ -128,20 +107,22 @@ func (txh runMsgsTxHandler) runMsgs(sdkCtx sdk.Context, msgs []sdk.Msg, txBytes
// separate each result.
events = events.AppendEvents(msgEvents)
txMsgData.Data = append(txMsgData.Data, &sdk.MsgData{MsgType: sdk.MsgTypeURL(msg), Data: msgResult.Data})
// Each individual sdk.Result has exactly one Msg response. We aggregate here.
msgResponse := msgResult.MsgResponses[0]
if msgResponse == nil {
return tx.Response{}, sdkerrors.ErrLogic.Wrapf("got nil Msg response at index %d for msg %s", i, sdk.MsgTypeURL(msg))
}
msgResponses[i] = msgResponse
msgLogs = append(msgLogs, sdk.NewABCIMessageLog(uint32(i), msgResult.Log, msgEvents))
}
msCache.Write()
data, err := proto.Marshal(txMsgData)
if err != nil {
return nil, sdkerrors.Wrap(err, "failed to marshal tx data")
}
return &sdk.Result{
Data: data,
Log: strings.TrimSpace(msgLogs.String()),
Events: events.ToABCIEvents(),
return tx.Response{
// GasInfo will be populated by the Gas middleware.
Log: strings.TrimSpace(msgLogs.String()),
Events: events.ToABCIEvents(),
MsgResponses: msgResponses,
}, nil
}

View File

@ -1,11 +1,14 @@
package middleware_test
import (
"github.com/tendermint/tendermint/abci/types"
"fmt"
"github.com/gogo/protobuf/proto"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/x/auth/middleware"
)
@ -20,17 +23,13 @@ func (s *MWTestSuite) TestRunMsgs() {
txBuilder := s.clientCtx.TxConfig.NewTxBuilder()
txBuilder.SetMsgs(&testdata.MsgCreateDog{Dog: &testdata.Dog{Name: "Spot"}})
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv}, []uint64{0}, []uint64{0}
tx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
testTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
s.Require().NoError(err)
txBytes, err := s.clientCtx.TxConfig.TxEncoder()(tx)
txBytes, err := s.clientCtx.TxConfig.TxEncoder()(testTx)
s.Require().NoError(err)
res, err := txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx, types.RequestDeliverTx{Tx: txBytes})
res, err := txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx, TxBytes: txBytes})
s.Require().NoError(err)
s.Require().NotEmpty(res.Data)
var txMsgData sdk.TxMsgData
err = s.clientCtx.Codec.Unmarshal(res.Data, &txMsgData)
s.Require().NoError(err)
s.Require().Len(txMsgData.Data, 1)
s.Require().Equal(sdk.MsgTypeURL(&testdata.MsgCreateDog{}), txMsgData.Data[0].MsgType)
s.Require().Len(res.MsgResponses, 1)
s.Require().Equal(fmt.Sprintf("/%s", proto.MessageName(&testdata.MsgCreateDogResponse{})), res.MsgResponses[0].TypeUrl)
}

View File

@ -52,9 +52,9 @@ func SetPubKeyMiddleware(ak AccountKeeper) tx.Middleware {
}
}
func (spkm setPubKeyTxHandler) setPubKey(ctx context.Context, tx sdk.Tx, simulate bool) error {
func (spkm setPubKeyTxHandler) setPubKey(ctx context.Context, req tx.Request, simulate bool) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
sigTx, ok := tx.(authsigning.SigVerifiableTx)
sigTx, ok := req.Tx.(authsigning.SigVerifiableTx)
if !ok {
return sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid tx type")
}
@ -126,28 +126,28 @@ func (spkm setPubKeyTxHandler) setPubKey(ctx context.Context, tx sdk.Tx, simulat
}
// CheckTx implements tx.Handler.CheckTx.
func (spkm setPubKeyTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
if err := spkm.setPubKey(ctx, tx, false); err != nil {
return abci.ResponseCheckTx{}, err
func (spkm setPubKeyTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
if err := spkm.setPubKey(ctx, req, false); err != nil {
return tx.Response{}, tx.ResponseCheckTx{}, err
}
return spkm.next.CheckTx(ctx, tx, req)
return spkm.next.CheckTx(ctx, req, checkReq)
}
// DeliverTx implements tx.Handler.DeliverTx.
func (spkm setPubKeyTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
if err := spkm.setPubKey(ctx, tx, false); err != nil {
return abci.ResponseDeliverTx{}, err
func (spkm setPubKeyTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := spkm.setPubKey(ctx, req, false); err != nil {
return tx.Response{}, err
}
return spkm.next.DeliverTx(ctx, tx, req)
return spkm.next.DeliverTx(ctx, req)
}
// SimulateTx implements tx.Handler.SimulateTx.
func (spkm setPubKeyTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
if err := spkm.setPubKey(ctx, sdkTx, true); err != nil {
return tx.ResponseSimulateTx{}, err
func (spkm setPubKeyTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := spkm.setPubKey(ctx, req, true); err != nil {
return tx.Response{}, err
}
return spkm.next.SimulateTx(ctx, sdkTx, req)
return spkm.next.SimulateTx(ctx, req)
}
var _ tx.Handler = validateSigCountTxHandler{}
@ -170,10 +170,10 @@ func ValidateSigCountMiddleware(ak AccountKeeper) tx.Middleware {
}
}
func (vscd validateSigCountTxHandler) checkSigCount(ctx context.Context, tx sdk.Tx) error {
func (vscd validateSigCountTxHandler) checkSigCount(ctx context.Context, req tx.Request) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
sigTx, ok := tx.(authsigning.SigVerifiableTx)
sigTx, ok := req.Tx.(authsigning.SigVerifiableTx)
if !ok {
return sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a sigTx")
}
@ -196,30 +196,30 @@ func (vscd validateSigCountTxHandler) checkSigCount(ctx context.Context, tx sdk.
}
// CheckTx implements tx.Handler.CheckTx.
func (vscd validateSigCountTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
if err := vscd.checkSigCount(ctx, tx); err != nil {
return abci.ResponseCheckTx{}, err
func (vscd validateSigCountTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
if err := vscd.checkSigCount(ctx, req); err != nil {
return tx.Response{}, tx.ResponseCheckTx{}, err
}
return vscd.next.CheckTx(ctx, tx, req)
return vscd.next.CheckTx(ctx, req, checkReq)
}
// DeliverTx implements tx.Handler.DeliverTx.
func (vscd validateSigCountTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
if err := vscd.checkSigCount(ctx, sdkTx); err != nil {
return tx.ResponseSimulateTx{}, err
func (vscd validateSigCountTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := vscd.checkSigCount(ctx, req); err != nil {
return tx.Response{}, err
}
return vscd.next.SimulateTx(ctx, sdkTx, req)
return vscd.next.DeliverTx(ctx, req)
}
// SimulateTx implements tx.Handler.SimulateTx.
func (vscd validateSigCountTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
if err := vscd.checkSigCount(ctx, tx); err != nil {
return abci.ResponseDeliverTx{}, err
func (vscd validateSigCountTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := vscd.checkSigCount(ctx, req); err != nil {
return tx.Response{}, err
}
return vscd.next.DeliverTx(ctx, tx, req)
return vscd.next.SimulateTx(ctx, req)
}
// DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It consumes gas
@ -308,10 +308,10 @@ func SigGasConsumeMiddleware(ak AccountKeeper, sigGasConsumer SignatureVerificat
}
}
func (sgcm sigGasConsumeTxHandler) sigGasConsume(ctx context.Context, tx sdk.Tx, simulate bool) error {
func (sgcm sigGasConsumeTxHandler) sigGasConsume(ctx context.Context, req tx.Request, simulate bool) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
sigTx, ok := tx.(authsigning.SigVerifiableTx)
sigTx, ok := req.Tx.(authsigning.SigVerifiableTx)
if !ok {
return sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
}
@ -359,30 +359,30 @@ func (sgcm sigGasConsumeTxHandler) sigGasConsume(ctx context.Context, tx sdk.Tx,
}
// CheckTx implements tx.Handler.CheckTx.
func (sgcm sigGasConsumeTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
if err := sgcm.sigGasConsume(ctx, tx, false); err != nil {
return abci.ResponseCheckTx{}, err
func (sgcm sigGasConsumeTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
if err := sgcm.sigGasConsume(ctx, req, false); err != nil {
return tx.Response{}, tx.ResponseCheckTx{}, err
}
return sgcm.next.CheckTx(ctx, tx, req)
return sgcm.next.CheckTx(ctx, req, checkReq)
}
// DeliverTx implements tx.Handler.DeliverTx.
func (sgcm sigGasConsumeTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
if err := sgcm.sigGasConsume(ctx, tx, false); err != nil {
return abci.ResponseDeliverTx{}, err
func (sgcm sigGasConsumeTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := sgcm.sigGasConsume(ctx, req, false); err != nil {
return tx.Response{}, err
}
return sgcm.next.DeliverTx(ctx, tx, req)
return sgcm.next.DeliverTx(ctx, req)
}
// SimulateTx implements tx.Handler.SimulateTx.
func (sgcm sigGasConsumeTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
if err := sgcm.sigGasConsume(ctx, sdkTx, true); err != nil {
return tx.ResponseSimulateTx{}, err
func (sgcm sigGasConsumeTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := sgcm.sigGasConsume(ctx, req, true); err != nil {
return tx.Response{}, err
}
return sgcm.next.SimulateTx(ctx, sdkTx, req)
return sgcm.next.SimulateTx(ctx, req)
}
var _ tx.Handler = sigVerificationTxHandler{}
@ -429,13 +429,13 @@ func OnlyLegacyAminoSigners(sigData signing.SignatureData) bool {
}
}
func (svd sigVerificationTxHandler) sigVerify(ctx context.Context, tx sdk.Tx, isReCheckTx, simulate bool) error {
func (svd sigVerificationTxHandler) sigVerify(ctx context.Context, req tx.Request, isReCheckTx, simulate bool) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
// no need to verify signatures on recheck tx
if isReCheckTx {
return nil
}
sigTx, ok := tx.(authsigning.SigVerifiableTx)
sigTx, ok := req.Tx.(authsigning.SigVerifiableTx)
if !ok {
return sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
}
@ -491,7 +491,7 @@ func (svd sigVerificationTxHandler) sigVerify(ctx context.Context, tx sdk.Tx, is
}
if !simulate {
err := authsigning.VerifySignature(pubKey, signerData, sig.Data, svd.signModeHandler, tx)
err := authsigning.VerifySignature(pubKey, signerData, sig.Data, svd.signModeHandler, req.Tx)
if err != nil {
var errMsg string
if OnlyLegacyAminoSigners(sig.Data) {
@ -511,30 +511,30 @@ func (svd sigVerificationTxHandler) sigVerify(ctx context.Context, tx sdk.Tx, is
}
// CheckTx implements tx.Handler.CheckTx.
func (svd sigVerificationTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
if err := svd.sigVerify(ctx, tx, req.Type == abci.CheckTxType_Recheck, false); err != nil {
return abci.ResponseCheckTx{}, err
func (svd sigVerificationTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
if err := svd.sigVerify(ctx, req, checkReq.Type == abci.CheckTxType_Recheck, false); err != nil {
return tx.Response{}, tx.ResponseCheckTx{}, err
}
return svd.next.CheckTx(ctx, tx, req)
return svd.next.CheckTx(ctx, req, checkReq)
}
// DeliverTx implements tx.Handler.DeliverTx.
func (svd sigVerificationTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
if err := svd.sigVerify(ctx, tx, false, false); err != nil {
return abci.ResponseDeliverTx{}, err
func (svd sigVerificationTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := svd.sigVerify(ctx, req, false, false); err != nil {
return tx.Response{}, err
}
return svd.next.DeliverTx(ctx, tx, req)
return svd.next.DeliverTx(ctx, req)
}
// SimulateTx implements tx.Handler.SimulateTx.
func (svd sigVerificationTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
if err := svd.sigVerify(ctx, sdkTx, false, true); err != nil {
return tx.ResponseSimulateTx{}, err
func (svd sigVerificationTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := svd.sigVerify(ctx, req, false, true); err != nil {
return tx.Response{}, err
}
return svd.next.SimulateTx(ctx, sdkTx, req)
return svd.next.SimulateTx(ctx, req)
}
var _ tx.Handler = incrementSequenceTxHandler{}
@ -562,9 +562,9 @@ func IncrementSequenceMiddleware(ak AccountKeeper) tx.Middleware {
}
}
func (isd incrementSequenceTxHandler) incrementSeq(ctx context.Context, tx sdk.Tx) error {
func (isd incrementSequenceTxHandler) incrementSeq(ctx context.Context, req tx.Request) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
sigTx, ok := tx.(authsigning.SigVerifiableTx)
sigTx, ok := req.Tx.(authsigning.SigVerifiableTx)
if !ok {
return sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
}
@ -583,30 +583,30 @@ func (isd incrementSequenceTxHandler) incrementSeq(ctx context.Context, tx sdk.T
}
// CheckTx implements tx.Handler.CheckTx.
func (isd incrementSequenceTxHandler) CheckTx(ctx context.Context, tx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
if err := isd.incrementSeq(ctx, tx); err != nil {
return abci.ResponseCheckTx{}, err
func (isd incrementSequenceTxHandler) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
if err := isd.incrementSeq(ctx, req); err != nil {
return tx.Response{}, tx.ResponseCheckTx{}, err
}
return isd.next.CheckTx(ctx, tx, req)
return isd.next.CheckTx(ctx, req, checkReq)
}
// DeliverTx implements tx.Handler.DeliverTx.
func (isd incrementSequenceTxHandler) DeliverTx(ctx context.Context, tx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
if err := isd.incrementSeq(ctx, tx); err != nil {
return abci.ResponseDeliverTx{}, err
func (isd incrementSequenceTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := isd.incrementSeq(ctx, req); err != nil {
return tx.Response{}, err
}
return isd.next.DeliverTx(ctx, tx, req)
return isd.next.DeliverTx(ctx, req)
}
// SimulateTx implements tx.Handler.SimulateTx.
func (isd incrementSequenceTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
if err := isd.incrementSeq(ctx, sdkTx); err != nil {
return tx.ResponseSimulateTx{}, err
func (isd incrementSequenceTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
if err := isd.incrementSeq(ctx, req); err != nil {
return tx.Response{}, err
}
return isd.next.SimulateTx(ctx, sdkTx, req)
return isd.next.SimulateTx(ctx, req)
}
// GetSignerAcc returns an account for a given address that is expected to sign

View File

@ -55,7 +55,7 @@ func (s *MWTestSuite) TestSetPubKey() {
testTx, _, err := s.createTestTx(txBuilder, privs, accNums, accSeqs, ctx.ChainID())
require.NoError(err)
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), testTx, abci.RequestDeliverTx{})
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx})
require.NoError(err)
// Require that all accounts have pubkey set after middleware runs
@ -183,9 +183,9 @@ func (s *MWTestSuite) TestSigVerification() {
s.Require().NoError(err)
if tc.recheck {
_, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), testTx, abci.RequestCheckTx{Type: abci.CheckTxType_Recheck})
_, _, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{Type: abci.CheckTxType_Recheck})
} else {
_, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), testTx, abci.RequestCheckTx{})
_, _, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{})
}
if tc.shouldErr {
s.Require().NotNil(err, "TestCase %d: %s did not error as expected", i, tc.name)
@ -278,9 +278,9 @@ func (s *MWTestSuite) TestSigVerification_ExplicitAmino() {
s.Require().NoError(err)
if tc.recheck {
_, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), testTx, abci.RequestCheckTx{Type: abci.CheckTxType_Recheck})
_, _, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{Type: abci.CheckTxType_Recheck})
} else {
_, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), testTx, abci.RequestCheckTx{})
_, _, err = txHandler.CheckTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx}, tx.RequestCheckTx{})
}
if tc.shouldErr {
s.Require().NotNil(err, "TestCase %d: %s did not error as expected", i, tc.name)
@ -353,7 +353,7 @@ func (s *MWTestSuite) runSigMiddlewares(params types.Params, _ bool, privs ...cr
// Determine gas consumption of txhandler with default params
before := ctx.GasMeter().GasConsumed()
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), testTx, abci.RequestDeliverTx{})
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx.Request{Tx: testTx})
after := ctx.GasMeter().GasConsumed()
return after - before, err
@ -401,9 +401,9 @@ func (s *MWTestSuite) TestIncrementSequenceMiddleware() {
for i, tc := range testCases {
var err error
if tc.simulate {
_, err = txHandler.SimulateTx(sdk.WrapSDKContext(tc.ctx), testTx, tx.RequestSimulateTx{})
_, err = txHandler.SimulateTx(sdk.WrapSDKContext(tc.ctx), tx.Request{Tx: testTx})
} else {
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(tc.ctx), testTx, abci.RequestDeliverTx{})
_, err = txHandler.DeliverTx(sdk.WrapSDKContext(tc.ctx), tx.Request{Tx: testTx})
}
s.Require().NoError(err, "unexpected error; tc #%d, %v", i, tc)

View File

@ -6,12 +6,12 @@ import (
"testing"
"github.com/stretchr/testify/suite"
"github.com/tendermint/tendermint/abci/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
@ -70,7 +70,16 @@ func (s *MWTestSuite) SetupTest(isCheckTx bool) sdk.Context {
msr := middleware.NewMsgServiceRouter(encodingConfig.InterfaceRegistry)
testdata.RegisterMsgServer(msr, testdata.MsgServerImpl{})
legacyRouter := middleware.NewLegacyRouter()
legacyRouter.AddRoute(sdk.NewRoute((&testdata.TestMsg{}).Route(), func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { return &sdk.Result{}, nil }))
legacyRouter.AddRoute(sdk.NewRoute((&testdata.TestMsg{}).Route(), func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
any, err := codectypes.NewAnyWithValue(msg)
if err != nil {
return nil, err
}
return &sdk.Result{
MsgResponses: []*codectypes.Any{any},
}, nil
}))
txHandler, err := middleware.NewDefaultTxHandler(middleware.TxHandlerOptions{
Debug: s.app.Trace(),
MsgServiceRouter: msr,
@ -174,8 +183,8 @@ func (s *MWTestSuite) runTestCase(ctx sdk.Context, txBuilder client.TxBuilder, p
// Theoretically speaking, middleware unit tests should only test
// middlewares, but here we sometimes also test the tx creation
// process.
tx, _, txErr := s.createTestTx(txBuilder, privs, accNums, accSeqs, chainID)
newCtx, txHandlerErr := s.txHandler.DeliverTx(sdk.WrapSDKContext(ctx), tx, types.RequestDeliverTx{})
testTx, _, txErr := s.createTestTx(txBuilder, privs, accNums, accSeqs, chainID)
newCtx, txHandlerErr := s.txHandler.DeliverTx(sdk.WrapSDKContext(ctx), txtypes.Request{Tx: testTx})
if tc.expPass {
s.Require().NoError(txErr)

View File

@ -3,8 +3,6 @@ package middleware
import (
"context"
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/x/auth/types"
@ -26,69 +24,46 @@ func NewTipMiddleware(bankKeeper types.BankKeeper) tx.Middleware {
var _ tx.Handler = tipsTxHandler{}
// CheckTx implements tx.Handler.CheckTx.
func (txh tipsTxHandler) CheckTx(ctx context.Context, sdkTx sdk.Tx, req abci.RequestCheckTx) (abci.ResponseCheckTx, error) {
res, err := txh.next.CheckTx(ctx, sdkTx, req)
if err != nil {
return abci.ResponseCheckTx{}, err
}
func (txh tipsTxHandler) CheckTx(ctx context.Context, req tx.Request, checkTx tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
res, resCheckTx, err := txh.next.CheckTx(ctx, req, checkTx)
res, err = txh.transferTip(ctx, req, res, err)
tipTx, ok := sdkTx.(tx.TipTx)
if !ok || tipTx.GetTip() == nil {
return res, err
}
if err := txh.transferTip(ctx, tipTx); err != nil {
return abci.ResponseCheckTx{}, err
}
return res, err
return res, resCheckTx, err
}
// DeliverTx implements tx.Handler.DeliverTx.
func (txh tipsTxHandler) DeliverTx(ctx context.Context, sdkTx sdk.Tx, req abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) {
res, err := txh.next.DeliverTx(ctx, sdkTx, req)
if err != nil {
return abci.ResponseDeliverTx{}, err
}
func (txh tipsTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
res, err := txh.next.DeliverTx(ctx, req)
tipTx, ok := sdkTx.(tx.TipTx)
if !ok || tipTx.GetTip() == nil {
return res, err
}
if err := txh.transferTip(ctx, tipTx); err != nil {
return abci.ResponseDeliverTx{}, err
}
return res, err
return txh.transferTip(ctx, req, res, err)
}
// SimulateTx implements tx.Handler.SimulateTx method.
func (txh tipsTxHandler) SimulateTx(ctx context.Context, sdkTx sdk.Tx, req tx.RequestSimulateTx) (tx.ResponseSimulateTx, error) {
res, err := txh.next.SimulateTx(ctx, sdkTx, req)
if err != nil {
return tx.ResponseSimulateTx{}, err
}
func (txh tipsTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
res, err := txh.next.SimulateTx(ctx, req)
tipTx, ok := sdkTx.(tx.TipTx)
return txh.transferTip(ctx, req, res, err)
}
// transferTip transfers the tip from the tipper to the fee payer.
func (txh tipsTxHandler) transferTip(ctx context.Context, req tx.Request, res tx.Response, err error) (tx.Response, error) {
tipTx, ok := req.Tx.(tx.TipTx)
// No-op if the tx doesn't have tips.
if !ok || tipTx.GetTip() == nil {
return res, err
}
if err := txh.transferTip(ctx, tipTx); err != nil {
return tx.ResponseSimulateTx{}, err
}
return res, err
}
// transferTip transfers the tip from the tipper to the fee payer.
func (txh tipsTxHandler) transferTip(ctx context.Context, tipTx tx.TipTx) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
tipper, err := sdk.AccAddressFromBech32(tipTx.GetTip().Tipper)
if err != nil {
return err
return tx.Response{}, err
}
return txh.bankKeeper.SendCoins(sdkCtx, tipper, tipTx.FeePayer(), tipTx.GetTip().Amount)
err = txh.bankKeeper.SendCoins(sdkCtx, tipper, tipTx.FeePayer(), tipTx.GetTip().Amount)
if err != nil {
return tx.Response{}, err
}
return res, nil
}

View File

@ -129,6 +129,7 @@ func (s IntegrationTestSuite) TestSimulateTx_GRPC() {
// - Sending Amount to recipient: coin_spent, coin_received, transfer and message.sender=<val1>
// - Msg events: message.module=bank and message.action=/cosmos.bank.v1beta1.MsgSend
s.Require().Equal(len(res.GetResult().GetEvents()), 13)
s.Require().Len(res.GetResult().MsgResponses, 1)
// Check the result and gas used are correct.
s.Require().True(res.GetGasInfo().GetGasUsed() > 0) // Gas used sometimes change, just check it's not empty.
}
@ -171,7 +172,8 @@ func (s IntegrationTestSuite) TestSimulateTx_GRPCGateway() {
s.Require().NoError(err)
// Check the result and gas used are correct.
s.Require().Equal(len(result.GetResult().GetEvents()), 13) // See TestSimulateTx_GRPC for the 13 events.
s.Require().True(result.GetGasInfo().GetGasUsed() > 0) // Gas used sometimes change, just check it's not empty.
s.Require().Len(result.GetResult().MsgResponses, 1)
s.Require().True(result.GetGasInfo().GetGasUsed() > 0) // Gas used sometimes change, just check it's not empty.
}
})
}