Add tx broadcast gRPC endpoint (#7852)

* WIP tx/broadcast grpc endpoint

* fix lint

* fix proto lint

* Update service.proto

* resolve conflicts

* update service.proto

* Update service.proto

* review changes

* proto lint

* Switch to txraw

* Add check breaking at the end

* Fix broadcast

* Send Msg on SetupSuite

* Remove proto-check-breaking

* 1 validator in test

* Add grpc server tests for broadcast

* Fix grpc server tests

* Add some changes

* Add ress comments

* Add table tests for tx service

* Add test for mode

* Add simulate tests

* Add build flag back

* Revert custom stringer for enum

* Remove stray logs

* Use /txs/{hash}

Co-authored-by: Amaury Martiny <amaury.martiny@protonmail.com>
Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>
This commit is contained in:
MD Aleem 2020-12-02 23:20:40 +05:30 committed by GitHub
parent f57828c091
commit b6c8d5ea9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1146 additions and 206 deletions

View File

@ -357,7 +357,7 @@ devdoc-update:
### Protobuf ###
###############################################################################
proto-all: proto-format proto-lint proto-check-breaking proto-gen
proto-all: proto-format proto-lint proto-gen
proto-gen:
@echo "Generating Protobuf files"

View File

@ -7,10 +7,13 @@ import (
"github.com/tendermint/tendermint/crypto/tmhash"
"github.com/tendermint/tendermint/mempool"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/cosmos/cosmos-sdk/client/flags"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx"
)
// BroadcastTx broadcasts a transactions either synchronously or asynchronously
@ -142,3 +145,36 @@ func (ctx Context) BroadcastTxAsync(txBytes []byte) (*sdk.TxResponse, error) {
return sdk.NewResponseFormatBroadcastTx(res), err
}
// TxServiceBroadcast is a helper function to broadcast a Tx with the correct gRPC types
// from the tx service. Calls `clientCtx.BroadcastTx` under the hood.
func TxServiceBroadcast(grpcCtx context.Context, clientCtx Context, req *tx.BroadcastTxRequest) (*tx.BroadcastTxResponse, error) {
if req == nil || req.TxBytes == nil {
return nil, status.Error(codes.InvalidArgument, "invalid empty tx")
}
clientCtx = clientCtx.WithBroadcastMode(normalizeBroadcastMode(req.Mode))
resp, err := clientCtx.BroadcastTx(req.TxBytes)
if err != nil {
return nil, err
}
return &tx.BroadcastTxResponse{
TxResponse: resp,
}, nil
}
// normalizeBroadcastMode converts a broadcast mode into a normalized string
// to be passed into the clientCtx.
func normalizeBroadcastMode(mode tx.BroadcastMode) string {
switch mode {
case tx.BroadcastMode_BROADCAST_MODE_ASYNC:
return "async"
case tx.BroadcastMode_BROADCAST_MODE_BLOCK:
return "block"
case tx.BroadcastMode_BROADCAST_MODE_SYNC:
return "sync"
default:
return "unspecified"
}
}

View File

@ -3,6 +3,7 @@ package client
import (
gocontext "context"
"fmt"
"reflect"
"strconv"
gogogrpc "github.com/gogo/protobuf/grpc"
@ -12,10 +13,10 @@ import (
"google.golang.org/grpc/encoding/proto"
"google.golang.org/grpc/metadata"
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
"github.com/cosmos/cosmos-sdk/codec/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
"github.com/cosmos/cosmos-sdk/types/tx"
)
var _ gogogrpc.ClientConn = Context{}
@ -23,7 +24,37 @@ var _ gogogrpc.ClientConn = Context{}
var protoCodec = encoding.GetCodec(proto.Name)
// Invoke implements the grpc ClientConn.Invoke method
func (ctx Context) Invoke(grpcCtx gocontext.Context, method string, args, reply interface{}, opts ...grpc.CallOption) error {
func (ctx Context) Invoke(grpcCtx gocontext.Context, method string, args, reply interface{}, opts ...grpc.CallOption) (err error) {
// Two things can happen here:
// 1. either we're broadcasting a Tx, in which call we call Tendermint's broadcast endpoint directly,
// 2. or we are querying for state, in which case we call ABCI's Query.
// In both cases, we don't allow empty request args (it will panic unexpectedly).
if reflect.ValueOf(args).IsNil() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "request cannot be nil")
}
// Case 1. Broadcasting a Tx.
if isBroadcast(method) {
req, ok := args.(*tx.BroadcastTxRequest)
if !ok {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "expected %T, got %T", (*tx.BroadcastTxRequest)(nil), args)
}
res, ok := reply.(*tx.BroadcastTxResponse)
if !ok {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "expected %T, got %T", (*tx.BroadcastTxResponse)(nil), args)
}
broadcastRes, err := TxServiceBroadcast(grpcCtx, ctx, req)
if err != nil {
return err
}
*res = *broadcastRes
return err
}
// Case 2. Querying state.
reqBz, err := protoCodec.Marshal(args)
if err != nil {
return err
@ -86,3 +117,7 @@ func (ctx Context) Invoke(grpcCtx gocontext.Context, method string, args, reply
func (Context) NewStream(gocontext.Context, *grpc.StreamDesc, string, ...grpc.CallOption) (grpc.ClientStream, error) {
return nil, fmt.Errorf("streaming rpc not supported")
}
func isBroadcast(method string) bool {
return method == "/cosmos.tx.v1beta1.Service/BroadcastTx"
}

View File

@ -31,7 +31,7 @@ Some modules expose legacy `POST` endpoints to generate unsigned transactions fo
| Legacy REST Endpoint | Description | New gGPC-gateway REST Endpoint |
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `GET /txs/{hash}` | Query tx by hash | `GET /cosmos/tx/v1beta1/tx/{hash}` |
| `GET /txs/{hash}` | Query tx by hash | `GET /cosmos/tx/v1beta1/txs/{hash}` |
| `GET /txs` | Query tx by events | `GET /cosmos/tx/v1beta1/txs` |
| `POST /txs` | Broadcast tx | `POST /cosmos/tx/v1beta1/txs` |
| `POST /txs/encode` | Encodes an Amino JSON tx to an Amino binary tx | N/A, use Protobuf directly |

View File

@ -4,6 +4,7 @@ package cosmos.tx.v1beta1;
import "google/api/annotations.proto";
import "cosmos/base/abci/v1beta1/abci.proto";
import "cosmos/tx/v1beta1/tx.proto";
import "gogoproto/gogo.proto";
import "cosmos/base/query/v1beta1/pagination.proto";
option go_package = "github.com/cosmos/cosmos-sdk/types/tx";
@ -12,13 +13,22 @@ option go_package = "github.com/cosmos/cosmos-sdk/types/tx";
service Service {
// Simulate simulates executing a transaction for estimating gas usage.
rpc Simulate(SimulateRequest) returns (SimulateResponse) {
option (google.api.http).post = "/cosmos/tx/v1beta1/simulate";
option (google.api.http) = {
post: "/cosmos/tx/v1beta1/simulate"
body: "*"
};
}
// GetTx fetches a tx by hash.
rpc GetTx(GetTxRequest) returns (GetTxResponse) {
option (google.api.http).get = "/cosmos/tx/v1beta1/tx/{hash}";
option (google.api.http).get = "/cosmos/tx/v1beta1/txs/{hash}";
}
// BroadcastTx broadcast transaction.
rpc BroadcastTx(BroadcastTxRequest) returns (BroadcastTxResponse) {
option (google.api.http) = {
post: "/cosmos/tx/v1beta1/txs"
body: "*"
};
}
// GetTxsEvent fetches txs by event.
rpc GetTxsEvent(GetTxsEventRequest) returns (GetTxsEventResponse) {
option (google.api.http).get = "/cosmos/tx/v1beta1/txs";
@ -45,6 +55,36 @@ message GetTxsEventResponse {
cosmos.base.query.v1beta1.PageResponse pagination = 3;
}
// BroadcastTxRequest is the request type for the Service.BroadcastTxRequest
// RPC method.
message BroadcastTxRequest {
// tx_bytes is the raw transaction.
bytes tx_bytes = 1;
BroadcastMode mode = 2;
}
// BroadcastMode specifies the broadcast mode for the TxService.Broadcast RPC method.
enum BroadcastMode {
// zero-value for mode ordering
BROADCAST_MODE_UNSPECIFIED = 0;
// BROADCAST_MODE_BLOCK defines a tx broadcasting mode where the client waits for
// the tx to be committed in a block.
BROADCAST_MODE_BLOCK = 1;
// BROADCAST_MODE_SYNC defines a tx broadcasting mode where the client waits for
// a CheckTx execution response only.
BROADCAST_MODE_SYNC = 2;
// BROADCAST_MODE_ASYNC defines a tx broadcasting mode where the client returns
// immediately.
BROADCAST_MODE_ASYNC = 3;
}
// BroadcastTxResponse is the response type for the
// Service.BroadcastTx method.
message BroadcastTxResponse {
// tx_response is the queried TxResponses.
cosmos.base.abci.v1beta1.TxResponse tx_response = 1;
}
// SimulateRequest is the request type for the Service.Simulate
// RPC method.
message SimulateRequest {

View File

@ -13,54 +13,64 @@ import (
"google.golang.org/grpc/metadata"
rpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
clienttx "github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/testutil/network"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
"github.com/cosmos/cosmos-sdk/types/tx"
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
)
type IntegrationTestSuite struct {
suite.Suite
cfg network.Config
network *network.Network
conn *grpc.ClientConn
}
func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite")
s.network = network.New(s.T(), network.DefaultConfig())
s.cfg = network.DefaultConfig()
s.network = network.New(s.T(), s.cfg)
s.Require().NotNil(s.network)
_, err := s.network.WaitForHeight(2)
s.Require().NoError(err)
val0 := s.network.Validators[0]
s.conn, err = grpc.Dial(
val0.AppConfig.GRPC.Address,
grpc.WithInsecure(), // Or else we get "no transport security set"
)
s.Require().NoError(err)
}
func (s *IntegrationTestSuite) TearDownSuite() {
s.T().Log("tearing down integration test suite")
s.conn.Close()
s.network.Cleanup()
}
func (s *IntegrationTestSuite) TestGRPCServer() {
val0 := s.network.Validators[0]
conn, err := grpc.Dial(
val0.AppConfig.GRPC.Address,
grpc.WithInsecure(), // Or else we get "no transport security set"
)
s.Require().NoError(err)
defer conn.Close()
func (s *IntegrationTestSuite) TestGRPCServer_TestService() {
// gRPC query to test service should work
testClient := testdata.NewQueryClient(conn)
testClient := testdata.NewQueryClient(s.conn)
testRes, err := testClient.Echo(context.Background(), &testdata.EchoRequest{Message: "hello"})
s.Require().NoError(err)
s.Require().Equal("hello", testRes.Message)
}
func (s *IntegrationTestSuite) TestGRPCServer_BankBalance() {
val0 := s.network.Validators[0]
// gRPC query to bank service should work
denom := fmt.Sprintf("%stoken", val0.Moniker)
bankClient := banktypes.NewQueryClient(conn)
bankClient := banktypes.NewQueryClient(s.conn)
var header metadata.MD
bankRes, err := bankClient.Balance(
context.Background(),
@ -83,9 +93,11 @@ func (s *IntegrationTestSuite) TestGRPCServer() {
)
blockHeight = header.Get(grpctypes.GRPCBlockHeightHeader)
s.Require().Equal([]string{"1"}, blockHeight)
}
func (s *IntegrationTestSuite) TestGRPCServer_Reflection() {
// Test server reflection
reflectClient := rpb.NewServerReflectionClient(conn)
reflectClient := rpb.NewServerReflectionClient(s.conn)
stream, err := reflectClient.ServerReflectionInfo(context.Background(), grpc.WaitForReady(true))
s.Require().NoError(err)
s.Require().NoError(stream.Send(&rpb.ServerReflectionRequest{
@ -100,11 +112,13 @@ func (s *IntegrationTestSuite) TestGRPCServer() {
}
// Make sure the following services are present
s.Require().True(servicesMap["cosmos.bank.v1beta1.Query"])
}
func (s *IntegrationTestSuite) TestGRPCServer_GetTxsEvent() {
// Query the tx via gRPC without pagination. This used to panic, see
// https://github.com/cosmos/cosmos-sdk/issues/8038.
txServiceClient := txtypes.NewServiceClient(conn)
_, err = txServiceClient.GetTxsEvent(
txServiceClient := txtypes.NewServiceClient(s.conn)
_, err := txServiceClient.GetTxsEvent(
context.Background(),
&tx.GetTxsEventRequest{
Events: []string{"message.action=send"},
@ -115,6 +129,50 @@ func (s *IntegrationTestSuite) TestGRPCServer() {
s.Require().NoError(err)
}
func (s *IntegrationTestSuite) TestGRPCServer_BroadcastTx() {
val0 := s.network.Validators[0]
// prepare txBuilder with msg
txBuilder := val0.ClientCtx.TxConfig.NewTxBuilder()
feeAmount := sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 10)}
gasLimit := testdata.NewTestGasLimit()
s.Require().NoError(
txBuilder.SetMsgs(&banktypes.MsgSend{
FromAddress: val0.Address.String(),
ToAddress: val0.Address.String(),
Amount: sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 10)},
}),
)
txBuilder.SetFeeAmount(feeAmount)
txBuilder.SetGasLimit(gasLimit)
// setup txFactory
txFactory := clienttx.Factory{}.
WithChainID(val0.ClientCtx.ChainID).
WithKeybase(val0.ClientCtx.Keyring).
WithTxConfig(val0.ClientCtx.TxConfig).
WithSignMode(signing.SignMode_SIGN_MODE_DIRECT)
// Sign Tx.
err := authclient.SignTx(txFactory, val0.ClientCtx, val0.Moniker, txBuilder, false)
s.Require().NoError(err)
txBytes, err := val0.ClientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
s.Require().NoError(err)
// Broadcast the tx via gRPC.
queryClient := tx.NewServiceClient(s.conn)
grpcRes, err := queryClient.BroadcastTx(
context.Background(),
&tx.BroadcastTxRequest{
Mode: tx.BroadcastMode_BROADCAST_MODE_SYNC,
TxBytes: txBytes,
},
)
s.Require().NoError(err)
s.Require().Equal(uint32(0), grpcRes.TxResponse.Code)
}
// Test and enforce that we upfront reject any connections to baseapp containing
// invalid initial x-cosmos-block-height that aren't positive and in the range [0, max(int64)]
// See issue https://github.com/cosmos/cosmos-sdk/issues/7662.

View File

@ -8,6 +8,7 @@ import (
fmt "fmt"
types "github.com/cosmos/cosmos-sdk/types"
query "github.com/cosmos/cosmos-sdk/types/query"
_ "github.com/gogo/protobuf/gogoproto"
grpc1 "github.com/gogo/protobuf/grpc"
proto "github.com/gogo/protobuf/proto"
_ "google.golang.org/genproto/googleapis/api/annotations"
@ -30,6 +31,45 @@ var _ = math.Inf
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// BroadcastMode specifies the broadcast mode for the TxService.Broadcast RPC method.
type BroadcastMode int32
const (
// zero-value for mode ordering
BroadcastMode_BROADCAST_MODE_UNSPECIFIED BroadcastMode = 0
// BROADCAST_MODE_BLOCK defines a tx broadcasting mode where the client waits for
// the tx to be committed in a block.
BroadcastMode_BROADCAST_MODE_BLOCK BroadcastMode = 1
// BROADCAST_MODE_SYNC defines a tx broadcasting mode where the client waits for
// a CheckTx execution response only.
BroadcastMode_BROADCAST_MODE_SYNC BroadcastMode = 2
// BROADCAST_MODE_ASYNC defines a tx broadcasting mode where the client returns
// immediately.
BroadcastMode_BROADCAST_MODE_ASYNC BroadcastMode = 3
)
var BroadcastMode_name = map[int32]string{
0: "BROADCAST_MODE_UNSPECIFIED",
1: "BROADCAST_MODE_BLOCK",
2: "BROADCAST_MODE_SYNC",
3: "BROADCAST_MODE_ASYNC",
}
var BroadcastMode_value = map[string]int32{
"BROADCAST_MODE_UNSPECIFIED": 0,
"BROADCAST_MODE_BLOCK": 1,
"BROADCAST_MODE_SYNC": 2,
"BROADCAST_MODE_ASYNC": 3,
}
func (x BroadcastMode) String() string {
return proto.EnumName(BroadcastMode_name, int32(x))
}
func (BroadcastMode) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_e0b00a618705eca7, []int{0}
}
// GetTxsEventRequest is the request type for the Service.TxsByEvents
// RPC method.
type GetTxsEventRequest struct {
@ -151,6 +191,108 @@ func (m *GetTxsEventResponse) GetPagination() *query.PageResponse {
return nil
}
// BroadcastTxRequest is the request type for the Service.BroadcastTxRequest
// RPC method.
type BroadcastTxRequest struct {
// tx_bytes is the raw transaction.
TxBytes []byte `protobuf:"bytes,1,opt,name=tx_bytes,json=txBytes,proto3" json:"tx_bytes,omitempty"`
Mode BroadcastMode `protobuf:"varint,2,opt,name=mode,proto3,enum=cosmos.tx.v1beta1.BroadcastMode" json:"mode,omitempty"`
}
func (m *BroadcastTxRequest) Reset() { *m = BroadcastTxRequest{} }
func (m *BroadcastTxRequest) String() string { return proto.CompactTextString(m) }
func (*BroadcastTxRequest) ProtoMessage() {}
func (*BroadcastTxRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_e0b00a618705eca7, []int{2}
}
func (m *BroadcastTxRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *BroadcastTxRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_BroadcastTxRequest.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *BroadcastTxRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_BroadcastTxRequest.Merge(m, src)
}
func (m *BroadcastTxRequest) XXX_Size() int {
return m.Size()
}
func (m *BroadcastTxRequest) XXX_DiscardUnknown() {
xxx_messageInfo_BroadcastTxRequest.DiscardUnknown(m)
}
var xxx_messageInfo_BroadcastTxRequest proto.InternalMessageInfo
func (m *BroadcastTxRequest) GetTxBytes() []byte {
if m != nil {
return m.TxBytes
}
return nil
}
func (m *BroadcastTxRequest) GetMode() BroadcastMode {
if m != nil {
return m.Mode
}
return BroadcastMode_BROADCAST_MODE_UNSPECIFIED
}
// BroadcastTxResponse is the response type for the
// Service.BroadcastTx method.
type BroadcastTxResponse struct {
// tx_response is the queried TxResponses.
TxResponse *types.TxResponse `protobuf:"bytes,1,opt,name=tx_response,json=txResponse,proto3" json:"tx_response,omitempty"`
}
func (m *BroadcastTxResponse) Reset() { *m = BroadcastTxResponse{} }
func (m *BroadcastTxResponse) String() string { return proto.CompactTextString(m) }
func (*BroadcastTxResponse) ProtoMessage() {}
func (*BroadcastTxResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_e0b00a618705eca7, []int{3}
}
func (m *BroadcastTxResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *BroadcastTxResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_BroadcastTxResponse.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *BroadcastTxResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_BroadcastTxResponse.Merge(m, src)
}
func (m *BroadcastTxResponse) XXX_Size() int {
return m.Size()
}
func (m *BroadcastTxResponse) XXX_DiscardUnknown() {
xxx_messageInfo_BroadcastTxResponse.DiscardUnknown(m)
}
var xxx_messageInfo_BroadcastTxResponse proto.InternalMessageInfo
func (m *BroadcastTxResponse) GetTxResponse() *types.TxResponse {
if m != nil {
return m.TxResponse
}
return nil
}
// SimulateRequest is the request type for the Service.Simulate
// RPC method.
type SimulateRequest struct {
@ -162,7 +304,7 @@ func (m *SimulateRequest) Reset() { *m = SimulateRequest{} }
func (m *SimulateRequest) String() string { return proto.CompactTextString(m) }
func (*SimulateRequest) ProtoMessage() {}
func (*SimulateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_e0b00a618705eca7, []int{2}
return fileDescriptor_e0b00a618705eca7, []int{4}
}
func (m *SimulateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -211,7 +353,7 @@ func (m *SimulateResponse) Reset() { *m = SimulateResponse{} }
func (m *SimulateResponse) String() string { return proto.CompactTextString(m) }
func (*SimulateResponse) ProtoMessage() {}
func (*SimulateResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_e0b00a618705eca7, []int{3}
return fileDescriptor_e0b00a618705eca7, []int{5}
}
func (m *SimulateResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -265,7 +407,7 @@ func (m *GetTxRequest) Reset() { *m = GetTxRequest{} }
func (m *GetTxRequest) String() string { return proto.CompactTextString(m) }
func (*GetTxRequest) ProtoMessage() {}
func (*GetTxRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_e0b00a618705eca7, []int{4}
return fileDescriptor_e0b00a618705eca7, []int{6}
}
func (m *GetTxRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -313,7 +455,7 @@ func (m *GetTxResponse) Reset() { *m = GetTxResponse{} }
func (m *GetTxResponse) String() string { return proto.CompactTextString(m) }
func (*GetTxResponse) ProtoMessage() {}
func (*GetTxResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_e0b00a618705eca7, []int{5}
return fileDescriptor_e0b00a618705eca7, []int{7}
}
func (m *GetTxResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -357,8 +499,11 @@ func (m *GetTxResponse) GetTxResponse() *types.TxResponse {
}
func init() {
proto.RegisterEnum("cosmos.tx.v1beta1.BroadcastMode", BroadcastMode_name, BroadcastMode_value)
proto.RegisterType((*GetTxsEventRequest)(nil), "cosmos.tx.v1beta1.GetTxsEventRequest")
proto.RegisterType((*GetTxsEventResponse)(nil), "cosmos.tx.v1beta1.GetTxsEventResponse")
proto.RegisterType((*BroadcastTxRequest)(nil), "cosmos.tx.v1beta1.BroadcastTxRequest")
proto.RegisterType((*BroadcastTxResponse)(nil), "cosmos.tx.v1beta1.BroadcastTxResponse")
proto.RegisterType((*SimulateRequest)(nil), "cosmos.tx.v1beta1.SimulateRequest")
proto.RegisterType((*SimulateResponse)(nil), "cosmos.tx.v1beta1.SimulateResponse")
proto.RegisterType((*GetTxRequest)(nil), "cosmos.tx.v1beta1.GetTxRequest")
@ -368,43 +513,54 @@ func init() {
func init() { proto.RegisterFile("cosmos/tx/v1beta1/service.proto", fileDescriptor_e0b00a618705eca7) }
var fileDescriptor_e0b00a618705eca7 = []byte{
// 563 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xcd, 0x6e, 0xd3, 0x40,
0x10, 0xae, 0x1d, 0x48, 0xdb, 0x49, 0x11, 0xb0, 0x88, 0x2a, 0x32, 0xc5, 0x0d, 0x4e, 0xd3, 0x56,
0x48, 0xd8, 0x6a, 0xb8, 0xf4, 0x80, 0x84, 0x84, 0x54, 0x22, 0x6e, 0xc8, 0xed, 0x89, 0x4b, 0xb5,
0x09, 0x5b, 0xc7, 0x22, 0xf1, 0xba, 0xd9, 0x49, 0xb4, 0x15, 0xf4, 0xc2, 0x91, 0x13, 0x12, 0x2f,
0xc5, 0x31, 0x12, 0x17, 0x8e, 0x28, 0xe1, 0x0d, 0x78, 0x01, 0xe4, 0xf5, 0x3a, 0x71, 0x68, 0x4c,
0x7b, 0xca, 0x8e, 0xf2, 0xfd, 0xcc, 0x37, 0xa3, 0x31, 0x6c, 0x77, 0xb8, 0xe8, 0x73, 0xe1, 0xa1,
0xf4, 0x46, 0x07, 0x6d, 0x86, 0xf4, 0xc0, 0x13, 0x6c, 0x30, 0x0a, 0x3b, 0xcc, 0x8d, 0x07, 0x1c,
0x39, 0xb9, 0x9f, 0x02, 0x5c, 0x94, 0xae, 0x06, 0x58, 0x5b, 0x01, 0xe7, 0x41, 0x8f, 0x79, 0x34,
0x0e, 0x3d, 0x1a, 0x45, 0x1c, 0x29, 0x86, 0x3c, 0x12, 0x29, 0xc1, 0xaa, 0x6b, 0xc5, 0x36, 0x15,
0xcc, 0xa3, 0xed, 0x4e, 0x38, 0x13, 0x4e, 0x0a, 0x0d, 0xb2, 0xae, 0xda, 0xa2, 0xd4, 0xff, 0x3d,
0xcd, 0x0b, 0x9c, 0x0f, 0xd9, 0xe0, 0x62, 0x86, 0x89, 0x69, 0x10, 0x46, 0xca, 0x2d, 0xc5, 0x3a,
0x08, 0xa4, 0xc5, 0xf0, 0x44, 0x8a, 0xa3, 0x11, 0x8b, 0xd0, 0x67, 0xe7, 0x43, 0x26, 0x90, 0x6c,
0x42, 0x99, 0x25, 0xb5, 0xa8, 0x1a, 0xb5, 0xd2, 0xfe, 0xba, 0xaf, 0x2b, 0xf2, 0x1a, 0x60, 0xae,
0x50, 0x35, 0x6b, 0xc6, 0x7e, 0xa5, 0xb9, 0xeb, 0xea, 0x80, 0x89, 0x9d, 0xab, 0xec, 0xb2, 0xa0,
0xee, 0x5b, 0x1a, 0x30, 0xad, 0xe9, 0xe7, 0x98, 0xce, 0xd8, 0x80, 0x07, 0x0b, 0xb6, 0x22, 0xe6,
0x91, 0x60, 0x64, 0x0f, 0x4a, 0x28, 0x53, 0xd3, 0x4a, 0xf3, 0xa1, 0x7b, 0x65, 0x72, 0xee, 0x89,
0xf4, 0x13, 0x04, 0x69, 0xc1, 0x06, 0xca, 0xd3, 0x81, 0xe6, 0x89, 0xaa, 0xa9, 0x18, 0x3b, 0x0b,
0xad, 0xa8, 0x69, 0xe5, 0x88, 0x1a, 0xec, 0x57, 0x70, 0xf6, 0x4e, 0x84, 0xf2, 0x89, 0x4a, 0x2a,
0xd1, 0xde, 0xb5, 0x89, 0xb4, 0x52, 0x3e, 0xd2, 0x21, 0xdc, 0x3d, 0x0e, 0xfb, 0xc3, 0x1e, 0xc5,
0x2c, 0x31, 0x69, 0x80, 0x89, 0xb2, 0x6a, 0x28, 0xcd, 0x82, 0x30, 0x26, 0x4a, 0xe7, 0x8b, 0x01,
0xf7, 0xe6, 0x54, 0x3d, 0x89, 0x17, 0xb0, 0x16, 0x50, 0x71, 0x1a, 0x46, 0x67, 0x5c, 0x2b, 0x3c,
0x29, 0x0e, 0xd7, 0xa2, 0xe2, 0x4d, 0x74, 0xc6, 0xfd, 0xd5, 0x20, 0x7d, 0x90, 0x43, 0x28, 0x0f,
0x98, 0x18, 0xf6, 0x50, 0xef, 0xa8, 0x56, 0xcc, 0xf5, 0x15, 0xce, 0xd7, 0x78, 0xc7, 0x81, 0x0d,
0xb5, 0x98, 0x2c, 0x03, 0x81, 0x5b, 0x5d, 0x2a, 0xba, 0xaa, 0x87, 0x75, 0x5f, 0xbd, 0x9d, 0x4b,
0xb8, 0xa3, 0x31, 0xba, 0xd9, 0x9b, 0x05, 0x25, 0x47, 0x50, 0xc9, 0x2d, 0x4d, 0xb7, 0x76, 0xb3,
0x9d, 0xc1, 0x7c, 0x67, 0xcd, 0x3f, 0x26, 0xac, 0x1e, 0xa7, 0x27, 0x46, 0x24, 0xac, 0x65, 0xa3,
0x23, 0xce, 0x12, 0xe7, 0x7f, 0x56, 0x62, 0xd5, 0xff, 0x8b, 0x49, 0x0d, 0x9c, 0xfa, 0xe7, 0x1f,
0xbf, 0xbf, 0x99, 0x8f, 0x9d, 0x47, 0xde, 0x92, 0xdb, 0xce, 0xdc, 0x62, 0xb8, 0xad, 0x86, 0x40,
0xb6, 0x97, 0x48, 0xe6, 0x47, 0x68, 0xd5, 0x8a, 0x01, 0xda, 0x70, 0x47, 0x19, 0xda, 0x64, 0xcb,
0x5b, 0x76, 0xd5, 0xde, 0xc7, 0x64, 0xea, 0x97, 0xe4, 0x13, 0x54, 0x72, 0x37, 0x43, 0x1a, 0x45,
0xb2, 0x0b, 0xa7, 0x6c, 0xed, 0x5e, 0x07, 0xd3, 0x3d, 0xd8, 0xaa, 0x87, 0x2a, 0xd9, 0x5c, 0xda,
0x83, 0x78, 0xf5, 0xf2, 0xfb, 0xc4, 0x36, 0xc6, 0x13, 0xdb, 0xf8, 0x35, 0xb1, 0x8d, 0xaf, 0x53,
0x7b, 0x65, 0x3c, 0xb5, 0x57, 0x7e, 0x4e, 0xed, 0x95, 0x77, 0x8d, 0x20, 0xc4, 0xee, 0xb0, 0xed,
0x76, 0x78, 0x3f, 0xe3, 0xa6, 0x3f, 0xcf, 0xc4, 0xfb, 0x0f, 0x1e, 0x5e, 0xc4, 0x2c, 0x11, 0x6b,
0x97, 0xd5, 0x07, 0xe7, 0xf9, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x62, 0x59, 0xdc, 0x70, 0x31,
0x05, 0x00, 0x00,
// 737 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xcd, 0x4f, 0x13, 0x41,
0x14, 0xef, 0xb6, 0xc8, 0xc7, 0x2b, 0x68, 0x1d, 0x10, 0x6b, 0xd1, 0xa5, 0x2c, 0x16, 0x08, 0x89,
0xbb, 0xa1, 0x7a, 0x20, 0xc6, 0xc4, 0xd0, 0x52, 0x08, 0x51, 0x3e, 0xb2, 0xc5, 0x83, 0xc6, 0xa4,
0x99, 0xb6, 0xc3, 0xb2, 0x91, 0xee, 0x94, 0xce, 0x94, 0x2c, 0x01, 0x62, 0xe2, 0xd1, 0x93, 0x89,
0xff, 0x94, 0x47, 0x12, 0x2f, 0x1e, 0x0d, 0xf8, 0x47, 0x78, 0x34, 0x3b, 0x3b, 0x6d, 0xb7, 0x65,
0x0b, 0xc4, 0x13, 0x33, 0xcc, 0xef, 0xfd, 0x3e, 0xde, 0x9b, 0x9d, 0xc2, 0x74, 0x85, 0xb2, 0x1a,
0x65, 0x06, 0x77, 0x8d, 0xa3, 0xa5, 0x32, 0xe1, 0x78, 0xc9, 0x60, 0xa4, 0x71, 0x64, 0x57, 0x88,
0x5e, 0x6f, 0x50, 0x4e, 0xd1, 0x7d, 0x1f, 0xa0, 0x73, 0x57, 0x97, 0x80, 0xd4, 0x63, 0x8b, 0x52,
0xeb, 0x80, 0x18, 0xb8, 0x6e, 0x1b, 0xd8, 0x71, 0x28, 0xc7, 0xdc, 0xa6, 0x0e, 0xf3, 0x0b, 0x52,
0xb3, 0x92, 0xb1, 0x8c, 0x19, 0x31, 0x70, 0xb9, 0x62, 0xb7, 0x89, 0xbd, 0x8d, 0x04, 0xa5, 0xae,
0xca, 0x72, 0x57, 0x9e, 0x4d, 0x58, 0xd4, 0xa2, 0x62, 0x69, 0x78, 0x2b, 0xf9, 0xdf, 0xc5, 0x20,
0xed, 0x61, 0x93, 0x34, 0x8e, 0xdb, 0x95, 0x75, 0x6c, 0xd9, 0x8e, 0xf0, 0xe0, 0x63, 0x35, 0x0e,
0x68, 0x9d, 0xf0, 0x5d, 0x97, 0x15, 0x8e, 0x88, 0xc3, 0x4d, 0x72, 0xd8, 0x24, 0x8c, 0xa3, 0x49,
0x18, 0x24, 0xde, 0x9e, 0x25, 0x95, 0x74, 0x6c, 0x61, 0xc4, 0x94, 0x3b, 0xb4, 0x06, 0xd0, 0x61,
0x48, 0x46, 0xd3, 0xca, 0x42, 0x3c, 0x3b, 0xa7, 0xcb, 0xd8, 0x9e, 0x9c, 0x2e, 0xe4, 0x5a, 0xf1,
0xf5, 0x1d, 0x6c, 0x11, 0xc9, 0x69, 0x06, 0x2a, 0xb5, 0x73, 0x05, 0xc6, 0xbb, 0x64, 0x59, 0x9d,
0x3a, 0x8c, 0xa0, 0x79, 0x88, 0x71, 0xd7, 0x17, 0x8d, 0x67, 0x1f, 0xe8, 0x57, 0xfa, 0xa9, 0xef,
0xba, 0xa6, 0x87, 0x40, 0xeb, 0x30, 0xca, 0xdd, 0x52, 0x43, 0xd6, 0xb1, 0x64, 0x54, 0x54, 0x3c,
0xed, 0xb2, 0x22, 0x7a, 0x18, 0x28, 0x94, 0x60, 0x33, 0xce, 0xdb, 0x6b, 0x8f, 0x28, 0x98, 0x28,
0x26, 0x12, 0xcd, 0xdf, 0x98, 0x48, 0x32, 0x05, 0x23, 0x11, 0x40, 0xb9, 0x06, 0xc5, 0xd5, 0x0a,
0x66, 0xdc, 0x13, 0xf3, 0x1b, 0xf9, 0x08, 0x86, 0xb9, 0x5b, 0x2a, 0x1f, 0x73, 0xe2, 0xa5, 0x52,
0x16, 0x46, 0xcd, 0x21, 0xee, 0xe6, 0xbc, 0x2d, 0x7a, 0x01, 0x03, 0x35, 0x5a, 0x25, 0xa2, 0x8b,
0x77, 0xb3, 0xe9, 0x90, 0xb0, 0x6d, 0xbe, 0x4d, 0x5a, 0x25, 0xa6, 0x40, 0x6b, 0x1f, 0x61, 0xbc,
0x4b, 0x46, 0x36, 0xae, 0x00, 0xf1, 0x40, 0x3f, 0x84, 0xd4, 0x6d, 0xdb, 0x01, 0x9d, 0x76, 0x68,
0xcb, 0x70, 0xaf, 0x68, 0xd7, 0x9a, 0x07, 0x98, 0xb7, 0xc6, 0x86, 0x32, 0x10, 0xe5, 0xae, 0x24,
0xec, 0x33, 0x91, 0x28, 0x77, 0xb5, 0xaf, 0x0a, 0x24, 0x3a, 0xa5, 0xd2, 0xd5, 0x2b, 0x18, 0xb6,
0x30, 0x2b, 0xd9, 0xce, 0x1e, 0x95, 0x0c, 0x33, 0xfd, 0x2d, 0xad, 0x63, 0xb6, 0xe1, 0xec, 0x51,
0x73, 0xc8, 0xf2, 0x17, 0x68, 0x19, 0x06, 0x1b, 0x84, 0x35, 0x0f, 0xb8, 0xbc, 0x68, 0xe9, 0xfe,
0xb5, 0xa6, 0xc0, 0x99, 0x12, 0xaf, 0x69, 0x30, 0x2a, 0x6e, 0x57, 0x2b, 0x03, 0x82, 0x81, 0x7d,
0xcc, 0xf6, 0x85, 0x87, 0x11, 0x53, 0xac, 0xb5, 0x33, 0x18, 0x93, 0x18, 0x69, 0xf6, 0x76, 0x41,
0x7b, 0x3b, 0x1d, 0xfd, 0xbf, 0x4e, 0x2f, 0x9e, 0xc2, 0x58, 0xd7, 0x78, 0x91, 0x0a, 0xa9, 0x9c,
0xb9, 0xbd, 0xb2, 0x9a, 0x5f, 0x29, 0xee, 0x96, 0x36, 0xb7, 0x57, 0x0b, 0xa5, 0x77, 0x5b, 0xc5,
0x9d, 0x42, 0x7e, 0x63, 0x6d, 0xa3, 0xb0, 0x9a, 0x88, 0xa0, 0x24, 0x4c, 0xf4, 0x9c, 0xe7, 0xde,
0x6e, 0xe7, 0xdf, 0x24, 0x14, 0xf4, 0x10, 0xc6, 0x7b, 0x4e, 0x8a, 0xef, 0xb7, 0xf2, 0x89, 0x68,
0x48, 0xc9, 0x8a, 0x38, 0x89, 0x65, 0xff, 0xc6, 0x60, 0xa8, 0xe8, 0xbf, 0x5d, 0xe8, 0x04, 0x86,
0x5b, 0x83, 0x43, 0x5a, 0x48, 0xee, 0x9e, 0x0b, 0x91, 0x9a, 0xbd, 0x16, 0x23, 0x2f, 0xd2, 0xdc,
0x97, 0x9f, 0x7f, 0xbe, 0x47, 0xd3, 0xda, 0x94, 0x11, 0xf2, 0x68, 0x4a, 0xf0, 0x4b, 0x65, 0x11,
0x1d, 0xc2, 0x1d, 0x31, 0x05, 0x34, 0x1d, 0xc2, 0x1a, 0x9c, 0x61, 0x2a, 0xdd, 0x1f, 0x20, 0x35,
0x33, 0x42, 0x73, 0x1a, 0x3d, 0x31, 0xc2, 0x5e, 0x4c, 0x66, 0x9c, 0x78, 0x73, 0x3f, 0x43, 0x9f,
0x21, 0x1e, 0xf8, 0x82, 0x50, 0xe6, 0xba, 0x0f, 0xaf, 0x23, 0x3f, 0x77, 0x13, 0x4c, 0x9a, 0x98,
0x11, 0x26, 0xa6, 0xb4, 0xc9, 0x70, 0x13, 0x5e, 0xe6, 0x53, 0x88, 0x07, 0xde, 0xbe, 0x50, 0x03,
0x57, 0x9f, 0xe4, 0x50, 0x03, 0x21, 0x4f, 0xa8, 0xa6, 0x0a, 0x03, 0x49, 0xd4, 0xc7, 0x40, 0xee,
0xf5, 0x8f, 0x0b, 0x55, 0x39, 0xbf, 0x50, 0x95, 0xdf, 0x17, 0xaa, 0xf2, 0xed, 0x52, 0x8d, 0x9c,
0x5f, 0xaa, 0x91, 0x5f, 0x97, 0x6a, 0xe4, 0x43, 0xc6, 0xb2, 0xf9, 0x7e, 0xb3, 0xac, 0x57, 0x68,
0xad, 0x55, 0xeb, 0xff, 0x79, 0xc6, 0xaa, 0x9f, 0x0c, 0x7e, 0x5c, 0x27, 0x1e, 0x59, 0x79, 0x50,
0xfc, 0x70, 0x3c, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0x96, 0xba, 0xfb, 0xcb, 0x0f, 0x07, 0x00,
0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -423,6 +579,8 @@ type ServiceClient interface {
Simulate(ctx context.Context, in *SimulateRequest, opts ...grpc.CallOption) (*SimulateResponse, error)
// GetTx fetches a tx by hash.
GetTx(ctx context.Context, in *GetTxRequest, opts ...grpc.CallOption) (*GetTxResponse, error)
// BroadcastTx broadcast transaction.
BroadcastTx(ctx context.Context, in *BroadcastTxRequest, opts ...grpc.CallOption) (*BroadcastTxResponse, error)
// GetTxsEvent fetches txs by event.
GetTxsEvent(ctx context.Context, in *GetTxsEventRequest, opts ...grpc.CallOption) (*GetTxsEventResponse, error)
}
@ -453,6 +611,15 @@ func (c *serviceClient) GetTx(ctx context.Context, in *GetTxRequest, opts ...grp
return out, nil
}
func (c *serviceClient) BroadcastTx(ctx context.Context, in *BroadcastTxRequest, opts ...grpc.CallOption) (*BroadcastTxResponse, error) {
out := new(BroadcastTxResponse)
err := c.cc.Invoke(ctx, "/cosmos.tx.v1beta1.Service/BroadcastTx", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *serviceClient) GetTxsEvent(ctx context.Context, in *GetTxsEventRequest, opts ...grpc.CallOption) (*GetTxsEventResponse, error) {
out := new(GetTxsEventResponse)
err := c.cc.Invoke(ctx, "/cosmos.tx.v1beta1.Service/GetTxsEvent", in, out, opts...)
@ -468,6 +635,8 @@ type ServiceServer interface {
Simulate(context.Context, *SimulateRequest) (*SimulateResponse, error)
// GetTx fetches a tx by hash.
GetTx(context.Context, *GetTxRequest) (*GetTxResponse, error)
// BroadcastTx broadcast transaction.
BroadcastTx(context.Context, *BroadcastTxRequest) (*BroadcastTxResponse, error)
// GetTxsEvent fetches txs by event.
GetTxsEvent(context.Context, *GetTxsEventRequest) (*GetTxsEventResponse, error)
}
@ -482,6 +651,9 @@ func (*UnimplementedServiceServer) Simulate(ctx context.Context, req *SimulateRe
func (*UnimplementedServiceServer) GetTx(ctx context.Context, req *GetTxRequest) (*GetTxResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetTx not implemented")
}
func (*UnimplementedServiceServer) BroadcastTx(ctx context.Context, req *BroadcastTxRequest) (*BroadcastTxResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method BroadcastTx not implemented")
}
func (*UnimplementedServiceServer) GetTxsEvent(ctx context.Context, req *GetTxsEventRequest) (*GetTxsEventResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetTxsEvent not implemented")
}
@ -526,6 +698,24 @@ func _Service_GetTx_Handler(srv interface{}, ctx context.Context, dec func(inter
return interceptor(ctx, in, info, handler)
}
func _Service_BroadcastTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(BroadcastTxRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ServiceServer).BroadcastTx(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/cosmos.tx.v1beta1.Service/BroadcastTx",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ServiceServer).BroadcastTx(ctx, req.(*BroadcastTxRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Service_GetTxsEvent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetTxsEventRequest)
if err := dec(in); err != nil {
@ -556,6 +746,10 @@ var _Service_serviceDesc = grpc.ServiceDesc{
MethodName: "GetTx",
Handler: _Service_GetTx_Handler,
},
{
MethodName: "BroadcastTx",
Handler: _Service_BroadcastTx_Handler,
},
{
MethodName: "GetTxsEvent",
Handler: _Service_GetTxsEvent_Handler,
@ -672,6 +866,76 @@ func (m *GetTxsEventResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *BroadcastTxRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *BroadcastTxRequest) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *BroadcastTxRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.Mode != 0 {
i = encodeVarintService(dAtA, i, uint64(m.Mode))
i--
dAtA[i] = 0x10
}
if len(m.TxBytes) > 0 {
i -= len(m.TxBytes)
copy(dAtA[i:], m.TxBytes)
i = encodeVarintService(dAtA, i, uint64(len(m.TxBytes)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *BroadcastTxResponse) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *BroadcastTxResponse) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *BroadcastTxResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.TxResponse != nil {
{
size, err := m.TxResponse.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintService(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *SimulateRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@ -886,6 +1150,35 @@ func (m *GetTxsEventResponse) Size() (n int) {
return n
}
func (m *BroadcastTxRequest) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.TxBytes)
if l > 0 {
n += 1 + l + sovService(uint64(l))
}
if m.Mode != 0 {
n += 1 + sovService(uint64(m.Mode))
}
return n
}
func (m *BroadcastTxResponse) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.TxResponse != nil {
l = m.TxResponse.Size()
n += 1 + l + sovService(uint64(l))
}
return n
}
func (m *SimulateRequest) Size() (n int) {
if m == nil {
return 0
@ -1230,6 +1523,201 @@ func (m *GetTxsEventResponse) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *BroadcastTxRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowService
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: BroadcastTxRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: BroadcastTxRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field TxBytes", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowService
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthService
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthService
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.TxBytes = append(m.TxBytes[:0], dAtA[iNdEx:postIndex]...)
if m.TxBytes == nil {
m.TxBytes = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Mode", wireType)
}
m.Mode = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowService
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Mode |= BroadcastMode(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipService(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthService
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthService
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *BroadcastTxResponse) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowService
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: BroadcastTxResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: BroadcastTxResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field TxResponse", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowService
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthService
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthService
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.TxResponse == nil {
m.TxResponse = &types.TxResponse{}
}
if err := m.TxResponse.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipService(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthService
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthService
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *SimulateRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0

View File

@ -31,18 +31,15 @@ var _ = runtime.String
var _ = utilities.NewDoubleArray
var _ = descriptor.ForMessage
var (
filter_Service_Simulate_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
)
func request_Service_Simulate_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq SimulateRequest
var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Service_Simulate_0); err != nil {
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -55,10 +52,11 @@ func local_request_Service_Simulate_0(ctx context.Context, marshaler runtime.Mar
var protoReq SimulateRequest
var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Service_Simulate_0); err != nil {
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -121,6 +119,40 @@ func local_request_Service_GetTx_0(ctx context.Context, marshaler runtime.Marsha
}
func request_Service_BroadcastTx_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq BroadcastTxRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.BroadcastTx(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Service_BroadcastTx_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq BroadcastTxRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.BroadcastTx(ctx, &protoReq)
return msg, metadata, err
}
var (
filter_Service_GetTxsEvent_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
)
@ -203,6 +235,26 @@ func RegisterServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, se
})
mux.Handle("POST", pattern_Service_BroadcastTx_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Service_BroadcastTx_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Service_BroadcastTx_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Service_GetTxsEvent_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@ -304,6 +356,26 @@ func RegisterServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, cl
})
mux.Handle("POST", pattern_Service_BroadcastTx_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Service_BroadcastTx_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Service_BroadcastTx_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Service_GetTxsEvent_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@ -330,7 +402,9 @@ func RegisterServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, cl
var (
pattern_Service_Simulate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "tx", "v1beta1", "simulate"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Service_GetTx_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 1, 1, 0, 4, 1, 5, 3}, []string{"cosmos", "tx", "v1beta1", "hash"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Service_GetTx_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "tx", "v1beta1", "txs", "hash"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Service_BroadcastTx_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "tx", "v1beta1", "txs"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Service_GetTxsEvent_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "tx", "v1beta1", "txs"}, "", runtime.AssumeColonVerbOpt(true)))
)
@ -340,5 +414,7 @@ var (
forward_Service_GetTx_0 = runtime.ForwardResponseMessage
forward_Service_BroadcastTx_0 = runtime.ForwardResponseMessage
forward_Service_GetTxsEvent_0 = runtime.ForwardResponseMessage
)

View File

@ -151,7 +151,7 @@ func QueryTxRequestHandlerFn(clientCtx client.Context) http.HandlerFunc {
rest.WriteErrorResponse(w, http.StatusNotFound, fmt.Sprintf("no transaction found with hash %s", hashHexStr))
}
err = checkSignModeError(clientCtx, output, "/cosmos/tx/v1beta1/tx/{txhash}")
err = checkSignModeError(clientCtx, output, "/cosmos/tx/v1beta1/txs/{txhash}")
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())

View File

@ -345,7 +345,7 @@ func (s *IntegrationTestSuite) broadcastReq(stdTx legacytx.StdTx, mode string) (
// testQueryIBCTx is a helper function to test querying txs which:
// - show an error message on legacy REST endpoints
// - succeed using gRPC
// In practise, we call this function on IBC txs.
// In practice, we call this function on IBC txs.
func (s *IntegrationTestSuite) testQueryIBCTx(txRes sdk.TxResponse, cmd *cobra.Command, args []string) {
val := s.network.Validators[0]
@ -381,7 +381,7 @@ func (s *IntegrationTestSuite) testQueryIBCTx(txRes sdk.TxResponse, cmd *cobra.C
}
// try fetching the txn using gRPC req, it will fetch info since it has proto codec.
grpcJSON, err := rest.GetRequest(fmt.Sprintf("%s/cosmos/tx/v1beta1/tx/%s", val.APIAddress, txRes.TxHash))
grpcJSON, err := rest.GetRequest(fmt.Sprintf("%s/cosmos/tx/v1beta1/txs/%s", val.APIAddress, txRes.TxHash))
s.Require().NoError(err)
var getTxRes txtypes.GetTxResponse

View File

@ -49,6 +49,10 @@ const (
// TxsByEvents implements the ServiceServer.TxsByEvents RPC method.
func (s txServer) GetTxsEvent(ctx context.Context, req *txtypes.GetTxsEventRequest) (*txtypes.GetTxsEventResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "request cannot be nil")
}
page, limit, err := pagination.ParsePagination(req.Pagination)
if err != nil {
return nil, err
@ -113,7 +117,7 @@ func (s txServer) GetTxsEvent(ctx context.Context, req *txtypes.GetTxsEventReque
// Simulate implements the ServiceServer.Simulate RPC method.
func (s txServer) Simulate(ctx context.Context, req *txtypes.SimulateRequest) (*txtypes.SimulateResponse, error) {
if req.Tx == nil {
if req == nil || req.Tx == nil {
return nil, status.Error(codes.InvalidArgument, "invalid empty tx")
}
@ -139,6 +143,10 @@ func (s txServer) Simulate(ctx context.Context, req *txtypes.SimulateRequest) (*
// GetTx implements the ServiceServer.GetTx RPC method.
func (s txServer) GetTx(ctx context.Context, req *txtypes.GetTxRequest) (*txtypes.GetTxResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "request cannot be nil")
}
// We get hash as a hex string in the request, convert it to bytes.
hash, err := hex.DecodeString(req.Hash)
if err != nil {
@ -170,6 +178,10 @@ func (s txServer) GetTx(ctx context.Context, req *txtypes.GetTxRequest) (*txtype
}, nil
}
func (s txServer) BroadcastTx(ctx context.Context, req *txtypes.BroadcastTxRequest) (*txtypes.BroadcastTxResponse, error) {
return client.TxServiceBroadcast(ctx, s.clientCtx, req)
}
// RegisterTxService registers the tx service on the gRPC router.
func RegisterTxService(
qrt gogogrpc.Server,

View File

@ -31,6 +31,7 @@ type IntegrationTestSuite struct {
network *network.Network
queryClient tx.ServiceClient
txRes sdk.TxResponse
}
func (s *IntegrationTestSuite) SetupSuite() {
@ -41,67 +42,14 @@ func (s *IntegrationTestSuite) SetupSuite() {
s.cfg = cfg
s.network = network.New(s.T(), cfg)
s.Require().NotNil(s.network)
val := s.network.Validators[0]
_, err := s.network.WaitForHeight(1)
s.Require().NoError(err)
s.queryClient = tx.NewServiceClient(s.network.Validators[0].ClientCtx)
}
func (s *IntegrationTestSuite) TearDownSuite() {
s.T().Log("tearing down integration test suite")
s.network.Cleanup()
}
func (s IntegrationTestSuite) TestSimulate() {
val := s.network.Validators[0]
// prepare txBuilder with msg
txBuilder := val.ClientCtx.TxConfig.NewTxBuilder()
feeAmount := sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 10)}
gasLimit := testdata.NewTestGasLimit()
s.Require().NoError(
txBuilder.SetMsgs(&banktypes.MsgSend{
FromAddress: val.Address.String(),
ToAddress: val.Address.String(),
Amount: sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 10)},
}),
)
txBuilder.SetFeeAmount(feeAmount)
txBuilder.SetGasLimit(gasLimit)
txBuilder.SetMemo("foobar")
// setup txFactory
txFactory := clienttx.Factory{}.
WithChainID(val.ClientCtx.ChainID).
WithKeybase(val.ClientCtx.Keyring).
WithTxConfig(val.ClientCtx.TxConfig).
WithSignMode(signing.SignMode_SIGN_MODE_DIRECT)
// Sign Tx.
err := authclient.SignTx(txFactory, val.ClientCtx, val.Moniker, txBuilder, false)
s.Require().NoError(err)
// Convert the txBuilder to a tx.Tx.
protoTx, err := txBuilderToProtoTx(txBuilder)
s.Require().NoError(err)
// Run the simulate gRPC query.
res, err := s.queryClient.Simulate(
context.Background(),
&tx.SimulateRequest{Tx: protoTx},
)
s.Require().NoError(err)
// Check the result and gas used are correct.
s.Require().Equal(len(res.GetResult().GetEvents()), 4) // 1 transfer, 3 messages.
s.Require().True(res.GetGasInfo().GetGasUsed() > 0) // Gas used sometimes change, just check it's not empty.
}
func (s IntegrationTestSuite) TestGetTxEvents() {
val := s.network.Validators[0]
s.queryClient = tx.NewServiceClient(val.ClientCtx)
// Create a new MsgSend tx from val to itself.
out, err := bankcli.MsgSendExec(
@ -118,51 +66,161 @@ func (s IntegrationTestSuite) TestGetTxEvents() {
fmt.Sprintf("--%s=foobar", flags.FlagMemo),
)
s.Require().NoError(err)
var txRes sdk.TxResponse
s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &txRes))
s.Require().Equal(uint32(0), txRes.Code)
s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &s.txRes))
s.Require().Equal(uint32(0), s.txRes.Code)
s.Require().NoError(s.network.WaitForNextBlock())
}
// Query the tx via gRPC empty params.
_, err = s.queryClient.GetTxsEvent(
context.Background(),
&tx.GetTxsEventRequest{},
)
s.Require().Error(err)
func (s *IntegrationTestSuite) TearDownSuite() {
s.T().Log("tearing down integration test suite")
s.network.Cleanup()
}
// Query the tx via gRPC.
grpcRes, err := s.queryClient.GetTxsEvent(
context.Background(),
&tx.GetTxsEventRequest{
Events: []string{"message.action=send"},
Pagination: &query.PageRequest{
CountTotal: false,
Offset: 0,
Limit: 1,
func (s IntegrationTestSuite) TestSimulateTx_GRPC() {
txBuilder := s.mkTxBuilder()
// Convert the txBuilder to a tx.Tx.
protoTx, err := txBuilderToProtoTx(txBuilder)
s.Require().NoError(err)
testCases := []struct {
name string
req *tx.SimulateRequest
expErr bool
expErrMsg string
}{
{"nil request", nil, true, "request cannot be nil"},
{"empty request", &tx.SimulateRequest{}, true, "invalid empty tx"},
{"valid request", &tx.SimulateRequest{Tx: protoTx}, false, ""},
}
for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
// Broadcast the tx via gRPC via the validator's clientCtx (which goes
// through Tendermint).
res, err := s.queryClient.Simulate(context.Background(), tc.req)
if tc.expErr {
s.Require().Error(err)
s.Require().Contains(err.Error(), tc.expErrMsg)
} else {
s.Require().NoError(err)
// Check the result and gas used are correct.
s.Require().Equal(len(res.GetResult().GetEvents()), 4) // 1 transfer, 3 messages.
s.Require().True(res.GetGasInfo().GetGasUsed() > 0) // Gas used sometimes change, just check it's not empty.
}
})
}
}
func (s IntegrationTestSuite) TestSimulateTx_GRPCGateway() {
val := s.network.Validators[0]
txBuilder := s.mkTxBuilder()
// Convert the txBuilder to a tx.Tx.
protoTx, err := txBuilderToProtoTx(txBuilder)
s.Require().NoError(err)
testCases := []struct {
name string
req *tx.SimulateRequest
expErr bool
expErrMsg string
}{
{"empty request", &tx.SimulateRequest{}, true, "invalid empty tx"},
{"valid request", &tx.SimulateRequest{Tx: protoTx}, false, ""},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
req, err := val.ClientCtx.JSONMarshaler.MarshalJSON(tc.req)
s.Require().NoError(err)
res, err := rest.PostRequest(fmt.Sprintf("%s/cosmos/tx/v1beta1/simulate", val.APIAddress), "application/json", req)
s.Require().NoError(err)
if tc.expErr {
s.Require().Contains(string(res), tc.expErrMsg)
} else {
var result tx.SimulateResponse
err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(res, &result)
s.Require().NoError(err)
// Check the result and gas used are correct.
s.Require().Equal(len(result.GetResult().GetEvents()), 4) // 1 transfer, 3 messages.
s.Require().True(result.GetGasInfo().GetGasUsed() > 0) // Gas used sometimes change, just check it's not empty.
}
})
}
}
func (s IntegrationTestSuite) TestGetTxEvents_GRPC() {
testCases := []struct {
name string
req *tx.GetTxsEventRequest
expErr bool
expErrMsg string
}{
{
"nil request",
nil,
true, "request cannot be nil",
},
{
"empty request",
&tx.GetTxsEventRequest{},
true, "must declare at least one event to search",
},
{
"request with dummy event",
&tx.GetTxsEventRequest{Events: []string{"foobar"}},
true, "event foobar should be of the format: {eventType}.{eventAttribute}={value}",
},
{
"without pagination",
&tx.GetTxsEventRequest{
Events: []string{"message.action=send"},
},
false, "",
},
)
s.Require().NoError(err)
s.Require().Equal(len(grpcRes.Txs), 1)
s.Require().Equal("foobar", grpcRes.Txs[0].Body.Memo)
// Query the tx via gRPC without pagination. This used to panic, see
// https://github.com/cosmos/cosmos-sdk/issues/8038.
grpcRes, err = s.queryClient.GetTxsEvent(
context.Background(),
&tx.GetTxsEventRequest{
Events: []string{"message.action=send"},
{
"with pagination",
&tx.GetTxsEventRequest{
Events: []string{"message.action=send"},
Pagination: &query.PageRequest{
CountTotal: false,
Offset: 0,
Limit: 1,
},
},
false, "",
},
)
// TODO Once https://github.com/cosmos/cosmos-sdk/pull/8029 is merged, this
// should not error anymore.
s.Require().NoError(err)
{
"with multi events",
&tx.GetTxsEventRequest{
Events: []string{"message.action=send", "message.module=bank"},
},
false, "",
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
// Query the tx via gRPC.
grpcRes, err := s.queryClient.GetTxsEvent(context.Background(), tc.req)
if tc.expErr {
s.Require().Error(err)
s.Require().Contains(err.Error(), tc.expErrMsg)
} else {
s.Require().NoError(err)
s.Require().GreaterOrEqual(len(grpcRes.Txs), 1)
s.Require().Equal("foobar", grpcRes.Txs[0].Body.Memo)
}
})
}
}
rpcTests := []struct {
func (s IntegrationTestSuite) TestGetTxEvents_GRPCGateway() {
val := s.network.Validators[0]
testCases := []struct {
name string
url string
expectErr bool
expErr bool
expErrMsg string
}{
{
@ -196,15 +254,16 @@ func (s IntegrationTestSuite) TestGetTxEvents() {
"",
},
}
for _, tc := range rpcTests {
for _, tc := range testCases {
s.Run(tc.name, func() {
res, err := rest.GetRequest(tc.url)
s.Require().NoError(err)
if tc.expectErr {
if tc.expErr {
s.Require().Contains(string(res), tc.expErrMsg)
} else {
var result tx.GetTxsEventResponse
val.ClientCtx.JSONMarshaler.UnmarshalJSON(res, &result)
err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(res, &result)
s.Require().NoError(err)
s.Require().GreaterOrEqual(len(result.Txs), 1)
s.Require().Equal("foobar", result.Txs[0].Body.Memo)
s.Require().NotZero(result.TxResponses[0].Height)
@ -213,52 +272,188 @@ func (s IntegrationTestSuite) TestGetTxEvents() {
}
}
func (s IntegrationTestSuite) TestGetTx() {
func (s IntegrationTestSuite) TestGetTx_GRPC() {
testCases := []struct {
name string
req *tx.GetTxRequest
expErr bool
expErrMsg string
}{
{"nil request", nil, true, "request cannot be nil"},
{"empty request", &tx.GetTxRequest{}, true, "transaction hash cannot be empty"},
{"request with dummy hash", &tx.GetTxRequest{Hash: "deadbeef"}, true, "tx (DEADBEEF) not found"},
{"good request", &tx.GetTxRequest{Hash: s.txRes.TxHash}, false, ""},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
// Query the tx via gRPC.
grpcRes, err := s.queryClient.GetTx(context.Background(), tc.req)
if tc.expErr {
s.Require().Error(err)
s.Require().Contains(err.Error(), tc.expErrMsg)
} else {
s.Require().NoError(err)
s.Require().Equal("foobar", grpcRes.Tx.Body.Memo)
}
})
}
}
func (s IntegrationTestSuite) TestGetTx_GRPCGateway() {
val := s.network.Validators[0]
testCases := []struct {
name string
url string
expErr bool
expErrMsg string
}{
{
"empty params",
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs/", val.APIAddress),
true, "transaction hash cannot be empty",
},
{
"dummy hash",
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs/%s", val.APIAddress, "deadbeef"),
true, "tx (DEADBEEF) not found",
},
{
"good hash",
fmt.Sprintf("%s/cosmos/tx/v1beta1/txs/%s", val.APIAddress, s.txRes.TxHash),
false, "",
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
res, err := rest.GetRequest(tc.url)
s.Require().NoError(err)
if tc.expErr {
s.Require().Contains(string(res), tc.expErrMsg)
} else {
var result tx.GetTxResponse
err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(res, &result)
s.Require().NoError(err)
s.Require().Equal("foobar", result.Tx.Body.Memo)
s.Require().NotZero(result.TxResponse.Height)
}
})
}
}
// Create a new MsgSend tx from val to itself.
out, err := bankcli.MsgSendExec(
val.ClientCtx,
val.Address,
val.Address,
sdk.NewCoins(
sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)),
),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
fmt.Sprintf("--gas=%d", flags.DefaultGasLimit),
fmt.Sprintf("--%s=foobar", flags.FlagMemo),
)
func (s IntegrationTestSuite) TestBroadcastTx_GRPC() {
val := s.network.Validators[0]
txBuilder := s.mkTxBuilder()
txBytes, err := val.ClientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
s.Require().NoError(err)
var txRes sdk.TxResponse
s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &txRes))
s.Require().Equal(uint32(0), txRes.Code)
s.Require().NoError(s.network.WaitForNextBlock())
testCases := []struct {
name string
req *tx.BroadcastTxRequest
expErr bool
expErrMsg string
}{
{"nil request", nil, true, "request cannot be nil"},
{"empty request", &tx.BroadcastTxRequest{}, true, "invalid empty tx"},
{"no mode", &tx.BroadcastTxRequest{
TxBytes: txBytes,
}, true, "supported types: sync, async, block"},
{"valid request", &tx.BroadcastTxRequest{
Mode: tx.BroadcastMode_BROADCAST_MODE_SYNC,
TxBytes: txBytes,
}, false, ""},
}
// Query the tx via gRPC.
grpcRes, err := s.queryClient.GetTx(
context.Background(),
&tx.GetTxRequest{Hash: txRes.TxHash},
)
for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
// Broadcast the tx via gRPC via the validator's clientCtx (which goes
// through Tendermint).
grpcRes, err := s.queryClient.BroadcastTx(context.Background(), tc.req)
if tc.expErr {
s.Require().Error(err)
s.Require().Contains(err.Error(), tc.expErrMsg)
} else {
s.Require().NoError(err)
s.Require().Equal(uint32(0), grpcRes.TxResponse.Code)
}
})
}
}
func (s IntegrationTestSuite) TestBroadcastTx_GRPCGateway() {
val := s.network.Validators[0]
txBuilder := s.mkTxBuilder()
txBytes, err := val.ClientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
s.Require().NoError(err)
s.Require().Equal("foobar", grpcRes.Tx.Body.Memo)
s.Require().NotZero(grpcRes.TxResponse.Height)
// Query the tx via grpc-gateway.
restRes, err := rest.GetRequest(fmt.Sprintf("%s/cosmos/tx/v1beta1/tx/%s", val.APIAddress, txRes.TxHash))
s.Require().NoError(err)
var getTxRes tx.GetTxResponse
s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(restRes, &getTxRes))
s.Require().Equal("foobar", grpcRes.Tx.Body.Memo)
s.Require().NotZero(grpcRes.TxResponse.Height)
testCases := []struct {
name string
req *tx.BroadcastTxRequest
expErr bool
expErrMsg string
}{
{"empty request", &tx.BroadcastTxRequest{}, true, "invalid empty tx"},
{"no mode", &tx.BroadcastTxRequest{TxBytes: txBytes}, true, "supported types: sync, async, block"},
{"valid request", &tx.BroadcastTxRequest{
Mode: tx.BroadcastMode_BROADCAST_MODE_SYNC,
TxBytes: txBytes,
}, false, ""},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
req, err := val.ClientCtx.JSONMarshaler.MarshalJSON(tc.req)
s.Require().NoError(err)
res, err := rest.PostRequest(fmt.Sprintf("%s/cosmos/tx/v1beta1/txs", val.APIAddress), "application/json", req)
s.Require().NoError(err)
if tc.expErr {
s.Require().Contains(string(res), tc.expErrMsg)
} else {
var result tx.BroadcastTxResponse
err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(res, &result)
s.Require().NoError(err)
s.Require().Equal(uint32(0), result.TxResponse.Code)
}
})
}
}
func TestIntegrationTestSuite(t *testing.T) {
suite.Run(t, new(IntegrationTestSuite))
}
func (s IntegrationTestSuite) mkTxBuilder() client.TxBuilder {
val := s.network.Validators[0]
s.Require().NoError(s.network.WaitForNextBlock())
// prepare txBuilder with msg
txBuilder := val.ClientCtx.TxConfig.NewTxBuilder()
feeAmount := sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 10)}
gasLimit := testdata.NewTestGasLimit()
s.Require().NoError(
txBuilder.SetMsgs(&banktypes.MsgSend{
FromAddress: val.Address.String(),
ToAddress: val.Address.String(),
Amount: sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 10)},
}),
)
txBuilder.SetFeeAmount(feeAmount)
txBuilder.SetGasLimit(gasLimit)
// setup txFactory
txFactory := clienttx.Factory{}.
WithChainID(val.ClientCtx.ChainID).
WithKeybase(val.ClientCtx.Keyring).
WithTxConfig(val.ClientCtx.TxConfig).
WithSignMode(signing.SignMode_SIGN_MODE_DIRECT)
// Sign Tx.
err := authclient.SignTx(txFactory, val.ClientCtx, val.Moniker, txBuilder, false)
s.Require().NoError(err)
return txBuilder
}
// txBuilderToProtoTx converts a txBuilder into a proto tx.Tx.
func txBuilderToProtoTx(txBuilder client.TxBuilder) (*tx.Tx, error) { // nolint
intoAnyTx, ok := txBuilder.(codectypes.IntoAny)