Browse Source

broadcast_tx via grpc

pull/255/head
Ethan Buchman 9 years ago
parent
commit
db437e7a45
13 changed files with 573 additions and 4 deletions
  1. +3
    -0
      cmd/tendermint/flags.go
  2. +1
    -0
      config/tendermint/config.go
  3. +1
    -0
      config/tendermint_test/config.go
  4. +12
    -0
      node/node.go
  5. +18
    -0
      rpc/grpc/api.go
  6. +44
    -0
      rpc/grpc/client_server.go
  7. +336
    -0
      rpc/grpc/types.pb.go
  8. +41
    -0
      rpc/grpc/types.proto
  9. +21
    -0
      rpc/test/grpc_test.go
  10. +7
    -0
      rpc/test/helpers.go
  11. +31
    -4
      test/app/counter_test.sh
  12. +36
    -0
      test/app/grpc_client.go
  13. +22
    -0
      test/app/test.sh

+ 3
- 0
cmd/tendermint/flags.go View File

@ -16,6 +16,7 @@ func parseFlags(config cfg.Config, args []string) {
fastSync bool fastSync bool
skipUPNP bool skipUPNP bool
rpcLaddr string rpcLaddr string
grpcLaddr string
logLevel string logLevel string
proxyApp string proxyApp string
tmspTransport string tmspTransport string
@ -30,6 +31,7 @@ func parseFlags(config cfg.Config, args []string) {
flags.BoolVar(&fastSync, "fast_sync", config.GetBool("fast_sync"), "Fast blockchain syncing") flags.BoolVar(&fastSync, "fast_sync", config.GetBool("fast_sync"), "Fast blockchain syncing")
flags.BoolVar(&skipUPNP, "skip_upnp", config.GetBool("skip_upnp"), "Skip UPNP configuration") flags.BoolVar(&skipUPNP, "skip_upnp", config.GetBool("skip_upnp"), "Skip UPNP configuration")
flags.StringVar(&rpcLaddr, "rpc_laddr", config.GetString("rpc_laddr"), "RPC listen address. Port required") flags.StringVar(&rpcLaddr, "rpc_laddr", config.GetString("rpc_laddr"), "RPC listen address. Port required")
flags.StringVar(&grpcLaddr, "grpc_laddr", config.GetString("grpc_laddr"), "GRPC listen address (BroadcastTx only). Port required")
flags.StringVar(&logLevel, "log_level", config.GetString("log_level"), "Log level") flags.StringVar(&logLevel, "log_level", config.GetString("log_level"), "Log level")
flags.StringVar(&proxyApp, "proxy_app", config.GetString("proxy_app"), flags.StringVar(&proxyApp, "proxy_app", config.GetString("proxy_app"),
"Proxy app address, or 'nilapp' or 'dummy' for local testing.") "Proxy app address, or 'nilapp' or 'dummy' for local testing.")
@ -47,6 +49,7 @@ func parseFlags(config cfg.Config, args []string) {
config.Set("fast_sync", fastSync) config.Set("fast_sync", fastSync)
config.Set("skip_upnp", skipUPNP) config.Set("skip_upnp", skipUPNP)
config.Set("rpc_laddr", rpcLaddr) config.Set("rpc_laddr", rpcLaddr)
config.Set("grpc_laddr", grpcLaddr)
config.Set("log_level", logLevel) config.Set("log_level", logLevel)
config.Set("proxy_app", proxyApp) config.Set("proxy_app", proxyApp)
config.Set("tmsp", tmspTransport) config.Set("tmsp", tmspTransport)


+ 1
- 0
config/tendermint/config.go View File

@ -67,6 +67,7 @@ func GetConfig(rootDir string) cfg.Config {
mapConfig.SetDefault("db_dir", rootDir+"/data") mapConfig.SetDefault("db_dir", rootDir+"/data")
mapConfig.SetDefault("log_level", "info") mapConfig.SetDefault("log_level", "info")
mapConfig.SetDefault("rpc_laddr", "tcp://0.0.0.0:46657") mapConfig.SetDefault("rpc_laddr", "tcp://0.0.0.0:46657")
mapConfig.SetDefault("grpc_laddr", "")
mapConfig.SetDefault("prof_laddr", "") mapConfig.SetDefault("prof_laddr", "")
mapConfig.SetDefault("revision_file", rootDir+"/revision") mapConfig.SetDefault("revision_file", rootDir+"/revision")
mapConfig.SetDefault("cs_wal_dir", rootDir+"/data/cs.wal") mapConfig.SetDefault("cs_wal_dir", rootDir+"/data/cs.wal")


+ 1
- 0
config/tendermint_test/config.go View File

@ -80,6 +80,7 @@ func ResetConfig(localPath string) cfg.Config {
mapConfig.SetDefault("db_dir", rootDir+"/data") mapConfig.SetDefault("db_dir", rootDir+"/data")
mapConfig.SetDefault("log_level", "debug") mapConfig.SetDefault("log_level", "debug")
mapConfig.SetDefault("rpc_laddr", "tcp://0.0.0.0:36657") mapConfig.SetDefault("rpc_laddr", "tcp://0.0.0.0:36657")
mapConfig.SetDefault("grpc_laddr", "tcp://0.0.0.0:36658")
mapConfig.SetDefault("prof_laddr", "") mapConfig.SetDefault("prof_laddr", "")
mapConfig.SetDefault("revision_file", rootDir+"/revision") mapConfig.SetDefault("revision_file", rootDir+"/revision")
mapConfig.SetDefault("cs_wal_dir", rootDir+"/data/cs.wal") mapConfig.SetDefault("cs_wal_dir", rootDir+"/data/cs.wal")


+ 12
- 0
node/node.go View File

@ -21,6 +21,7 @@ import (
mempl "github.com/tendermint/tendermint/mempool" mempl "github.com/tendermint/tendermint/mempool"
"github.com/tendermint/tendermint/proxy" "github.com/tendermint/tendermint/proxy"
rpccore "github.com/tendermint/tendermint/rpc/core" rpccore "github.com/tendermint/tendermint/rpc/core"
grpccore "github.com/tendermint/tendermint/rpc/grpc"
sm "github.com/tendermint/tendermint/state" sm "github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/version" "github.com/tendermint/tendermint/version"
@ -218,6 +219,17 @@ func (n *Node) StartRPC() ([]net.Listener, error) {
} }
listeners[i] = listener listeners[i] = listener
} }
// we expose a simplified api over grpc for convenience to app devs
grpcListenAddr := n.config.GetString("grpc_laddr")
if grpcListenAddr != "" {
listener, err := grpccore.StartGRPCServer(grpcListenAddr)
if err != nil {
return nil, err
}
listeners = append(listeners, listener)
}
return listeners, nil return listeners, nil
} }


+ 18
- 0
rpc/grpc/api.go View File

@ -0,0 +1,18 @@
package core_grpc
import (
core "github.com/tendermint/tendermint/rpc/core"
context "golang.org/x/net/context"
)
type broadcastAPI struct {
}
func (bapi *broadcastAPI) BroadcastTx(ctx context.Context, req *RequestBroadcastTx) (*ResponseBroadcastTx, error) {
res, err := core.BroadcastTxCommit(req.Tx)
if res == nil {
return nil, err
}
return &ResponseBroadcastTx{uint64(res.Code), res.Data, res.Log}, err
}

+ 44
- 0
rpc/grpc/client_server.go View File

@ -0,0 +1,44 @@
package core_grpc
import (
"fmt"
"net"
"strings"
"time"
"google.golang.org/grpc"
. "github.com/tendermint/go-common"
)
// Start the grpcServer in a go routine
func StartGRPCServer(protoAddr string) (net.Listener, error) {
parts := strings.SplitN(protoAddr, "://", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("Invalid listen address for grpc server (did you forget a tcp:// prefix?) : %s", protoAddr)
}
proto, addr := parts[0], parts[1]
ln, err := net.Listen(proto, addr)
if err != nil {
return nil, err
}
grpcServer := grpc.NewServer()
RegisterBroadcastAPIServer(grpcServer, &broadcastAPI{})
go grpcServer.Serve(ln)
return ln, nil
}
// Start the client by dialing the server
func StartGRPCClient(protoAddr string) BroadcastAPIClient {
conn, err := grpc.Dial(protoAddr, grpc.WithInsecure(), grpc.WithDialer(dialerFunc))
if err != nil {
panic(err)
}
return NewBroadcastAPIClient(conn)
}
func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) {
return Connect(addr)
}

+ 336
- 0
rpc/grpc/types.pb.go View File

@ -0,0 +1,336 @@
// Code generated by protoc-gen-go.
// source: types.proto
// DO NOT EDIT!
/*
Package core_grpc is a generated protocol buffer package.
It is generated from these files:
types.proto
It has these top-level messages:
Request
RequestBroadcastTx
Response
ResponseBroadcastTx
*/
package core_grpc
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type Request struct {
// Types that are valid to be assigned to Value:
// *Request_BroadcastTx
Value isRequest_Value `protobuf_oneof:"value"`
}
func (m *Request) Reset() { *m = Request{} }
func (m *Request) String() string { return proto.CompactTextString(m) }
func (*Request) ProtoMessage() {}
func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type isRequest_Value interface {
isRequest_Value()
}
type Request_BroadcastTx struct {
BroadcastTx *RequestBroadcastTx `protobuf:"bytes,1,opt,name=broadcast_tx,json=broadcastTx,oneof"`
}
func (*Request_BroadcastTx) isRequest_Value() {}
func (m *Request) GetValue() isRequest_Value {
if m != nil {
return m.Value
}
return nil
}
func (m *Request) GetBroadcastTx() *RequestBroadcastTx {
if x, ok := m.GetValue().(*Request_BroadcastTx); ok {
return x.BroadcastTx
}
return nil
}
// XXX_OneofFuncs is for the internal use of the proto package.
func (*Request) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
return _Request_OneofMarshaler, _Request_OneofUnmarshaler, _Request_OneofSizer, []interface{}{
(*Request_BroadcastTx)(nil),
}
}
func _Request_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*Request)
// value
switch x := m.Value.(type) {
case *Request_BroadcastTx:
b.EncodeVarint(1<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.BroadcastTx); err != nil {
return err
}
case nil:
default:
return fmt.Errorf("Request.Value has unexpected type %T", x)
}
return nil
}
func _Request_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*Request)
switch tag {
case 1: // value.broadcast_tx
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(RequestBroadcastTx)
err := b.DecodeMessage(msg)
m.Value = &Request_BroadcastTx{msg}
return true, err
default:
return false, nil
}
}
func _Request_OneofSizer(msg proto.Message) (n int) {
m := msg.(*Request)
// value
switch x := m.Value.(type) {
case *Request_BroadcastTx:
s := proto.Size(x.BroadcastTx)
n += proto.SizeVarint(1<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case nil:
default:
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
}
return n
}
type RequestBroadcastTx struct {
Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"`
}
func (m *RequestBroadcastTx) Reset() { *m = RequestBroadcastTx{} }
func (m *RequestBroadcastTx) String() string { return proto.CompactTextString(m) }
func (*RequestBroadcastTx) ProtoMessage() {}
func (*RequestBroadcastTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
type Response struct {
// Types that are valid to be assigned to Value:
// *Response_BroadcastTx
Value isResponse_Value `protobuf_oneof:"value"`
}
func (m *Response) Reset() { *m = Response{} }
func (m *Response) String() string { return proto.CompactTextString(m) }
func (*Response) ProtoMessage() {}
func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
type isResponse_Value interface {
isResponse_Value()
}
type Response_BroadcastTx struct {
BroadcastTx *ResponseBroadcastTx `protobuf:"bytes,1,opt,name=broadcast_tx,json=broadcastTx,oneof"`
}
func (*Response_BroadcastTx) isResponse_Value() {}
func (m *Response) GetValue() isResponse_Value {
if m != nil {
return m.Value
}
return nil
}
func (m *Response) GetBroadcastTx() *ResponseBroadcastTx {
if x, ok := m.GetValue().(*Response_BroadcastTx); ok {
return x.BroadcastTx
}
return nil
}
// XXX_OneofFuncs is for the internal use of the proto package.
func (*Response) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
return _Response_OneofMarshaler, _Response_OneofUnmarshaler, _Response_OneofSizer, []interface{}{
(*Response_BroadcastTx)(nil),
}
}
func _Response_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*Response)
// value
switch x := m.Value.(type) {
case *Response_BroadcastTx:
b.EncodeVarint(1<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.BroadcastTx); err != nil {
return err
}
case nil:
default:
return fmt.Errorf("Response.Value has unexpected type %T", x)
}
return nil
}
func _Response_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*Response)
switch tag {
case 1: // value.broadcast_tx
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(ResponseBroadcastTx)
err := b.DecodeMessage(msg)
m.Value = &Response_BroadcastTx{msg}
return true, err
default:
return false, nil
}
}
func _Response_OneofSizer(msg proto.Message) (n int) {
m := msg.(*Response)
// value
switch x := m.Value.(type) {
case *Response_BroadcastTx:
s := proto.Size(x.BroadcastTx)
n += proto.SizeVarint(1<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case nil:
default:
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
}
return n
}
type ResponseBroadcastTx struct {
Code uint64 `protobuf:"varint,1,opt,name=code" json:"code,omitempty"`
Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"`
}
func (m *ResponseBroadcastTx) Reset() { *m = ResponseBroadcastTx{} }
func (m *ResponseBroadcastTx) String() string { return proto.CompactTextString(m) }
func (*ResponseBroadcastTx) ProtoMessage() {}
func (*ResponseBroadcastTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func init() {
proto.RegisterType((*Request)(nil), "core_grpc.Request")
proto.RegisterType((*RequestBroadcastTx)(nil), "core_grpc.RequestBroadcastTx")
proto.RegisterType((*Response)(nil), "core_grpc.Response")
proto.RegisterType((*ResponseBroadcastTx)(nil), "core_grpc.ResponseBroadcastTx")
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion3
// Client API for BroadcastAPI service
type BroadcastAPIClient interface {
BroadcastTx(ctx context.Context, in *RequestBroadcastTx, opts ...grpc.CallOption) (*ResponseBroadcastTx, error)
}
type broadcastAPIClient struct {
cc *grpc.ClientConn
}
func NewBroadcastAPIClient(cc *grpc.ClientConn) BroadcastAPIClient {
return &broadcastAPIClient{cc}
}
func (c *broadcastAPIClient) BroadcastTx(ctx context.Context, in *RequestBroadcastTx, opts ...grpc.CallOption) (*ResponseBroadcastTx, error) {
out := new(ResponseBroadcastTx)
err := grpc.Invoke(ctx, "/core_grpc.BroadcastAPI/BroadcastTx", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for BroadcastAPI service
type BroadcastAPIServer interface {
BroadcastTx(context.Context, *RequestBroadcastTx) (*ResponseBroadcastTx, error)
}
func RegisterBroadcastAPIServer(s *grpc.Server, srv BroadcastAPIServer) {
s.RegisterService(&_BroadcastAPI_serviceDesc, srv)
}
func _BroadcastAPI_BroadcastTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RequestBroadcastTx)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BroadcastAPIServer).BroadcastTx(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/core_grpc.BroadcastAPI/BroadcastTx",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BroadcastAPIServer).BroadcastTx(ctx, req.(*RequestBroadcastTx))
}
return interceptor(ctx, in, info, handler)
}
var _BroadcastAPI_serviceDesc = grpc.ServiceDesc{
ServiceName: "core_grpc.BroadcastAPI",
HandlerType: (*BroadcastAPIServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "BroadcastTx",
Handler: _BroadcastAPI_BroadcastTx_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: fileDescriptor0,
}
func init() { proto.RegisterFile("types.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 222 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x2e, 0xa9, 0x2c, 0x48,
0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4c, 0xce, 0x2f, 0x4a, 0x8d, 0x4f, 0x2f,
0x2a, 0x48, 0x56, 0x0a, 0xe3, 0x62, 0x0f, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0x72, 0xe2,
0xe2, 0x49, 0x2a, 0xca, 0x4f, 0x4c, 0x49, 0x4e, 0x2c, 0x2e, 0x89, 0x2f, 0xa9, 0x90, 0x60, 0x54,
0x60, 0xd4, 0xe0, 0x36, 0x92, 0xd5, 0x83, 0x2b, 0xd6, 0x83, 0xaa, 0x74, 0x82, 0xa9, 0x0a, 0xa9,
0xf0, 0x60, 0x08, 0xe2, 0x4e, 0x42, 0x70, 0x9d, 0xd8, 0xb9, 0x58, 0xcb, 0x12, 0x73, 0x4a, 0x53,
0x95, 0x54, 0xb8, 0x84, 0x30, 0x55, 0x0b, 0xf1, 0x71, 0x31, 0x41, 0x0d, 0xe6, 0x09, 0x02, 0xb2,
0x94, 0x22, 0xb8, 0x38, 0x82, 0x52, 0x8b, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x85, 0x9c, 0xb1, 0x5a,
0x2f, 0x87, 0x62, 0x3d, 0x44, 0x29, 0x31, 0xf6, 0xfb, 0x73, 0x09, 0x63, 0x51, 0x2e, 0x24, 0xc4,
0xc5, 0x92, 0x9c, 0x9f, 0x92, 0x0a, 0x36, 0x9c, 0x25, 0x08, 0xcc, 0x06, 0x89, 0xa5, 0x24, 0x96,
0x24, 0x4a, 0x30, 0x81, 0x9d, 0x05, 0x66, 0x0b, 0x09, 0x70, 0x31, 0xe7, 0xe4, 0xa7, 0x4b, 0x30,
0x03, 0x85, 0x38, 0x83, 0x40, 0x4c, 0xa3, 0x18, 0x2e, 0x1e, 0xb8, 0x41, 0x8e, 0x01, 0x9e, 0x42,
0x3e, 0x5c, 0xdc, 0xc8, 0x06, 0xe3, 0x0f, 0x26, 0x29, 0x02, 0xde, 0x48, 0x62, 0x03, 0x47, 0x8c,
0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xb2, 0x77, 0xda, 0x85, 0xa7, 0x01, 0x00, 0x00,
}

+ 41
- 0
rpc/grpc/types.proto View File

@ -0,0 +1,41 @@
syntax = "proto3";
package core_grpc;
//----------------------------------------
// Message types
//----------------------------------------
// Request types
message Request {
oneof value{
RequestBroadcastTx broadcast_tx = 1;
}
}
message RequestBroadcastTx {
bytes tx = 1;
}
//----------------------------------------
// Response types
message Response {
oneof value{
ResponseBroadcastTx broadcast_tx = 1;
}
}
message ResponseBroadcastTx{
uint64 code = 1; // TODO: import tmsp ...
bytes data = 2;
string log = 3;
}
//----------------------------------------
// Service Definition
service BroadcastAPI {
rpc BroadcastTx(RequestBroadcastTx) returns (ResponseBroadcastTx) ;
}

+ 21
- 0
rpc/test/grpc_test.go View File

@ -0,0 +1,21 @@
package rpctest
import (
"testing"
"golang.org/x/net/context"
"github.com/tendermint/tendermint/rpc/grpc"
)
//-------------------------------------------
func TestBroadcastTx(t *testing.T) {
res, err := clientGRPC.BroadcastTx(context.Background(), &core_grpc.RequestBroadcastTx{[]byte("this is a tx")})
if err != nil {
t.Fatal(err)
}
if res.Code != 0 {
t.Fatalf("Non-zero code: %d", res.Code)
}
}

+ 7
- 0
rpc/test/helpers.go View File

@ -13,6 +13,7 @@ import (
"github.com/tendermint/tendermint/config/tendermint_test" "github.com/tendermint/tendermint/config/tendermint_test"
nm "github.com/tendermint/tendermint/node" nm "github.com/tendermint/tendermint/node"
ctypes "github.com/tendermint/tendermint/rpc/core/types" ctypes "github.com/tendermint/tendermint/rpc/core/types"
"github.com/tendermint/tendermint/rpc/grpc"
) )
// global variables for use across all tests // global variables for use across all tests
@ -24,8 +25,10 @@ var (
requestAddr string requestAddr string
websocketAddr string websocketAddr string
websocketEndpoint string websocketEndpoint string
grpcAddr string
clientURI *client.ClientURI clientURI *client.ClientURI
clientJSON *client.ClientJSONRPC clientJSON *client.ClientJSONRPC
clientGRPC core_grpc.BroadcastAPIClient
) )
// initialize config and create new node // initialize config and create new node
@ -33,12 +36,14 @@ func init() {
config = tendermint_test.ResetConfig("rpc_test_client_test") config = tendermint_test.ResetConfig("rpc_test_client_test")
chainID = config.GetString("chain_id") chainID = config.GetString("chain_id")
rpcAddr = config.GetString("rpc_laddr") rpcAddr = config.GetString("rpc_laddr")
grpcAddr = config.GetString("grpc_laddr")
requestAddr = rpcAddr requestAddr = rpcAddr
websocketAddr = rpcAddr websocketAddr = rpcAddr
websocketEndpoint = "/websocket" websocketEndpoint = "/websocket"
clientURI = client.NewClientURI(requestAddr) clientURI = client.NewClientURI(requestAddr)
clientJSON = client.NewClientJSONRPC(requestAddr) clientJSON = client.NewClientJSONRPC(requestAddr)
clientGRPC = core_grpc.StartGRPCClient(grpcAddr)
// TODO: change consensus/state.go timeouts to be shorter // TODO: change consensus/state.go timeouts to be shorter
@ -59,6 +64,8 @@ func newNode(ready chan struct{}) {
// Run the RPC server. // Run the RPC server.
node.StartRPC() node.StartRPC()
time.Sleep(time.Second)
ready <- struct{}{} ready <- struct{}{}
// Sleep forever // Sleep forever


+ 31
- 4
test/app/counter_test.sh View File

@ -9,10 +9,37 @@ TESTNAME=$1
function sendTx() { function sendTx() {
TX=$1 TX=$1
RESPONSE=`curl -s localhost:46657/broadcast_tx_commit?tx=\"$TX\"`
CODE=`echo $RESPONSE | jq .result[1].code`
ERROR=`echo $RESPONSE | jq .error`
ERROR=$(echo "$ERROR" | tr -d '"') # remove surrounding quotes
if [[ "$GRPC_BROADCAST_TX" == "" ]]; then
RESPONSE=`curl -s localhost:46657/broadcast_tx_commit?tx=\"$TX\"`
CODE=`echo $RESPONSE | jq .result[1].code`
ERROR=`echo $RESPONSE | jq .error`
ERROR=$(echo "$ERROR" | tr -d '"') # remove surrounding quotes
else
RESPONSE=`go run grpc_client.go $TX`
echo $RESPONSE | jq . &> /dev/null
IS_JSON=$?
if [[ "$IS_JSON" != "0" ]]; then
ERROR="$RESPONSE"
else
ERROR="" # reset
fi
if [[ "$RESPONSE" == "{}" ]]; then
# protobuf auto adds `omitempty` to everything so code OK and empty data/log
# will not even show when marshalled into json
# apparently we can use github.com/golang/protobuf/jsonpb to do the marshalling ...
CODE=0
else
# this wont actually work if theres an error ...
CODE=`echo $RESPONSE | jq .code`
fi
#echo "-------"
#echo "TX $TX"
#echo "RESPONSE $RESPONSE"
#echo "CODE $CODE"
#echo "ERROR $ERROR"
#echo "----"
fi
} }
# 0 should pass once and get in block, with no error # 0 should pass once and get in block, with no error


+ 36
- 0
test/app/grpc_client.go View File

@ -0,0 +1,36 @@
package main
import (
"encoding/hex"
"fmt"
"os"
"golang.org/x/net/context"
"github.com/tendermint/go-wire"
"github.com/tendermint/tendermint/rpc/grpc"
)
var grpcAddr = "tcp://localhost:36656"
func main() {
args := os.Args
if len(args) == 1 {
fmt.Println("Must enter a transaction to send (hex)")
os.Exit(1)
}
tx := args[1]
txBytes, err := hex.DecodeString(tx)
if err != nil {
fmt.Println("Invalid hex", err)
os.Exit(1)
}
clientGRPC := core_grpc.StartGRPCClient(grpcAddr)
res, err := clientGRPC.BroadcastTx(context.Background(), &core_grpc.RequestBroadcastTx{txBytes})
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(string(wire.JSONBytes(res)))
}

+ 22
- 0
test/app/test.sh View File

@ -77,6 +77,23 @@ function counter_over_grpc() {
kill -9 $pid_counter $pid_tendermint kill -9 $pid_counter $pid_tendermint
} }
function counter_over_grpc_grpc() {
rm -rf $TMROOT
tendermint init
echo "Starting counter and tendermint"
counter --serial --tmsp grpc > /dev/null &
pid_counter=$!
GRPC_PORT=36656
tendermint node --tmsp grpc --grpc_laddr tcp://localhost:$GRPC_PORT > tendermint.log &
pid_tendermint=$!
sleep 5
echo "running test"
GRPC_BROADCAST_TX=true bash counter_test.sh "Counter over GRPC via GRPC BroadcastTx"
kill -9 $pid_counter $pid_tendermint
}
cd $GOPATH/src/github.com/tendermint/tendermint/test/app cd $GOPATH/src/github.com/tendermint/tendermint/test/app
case "$1" in case "$1" in
@ -92,6 +109,9 @@ case "$1" in
"counter_over_grpc") "counter_over_grpc")
counter_over_grpc counter_over_grpc
;; ;;
"counter_over_grpc_grpc")
counter_over_grpc_grpc
;;
*) *)
echo "Running all" echo "Running all"
dummy_over_socket dummy_over_socket
@ -101,5 +121,7 @@ case "$1" in
counter_over_socket counter_over_socket
echo "" echo ""
counter_over_grpc counter_over_grpc
echo ""
counter_over_grpc_grpc
esac esac

Loading…
Cancel
Save