Browse Source

rpc: replace Amino with new JSON encoder (#4968)

Migrates the `rpc` package to use new JSON encoder in #4955. Branched off of that PR.

Tests pass, but I haven't done any manual testing beyond that. This should be handled as part of broader 0.34 testing.
pull/4988/head
Erik Grinaker 5 years ago
committed by GitHub
parent
commit
ba3a2dde37
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 105 additions and 204 deletions
  1. +0
    -2
      cmd/tendermint/commands/lite.go
  2. +6
    -0
      crypto/ed25519/ed25519.go
  3. +2
    -8
      light/proxy/proxy.go
  4. +0
    -1
      light/rpc/client.go
  5. +2
    -6
      node/node.go
  6. +0
    -13
      rpc/client/codec.go
  7. +4
    -11
      rpc/client/http/http.go
  8. +0
    -1
      rpc/core/events.go
  9. +0
    -1
      rpc/core/routes.go
  10. +0
    -12
      rpc/core/types/codec.go
  11. +1
    -4
      rpc/jsonrpc/client/args_test.go
  12. +3
    -6
      rpc/jsonrpc/client/decode.go
  13. +5
    -5
      rpc/jsonrpc/client/encode.go
  14. +4
    -18
      rpc/jsonrpc/client/http_json_client.go
  15. +2
    -12
      rpc/jsonrpc/client/http_uri_client.go
  16. +2
    -9
      rpc/jsonrpc/client/ws_client.go
  17. +4
    -9
      rpc/jsonrpc/jsonrpc_test.go
  18. +9
    -12
      rpc/jsonrpc/server/http_json_handler.go
  19. +1
    -4
      rpc/jsonrpc/server/http_json_handler_test.go
  20. +15
    -16
      rpc/jsonrpc/server/http_uri_handler.go
  21. +2
    -5
      rpc/jsonrpc/server/parse_test.go
  22. +3
    -5
      rpc/jsonrpc/server/rpc_func.go
  23. +3
    -17
      rpc/jsonrpc/server/ws_handler.go
  24. +1
    -4
      rpc/jsonrpc/server/ws_handler_test.go
  25. +1
    -4
      rpc/jsonrpc/test/main.go
  26. +9
    -11
      rpc/jsonrpc/types/types.go
  27. +2
    -5
      rpc/jsonrpc/types/types_test.go
  28. +2
    -2
      rpc/swagger/swagger.yaml
  29. +0
    -1
      rpc/test/helpers.go
  30. +13
    -0
      types/events.go
  31. +9
    -0
      types/evidence.go

+ 0
- 2
cmd/tendermint/commands/lite.go View File

@ -9,7 +9,6 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/tendermint/go-amino"
dbm "github.com/tendermint/tm-db" dbm "github.com/tendermint/tm-db"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
@ -152,7 +151,6 @@ func runProxy(cmd *cobra.Command, args []string) error {
p := lproxy.Proxy{ p := lproxy.Proxy{
Addr: listenAddr, Addr: listenAddr,
Config: cfg, Config: cfg,
Codec: amino.NewCodec(),
Client: lrpc.NewClient(rpcClient, c), Client: lrpc.NewClient(rpcClient, c),
Logger: logger, Logger: logger,
} }


+ 6
- 0
crypto/ed25519/ed25519.go View File

@ -10,6 +10,7 @@ import (
"github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/tmhash" "github.com/tendermint/tendermint/crypto/tmhash"
tmjson "github.com/tendermint/tendermint/libs/json"
) )
//------------------------------------- //-------------------------------------
@ -31,6 +32,11 @@ const (
SeedSize = 32 SeedSize = 32
) )
func init() {
tmjson.RegisterType(PubKey{}, PubKeyAminoName)
tmjson.RegisterType(PrivKey{}, PrivKeyAminoName)
}
// PrivKey implements crypto.PrivKey. // PrivKey implements crypto.PrivKey.
type PrivKey []byte type PrivKey []byte


+ 2
- 8
light/proxy/proxy.go View File

@ -6,12 +6,9 @@ import (
"net" "net"
"net/http" "net/http"
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
tmpubsub "github.com/tendermint/tendermint/libs/pubsub" tmpubsub "github.com/tendermint/tendermint/libs/pubsub"
lrpc "github.com/tendermint/tendermint/light/rpc" lrpc "github.com/tendermint/tendermint/light/rpc"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
rpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server" rpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server"
) )
@ -19,7 +16,6 @@ import (
type Proxy struct { type Proxy struct {
Addr string // TCP address to listen on, ":http" if empty Addr string // TCP address to listen on, ":http" if empty
Config *rpcserver.Config Config *rpcserver.Config
Codec *amino.Codec
Client *lrpc.Client Client *lrpc.Client
Logger log.Logger Logger log.Logger
Listener net.Listener Listener net.Listener
@ -65,17 +61,15 @@ func (p *Proxy) ListenAndServeTLS(certFile, keyFile string) error {
} }
func (p *Proxy) listen() (net.Listener, *http.ServeMux, error) { func (p *Proxy) listen() (net.Listener, *http.ServeMux, error) {
ctypes.RegisterAmino(p.Codec)
mux := http.NewServeMux() mux := http.NewServeMux()
// 1) Register regular routes. // 1) Register regular routes.
r := RPCRoutes(p.Client) r := RPCRoutes(p.Client)
rpcserver.RegisterRPCFuncs(mux, r, p.Codec, p.Logger)
rpcserver.RegisterRPCFuncs(mux, r, p.Logger)
// 2) Allow websocket connections. // 2) Allow websocket connections.
wmLogger := p.Logger.With("protocol", "websocket") wmLogger := p.Logger.With("protocol", "websocket")
wm := rpcserver.NewWebsocketManager(r, p.Codec,
wm := rpcserver.NewWebsocketManager(r,
rpcserver.OnDisconnect(func(remoteAddr string) { rpcserver.OnDisconnect(func(remoteAddr string) {
err := p.Client.UnsubscribeAll(context.Background(), remoteAddr) err := p.Client.UnsubscribeAll(context.Background(), remoteAddr)
if err != nil && err != tmpubsub.ErrSubscriptionNotFound { if err != nil && err != tmpubsub.ErrSubscriptionNotFound {


+ 0
- 1
light/rpc/client.go View File

@ -479,7 +479,6 @@ func (c *Client) SubscribeWS(ctx *rpctypes.Context, query string) (*ctypes.Resul
// depending on the event's type. // depending on the event's type.
ctx.WSConn.TryWriteRPCResponse( ctx.WSConn.TryWriteRPCResponse(
rpctypes.NewRPCSuccessResponse( rpctypes.NewRPCSuccessResponse(
ctx.WSConn.Codec(),
rpctypes.JSONRPCStringID(fmt.Sprintf("%v#event", ctx.JSONReq.ID)), rpctypes.JSONRPCStringID(fmt.Sprintf("%v#event", ctx.JSONReq.ID)),
resultEvent, resultEvent,
)) ))


+ 2
- 6
node/node.go View File

@ -15,7 +15,6 @@ import (
"github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/rs/cors" "github.com/rs/cors"
amino "github.com/tendermint/go-amino"
dbm "github.com/tendermint/tm-db" dbm "github.com/tendermint/tm-db"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
@ -36,7 +35,6 @@ import (
"github.com/tendermint/tendermint/privval" "github.com/tendermint/tendermint/privval"
"github.com/tendermint/tendermint/proxy" "github.com/tendermint/tendermint/proxy"
rpccore "github.com/tendermint/tendermint/rpc/core" rpccore "github.com/tendermint/tendermint/rpc/core"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
grpccore "github.com/tendermint/tendermint/rpc/grpc" grpccore "github.com/tendermint/tendermint/rpc/grpc"
rpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server" rpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server"
sm "github.com/tendermint/tendermint/state" sm "github.com/tendermint/tendermint/state"
@ -989,8 +987,6 @@ func (n *Node) startRPC() ([]net.Listener, error) {
} }
listenAddrs := splitAndTrimEmpty(n.config.RPC.ListenAddress, ",", " ") listenAddrs := splitAndTrimEmpty(n.config.RPC.ListenAddress, ",", " ")
coreCodec := amino.NewCodec()
ctypes.RegisterAmino(coreCodec)
if n.config.RPC.Unsafe { if n.config.RPC.Unsafe {
rpccore.AddUnsafeRoutes() rpccore.AddUnsafeRoutes()
@ -1013,7 +1009,7 @@ func (n *Node) startRPC() ([]net.Listener, error) {
mux := http.NewServeMux() mux := http.NewServeMux()
rpcLogger := n.Logger.With("module", "rpc-server") rpcLogger := n.Logger.With("module", "rpc-server")
wmLogger := rpcLogger.With("protocol", "websocket") wmLogger := rpcLogger.With("protocol", "websocket")
wm := rpcserver.NewWebsocketManager(rpccore.Routes, coreCodec,
wm := rpcserver.NewWebsocketManager(rpccore.Routes,
rpcserver.OnDisconnect(func(remoteAddr string) { rpcserver.OnDisconnect(func(remoteAddr string) {
err := n.eventBus.UnsubscribeAll(context.Background(), remoteAddr) err := n.eventBus.UnsubscribeAll(context.Background(), remoteAddr)
if err != nil && err != tmpubsub.ErrSubscriptionNotFound { if err != nil && err != tmpubsub.ErrSubscriptionNotFound {
@ -1024,7 +1020,7 @@ func (n *Node) startRPC() ([]net.Listener, error) {
) )
wm.SetLogger(wmLogger) wm.SetLogger(wmLogger)
mux.HandleFunc("/websocket", wm.WebsocketHandler) mux.HandleFunc("/websocket", wm.WebsocketHandler)
rpcserver.RegisterRPCFuncs(mux, rpccore.Routes, coreCodec, rpcLogger)
rpcserver.RegisterRPCFuncs(mux, rpccore.Routes, rpcLogger)
listener, err := rpcserver.Listen( listener, err := rpcserver.Listen(
listenAddr, listenAddr,
config, config,


+ 0
- 13
rpc/client/codec.go View File

@ -1,13 +0,0 @@
package client
import (
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/types"
)
var cdc = amino.NewCodec()
func init() {
types.RegisterEvidences(cdc)
}

+ 4
- 11
rpc/client/http/http.go View File

@ -8,9 +8,8 @@ import (
"sync" "sync"
"time" "time"
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/libs/bytes" "github.com/tendermint/tendermint/libs/bytes"
tmjson "github.com/tendermint/tendermint/libs/json"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
tmpubsub "github.com/tendermint/tendermint/libs/pubsub" tmpubsub "github.com/tendermint/tendermint/libs/pubsub"
"github.com/tendermint/tendermint/libs/service" "github.com/tendermint/tendermint/libs/service"
@ -138,11 +137,8 @@ func NewWithClient(remote, wsEndpoint string, client *http.Client) (*HTTP, error
if err != nil { if err != nil {
return nil, err return nil, err
} }
cdc := rc.Codec()
ctypes.RegisterAmino(cdc)
rc.SetCodec(cdc)
wsEvents, err := newWSEvents(cdc, remote, wsEndpoint)
wsEvents, err := newWSEvents(remote, wsEndpoint)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -479,7 +475,6 @@ var errNotRunning = errors.New("client is not running. Use .Start() method to st
// WSEvents is a wrapper around WSClient, which implements EventsClient. // WSEvents is a wrapper around WSClient, which implements EventsClient.
type WSEvents struct { type WSEvents struct {
service.BaseService service.BaseService
cdc *amino.Codec
remote string remote string
endpoint string endpoint string
ws *jsonrpcclient.WSClient ws *jsonrpcclient.WSClient
@ -488,9 +483,8 @@ type WSEvents struct {
subscriptions map[string]chan ctypes.ResultEvent // query -> chan subscriptions map[string]chan ctypes.ResultEvent // query -> chan
} }
func newWSEvents(cdc *amino.Codec, remote, endpoint string) (*WSEvents, error) {
func newWSEvents(remote, endpoint string) (*WSEvents, error) {
w := &WSEvents{ w := &WSEvents{
cdc: cdc,
endpoint: endpoint, endpoint: endpoint,
remote: remote, remote: remote,
subscriptions: make(map[string]chan ctypes.ResultEvent), subscriptions: make(map[string]chan ctypes.ResultEvent),
@ -505,7 +499,6 @@ func newWSEvents(cdc *amino.Codec, remote, endpoint string) (*WSEvents, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
w.ws.SetCodec(w.cdc)
w.ws.SetLogger(w.Logger) w.ws.SetLogger(w.Logger)
return w, nil return w, nil
@ -645,7 +638,7 @@ func (w *WSEvents) eventListener() {
} }
result := new(ctypes.ResultEvent) result := new(ctypes.ResultEvent)
err := w.cdc.UnmarshalJSON(resp.Result, result)
err := tmjson.Unmarshal(resp.Result, result)
if err != nil { if err != nil {
w.Logger.Error("failed to unmarshal response", "err", err) w.Logger.Error("failed to unmarshal response", "err", err)
continue continue


+ 0
- 1
rpc/core/events.go View File

@ -50,7 +50,6 @@ func Subscribe(ctx *rpctypes.Context, query string) (*ctypes.ResultSubscribe, er
resultEvent := &ctypes.ResultEvent{Query: query, Data: msg.Data(), Events: msg.Events()} resultEvent := &ctypes.ResultEvent{Query: query, Data: msg.Data(), Events: msg.Events()}
ctx.WSConn.TryWriteRPCResponse( ctx.WSConn.TryWriteRPCResponse(
rpctypes.NewRPCSuccessResponse( rpctypes.NewRPCSuccessResponse(
ctx.WSConn.Codec(),
subscriptionID, subscriptionID,
resultEvent, resultEvent,
)) ))


+ 0
- 1
rpc/core/routes.go View File

@ -5,7 +5,6 @@ import (
) )
// TODO: better system than "unsafe" prefix // TODO: better system than "unsafe" prefix
// NOTE: Amino is registered in rpc/core/types/codec.go.
var Routes = map[string]*rpc.RPCFunc{ var Routes = map[string]*rpc.RPCFunc{
// subscribe/unsubscribe are reserved for websocket events. // subscribe/unsubscribe are reserved for websocket events.


+ 0
- 12
rpc/core/types/codec.go View File

@ -1,12 +0,0 @@
package coretypes
import (
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/types"
)
func RegisterAmino(cdc *amino.Codec) {
types.RegisterEventDatas(cdc)
types.RegisterBlockAmino(cdc)
}

+ 1
- 4
rpc/jsonrpc/client/args_test.go View File

@ -5,7 +5,6 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
amino "github.com/tendermint/go-amino"
) )
type Tx []byte type Tx []byte
@ -28,11 +27,9 @@ func TestArgToJSON(t *testing.T) {
{Foo{7, "hello"}, `{"Bar":"7","Baz":"hello"}`}, {Foo{7, "hello"}, `{"Bar":"7","Baz":"hello"}`},
} }
cdc := amino.NewCodec()
for i, tc := range cases { for i, tc := range cases {
args := map[string]interface{}{"data": tc.input} args := map[string]interface{}{"data": tc.input}
err := argsToJSON(cdc, args)
err := argsToJSON(args)
require.Nil(err, "%d: %+v", i, err) require.Nil(err, "%d: %+v", i, err)
require.Equal(1, len(args), "%d", i) require.Equal(1, len(args), "%d", i)
data, ok := args["data"].(string) data, ok := args["data"].(string)


+ 3
- 6
rpc/jsonrpc/client/decode.go View File

@ -5,13 +5,11 @@ import (
"errors" "errors"
"fmt" "fmt"
amino "github.com/tendermint/go-amino"
tmjson "github.com/tendermint/tendermint/libs/json"
types "github.com/tendermint/tendermint/rpc/jsonrpc/types" types "github.com/tendermint/tendermint/rpc/jsonrpc/types"
) )
func unmarshalResponseBytes( func unmarshalResponseBytes(
cdc *amino.Codec,
responseBytes []byte, responseBytes []byte,
expectedID types.JSONRPCIntID, expectedID types.JSONRPCIntID,
result interface{}, result interface{},
@ -33,7 +31,7 @@ func unmarshalResponseBytes(
} }
// Unmarshal the RawMessage into the result. // Unmarshal the RawMessage into the result.
if err := cdc.UnmarshalJSON(response.Result, result); err != nil {
if err := tmjson.Unmarshal(response.Result, result); err != nil {
return nil, fmt.Errorf("error unmarshalling result: %w", err) return nil, fmt.Errorf("error unmarshalling result: %w", err)
} }
@ -41,7 +39,6 @@ func unmarshalResponseBytes(
} }
func unmarshalResponseBytesArray( func unmarshalResponseBytesArray(
cdc *amino.Codec,
responseBytes []byte, responseBytes []byte,
expectedIDs []types.JSONRPCIntID, expectedIDs []types.JSONRPCIntID,
results []interface{}, results []interface{},
@ -80,7 +77,7 @@ func unmarshalResponseBytesArray(
} }
for i := 0; i < len(responses); i++ { for i := 0; i < len(responses); i++ {
if err := cdc.UnmarshalJSON(responses[i].Result, results[i]); err != nil {
if err := tmjson.Unmarshal(responses[i].Result, results[i]); err != nil {
return nil, fmt.Errorf("error unmarshalling #%d result: %w", i, err) return nil, fmt.Errorf("error unmarshalling #%d result: %w", i, err)
} }
} }


+ 5
- 5
rpc/jsonrpc/client/encode.go View File

@ -5,16 +5,16 @@ import (
"net/url" "net/url"
"reflect" "reflect"
amino "github.com/tendermint/go-amino"
tmjson "github.com/tendermint/tendermint/libs/json"
) )
func argsToURLValues(cdc *amino.Codec, args map[string]interface{}) (url.Values, error) {
func argsToURLValues(args map[string]interface{}) (url.Values, error) {
values := make(url.Values) values := make(url.Values)
if len(args) == 0 { if len(args) == 0 {
return values, nil return values, nil
} }
err := argsToJSON(cdc, args)
err := argsToJSON(args)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -26,7 +26,7 @@ func argsToURLValues(cdc *amino.Codec, args map[string]interface{}) (url.Values,
return values, nil return values, nil
} }
func argsToJSON(cdc *amino.Codec, args map[string]interface{}) error {
func argsToJSON(args map[string]interface{}) error {
for k, v := range args { for k, v := range args {
rt := reflect.TypeOf(v) rt := reflect.TypeOf(v)
isByteSlice := rt.Kind() == reflect.Slice && rt.Elem().Kind() == reflect.Uint8 isByteSlice := rt.Kind() == reflect.Slice && rt.Elem().Kind() == reflect.Uint8
@ -36,7 +36,7 @@ func argsToJSON(cdc *amino.Codec, args map[string]interface{}) error {
continue continue
} }
data, err := cdc.MarshalJSON(v)
data, err := tmjson.Marshal(v)
if err != nil { if err != nil {
return err return err
} }


+ 4
- 18
rpc/jsonrpc/client/http_json_client.go View File

@ -11,8 +11,6 @@ import (
"strings" "strings"
"sync" "sync"
amino "github.com/tendermint/go-amino"
types "github.com/tendermint/tendermint/rpc/jsonrpc/types" types "github.com/tendermint/tendermint/rpc/jsonrpc/types"
) )
@ -81,10 +79,6 @@ func (u parsedURL) GetTrimmedURL() string {
type HTTPClient interface { type HTTPClient interface {
// Call calls the given method with the params and returns a result. // Call calls the given method with the params and returns a result.
Call(method string, params map[string]interface{}, result interface{}) (interface{}, error) Call(method string, params map[string]interface{}, result interface{}) (interface{}, error)
// Codec returns an amino codec used.
Codec() *amino.Codec
// SetCodec sets an amino codec.
SetCodec(*amino.Codec)
} }
// Caller implementers can facilitate calling the JSON-RPC endpoint. // Caller implementers can facilitate calling the JSON-RPC endpoint.
@ -97,9 +91,6 @@ type Caller interface {
// Client is a JSON-RPC client, which sends POST HTTP requests to the // Client is a JSON-RPC client, which sends POST HTTP requests to the
// remote server. // remote server.
// //
// Request values are amino encoded. Response is expected to be amino encoded.
// New amino codec is used if no other codec was set using SetCodec.
//
// Client is safe for concurrent use by multiple goroutines. // Client is safe for concurrent use by multiple goroutines.
type Client struct { type Client struct {
address string address string
@ -107,7 +98,6 @@ type Client struct {
password string password string
client *http.Client client *http.Client
cdc *amino.Codec
mtx sync.Mutex mtx sync.Mutex
nextReqID int nextReqID int
@ -154,7 +144,6 @@ func NewWithHTTPClient(remote string, client *http.Client) (*Client, error) {
username: username, username: username,
password: password, password: password,
client: client, client: client,
cdc: amino.NewCodec(),
} }
return rpcClient, nil return rpcClient, nil
@ -165,7 +154,7 @@ func NewWithHTTPClient(remote string, client *http.Client) (*Client, error) {
func (c *Client) Call(method string, params map[string]interface{}, result interface{}) (interface{}, error) { func (c *Client) Call(method string, params map[string]interface{}, result interface{}) (interface{}, error) {
id := c.nextRequestID() id := c.nextRequestID()
request, err := types.MapToRequest(c.cdc, id, method, params)
request, err := types.MapToRequest(id, method, params)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to encode params: %w", err) return nil, fmt.Errorf("failed to encode params: %w", err)
} }
@ -195,12 +184,9 @@ func (c *Client) Call(method string, params map[string]interface{}, result inter
return nil, fmt.Errorf("failed to read response body: %w", err) return nil, fmt.Errorf("failed to read response body: %w", err)
} }
return unmarshalResponseBytes(c.cdc, responseBytes, id, result)
return unmarshalResponseBytes(responseBytes, id, result)
} }
func (c *Client) Codec() *amino.Codec { return c.cdc }
func (c *Client) SetCodec(cdc *amino.Codec) { c.cdc = cdc }
// NewRequestBatch starts a batch of requests for this client. // NewRequestBatch starts a batch of requests for this client.
func (c *Client) NewRequestBatch() *RequestBatch { func (c *Client) NewRequestBatch() *RequestBatch {
return &RequestBatch{ return &RequestBatch{
@ -248,7 +234,7 @@ func (c *Client) sendBatch(requests []*jsonRPCBufferedRequest) ([]interface{}, e
ids[i] = req.request.ID.(types.JSONRPCIntID) ids[i] = req.request.ID.(types.JSONRPCIntID)
} }
return unmarshalResponseBytesArray(c.cdc, responseBytes, ids, results)
return unmarshalResponseBytesArray(responseBytes, ids, results)
} }
func (c *Client) nextRequestID() types.JSONRPCIntID { func (c *Client) nextRequestID() types.JSONRPCIntID {
@ -324,7 +310,7 @@ func (b *RequestBatch) Call(
result interface{}, result interface{},
) (interface{}, error) { ) (interface{}, error) {
id := b.client.nextRequestID() id := b.client.nextRequestID()
request, err := types.MapToRequest(b.client.cdc, id, method, params)
request, err := types.MapToRequest(id, method, params)
if err != nil { if err != nil {
return nil, err return nil, err
} }


+ 2
- 12
rpc/jsonrpc/client/http_uri_client.go View File

@ -5,8 +5,6 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
amino "github.com/tendermint/go-amino"
types "github.com/tendermint/tendermint/rpc/jsonrpc/types" types "github.com/tendermint/tendermint/rpc/jsonrpc/types"
) )
@ -18,14 +16,10 @@ const (
// URIClient is a JSON-RPC client, which sends POST form HTTP requests to the // URIClient is a JSON-RPC client, which sends POST form HTTP requests to the
// remote server. // remote server.
// //
// Request values are amino encoded. Response is expected to be amino encoded.
// New amino codec is used if no other codec was set using SetCodec.
//
// URIClient is safe for concurrent use by multiple goroutines. // URIClient is safe for concurrent use by multiple goroutines.
type URIClient struct { type URIClient struct {
address string address string
client *http.Client client *http.Client
cdc *amino.Codec
} }
var _ HTTPClient = (*URIClient)(nil) var _ HTTPClient = (*URIClient)(nil)
@ -49,7 +43,6 @@ func NewURI(remote string) (*URIClient, error) {
uriClient := &URIClient{ uriClient := &URIClient{
address: parsedURL.GetTrimmedURL(), address: parsedURL.GetTrimmedURL(),
client: httpClient, client: httpClient,
cdc: amino.NewCodec(),
} }
return uriClient, nil return uriClient, nil
@ -57,7 +50,7 @@ func NewURI(remote string) (*URIClient, error) {
// Call issues a POST form HTTP request. // Call issues a POST form HTTP request.
func (c *URIClient) Call(method string, params map[string]interface{}, result interface{}) (interface{}, error) { func (c *URIClient) Call(method string, params map[string]interface{}, result interface{}) (interface{}, error) {
values, err := argsToURLValues(c.cdc, params)
values, err := argsToURLValues(params)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to encode params: %w", err) return nil, fmt.Errorf("failed to encode params: %w", err)
} }
@ -73,8 +66,5 @@ func (c *URIClient) Call(method string, params map[string]interface{}, result in
return nil, fmt.Errorf("failed to read response body: %w", err) return nil, fmt.Errorf("failed to read response body: %w", err)
} }
return unmarshalResponseBytes(c.cdc, responseBytes, URIClientRequestID, result)
return unmarshalResponseBytes(responseBytes, URIClientRequestID, result)
} }
func (c *URIClient) Codec() *amino.Codec { return c.cdc }
func (c *URIClient) SetCodec(cdc *amino.Codec) { c.cdc = cdc }

+ 2
- 9
rpc/jsonrpc/client/ws_client.go View File

@ -12,8 +12,6 @@ import (
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
metrics "github.com/rcrowley/go-metrics" metrics "github.com/rcrowley/go-metrics"
amino "github.com/tendermint/go-amino"
tmrand "github.com/tendermint/tendermint/libs/rand" tmrand "github.com/tendermint/tendermint/libs/rand"
"github.com/tendermint/tendermint/libs/service" "github.com/tendermint/tendermint/libs/service"
types "github.com/tendermint/tendermint/rpc/jsonrpc/types" types "github.com/tendermint/tendermint/rpc/jsonrpc/types"
@ -32,7 +30,6 @@ const (
// WSClient is safe for concurrent use by multiple goroutines. // WSClient is safe for concurrent use by multiple goroutines.
type WSClient struct { // nolint: maligned type WSClient struct { // nolint: maligned
conn *websocket.Conn conn *websocket.Conn
cdc *amino.Codec
Address string // IP:PORT or /path/to/socket Address string // IP:PORT or /path/to/socket
Endpoint string // /websocket/url/endpoint Endpoint string // /websocket/url/endpoint
@ -101,7 +98,6 @@ func NewWS(remoteAddr, endpoint string, options ...func(*WSClient)) (*WSClient,
} }
c := &WSClient{ c := &WSClient{
cdc: amino.NewCodec(),
Address: parsedURL.GetTrimmedHostWithPath(), Address: parsedURL.GetTrimmedHostWithPath(),
Dialer: dialFn, Dialer: dialFn,
Endpoint: endpoint, Endpoint: endpoint,
@ -234,7 +230,7 @@ func (c *WSClient) Send(ctx context.Context, request types.RPCRequest) error {
// Call enqueues a call request onto the Send queue. Requests are JSON encoded. // Call enqueues a call request onto the Send queue. Requests are JSON encoded.
func (c *WSClient) Call(ctx context.Context, method string, params map[string]interface{}) error { func (c *WSClient) Call(ctx context.Context, method string, params map[string]interface{}) error {
request, err := types.MapToRequest(c.cdc, c.nextRequestID(), method, params)
request, err := types.MapToRequest(c.nextRequestID(), method, params)
if err != nil { if err != nil {
return err return err
} }
@ -244,16 +240,13 @@ func (c *WSClient) Call(ctx context.Context, method string, params map[string]in
// CallWithArrayParams enqueues a call request onto the Send queue. Params are // CallWithArrayParams enqueues a call request onto the Send queue. Params are
// in a form of array (e.g. []interface{}{"abcd"}). Requests are JSON encoded. // in a form of array (e.g. []interface{}{"abcd"}). Requests are JSON encoded.
func (c *WSClient) CallWithArrayParams(ctx context.Context, method string, params []interface{}) error { func (c *WSClient) CallWithArrayParams(ctx context.Context, method string, params []interface{}) error {
request, err := types.ArrayToRequest(c.cdc, c.nextRequestID(), method, params)
request, err := types.ArrayToRequest(c.nextRequestID(), method, params)
if err != nil { if err != nil {
return err return err
} }
return c.Send(ctx, request) return c.Send(ctx, request)
} }
func (c *WSClient) Codec() *amino.Codec { return c.cdc }
func (c *WSClient) SetCodec(cdc *amino.Codec) { c.cdc = cdc }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Private methods // Private methods


+ 4
- 9
rpc/jsonrpc/jsonrpc_test.go View File

@ -16,8 +16,6 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
amino "github.com/tendermint/go-amino"
tmbytes "github.com/tendermint/tendermint/libs/bytes" tmbytes "github.com/tendermint/tendermint/libs/bytes"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
tmrand "github.com/tendermint/tendermint/libs/rand" tmrand "github.com/tendermint/tendermint/libs/rand"
@ -64,9 +62,6 @@ var Routes = map[string]*server.RPCFunc{
"echo_int": server.NewRPCFunc(EchoIntResult, "arg"), "echo_int": server.NewRPCFunc(EchoIntResult, "arg"),
} }
// Amino codec required to encode/decode everything above.
var RoutesCdc = amino.NewCodec()
func EchoResult(ctx *types.Context, v string) (*ResultEcho, error) { func EchoResult(ctx *types.Context, v string) (*ResultEcho, error) {
return &ResultEcho{v}, nil return &ResultEcho{v}, nil
} }
@ -121,8 +116,8 @@ func setup() {
tcpLogger := logger.With("socket", "tcp") tcpLogger := logger.With("socket", "tcp")
mux := http.NewServeMux() mux := http.NewServeMux()
server.RegisterRPCFuncs(mux, Routes, RoutesCdc, tcpLogger)
wm := server.NewWebsocketManager(Routes, RoutesCdc, server.ReadWait(5*time.Second), server.PingPeriod(1*time.Second))
server.RegisterRPCFuncs(mux, Routes, tcpLogger)
wm := server.NewWebsocketManager(Routes, server.ReadWait(5*time.Second), server.PingPeriod(1*time.Second))
wm.SetLogger(tcpLogger) wm.SetLogger(tcpLogger)
mux.HandleFunc(websocketEndpoint, wm.WebsocketHandler) mux.HandleFunc(websocketEndpoint, wm.WebsocketHandler)
config := server.DefaultConfig() config := server.DefaultConfig()
@ -134,8 +129,8 @@ func setup() {
unixLogger := logger.With("socket", "unix") unixLogger := logger.With("socket", "unix")
mux2 := http.NewServeMux() mux2 := http.NewServeMux()
server.RegisterRPCFuncs(mux2, Routes, RoutesCdc, unixLogger)
wm = server.NewWebsocketManager(Routes, RoutesCdc)
server.RegisterRPCFuncs(mux2, Routes, unixLogger)
wm = server.NewWebsocketManager(Routes)
wm.SetLogger(unixLogger) wm.SetLogger(unixLogger)
mux2.HandleFunc(websocketEndpoint, wm.WebsocketHandler) mux2.HandleFunc(websocketEndpoint, wm.WebsocketHandler)
listener2, err := server.Listen(unixAddr, config) listener2, err := server.Listen(unixAddr, config)


+ 9
- 12
rpc/jsonrpc/server/http_json_handler.go View File

@ -9,8 +9,7 @@ import (
"reflect" "reflect"
"sort" "sort"
amino "github.com/tendermint/go-amino"
tmjson "github.com/tendermint/tendermint/libs/json"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
types "github.com/tendermint/tendermint/rpc/jsonrpc/types" types "github.com/tendermint/tendermint/rpc/jsonrpc/types"
) )
@ -20,7 +19,7 @@ import (
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// jsonrpc calls grab the given method's function info and runs reflect.Call // jsonrpc calls grab the given method's function info and runs reflect.Call
func makeJSONRPCHandler(funcMap map[string]*RPCFunc, cdc *amino.Codec, logger log.Logger) http.HandlerFunc {
func makeJSONRPCHandler(funcMap map[string]*RPCFunc, logger log.Logger) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
b, err := ioutil.ReadAll(r.Body) b, err := ioutil.ReadAll(r.Body)
if err != nil { if err != nil {
@ -88,7 +87,7 @@ func makeJSONRPCHandler(funcMap map[string]*RPCFunc, cdc *amino.Codec, logger lo
ctx := &types.Context{JSONReq: &request, HTTPReq: r} ctx := &types.Context{JSONReq: &request, HTTPReq: r}
args := []reflect.Value{reflect.ValueOf(ctx)} args := []reflect.Value{reflect.ValueOf(ctx)}
if len(request.Params) > 0 { if len(request.Params) > 0 {
fnArgs, err := jsonParamsToArgs(rpcFunc, cdc, request.Params)
fnArgs, err := jsonParamsToArgs(rpcFunc, request.Params)
if err != nil { if err != nil {
responses = append( responses = append(
responses, responses,
@ -105,7 +104,7 @@ func makeJSONRPCHandler(funcMap map[string]*RPCFunc, cdc *amino.Codec, logger lo
responses = append(responses, types.RPCInternalError(request.ID, err)) responses = append(responses, types.RPCInternalError(request.ID, err))
continue continue
} }
responses = append(responses, types.NewRPCSuccessResponse(cdc, request.ID, result))
responses = append(responses, types.NewRPCSuccessResponse(request.ID, result))
} }
if len(responses) > 0 { if len(responses) > 0 {
WriteRPCResponseArrayHTTP(w, responses) WriteRPCResponseArrayHTTP(w, responses)
@ -128,7 +127,6 @@ func handleInvalidJSONRPCPaths(next http.HandlerFunc) http.HandlerFunc {
func mapParamsToArgs( func mapParamsToArgs(
rpcFunc *RPCFunc, rpcFunc *RPCFunc,
cdc *amino.Codec,
params map[string]json.RawMessage, params map[string]json.RawMessage,
argsOffset int, argsOffset int,
) ([]reflect.Value, error) { ) ([]reflect.Value, error) {
@ -139,7 +137,7 @@ func mapParamsToArgs(
if p, ok := params[argName]; ok && p != nil && len(p) > 0 { if p, ok := params[argName]; ok && p != nil && len(p) > 0 {
val := reflect.New(argType) val := reflect.New(argType)
err := cdc.UnmarshalJSON(p, val.Interface())
err := tmjson.Unmarshal(p, val.Interface())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -154,7 +152,6 @@ func mapParamsToArgs(
func arrayParamsToArgs( func arrayParamsToArgs(
rpcFunc *RPCFunc, rpcFunc *RPCFunc,
cdc *amino.Codec,
params []json.RawMessage, params []json.RawMessage,
argsOffset int, argsOffset int,
) ([]reflect.Value, error) { ) ([]reflect.Value, error) {
@ -168,7 +165,7 @@ func arrayParamsToArgs(
for i, p := range params { for i, p := range params {
argType := rpcFunc.args[i+argsOffset] argType := rpcFunc.args[i+argsOffset]
val := reflect.New(argType) val := reflect.New(argType)
err := cdc.UnmarshalJSON(p, val.Interface())
err := tmjson.Unmarshal(p, val.Interface())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -183,7 +180,7 @@ func arrayParamsToArgs(
// Example: // Example:
// rpcFunc.args = [rpctypes.Context string] // rpcFunc.args = [rpctypes.Context string]
// rpcFunc.argNames = ["arg"] // rpcFunc.argNames = ["arg"]
func jsonParamsToArgs(rpcFunc *RPCFunc, cdc *amino.Codec, raw []byte) ([]reflect.Value, error) {
func jsonParamsToArgs(rpcFunc *RPCFunc, raw []byte) ([]reflect.Value, error) {
const argsOffset = 1 const argsOffset = 1
// TODO: Make more efficient, perhaps by checking the first character for '{' or '['? // TODO: Make more efficient, perhaps by checking the first character for '{' or '['?
@ -191,14 +188,14 @@ func jsonParamsToArgs(rpcFunc *RPCFunc, cdc *amino.Codec, raw []byte) ([]reflect
var m map[string]json.RawMessage var m map[string]json.RawMessage
err := json.Unmarshal(raw, &m) err := json.Unmarshal(raw, &m)
if err == nil { if err == nil {
return mapParamsToArgs(rpcFunc, cdc, m, argsOffset)
return mapParamsToArgs(rpcFunc, m, argsOffset)
} }
// Otherwise, try an array. // Otherwise, try an array.
var a []json.RawMessage var a []json.RawMessage
err = json.Unmarshal(raw, &a) err = json.Unmarshal(raw, &a)
if err == nil { if err == nil {
return arrayParamsToArgs(rpcFunc, cdc, a, argsOffset)
return arrayParamsToArgs(rpcFunc, a, argsOffset)
} }
// Otherwise, bad format, we cannot parse // Otherwise, bad format, we cannot parse


+ 1
- 4
rpc/jsonrpc/server/http_json_handler_test.go View File

@ -12,8 +12,6 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
types "github.com/tendermint/tendermint/rpc/jsonrpc/types" types "github.com/tendermint/tendermint/rpc/jsonrpc/types"
) )
@ -22,11 +20,10 @@ func testMux() *http.ServeMux {
funcMap := map[string]*RPCFunc{ funcMap := map[string]*RPCFunc{
"c": NewRPCFunc(func(ctx *types.Context, s string, i int) (string, error) { return "foo", nil }, "s,i"), "c": NewRPCFunc(func(ctx *types.Context, s string, i int) (string, error) { return "foo", nil }, "s,i"),
} }
cdc := amino.NewCodec()
mux := http.NewServeMux() mux := http.NewServeMux()
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
logger := log.NewTMLogger(buf) logger := log.NewTMLogger(buf)
RegisterRPCFuncs(mux, funcMap, cdc, logger)
RegisterRPCFuncs(mux, funcMap, logger)
return mux return mux
} }


+ 15
- 16
rpc/jsonrpc/server/http_uri_handler.go View File

@ -8,8 +8,7 @@ import (
"regexp" "regexp"
"strings" "strings"
amino "github.com/tendermint/go-amino"
tmjson "github.com/tendermint/tendermint/libs/json"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
types "github.com/tendermint/tendermint/rpc/jsonrpc/types" types "github.com/tendermint/tendermint/rpc/jsonrpc/types"
) )
@ -21,7 +20,7 @@ import (
var reInt = regexp.MustCompile(`^-?[0-9]+$`) var reInt = regexp.MustCompile(`^-?[0-9]+$`)
// convert from a function name to the http handler // convert from a function name to the http handler
func makeHTTPHandler(rpcFunc *RPCFunc, cdc *amino.Codec, logger log.Logger) func(http.ResponseWriter, *http.Request) {
func makeHTTPHandler(rpcFunc *RPCFunc, logger log.Logger) func(http.ResponseWriter, *http.Request) {
// Always return -1 as there's no ID here. // Always return -1 as there's no ID here.
dummyID := types.JSONRPCIntID(-1) // URIClientRequestID dummyID := types.JSONRPCIntID(-1) // URIClientRequestID
@ -39,7 +38,7 @@ func makeHTTPHandler(rpcFunc *RPCFunc, cdc *amino.Codec, logger log.Logger) func
ctx := &types.Context{HTTPReq: r} ctx := &types.Context{HTTPReq: r}
args := []reflect.Value{reflect.ValueOf(ctx)} args := []reflect.Value{reflect.ValueOf(ctx)}
fnArgs, err := httpParamsToArgs(rpcFunc, cdc, r)
fnArgs, err := httpParamsToArgs(rpcFunc, r)
if err != nil { if err != nil {
WriteRPCResponseHTTP( WriteRPCResponseHTTP(
w, w,
@ -60,13 +59,13 @@ func makeHTTPHandler(rpcFunc *RPCFunc, cdc *amino.Codec, logger log.Logger) func
WriteRPCResponseHTTP(w, types.RPCInternalError(dummyID, err)) WriteRPCResponseHTTP(w, types.RPCInternalError(dummyID, err))
return return
} }
WriteRPCResponseHTTP(w, types.NewRPCSuccessResponse(cdc, dummyID, result))
WriteRPCResponseHTTP(w, types.NewRPCSuccessResponse(dummyID, result))
} }
} }
// Covert an http query to a list of properly typed values. // Covert an http query to a list of properly typed values.
// To be properly decoded the arg must be a concrete type from tendermint (if its an interface). // To be properly decoded the arg must be a concrete type from tendermint (if its an interface).
func httpParamsToArgs(rpcFunc *RPCFunc, cdc *amino.Codec, r *http.Request) ([]reflect.Value, error) {
func httpParamsToArgs(rpcFunc *RPCFunc, r *http.Request) ([]reflect.Value, error) {
// skip types.Context // skip types.Context
const argsOffset = 1 const argsOffset = 1
@ -84,7 +83,7 @@ func httpParamsToArgs(rpcFunc *RPCFunc, cdc *amino.Codec, r *http.Request) ([]re
continue continue
} }
v, ok, err := nonJSONStringToArg(cdc, argType, arg)
v, ok, err := nonJSONStringToArg(argType, arg)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -93,7 +92,7 @@ func httpParamsToArgs(rpcFunc *RPCFunc, cdc *amino.Codec, r *http.Request) ([]re
continue continue
} }
values[i], err = jsonStringToArg(cdc, argType, arg)
values[i], err = jsonStringToArg(argType, arg)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -102,9 +101,9 @@ func httpParamsToArgs(rpcFunc *RPCFunc, cdc *amino.Codec, r *http.Request) ([]re
return values, nil return values, nil
} }
func jsonStringToArg(cdc *amino.Codec, rt reflect.Type, arg string) (reflect.Value, error) {
func jsonStringToArg(rt reflect.Type, arg string) (reflect.Value, error) {
rv := reflect.New(rt) rv := reflect.New(rt)
err := cdc.UnmarshalJSON([]byte(arg), rv.Interface())
err := tmjson.Unmarshal([]byte(arg), rv.Interface())
if err != nil { if err != nil {
return rv, err return rv, err
} }
@ -112,9 +111,9 @@ func jsonStringToArg(cdc *amino.Codec, rt reflect.Type, arg string) (reflect.Val
return rv, nil return rv, nil
} }
func nonJSONStringToArg(cdc *amino.Codec, rt reflect.Type, arg string) (reflect.Value, bool, error) {
func nonJSONStringToArg(rt reflect.Type, arg string) (reflect.Value, bool, error) {
if rt.Kind() == reflect.Ptr { if rt.Kind() == reflect.Ptr {
rv1, ok, err := nonJSONStringToArg(cdc, rt.Elem(), arg)
rv1, ok, err := nonJSONStringToArg(rt.Elem(), arg)
switch { switch {
case err != nil: case err != nil:
return reflect.Value{}, false, err return reflect.Value{}, false, err
@ -126,12 +125,12 @@ func nonJSONStringToArg(cdc *amino.Codec, rt reflect.Type, arg string) (reflect.
return reflect.Value{}, false, nil return reflect.Value{}, false, nil
} }
} else { } else {
return _nonJSONStringToArg(cdc, rt, arg)
return _nonJSONStringToArg(rt, arg)
} }
} }
// NOTE: rt.Kind() isn't a pointer. // NOTE: rt.Kind() isn't a pointer.
func _nonJSONStringToArg(cdc *amino.Codec, rt reflect.Type, arg string) (reflect.Value, bool, error) {
func _nonJSONStringToArg(rt reflect.Type, arg string) (reflect.Value, bool, error) {
isIntString := reInt.Match([]byte(arg)) isIntString := reInt.Match([]byte(arg))
isQuotedString := strings.HasPrefix(arg, `"`) && strings.HasSuffix(arg, `"`) isQuotedString := strings.HasPrefix(arg, `"`) && strings.HasSuffix(arg, `"`)
isHexString := strings.HasPrefix(strings.ToLower(arg), "0x") isHexString := strings.HasPrefix(strings.ToLower(arg), "0x")
@ -157,7 +156,7 @@ func _nonJSONStringToArg(cdc *amino.Codec, rt reflect.Type, arg string) (reflect
if isIntString && expectingInt { if isIntString && expectingInt {
qarg := `"` + arg + `"` qarg := `"` + arg + `"`
rv, err := jsonStringToArg(cdc, rt, qarg)
rv, err := jsonStringToArg(rt, qarg)
if err != nil { if err != nil {
return rv, false, err return rv, false, err
} }
@ -185,7 +184,7 @@ func _nonJSONStringToArg(cdc *amino.Codec, rt reflect.Type, arg string) (reflect
if isQuotedString && expectingByteSlice { if isQuotedString && expectingByteSlice {
v := reflect.New(reflect.TypeOf("")) v := reflect.New(reflect.TypeOf(""))
err := cdc.UnmarshalJSON([]byte(arg), v.Interface())
err := tmjson.Unmarshal([]byte(arg), v.Interface())
if err != nil { if err != nil {
return reflect.ValueOf(nil), false, err return reflect.ValueOf(nil), false, err
} }


+ 2
- 5
rpc/jsonrpc/server/parse_test.go View File

@ -8,7 +8,6 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/libs/bytes" "github.com/tendermint/tendermint/libs/bytes"
types "github.com/tendermint/tendermint/rpc/jsonrpc/types" types "github.com/tendermint/tendermint/rpc/jsonrpc/types"
@ -137,7 +136,6 @@ func TestParseJSONArray(t *testing.T) {
func TestParseJSONRPC(t *testing.T) { func TestParseJSONRPC(t *testing.T) {
demo := func(ctx *types.Context, height int, name string) {} demo := func(ctx *types.Context, height int, name string) {}
call := NewRPCFunc(demo, "height,name") call := NewRPCFunc(demo, "height,name")
cdc := amino.NewCodec()
cases := []struct { cases := []struct {
raw string raw string
@ -158,7 +156,7 @@ func TestParseJSONRPC(t *testing.T) {
for idx, tc := range cases { for idx, tc := range cases {
i := strconv.Itoa(idx) i := strconv.Itoa(idx)
data := []byte(tc.raw) data := []byte(tc.raw)
vals, err := jsonParamsToArgs(call, cdc, data)
vals, err := jsonParamsToArgs(call, data)
if tc.fail { if tc.fail {
assert.NotNil(t, err, i) assert.NotNil(t, err, i)
} else { } else {
@ -175,7 +173,6 @@ func TestParseJSONRPC(t *testing.T) {
func TestParseURI(t *testing.T) { func TestParseURI(t *testing.T) {
demo := func(ctx *types.Context, height int, name string) {} demo := func(ctx *types.Context, height int, name string) {}
call := NewRPCFunc(demo, "height,name") call := NewRPCFunc(demo, "height,name")
cdc := amino.NewCodec()
cases := []struct { cases := []struct {
raw []string raw []string
@ -201,7 +198,7 @@ func TestParseURI(t *testing.T) {
tc.raw[0], tc.raw[1]) tc.raw[0], tc.raw[1])
req, err := http.NewRequest("GET", url, nil) req, err := http.NewRequest("GET", url, nil)
assert.NoError(t, err) assert.NoError(t, err)
vals, err := httpParamsToArgs(call, cdc, req)
vals, err := httpParamsToArgs(call, req)
if tc.fail { if tc.fail {
assert.NotNil(t, err, i) assert.NotNil(t, err, i)
} else { } else {


+ 3
- 5
rpc/jsonrpc/server/rpc_func.go View File

@ -6,8 +6,6 @@ import (
"reflect" "reflect"
"strings" "strings"
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
) )
@ -15,14 +13,14 @@ import (
// general jsonrpc and websocket handlers for all functions. "result" is the // general jsonrpc and websocket handlers for all functions. "result" is the
// interface on which the result objects are registered, and is popualted with // interface on which the result objects are registered, and is popualted with
// every RPCResponse // every RPCResponse
func RegisterRPCFuncs(mux *http.ServeMux, funcMap map[string]*RPCFunc, cdc *amino.Codec, logger log.Logger) {
func RegisterRPCFuncs(mux *http.ServeMux, funcMap map[string]*RPCFunc, logger log.Logger) {
// HTTP endpoints // HTTP endpoints
for funcName, rpcFunc := range funcMap { for funcName, rpcFunc := range funcMap {
mux.HandleFunc("/"+funcName, makeHTTPHandler(rpcFunc, cdc, logger))
mux.HandleFunc("/"+funcName, makeHTTPHandler(rpcFunc, logger))
} }
// JSONRPC endpoints // JSONRPC endpoints
mux.HandleFunc("/", handleInvalidJSONRPCPaths(makeJSONRPCHandler(funcMap, cdc, logger)))
mux.HandleFunc("/", handleInvalidJSONRPCPaths(makeJSONRPCHandler(funcMap, logger)))
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////


+ 3
- 17
rpc/jsonrpc/server/ws_handler.go View File

@ -11,8 +11,6 @@ import (
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/libs/service" "github.com/tendermint/tendermint/libs/service"
types "github.com/tendermint/tendermint/rpc/jsonrpc/types" types "github.com/tendermint/tendermint/rpc/jsonrpc/types"
@ -36,7 +34,6 @@ type WebsocketManager struct {
websocket.Upgrader websocket.Upgrader
funcMap map[string]*RPCFunc funcMap map[string]*RPCFunc
cdc *amino.Codec
logger log.Logger logger log.Logger
wsConnOptions []func(*wsConnection) wsConnOptions []func(*wsConnection)
} }
@ -45,12 +42,10 @@ type WebsocketManager struct {
// functions, connection options and logger to new WS connections. // functions, connection options and logger to new WS connections.
func NewWebsocketManager( func NewWebsocketManager(
funcMap map[string]*RPCFunc, funcMap map[string]*RPCFunc,
cdc *amino.Codec,
wsConnOptions ...func(*wsConnection), wsConnOptions ...func(*wsConnection),
) *WebsocketManager { ) *WebsocketManager {
return &WebsocketManager{ return &WebsocketManager{
funcMap: funcMap, funcMap: funcMap,
cdc: cdc,
Upgrader: websocket.Upgrader{ Upgrader: websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { CheckOrigin: func(r *http.Request) bool {
// TODO ??? // TODO ???
@ -91,7 +86,7 @@ func (wm *WebsocketManager) WebsocketHandler(w http.ResponseWriter, r *http.Requ
}() }()
// register connection // register connection
con := newWSConnection(wsConn, wm.funcMap, wm.cdc, wm.wsConnOptions...)
con := newWSConnection(wsConn, wm.funcMap, wm.wsConnOptions...)
con.SetLogger(wm.logger.With("remote", wsConn.RemoteAddr())) con.SetLogger(wm.logger.With("remote", wsConn.RemoteAddr()))
wm.logger.Info("New websocket connection", "remote", con.remoteAddr) wm.logger.Info("New websocket connection", "remote", con.remoteAddr)
err = con.Start() // BLOCKING err = con.Start() // BLOCKING
@ -123,7 +118,6 @@ type wsConnection struct {
readRoutineQuit chan struct{} readRoutineQuit chan struct{}
funcMap map[string]*RPCFunc funcMap map[string]*RPCFunc
cdc *amino.Codec
// write channel capacity // write channel capacity
writeChanCapacity int writeChanCapacity int
@ -156,14 +150,12 @@ type wsConnection struct {
func newWSConnection( func newWSConnection(
baseConn *websocket.Conn, baseConn *websocket.Conn,
funcMap map[string]*RPCFunc, funcMap map[string]*RPCFunc,
cdc *amino.Codec,
options ...func(*wsConnection), options ...func(*wsConnection),
) *wsConnection { ) *wsConnection {
wsc := &wsConnection{ wsc := &wsConnection{
remoteAddr: baseConn.RemoteAddr().String(), remoteAddr: baseConn.RemoteAddr().String(),
baseConn: baseConn, baseConn: baseConn,
funcMap: funcMap, funcMap: funcMap,
cdc: cdc,
writeWait: defaultWSWriteWait, writeWait: defaultWSWriteWait,
writeChanCapacity: defaultWSWriteChanCapacity, writeChanCapacity: defaultWSWriteChanCapacity,
readWait: defaultWSReadWait, readWait: defaultWSReadWait,
@ -280,12 +272,6 @@ func (wsc *wsConnection) TryWriteRPCResponse(resp types.RPCResponse) bool {
} }
} }
// Codec returns an amino codec used to decode parameters and encode results.
// It implements WSRPCConnection.
func (wsc *wsConnection) Codec() *amino.Codec {
return wsc.cdc
}
// Context returns the connection's context. // Context returns the connection's context.
// The context is canceled when the client's connection closes. // The context is canceled when the client's connection closes.
func (wsc *wsConnection) Context() context.Context { func (wsc *wsConnection) Context() context.Context {
@ -363,7 +349,7 @@ func (wsc *wsConnection) readRoutine() {
ctx := &types.Context{JSONReq: &request, WSConn: wsc} ctx := &types.Context{JSONReq: &request, WSConn: wsc}
args := []reflect.Value{reflect.ValueOf(ctx)} args := []reflect.Value{reflect.ValueOf(ctx)}
if len(request.Params) > 0 { if len(request.Params) > 0 {
fnArgs, err := jsonParamsToArgs(rpcFunc, wsc.cdc, request.Params)
fnArgs, err := jsonParamsToArgs(rpcFunc, request.Params)
if err != nil { if err != nil {
wsc.WriteRPCResponse( wsc.WriteRPCResponse(
types.RPCInternalError(request.ID, fmt.Errorf("error converting json params to arguments: %w", err)), types.RPCInternalError(request.ID, fmt.Errorf("error converting json params to arguments: %w", err)),
@ -384,7 +370,7 @@ func (wsc *wsConnection) readRoutine() {
continue continue
} }
wsc.WriteRPCResponse(types.NewRPCSuccessResponse(wsc.cdc, request.ID, result))
wsc.WriteRPCResponse(types.NewRPCSuccessResponse(request.ID, result))
} }
} }
} }


+ 1
- 4
rpc/jsonrpc/server/ws_handler_test.go View File

@ -8,8 +8,6 @@ import (
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
types "github.com/tendermint/tendermint/rpc/jsonrpc/types" types "github.com/tendermint/tendermint/rpc/jsonrpc/types"
) )
@ -29,7 +27,6 @@ func TestWebsocketManagerHandler(t *testing.T) {
// check basic functionality works // check basic functionality works
req, err := types.MapToRequest( req, err := types.MapToRequest(
amino.NewCodec(),
types.JSONRPCStringID("TestWebsocketManager"), types.JSONRPCStringID("TestWebsocketManager"),
"c", "c",
map[string]interface{}{"s": "a", "i": 10}, map[string]interface{}{"s": "a", "i": 10},
@ -49,7 +46,7 @@ func newWSServer() *httptest.Server {
funcMap := map[string]*RPCFunc{ funcMap := map[string]*RPCFunc{
"c": NewWSRPCFunc(func(ctx *types.Context, s string, i int) (string, error) { return "foo", nil }, "s,i"), "c": NewWSRPCFunc(func(ctx *types.Context, s string, i int) (string, error) { return "foo", nil }, "s,i"),
} }
wm := NewWebsocketManager(funcMap, amino.NewCodec())
wm := NewWebsocketManager(funcMap)
wm.SetLogger(log.TestingLogger()) wm.SetLogger(log.TestingLogger())
mux := http.NewServeMux() mux := http.NewServeMux()


+ 1
- 4
rpc/jsonrpc/test/main.go View File

@ -5,8 +5,6 @@ import (
"net/http" "net/http"
"os" "os"
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
tmos "github.com/tendermint/tendermint/libs/os" tmos "github.com/tendermint/tendermint/libs/os"
rpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server" rpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server"
@ -28,14 +26,13 @@ type Result struct {
func main() { func main() {
var ( var (
mux = http.NewServeMux() mux = http.NewServeMux()
cdc = amino.NewCodec()
logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout))
) )
// Stop upon receiving SIGTERM or CTRL-C. // Stop upon receiving SIGTERM or CTRL-C.
tmos.TrapSignal(logger, func() {}) tmos.TrapSignal(logger, func() {})
rpcserver.RegisterRPCFuncs(mux, routes, cdc, logger)
rpcserver.RegisterRPCFuncs(mux, routes, logger)
config := rpcserver.DefaultConfig() config := rpcserver.DefaultConfig()
listener, err := rpcserver.Listen("tcp://127.0.0.1:8008", config) listener, err := rpcserver.Listen("tcp://127.0.0.1:8008", config)
if err != nil { if err != nil {


+ 9
- 11
rpc/jsonrpc/types/types.go View File

@ -8,7 +8,7 @@ import (
"reflect" "reflect"
"strings" "strings"
amino "github.com/tendermint/go-amino"
tmjson "github.com/tendermint/tendermint/libs/json"
) )
// a wrapper to emulate a sum type: jsonrpcid = string | int // a wrapper to emulate a sum type: jsonrpcid = string | int
@ -94,17 +94,17 @@ func (req RPCRequest) String() string {
return fmt.Sprintf("RPCRequest{%s %s/%X}", req.ID, req.Method, req.Params) return fmt.Sprintf("RPCRequest{%s %s/%X}", req.ID, req.Method, req.Params)
} }
func MapToRequest(cdc *amino.Codec, id jsonrpcid, method string, params map[string]interface{}) (RPCRequest, error) {
func MapToRequest(id jsonrpcid, method string, params map[string]interface{}) (RPCRequest, error) {
var paramsMap = make(map[string]json.RawMessage, len(params)) var paramsMap = make(map[string]json.RawMessage, len(params))
for name, value := range params { for name, value := range params {
valueJSON, err := cdc.MarshalJSON(value)
valueJSON, err := tmjson.Marshal(value)
if err != nil { if err != nil {
return RPCRequest{}, err return RPCRequest{}, err
} }
paramsMap[name] = valueJSON paramsMap[name] = valueJSON
} }
payload, err := json.Marshal(paramsMap) // NOTE: Amino doesn't handle maps yet.
payload, err := json.Marshal(paramsMap)
if err != nil { if err != nil {
return RPCRequest{}, err return RPCRequest{}, err
} }
@ -112,17 +112,17 @@ func MapToRequest(cdc *amino.Codec, id jsonrpcid, method string, params map[stri
return NewRPCRequest(id, method, payload), nil return NewRPCRequest(id, method, payload), nil
} }
func ArrayToRequest(cdc *amino.Codec, id jsonrpcid, method string, params []interface{}) (RPCRequest, error) {
func ArrayToRequest(id jsonrpcid, method string, params []interface{}) (RPCRequest, error) {
var paramsMap = make([]json.RawMessage, len(params)) var paramsMap = make([]json.RawMessage, len(params))
for i, value := range params { for i, value := range params {
valueJSON, err := cdc.MarshalJSON(value)
valueJSON, err := tmjson.Marshal(value)
if err != nil { if err != nil {
return RPCRequest{}, err return RPCRequest{}, err
} }
paramsMap[i] = valueJSON paramsMap[i] = valueJSON
} }
payload, err := json.Marshal(paramsMap) // NOTE: Amino doesn't handle maps yet.
payload, err := json.Marshal(paramsMap)
if err != nil { if err != nil {
return RPCRequest{}, err return RPCRequest{}, err
} }
@ -180,12 +180,12 @@ func (resp *RPCResponse) UnmarshalJSON(data []byte) error {
return nil return nil
} }
func NewRPCSuccessResponse(cdc *amino.Codec, id jsonrpcid, res interface{}) RPCResponse {
func NewRPCSuccessResponse(id jsonrpcid, res interface{}) RPCResponse {
var rawMsg json.RawMessage var rawMsg json.RawMessage
if res != nil { if res != nil {
var js []byte var js []byte
js, err := cdc.MarshalJSON(res)
js, err := tmjson.Marshal(res)
if err != nil { if err != nil {
return RPCInternalError(id, fmt.Errorf("error marshalling response: %w", err)) return RPCInternalError(id, fmt.Errorf("error marshalling response: %w", err))
} }
@ -250,8 +250,6 @@ type WSRPCConnection interface {
WriteRPCResponse(resp RPCResponse) WriteRPCResponse(resp RPCResponse)
// TryWriteRPCResponse tries to write the resp onto connection (NON-BLOCKING). // TryWriteRPCResponse tries to write the resp onto connection (NON-BLOCKING).
TryWriteRPCResponse(resp RPCResponse) bool TryWriteRPCResponse(resp RPCResponse) bool
// Codec returns an Amino codec used.
Codec() *amino.Codec
// Context returns the connection's context. // Context returns the connection's context.
Context() context.Context Context() context.Context
} }


+ 2
- 5
rpc/jsonrpc/types/types_test.go View File

@ -7,7 +7,6 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
amino "github.com/tendermint/go-amino"
) )
type SampleResult struct { type SampleResult struct {
@ -32,10 +31,9 @@ var responseTests = []responseTest{
func TestResponses(t *testing.T) { func TestResponses(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
cdc := amino.NewCodec()
for _, tt := range responseTests { for _, tt := range responseTests {
jsonid := tt.id jsonid := tt.id
a := NewRPCSuccessResponse(cdc, jsonid, &SampleResult{"hello"})
a := NewRPCSuccessResponse(jsonid, &SampleResult{"hello"})
b, _ := json.Marshal(a) b, _ := json.Marshal(a)
s := fmt.Sprintf(`{"jsonrpc":"2.0","id":%v,"result":{"Value":"hello"}}`, tt.expected) s := fmt.Sprintf(`{"jsonrpc":"2.0","id":%v,"result":{"Value":"hello"}}`, tt.expected)
assert.Equal(s, string(b)) assert.Equal(s, string(b))
@ -54,7 +52,6 @@ func TestResponses(t *testing.T) {
func TestUnmarshallResponses(t *testing.T) { func TestUnmarshallResponses(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
cdc := amino.NewCodec()
for _, tt := range responseTests { for _, tt := range responseTests {
response := &RPCResponse{} response := &RPCResponse{}
err := json.Unmarshal( err := json.Unmarshal(
@ -62,7 +59,7 @@ func TestUnmarshallResponses(t *testing.T) {
response, response,
) )
assert.Nil(err) assert.Nil(err)
a := NewRPCSuccessResponse(cdc, tt.id, &SampleResult{"hello"})
a := NewRPCSuccessResponse(tt.id, &SampleResult{"hello"})
assert.Equal(*response, a) assert.Equal(*response, a)
} }
response := &RPCResponse{} response := &RPCResponse{}


+ 2
- 2
rpc/swagger/swagger.yaml View File

@ -1008,11 +1008,11 @@ paths:
parameters: parameters:
- in: query - in: query
name: evidence name: evidence
description: Amino-encoded JSON evidence
description: JSON evidence
required: true required: true
schema: schema:
type: string type: string
example: "JSON_EVIDENCE_Amino_encoded"
example: "JSON_EVIDENCE_encoded"
tags: tags:
- Info - Info
description: | description: |


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

@ -41,7 +41,6 @@ func waitForRPC() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
ctypes.RegisterAmino(client.Codec())
result := new(ctypes.ResultStatus) result := new(ctypes.ResultStatus)
for { for {
_, err := client.Call("status", map[string]interface{}{}, result) _, err := client.Call("status", map[string]interface{}{}, result)


+ 13
- 0
types/events.go View File

@ -6,6 +6,7 @@ import (
amino "github.com/tendermint/go-amino" amino "github.com/tendermint/go-amino"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
tmjson "github.com/tendermint/tendermint/libs/json"
tmpubsub "github.com/tendermint/tendermint/libs/pubsub" tmpubsub "github.com/tendermint/tendermint/libs/pubsub"
tmquery "github.com/tendermint/tendermint/libs/pubsub/query" tmquery "github.com/tendermint/tendermint/libs/pubsub/query"
) )
@ -60,6 +61,18 @@ func RegisterEventDatas(cdc *amino.Codec) {
cdc.RegisterConcrete(EventDataString(""), "tendermint/event/ProposalString", nil) cdc.RegisterConcrete(EventDataString(""), "tendermint/event/ProposalString", nil)
} }
func init() {
tmjson.RegisterType(EventDataNewBlock{}, "tendermint/event/NewBlock")
tmjson.RegisterType(EventDataNewBlockHeader{}, "tendermint/event/NewBlockHeader")
tmjson.RegisterType(EventDataTx{}, "tendermint/event/Tx")
tmjson.RegisterType(EventDataRoundState{}, "tendermint/event/RoundState")
tmjson.RegisterType(EventDataNewRound{}, "tendermint/event/NewRound")
tmjson.RegisterType(EventDataCompleteProposal{}, "tendermint/event/CompleteProposal")
tmjson.RegisterType(EventDataVote{}, "tendermint/event/Vote")
tmjson.RegisterType(EventDataValidatorSetUpdates{}, "tendermint/event/ValidatorSetUpdates")
tmjson.RegisterType(EventDataString(""), "tendermint/event/ProposalString")
}
// Most event messages are basic types (a block, a transaction) // Most event messages are basic types (a block, a transaction)
// but some (an input to a call tx or a receive) are more exotic // but some (an input to a call tx or a receive) are more exotic


+ 9
- 0
types/evidence.go View File

@ -12,6 +12,7 @@ import (
"github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/merkle" "github.com/tendermint/tendermint/crypto/merkle"
"github.com/tendermint/tendermint/crypto/tmhash" "github.com/tendermint/tendermint/crypto/tmhash"
tmjson "github.com/tendermint/tendermint/libs/json"
tmmath "github.com/tendermint/tendermint/libs/math" tmmath "github.com/tendermint/tendermint/libs/math"
tmproto "github.com/tendermint/tendermint/proto/types" tmproto "github.com/tendermint/tendermint/proto/types"
) )
@ -328,6 +329,14 @@ func RegisterEvidences(cdc *amino.Codec) {
cdc.RegisterConcrete(&PotentialAmnesiaEvidence{}, "tendermint/PotentialAmnesiaEvidence", nil) cdc.RegisterConcrete(&PotentialAmnesiaEvidence{}, "tendermint/PotentialAmnesiaEvidence", nil)
} }
func init() {
tmjson.RegisterType(&DuplicateVoteEvidence{}, "tendermint/DuplicateVoteEvidence")
tmjson.RegisterType(&ConflictingHeadersEvidence{}, "tendermint/ConflictingHeadersEvidence")
tmjson.RegisterType(&PhantomValidatorEvidence{}, "tendermint/PhantomValidatorEvidence")
tmjson.RegisterType(&LunaticValidatorEvidence{}, "tendermint/LunaticValidatorEvidence")
tmjson.RegisterType(&PotentialAmnesiaEvidence{}, "tendermint/PotentialAmnesiaEvidence")
}
func RegisterMockEvidences(cdc *amino.Codec) { func RegisterMockEvidences(cdc *amino.Codec) {
cdc.RegisterConcrete(MockEvidence{}, "tendermint/MockEvidence", nil) cdc.RegisterConcrete(MockEvidence{}, "tendermint/MockEvidence", nil)
cdc.RegisterConcrete(MockRandomEvidence{}, "tendermint/MockRandomEvidence", nil) cdc.RegisterConcrete(MockRandomEvidence{}, "tendermint/MockRandomEvidence", nil)


Loading…
Cancel
Save