diff --git a/client/commands/proxy/root.go b/client/commands/proxy/root.go index cc47107ed2..e8170015c2 100644 --- a/client/commands/proxy/root.go +++ b/client/commands/proxy/root.go @@ -1,19 +1,15 @@ package proxy import ( - "net/http" "os" "github.com/spf13/cobra" "github.com/spf13/viper" - certclient "github.com/tendermint/light-client/certifiers/client" - "github.com/tendermint/tendermint/rpc/client" - "github.com/tendermint/tendermint/rpc/core" - rpc "github.com/tendermint/tendermint/rpc/lib/server" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/commands" ) @@ -32,8 +28,7 @@ just with added trust and running locally.`, } const ( - bindFlag = "serve" - wsEndpoint = "/websocket" + bindFlag = "serve" ) func init() { @@ -50,24 +45,15 @@ func init() { func runProxy(cmd *cobra.Command, args []string) error { // First, connect a client - c := commands.GetNode() + node := commands.GetNode() + bind := viper.GetString(bindFlag) cert, err := commands.GetCertifier() if err != nil { return err } - sc := certclient.Wrap(c, cert) - sc.Start() - r := routes(sc) + sc := client.SecureClient(node, cert) - // build the handler... - mux := http.NewServeMux() - rpc.RegisterRPCFuncs(mux, r, logger) - wm := rpc.NewWebsocketManager(r, c) - wm.SetLogger(logger) - core.SetLogger(logger) - mux.HandleFunc(wsEndpoint, wm.WebsocketHandler) - - _, err = rpc.StartHTTPServer(viper.GetString(bindFlag), mux, logger) + err = client.StartProxy(sc, bind, logger) if err != nil { return err } @@ -78,33 +64,3 @@ func runProxy(cmd *cobra.Command, args []string) error { return nil } - -// First step, proxy with no checks.... -func routes(c client.Client) map[string]*rpc.RPCFunc { - - return map[string]*rpc.RPCFunc{ - // Subscribe/unsubscribe are reserved for websocket events. - // We can just use the core tendermint impl, which uses the - // EventSwitch we registered in NewWebsocketManager above - "subscribe": rpc.NewWSRPCFunc(core.Subscribe, "event"), - "unsubscribe": rpc.NewWSRPCFunc(core.Unsubscribe, "event"), - - // info API - "status": rpc.NewRPCFunc(c.Status, ""), - "blockchain": rpc.NewRPCFunc(c.BlockchainInfo, "minHeight,maxHeight"), - "genesis": rpc.NewRPCFunc(c.Genesis, ""), - "block": rpc.NewRPCFunc(c.Block, "height"), - "commit": rpc.NewRPCFunc(c.Commit, "height"), - "tx": rpc.NewRPCFunc(c.Tx, "hash,prove"), - "validators": rpc.NewRPCFunc(c.Validators, ""), - - // broadcast API - "broadcast_tx_commit": rpc.NewRPCFunc(c.BroadcastTxCommit, "tx"), - "broadcast_tx_sync": rpc.NewRPCFunc(c.BroadcastTxSync, "tx"), - "broadcast_tx_async": rpc.NewRPCFunc(c.BroadcastTxAsync, "tx"), - - // abci API - "abci_query": rpc.NewRPCFunc(c.ABCIQuery, "path,data,prove"), - "abci_info": rpc.NewRPCFunc(c.ABCIInfo, ""), - } -} diff --git a/client/commands/rpc/root.go b/client/commands/rpc/root.go index dcb40d6e43..88003a43da 100644 --- a/client/commands/rpc/root.go +++ b/client/commands/rpc/root.go @@ -46,7 +46,7 @@ func getSecureNode() (rpcclient.Client, error) { if err != nil { return nil, err } - return client.GetSecureNode(c, cert), nil + return client.SecureClient(c, cert), nil } // printResult just writes the struct to the console, returns an error if it can't diff --git a/client/common.go b/client/common.go index 79f816f87d..f2c0d01412 100644 --- a/client/common.go +++ b/client/common.go @@ -47,8 +47,8 @@ func GetCertifier(chainID string, trust certifiers.Provider, return cert, nil } -// GetSecureNode uses a given certifier to wrap an connection to an untrusted +// SecureClient uses a given certifier to wrap an connection to an untrusted // host and return a cryptographically secure rpc client. -func GetSecureNode(c rpcclient.Client, cert *certifiers.InquiringCertifier) rpcclient.Client { +func SecureClient(c rpcclient.Client, cert *certifiers.InquiringCertifier) rpcclient.Client { return certclient.Wrap(c, cert) } diff --git a/client/proxy.go b/client/proxy.go new file mode 100644 index 0000000000..6518dfadbc --- /dev/null +++ b/client/proxy.go @@ -0,0 +1,68 @@ +package client + +import ( + "net/http" + + "github.com/tendermint/tmlibs/log" + + rpcclient "github.com/tendermint/tendermint/rpc/client" + "github.com/tendermint/tendermint/rpc/core" + rpc "github.com/tendermint/tendermint/rpc/lib/server" +) + +const ( + wsEndpoint = "/websocket" +) + +// StartProxy will start the websocket manager on the client, +// set up the rpc routes to proxy via the given client, +// and start up an http/rpc server on the location given by bind (eg. :1234) +func StartProxy(c rpcclient.Client, bind string, logger log.Logger) error { + c.Start() + r := RPCRoutes(c) + + // build the handler... + mux := http.NewServeMux() + rpc.RegisterRPCFuncs(mux, r, logger) + wm := rpc.NewWebsocketManager(r, c) + wm.SetLogger(logger) + core.SetLogger(logger) + mux.HandleFunc(wsEndpoint, wm.WebsocketHandler) + + _, err := rpc.StartHTTPServer(bind, mux, logger) + + return err +} + +// RPCRoutes just routes everything to the given client, as if it were +// a tendermint fullnode. +// +// if we want security, the client must implement it as a secure client +func RPCRoutes(c rpcclient.Client) map[string]*rpc.RPCFunc { + + return map[string]*rpc.RPCFunc{ + // Subscribe/unsubscribe are reserved for websocket events. + // We can just use the core tendermint impl, which uses the + // EventSwitch we registered in NewWebsocketManager above + "subscribe": rpc.NewWSRPCFunc(core.Subscribe, "event"), + "unsubscribe": rpc.NewWSRPCFunc(core.Unsubscribe, "event"), + + // info API + "status": rpc.NewRPCFunc(c.Status, ""), + "blockchain": rpc.NewRPCFunc(c.BlockchainInfo, "minHeight,maxHeight"), + "genesis": rpc.NewRPCFunc(c.Genesis, ""), + "block": rpc.NewRPCFunc(c.Block, "height"), + "commit": rpc.NewRPCFunc(c.Commit, "height"), + "tx": rpc.NewRPCFunc(c.Tx, "hash,prove"), + "validators": rpc.NewRPCFunc(c.Validators, ""), + + // broadcast API + "broadcast_tx_commit": rpc.NewRPCFunc(c.BroadcastTxCommit, "tx"), + "broadcast_tx_sync": rpc.NewRPCFunc(c.BroadcastTxSync, "tx"), + "broadcast_tx_async": rpc.NewRPCFunc(c.BroadcastTxAsync, "tx"), + + // abci API + "abci_query": rpc.NewRPCFunc(c.ABCIQuery, "path,data,prove"), + "abci_info": rpc.NewRPCFunc(c.ABCIInfo, ""), + } +}