Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dot/rpc: Implement RPC system_name, system_version, system_chain #849

Merged
merged 9 commits into from
May 20, 2020
25 changes: 23 additions & 2 deletions cmd/gossamer/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@ import (
"strconv"
"strings"

database "github.com/ChainSafe/chaindb"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was this intentionally moved?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, maybe my IDE did it when I did goimports? not sure.

"github.com/ChainSafe/gossamer/dot"
"github.com/ChainSafe/gossamer/dot/state"
"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"
)
Expand Down Expand Up @@ -95,6 +94,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)

return cfg, nil
}

Expand All @@ -112,6 +114,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)

// ensure configuration values match genesis and overwrite with genesis
updateDotConfigFromGenesisJSON(ctx, cfg)

Expand All @@ -137,6 +142,9 @@ func createExportConfig(ctx *cli.Context) (cfg *dot.Config) {
setDotNetworkConfig(ctx, &cfg.Network)
setDotRPCConfig(ctx, &cfg.RPC)

// set system info
setSystemInfoConfig(ctx, cfg)

return cfg
}

Expand Down Expand Up @@ -332,6 +340,19 @@ func setDotRPCConfig(ctx *cli.Context, cfg *dot.RPCConfig) {
)
}

func setSystemInfoConfig(ctx *cli.Context, cfg *dot.Config) {
// load system information
if ctx.App != nil {
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
func updateDotConfigFromGenesisJSON(ctx *cli.Context, cfg *dot.Config) {

Expand Down
5 changes: 4 additions & 1 deletion cmd/gossamer/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
23 changes: 16 additions & 7 deletions dot/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,22 @@ import (
"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"`
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:"-"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this exclude it from the config file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

}

// GlobalConfig is to marshal/unmarshal toml global config vars
Expand Down Expand Up @@ -132,6 +133,10 @@ func GssmrConfig() *Config {
Modules: gssmr.DefaultRPCModules,
WSPort: gssmr.DefaultRPCWSPort,
},
System: types.SystemInfo{
NodeName: gssmr.DefaultName,
SystemProperties: make(map[string]interface{}),
},
}
}

Expand Down Expand Up @@ -167,6 +172,10 @@ func KsmccConfig() *Config {
Modules: ksmcc.DefaultRPCModules,
WSPort: ksmcc.DefaultRPCWSPort,
},
System: types.SystemInfo{
NodeName: ksmcc.DefaultName,
SystemProperties: make(map[string]interface{}),
},
}
}

Expand Down
8 changes: 7 additions & 1 deletion dot/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


// 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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

nodeSrvcs = append(nodeSrvcs, rpcSrvc)

} else {
Expand Down
3 changes: 2 additions & 1 deletion dot/rpc/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -81,7 +82,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.SystemAPI)
case "author":
srvc = modules.NewAuthorModule(h.serverConfig.CoreAPI, h.serverConfig.RuntimeAPI, h.serverConfig.TransactionQueueAPI)
case "chain":
Expand Down
15 changes: 11 additions & 4 deletions dot/rpc/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +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"
)

func TestNewHTTPServer(t *testing.T) {
coreAPI := core.NewTestService(t, nil)
si := &types.SystemInfo{
SystemName: "gossamer",
}
sysAPI := system.NewService(si)
cfg := &HTTPServerConfig{
Modules: []string{"system"},
RPCPort: 8545,
RPCAPI: NewService(),
CoreAPI: coreAPI,
Modules: []string{"system"},
RPCPort: 8545,
RPCAPI: NewService(),
CoreAPI: coreAPI,
SystemAPI: sysAPI,
}

s := NewHTTPServer(cfg)
Expand Down
8 changes: 8 additions & 0 deletions dot/rpc/modules/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,11 @@ type RPCAPI interface {
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
Properties() map[string]interface{}
}
39 changes: 11 additions & 28 deletions dot/rpc/modules/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,10 @@ 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
systemAPI SystemAPI
}

// EmptyRequest represents an RPC request with no fields
Expand All @@ -51,50 +49,35 @@ 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) *SystemModule {
func NewSystemModule(net NetworkAPI, sys SystemAPI) *SystemModule {
return &SystemModule{
networkAPI: net, // TODO: migrate to network state
systemAPI: sys,
}
}

// Chain returns the runtime chain
func (sm *SystemModule) Chain(r *http.Request, req *EmptyRequest, res *StringResponse) error {
// TODO implement lookup of value
*res = "Development"
func (sm *SystemModule) Chain(r *http.Request, req *EmptyRequest, res *string) error {
*res = sm.systemAPI.NodeName()
return nil
}

// Name returns the runtime name
func (sm *SystemModule) Name(r *http.Request, req *EmptyRequest, res *StringResponse) error {
// TODO implement lookup of value
*res = "gossamer v0.0"
func (sm *SystemModule) Name(r *http.Request, req *EmptyRequest, res *string) error {
*res = sm.systemAPI.SystemName()
return nil
}

// 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
}

// Version returns the runtime version
func (sm *SystemModule) Version(r *http.Request, req *EmptyRequest, res *StringResponse) error {
// TODO implement lookup of this
*res = "0.0.0"
func (sm *SystemModule) Version(r *http.Request, req *EmptyRequest, res *string) error {
*res = sm.systemAPI.SystemVersion()
return nil
}

Expand Down
6 changes: 3 additions & 3 deletions dot/rpc/modules/system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down
4 changes: 3 additions & 1 deletion dot/rpc/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ type Service struct {

// NewService create a new instance of Service
func NewService() *Service {
return &Service{rpcMethods: []string{}}
return &Service{
rpcMethods: []string{},
}
}

// Methods returns list of methods available via RPC call
Expand Down
2 changes: 1 addition & 1 deletion dot/rpc/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func TestService_Methods(t *testing.T) {
qtyAuthorMethods := 6

rpcService := NewService()
sysMod := modules.NewSystemModule(nil)
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
Expand Down
9 changes: 8 additions & 1 deletion dot/rpc/websocket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand All @@ -17,21 +19,26 @@ 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(`{"jsonrpc":"2.0","error":{"code":-32600,"message":"Invalid request"},"id":null}` + "\n")}, // empty request
{[]byte(`{"jsonrpc":"2.0","method":"chain_subscribeNewHeads","params":[],"id":1}`), []byte(`{"jsonrpc":"2.0","result":1,"id":1}` + "\n")},
}

func TestNewWebSocketServer(t *testing.T) {
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(),
CoreAPI: coreAPI,
SystemAPI: sysAPI,
}

s := NewHTTPServer(cfg)
Expand Down
Loading