diff --git a/internal/configs/node/config.go b/internal/configs/node/config.go new file mode 100644 index 000000000..b470a01ba --- /dev/null +++ b/internal/configs/node/config.go @@ -0,0 +1,165 @@ +// Package nodeconfig includes all the configuration variables for a node. +// It is a global configuration for node and other services. +// It will be included in node module, and other modules. +package nodeconfig + +import ( + "fmt" + "sync" + + "github.com/harmony-one/harmony/p2p" +) + +// Role defines a role of a node. +type Role byte + +// All constants for different node roles. +const ( + Unknown Role = iota + ShardLeader + ShardValidator + BeaconLeader + BeaconValidator + NewNode + ClientNode +) + +func (role Role) String() string { + switch role { + case Unknown: + return "Unknown" + case ShardLeader: + return "ShardLeader" + case ShardValidator: + return "ShardValidator" + case BeaconLeader: + return "BeaconLeader" + case BeaconValidator: + return "BeaconValidator" + case NewNode: + return "NewNode" + case ClientNode: + return "ClientNode" + } + return "Unknown" +} + +// Global is the index of the global node configuration +const ( + Global = 0 + MaxShards = 32 // maximum number of shards. It is also the maxium number of configs. +) + +// ConfigType is the structure of all node related configuration variables +type ConfigType struct { + // The three groupID design, please refer to https://github.com/harmony-one/harmony/blob/master/node/node.md#libp2p-integration + beacon p2p.GroupID // the beacon group ID + group p2p.GroupID // the group ID of the shard + client p2p.GroupID // the client group ID of the shard + isClient bool // whether this node is a client node, such as wallet/txgen + isBeacon bool // whether this node is a beacon node or not + isLeader bool // whether this node is a leader or not + shardID uint32 // shardID of this node + role Role // Role of the node +} + +// configs is a list of node configuration. +// It has at least one configuration. +// The first one is the default, global node configuration +var configs []ConfigType +var onceForConfigs sync.Once + +// GetConfigs return the indexed ConfigType variable +func GetConfigs(index int) *ConfigType { + onceForConfigs.Do(func() { + configs = make([]ConfigType, MaxShards) + }) + if index > cap(configs) { + return nil + } + return &configs[index] +} + +func (conf *ConfigType) String() string { + return fmt.Sprintf("%s/%s/%s:%v,%v,%v:%v", conf.beacon, conf.group, conf.client, conf.isClient, conf.isBeacon, conf.isLeader, conf.shardID) +} + +// SetBeaconGroupID set the groupID for beacon group +func (conf *ConfigType) SetBeaconGroupID(g p2p.GroupID) { + conf.beacon = g +} + +// SetShardGroupID set the groupID for shard group +func (conf *ConfigType) SetShardGroupID(g p2p.GroupID) { + conf.group = g +} + +// SetClientGroupID set the groupID for client group +func (conf *ConfigType) SetClientGroupID(g p2p.GroupID) { + conf.client = g +} + +// SetIsClient set the isClient configuration +func (conf *ConfigType) SetIsClient(b bool) { + conf.isClient = b +} + +// SetIsBeacon set the isBeacon configuration +func (conf *ConfigType) SetIsBeacon(b bool) { + conf.isBeacon = b +} + +// SetIsLeader set the isLeader configuration +func (conf *ConfigType) SetIsLeader(b bool) { + conf.isLeader = b +} + +// SetShardID set the shardID +func (conf *ConfigType) SetShardID(s uint32) { + conf.shardID = s +} + +// SetRole set the role +func (conf *ConfigType) SetRole(r Role) { + conf.role = r +} + +// GetBeaconGroupID returns the groupID for beacon group +func (conf *ConfigType) GetBeaconGroupID() p2p.GroupID { + return conf.beacon +} + +// GetShardGroupID returns the groupID for shard group +func (conf *ConfigType) GetShardGroupID() p2p.GroupID { + return conf.group +} + +// GetClientGroupID returns the groupID for client group +func (conf *ConfigType) GetClientGroupID() p2p.GroupID { + return conf.client +} + +// IsClient returns the isClient configuration +func (conf *ConfigType) IsClient() bool { + return conf.isClient +} + +// IsBeacon returns the isBeacon configuration +func (conf *ConfigType) IsBeacon() bool { + return conf.isBeacon +} + +// IsLeader returns the isLeader configuration +func (conf *ConfigType) IsLeader() bool { + return conf.isLeader +} + +// ShardID returns the shardID +func (conf *ConfigType) ShardID() uint32 { + return conf.shardID +} + +// Role returns the role +func (conf *ConfigType) Role() Role { + return conf.role +} diff --git a/internal/configs/node/config_test.go b/internal/configs/node/config_test.go new file mode 100644 index 000000000..b4460a910 --- /dev/null +++ b/internal/configs/node/config_test.go @@ -0,0 +1,75 @@ +package nodeconfig + +import ( + "testing" + + "github.com/harmony-one/harmony/p2p" +) + +func TestNodeConfigSingleton(t *testing.T) { + // init 3 configs + _ = GetConfigs(2) + + // get the singleton variable + c := GetConfigs(Global) + + c.SetIsLeader(true) + + if !c.IsLeader() { + t.Errorf("IsLeader = %v, expected = %v", c.IsLeader(), true) + } + + c.SetBeaconGroupID(p2p.GroupIDBeacon) + + d := GetConfigs(Global) + + if !d.IsLeader() { + t.Errorf("IsLeader = %v, expected = %v", d.IsLeader(), true) + } + + g := d.GetBeaconGroupID() + + if g != p2p.GroupIDBeacon { + t.Errorf("GetBeaconGroupID = %v, expected = %v", g, p2p.GroupIDBeacon) + } +} + +func TestNodeConfigMultiple(t *testing.T) { + // init 3 configs + c := GetConfigs(2) + d := GetConfigs(1) + e := GetConfigs(0) + f := GetConfigs(42) + + if f != nil { + t.Errorf("expecting nil, got: %v", f) + } + + c.SetIsBeacon(true) + if c.IsBeacon() != true { + t.Errorf("expecting true, got: %v", c.IsBeacon()) + } + + d.SetShardGroupID("abcd") + if d.GetShardGroupID() != "abcd" { + t.Errorf("expecting abcd, got: %v", d.GetShardGroupID()) + } + + e.SetClientGroupID("client") + if e.GetClientGroupID() != "client" { + t.Errorf("expecting client, got: %v", d.GetClientGroupID()) + } + + e.SetIsClient(false) + if e.IsClient() != false { + t.Errorf("expecting false, got: %v", e.IsClient()) + } + + c.SetRole(NewNode) + if c.Role() != NewNode { + t.Errorf("expecting NewNode, got: %s", c.Role()) + } + if c.Role().String() != "NewNode" { + t.Errorf("expecting NewNode, got: %s", c.Role().String()) + } +}