Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Change tx.Handler interface to remove code duplication #10484

Closed
amaury1093 opened this issue Nov 2, 2021 · 4 comments · Fixed by #10527
Closed

Change tx.Handler interface to remove code duplication #10484

amaury1093 opened this issue Nov 2, 2021 · 4 comments · Fixed by #10527
Assignees

Comments

@amaury1093
Copy link
Contributor

amaury1093 commented Nov 2, 2021

Summary

Make the middleware's tx.Handler interface as simple as possible.

Problem

The current tx.Handler interface has 3 methods, and because of their signatures, it creates code duplication.

Current interface:

// 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)
}

Example of duplication here and #10208 (comment).

Solution

Proposal:

We propose a common tx.Response type for the 3 methods

package tx // types/tx

type Handler interface {
  func CheckTx(ctx context.Content, tx sdk.Tx, checkReq tx.CheckRequest) (res tx.Response, checkRes tx.CheckResponse, error error)
  func DeliverTx(ctx context.Content, tx sdk.Tx) (res tx.Response, error error)
  func SimulateTx(ctx context.Content, tx sdk.Tx) (res tx.Response, error error)
}

type Response struct {
  GasInfo sdk.GasInfo
  MsgResponses  codectypes.Any[] // Represents each Msg service handler's response type. Will get proto-serialized into the `Data` field in ABCI, see note #2
  Log string
  Events sdk.Events
}

type CheckRequest {
  Type CheckTxType // Check or Recheck
}

type CheckResponse {
  Priority uint32
}

Notes

  1. Alternative solution is to merge the tx types in ABCI Can we merge CheckTx and DeliverTx response types tendermint/spec#342
  2. For rationale to use Any, see [types.TxMsgData, types.MsgData]: consider using google.Protobuf.Any instead of sdk.MsgData #10496
@aaronc
Copy link
Member

aaronc commented Nov 8, 2021

This seems reasonable.

We could even go a step further and lift GasInfo and Events into Response.

type Response struct {
  GasWanted uint64
  GasUsed uint64
  MsgResponses  codectypes.Any[] // Represents each Msg service handler's response type. Will get proto-serialized into the `Data` field in ABCI, see note #2
  Log string
  Events []Event
}

Events still depends on tendermint types, and also there has been some recent discussion about bypassing tendermint events altogether for efficiency. But maybe that's a separate conversation.

@atheeshp
Copy link
Contributor

atheeshp commented Nov 12, 2021

@aaronc we need TxBytes in few middleware handlers (ref), @AmauryM and I are aligning on a solution to add tx.Request like below

type tx.Request struct {
    Tx sdk.Tx 
    TxBytes []byte
}

Hence the tx.Handler interface look like

type Handler interface {
  func CheckTx(ctx context.Content, req tx.Request, checkReq tx.CheckRequest) (res tx.Response, checkRes tx.CheckResponse, error error)
  func DeliverTx(ctx context.Content, req tx.Request) (res tx.Response, error error)
  func SimulateTx(ctx context.Content, req tx.Request) (res tx.Response, error error)
}

wdyt?

@aaronc
Copy link
Member

aaronc commented Nov 16, 2021

@aaronc we need TxBytes in few middleware handlers (ref), @AmauryM and I are aligning on a solution to add tx.Request like below

type tx.Request struct {
    Tx sdk.Tx 
    TxBytes []byte
}

Hence the tx.Handler interface look like

type Handler interface {
  func CheckTx(ctx context.Content, req tx.Request, checkReq tx.CheckRequest) (res tx.Response, checkRes tx.CheckResponse, error error)
  func DeliverTx(ctx context.Content, req tx.Request) (res tx.Response, error error)
  func SimulateTx(ctx context.Content, req tx.Request) (res tx.Response, error error)
}

wdyt?

This sounds like the right plan @atheeshp.

I would also like to pull TxDecoder out of BaseApp and into the Middleware so this solution will allow that. Basically BaseApp will call the root Handler with only TxBytes and Tx set to nil and the first middleware will do the decoding. There is actually a use case for having one middleware before tx decoding that we can handle with this approach.

@amaury1093
Copy link
Contributor Author

amaury1093 commented Nov 16, 2021

Makes sense. The refactor PR is getting big, I would propose to the the TxDecoderMiddleware in a separate PR.

#10610

@amaury1093 amaury1093 self-assigned this Nov 25, 2021
@mergify mergify bot closed this as completed in #10527 Dec 2, 2021
mergify bot pushed a commit that referenced this issue Dec 2, 2021
<!--
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)
blewater pushed a commit to e-money/cosmos-sdk that referenced this issue Dec 8, 2021
…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: cosmos#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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants