Static peers are now also optionally configurable (#738)
* Rename bootnode to static peers Also add some groupings between types. * Remove not needed genesisHash * More cleanup of bootnodes with static peers * Add option of cluster configuration file * New generated bindata.go * Changes after npm install * Add argument for cluster configuration file * Add test for dynamic cluster loading Not yet sure with name "cluster config". * Solved conflicts * Renaming of static peers * Remove static peers population * Missing argument for config * Renaming of static peers to boot nodes for consistency * Fix of name change * Cluster config is now cluster data * Load static nodes from configuration * Final renaming of var for file content
This commit is contained in:
parent
d84510de92
commit
8e42014671
|
@ -25,6 +25,7 @@ var (
|
|||
)
|
||||
|
||||
var (
|
||||
clusterConfigFile = flag.String("clusterconfig", "", "Cluster configuration file")
|
||||
prodMode = flag.Bool("production", false, "Whether production settings should be loaded")
|
||||
nodeKeyFile = flag.String("nodekey", "", "P2P node key file (private key)")
|
||||
dataDir = flag.String("datadir", params.DataDir, "Data directory for the databases and keystore")
|
||||
|
@ -189,7 +190,7 @@ func startCollectingStats(interruptCh <-chan struct{}, nodeManager common.NodeMa
|
|||
// makeNodeConfig parses incoming CLI options and returns node configuration object
|
||||
func makeNodeConfig() (*params.NodeConfig, error) {
|
||||
devMode := !*prodMode
|
||||
nodeConfig, err := params.NewNodeConfig(*dataDir, uint64(*networkID), devMode)
|
||||
nodeConfig, err := params.NewNodeConfig(*dataDir, *clusterConfigFile, uint64(*networkID), devMode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ package common
|
|||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
accounts "github.com/ethereum/go-ethereum/accounts"
|
||||
keystore "github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
common "github.com/ethereum/go-ethereum/common"
|
||||
|
@ -15,7 +17,6 @@ import (
|
|||
gomock "github.com/golang/mock/gomock"
|
||||
params "github.com/status-im/status-go/geth/params"
|
||||
rpc "github.com/status-im/status-go/geth/rpc"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
// MockNodeManager is a mock of NodeManager interface
|
||||
|
|
|
@ -98,12 +98,6 @@ func (m *NodeManager) startNode(config *params.NodeConfig) error {
|
|||
log.Error("Failed to create an RPC client", "error", err)
|
||||
return RPCClientError(err)
|
||||
}
|
||||
// populate static peers exits when node stopped
|
||||
go func() {
|
||||
if err := m.PopulateStaticPeers(); err != nil {
|
||||
log.Error("Static peers population", "error", err)
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -202,7 +196,7 @@ func (m *NodeManager) populateStaticPeers() error {
|
|||
|
||||
func (m *NodeManager) removeStaticPeers() error {
|
||||
if !m.config.BootClusterConfig.Enabled {
|
||||
log.Info("Boot cluster is disabled")
|
||||
log.Info("static peers are disabled")
|
||||
return nil
|
||||
}
|
||||
server := m.node.Server()
|
||||
|
@ -212,10 +206,10 @@ func (m *NodeManager) removeStaticPeers() error {
|
|||
for _, enode := range m.config.BootClusterConfig.BootNodes {
|
||||
err := m.removePeer(enode)
|
||||
if err != nil {
|
||||
log.Warn("Boot node deletion failed", "error", err)
|
||||
log.Warn("static peer deletion failed", "error", err)
|
||||
return err
|
||||
}
|
||||
log.Info("Boot node deleted", "enode", enode)
|
||||
log.Info("static peer deleted", "enode", enode)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ func defaultEmbeddedNodeConfig(config *params.NodeConfig) *node.Config {
|
|||
}
|
||||
|
||||
if config.BootClusterConfig.Enabled {
|
||||
nc.P2P.BootstrapNodes = makeBootstrapNodes(config.BootClusterConfig.BootNodes)
|
||||
nc.P2P.StaticNodes = makeBootstrapNodes(config.BootClusterConfig.BootNodes)
|
||||
}
|
||||
|
||||
return nc
|
||||
|
|
|
@ -25,6 +25,10 @@ var (
|
|||
ErrAuthorizationKeyFileNotSet = errors.New("authorization key file is not set")
|
||||
)
|
||||
|
||||
// ----------
|
||||
// LightEthConfig
|
||||
// ----------
|
||||
|
||||
// LightEthConfig holds LES-related configuration
|
||||
// Status nodes are always lightweight clients (due to mobile platform constraints)
|
||||
type LightEthConfig struct {
|
||||
|
@ -38,6 +42,10 @@ type LightEthConfig struct {
|
|||
DatabaseCache int
|
||||
}
|
||||
|
||||
// ----------
|
||||
// FirebaseConfig
|
||||
// ----------
|
||||
|
||||
// FirebaseConfig holds FCM-related configuration
|
||||
type FirebaseConfig struct {
|
||||
// AuthorizationKeyFile file path that contains FCM authorization key
|
||||
|
@ -67,6 +75,10 @@ func (c *FirebaseConfig) ReadAuthorizationKeyFile() ([]byte, error) {
|
|||
return key, nil
|
||||
}
|
||||
|
||||
// ----------
|
||||
// WhisperConfig
|
||||
// ----------
|
||||
|
||||
// WhisperConfig holds SHH-related configuration
|
||||
type WhisperConfig struct {
|
||||
// Enabled flag specifies whether protocol is enabled
|
||||
|
@ -126,6 +138,10 @@ func (c *WhisperConfig) String() string {
|
|||
return string(data)
|
||||
}
|
||||
|
||||
// ----------
|
||||
// SwarmConfig
|
||||
// ----------
|
||||
|
||||
// SwarmConfig holds Swarm-related configuration
|
||||
type SwarmConfig struct {
|
||||
// Enabled flag specifies whether protocol is enabled
|
||||
|
@ -138,14 +154,18 @@ func (c *SwarmConfig) String() string {
|
|||
return string(data)
|
||||
}
|
||||
|
||||
// BootClusterConfig holds configuration for supporting boot cluster, which is a temporary
|
||||
// ----------
|
||||
// BootClusterConfig
|
||||
// ----------
|
||||
|
||||
// BootClusterConfig holds configuration for supporting cluster peers, which is a temporary
|
||||
// means for mobile devices to get connected to Ethereum network (UDP-based discovery
|
||||
// may not be available, so we need means to discover the network manually).
|
||||
type BootClusterConfig struct {
|
||||
// Enabled flag specifies whether feature is enabled
|
||||
Enabled bool
|
||||
|
||||
// BootNodes list of bootstrap nodes for a given network (Ropsten, Rinkeby, Homestead),
|
||||
// BootNodes list of cluster peer nodes for a given network (Ropsten, Rinkeby, Homestead),
|
||||
// for a given mode (production vs development)
|
||||
BootNodes []string
|
||||
}
|
||||
|
@ -156,7 +176,9 @@ func (c *BootClusterConfig) String() string {
|
|||
return string(data)
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// ----------
|
||||
// UpstreamRPCConfig
|
||||
// ----------
|
||||
|
||||
// UpstreamRPCConfig stores configuration for upstream rpc connection.
|
||||
type UpstreamRPCConfig struct {
|
||||
|
@ -168,7 +190,9 @@ type UpstreamRPCConfig struct {
|
|||
URL string
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// ----------
|
||||
// NodeConfig
|
||||
// ----------
|
||||
|
||||
// NodeConfig stores configuration options for a node
|
||||
type NodeConfig struct {
|
||||
|
@ -187,7 +211,7 @@ type NodeConfig struct {
|
|||
// If KeyStoreDir is empty, the default location is the "keystore" subdirectory of DataDir.
|
||||
KeyStoreDir string
|
||||
|
||||
// PrivateKeyFile is a filename with node ID (private key)
|
||||
// NodeKeyFile is a filename with node ID (private key)
|
||||
// This file should contain a valid secp256k1 private key that will be used for both
|
||||
// remote peer identification as well as network traffic encryption.
|
||||
NodeKeyFile string
|
||||
|
@ -256,7 +280,11 @@ type NodeConfig struct {
|
|||
// UpstreamConfig extra config for providing upstream infura server.
|
||||
UpstreamConfig UpstreamRPCConfig `json:"UpstreamConfig"`
|
||||
|
||||
// BootClusterConfig extra configuration for supporting cluster
|
||||
// ClusterConfigFile contains the file name of the cluster configuration. If
|
||||
// empty the statical configuration data will be taken.
|
||||
ClusterConfigFile string `json:"ClusterConfigFile"`
|
||||
|
||||
// BootClusterConfig extra configuration for supporting cluster peers.
|
||||
BootClusterConfig *BootClusterConfig `json:"BootClusterConfig," validate:"structonly"`
|
||||
|
||||
// LightEthConfig extra configuration for LES
|
||||
|
@ -270,7 +298,7 @@ type NodeConfig struct {
|
|||
}
|
||||
|
||||
// NewNodeConfig creates new node configuration object
|
||||
func NewNodeConfig(dataDir string, networkID uint64, devMode bool) (*NodeConfig, error) {
|
||||
func NewNodeConfig(dataDir string, clstrCfgFile string, networkID uint64, devMode bool) (*NodeConfig, error) {
|
||||
nodeConfig := &NodeConfig{
|
||||
DevMode: devMode,
|
||||
NetworkID: networkID,
|
||||
|
@ -290,6 +318,7 @@ func NewNodeConfig(dataDir string, networkID uint64, devMode bool) (*NodeConfig,
|
|||
LogFile: LogFile,
|
||||
LogLevel: LogLevel,
|
||||
LogToStderr: LogToStderr,
|
||||
ClusterConfigFile: clstrCfgFile,
|
||||
BootClusterConfig: &BootClusterConfig{
|
||||
Enabled: true,
|
||||
BootNodes: []string{},
|
||||
|
@ -332,7 +361,7 @@ func LoadNodeConfig(configJSON string) (*NodeConfig, error) {
|
|||
}
|
||||
|
||||
func loadNodeConfig(configJSON string) (*NodeConfig, error) {
|
||||
nodeConfig, err := NewNodeConfig("", 0, true)
|
||||
nodeConfig, err := NewNodeConfig("", "", 0, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -433,7 +462,7 @@ func (c *NodeConfig) updateConfig() error {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := c.updateBootClusterConfig(); err != nil {
|
||||
if err := c.updateClusterConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -511,10 +540,10 @@ func (c *NodeConfig) updateUpstreamConfig() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// updateBootClusterConfig loads boot nodes and CHT for a given network and mode.
|
||||
// updateClusterConfig loads static peer nodes and CHT for a given network and mode.
|
||||
// This is necessary until we have LES protocol support CHT sync, and better node
|
||||
// discovery on mobile devices)
|
||||
func (c *NodeConfig) updateBootClusterConfig() error {
|
||||
func (c *NodeConfig) updateClusterConfig() error {
|
||||
if !c.BootClusterConfig.Enabled {
|
||||
return nil
|
||||
}
|
||||
|
@ -523,27 +552,38 @@ func (c *NodeConfig) updateBootClusterConfig() error {
|
|||
// Once CHT sync sub-protocol is working in LES, we will rely on it, as it provides
|
||||
// decentralized solution. For now, in order to avoid forcing users to long sync times
|
||||
// we use central static resource
|
||||
type subClusterConfig struct {
|
||||
type subClusterData struct {
|
||||
Number int `json:"number"`
|
||||
Hash string `json:"hash"`
|
||||
BootNodes []string `json:"bootnodes"`
|
||||
}
|
||||
type clusterConfig struct {
|
||||
type clusterData struct {
|
||||
NetworkID int `json:"networkID"`
|
||||
GenesisHash string `json:"genesisHash"`
|
||||
Prod subClusterConfig `json:"prod"`
|
||||
Dev subClusterConfig `json:"dev"`
|
||||
Prod subClusterData `json:"prod"`
|
||||
Dev subClusterData `json:"dev"`
|
||||
}
|
||||
|
||||
chtFile, err := static.Asset("config/staticpeers.json")
|
||||
var configFile []byte
|
||||
var err error
|
||||
|
||||
if c.ClusterConfigFile != "" {
|
||||
// Load cluster configuration from external file.
|
||||
configFile, err = ioutil.ReadFile(c.ClusterConfigFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("staticpeers.json could not be loaded: %s", err)
|
||||
return fmt.Errorf("cluster configuration file '%s' could not be loaded: %s", c.ClusterConfigFile, err)
|
||||
}
|
||||
} else {
|
||||
// Fallback to embedded file.
|
||||
configFile, err = static.Asset("config/cluster.json")
|
||||
if err != nil {
|
||||
return fmt.Errorf("cluster.json could not be loaded: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
var clusters []clusterConfig
|
||||
err = json.Unmarshal(chtFile, &clusters)
|
||||
var clusters []clusterData
|
||||
err = json.Unmarshal(configFile, &clusters)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unmarshal staticpeers.json: %s", err)
|
||||
return fmt.Errorf("failed to unmarshal cluster configuration file: %s", err)
|
||||
}
|
||||
|
||||
for _, cluster := range clusters {
|
||||
|
|
|
@ -17,6 +17,24 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var clusterConfigData = []byte(`[
|
||||
{
|
||||
"networkID": 3,
|
||||
"prod": {
|
||||
"bootnodes": [
|
||||
"enode://7ab298cedc4185a894d21d8a4615262ec6bdce66c9b6783878258e0d5b31013d30c9038932432f70e5b2b6a5cd323bf820554fcb22fbc7b45367889522e9c449@10.1.1.1:30303",
|
||||
"enode://f59e8701f18c79c5cbc7618dc7bb928d44dc2f5405c7d693dad97da2d8585975942ec6fd36d3fe608bfdc7270a34a4dd00f38cfe96b2baa24f7cd0ac28d382a1@10.1.1.2:30303"
|
||||
]
|
||||
},
|
||||
"dev": {
|
||||
"bootnodes": [
|
||||
"enode://7ab298cedc4185a894d21d8a4615262ec6bdce66c9b6783878258e0d5b31013d30c9038932432f70e5b2b6a5cd323bf820554fcb22fbc7b45367889522e9c449@10.1.1.1:30303",
|
||||
"enode://f59e8701f18c79c5cbc7618dc7bb928d44dc2f5405c7d693dad97da2d8585975942ec6fd36d3fe608bfdc7270a34a4dd00f38cfe96b2baa24f7cd0ac28d382a1@10.1.1.2:30303"
|
||||
]
|
||||
}
|
||||
}
|
||||
]`)
|
||||
|
||||
var loadConfigTestCases = []struct {
|
||||
name string
|
||||
configJSON string
|
||||
|
@ -215,17 +233,43 @@ var loadConfigTestCases = []struct {
|
|||
},
|
||||
},
|
||||
{
|
||||
`default boot cluster (Ropsten Dev)`,
|
||||
`default boot nodes (Ropsten Dev)`,
|
||||
`{
|
||||
"NetworkId": 3,
|
||||
"DataDir": "$TMPDIR"
|
||||
}`,
|
||||
func(t *testing.T, dataDir string, nodeConfig *params.NodeConfig, err error) {
|
||||
require.NoError(t, err)
|
||||
require.True(t, nodeConfig.BootClusterConfig.Enabled, "boot cluster is expected to be enabled by default")
|
||||
require.True(t, nodeConfig.BootClusterConfig.Enabled, "boot nodes are expected to be enabled by default")
|
||||
|
||||
enodes := nodeConfig.BootClusterConfig.BootNodes
|
||||
require.Len(t, enodes, 4)
|
||||
require.Len(t, enodes, 2)
|
||||
},
|
||||
},
|
||||
{
|
||||
`illegal cluster config file`,
|
||||
`{
|
||||
"NetworkId": 3,
|
||||
"DataDir": "$TMPDIR",
|
||||
"ClusterConfigFile": "/file/does/not.exist"
|
||||
}`,
|
||||
func(t *testing.T, dataDir string, nodeConfig *params.NodeConfig, err error) {
|
||||
require.Error(t, err, "error is expected, not thrown")
|
||||
},
|
||||
},
|
||||
{
|
||||
`valid cluster config file`,
|
||||
`{
|
||||
"NetworkId": 3,
|
||||
"DataDir": "$TMPDIR",
|
||||
"ClusterConfigFile": "$TMPDIR/cluster.json"
|
||||
}`,
|
||||
func(t *testing.T, dataDir string, nodeConfig *params.NodeConfig, err error) {
|
||||
require.NoError(t, err)
|
||||
require.True(t, nodeConfig.BootClusterConfig.Enabled, "boot cluster is expected to be enabled after loading file")
|
||||
|
||||
enodes := nodeConfig.BootClusterConfig.BootNodes
|
||||
require.True(t, len(enodes) == 2)
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -240,7 +284,7 @@ var loadConfigTestCases = []struct {
|
|||
require.True(t, nodeConfig.BootClusterConfig.Enabled, "boot cluster is expected to be enabled by default")
|
||||
|
||||
enodes := nodeConfig.BootClusterConfig.BootNodes
|
||||
require.Len(t, enodes, 4)
|
||||
require.Len(t, enodes, 2)
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -364,9 +408,8 @@ func TestLoadNodeConfig(t *testing.T) {
|
|||
}
|
||||
defer os.RemoveAll(tmpDir) // nolint: errcheck
|
||||
|
||||
// create sample Bootstrap Cluster Config
|
||||
bootstrapConfig := []byte(`["enode://foobar@41.41.41.41:30300", "enode://foobaz@42.42.42.42:30302"]`)
|
||||
err = ioutil.WriteFile(filepath.Join(tmpDir, "bootstrap-cluster.json"), bootstrapConfig, os.ModePerm)
|
||||
// create sample bootnodes config
|
||||
err = ioutil.WriteFile(filepath.Join(tmpDir, "cluster.json"), clusterConfigData, os.ModePerm)
|
||||
require.NoError(t, err)
|
||||
t.Log(tmpDir)
|
||||
|
||||
|
@ -383,7 +426,7 @@ func TestConfigWriteRead(t *testing.T) {
|
|||
require.Nil(t, err)
|
||||
defer os.RemoveAll(tmpDir) // nolint: errcheck
|
||||
|
||||
nodeConfig, err := params.NewNodeConfig(tmpDir, params.RopstenNetworkID, true)
|
||||
nodeConfig, err := params.NewNodeConfig(tmpDir, "", params.RopstenNetworkID, true)
|
||||
require.Nil(t, err, "cannot create new config object")
|
||||
|
||||
err = nodeConfig.Save()
|
||||
|
|
|
@ -57,7 +57,7 @@ func (s *TxQueueTestSuite) SetupTest() {
|
|||
s.client = gethrpc.DialInProc(s.server)
|
||||
rpclient, _ := rpc.NewClient(s.client, params.UpstreamRPCConfig{})
|
||||
s.nodeManagerMock.EXPECT().RPCClient().Return(rpclient)
|
||||
nodeConfig, err := params.NewNodeConfig("/tmp", params.RopstenNetworkID, true)
|
||||
nodeConfig, err := params.NewNodeConfig("/tmp", "", params.RopstenNetworkID, true)
|
||||
s.Require().NoError(err)
|
||||
s.nodeConfig = nodeConfig
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
//GenerateConfig for status node
|
||||
//export GenerateConfig
|
||||
func GenerateConfig(datadir *C.char, networkID C.int, devMode C.int) *C.char {
|
||||
config, err := params.NewNodeConfig(C.GoString(datadir), uint64(networkID), devMode == 1)
|
||||
config, err := params.NewNodeConfig(C.GoString(datadir), "", uint64(networkID), devMode == 1)
|
||||
if err != nil {
|
||||
return makeJSONResponse(err)
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,6 @@
|
|||
[
|
||||
{
|
||||
"networkID": 3,
|
||||
"genesisHash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d",
|
||||
"prod": {
|
||||
"bootnodes": [
|
||||
"enode://dffef3874011709b12d1e540d83ddb19a9db8614ad9151d05bcf813585e45cbebba5aaea223fe315786c401d8cecb1ad2de9f179680c536ea30311fb21fa934b@188.166.100.178:30303",
|
||||
|
@ -17,7 +16,6 @@
|
|||
},
|
||||
{
|
||||
"networkID": 4,
|
||||
"genesisHash": "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177",
|
||||
"prod": {
|
||||
"bootnodes": [
|
||||
"enode://fda3f6273a0f2da4ac5858d1f52e5afaf9def281121be3d37558c67d4d9ca26c6ad7a0520b2cd7454120fb770e86d5760487c9924b2166e65485f606e56d60fc@51.15.69.144:30303",
|
||||
|
@ -35,7 +33,6 @@
|
|||
},
|
||||
{
|
||||
"networkID": 1,
|
||||
"genesisHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3",
|
||||
"prod": {
|
||||
"bootnodes": [
|
||||
"enode://71bb01b58165e3262aea2d3b06dbf9abb8d5512d96e5000e7e41ab2138b47be685935d3eb119fc25e1413db00d8db231fd9d59555a1cd75229821559b6a4eb51@51.15.85.243:30303",
|
|
@ -306,7 +306,7 @@ func (s *ManagerTestSuite) TestStartNodeWithUpstreamEnabled() {
|
|||
// },
|
||||
// func(config *params.NodeConfig) {
|
||||
// log.Info("PopulateStaticPeers()")
|
||||
// s.T().Logf("PopulateStaticPeers(), error: %v", s.NodeManager.PopulateStaticPeers())
|
||||
// s.T().Logf("PopulateBootNodes(), error: %v", s.NodeManager.PopulateStaticPeers())
|
||||
// progress <- struct{}{}
|
||||
// },
|
||||
// // TODO(adam): quarantined until it uses a different datadir
|
||||
|
|
Loading…
Reference in New Issue