From e96cd7c9b82fb48171b2b639dc1850b125695ca2 Mon Sep 17 00:00:00 2001 From: Edward Mack Date: Mon, 11 May 2020 16:33:29 -0400 Subject: [PATCH 1/7] implement RPC call system_name, system_version --- cmd/gossamer/main.go | 2 +- dot/node.go | 6 ++++-- dot/node_test.go | 8 ++++---- dot/rpc/http.go | 2 +- dot/rpc/http_test.go | 9 ++++++++- dot/rpc/modules/api.go | 2 ++ dot/rpc/modules/system.go | 12 +++++++----- dot/rpc/modules/system_test.go | 6 +++--- dot/rpc/service.go | 29 +++++++++++++++++++++++++++-- dot/rpc/service_test.go | 19 ++++++++++++++++--- dot/rpc/websocket_test.go | 12 +++++++++--- dot/services.go | 6 ++++-- dot/services_test.go | 10 +++++++++- 13 files changed, 95 insertions(+), 28 deletions(-) diff --git a/cmd/gossamer/main.go b/cmd/gossamer/main.go index 6e98d21a4c..4b31dc78d6 100644 --- a/cmd/gossamer/main.go +++ b/cmd/gossamer/main.go @@ -154,7 +154,7 @@ func gossamerAction(ctx *cli.Context) error { return err } - node, err := dot.NewNode(cfg, ks) + node, err := dot.NewNode(cfg, ks, ctx) if err != nil { log.Error("[cmd] failed to create node services", "error", err) return err diff --git a/dot/node.go b/dot/node.go index 2b21427a8b..316cbca465 100644 --- a/dot/node.go +++ b/dot/node.go @@ -24,6 +24,8 @@ import ( "path" "syscall" + "github.com/urfave/cli" + "github.com/ChainSafe/gossamer/dot/network" "github.com/ChainSafe/gossamer/dot/state" "github.com/ChainSafe/gossamer/lib/common" @@ -170,7 +172,7 @@ func NodeInitialized(datadir string, expected bool) bool { } // NewNode creates a new dot node from a dot node configuration -func NewNode(cfg *Config, ks *keystore.Keystore) (*Node, error) { +func NewNode(cfg *Config, ks *keystore.Keystore, ctx *cli.Context) (*Node, error) { // if authority node, should have at least 1 key in keystore if cfg.Core.Authority && ks.NumSr25519Keys() == 0 { @@ -241,7 +243,7 @@ func NewNode(cfg *Config, ks *keystore.Keystore) (*Node, error) { if enabled := RPCServiceEnabled(cfg); enabled { // create rpc service and append rpc service to node services - rpcSrvc := createRPCService(cfg, stateSrvc, coreSrvc, networkSrvc, rt) + rpcSrvc := createRPCService(cfg, stateSrvc, coreSrvc, networkSrvc, rt, ctx) nodeSrvcs = append(nodeSrvcs, rpcSrvc) } else { diff --git a/dot/node_test.go b/dot/node_test.go index bf2c6fbec8..c0b7ed5b3c 100644 --- a/dot/node_test.go +++ b/dot/node_test.go @@ -95,7 +95,7 @@ func TestNewNode(t *testing.T) { // TODO: improve dot tests #687 cfg.Core.Authority = false - _, err = NewNode(cfg, ks) + _, err = NewNode(cfg, ks, nil) require.Nil(t, err) } @@ -121,7 +121,7 @@ func TestStartNode(t *testing.T) { // TODO: improve dot tests #687 cfg.Core.Authority = false - node, err := NewNode(cfg, ks) + node, err := NewNode(cfg, ks, nil) require.Nil(t, err) go node.Start() @@ -225,7 +225,7 @@ func TestInitNode_LoadStorageRoot(t *testing.T) { ks := keystore.NewKeystore() require.NotNil(t, ks) - node, err := NewNode(cfg, ks) + node, err := NewNode(cfg, ks, nil) require.Nil(t, err) if reflect.TypeOf(node) != reflect.TypeOf(&Node{}) { @@ -278,7 +278,7 @@ func TestInitNode_LoadBalances(t *testing.T) { ks := keystore.NewKeystore() require.NotNil(t, ks) - node, err := NewNode(cfg, ks) + node, err := NewNode(cfg, ks, nil) require.Nil(t, err) if reflect.TypeOf(node) != reflect.TypeOf(&Node{}) { diff --git a/dot/rpc/http.go b/dot/rpc/http.go index 476df9c288..6affa5ec88 100644 --- a/dot/rpc/http.go +++ b/dot/rpc/http.go @@ -67,7 +67,7 @@ func (h *HTTPServer) RegisterModules(mods []string) { var srvc interface{} switch mod { case "system": - srvc = modules.NewSystemModule(h.serverConfig.NetworkAPI) + srvc = modules.NewSystemModule(h.serverConfig.NetworkAPI, h.serverConfig.RPCAPI) case "author": srvc = modules.NewAuthorModule(h.serverConfig.CoreAPI, h.serverConfig.RuntimeAPI, h.serverConfig.TransactionQueueAPI) case "chain": diff --git a/dot/rpc/http_test.go b/dot/rpc/http_test.go index 2591596f53..2cf521b37f 100644 --- a/dot/rpc/http_test.go +++ b/dot/rpc/http_test.go @@ -23,14 +23,21 @@ import ( "time" "github.com/stretchr/testify/require" + "github.com/urfave/cli" ) func TestNewHTTPServer(t *testing.T) { + ctx := &cli.Context{ + App: &cli.App{ + Name: "gossamer", + Version: "0.0.1", + }, + } cfg := &HTTPServerConfig{ Modules: []string{"system"}, RPCPort: 8545, - RPCAPI: NewService(), + RPCAPI: NewService(ctx), } s := NewHTTPServer(cfg) err := s.Start() diff --git a/dot/rpc/modules/api.go b/dot/rpc/modules/api.go index e9e5f169ff..4897747720 100644 --- a/dot/rpc/modules/api.go +++ b/dot/rpc/modules/api.go @@ -51,6 +51,8 @@ type CoreAPI interface { type RPCAPI interface { Methods() []string BuildMethodNames(rcvr interface{}, name string) + SystemName() string + SystemVersion() string } // RuntimeAPI is the interface for runtime methods diff --git a/dot/rpc/modules/system.go b/dot/rpc/modules/system.go index d411fe7eb4..1464fc1bf4 100644 --- a/dot/rpc/modules/system.go +++ b/dot/rpc/modules/system.go @@ -28,6 +28,7 @@ const NOT_IMPLEMENTED = "not yet implemented" // SystemModule is an RPC module providing access to core API points type SystemModule struct { networkAPI NetworkAPI + rpcAPI RPCAPI } // EmptyRequest represents an RPC request with no fields @@ -59,9 +60,10 @@ type SystemPropertiesResponse struct { } // NewSystemModule creates a new API instance -func NewSystemModule(net NetworkAPI) *SystemModule { +func NewSystemModule(net NetworkAPI, rpc RPCAPI) *SystemModule { return &SystemModule{ networkAPI: net, // TODO: migrate to network state + rpcAPI: rpc, } } @@ -72,8 +74,8 @@ func (sm *SystemModule) Chain(r *http.Request, req *EmptyRequest, res *StringRes } // Name returns the runtime name -func (sm *SystemModule) Name(r *http.Request, req *EmptyRequest, res *StringResponse) error { - *res = "gossamer v0.0" +func (sm *SystemModule) Name(r *http.Request, req *EmptyRequest, res *string) error { + *res = sm.rpcAPI.SystemName() return nil } @@ -84,8 +86,8 @@ func (sm *SystemModule) Properties(r *http.Request, req *EmptyRequest, res *Stri } // Version returns the runtime version -func (sm *SystemModule) Version(r *http.Request, req *EmptyRequest, res *StringResponse) error { - *res = NOT_IMPLEMENTED +func (sm *SystemModule) Version(r *http.Request, req *EmptyRequest, res *string) error { + *res = sm.rpcAPI.SystemVersion() return nil } diff --git a/dot/rpc/modules/system_test.go b/dot/rpc/modules/system_test.go index 63db6b3618..86f3ee1741 100644 --- a/dot/rpc/modules/system_test.go +++ b/dot/rpc/modules/system_test.go @@ -59,7 +59,7 @@ func newNetworkService(t *testing.T) *network.Service { // Test RPC's System.Health() response func TestSystemModule_Health(t *testing.T) { net := newNetworkService(t) - sys := NewSystemModule(net) + sys := NewSystemModule(net, nil) res := &SystemHealthResponse{} sys.Health(nil, nil, res) @@ -72,7 +72,7 @@ func TestSystemModule_Health(t *testing.T) { // Test RPC's System.NetworkState() response func TestSystemModule_NetworkState(t *testing.T) { net := newNetworkService(t) - sys := NewSystemModule(net) + sys := NewSystemModule(net, nil) res := &SystemNetworkStateResponse{} sys.NetworkState(nil, nil, res) @@ -87,7 +87,7 @@ func TestSystemModule_NetworkState(t *testing.T) { // Test RPC's System.Peers() response func TestSystemModule_Peers(t *testing.T) { net := newNetworkService(t) - sys := NewSystemModule(net) + sys := NewSystemModule(net, nil) res := &SystemPeersResponse{} sys.Peers(nil, nil, res) diff --git a/dot/rpc/service.go b/dot/rpc/service.go index 8843f8e047..89bcf6f363 100644 --- a/dot/rpc/service.go +++ b/dot/rpc/service.go @@ -21,16 +21,31 @@ import ( "strings" "unicode" "unicode/utf8" + + "github.com/urfave/cli" ) // Service struct to hold rpc service data type Service struct { rpcMethods []string // list of method names offered by rpc + systemInfo *systemInfo +} + +type systemInfo struct { + systemName string + systemVersion string } // NewService create a new instance of Service -func NewService() *Service { - return &Service{rpcMethods: []string{}} +func NewService(ctx *cli.Context) *Service { + si := &systemInfo{ + systemName: ctx.App.Name, + systemVersion: ctx.App.Version, + } + return &Service{ + rpcMethods: []string{}, + systemInfo: si, + } } // Methods returns list of methods available via RPC call @@ -38,6 +53,16 @@ func (s *Service) Methods() []string { return s.rpcMethods } +// SystemName returns the app name +func (s *Service) SystemName() string { + return s.systemInfo.systemName +} + +// SystemVersion returns the app version +func (s *Service) SystemVersion() string { + return s.systemInfo.systemVersion +} + var ( // Precompute the reflect.Type of error and http.Request typeOfError = reflect.TypeOf((*error)(nil)).Elem() diff --git a/dot/rpc/service_test.go b/dot/rpc/service_test.go index c12e74b108..e8383ca8da 100644 --- a/dot/rpc/service_test.go +++ b/dot/rpc/service_test.go @@ -20,10 +20,17 @@ import ( "github.com/ChainSafe/gossamer/dot/rpc/modules" "github.com/stretchr/testify/require" + "github.com/urfave/cli" ) func TestNewService(t *testing.T) { - NewService() + ctx := &cli.Context{ + App: &cli.App{ + Name: "gossamer", + Version: "0.0.1", + }, + } + NewService(ctx) } func TestService_Methods(t *testing.T) { @@ -31,8 +38,14 @@ func TestService_Methods(t *testing.T) { qtyRPCMethods := 1 qtyAuthorMethods := 6 - rpcService := NewService() - sysMod := modules.NewSystemModule(nil) + ctx := &cli.Context{ + App: &cli.App{ + Name: "gossamer", + Version: "0.0.1", + }, + } + rpcService := NewService(ctx) + sysMod := modules.NewSystemModule(nil, nil) rpcService.BuildMethodNames(sysMod, "system") m := rpcService.Methods() require.Equal(t, qtySystemMethods, len(m)) // check to confirm quantity for methods is correct diff --git a/dot/rpc/websocket_test.go b/dot/rpc/websocket_test.go index 46b050c46b..048780f0a1 100644 --- a/dot/rpc/websocket_test.go +++ b/dot/rpc/websocket_test.go @@ -9,6 +9,7 @@ import ( "github.com/gorilla/websocket" "github.com/stretchr/testify/require" + "github.com/urfave/cli" ) var addr = flag.String("addr", "localhost:8546", "http service address") @@ -16,18 +17,23 @@ var testCalls = []struct { call []byte expected []byte }{ - {[]byte(`{"jsonrpc":"2.0","method":"system_name","params":[],"id":1}`), []byte(`{"id":1,"jsonrpc":"2.0","result":"gossamer v0.0"}` + "\n")}, // working request + {[]byte(`{"jsonrpc":"2.0","method":"system_name","params":[],"id":1}`), []byte(`{"id":1,"jsonrpc":"2.0","result":"gossamer"}` + "\n")}, // working request {[]byte(`{"jsonrpc":"2.0","method":"unknown","params":[],"id":1}`), []byte(`{"error":{"code":-32000,"data":null,"message":"rpc error method unknown not found"},"id":1,"jsonrpc":"2.0"}` + "\n")}, // unknown method {[]byte{}, []byte(`{"error":{"code":-32700,"data":{"id":null,"jsonrpc":"","method":"","params":null},"message":"EOF"},"id":null,"jsonrpc":"2.0"}` + "\n")}, // empty request } func TestNewWebSocketServer(t *testing.T) { - + ctx := &cli.Context{ + App: &cli.App{ + Name: "gossamer", + Version: "0.0.1", + }, + } cfg := &HTTPServerConfig{ Modules: []string{"system"}, RPCPort: 8545, WSPort: 8546, - RPCAPI: NewService(), + RPCAPI: NewService(ctx), } s := NewHTTPServer(cfg) err := s.Start() diff --git a/dot/services.go b/dot/services.go index 19b46f01a8..3260dd79e6 100644 --- a/dot/services.go +++ b/dot/services.go @@ -20,6 +20,8 @@ import ( "fmt" "math/big" + "github.com/urfave/cli" + "github.com/ChainSafe/gossamer/dot/core" "github.com/ChainSafe/gossamer/dot/network" "github.com/ChainSafe/gossamer/dot/rpc" @@ -144,7 +146,7 @@ func createNetworkService(cfg *Config, stateSrvc *state.Service, coreMsgs chan n // RPC Service // createRPCService creates the RPC service from the provided core configuration -func createRPCService(cfg *Config, stateSrvc *state.Service, coreSrvc *core.Service, networkSrvc *network.Service, rt *runtime.Runtime) *rpc.HTTPServer { +func createRPCService(cfg *Config, stateSrvc *state.Service, coreSrvc *core.Service, networkSrvc *network.Service, rt *runtime.Runtime, ctx *cli.Context) *rpc.HTTPServer { log.Info( "[dot] creating rpc service...", "host", cfg.RPC.Host, @@ -152,7 +154,7 @@ func createRPCService(cfg *Config, stateSrvc *state.Service, coreSrvc *core.Serv "mods", cfg.RPC.Modules, "ws port", cfg.RPC.WSPort, ) - rpcService := rpc.NewService() + rpcService := rpc.NewService(ctx) rpcConfig := &rpc.HTTPServerConfig{ BlockAPI: stateSrvc.Block, diff --git a/dot/services_test.go b/dot/services_test.go index 6a1c9a26c3..9e6579ad17 100644 --- a/dot/services_test.go +++ b/dot/services_test.go @@ -23,6 +23,7 @@ import ( "github.com/ChainSafe/gossamer/dot/network" "github.com/ChainSafe/gossamer/lib/keystore" "github.com/ChainSafe/gossamer/lib/utils" + "github.com/urfave/cli" "github.com/stretchr/testify/require" ) @@ -150,7 +151,14 @@ func TestCreateRPCService(t *testing.T) { networkSrvc := &network.Service{} // TODO: rpc service without network service - rpcSrvc := createRPCService(cfg, stateSrvc, coreSrvc, networkSrvc, rt) + ctx := &cli.Context{ + App: &cli.App{ + Name: "gossamer", + Version: "0.0.1", + }, + } + + rpcSrvc := createRPCService(cfg, stateSrvc, coreSrvc, networkSrvc, rt, ctx) require.Nil(t, err) // TODO: improve dot tests #687 From 03e7c1219464995c53322ba25c754b5c669bd789 Mon Sep 17 00:00:00 2001 From: Edward Mack Date: Mon, 11 May 2020 17:37:49 -0400 Subject: [PATCH 2/7] implement RPC call system_chain --- dot/rpc/http_test.go | 2 +- dot/rpc/modules/api.go | 1 + dot/rpc/modules/system.go | 4 ++-- dot/rpc/service.go | 9 ++++++++- dot/rpc/service_test.go | 4 ++-- dot/rpc/websocket_test.go | 4 ++-- dot/services.go | 2 +- 7 files changed, 17 insertions(+), 9 deletions(-) diff --git a/dot/rpc/http_test.go b/dot/rpc/http_test.go index 2cf521b37f..dcabca60f8 100644 --- a/dot/rpc/http_test.go +++ b/dot/rpc/http_test.go @@ -37,7 +37,7 @@ func TestNewHTTPServer(t *testing.T) { cfg := &HTTPServerConfig{ Modules: []string{"system"}, RPCPort: 8545, - RPCAPI: NewService(ctx), + RPCAPI: NewService(ctx, "gssmr"), } s := NewHTTPServer(cfg) err := s.Start() diff --git a/dot/rpc/modules/api.go b/dot/rpc/modules/api.go index 4897747720..dfb4d52fae 100644 --- a/dot/rpc/modules/api.go +++ b/dot/rpc/modules/api.go @@ -53,6 +53,7 @@ type RPCAPI interface { BuildMethodNames(rcvr interface{}, name string) SystemName() string SystemVersion() string + NodeName() string } // RuntimeAPI is the interface for runtime methods diff --git a/dot/rpc/modules/system.go b/dot/rpc/modules/system.go index 1464fc1bf4..01575aa393 100644 --- a/dot/rpc/modules/system.go +++ b/dot/rpc/modules/system.go @@ -68,8 +68,8 @@ func NewSystemModule(net NetworkAPI, rpc RPCAPI) *SystemModule { } // Chain returns the runtime chain -func (sm *SystemModule) Chain(r *http.Request, req *EmptyRequest, res *StringResponse) error { - *res = NOT_IMPLEMENTED +func (sm *SystemModule) Chain(r *http.Request, req *EmptyRequest, res *string) error { + *res = sm.rpcAPI.NodeName() return nil } diff --git a/dot/rpc/service.go b/dot/rpc/service.go index 89bcf6f363..84df4d59fc 100644 --- a/dot/rpc/service.go +++ b/dot/rpc/service.go @@ -34,13 +34,15 @@ type Service struct { type systemInfo struct { systemName string systemVersion string + nodeName string } // NewService create a new instance of Service -func NewService(ctx *cli.Context) *Service { +func NewService(ctx *cli.Context, nodeName string) *Service { si := &systemInfo{ systemName: ctx.App.Name, systemVersion: ctx.App.Version, + nodeName: nodeName, } return &Service{ rpcMethods: []string{}, @@ -63,6 +65,11 @@ func (s *Service) SystemVersion() string { return s.systemInfo.systemVersion } +// NodeName returns the nodeName (chain name) +func (s *Service) NodeName() string { + return s.systemInfo.nodeName +} + var ( // Precompute the reflect.Type of error and http.Request typeOfError = reflect.TypeOf((*error)(nil)).Elem() diff --git a/dot/rpc/service_test.go b/dot/rpc/service_test.go index e8383ca8da..19677eaebc 100644 --- a/dot/rpc/service_test.go +++ b/dot/rpc/service_test.go @@ -30,7 +30,7 @@ func TestNewService(t *testing.T) { Version: "0.0.1", }, } - NewService(ctx) + NewService(ctx, "gssmr") } func TestService_Methods(t *testing.T) { @@ -44,7 +44,7 @@ func TestService_Methods(t *testing.T) { Version: "0.0.1", }, } - rpcService := NewService(ctx) + rpcService := NewService(ctx, "gssmr") sysMod := modules.NewSystemModule(nil, nil) rpcService.BuildMethodNames(sysMod, "system") m := rpcService.Methods() diff --git a/dot/rpc/websocket_test.go b/dot/rpc/websocket_test.go index 048780f0a1..34d354c7d8 100644 --- a/dot/rpc/websocket_test.go +++ b/dot/rpc/websocket_test.go @@ -17,7 +17,7 @@ var testCalls = []struct { call []byte expected []byte }{ - {[]byte(`{"jsonrpc":"2.0","method":"system_name","params":[],"id":1}`), []byte(`{"id":1,"jsonrpc":"2.0","result":"gossamer"}` + "\n")}, // working request + {[]byte(`{"jsonrpc":"2.0","method":"system_name","params":[],"id":1}`), []byte(`{"id":1,"jsonrpc":"2.0","result":"gossamer"}` + "\n")}, // working request {[]byte(`{"jsonrpc":"2.0","method":"unknown","params":[],"id":1}`), []byte(`{"error":{"code":-32000,"data":null,"message":"rpc error method unknown not found"},"id":1,"jsonrpc":"2.0"}` + "\n")}, // unknown method {[]byte{}, []byte(`{"error":{"code":-32700,"data":{"id":null,"jsonrpc":"","method":"","params":null},"message":"EOF"},"id":null,"jsonrpc":"2.0"}` + "\n")}, // empty request } @@ -33,7 +33,7 @@ func TestNewWebSocketServer(t *testing.T) { Modules: []string{"system"}, RPCPort: 8545, WSPort: 8546, - RPCAPI: NewService(ctx), + RPCAPI: NewService(ctx, "gssmr"), } s := NewHTTPServer(cfg) err := s.Start() diff --git a/dot/services.go b/dot/services.go index 3260dd79e6..aef54c1dc3 100644 --- a/dot/services.go +++ b/dot/services.go @@ -154,7 +154,7 @@ func createRPCService(cfg *Config, stateSrvc *state.Service, coreSrvc *core.Serv "mods", cfg.RPC.Modules, "ws port", cfg.RPC.WSPort, ) - rpcService := rpc.NewService(ctx) + rpcService := rpc.NewService(ctx, cfg.Global.Name) rpcConfig := &rpc.HTTPServerConfig{ BlockAPI: stateSrvc.Block, From b344113b5aa4093c42b5e7465befe9a11fad5a4b Mon Sep 17 00:00:00 2001 From: Edward Mack Date: Mon, 11 May 2020 18:10:13 -0400 Subject: [PATCH 3/7] added tests --- dot/rpc/service_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/dot/rpc/service_test.go b/dot/rpc/service_test.go index 19677eaebc..7d035ff4bb 100644 --- a/dot/rpc/service_test.go +++ b/dot/rpc/service_test.go @@ -60,3 +60,42 @@ func TestService_Methods(t *testing.T) { m = rpcService.Methods() require.Equal(t, qtySystemMethods+qtyRPCMethods+qtyAuthorMethods, len(m)) } + +func TestService_NodeName(t *testing.T) { + ctx := &cli.Context{ + App: &cli.App{ + Name: "gossamer", + Version: "0.0.1", + }, + } + rpcService := NewService(ctx, "gssmr") + + name := rpcService.NodeName() + require.Equal(t, "gssmr", name) +} + +func TestService_SystemName(t *testing.T) { + ctx := &cli.Context{ + App: &cli.App{ + Name: "gossamer", + Version: "0.0.1", + }, + } + rpcService := NewService(ctx, "gssmr") + + name := rpcService.SystemName() + require.Equal(t, "gossamer", name) +} + +func TestService_SystemVersion(t *testing.T) { + ctx := &cli.Context{ + App: &cli.App{ + Name: "gossamer", + Version: "0.0.1", + }, + } + rpcService := NewService(ctx, "gssmr") + + ver := rpcService.SystemVersion() + require.Equal(t, "0.0.1", ver) +} From d04e7e6f445ea752286df2ce04be19c97124e8ad Mon Sep 17 00:00:00 2001 From: Edward Mack Date: Mon, 18 May 2020 10:47:20 -0400 Subject: [PATCH 4/7] save commit, refactoring rpc module --- cmd/gossamer/config.go | 16 ++++++++++++++++ cmd/gossamer/main.go | 2 +- dot/config.go | 20 ++++++++++++++++++++ dot/node.go | 6 ++---- dot/rpc/modules/system.go | 2 +- dot/rpc/modules/system_test.go | 14 ++++++++++++++ dot/rpc/service.go | 26 +++++++++----------------- dot/services.go | 6 ++---- dot/types/system.go | 14 ++++++++++++++ 9 files changed, 79 insertions(+), 27 deletions(-) create mode 100644 dot/types/system.go diff --git a/cmd/gossamer/config.go b/cmd/gossamer/config.go index fbc5cd02a2..b5e59f47a6 100644 --- a/cmd/gossamer/config.go +++ b/cmd/gossamer/config.go @@ -18,6 +18,7 @@ package main import ( "fmt" + "github.com/ChainSafe/gossamer/dot/types" "strconv" "strings" @@ -95,6 +96,9 @@ func createDotConfig(ctx *cli.Context) (cfg *dot.Config, err error) { setDotNetworkConfig(ctx, &cfg.Network) setDotRPCConfig(ctx, &cfg.RPC) + // set system info + setSystemInfoConfig(ctx, &cfg.System) + return cfg, nil } @@ -112,6 +116,9 @@ func createInitConfig(ctx *cli.Context) (cfg *dot.Config, err error) { // set init configuration values setDotInitConfig(ctx, &cfg.Init) + // set system info + setSystemInfoConfig(ctx, &cfg.System) + // ensure configuration values match genesis and overwrite with genesis updateDotConfigFromGenesisJSON(ctx, cfg) @@ -137,6 +144,9 @@ func createExportConfig(ctx *cli.Context) (cfg *dot.Config) { setDotNetworkConfig(ctx, &cfg.Network) setDotRPCConfig(ctx, &cfg.RPC) + // set system info + setSystemInfoConfig(ctx, &cfg.System) + return cfg } @@ -321,6 +331,12 @@ func setDotRPCConfig(ctx *cli.Context, cfg *dot.RPCConfig) { ) } +func setSystemInfoConfig(ctx *cli.Context, cfg *types.SystemInfo) { + // load system information + cfg.SystemName = ctx.App.Name + cfg.SystemVersion = ctx.App.Version +} + // updateDotConfigFromGenesisJSON updates the configuration based on the genesis file values func updateDotConfigFromGenesisJSON(ctx *cli.Context, cfg *dot.Config) { diff --git a/cmd/gossamer/main.go b/cmd/gossamer/main.go index 4b31dc78d6..6e98d21a4c 100644 --- a/cmd/gossamer/main.go +++ b/cmd/gossamer/main.go @@ -154,7 +154,7 @@ func gossamerAction(ctx *cli.Context) error { return err } - node, err := dot.NewNode(cfg, ks, ctx) + node, err := dot.NewNode(cfg, ks) if err != nil { log.Error("[cmd] failed to create node services", "error", err) return err diff --git a/dot/config.go b/dot/config.go index b83f8c53ee..140e4cee6c 100644 --- a/dot/config.go +++ b/dot/config.go @@ -19,6 +19,7 @@ package dot import ( "encoding/json" "fmt" + "github.com/ChainSafe/gossamer/dot/types" "os" "path/filepath" "reflect" @@ -39,6 +40,7 @@ type Config struct { Core CoreConfig `toml:"core"` Network NetworkConfig `toml:"network"` RPC RPCConfig `toml:"rpc"` + System types.SystemInfo } // GlobalConfig is to marshal/unmarshal toml global config vars @@ -131,6 +133,15 @@ func GssmrConfig() *Config { Modules: gssmr.DefaultRPCModules, WSPort: gssmr.DefaultRPCWSPort, }, + System: types.SystemInfo{ + // TODO determine how to get these values from genesis.json + //nodeName: gssmr.DefaultName, + //systemProperties: systemProperties{ + // Ss58Format: 0, + // TokenDecimals: 0, + // TokenSymbol: "", + //}, + }, } } @@ -166,6 +177,15 @@ func KsmccConfig() *Config { Modules: ksmcc.DefaultRPCModules, WSPort: ksmcc.DefaultRPCWSPort, }, + System: types.SystemInfo{ + // TODO determine how to get these values from genesis.json + //nodeName: ksmcc.DefaultName, + //systemProperties: systemProperties{ + // Ss58Format: 0, + // TokenDecimals: 0, + // TokenSymbol: "", + //}, + }, } } diff --git a/dot/node.go b/dot/node.go index 316cbca465..2b21427a8b 100644 --- a/dot/node.go +++ b/dot/node.go @@ -24,8 +24,6 @@ import ( "path" "syscall" - "github.com/urfave/cli" - "github.com/ChainSafe/gossamer/dot/network" "github.com/ChainSafe/gossamer/dot/state" "github.com/ChainSafe/gossamer/lib/common" @@ -172,7 +170,7 @@ func NodeInitialized(datadir string, expected bool) bool { } // NewNode creates a new dot node from a dot node configuration -func NewNode(cfg *Config, ks *keystore.Keystore, ctx *cli.Context) (*Node, error) { +func NewNode(cfg *Config, ks *keystore.Keystore) (*Node, error) { // if authority node, should have at least 1 key in keystore if cfg.Core.Authority && ks.NumSr25519Keys() == 0 { @@ -243,7 +241,7 @@ func NewNode(cfg *Config, ks *keystore.Keystore, ctx *cli.Context) (*Node, error if enabled := RPCServiceEnabled(cfg); enabled { // create rpc service and append rpc service to node services - rpcSrvc := createRPCService(cfg, stateSrvc, coreSrvc, networkSrvc, rt, ctx) + rpcSrvc := createRPCService(cfg, stateSrvc, coreSrvc, networkSrvc, rt) nodeSrvcs = append(nodeSrvcs, rpcSrvc) } else { diff --git a/dot/rpc/modules/system.go b/dot/rpc/modules/system.go index 288565c81a..a0eee1285c 100644 --- a/dot/rpc/modules/system.go +++ b/dot/rpc/modules/system.go @@ -52,7 +52,7 @@ type SystemPeersResponse struct { Peers []common.PeerInfo `json:"peers"` } -// SystemPropertiesResponse struct to marshal json +//SystemPropertiesResponse struct to marshal json type SystemPropertiesResponse struct { Ss58Format int `json:"ss58Format"` TokenDecimals int `json:"tokenDecimals"` diff --git a/dot/rpc/modules/system_test.go b/dot/rpc/modules/system_test.go index 86f3ee1741..399ceeeb3a 100644 --- a/dot/rpc/modules/system_test.go +++ b/dot/rpc/modules/system_test.go @@ -17,6 +17,9 @@ package modules import ( + "fmt" + "github.com/ChainSafe/gossamer/dot/rpc" + "github.com/ChainSafe/gossamer/dot/types" "math/big" "os" "path" @@ -96,3 +99,14 @@ func TestSystemModule_Peers(t *testing.T) { t.Errorf("System.Peers: expected: %+v got: %+v\n", testPeers, res.Peers) } } + +func TestSystemModule_Name(t *testing.T) { + sysCfg := &types.SystemInfo{ + SystemName: "fooBar", + } + rpcService := rpc.NewService(sysCfg) + sys := NewSystemModule(nil, rpcService) + var res string + sys.Chain(nil, nil, &res) + fmt.Printf("SystemName %v\n", res) +} diff --git a/dot/rpc/service.go b/dot/rpc/service.go index 84df4d59fc..24a9400754 100644 --- a/dot/rpc/service.go +++ b/dot/rpc/service.go @@ -16,34 +16,23 @@ package rpc import ( + "github.com/ChainSafe/gossamer/dot/types" "net/http" "reflect" "strings" "unicode" "unicode/utf8" - - "github.com/urfave/cli" ) // Service struct to hold rpc service data type Service struct { rpcMethods []string // list of method names offered by rpc - systemInfo *systemInfo + systemInfo *types.SystemInfo } -type systemInfo struct { - systemName string - systemVersion string - nodeName string -} // NewService create a new instance of Service -func NewService(ctx *cli.Context, nodeName string) *Service { - si := &systemInfo{ - systemName: ctx.App.Name, - systemVersion: ctx.App.Version, - nodeName: nodeName, - } +func NewService(si *types.SystemInfo) *Service { return &Service{ rpcMethods: []string{}, systemInfo: si, @@ -57,17 +46,20 @@ func (s *Service) Methods() []string { // SystemName returns the app name func (s *Service) SystemName() string { - return s.systemInfo.systemName + //return s.systemInfo.SystemName + return "" } // SystemVersion returns the app version func (s *Service) SystemVersion() string { - return s.systemInfo.systemVersion + //return s.systemInfo.SystemVersion + return "" } // NodeName returns the nodeName (chain name) func (s *Service) NodeName() string { - return s.systemInfo.nodeName + //return s.systemInfo.NodeName + return "" } var ( diff --git a/dot/services.go b/dot/services.go index aef54c1dc3..cd5f627fe3 100644 --- a/dot/services.go +++ b/dot/services.go @@ -20,8 +20,6 @@ import ( "fmt" "math/big" - "github.com/urfave/cli" - "github.com/ChainSafe/gossamer/dot/core" "github.com/ChainSafe/gossamer/dot/network" "github.com/ChainSafe/gossamer/dot/rpc" @@ -146,7 +144,7 @@ func createNetworkService(cfg *Config, stateSrvc *state.Service, coreMsgs chan n // RPC Service // createRPCService creates the RPC service from the provided core configuration -func createRPCService(cfg *Config, stateSrvc *state.Service, coreSrvc *core.Service, networkSrvc *network.Service, rt *runtime.Runtime, ctx *cli.Context) *rpc.HTTPServer { +func createRPCService(cfg *Config, stateSrvc *state.Service, coreSrvc *core.Service, networkSrvc *network.Service, rt *runtime.Runtime) *rpc.HTTPServer { log.Info( "[dot] creating rpc service...", "host", cfg.RPC.Host, @@ -154,7 +152,7 @@ func createRPCService(cfg *Config, stateSrvc *state.Service, coreSrvc *core.Serv "mods", cfg.RPC.Modules, "ws port", cfg.RPC.WSPort, ) - rpcService := rpc.NewService(ctx, cfg.Global.Name) + rpcService := rpc.NewService(nil) rpcConfig := &rpc.HTTPServerConfig{ BlockAPI: stateSrvc.Block, diff --git a/dot/types/system.go b/dot/types/system.go new file mode 100644 index 0000000000..cb7661f111 --- /dev/null +++ b/dot/types/system.go @@ -0,0 +1,14 @@ +package types + +type SystemInfo struct { + SystemName string + SystemVersion string + NodeName string + SystemProperties systemProperties +} + +type systemProperties struct { + Ss58Format int + TokenDecimals int + TokenSymbol string +} From 2f0d66c742a9d009bb0d30b0cbcd6231efd74d6e Mon Sep 17 00:00:00 2001 From: Edward Mack Date: Mon, 18 May 2020 16:16:15 -0400 Subject: [PATCH 5/7] move system rpc api to it's own package --- cmd/gossamer/config.go | 11 ++++--- dot/config.go | 17 +++++------ dot/node_test.go | 8 ++--- dot/rpc/http.go | 3 +- dot/rpc/http_test.go | 22 ++++++------- dot/rpc/modules/api.go | 10 ++++-- dot/rpc/modules/system.go | 12 ++++---- dot/rpc/modules/system_test.go | 14 --------- dot/rpc/service.go | 24 +-------------- dot/rpc/service_test.go | 56 ++-------------------------------- dot/rpc/websocket_test.go | 15 ++++----- dot/services.go | 6 ++-- dot/services_test.go | 11 +------ dot/system/service.go | 46 ++++++++++++++++++++++++++++ dot/system/service_test.go | 53 ++++++++++++++++++++++++++++++++ dot/types/system.go | 7 +++-- node/gssmr/config.toml | 1 + node/ksmcc/config.toml | 1 + 18 files changed, 165 insertions(+), 152 deletions(-) create mode 100644 dot/system/service.go create mode 100644 dot/system/service_test.go diff --git a/cmd/gossamer/config.go b/cmd/gossamer/config.go index 1e09b45ee5..1d2110b7ea 100644 --- a/cmd/gossamer/config.go +++ b/cmd/gossamer/config.go @@ -18,16 +18,15 @@ package main import ( "fmt" - "github.com/ChainSafe/gossamer/dot/types" "strconv" "strings" + database "github.com/ChainSafe/chaindb" "github.com/ChainSafe/gossamer/dot" "github.com/ChainSafe/gossamer/dot/state" + "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/genesis" - - database "github.com/ChainSafe/chaindb" log "github.com/ChainSafe/log15" "github.com/urfave/cli" ) @@ -344,8 +343,10 @@ func setDotRPCConfig(ctx *cli.Context, cfg *dot.RPCConfig) { func setSystemInfoConfig(ctx *cli.Context, cfg *types.SystemInfo) { // load system information - cfg.SystemName = ctx.App.Name - cfg.SystemVersion = ctx.App.Version + if ctx.App != nil { + cfg.SystemName = ctx.App.Name + cfg.SystemVersion = ctx.App.Version + } } // updateDotConfigFromGenesisJSON updates the configuration based on the genesis file values diff --git a/dot/config.go b/dot/config.go index fc862dbaf6..2e5fc752e1 100644 --- a/dot/config.go +++ b/dot/config.go @@ -19,28 +19,27 @@ package dot import ( "encoding/json" "fmt" - "github.com/ChainSafe/gossamer/dot/types" "os" "path/filepath" "reflect" "unicode" + "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/node/gssmr" "github.com/ChainSafe/gossamer/node/ksmcc" - log "github.com/ChainSafe/log15" "github.com/naoina/toml" ) // Config is a collection of configurations throughout the system type Config struct { - Global GlobalConfig `toml:"global"` - Init InitConfig `toml:"init"` - Account AccountConfig `toml:"account"` - Core CoreConfig `toml:"core"` - Network NetworkConfig `toml:"network"` - RPC RPCConfig `toml:"rpc"` - System types.SystemInfo + Global GlobalConfig `toml:"global"` + Init InitConfig `toml:"init"` + Account AccountConfig `toml:"account"` + Core CoreConfig `toml:"core"` + Network NetworkConfig `toml:"network"` + RPC RPCConfig `toml:"rpc"` + System types.SystemInfo `toml:"-"` } // GlobalConfig is to marshal/unmarshal toml global config vars diff --git a/dot/node_test.go b/dot/node_test.go index c0b7ed5b3c..bf2c6fbec8 100644 --- a/dot/node_test.go +++ b/dot/node_test.go @@ -95,7 +95,7 @@ func TestNewNode(t *testing.T) { // TODO: improve dot tests #687 cfg.Core.Authority = false - _, err = NewNode(cfg, ks, nil) + _, err = NewNode(cfg, ks) require.Nil(t, err) } @@ -121,7 +121,7 @@ func TestStartNode(t *testing.T) { // TODO: improve dot tests #687 cfg.Core.Authority = false - node, err := NewNode(cfg, ks, nil) + node, err := NewNode(cfg, ks) require.Nil(t, err) go node.Start() @@ -225,7 +225,7 @@ func TestInitNode_LoadStorageRoot(t *testing.T) { ks := keystore.NewKeystore() require.NotNil(t, ks) - node, err := NewNode(cfg, ks, nil) + node, err := NewNode(cfg, ks) require.Nil(t, err) if reflect.TypeOf(node) != reflect.TypeOf(&Node{}) { @@ -278,7 +278,7 @@ func TestInitNode_LoadBalances(t *testing.T) { ks := keystore.NewKeystore() require.NotNil(t, ks) - node, err := NewNode(cfg, ks, nil) + node, err := NewNode(cfg, ks) require.Nil(t, err) if reflect.TypeOf(node) != reflect.TypeOf(&Node{}) { diff --git a/dot/rpc/http.go b/dot/rpc/http.go index cd6617b280..27a9cfd0eb 100644 --- a/dot/rpc/http.go +++ b/dot/rpc/http.go @@ -44,6 +44,7 @@ type HTTPServerConfig struct { RuntimeAPI modules.RuntimeAPI TransactionQueueAPI modules.TransactionQueueAPI RPCAPI modules.RPCAPI + SystemAPI modules.SystemAPI Host string RPCPort uint32 WSEnabled bool @@ -81,7 +82,7 @@ func (h *HTTPServer) RegisterModules(mods []string) { var srvc interface{} switch mod { case "system": - srvc = modules.NewSystemModule(h.serverConfig.NetworkAPI, h.serverConfig.RPCAPI) + srvc = modules.NewSystemModule(h.serverConfig.NetworkAPI, h.serverConfig.SystemAPI) case "author": srvc = modules.NewAuthorModule(h.serverConfig.CoreAPI, h.serverConfig.RuntimeAPI, h.serverConfig.TransactionQueueAPI) case "chain": diff --git a/dot/rpc/http_test.go b/dot/rpc/http_test.go index 18e6a0cd27..c30d46395c 100644 --- a/dot/rpc/http_test.go +++ b/dot/rpc/http_test.go @@ -23,23 +23,23 @@ import ( "time" "github.com/ChainSafe/gossamer/dot/core" + "github.com/ChainSafe/gossamer/dot/system" + "github.com/ChainSafe/gossamer/dot/types" "github.com/stretchr/testify/require" - "github.com/urfave/cli" ) func TestNewHTTPServer(t *testing.T) { - ctx := &cli.Context{ - App: &cli.App{ - Name: "gossamer", - Version: "0.0.1", - }, - } coreAPI := core.NewTestService(t, nil) + si := &types.SystemInfo{ + SystemName: "gossamer", + } + sysAPI := system.NewService(si) cfg := &HTTPServerConfig{ - Modules: []string{"system"}, - RPCPort: 8545, - RPCAPI: NewService(ctx, "gssmr"), - CoreAPI: coreAPI, + Modules: []string{"system"}, + RPCPort: 8545, + RPCAPI: NewService(), + CoreAPI: coreAPI, + SystemAPI: sysAPI, } s := NewHTTPServer(cfg) diff --git a/dot/rpc/modules/api.go b/dot/rpc/modules/api.go index 9b4f74052a..f033bf7d77 100644 --- a/dot/rpc/modules/api.go +++ b/dot/rpc/modules/api.go @@ -53,12 +53,16 @@ type CoreAPI interface { type RPCAPI interface { Methods() []string BuildMethodNames(rcvr interface{}, name string) - SystemName() string - SystemVersion() string - NodeName() string } // RuntimeAPI is the interface for runtime methods type RuntimeAPI interface { ValidateTransaction(e types.Extrinsic) (*transaction.Validity, error) } + +// SystemAPI is the interface for handling system methods +type SystemAPI interface { + SystemName() string + SystemVersion() string + NodeName() string +} diff --git a/dot/rpc/modules/system.go b/dot/rpc/modules/system.go index a0eee1285c..1a647c2c59 100644 --- a/dot/rpc/modules/system.go +++ b/dot/rpc/modules/system.go @@ -28,7 +28,7 @@ const NOT_IMPLEMENTED = "not yet implemented" // SystemModule is an RPC module providing access to core API points type SystemModule struct { networkAPI NetworkAPI - rpcAPI RPCAPI + systemAPI SystemAPI } // EmptyRequest represents an RPC request with no fields @@ -60,22 +60,22 @@ type SystemPropertiesResponse struct { } // NewSystemModule creates a new API instance -func NewSystemModule(net NetworkAPI, rpc RPCAPI) *SystemModule { +func NewSystemModule(net NetworkAPI, sys SystemAPI) *SystemModule { return &SystemModule{ networkAPI: net, // TODO: migrate to network state - rpcAPI: rpc, + systemAPI: sys, } } // Chain returns the runtime chain func (sm *SystemModule) Chain(r *http.Request, req *EmptyRequest, res *string) error { - *res = sm.rpcAPI.NodeName() + *res = sm.systemAPI.NodeName() return nil } // Name returns the runtime name func (sm *SystemModule) Name(r *http.Request, req *EmptyRequest, res *string) error { - *res = sm.rpcAPI.SystemName() + *res = sm.systemAPI.SystemName() return nil } @@ -93,7 +93,7 @@ func (sm *SystemModule) Properties(r *http.Request, req *EmptyRequest, res *Syst // Version returns the runtime version func (sm *SystemModule) Version(r *http.Request, req *EmptyRequest, res *string) error { - *res = sm.rpcAPI.SystemVersion() + *res = sm.systemAPI.SystemVersion() return nil } diff --git a/dot/rpc/modules/system_test.go b/dot/rpc/modules/system_test.go index 399ceeeb3a..86f3ee1741 100644 --- a/dot/rpc/modules/system_test.go +++ b/dot/rpc/modules/system_test.go @@ -17,9 +17,6 @@ package modules import ( - "fmt" - "github.com/ChainSafe/gossamer/dot/rpc" - "github.com/ChainSafe/gossamer/dot/types" "math/big" "os" "path" @@ -99,14 +96,3 @@ func TestSystemModule_Peers(t *testing.T) { t.Errorf("System.Peers: expected: %+v got: %+v\n", testPeers, res.Peers) } } - -func TestSystemModule_Name(t *testing.T) { - sysCfg := &types.SystemInfo{ - SystemName: "fooBar", - } - rpcService := rpc.NewService(sysCfg) - sys := NewSystemModule(nil, rpcService) - var res string - sys.Chain(nil, nil, &res) - fmt.Printf("SystemName %v\n", res) -} diff --git a/dot/rpc/service.go b/dot/rpc/service.go index 24a9400754..b1e179b666 100644 --- a/dot/rpc/service.go +++ b/dot/rpc/service.go @@ -16,7 +16,6 @@ package rpc import ( - "github.com/ChainSafe/gossamer/dot/types" "net/http" "reflect" "strings" @@ -27,15 +26,12 @@ import ( // Service struct to hold rpc service data type Service struct { rpcMethods []string // list of method names offered by rpc - systemInfo *types.SystemInfo } - // NewService create a new instance of Service -func NewService(si *types.SystemInfo) *Service { +func NewService() *Service { return &Service{ rpcMethods: []string{}, - systemInfo: si, } } @@ -44,24 +40,6 @@ func (s *Service) Methods() []string { return s.rpcMethods } -// SystemName returns the app name -func (s *Service) SystemName() string { - //return s.systemInfo.SystemName - return "" -} - -// SystemVersion returns the app version -func (s *Service) SystemVersion() string { - //return s.systemInfo.SystemVersion - return "" -} - -// NodeName returns the nodeName (chain name) -func (s *Service) NodeName() string { - //return s.systemInfo.NodeName - return "" -} - var ( // Precompute the reflect.Type of error and http.Request typeOfError = reflect.TypeOf((*error)(nil)).Elem() diff --git a/dot/rpc/service_test.go b/dot/rpc/service_test.go index 7d035ff4bb..987a755717 100644 --- a/dot/rpc/service_test.go +++ b/dot/rpc/service_test.go @@ -20,17 +20,10 @@ import ( "github.com/ChainSafe/gossamer/dot/rpc/modules" "github.com/stretchr/testify/require" - "github.com/urfave/cli" ) func TestNewService(t *testing.T) { - ctx := &cli.Context{ - App: &cli.App{ - Name: "gossamer", - Version: "0.0.1", - }, - } - NewService(ctx, "gssmr") + NewService() } func TestService_Methods(t *testing.T) { @@ -38,13 +31,7 @@ func TestService_Methods(t *testing.T) { qtyRPCMethods := 1 qtyAuthorMethods := 6 - ctx := &cli.Context{ - App: &cli.App{ - Name: "gossamer", - Version: "0.0.1", - }, - } - rpcService := NewService(ctx, "gssmr") + rpcService := NewService() sysMod := modules.NewSystemModule(nil, nil) rpcService.BuildMethodNames(sysMod, "system") m := rpcService.Methods() @@ -60,42 +47,3 @@ func TestService_Methods(t *testing.T) { m = rpcService.Methods() require.Equal(t, qtySystemMethods+qtyRPCMethods+qtyAuthorMethods, len(m)) } - -func TestService_NodeName(t *testing.T) { - ctx := &cli.Context{ - App: &cli.App{ - Name: "gossamer", - Version: "0.0.1", - }, - } - rpcService := NewService(ctx, "gssmr") - - name := rpcService.NodeName() - require.Equal(t, "gssmr", name) -} - -func TestService_SystemName(t *testing.T) { - ctx := &cli.Context{ - App: &cli.App{ - Name: "gossamer", - Version: "0.0.1", - }, - } - rpcService := NewService(ctx, "gssmr") - - name := rpcService.SystemName() - require.Equal(t, "gossamer", name) -} - -func TestService_SystemVersion(t *testing.T) { - ctx := &cli.Context{ - App: &cli.App{ - Name: "gossamer", - Version: "0.0.1", - }, - } - rpcService := NewService(ctx, "gssmr") - - ver := rpcService.SystemVersion() - require.Equal(t, "0.0.1", ver) -} diff --git a/dot/rpc/websocket_test.go b/dot/rpc/websocket_test.go index 756493b99b..b0ae6e17b4 100644 --- a/dot/rpc/websocket_test.go +++ b/dot/rpc/websocket_test.go @@ -8,6 +8,8 @@ import ( "time" "github.com/ChainSafe/gossamer/dot/core" + "github.com/ChainSafe/gossamer/dot/system" + "github.com/ChainSafe/gossamer/dot/types" "github.com/gorilla/websocket" "github.com/stretchr/testify/require" ) @@ -24,20 +26,19 @@ var testCalls = []struct { } func TestNewWebSocketServer(t *testing.T) { - //ctx := &cli.Context{ - // App: &cli.App{ - // Name: "gossamer", - // Version: "0.0.1", - // }, - //} coreAPI := core.NewTestService(t, nil) + si := &types.SystemInfo{ + SystemName: "gossamer", + } + sysAPI := system.NewService(si) cfg := &HTTPServerConfig{ Modules: []string{"system", "chain"}, RPCPort: 8545, WSPort: 8546, WSEnabled: true, - RPCAPI: NewService(nil), + RPCAPI: NewService(), CoreAPI: coreAPI, + SystemAPI: sysAPI, } s := NewHTTPServer(cfg) diff --git a/dot/services.go b/dot/services.go index 62c5b4e891..b8a83ec399 100644 --- a/dot/services.go +++ b/dot/services.go @@ -24,6 +24,7 @@ import ( "github.com/ChainSafe/gossamer/dot/network" "github.com/ChainSafe/gossamer/dot/rpc" "github.com/ChainSafe/gossamer/dot/state" + "github.com/ChainSafe/gossamer/dot/system" "github.com/ChainSafe/gossamer/lib/keystore" "github.com/ChainSafe/gossamer/lib/runtime" log "github.com/ChainSafe/log15" @@ -152,8 +153,8 @@ func createRPCService(cfg *Config, stateSrvc *state.Service, coreSrvc *core.Serv "mods", cfg.RPC.Modules, "ws port", cfg.RPC.WSPort, ) - rpcService := rpc.NewService(nil) - + rpcService := rpc.NewService() + systemService := system.NewService(&cfg.System) rpcConfig := &rpc.HTTPServerConfig{ BlockAPI: stateSrvc.Block, StorageAPI: stateSrvc.Storage, @@ -162,6 +163,7 @@ func createRPCService(cfg *Config, stateSrvc *state.Service, coreSrvc *core.Serv RuntimeAPI: rt, TransactionQueueAPI: stateSrvc.TransactionQueue, RPCAPI: rpcService, + SystemAPI: systemService, Host: cfg.RPC.Host, RPCPort: cfg.RPC.Port, WSEnabled: cfg.RPC.WSEnabled, diff --git a/dot/services_test.go b/dot/services_test.go index 9e6579ad17..9dab93f35a 100644 --- a/dot/services_test.go +++ b/dot/services_test.go @@ -23,8 +23,6 @@ import ( "github.com/ChainSafe/gossamer/dot/network" "github.com/ChainSafe/gossamer/lib/keystore" "github.com/ChainSafe/gossamer/lib/utils" - "github.com/urfave/cli" - "github.com/stretchr/testify/require" ) @@ -151,14 +149,7 @@ func TestCreateRPCService(t *testing.T) { networkSrvc := &network.Service{} // TODO: rpc service without network service - ctx := &cli.Context{ - App: &cli.App{ - Name: "gossamer", - Version: "0.0.1", - }, - } - - rpcSrvc := createRPCService(cfg, stateSrvc, coreSrvc, networkSrvc, rt, ctx) + rpcSrvc := createRPCService(cfg, stateSrvc, coreSrvc, networkSrvc, rt) require.Nil(t, err) // TODO: improve dot tests #687 diff --git a/dot/system/service.go b/dot/system/service.go new file mode 100644 index 0000000000..856cdbb978 --- /dev/null +++ b/dot/system/service.go @@ -0,0 +1,46 @@ +// Copyright 2020 ChainSafe Systems (ON) Corp. +// This file is part of gossamer. +// +// The gossamer library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The gossamer library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the gossamer library. If not, see . + +package system + +import "github.com/ChainSafe/gossamer/dot/types" + +// Service struct to hold rpc service data +type Service struct { + systemInfo *types.SystemInfo +} + +// NewService create a new instance of Service +func NewService(si *types.SystemInfo) *Service { + return &Service{ + systemInfo: si, + } +} + +// SystemName returns the app name +func (s *Service) SystemName() string { + return s.systemInfo.SystemName +} + +// SystemVersion returns the app version +func (s *Service) SystemVersion() string { + return s.systemInfo.SystemVersion +} + +// NodeName returns the nodeName (chain name) +func (s *Service) NodeName() string { + return s.systemInfo.NodeName +} diff --git a/dot/system/service_test.go b/dot/system/service_test.go new file mode 100644 index 0000000000..7fe5e020b3 --- /dev/null +++ b/dot/system/service_test.go @@ -0,0 +1,53 @@ +// Copyright 2020 ChainSafe Systems (ON) Corp. +// This file is part of gossamer. +// +// The gossamer library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The gossamer library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the gossamer library. If not, see . + +package system + +import ( + "testing" + + "github.com/ChainSafe/gossamer/dot/types" + "github.com/stretchr/testify/require" +) + +func TestService_NodeName(t *testing.T) { + svc := newTestService() + + name := svc.NodeName() + require.Equal(t, "gssmr", name) +} + +func TestService_SystemName(t *testing.T) { + svc := newTestService() + + name := svc.SystemName() + require.Equal(t, "gossamer", name) +} + +func TestService_SystemVersion(t *testing.T) { + svc := newTestService() + ver := svc.SystemVersion() + require.Equal(t, "0.0.1", ver) +} + +func newTestService() *Service { + sysInfo := &types.SystemInfo{ + SystemName: "gossamer", + SystemVersion: "0.0.1", + NodeName: "gssmr", + } + return NewService(sysInfo) +} diff --git a/dot/types/system.go b/dot/types/system.go index cb7661f111..160ff8ded4 100644 --- a/dot/types/system.go +++ b/dot/types/system.go @@ -1,9 +1,10 @@ package types +// SystemInfo struct to hold system related information type SystemInfo struct { - SystemName string - SystemVersion string - NodeName string + SystemName string + SystemVersion string + NodeName string SystemProperties systemProperties } diff --git a/node/gssmr/config.toml b/node/gssmr/config.toml index dcc8072270..256375f6fe 100644 --- a/node/gssmr/config.toml +++ b/node/gssmr/config.toml @@ -27,3 +27,4 @@ port = 8545 host = "localhost" modules = ["system", "author", "chain", "state"] ws-port = 8546 +ws-enabled = false diff --git a/node/ksmcc/config.toml b/node/ksmcc/config.toml index eab0aa9261..81914644ff 100644 --- a/node/ksmcc/config.toml +++ b/node/ksmcc/config.toml @@ -27,3 +27,4 @@ port = 8545 host = "localhost" modules = ["system"] ws-port = 8546 +ws-enabled = false From 0a2d663e0f18e52ee7392c9d5cebdce4cc230965 Mon Sep 17 00:00:00 2001 From: Edward Mack Date: Mon, 18 May 2020 18:40:44 -0400 Subject: [PATCH 6/7] treat system_properties response as map instead of go struct so that it can be build dynamically later based on genesis definition. --- cmd/gossamer/config.go | 18 +++++++++++------- cmd/gossamer/config_test.go | 5 ++++- dot/config.go | 18 ++++-------------- dot/rpc/modules/api.go | 1 + dot/rpc/modules/system.go | 20 ++------------------ dot/system/service.go | 5 +++++ dot/system/service_test.go | 23 ++++++++++++++++++++--- dot/types/system.go | 8 +------- dot/utils.go | 1 + 9 files changed, 49 insertions(+), 50 deletions(-) diff --git a/cmd/gossamer/config.go b/cmd/gossamer/config.go index 1d2110b7ea..c3ca725f8c 100644 --- a/cmd/gossamer/config.go +++ b/cmd/gossamer/config.go @@ -24,7 +24,6 @@ import ( database "github.com/ChainSafe/chaindb" "github.com/ChainSafe/gossamer/dot" "github.com/ChainSafe/gossamer/dot/state" - "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/genesis" log "github.com/ChainSafe/log15" @@ -96,7 +95,7 @@ func createDotConfig(ctx *cli.Context) (cfg *dot.Config, err error) { setDotRPCConfig(ctx, &cfg.RPC) // set system info - setSystemInfoConfig(ctx, &cfg.System) + setSystemInfoConfig(ctx, cfg) return cfg, nil } @@ -116,7 +115,7 @@ func createInitConfig(ctx *cli.Context) (cfg *dot.Config, err error) { setDotInitConfig(ctx, &cfg.Init) // set system info - setSystemInfoConfig(ctx, &cfg.System) + setSystemInfoConfig(ctx, cfg) // ensure configuration values match genesis and overwrite with genesis updateDotConfigFromGenesisJSON(ctx, cfg) @@ -144,7 +143,7 @@ func createExportConfig(ctx *cli.Context) (cfg *dot.Config) { setDotRPCConfig(ctx, &cfg.RPC) // set system info - setSystemInfoConfig(ctx, &cfg.System) + setSystemInfoConfig(ctx, cfg) return cfg } @@ -341,12 +340,17 @@ func setDotRPCConfig(ctx *cli.Context, cfg *dot.RPCConfig) { ) } -func setSystemInfoConfig(ctx *cli.Context, cfg *types.SystemInfo) { +func setSystemInfoConfig(ctx *cli.Context, cfg *dot.Config) { // load system information if ctx.App != nil { - cfg.SystemName = ctx.App.Name - cfg.SystemVersion = ctx.App.Version + cfg.System.SystemName = ctx.App.Name + cfg.System.SystemVersion = ctx.App.Version } + + // TODO lookup system properties from genesis file and set here (See issue #865) + cfg.System.NodeName = cfg.Global.Name + props := make(map[string]interface{}) + cfg.System.SystemProperties = props } // updateDotConfigFromGenesisJSON updates the configuration based on the genesis file values diff --git a/cmd/gossamer/config_test.go b/cmd/gossamer/config_test.go index d7a030098f..68ed491caa 100644 --- a/cmd/gossamer/config_test.go +++ b/cmd/gossamer/config_test.go @@ -545,6 +545,7 @@ func TestUpdateConfigFromGenesisJSON(t *testing.T) { Core: testCfg.Core, Network: testCfg.Network, RPC: testCfg.RPC, + System: testCfg.System, } cfg, err := createDotConfig(ctx) @@ -585,6 +586,7 @@ func TestUpdateConfigFromGenesisJSON_Default(t *testing.T) { Core: testCfg.Core, Network: testCfg.Network, RPC: testCfg.RPC, + System: testCfg.System, } cfg, err := createDotConfig(ctx) @@ -626,7 +628,8 @@ func TestUpdateConfigFromGenesisData(t *testing.T) { NoBootstrap: testCfg.Network.NoBootstrap, NoMDNS: testCfg.Network.NoMDNS, }, - RPC: testCfg.RPC, + RPC: testCfg.RPC, + System: testCfg.System, } cfg, err := createDotConfig(ctx) diff --git a/dot/config.go b/dot/config.go index 2e5fc752e1..2e5fc4e53f 100644 --- a/dot/config.go +++ b/dot/config.go @@ -134,13 +134,8 @@ func GssmrConfig() *Config { WSPort: gssmr.DefaultRPCWSPort, }, System: types.SystemInfo{ - // TODO determine how to get these values from genesis.json - //nodeName: gssmr.DefaultName, - //systemProperties: systemProperties{ - // Ss58Format: 0, - // TokenDecimals: 0, - // TokenSymbol: "", - //}, + NodeName: gssmr.DefaultName, + SystemProperties: make(map[string]interface{}), }, } } @@ -178,13 +173,8 @@ func KsmccConfig() *Config { WSPort: ksmcc.DefaultRPCWSPort, }, System: types.SystemInfo{ - // TODO determine how to get these values from genesis.json - //nodeName: ksmcc.DefaultName, - //systemProperties: systemProperties{ - // Ss58Format: 0, - // TokenDecimals: 0, - // TokenSymbol: "", - //}, + NodeName: ksmcc.DefaultName, + SystemProperties: make(map[string]interface{}), }, } } diff --git a/dot/rpc/modules/api.go b/dot/rpc/modules/api.go index f033bf7d77..fb116453bb 100644 --- a/dot/rpc/modules/api.go +++ b/dot/rpc/modules/api.go @@ -65,4 +65,5 @@ type SystemAPI interface { SystemName() string SystemVersion() string NodeName() string + Properties() map[string]interface{} } diff --git a/dot/rpc/modules/system.go b/dot/rpc/modules/system.go index 1a647c2c59..db1415ef89 100644 --- a/dot/rpc/modules/system.go +++ b/dot/rpc/modules/system.go @@ -22,9 +22,6 @@ import ( "github.com/ChainSafe/gossamer/lib/common" ) -// NOT_IMPLEMENTED used as placeholder for not implemented yet funcs -const NOT_IMPLEMENTED = "not yet implemented" - // SystemModule is an RPC module providing access to core API points type SystemModule struct { networkAPI NetworkAPI @@ -52,13 +49,6 @@ type SystemPeersResponse struct { Peers []common.PeerInfo `json:"peers"` } -//SystemPropertiesResponse struct to marshal json -type SystemPropertiesResponse struct { - Ss58Format int `json:"ss58Format"` - TokenDecimals int `json:"tokenDecimals"` - TokenSymbol string `json:"tokenSymbol"` -} - // NewSystemModule creates a new API instance func NewSystemModule(net NetworkAPI, sys SystemAPI) *SystemModule { return &SystemModule{ @@ -80,14 +70,8 @@ func (sm *SystemModule) Name(r *http.Request, req *EmptyRequest, res *string) er } // Properties returns the runtime properties -func (sm *SystemModule) Properties(r *http.Request, req *EmptyRequest, res *SystemPropertiesResponse) error { - // TODO implement lookup of this value - sp := SystemPropertiesResponse{ - Ss58Format: 2, - TokenDecimals: 12, - TokenSymbol: "KSM", - } - *res = sp +func (sm *SystemModule) Properties(r *http.Request, req *EmptyRequest, res *interface{}) error { + *res = sm.systemAPI.Properties() return nil } diff --git a/dot/system/service.go b/dot/system/service.go index 856cdbb978..31e794264e 100644 --- a/dot/system/service.go +++ b/dot/system/service.go @@ -44,3 +44,8 @@ func (s *Service) SystemVersion() string { func (s *Service) NodeName() string { return s.systemInfo.NodeName } + +// Properties Get a custom set of properties as a JSON object, defined in the chain spec. +func (s *Service) Properties() map[string]interface{} { + return s.systemInfo.SystemProperties +} diff --git a/dot/system/service_test.go b/dot/system/service_test.go index 7fe5e020b3..bfe9f35be6 100644 --- a/dot/system/service_test.go +++ b/dot/system/service_test.go @@ -43,11 +43,28 @@ func TestService_SystemVersion(t *testing.T) { require.Equal(t, "0.0.1", ver) } +func TestService_Properties(t *testing.T) { + expected := make(map[string]interface{}) + expected["ss58Format"] = 2 + expected["tokenDecimals"] = 12 + expected["tokenSymbol"] = "KSM" + + svc := newTestService() + props := svc.Properties() + require.Equal(t, expected, props) +} + func newTestService() *Service { + sysProps := make(map[string]interface{}) + sysProps["ss58Format"] = 2 + sysProps["tokenDecimals"] = 12 + sysProps["tokenSymbol"] = "KSM" + sysInfo := &types.SystemInfo{ - SystemName: "gossamer", - SystemVersion: "0.0.1", - NodeName: "gssmr", + SystemName: "gossamer", + SystemVersion: "0.0.1", + NodeName: "gssmr", + SystemProperties: sysProps, } return NewService(sysInfo) } diff --git a/dot/types/system.go b/dot/types/system.go index 160ff8ded4..c71b4d00f8 100644 --- a/dot/types/system.go +++ b/dot/types/system.go @@ -5,11 +5,5 @@ type SystemInfo struct { SystemName string SystemVersion string NodeName string - SystemProperties systemProperties -} - -type systemProperties struct { - Ss58Format int - TokenDecimals int - TokenSymbol string + SystemProperties map[string]interface{} } diff --git a/dot/utils.go b/dot/utils.go index d83bc4edee..11c456dd5f 100644 --- a/dot/utils.go +++ b/dot/utils.go @@ -47,6 +47,7 @@ func NewTestConfig(t *testing.T) *Config { Core: GssmrConfig().Core, Network: GssmrConfig().Network, RPC: GssmrConfig().RPC, + System: GssmrConfig().System, } } From 94353494ec3af3f2042c9e70b447349caae6ed04 Mon Sep 17 00:00:00 2001 From: Edward Mack Date: Wed, 20 May 2020 14:35:14 -0400 Subject: [PATCH 7/7] make system service implement Service interface --- dot/node.go | 8 +++++++- dot/services.go | 12 +++++++++--- dot/services_test.go | 4 +++- dot/system/service.go | 10 ++++++++++ dot/system/service_test.go | 12 ++++++++++++ 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/dot/node.go b/dot/node.go index 2b21427a8b..b75b83aeb4 100644 --- a/dot/node.go +++ b/dot/node.go @@ -235,13 +235,19 @@ func NewNode(cfg *Config, ks *keystore.Keystore) (*Node, error) { } + // System Service + + // create system service and append to node services + sysSrvc := createSystemService(&cfg.System) + nodeSrvcs = append(nodeSrvcs, sysSrvc) + // RPC Service // check if rpc service is enabled if enabled := RPCServiceEnabled(cfg); enabled { // create rpc service and append rpc service to node services - rpcSrvc := createRPCService(cfg, stateSrvc, coreSrvc, networkSrvc, rt) + rpcSrvc := createRPCService(cfg, stateSrvc, coreSrvc, networkSrvc, rt, sysSrvc) nodeSrvcs = append(nodeSrvcs, rpcSrvc) } else { diff --git a/dot/services.go b/dot/services.go index b8a83ec399..d062dd3abf 100644 --- a/dot/services.go +++ b/dot/services.go @@ -25,6 +25,7 @@ import ( "github.com/ChainSafe/gossamer/dot/rpc" "github.com/ChainSafe/gossamer/dot/state" "github.com/ChainSafe/gossamer/dot/system" + "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/lib/keystore" "github.com/ChainSafe/gossamer/lib/runtime" log "github.com/ChainSafe/log15" @@ -145,7 +146,7 @@ func createNetworkService(cfg *Config, stateSrvc *state.Service, coreMsgs chan n // RPC Service // createRPCService creates the RPC service from the provided core configuration -func createRPCService(cfg *Config, stateSrvc *state.Service, coreSrvc *core.Service, networkSrvc *network.Service, rt *runtime.Runtime) *rpc.HTTPServer { +func createRPCService(cfg *Config, stateSrvc *state.Service, coreSrvc *core.Service, networkSrvc *network.Service, rt *runtime.Runtime, sysSrvc *system.Service) *rpc.HTTPServer { log.Info( "[dot] creating rpc service...", "host", cfg.RPC.Host, @@ -154,7 +155,6 @@ func createRPCService(cfg *Config, stateSrvc *state.Service, coreSrvc *core.Serv "ws port", cfg.RPC.WSPort, ) rpcService := rpc.NewService() - systemService := system.NewService(&cfg.System) rpcConfig := &rpc.HTTPServerConfig{ BlockAPI: stateSrvc.Block, StorageAPI: stateSrvc.Storage, @@ -163,7 +163,7 @@ func createRPCService(cfg *Config, stateSrvc *state.Service, coreSrvc *core.Serv RuntimeAPI: rt, TransactionQueueAPI: stateSrvc.TransactionQueue, RPCAPI: rpcService, - SystemAPI: systemService, + SystemAPI: sysSrvc, Host: cfg.RPC.Host, RPCPort: cfg.RPC.Port, WSEnabled: cfg.RPC.WSEnabled, @@ -173,3 +173,9 @@ func createRPCService(cfg *Config, stateSrvc *state.Service, coreSrvc *core.Serv return rpc.NewHTTPServer(rpcConfig) } + +// System service +// creates a service for providing system related information +func createSystemService(cfg *types.SystemInfo) *system.Service { + return system.NewService(cfg) +} diff --git a/dot/services_test.go b/dot/services_test.go index 9dab93f35a..27f04d18ba 100644 --- a/dot/services_test.go +++ b/dot/services_test.go @@ -149,7 +149,9 @@ func TestCreateRPCService(t *testing.T) { networkSrvc := &network.Service{} // TODO: rpc service without network service - rpcSrvc := createRPCService(cfg, stateSrvc, coreSrvc, networkSrvc, rt) + sysSrvc := createSystemService(&cfg.System) + + rpcSrvc := createRPCService(cfg, stateSrvc, coreSrvc, networkSrvc, rt, sysSrvc) require.Nil(t, err) // TODO: improve dot tests #687 diff --git a/dot/system/service.go b/dot/system/service.go index 31e794264e..c192678da2 100644 --- a/dot/system/service.go +++ b/dot/system/service.go @@ -49,3 +49,13 @@ func (s *Service) NodeName() string { func (s *Service) Properties() map[string]interface{} { return s.systemInfo.SystemProperties } + +// Start implements Service interface +func (s *Service) Start() error { + return nil +} + +// Stop implements Service interface +func (s *Service) Stop() error { + return nil +} diff --git a/dot/system/service_test.go b/dot/system/service_test.go index bfe9f35be6..3f1b78b487 100644 --- a/dot/system/service_test.go +++ b/dot/system/service_test.go @@ -54,6 +54,18 @@ func TestService_Properties(t *testing.T) { require.Equal(t, expected, props) } +func TestService_Start(t *testing.T) { + svc := newTestService() + err := svc.Start() + require.NoError(t, err) +} + +func TestService_Stop(t *testing.T) { + svc := newTestService() + err := svc.Stop() + require.NoError(t, err) +} + func newTestService() *Service { sysProps := make(map[string]interface{}) sysProps["ss58Format"] = 2