From 284c2a033318df2b5c21b89e1c7427f61f5c16f0 Mon Sep 17 00:00:00 2001 From: David Ansermino Date: Mon, 15 Jul 2019 10:13:59 -0400 Subject: [PATCH] Enable RPC Server (#75) - Introduces rpc command to cli (rest-server) - Moves server/rpc to rpc/ - Enables module selection (eg. "web3" or "eth" or "web3,eth"), however there is no CLI flag to configure these (See #74) - Adds CLI context to eth API --- cmd/emintcli/main.go | 9 ++-- rpc/apis.go | 24 +++++++++++ {server/rpc => rpc}/apis_test.go | 3 +- rpc/config.go | 60 +++++++++++++++++++++++++++ {server/rpc => rpc}/eth_api.go | 11 +++-- {server/rpc => rpc}/rpc.go | 0 {server/rpc => rpc}/rpc_test.go | 0 server/rpc/apis.go => rpc/web3_api.go | 23 +--------- server/rpc/config.go | 16 ------- 9 files changed, 100 insertions(+), 46 deletions(-) create mode 100644 rpc/apis.go rename {server/rpc => rpc}/apis_test.go (92%) create mode 100644 rpc/config.go rename {server/rpc => rpc}/eth_api.go (97%) rename {server/rpc => rpc}/rpc.go (100%) rename {server/rpc => rpc}/rpc_test.go (100%) rename server/rpc/apis.go => rpc/web3_api.go (57%) delete mode 100644 server/rpc/config.go diff --git a/cmd/emintcli/main.go b/cmd/emintcli/main.go index 1d3856db..b2963b1c 100644 --- a/cmd/emintcli/main.go +++ b/cmd/emintcli/main.go @@ -6,10 +6,11 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/keys" - "github.com/cosmos/cosmos-sdk/client/rpc" + sdkrpc "github.com/cosmos/cosmos-sdk/client/rpc" sdk "github.com/cosmos/cosmos-sdk/types" emintapp "github.com/cosmos/ethermint/app" + "github.com/cosmos/ethermint/rpc" "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/tendermint/tendermint/libs/cli" @@ -18,7 +19,7 @@ import ( func main() { cobra.EnableCommandSorting = false - // TODO: Set up codec + cdc := emintapp.MakeCodec() // Read in the configuration file for the sdk config := sdk.GetConfig() @@ -40,12 +41,12 @@ func main() { // Construct Root Command rootCmd.AddCommand( - rpc.StatusCommand(), + sdkrpc.StatusCommand(), client.ConfigCmd(emintapp.DefaultCLIHome), // TODO: Set up query command // TODO: Set up tx command // TODO: Set up rest routes (if included, different from web3 api) - // TODO: Set up web3 API setup command? + rpc.Web3RpcCmd(cdc), client.LineBreak, keys.Commands(), client.LineBreak, diff --git a/rpc/apis.go b/rpc/apis.go new file mode 100644 index 00000000..1570bce5 --- /dev/null +++ b/rpc/apis.go @@ -0,0 +1,24 @@ +// Package rpc contains RPC handler methods and utilities to start +// Ethermint's Web3-compatibly JSON-RPC server. +package rpc + +import ( + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/ethereum/go-ethereum/rpc" +) + +// GetRPCAPIs returns the list of all APIs +func GetRPCAPIs(cliCtx context.CLIContext) []rpc.API { + return []rpc.API{ + { + Namespace: "web3", + Version: "1.0", + Service: NewPublicWeb3API(), + }, + { + Namespace: "eth", + Version: "1.0", + Service: NewPublicEthAPI(cliCtx), + }, + } +} diff --git a/server/rpc/apis_test.go b/rpc/apis_test.go similarity index 92% rename from server/rpc/apis_test.go rename to rpc/apis_test.go index e0140862..87822fe8 100644 --- a/server/rpc/apis_test.go +++ b/rpc/apis_test.go @@ -2,6 +2,7 @@ package rpc import ( "context" + sdkcontext"github.com/cosmos/cosmos-sdk/client/context" "testing" "time" @@ -67,7 +68,7 @@ func startAPIServer() (context.CancelFunc, int, error) { ctx, cancel := context.WithCancel(context.Background()) - _, err := StartHTTPEndpoint(ctx, config, GetRPCAPIs(), timeouts) + _, err := StartHTTPEndpoint(ctx, config, GetRPCAPIs(sdkcontext.NewCLIContext()), timeouts) if err != nil { return cancel, 0, err } diff --git a/rpc/config.go b/rpc/config.go new file mode 100644 index 00000000..43997155 --- /dev/null +++ b/rpc/config.go @@ -0,0 +1,60 @@ +package rpc + +import ( + "github.com/cosmos/cosmos-sdk/client/lcd" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/ethereum/go-ethereum/rpc" + "github.com/spf13/cobra" + "log" +) + +// defaultModules returns all available modules +func defaultModules() []string { + return []string{"web3", "eth"} +} + +// Config contains configuration fields that determine the behavior of the RPC HTTP server. +// TODO: These may become irrelevant if HTTP config is handled by the SDK +type Config struct { + // EnableRPC defines whether or not to enable the RPC server + EnableRPC bool + // RPCAddr defines the IP address to listen on + RPCAddr string + // RPCPort defines the port to listen on + RPCPort int + // RPCCORSDomains defines list of domains to enable CORS headers for (used by browsers) + RPCCORSDomains []string + // RPCVhosts defines list of domains to listen on (useful if Tendermint is addressable via DNS) + RPCVHosts []string +} + +// Web3RpcCmd creates a CLI command to start RPC server +func Web3RpcCmd(cdc *codec.Codec) *cobra.Command { + return lcd.ServeCommand(cdc, registerRoutes) +} + +// registerRoutes creates a new server and registers the `/rpc` endpoint. +// Rpc calls are enabled based on their associated module (eg. "eth"). +func registerRoutes(rs *lcd.RestServer) { + s := rpc.NewServer() + apis := GetRPCAPIs(rs.CliCtx) + + // TODO: Allow cli to configure modules https://github.com/ChainSafe/ethermint/issues/74 + modules := defaultModules() + whitelist := make(map[string]bool) + for _, module := range modules { + whitelist[module] = true + } + + // Register all the APIs exposed by the services + for _, api := range apis { + if whitelist[api.Namespace] || (len(whitelist) == 0 && api.Public) { + if err := s.RegisterName(api.Namespace, api.Service); err != nil { + log.Println(err) + return + } + } + } + + rs.Mux.HandleFunc("/rpc", s.ServeHTTP).Methods("POST") +} diff --git a/server/rpc/eth_api.go b/rpc/eth_api.go similarity index 97% rename from server/rpc/eth_api.go rename to rpc/eth_api.go index fc212ff0..15ab5880 100644 --- a/server/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -1,6 +1,7 @@ package rpc import ( + "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/ethermint/version" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -10,11 +11,15 @@ import ( ) // PublicEthAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec. -type PublicEthAPI struct{} +type PublicEthAPI struct{ + cliCtx context.CLIContext +} // NewPublicEthAPI creates an instance of the public ETH Web3 API. -func NewPublicEthAPI() *PublicEthAPI { - return &PublicEthAPI{} +func NewPublicEthAPI(cliCtx context.CLIContext) *PublicEthAPI { + return &PublicEthAPI{ + cliCtx: cliCtx, + } } // ProtocolVersion returns the supported Ethereum protocol version. diff --git a/server/rpc/rpc.go b/rpc/rpc.go similarity index 100% rename from server/rpc/rpc.go rename to rpc/rpc.go diff --git a/server/rpc/rpc_test.go b/rpc/rpc_test.go similarity index 100% rename from server/rpc/rpc_test.go rename to rpc/rpc_test.go diff --git a/server/rpc/apis.go b/rpc/web3_api.go similarity index 57% rename from server/rpc/apis.go rename to rpc/web3_api.go index 3286b5af..ec7c33d0 100644 --- a/server/rpc/apis.go +++ b/rpc/web3_api.go @@ -1,34 +1,13 @@ -// Package rpc contains RPC handler methods and utilities to start -// Ethermint's Web3-compatibly JSON-RPC server. package rpc import ( "github.com/cosmos/ethermint/version" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rpc" ) -// GetRPCAPIs returns the master list of public APIs for use with -// StartHTTPEndpoint. -func GetRPCAPIs() []rpc.API { - return []rpc.API{ - { - Namespace: "web3", - Version: "1.0", - Service: NewPublicWeb3API(), - }, - { - Namespace: "eth", - Version: "1.0", - Service: NewPublicEthAPI(), - }, - } -} - // PublicWeb3API is the web3_ prefixed set of APIs in the Web3 JSON-RPC spec. -type PublicWeb3API struct { -} +type PublicWeb3API struct {} // NewPublicWeb3API creates an instance of the Web3 API. func NewPublicWeb3API() *PublicWeb3API { diff --git a/server/rpc/config.go b/server/rpc/config.go deleted file mode 100644 index 2c030f1b..00000000 --- a/server/rpc/config.go +++ /dev/null @@ -1,16 +0,0 @@ -package rpc - -// Config contains configuration fields that determine the -// behavior of the RPC HTTP server. -type Config struct { - // EnableRPC defines whether or not to enable the RPC server - EnableRPC bool - // RPCAddr defines the IP address to listen on - RPCAddr string - // RPCPort defines the port to listen on - RPCPort int - // RPCCORSDomains defines list of domains to enable CORS headers for (used by browsers) - RPCCORSDomains []string - // RPCVhosts defines list of domains to listen on (useful if Tendermint is addressable via DNS) - RPCVHosts []string -}