You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
173 lines
4.6 KiB
173 lines
4.6 KiB
package utils
|
|
|
|
import (
|
|
"bufio"
|
|
"log"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/harmony-one/harmony/crypto"
|
|
"github.com/harmony-one/harmony/crypto/pki"
|
|
"github.com/harmony-one/harmony/p2p"
|
|
)
|
|
|
|
// ConfigEntry is the config entry.
|
|
type ConfigEntry struct {
|
|
IP string
|
|
Port string
|
|
Role string
|
|
ShardID string
|
|
ValidatorID int // Validator ID in its shard.
|
|
}
|
|
|
|
// DistributionConfig is the distribution config.
|
|
type DistributionConfig struct {
|
|
config []ConfigEntry
|
|
}
|
|
|
|
// NewDistributionConfig creates new DistributionConfig
|
|
func NewDistributionConfig() *DistributionConfig {
|
|
config := DistributionConfig{}
|
|
return &config
|
|
}
|
|
|
|
// GetLeadersAndShardIDs gets all the leader peers and corresponding shard Ids
|
|
func (config *DistributionConfig) GetLeadersAndShardIDs() ([]p2p.Peer, []uint32) {
|
|
var peerList []p2p.Peer
|
|
var shardIDs []uint32
|
|
for _, entry := range config.config {
|
|
if entry.Role == "leader" {
|
|
peerList = append(peerList, p2p.Peer{IP: entry.IP, Port: entry.Port})
|
|
val, err := strconv.Atoi(entry.ShardID)
|
|
if err == nil {
|
|
shardIDs = append(shardIDs, uint32(val))
|
|
} else {
|
|
log.Print("[Generator] Error parsing the shard Id ", entry.ShardID)
|
|
}
|
|
}
|
|
}
|
|
return peerList, shardIDs
|
|
}
|
|
|
|
// GetClientPeer returns client peer.
|
|
func (config *DistributionConfig) GetClientPeer() *p2p.Peer {
|
|
for _, entry := range config.config {
|
|
if entry.Role != "client" {
|
|
continue
|
|
}
|
|
peer := p2p.Peer{Port: entry.Port, IP: entry.IP}
|
|
return &peer
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetClientPort gets the port of the client node in the config
|
|
func (config *DistributionConfig) GetClientPort() string {
|
|
for _, entry := range config.config {
|
|
if entry.Role == "client" {
|
|
return entry.Port
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// ReadConfigFile parses the config file and return a 2d array containing the file data
|
|
func (config *DistributionConfig) ReadConfigFile(filename string) error {
|
|
file, err := os.Open(filename)
|
|
if err != nil {
|
|
log.Fatal("Failed to read config file ", filename)
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
fscanner := bufio.NewScanner(file)
|
|
|
|
result := []ConfigEntry{}
|
|
validatorMap := map[int]int{}
|
|
for fscanner.Scan() {
|
|
p := strings.Split(fscanner.Text(), " ")
|
|
shardID, _ := strconv.Atoi(p[3])
|
|
validatorID := -1
|
|
if p[2] == "validator" {
|
|
validatorMap[shardID]++
|
|
validatorID = validatorMap[shardID]
|
|
}
|
|
entry := ConfigEntry{p[0], p[1], p[2], p[3], validatorID}
|
|
result = append(result, entry)
|
|
}
|
|
config.config = result
|
|
return nil
|
|
}
|
|
|
|
// GetShardID Gets the shard id of the node corresponding to this ip and port
|
|
func (config *DistributionConfig) GetShardID(ip, port string) string {
|
|
for _, entry := range config.config {
|
|
if entry.IP == ip && entry.Port == port {
|
|
return entry.ShardID
|
|
}
|
|
}
|
|
return "N/A"
|
|
}
|
|
|
|
// GetPeers Gets the validator list
|
|
func (config *DistributionConfig) GetPeers(ip, port, shardID string) []p2p.Peer {
|
|
var peerList []p2p.Peer
|
|
for _, entry := range config.config {
|
|
if entry.Role != "validator" || entry.ShardID != shardID {
|
|
continue
|
|
}
|
|
// Get public key deterministically based on ip and port
|
|
peer := p2p.Peer{Port: entry.Port, IP: entry.IP, ValidatorID: entry.ValidatorID}
|
|
setKey(&peer)
|
|
peerList = append(peerList, peer)
|
|
}
|
|
return peerList
|
|
}
|
|
|
|
// GetSelfPeer Gets the validator list
|
|
func (config *DistributionConfig) GetSelfPeer(ip, port, shardID string) p2p.Peer {
|
|
for _, entry := range config.config {
|
|
if entry.IP == ip && entry.Port == port && entry.ShardID == shardID {
|
|
peer := p2p.Peer{Port: entry.Port, IP: entry.IP, ValidatorID: entry.ValidatorID}
|
|
return peer
|
|
}
|
|
}
|
|
return p2p.Peer{}
|
|
}
|
|
|
|
// GetLeader Gets the leader of this shard id
|
|
func (config *DistributionConfig) GetLeader(shardID string) p2p.Peer {
|
|
var leaderPeer p2p.Peer
|
|
for _, entry := range config.config {
|
|
if entry.Role == "leader" && entry.ShardID == shardID {
|
|
leaderPeer.IP = entry.IP
|
|
leaderPeer.Port = entry.Port
|
|
setKey(&leaderPeer)
|
|
}
|
|
}
|
|
return leaderPeer
|
|
}
|
|
|
|
// GetConfigEntries returns a list of ConfigEntry.
|
|
func (config *DistributionConfig) GetConfigEntries() []ConfigEntry {
|
|
return config.config
|
|
}
|
|
|
|
// GetMyConfigEntry ...
|
|
func (config *DistributionConfig) GetMyConfigEntry(ip string, port string) *ConfigEntry {
|
|
if config.config == nil {
|
|
return nil
|
|
}
|
|
for _, entry := range config.config {
|
|
if entry.IP == ip && entry.Port == port {
|
|
return &entry
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func setKey(peer *p2p.Peer) {
|
|
// Get public key deterministically based on ip and port
|
|
priKey := crypto.Ed25519Curve.Scalar().SetInt64(int64(GetUniqueIDFromPeer(*peer))) // TODO: figure out why using a random hash value doesn't work for private key (schnorr)
|
|
peer.PubKey = pki.GetPublicKeyFromScalar(priKey)
|
|
}
|
|
|