From 0561c14ed9a5ee050f18b61d0622cae46bf7c1ad Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Fri, 1 Oct 2021 21:06:07 +0530 Subject: [PATCH 1/9] Implement sync_state_genSyncSpec RPC call Fixes #1767 --- dot/rpc/http.go | 1 + dot/rpc/modules/api.go | 4 ++++ dot/rpc/modules/sync_state.go | 41 +++++++++++++++++++++++++++++++++++ dot/rpc/service.go | 2 +- dot/services.go | 1 + 5 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 dot/rpc/modules/sync_state.go diff --git a/dot/rpc/http.go b/dot/rpc/http.go index 76fa52b06d..ad2f918088 100644 --- a/dot/rpc/http.go +++ b/dot/rpc/http.go @@ -54,6 +54,7 @@ type HTTPServerConfig struct { TransactionQueueAPI modules.TransactionStateAPI RPCAPI modules.RPCAPI SystemAPI modules.SystemAPI + SyncStateAPI modules.SyncStateAPI NodeStorage *runtime.NodeStorage RPC bool RPCExternal bool diff --git a/dot/rpc/modules/api.go b/dot/rpc/modules/api.go index 8812b09969..fb46475b1b 100644 --- a/dot/rpc/modules/api.go +++ b/dot/rpc/modules/api.go @@ -119,3 +119,7 @@ type RuntimeStorageAPI interface { GetLocal(k []byte) ([]byte, error) GetPersistent(k []byte) ([]byte, error) } + +type SyncStateAPI interface { + GenSyncSpec(raw bool) ([]byte, error) +} diff --git a/dot/rpc/modules/sync_state.go b/dot/rpc/modules/sync_state.go new file mode 100644 index 0000000000..0a1db4c1c0 --- /dev/null +++ b/dot/rpc/modules/sync_state.go @@ -0,0 +1,41 @@ +// Copyright 2019 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 modules + +import ( + "io/ioutil" + "path/filepath" +) + +type SyncState struct { + GenesisFilePath string +} + +// GenSyncSpec returns the JSON serialized chain specification running the node +// (i.e. the current state), with a sync state. +func (s SyncState) GenSyncSpec(raw bool) ([]byte, error) { + fp, err := filepath.Abs(s.GenesisFilePath) + if err != nil { + return nil, err + } + data, err := ioutil.ReadFile(filepath.Clean(fp)) + if err != nil { + return nil, err + } + + return data, nil +} diff --git a/dot/rpc/service.go b/dot/rpc/service.go index 6d34ee7db2..f72f48469c 100644 --- a/dot/rpc/service.go +++ b/dot/rpc/service.go @@ -49,7 +49,7 @@ var ( ) // BuildMethodNames takes receiver interface and populates rpcMethods array with available -// method names +// method names func (s *Service) BuildMethodNames(rcvr interface{}, name string) { rcvrType := reflect.TypeOf(rcvr) for i := 0; i < rcvrType.NumMethod(); i++ { diff --git a/dot/services.go b/dot/services.go index c6e8bf5830..1beb1b870a 100644 --- a/dot/services.go +++ b/dot/services.go @@ -346,6 +346,7 @@ func createRPCService(cfg *Config, ns *runtime.NodeStorage, stateSrvc *state.Ser BlockFinalityAPI: finSrvc, TransactionQueueAPI: stateSrvc.Transaction, RPCAPI: rpcService, + SyncStateAPI: modules.SyncState{GenesisFilePath: cfg.Init.Genesis}, SystemAPI: sysSrvc, RPC: cfg.RPC.Enabled, RPCExternal: cfg.RPC.External, From bcfedd6580c806f601f76d1afd47a2206cbb7693 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Mon, 4 Oct 2021 20:49:40 +0530 Subject: [PATCH 2/9] Registered the module and added tests --- chain/dev/defaults.go | 2 +- chain/gssmr/config.toml | 2 +- chain/gssmr/defaults.go | 2 +- chain/kusama/config.toml | 2 +- chain/kusama/defaults.go | 2 +- chain/polkadot/config.toml | 2 +- chain/polkadot/defaults.go | 2 +- dot/rpc/http.go | 2 ++ dot/rpc/http_test.go | 4 ++-- dot/rpc/modules/sync_state.go | 19 +++++++++++++++++++ dot/rpc/modules/sync_state_test.go | 22 ++++++++++++++++++++++ tests/data/db/config.toml | 2 +- 12 files changed, 53 insertions(+), 10 deletions(-) create mode 100644 dot/rpc/modules/sync_state_test.go diff --git a/chain/dev/defaults.go b/chain/dev/defaults.go index b6db6ec7e9..40ab274cef 100644 --- a/chain/dev/defaults.go +++ b/chain/dev/defaults.go @@ -87,7 +87,7 @@ var ( // DefaultRPCHTTPPort rpc port DefaultRPCHTTPPort = uint32(8545) // DefaultRPCModules rpc modules - DefaultRPCModules = []string{"system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate"} + DefaultRPCModules = []string{"system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate", "syncstate"} // DefaultRPCWSPort rpc websocket port DefaultRPCWSPort = uint32(8546) // DefaultRPCEnabled enables the RPC server diff --git a/chain/gssmr/config.toml b/chain/gssmr/config.toml index 6419e8cec1..e2d1b3d180 100644 --- a/chain/gssmr/config.toml +++ b/chain/gssmr/config.toml @@ -35,5 +35,5 @@ discovery-interval = 10 enabled = false port = 8545 host = "localhost" -modules = ["system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate"] +modules = ["system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate", "syncstate"] ws-port = 8546 diff --git a/chain/gssmr/defaults.go b/chain/gssmr/defaults.go index 0cdc3d2d35..48e6ae7a43 100644 --- a/chain/gssmr/defaults.go +++ b/chain/gssmr/defaults.go @@ -92,7 +92,7 @@ var ( // DefaultRPCHTTPPort rpc port DefaultRPCHTTPPort = uint32(8545) // DefaultRPCModules rpc modules - DefaultRPCModules = []string{"system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate"} + DefaultRPCModules = []string{"system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate", "syncstate"} // DefaultRPCWSPort rpc websocket port DefaultRPCWSPort = uint32(8546) ) diff --git a/chain/kusama/config.toml b/chain/kusama/config.toml index dd3261fde6..e3f7df57ca 100644 --- a/chain/kusama/config.toml +++ b/chain/kusama/config.toml @@ -35,7 +35,7 @@ enabled = false external = false port = 8545 host = "localhost" -modules = ["system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate"] +modules = ["system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate", "syncstate"] ws-port = 8546 ws = false ws-external = false diff --git a/chain/kusama/defaults.go b/chain/kusama/defaults.go index 8902a46297..0c73ccaced 100644 --- a/chain/kusama/defaults.go +++ b/chain/kusama/defaults.go @@ -83,7 +83,7 @@ var ( // DefaultRPCHTTPPort rpc port DefaultRPCHTTPPort = uint32(8545) // DefaultRPCModules rpc modules - DefaultRPCModules = []string{"system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate"} + DefaultRPCModules = []string{"system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate", "syncstate"} // DefaultRPCWSPort rpc websocket port DefaultRPCWSPort = uint32(8546) ) diff --git a/chain/polkadot/config.toml b/chain/polkadot/config.toml index 98f3291e1b..71049fb265 100644 --- a/chain/polkadot/config.toml +++ b/chain/polkadot/config.toml @@ -34,5 +34,5 @@ nomdns = false enabled = false port = 8545 host = "localhost" -modules = ["system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate"] +modules = ["system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate", "syncstate"] ws-port = 8546 \ No newline at end of file diff --git a/chain/polkadot/defaults.go b/chain/polkadot/defaults.go index dbc0dd8e2b..95b98b74cf 100644 --- a/chain/polkadot/defaults.go +++ b/chain/polkadot/defaults.go @@ -84,7 +84,7 @@ var ( // DefaultRPCHTTPPort rpc port DefaultRPCHTTPPort = uint32(8545) // DefaultRPCModules rpc modules - DefaultRPCModules = []string{"system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate"} + DefaultRPCModules = []string{"system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate", "syncstate"} // DefaultRPCWSPort rpc websocket port DefaultRPCWSPort = uint32(8546) ) diff --git a/dot/rpc/http.go b/dot/rpc/http.go index ad2f918088..8c48976eae 100644 --- a/dot/rpc/http.go +++ b/dot/rpc/http.go @@ -130,6 +130,8 @@ func (h *HTTPServer) RegisterModules(mods []string) { srvc = modules.NewOffchainModule(h.serverConfig.NodeStorage) case "childstate": srvc = modules.NewChildStateModule(h.serverConfig.StorageAPI, h.serverConfig.BlockAPI) + case "syncstate": + srvc = modules.NewSyncStateModule(h.serverConfig.SyncStateAPI) default: h.logger.Warn("Unrecognised module", "module", mod) continue diff --git a/dot/rpc/http_test.go b/dot/rpc/http_test.go index b2dfb50b01..2fc7f0d11d 100644 --- a/dot/rpc/http_test.go +++ b/dot/rpc/http_test.go @@ -41,7 +41,7 @@ import ( func TestRegisterModules(t *testing.T) { rpcapiMocks := new(mocks.MockRPCAPI) - mods := []string{"system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate"} + mods := []string{"system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate", "syncstate"} for _, modName := range mods { rpcapiMocks.On("BuildMethodNames", mock.Anything, modName).Once() @@ -125,7 +125,7 @@ func TestNewHTTPServer(t *testing.T) { func TestUnsafeRPCProtection(t *testing.T) { cfg := &HTTPServerConfig{ - Modules: []string{"system", "author", "chain", "state", "rpc", "grandpa", "dev"}, + Modules: []string{"system", "author", "chain", "state", "rpc", "grandpa", "dev", "syncstate"}, RPCPort: 7878, RPCAPI: NewService(), RPCUnsafe: false, diff --git a/dot/rpc/modules/sync_state.go b/dot/rpc/modules/sync_state.go index 0a1db4c1c0..eea80f7bb4 100644 --- a/dot/rpc/modules/sync_state.go +++ b/dot/rpc/modules/sync_state.go @@ -18,9 +18,28 @@ package modules import ( "io/ioutil" + "net/http" "path/filepath" ) +type SyncStateModule struct { + SyncStateAPI SyncStateAPI +} + +func NewSyncStateModule(s SyncStateAPI) *SyncStateModule { + return &SyncStateModule{SyncStateAPI: s} +} + +func (ss *SyncStateModule) GenSyncSpec(_ *http.Request, req *bool, res *[]byte) error { + genesis, err := ss.SyncStateAPI.GenSyncSpec(*req) + if err != nil { + return err + } + + *res = genesis + return nil +} + type SyncState struct { GenesisFilePath string } diff --git a/dot/rpc/modules/sync_state_test.go b/dot/rpc/modules/sync_state_test.go new file mode 100644 index 0000000000..5a72989586 --- /dev/null +++ b/dot/rpc/modules/sync_state_test.go @@ -0,0 +1,22 @@ +package modules + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +const GssmrGenesisPath = "../../../chain/gssmr/genesis.json" + +func TestSyncStateModule(t *testing.T) { + module := NewSyncStateModule(SyncState{GenesisFilePath: GssmrGenesisPath}) + + req := true + var res []byte + + err := module.GenSyncSpec(nil, &req, &res) + require.NoError(t, err) + + fmt.Println(string(res)) +} diff --git a/tests/data/db/config.toml b/tests/data/db/config.toml index 7592d17e54..841fa35b2b 100644 --- a/tests/data/db/config.toml +++ b/tests/data/db/config.toml @@ -34,5 +34,5 @@ nomdns = false enabled = false port = 8545 host = "localhost" -modules = ["system", "author", "chain", "state", "rpc", "grandpa"] +modules = ["system", "author", "chain", "state", "rpc", "grandpa", "syncstate"] ws-port = 8546 From 085d5b038f7ba4d080c810c9d7a0442ed2f9713b Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Tue, 5 Oct 2021 19:52:59 +0530 Subject: [PATCH 3/9] Changed rpc out to Genesis format and added logic for raw and not raw option Fixes #1767 --- chain/dev/config.toml | 2 +- dot/rpc/http.go | 1 - dot/rpc/modules/api.go | 3 ++- dot/rpc/modules/sync_state.go | 30 +++++++++++++++++++++++++----- dot/rpc/modules/sync_state_test.go | 10 +++++----- 5 files changed, 33 insertions(+), 13 deletions(-) diff --git a/chain/dev/config.toml b/chain/dev/config.toml index f19fa63578..793b2c687c 100644 --- a/chain/dev/config.toml +++ b/chain/dev/config.toml @@ -35,5 +35,5 @@ enabled = true ws = true port = 8545 host = "localhost" -modules = ["system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate"] +modules = ["system", "author", "chain", "state", "rpc", "grandpa", "offchain", "childstate", "syncstate"] ws-port = 8546 diff --git a/dot/rpc/http.go b/dot/rpc/http.go index 8c48976eae..8182dd8bbf 100644 --- a/dot/rpc/http.go +++ b/dot/rpc/http.go @@ -138,7 +138,6 @@ func (h *HTTPServer) RegisterModules(mods []string) { } err := h.rpcServer.RegisterService(srvc, mod) - if err != nil { h.logger.Warn("Failed to register module", "mod", mod, "err", err) } diff --git a/dot/rpc/modules/api.go b/dot/rpc/modules/api.go index 254f4f271b..9fabd70e4f 100644 --- a/dot/rpc/modules/api.go +++ b/dot/rpc/modules/api.go @@ -9,6 +9,7 @@ import ( "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/crypto" "github.com/ChainSafe/gossamer/lib/crypto/ed25519" + "github.com/ChainSafe/gossamer/lib/genesis" "github.com/ChainSafe/gossamer/lib/grandpa" "github.com/ChainSafe/gossamer/lib/runtime" "github.com/ChainSafe/gossamer/lib/transaction" @@ -123,5 +124,5 @@ type RuntimeStorageAPI interface { } type SyncStateAPI interface { - GenSyncSpec(raw bool) ([]byte, error) + GenSyncSpec(raw bool) (*genesis.Genesis, error) } diff --git a/dot/rpc/modules/sync_state.go b/dot/rpc/modules/sync_state.go index eea80f7bb4..7858e39d65 100644 --- a/dot/rpc/modules/sync_state.go +++ b/dot/rpc/modules/sync_state.go @@ -17,26 +17,33 @@ package modules import ( + "encoding/json" "io/ioutil" "net/http" "path/filepath" + + "github.com/ChainSafe/gossamer/lib/genesis" ) type SyncStateModule struct { SyncStateAPI SyncStateAPI } +type BoolRequest struct { + Raw bool +} + func NewSyncStateModule(s SyncStateAPI) *SyncStateModule { return &SyncStateModule{SyncStateAPI: s} } -func (ss *SyncStateModule) GenSyncSpec(_ *http.Request, req *bool, res *[]byte) error { - genesis, err := ss.SyncStateAPI.GenSyncSpec(*req) +func (ss *SyncStateModule) GenSyncSpec(_ *http.Request, req *BoolRequest, res *genesis.Genesis) error { + genesis, err := ss.SyncStateAPI.GenSyncSpec(req.Raw) if err != nil { return err } - *res = genesis + *res = *genesis return nil } @@ -46,7 +53,7 @@ type SyncState struct { // GenSyncSpec returns the JSON serialized chain specification running the node // (i.e. the current state), with a sync state. -func (s SyncState) GenSyncSpec(raw bool) ([]byte, error) { +func (s SyncState) GenSyncSpec(raw bool) (*genesis.Genesis, error) { fp, err := filepath.Abs(s.GenesisFilePath) if err != nil { return nil, err @@ -56,5 +63,18 @@ func (s SyncState) GenSyncSpec(raw bool) ([]byte, error) { return nil, err } - return data, nil + g := new(genesis.Genesis) + err = json.Unmarshal(data, g) + if err != nil { + return nil, err + } + + if raw { + err = g.ToRaw() + if err != nil { + return nil, err + } + } + + return g, nil } diff --git a/dot/rpc/modules/sync_state_test.go b/dot/rpc/modules/sync_state_test.go index 5a72989586..5f8420d369 100644 --- a/dot/rpc/modules/sync_state_test.go +++ b/dot/rpc/modules/sync_state_test.go @@ -1,9 +1,9 @@ package modules import ( - "fmt" "testing" + "github.com/ChainSafe/gossamer/lib/genesis" "github.com/stretchr/testify/require" ) @@ -12,11 +12,11 @@ const GssmrGenesisPath = "../../../chain/gssmr/genesis.json" func TestSyncStateModule(t *testing.T) { module := NewSyncStateModule(SyncState{GenesisFilePath: GssmrGenesisPath}) - req := true - var res []byte + req := BoolRequest{ + Raw: true, + } + var res genesis.Genesis err := module.GenSyncSpec(nil, &req, &res) require.NoError(t, err) - - fmt.Println(string(res)) } From 0f9b52111e92354a855c3ab271a2c1a5d606ac10 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Wed, 6 Oct 2021 23:59:18 +0530 Subject: [PATCH 4/9] Removed SyncStateAPI interface and its implementation --- dot/rpc/http.go | 4 +-- dot/rpc/modules/api.go | 5 ---- dot/rpc/modules/sync_state.go | 45 ++++-------------------------- dot/rpc/modules/sync_state_test.go | 2 +- dot/services.go | 2 +- lib/genesis/genesis.go | 32 +++++++++++++++++++++ 6 files changed, 41 insertions(+), 49 deletions(-) diff --git a/dot/rpc/http.go b/dot/rpc/http.go index 8182dd8bbf..a70f4f4c76 100644 --- a/dot/rpc/http.go +++ b/dot/rpc/http.go @@ -54,7 +54,7 @@ type HTTPServerConfig struct { TransactionQueueAPI modules.TransactionStateAPI RPCAPI modules.RPCAPI SystemAPI modules.SystemAPI - SyncStateAPI modules.SyncStateAPI + GenesisFilePath string NodeStorage *runtime.NodeStorage RPC bool RPCExternal bool @@ -131,7 +131,7 @@ func (h *HTTPServer) RegisterModules(mods []string) { case "childstate": srvc = modules.NewChildStateModule(h.serverConfig.StorageAPI, h.serverConfig.BlockAPI) case "syncstate": - srvc = modules.NewSyncStateModule(h.serverConfig.SyncStateAPI) + srvc = modules.NewSyncStateModule(h.serverConfig.GenesisFilePath) default: h.logger.Warn("Unrecognised module", "module", mod) continue diff --git a/dot/rpc/modules/api.go b/dot/rpc/modules/api.go index 9fabd70e4f..d79d9e5583 100644 --- a/dot/rpc/modules/api.go +++ b/dot/rpc/modules/api.go @@ -9,7 +9,6 @@ import ( "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/crypto" "github.com/ChainSafe/gossamer/lib/crypto/ed25519" - "github.com/ChainSafe/gossamer/lib/genesis" "github.com/ChainSafe/gossamer/lib/grandpa" "github.com/ChainSafe/gossamer/lib/runtime" "github.com/ChainSafe/gossamer/lib/transaction" @@ -122,7 +121,3 @@ type RuntimeStorageAPI interface { GetLocal(k []byte) ([]byte, error) GetPersistent(k []byte) ([]byte, error) } - -type SyncStateAPI interface { - GenSyncSpec(raw bool) (*genesis.Genesis, error) -} diff --git a/dot/rpc/modules/sync_state.go b/dot/rpc/modules/sync_state.go index 7858e39d65..d86b2610e7 100644 --- a/dot/rpc/modules/sync_state.go +++ b/dot/rpc/modules/sync_state.go @@ -17,64 +17,29 @@ package modules import ( - "encoding/json" - "io/ioutil" "net/http" - "path/filepath" "github.com/ChainSafe/gossamer/lib/genesis" ) type SyncStateModule struct { - SyncStateAPI SyncStateAPI + GenesisFilePath string } type BoolRequest struct { Raw bool } -func NewSyncStateModule(s SyncStateAPI) *SyncStateModule { - return &SyncStateModule{SyncStateAPI: s} +func NewSyncStateModule(s string) *SyncStateModule { + return &SyncStateModule{GenesisFilePath: s} } func (ss *SyncStateModule) GenSyncSpec(_ *http.Request, req *BoolRequest, res *genesis.Genesis) error { - genesis, err := ss.SyncStateAPI.GenSyncSpec(req.Raw) + g, err := genesis.GenSyncSpec(req.Raw, ss.GenesisFilePath) if err != nil { return err } - *res = *genesis + *res = *g return nil } - -type SyncState struct { - GenesisFilePath string -} - -// GenSyncSpec returns the JSON serialized chain specification running the node -// (i.e. the current state), with a sync state. -func (s SyncState) GenSyncSpec(raw bool) (*genesis.Genesis, error) { - fp, err := filepath.Abs(s.GenesisFilePath) - if err != nil { - return nil, err - } - data, err := ioutil.ReadFile(filepath.Clean(fp)) - if err != nil { - return nil, err - } - - g := new(genesis.Genesis) - err = json.Unmarshal(data, g) - if err != nil { - return nil, err - } - - if raw { - err = g.ToRaw() - if err != nil { - return nil, err - } - } - - return g, nil -} diff --git a/dot/rpc/modules/sync_state_test.go b/dot/rpc/modules/sync_state_test.go index 5f8420d369..46e505c528 100644 --- a/dot/rpc/modules/sync_state_test.go +++ b/dot/rpc/modules/sync_state_test.go @@ -10,7 +10,7 @@ import ( const GssmrGenesisPath = "../../../chain/gssmr/genesis.json" func TestSyncStateModule(t *testing.T) { - module := NewSyncStateModule(SyncState{GenesisFilePath: GssmrGenesisPath}) + module := NewSyncStateModule(GssmrGenesisPath) req := BoolRequest{ Raw: true, diff --git a/dot/services.go b/dot/services.go index 1beb1b870a..aacbda466c 100644 --- a/dot/services.go +++ b/dot/services.go @@ -346,7 +346,7 @@ func createRPCService(cfg *Config, ns *runtime.NodeStorage, stateSrvc *state.Ser BlockFinalityAPI: finSrvc, TransactionQueueAPI: stateSrvc.Transaction, RPCAPI: rpcService, - SyncStateAPI: modules.SyncState{GenesisFilePath: cfg.Init.Genesis}, + GenesisFilePath: cfg.Init.Genesis, SystemAPI: sysSrvc, RPC: cfg.RPC.Enabled, RPCExternal: cfg.RPC.External, diff --git a/lib/genesis/genesis.go b/lib/genesis/genesis.go index 6eedd46d05..31156cd1cb 100644 --- a/lib/genesis/genesis.go +++ b/lib/genesis/genesis.go @@ -17,6 +17,10 @@ package genesis import ( + "encoding/json" + "io/ioutil" + "path/filepath" + "github.com/ChainSafe/gossamer/lib/common" ) @@ -107,6 +111,34 @@ func (g *Genesis) ToRaw() error { return nil } +// GenSyncSpec returns the JSON serialized chain specification running the node +// (i.e. the current state), with a sync state. +func GenSyncSpec(raw bool, GenesisFilePath string) (*Genesis, error) { + fp, err := filepath.Abs(GenesisFilePath) + if err != nil { + return nil, err + } + data, err := ioutil.ReadFile(filepath.Clean(fp)) + if err != nil { + return nil, err + } + + g := new(Genesis) + err = json.Unmarshal(data, g) + if err != nil { + return nil, err + } + + if raw { + err = g.ToRaw() + if err != nil { + return nil, err + } + } + + return g, nil +} + func interfaceToTelemetryEndpoint(endpoints []interface{}) []*TelemetryEndpoint { var res []*TelemetryEndpoint for _, v := range endpoints { From a90362388a9f116aae9b2d58e67b9b4d319b037d Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Tue, 12 Oct 2021 19:25:41 +0530 Subject: [PATCH 5/9] Instead of reading the genesis file use `dot.BuildFromDB()` Issue #1767 --- dot/rpc/http.go | 4 +-- dot/rpc/modules/api.go | 6 ++++ dot/rpc/modules/sync_state.go | 44 ++++++++++++++++++++++++------ dot/rpc/modules/sync_state_test.go | 19 +++++++++++-- dot/services.go | 5 +++- lib/genesis/genesis.go | 32 ---------------------- 6 files changed, 64 insertions(+), 46 deletions(-) diff --git a/dot/rpc/http.go b/dot/rpc/http.go index a70f4f4c76..8182dd8bbf 100644 --- a/dot/rpc/http.go +++ b/dot/rpc/http.go @@ -54,7 +54,7 @@ type HTTPServerConfig struct { TransactionQueueAPI modules.TransactionStateAPI RPCAPI modules.RPCAPI SystemAPI modules.SystemAPI - GenesisFilePath string + SyncStateAPI modules.SyncStateAPI NodeStorage *runtime.NodeStorage RPC bool RPCExternal bool @@ -131,7 +131,7 @@ func (h *HTTPServer) RegisterModules(mods []string) { case "childstate": srvc = modules.NewChildStateModule(h.serverConfig.StorageAPI, h.serverConfig.BlockAPI) case "syncstate": - srvc = modules.NewSyncStateModule(h.serverConfig.GenesisFilePath) + srvc = modules.NewSyncStateModule(h.serverConfig.SyncStateAPI) default: h.logger.Warn("Unrecognised module", "module", mod) continue diff --git a/dot/rpc/modules/api.go b/dot/rpc/modules/api.go index d79d9e5583..0bd7a67ae1 100644 --- a/dot/rpc/modules/api.go +++ b/dot/rpc/modules/api.go @@ -9,6 +9,7 @@ import ( "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/crypto" "github.com/ChainSafe/gossamer/lib/crypto/ed25519" + "github.com/ChainSafe/gossamer/lib/genesis" "github.com/ChainSafe/gossamer/lib/grandpa" "github.com/ChainSafe/gossamer/lib/runtime" "github.com/ChainSafe/gossamer/lib/transaction" @@ -121,3 +122,8 @@ type RuntimeStorageAPI interface { GetLocal(k []byte) ([]byte, error) GetPersistent(k []byte) ([]byte, error) } + +// SyncStateAPI is the interface to interact with sync state. +type SyncStateAPI interface { + GenSyncSpec(raw bool) (*genesis.Genesis, error) +} diff --git a/dot/rpc/modules/sync_state.go b/dot/rpc/modules/sync_state.go index d86b2610e7..25ba86ea2f 100644 --- a/dot/rpc/modules/sync_state.go +++ b/dot/rpc/modules/sync_state.go @@ -22,20 +22,25 @@ import ( "github.com/ChainSafe/gossamer/lib/genesis" ) -type SyncStateModule struct { - GenesisFilePath string +// GenSyncSpecRequest represents request to get chain specification. +type GenSyncSpecRequest struct { + Raw bool } -type BoolRequest struct { - Raw bool +// SyncStateModule is an RPC module to interact with sync state methods. +type SyncStateModule struct { + syncStateAPI SyncStateAPI } -func NewSyncStateModule(s string) *SyncStateModule { - return &SyncStateModule{GenesisFilePath: s} +// NewSyncStateModule creates an instance of SyncStateModule given SyncStateAPI. +func NewSyncStateModule(syncStateAPI SyncStateAPI) *SyncStateModule { + return &SyncStateModule{syncStateAPI: syncStateAPI} } -func (ss *SyncStateModule) GenSyncSpec(_ *http.Request, req *BoolRequest, res *genesis.Genesis) error { - g, err := genesis.GenSyncSpec(req.Raw, ss.GenesisFilePath) +// GenSyncSpec returns the JSON serialised chain specification running the node +// (i.e. the current state state), with a sync state. +func (ss *SyncStateModule) GenSyncSpec(_ *http.Request, req *GenSyncSpecRequest, res *genesis.Genesis) error { + g, err := ss.syncStateAPI.GenSyncSpec(req.Raw) if err != nil { return err } @@ -43,3 +48,26 @@ func (ss *SyncStateModule) GenSyncSpec(_ *http.Request, req *BoolRequest, res *g *res = *g return nil } + +// SyncState implements SyncStateAPI. +type SyncState struct { + chainSpecification *genesis.Genesis +} + +// NewStateSync creates an instance of SyncStateAPI given a chain specification. +func NewStateSync(chainSpecification *genesis.Genesis) SyncStateAPI { + return SyncState{chainSpecification: chainSpecification} +} + +// GenSyncSpec returns the JSON serialised chain specification running the node +// (i.e. the current state), with a sync state. +func (s SyncState) GenSyncSpec(raw bool) (*genesis.Genesis, error) { + if raw { + err := s.chainSpecification.ToRaw() + if err != nil { + return nil, err + } + } + + return s.chainSpecification, nil +} diff --git a/dot/rpc/modules/sync_state_test.go b/dot/rpc/modules/sync_state_test.go index 46e505c528..1c316dda5b 100644 --- a/dot/rpc/modules/sync_state_test.go +++ b/dot/rpc/modules/sync_state_test.go @@ -1,6 +1,9 @@ package modules import ( + "encoding/json" + "io/ioutil" + "path/filepath" "testing" "github.com/ChainSafe/gossamer/lib/genesis" @@ -10,13 +13,23 @@ import ( const GssmrGenesisPath = "../../../chain/gssmr/genesis.json" func TestSyncStateModule(t *testing.T) { - module := NewSyncStateModule(GssmrGenesisPath) + fp, err := filepath.Abs(GssmrGenesisPath) + require.NoError(t, err) + + data, err := ioutil.ReadFile(filepath.Clean(fp)) + require.NoError(t, err) + + g := new(genesis.Genesis) + err = json.Unmarshal(data, g) + require.NoError(t, err) + + module := NewSyncStateModule(NewStateSync(g)) - req := BoolRequest{ + req := GenSyncSpecRequest{ Raw: true, } var res genesis.Genesis - err := module.GenSyncSpec(nil, &req, &res) + err = module.GenSyncSpec(nil, &req, &res) require.NoError(t, err) } diff --git a/dot/services.go b/dot/services.go index aacbda466c..ef83e77180 100644 --- a/dot/services.go +++ b/dot/services.go @@ -335,6 +335,9 @@ func createRPCService(cfg *Config, ns *runtime.NodeStorage, stateSrvc *state.Ser ) rpcService := rpc.NewService() + buildSpec, _ := BuildFromDB(cfg.Global.BasePath) + syncStateSrvc := modules.NewStateSync(buildSpec.genesis) + rpcConfig := &rpc.HTTPServerConfig{ LogLvl: cfg.Log.RPCLvl, BlockAPI: stateSrvc.Block, @@ -346,7 +349,7 @@ func createRPCService(cfg *Config, ns *runtime.NodeStorage, stateSrvc *state.Ser BlockFinalityAPI: finSrvc, TransactionQueueAPI: stateSrvc.Transaction, RPCAPI: rpcService, - GenesisFilePath: cfg.Init.Genesis, + SyncStateAPI: syncStateSrvc, SystemAPI: sysSrvc, RPC: cfg.RPC.Enabled, RPCExternal: cfg.RPC.External, diff --git a/lib/genesis/genesis.go b/lib/genesis/genesis.go index 31156cd1cb..6eedd46d05 100644 --- a/lib/genesis/genesis.go +++ b/lib/genesis/genesis.go @@ -17,10 +17,6 @@ package genesis import ( - "encoding/json" - "io/ioutil" - "path/filepath" - "github.com/ChainSafe/gossamer/lib/common" ) @@ -111,34 +107,6 @@ func (g *Genesis) ToRaw() error { return nil } -// GenSyncSpec returns the JSON serialized chain specification running the node -// (i.e. the current state), with a sync state. -func GenSyncSpec(raw bool, GenesisFilePath string) (*Genesis, error) { - fp, err := filepath.Abs(GenesisFilePath) - if err != nil { - return nil, err - } - data, err := ioutil.ReadFile(filepath.Clean(fp)) - if err != nil { - return nil, err - } - - g := new(Genesis) - err = json.Unmarshal(data, g) - if err != nil { - return nil, err - } - - if raw { - err = g.ToRaw() - if err != nil { - return nil, err - } - } - - return g, nil -} - func interfaceToTelemetryEndpoint(endpoints []interface{}) []*TelemetryEndpoint { var res []*TelemetryEndpoint for _, v := range endpoints { From 9b9ddacf3b2b34584a8e8e182bbc1f7837c2f2e2 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Tue, 12 Oct 2021 19:34:46 +0530 Subject: [PATCH 6/9] No need to export SyncState --- dot/rpc/modules/sync_state.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dot/rpc/modules/sync_state.go b/dot/rpc/modules/sync_state.go index 25ba86ea2f..f14387f81d 100644 --- a/dot/rpc/modules/sync_state.go +++ b/dot/rpc/modules/sync_state.go @@ -49,19 +49,19 @@ func (ss *SyncStateModule) GenSyncSpec(_ *http.Request, req *GenSyncSpecRequest, return nil } -// SyncState implements SyncStateAPI. -type SyncState struct { +// syncState implements SyncStateAPI. +type syncState struct { chainSpecification *genesis.Genesis } // NewStateSync creates an instance of SyncStateAPI given a chain specification. func NewStateSync(chainSpecification *genesis.Genesis) SyncStateAPI { - return SyncState{chainSpecification: chainSpecification} + return syncState{chainSpecification: chainSpecification} } // GenSyncSpec returns the JSON serialised chain specification running the node // (i.e. the current state), with a sync state. -func (s SyncState) GenSyncSpec(raw bool) (*genesis.Genesis, error) { +func (s syncState) GenSyncSpec(raw bool) (*genesis.Genesis, error) { if raw { err := s.chainSpecification.ToRaw() if err != nil { From a19e059876a5ecd24c95e38fab5cdc5478b53592 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Wed, 13 Oct 2021 11:50:57 +0530 Subject: [PATCH 7/9] Can't use BuildFromDB, since badger DB is already occupied Use`*state.BaseState.LoadGenesisData()` instead and then Use StorageAPI to create genesis.Genesis --- dot/node.go | 5 ++++- dot/rpc/modules/sync_state.go | 33 ++++++++++++++++++++++++++++-- dot/rpc/modules/sync_state_test.go | 2 +- dot/services.go | 15 ++++++++++---- dot/services_test.go | 6 ++++-- 5 files changed, 51 insertions(+), 10 deletions(-) diff --git a/dot/node.go b/dot/node.go index 9b9b26c22a..93e0a68d9b 100644 --- a/dot/node.go +++ b/dot/node.go @@ -313,7 +313,10 @@ func NewNode(cfg *Config, ks *keystore.GlobalKeystore, stopFunc func()) (*Node, // check if rpc service is enabled if enabled := cfg.RPC.isRPCEnabled() || cfg.RPC.isWSEnabled(); enabled { - rpcSrvc := createRPCService(cfg, ns, stateSrvc, coreSrvc, networkSrvc, bp, sysSrvc, fg) + rpcSrvc, err := createRPCService(cfg, ns, stateSrvc, coreSrvc, networkSrvc, bp, sysSrvc, fg) + if err != nil { + return nil, fmt.Errorf("failed to create rpc service: %s", err) + } nodeSrvcs = append(nodeSrvcs, rpcSrvc) } else { logger.Debug("rpc service disabled by default", "rpc", enabled) diff --git a/dot/rpc/modules/sync_state.go b/dot/rpc/modules/sync_state.go index f14387f81d..15723f9943 100644 --- a/dot/rpc/modules/sync_state.go +++ b/dot/rpc/modules/sync_state.go @@ -55,8 +55,37 @@ type syncState struct { } // NewStateSync creates an instance of SyncStateAPI given a chain specification. -func NewStateSync(chainSpecification *genesis.Genesis) SyncStateAPI { - return syncState{chainSpecification: chainSpecification} +func NewStateSync(gData *genesis.Data, storageAPI StorageAPI) (SyncStateAPI, error) { + tmpGen := &genesis.Genesis{ + Name: "", + ID: "", + Bootnodes: nil, + ProtocolID: "", + Genesis: genesis.Fields{ + Runtime: nil, + }, + } + tmpGen.Genesis.Raw = make(map[string]map[string]string) + tmpGen.Genesis.Runtime = make(map[string]map[string]interface{}) + + // set genesis fields data + ent, err := storageAPI.Entries(nil) + if err != nil { + return nil, err + } + + err = genesis.BuildFromMap(ent, tmpGen) + if err != nil { + return nil, err + } + + tmpGen.Name = gData.Name + tmpGen.ID = gData.ID + // todo figure out how to assign bootnodes (see issue #1030) + //tmpGen.Bootnodes = gData.(*genesis.Data).Bootnodes + tmpGen.ProtocolID = gData.ProtocolID + + return syncState{chainSpecification: tmpGen}, nil } // GenSyncSpec returns the JSON serialised chain specification running the node diff --git a/dot/rpc/modules/sync_state_test.go b/dot/rpc/modules/sync_state_test.go index 1c316dda5b..2b6f800887 100644 --- a/dot/rpc/modules/sync_state_test.go +++ b/dot/rpc/modules/sync_state_test.go @@ -23,7 +23,7 @@ func TestSyncStateModule(t *testing.T) { err = json.Unmarshal(data, g) require.NoError(t, err) - module := NewSyncStateModule(NewStateSync(g)) + module := NewSyncStateModule(syncState{chainSpecification: g}) req := GenSyncSpecRequest{ Raw: true, diff --git a/dot/services.go b/dot/services.go index 62f8800718..7959c1f7e1 100644 --- a/dot/services.go +++ b/dot/services.go @@ -322,7 +322,7 @@ func createNetworkService(cfg *Config, stateSrvc *state.Service) (*network.Servi // RPC Service // createRPCService creates the RPC service from the provided core configuration -func createRPCService(cfg *Config, ns *runtime.NodeStorage, stateSrvc *state.Service, coreSrvc *core.Service, networkSrvc *network.Service, bp modules.BlockProducerAPI, sysSrvc *system.Service, finSrvc *grandpa.Service) *rpc.HTTPServer { +func createRPCService(cfg *Config, ns *runtime.NodeStorage, stateSrvc *state.Service, coreSrvc *core.Service, networkSrvc *network.Service, bp modules.BlockProducerAPI, sysSrvc *system.Service, finSrvc *grandpa.Service) (*rpc.HTTPServer, error) { logger.Info( "creating rpc service...", "host", cfg.RPC.Host, @@ -335,8 +335,15 @@ func createRPCService(cfg *Config, ns *runtime.NodeStorage, stateSrvc *state.Ser ) rpcService := rpc.NewService() - buildSpec, _ := BuildFromDB(cfg.Global.BasePath) - syncStateSrvc := modules.NewStateSync(buildSpec.genesis) + genesisData, err := stateSrvc.Base.LoadGenesisData() + if err != nil { + return nil, fmt.Errorf("failed to load genesis data: %s", err) + } + + syncStateSrvc, err := modules.NewStateSync(genesisData, stateSrvc.Storage) + if err != nil { + return nil, fmt.Errorf("failed to create sync state service: %s", err) + } rpcConfig := &rpc.HTTPServerConfig{ LogLvl: cfg.Log.RPCLvl, @@ -365,7 +372,7 @@ func createRPCService(cfg *Config, ns *runtime.NodeStorage, stateSrvc *state.Ser Modules: cfg.RPC.Modules, } - return rpc.NewHTTPServer(rpcConfig) + return rpc.NewHTTPServer(rpcConfig), nil } // System service diff --git a/dot/services_test.go b/dot/services_test.go index 03d71432c3..af005d1ef6 100644 --- a/dot/services_test.go +++ b/dot/services_test.go @@ -212,7 +212,8 @@ func TestCreateRPCService(t *testing.T) { sysSrvc, err := createSystemService(&cfg.System, stateSrvc) require.NoError(t, err) - rpcSrvc := createRPCService(cfg, ns, stateSrvc, coreSrvc, networkSrvc, nil, sysSrvc, nil) + rpcSrvc, err := createRPCService(cfg, ns, stateSrvc, coreSrvc, networkSrvc, nil, sysSrvc, nil) + require.NoError(t, err) require.NotNil(t, rpcSrvc) } @@ -350,7 +351,8 @@ func TestNewWebSocketServer(t *testing.T) { sysSrvc, err := createSystemService(&cfg.System, stateSrvc) require.NoError(t, err) - rpcSrvc := createRPCService(cfg, ns, stateSrvc, coreSrvc, networkSrvc, nil, sysSrvc, nil) + rpcSrvc, err := createRPCService(cfg, ns, stateSrvc, coreSrvc, networkSrvc, nil, sysSrvc, nil) + require.NoError(t, err) err = rpcSrvc.Start() require.Nil(t, err) From 929b8edc106be899bb251d55d565cba6253ba5df Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Wed, 13 Oct 2021 12:17:47 +0530 Subject: [PATCH 8/9] Fixing a linting error --- dot/node.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dot/node.go b/dot/node.go index 93e0a68d9b..f6298ab7e2 100644 --- a/dot/node.go +++ b/dot/node.go @@ -30,6 +30,7 @@ import ( "github.com/ChainSafe/gossamer/dot/metrics" "github.com/ChainSafe/gossamer/dot/network" + "github.com/ChainSafe/gossamer/dot/rpc" "github.com/ChainSafe/gossamer/dot/state" "github.com/ChainSafe/gossamer/dot/state/pruner" "github.com/ChainSafe/gossamer/dot/telemetry" @@ -313,7 +314,8 @@ func NewNode(cfg *Config, ks *keystore.GlobalKeystore, stopFunc func()) (*Node, // check if rpc service is enabled if enabled := cfg.RPC.isRPCEnabled() || cfg.RPC.isWSEnabled(); enabled { - rpcSrvc, err := createRPCService(cfg, ns, stateSrvc, coreSrvc, networkSrvc, bp, sysSrvc, fg) + var rpcSrvc *rpc.HTTPServer + rpcSrvc, err = createRPCService(cfg, ns, stateSrvc, coreSrvc, networkSrvc, bp, sysSrvc, fg) if err != nil { return nil, fmt.Errorf("failed to create rpc service: %s", err) } From 337cf45e786bf86804b42a3679ed6893e1e333b2 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Wed, 13 Oct 2021 13:47:32 +0530 Subject: [PATCH 9/9] Removed a TODO for assigning bootnodes --- dot/build_spec.go | 3 +-- dot/rpc/modules/sync_state.go | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/dot/build_spec.go b/dot/build_spec.go index 7abe4a2727..1b0e26e5d3 100644 --- a/dot/build_spec.go +++ b/dot/build_spec.go @@ -142,8 +142,7 @@ func BuildFromDB(path string) (*BuildSpec, error) { } tmpGen.Name = gData.Name tmpGen.ID = gData.ID - // todo figure out how to assign bootnodes (see issue #1030) - //tmpGen.Bootnodes = gData.(*genesis.Data).Bootnodes + tmpGen.Bootnodes = common.BytesToStringArray(gData.Bootnodes) tmpGen.ProtocolID = gData.ProtocolID bs := &BuildSpec{ diff --git a/dot/rpc/modules/sync_state.go b/dot/rpc/modules/sync_state.go index 15723f9943..90d2463056 100644 --- a/dot/rpc/modules/sync_state.go +++ b/dot/rpc/modules/sync_state.go @@ -19,6 +19,7 @@ package modules import ( "net/http" + "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/genesis" ) @@ -81,8 +82,7 @@ func NewStateSync(gData *genesis.Data, storageAPI StorageAPI) (SyncStateAPI, err tmpGen.Name = gData.Name tmpGen.ID = gData.ID - // todo figure out how to assign bootnodes (see issue #1030) - //tmpGen.Bootnodes = gData.(*genesis.Data).Bootnodes + tmpGen.Bootnodes = common.BytesToStringArray(gData.Bootnodes) tmpGen.ProtocolID = gData.ProtocolID return syncState{chainSpecification: tmpGen}, nil