Merge pull request #1939 from harmony-ek/staking_flag

Add staking mode knob to harmony & node.sh
pull/1941/head
Eugene Kim 5 years ago committed by GitHub
commit 66493dd3ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      api/service/networkinfo/service.go
  2. 9
      cmd/client/txgen/main.go
  3. 10
      cmd/client/wallet/main.go
  4. 10
      cmd/client/wallet_stress_test/main.go
  5. 98
      cmd/harmony/main.go
  6. 2
      core/rawdb/accessors_chain.go
  7. 78
      internal/configs/node/config.go
  8. 83
      internal/configs/node/config_test.go
  9. 298
      internal/configs/sharding/mock/shardingconfig.go
  10. 2
      internal/configs/sharding/shardingconfig.go
  11. 28
      internal/utils/flags_test.go
  12. 38
      internal/utils/utils_test.go
  13. 12
      internal/wallet/configfile.go
  14. 12
      internal/wallet/configfile_test.go
  15. 0
      internal/wallet/test.ini
  16. 11
      node/node.go
  17. 2
      p2p/utils/flags.go
  18. 67
      p2p/utils/flags_test.go
  19. 13
      scripts/node.sh

@ -15,6 +15,7 @@ import (
nodeconfig "github.com/harmony-one/harmony/internal/configs/node" nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/p2p"
p2putils "github.com/harmony-one/harmony/p2p/utils"
badger "github.com/ipfs/go-ds-badger" badger "github.com/ipfs/go-ds-badger"
coredis "github.com/libp2p/go-libp2p-core/discovery" coredis "github.com/libp2p/go-libp2p-core/discovery"
libp2pdis "github.com/libp2p/go-libp2p-discovery" libp2pdis "github.com/libp2p/go-libp2p-discovery"
@ -27,7 +28,7 @@ import (
type Service struct { type Service struct {
Host p2p.Host Host p2p.Host
Rendezvous nodeconfig.GroupID Rendezvous nodeconfig.GroupID
bootnodes utils.AddrList bootnodes p2putils.AddrList
dht *libp2pdht.IpfsDHT dht *libp2pdht.IpfsDHT
cancel context.CancelFunc cancel context.CancelFunc
stopChan chan struct{} stopChan chan struct{}
@ -60,7 +61,7 @@ const (
// points to a persistent database directory to use. // points to a persistent database directory to use.
func New( func New(
h p2p.Host, rendezvous nodeconfig.GroupID, peerChan chan p2p.Peer, h p2p.Host, rendezvous nodeconfig.GroupID, peerChan chan p2p.Peer,
bootnodes utils.AddrList, dataStorePath string, bootnodes p2putils.AddrList, dataStorePath string,
) (*Service, error) { ) (*Service, error) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
var dhtOpts []libp2pdhtopts.Option var dhtOpts []libp2pdhtopts.Option
@ -98,7 +99,7 @@ func New(
// MustNew is a panic-on-error version of New. // MustNew is a panic-on-error version of New.
func MustNew( func MustNew(
h p2p.Host, rendezvous nodeconfig.GroupID, peerChan chan p2p.Peer, h p2p.Host, rendezvous nodeconfig.GroupID, peerChan chan p2p.Peer,
bootnodes utils.AddrList, dataStorePath string, bootnodes p2putils.AddrList, dataStorePath string,
) *Service { ) *Service {
service, err := New(h, rendezvous, peerChan, bootnodes, dataStorePath) service, err := New(h, rendezvous, peerChan, bootnodes, dataStorePath)
if err != nil { if err != nil {
@ -134,7 +135,7 @@ func (s *Service) Init() error {
var wg sync.WaitGroup var wg sync.WaitGroup
if s.bootnodes == nil { if s.bootnodes == nil {
// TODO: should've passed in bootnodes through constructor. // TODO: should've passed in bootnodes through constructor.
s.bootnodes = utils.BootNodes s.bootnodes = p2putils.BootNodes
} }
connected := false connected := false

@ -30,6 +30,7 @@ import (
"github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/p2p"
p2p_host "github.com/harmony-one/harmony/p2p/host" p2p_host "github.com/harmony-one/harmony/p2p/host"
"github.com/harmony-one/harmony/p2p/p2pimpl" "github.com/harmony-one/harmony/p2p/p2pimpl"
p2putils "github.com/harmony-one/harmony/p2p/utils"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
) )
@ -129,7 +130,7 @@ func setUpTXGen() *node.Node {
} }
func main() { func main() {
flag.Var(&utils.BootNodes, "bootnodes", "a list of bootnode multiaddress") flag.Var(&p2putils.BootNodes, "bootnodes", "a list of bootnode multiaddress")
flag.Parse() flag.Parse()
if *versionFlag { if *versionFlag {
printVersion(os.Args[0]) printVersion(os.Args[0])
@ -137,12 +138,12 @@ func main() {
// Logging setup // Logging setup
utils.SetLogContext(*port, *ip) utils.SetLogContext(*port, *ip)
utils.SetLogVerbosity(log.Lvl(*verbosity)) utils.SetLogVerbosity(log.Lvl(*verbosity))
if len(utils.BootNodes) == 0 { if len(p2putils.BootNodes) == 0 {
bootNodeAddrs, err := utils.StringsToAddrs(utils.DefaultBootNodeAddrStrings) bootNodeAddrs, err := p2putils.StringsToAddrs(p2putils.DefaultBootNodeAddrStrings)
if err != nil { if err != nil {
panic(err) panic(err)
} }
utils.BootNodes = bootNodeAddrs p2putils.BootNodes = bootNodeAddrs
} }
// Init with LibP2P enabled, FIXME: (leochen) right now we support only one shard // Init with LibP2P enabled, FIXME: (leochen) right now we support only one shard
setting := Settings{ setting := Settings{

@ -33,10 +33,12 @@ import (
"github.com/harmony-one/harmony/internal/ctxerror" "github.com/harmony-one/harmony/internal/ctxerror"
"github.com/harmony-one/harmony/internal/shardchain" "github.com/harmony-one/harmony/internal/shardchain"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/internal/wallet"
"github.com/harmony-one/harmony/node" "github.com/harmony-one/harmony/node"
"github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/p2p"
p2p_host "github.com/harmony-one/harmony/p2p/host" p2p_host "github.com/harmony-one/harmony/p2p/host"
"github.com/harmony-one/harmony/p2p/p2pimpl" "github.com/harmony-one/harmony/p2p/p2pimpl"
p2putils "github.com/harmony-one/harmony/p2p/utils"
) )
var ( var (
@ -124,7 +126,7 @@ var (
var ( var (
networkType string networkType string
walletProfile *utils.WalletProfile walletProfile *wallet.Profile
ks *keystore.KeyStore ks *keystore.KeyStore
) )
@ -278,7 +280,7 @@ func readProfile(profile string) {
iniBytes = []byte(defaultWalletIni) iniBytes = []byte(defaultWalletIni)
} }
walletProfile, err = utils.ReadWalletProfile(iniBytes, profile) walletProfile, err = wallet.ReadProfile(iniBytes, profile)
if err != nil { if err != nil {
fmt.Printf("Read wallet profile error: %v\nExiting ...\n", err) fmt.Printf("Read wallet profile error: %v\nExiting ...\n", err)
os.Exit(2) os.Exit(2)
@ -287,11 +289,11 @@ func readProfile(profile string) {
// createWalletNode creates wallet server node. // createWalletNode creates wallet server node.
func createWalletNode() *node.Node { func createWalletNode() *node.Node {
bootNodeAddrs, err := utils.StringsToAddrs(walletProfile.Bootnodes) bootNodeAddrs, err := p2putils.StringsToAddrs(walletProfile.Bootnodes)
if err != nil { if err != nil {
panic(err) panic(err)
} }
utils.BootNodes = bootNodeAddrs p2putils.BootNodes = bootNodeAddrs
shardID := 0 shardID := 0
// dummy host for wallet // dummy host for wallet
// TODO: potentially, too many dummy IP may flush out good IP address from our bootnode DHT // TODO: potentially, too many dummy IP may flush out good IP address from our bootnode DHT

@ -27,10 +27,12 @@ import (
"github.com/harmony-one/harmony/internal/ctxerror" "github.com/harmony-one/harmony/internal/ctxerror"
"github.com/harmony-one/harmony/internal/shardchain" "github.com/harmony-one/harmony/internal/shardchain"
"github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/internal/wallet"
"github.com/harmony-one/harmony/node" "github.com/harmony-one/harmony/node"
"github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/p2p"
p2p_host "github.com/harmony-one/harmony/p2p/host" p2p_host "github.com/harmony-one/harmony/p2p/host"
"github.com/harmony-one/harmony/p2p/p2pimpl" "github.com/harmony-one/harmony/p2p/p2pimpl"
p2putils "github.com/harmony-one/harmony/p2p/utils"
) )
var ( var (
@ -72,7 +74,7 @@ var (
) )
var ( var (
walletProfile *utils.WalletProfile walletProfile *wallet.Profile
ks *keystore.KeyStore ks *keystore.KeyStore
) )
@ -162,7 +164,7 @@ func readProfile(profile string) {
iniBytes = []byte(defaultWalletIni) iniBytes = []byte(defaultWalletIni)
} }
walletProfile, err = utils.ReadWalletProfile(iniBytes, profile) walletProfile, err = wallet.ReadProfile(iniBytes, profile)
if err != nil { if err != nil {
fmt.Printf("Read wallet profile error: %v\nExiting ...\n", err) fmt.Printf("Read wallet profile error: %v\nExiting ...\n", err)
os.Exit(2) os.Exit(2)
@ -171,11 +173,11 @@ func readProfile(profile string) {
// createWalletNode creates wallet server node. // createWalletNode creates wallet server node.
func createWalletNode() *node.Node { func createWalletNode() *node.Node {
bootNodeAddrs, err := utils.StringsToAddrs(walletProfile.Bootnodes) bootNodeAddrs, err := p2putils.StringsToAddrs(walletProfile.Bootnodes)
if err != nil { if err != nil {
panic(err) panic(err)
} }
utils.BootNodes = bootNodeAddrs p2putils.BootNodes = bootNodeAddrs
shardID := 0 shardID := 0
// dummy host for wallet // dummy host for wallet
// TODO: potentially, too many dummy IP may flush out good IP address from our bootnode DHT // TODO: potentially, too many dummy IP may flush out good IP address from our bootnode DHT

@ -15,6 +15,8 @@ import (
ethCommon "github.com/ethereum/go-ethereum/common" ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
"github.com/pkg/errors"
"github.com/harmony-one/harmony/api/service/syncing" "github.com/harmony-one/harmony/api/service/syncing"
"github.com/harmony-one/harmony/consensus" "github.com/harmony-one/harmony/consensus"
"github.com/harmony-one/harmony/consensus/quorum" "github.com/harmony-one/harmony/consensus/quorum"
@ -31,6 +33,7 @@ import (
"github.com/harmony-one/harmony/node" "github.com/harmony-one/harmony/node"
"github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/p2p"
"github.com/harmony-one/harmony/p2p/p2pimpl" "github.com/harmony-one/harmony/p2p/p2pimpl"
p2putils "github.com/harmony-one/harmony/p2p/utils"
"github.com/harmony-one/harmony/shard" "github.com/harmony-one/harmony/shard"
) )
@ -48,7 +51,7 @@ var (
) )
func printVersion() { func printVersion() {
fmt.Fprintln(os.Stderr, nodeconfig.GetVersion()) _, _ = fmt.Fprintln(os.Stderr, nodeconfig.GetVersion())
os.Exit(0) os.Exit(0)
} }
@ -85,6 +88,8 @@ var (
// blockPeriod indicates the how long the leader waits to propose a new block. // blockPeriod indicates the how long the leader waits to propose a new block.
blockPeriod = flag.Int("block_period", 8, "how long in second the leader waits to propose a new block.") blockPeriod = flag.Int("block_period", 8, "how long in second the leader waits to propose a new block.")
leaderOverride = flag.Bool("leader_override", false, "true means override the default leader role and acts as validator") leaderOverride = flag.Bool("leader_override", false, "true means override the default leader role and acts as validator")
// staking indicates whether the node is operating in staking mode.
stakingFlag = flag.Bool("staking", false, "whether the node should operate in staking mode")
// shardID indicates the shard ID of this node // shardID indicates the shard ID of this node
shardID = flag.Int("shard_id", -1, "the shard ID of this node") shardID = flag.Int("shard_id", -1, "the shard ID of this node")
enableMemProfiling = flag.Bool("enableMemProfiling", false, "Enable memsize logging.") enableMemProfiling = flag.Bool("enableMemProfiling", false, "Enable memsize logging.")
@ -138,6 +143,9 @@ func initSetup() {
nodeconfig.GetDefaultConfig().Port = *port nodeconfig.GetDefaultConfig().Port = *port
nodeconfig.GetDefaultConfig().IP = *ip nodeconfig.GetDefaultConfig().IP = *ip
// Set sharding schedule
nodeconfig.SetShardingSchedule(shard.Schedule)
// Setup mem profiling. // Setup mem profiling.
memprofiling.GetMemProfiling().Config() memprofiling.GetMemProfiling().Config()
@ -147,12 +155,12 @@ func initSetup() {
// Set up randomization seed. // Set up randomization seed.
rand.Seed(int64(time.Now().Nanosecond())) rand.Seed(int64(time.Now().Nanosecond()))
if len(utils.BootNodes) == 0 { if len(p2putils.BootNodes) == 0 {
bootNodeAddrs, err := utils.StringsToAddrs(utils.DefaultBootNodeAddrStrings) bootNodeAddrs, err := p2putils.StringsToAddrs(p2putils.DefaultBootNodeAddrStrings)
if err != nil { if err != nil {
panic(err) panic(err)
} }
utils.BootNodes = bootNodeAddrs p2putils.BootNodes = bootNodeAddrs
} }
} }
@ -169,47 +177,54 @@ func passphraseForBls() {
} }
passphrase, err := utils.GetPassphraseFromSource(*blsPass) passphrase, err := utils.GetPassphraseFromSource(*blsPass)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "ERROR when reading passphrase file: %v\n", err) _, _ = fmt.Fprintf(os.Stderr, "ERROR when reading passphrase file: %v\n", err)
os.Exit(100) os.Exit(100)
} }
blsPassphrase = passphrase blsPassphrase = passphrase
} }
func setupInitialAccount() (isLeader bool) { func setupLegacyNodeAccount() error {
genesisShardingConfig := shard.Schedule.InstanceForEpoch(big.NewInt(core.GenesisEpoch)) genesisShardingConfig := shard.Schedule.InstanceForEpoch(big.NewInt(core.GenesisEpoch))
pubKey := setupConsensusKey(nodeconfig.GetDefaultConfig()) pubKey := setupConsensusKey(nodeconfig.GetDefaultConfig())
reshardingEpoch := genesisShardingConfig.ReshardingEpoch() reshardingEpoch := genesisShardingConfig.ReshardingEpoch()
// TODO: after staking, what if the FN validator uses the old bls pub keys?
if reshardingEpoch != nil && len(reshardingEpoch) > 0 { if reshardingEpoch != nil && len(reshardingEpoch) > 0 {
for _, epoch := range reshardingEpoch { for _, epoch := range reshardingEpoch {
config := shard.Schedule.InstanceForEpoch(epoch) config := shard.Schedule.InstanceForEpoch(epoch)
isLeader, initialAccount = config.FindAccount(pubKey.SerializeToHexStr()) _, initialAccount = config.FindAccount(pubKey.SerializeToHexStr())
if initialAccount != nil { if initialAccount != nil {
break break
} }
} }
} else { } else {
isLeader, initialAccount = genesisShardingConfig.FindAccount(pubKey.SerializeToHexStr()) _, initialAccount = genesisShardingConfig.FindAccount(pubKey.SerializeToHexStr())
} }
if initialAccount == nil { if initialAccount == nil {
return errors.Errorf("cannot find key %s in table", pubKey.SerializeToHexStr())
}
fmt.Printf("My Genesis Account: %v\n", *initialAccount)
return nil
}
func setupStakingNodeAccount() error {
pubKey := setupConsensusKey(nodeconfig.GetDefaultConfig())
shardID, err := nodeconfig.GetDefaultConfig().ShardIDFromConsensusKey()
if err != nil {
return errors.Wrap(err, "cannot determine shard to join")
}
initialAccount = &genesis.DeployAccount{} initialAccount = &genesis.DeployAccount{}
initialAccount.ShardID = uint32(*shardID) initialAccount.ShardID = shardID
initialAccount.BlsPublicKey = pubKey.SerializeToHexStr() initialAccount.BlsPublicKey = pubKey.SerializeToHexStr()
blsAddressBytes := pubKey.GetAddress() blsAddressBytes := pubKey.GetAddress()
initialAccount.Address = hex.EncodeToString(blsAddressBytes[:]) initialAccount.Address = hex.EncodeToString(blsAddressBytes[:])
} else { return nil
fmt.Printf("My Genesis Account: %v\n", *initialAccount)
}
return isLeader
} }
func setupConsensusKey(nodeConfig *nodeconfig.ConfigType) *bls.PublicKey { func setupConsensusKey(nodeConfig *nodeconfig.ConfigType) *bls.PublicKey {
consensusPriKey, err := blsgen.LoadBlsKeyWithPassPhrase(*blsKeyFile, blsPassphrase) consensusPriKey, err := blsgen.LoadBlsKeyWithPassPhrase(*blsKeyFile, blsPassphrase)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "ERROR when loading bls key, err :%v\n", err) _, _ = fmt.Fprintf(os.Stderr, "ERROR when loading bls key, err :%v\n", err)
os.Exit(100) os.Exit(100)
} }
pubKey := consensusPriKey.GetPublicKey() pubKey := consensusPriKey.GetPublicKey()
@ -223,7 +238,7 @@ func setupConsensusKey(nodeConfig *nodeconfig.ConfigType) *bls.PublicKey {
return pubKey return pubKey
} }
func createGlobalConfig() *nodeconfig.ConfigType { func createGlobalConfig() (*nodeconfig.ConfigType, error) {
var err error var err error
nodeConfig := nodeconfig.GetShardConfig(initialAccount.ShardID) nodeConfig := nodeconfig.GetShardConfig(initialAccount.ShardID)
@ -236,13 +251,7 @@ func createGlobalConfig() *nodeconfig.ConfigType {
// Set network type // Set network type
netType := nodeconfig.NetworkType(*networkType) netType := nodeconfig.NetworkType(*networkType)
switch netType { nodeconfig.SetNetworkType(netType) // sets for both global and shard configs
case nodeconfig.Mainnet, nodeconfig.Testnet, nodeconfig.Pangaea, nodeconfig.Localnet, nodeconfig.Devnet:
nodeconfig.SetNetworkType(netType)
default:
panic(fmt.Sprintf("invalid network type: %s", *networkType))
}
nodeConfig.SetPushgatewayIP(*pushgatewayIP) nodeConfig.SetPushgatewayIP(*pushgatewayIP)
nodeConfig.SetPushgatewayPort(*pushgatewayPort) nodeConfig.SetPushgatewayPort(*pushgatewayPort)
nodeConfig.SetMetricsFlag(*metricsFlag) nodeConfig.SetMetricsFlag(*metricsFlag)
@ -250,22 +259,23 @@ func createGlobalConfig() *nodeconfig.ConfigType {
// P2p private key is used for secure message transfer between p2p nodes. // P2p private key is used for secure message transfer between p2p nodes.
nodeConfig.P2pPriKey, _, err = utils.LoadKeyFromFile(*keyFile) nodeConfig.P2pPriKey, _, err = utils.LoadKeyFromFile(*keyFile)
if err != nil { if err != nil {
panic(err) return nil, errors.Wrapf(err, "cannot load or create P2P key at %#v",
*keyFile)
} }
selfPeer := p2p.Peer{IP: *ip, Port: *port, ConsensusPubKey: nodeConfig.ConsensusPubKey} selfPeer := p2p.Peer{IP: *ip, Port: *port, ConsensusPubKey: nodeConfig.ConsensusPubKey}
myHost, err = p2pimpl.NewHost(&selfPeer, nodeConfig.P2pPriKey) myHost, err = p2pimpl.NewHost(&selfPeer, nodeConfig.P2pPriKey)
if err != nil {
return nil, errors.Wrap(err, "cannot create P2P network host")
}
if *logConn && nodeConfig.GetNetworkType() != nodeconfig.Mainnet { if *logConn && nodeConfig.GetNetworkType() != nodeconfig.Mainnet {
myHost.GetP2PHost().Network().Notify(utils.NewConnLogger(utils.GetLogger())) myHost.GetP2PHost().Network().Notify(utils.NewConnLogger(utils.GetLogger()))
} }
if err != nil {
panic("unable to new host in harmony")
}
nodeConfig.DBDir = *dbDir nodeConfig.DBDir = *dbDir
return nodeConfig return nodeConfig, nil
} }
func setupConsensusAndNode(nodeConfig *nodeconfig.ConfigType) *node.Node { func setupConsensusAndNode(nodeConfig *nodeconfig.ConfigType) *node.Node {
@ -287,7 +297,7 @@ func setupConsensusAndNode(nodeConfig *nodeconfig.ConfigType) *node.Node {
currentConsensus.SelfAddress = common.ParseAddr(initialAccount.Address) currentConsensus.SelfAddress = common.ParseAddr(initialAccount.Address)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Error :%v \n", err) _, _ = fmt.Fprintf(os.Stderr, "Error :%v \n", err)
os.Exit(1) os.Exit(1)
} }
commitDelay, err := time.ParseDuration(*delayCommit) commitDelay, err := time.ParseDuration(*delayCommit)
@ -396,7 +406,7 @@ func setupConsensusAndNode(nodeConfig *nodeconfig.ConfigType) *node.Node {
} }
func main() { func main() {
flag.Var(&utils.BootNodes, "bootnodes", "a list of bootnode multiaddress (delimited by ,)") flag.Var(&p2putils.BootNodes, "bootnodes", "a list of bootnode multiaddress (delimited by ,)")
flag.Parse() flag.Parse()
switch *nodeType { switch *nodeType {
@ -404,7 +414,7 @@ func main() {
case "explorer": case "explorer":
break break
default: default:
fmt.Fprintf(os.Stderr, "Unknown node type: %s\n", *nodeType) _, _ = fmt.Fprintf(os.Stderr, "Unknown node type: %s\n", *nodeType)
os.Exit(1) os.Exit(1)
} }
@ -436,6 +446,9 @@ func main() {
os.Exit(1) os.Exit(1)
} }
shard.Schedule = shardingconfig.NewFixedSchedule(devnetConfig) shard.Schedule = shardingconfig.NewFixedSchedule(devnetConfig)
default:
_, _ = fmt.Fprintf(os.Stderr, "invalid network type: %#v\n", *networkType)
os.Exit(2)
} }
initSetup() initSetup()
@ -446,8 +459,21 @@ func main() {
} }
if *nodeType == "validator" { if *nodeType == "validator" {
setupInitialAccount() var err error
if *stakingFlag {
err = setupStakingNodeAccount()
} else {
err = setupLegacyNodeAccount()
}
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "cannot set up node account: %s\n", err)
os.Exit(1)
} }
}
fmt.Printf("%s mode; node key %s -> shard %d\n",
map[bool]string{false: "Legacy", true: "Staking"}[*stakingFlag],
nodeconfig.GetDefaultConfig().ConsensusPubKey.SerializeToHexStr(),
initialAccount.ShardID)
if *nodeType != "validator" && *shardID >= 0 { if *nodeType != "validator" && *shardID >= 0 {
utils.Logger().Info(). utils.Logger().Info().
@ -457,7 +483,11 @@ func main() {
initialAccount.ShardID = uint32(*shardID) initialAccount.ShardID = uint32(*shardID)
} }
nodeConfig := createGlobalConfig() nodeConfig, err := createGlobalConfig()
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "ERROR cannot configure node: %s\n", err)
os.Exit(1)
}
currentNode := setupConsensusAndNode(nodeConfig) currentNode := setupConsensusAndNode(nodeConfig)
//setup state syncing and beacon syncing frequency //setup state syncing and beacon syncing frequency
currentNode.SetSyncFreq(*syncFreq) currentNode.SetSyncFreq(*syncFreq)

@ -428,7 +428,7 @@ func ReadShardState(
if err2 != nil { if err2 != nil {
return nil, ctxerror.New("cannot decode sharding state", return nil, ctxerror.New("cannot decode sharding state",
"epoch", epoch, "epoch", epoch,
).WithCause(err) ).WithCause(err2)
} }
return ss, nil return ss, nil
} }

@ -5,12 +5,17 @@ package nodeconfig
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"errors"
"fmt" "fmt"
"math/big"
"sync" "sync"
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
p2p_crypto "github.com/libp2p/go-libp2p-crypto" p2p_crypto "github.com/libp2p/go-libp2p-crypto"
"github.com/pkg/errors"
shardingconfig "github.com/harmony-one/harmony/internal/configs/sharding"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/shard"
) )
// Role defines a role of a node. // Role defines a role of a node.
@ -70,7 +75,7 @@ type ConfigType struct {
client GroupID // the client group ID of the shard client GroupID // the client group ID of the shard
isClient bool // whether this node is a client node, such as wallet isClient bool // whether this node is a client node, such as wallet
isBeacon bool // whether this node is beacon node doing consensus or not isBeacon bool // whether this node is beacon node doing consensus or not
ShardID uint32 // ShardID of this node; TODO ek – reviisit when resharding ShardID uint32 // ShardID of this node; TODO ek – revisit when resharding
role Role // Role of the node role Role // Role of the node
Port string // Port of the node. Port string // Port of the node.
IP string // IP of the node. IP string // IP of the node.
@ -88,6 +93,8 @@ type ConfigType struct {
DBDir string DBDir string
networkType NetworkType networkType NetworkType
shardingSchedule shardingconfig.Schedule
} }
// configs is a list of node configuration. // configs is a list of node configuration.
@ -97,31 +104,23 @@ var shardConfigs []ConfigType
var defaultConfig ConfigType var defaultConfig ConfigType
var onceForConfigs sync.Once var onceForConfigs sync.Once
// GetShardConfig return the shard's ConfigType variable func ensureShardConfigs() {
func GetShardConfig(shardID uint32) *ConfigType {
onceForConfigs.Do(func() { onceForConfigs.Do(func() {
shardConfigs = make([]ConfigType, MaxShards) shardConfigs = make([]ConfigType, MaxShards)
for i := range shardConfigs { for i := range shardConfigs {
shardConfigs[i].ShardID = uint32(i) shardConfigs[i].ShardID = uint32(i)
} }
}) })
if int(shardID) >= cap(shardConfigs) {
return nil
}
return &shardConfigs[shardID]
} }
// SetConfigs set ConfigType in the right index. // GetShardConfig return the shard's ConfigType variable
func SetConfigs(config ConfigType, shardID uint32) error { func GetShardConfig(shardID uint32) *ConfigType {
onceForConfigs.Do(func() { ensureShardConfigs()
shardConfigs = make([]ConfigType, MaxShards)
})
if int(shardID) >= cap(shardConfigs) { if int(shardID) >= cap(shardConfigs) {
return errors.New("Failed to set ConfigType")
}
shardConfigs[int(shardID)] = config
return nil return nil
} }
return &shardConfigs[shardID]
}
// GetDefaultConfig returns default config. // GetDefaultConfig returns default config.
func GetDefaultConfig() *ConfigType { func GetDefaultConfig() *ConfigType {
@ -224,6 +223,7 @@ func (conf *ConfigType) Role() Role {
// SetNetworkType set the networkType // SetNetworkType set the networkType
func SetNetworkType(networkType NetworkType) { func SetNetworkType(networkType NetworkType) {
ensureShardConfigs()
defaultConfig.networkType = networkType defaultConfig.networkType = networkType
for i := range shardConfigs { for i := range shardConfigs {
shardConfigs[i].networkType = networkType shardConfigs[i].networkType = networkType
@ -254,3 +254,49 @@ func SetPublicRPC(v bool) {
func GetPublicRPC() bool { func GetPublicRPC() bool {
return publicRPC return publicRPC
} }
// ShardingSchedule returns the sharding schedule for this node config.
func (conf *ConfigType) ShardingSchedule() shardingconfig.Schedule {
return conf.shardingSchedule
}
// SetShardingSchedule sets the sharding schedule for this node config.
func (conf *ConfigType) SetShardingSchedule(schedule shardingconfig.Schedule) {
conf.shardingSchedule = schedule
}
// SetShardingSchedule sets the sharding schedule for all config instances.
func SetShardingSchedule(schedule shardingconfig.Schedule) {
ensureShardConfigs()
defaultConfig.SetShardingSchedule(schedule)
for _, config := range shardConfigs {
config.SetShardingSchedule(schedule)
}
}
// ShardIDFromConsensusKey returns the shard ID statically determined from the
// consensus key.
func (conf *ConfigType) ShardIDFromConsensusKey() (uint32, error) {
var pubKey shard.BlsPublicKey
if err := pubKey.FromLibBLSPublicKey(conf.ConsensusPubKey); err != nil {
return 0, errors.Wrapf(err,
"cannot convert libbls public key %s to internal form",
conf.ConsensusPubKey.SerializeToHexStr())
}
epoch := conf.networkType.ChainConfig().StakingEpoch
numShards := conf.shardingSchedule.InstanceForEpoch(epoch).NumShards()
shardID := new(big.Int).Mod(pubKey.Big(), big.NewInt(int64(numShards)))
return uint32(shardID.Uint64()), nil
}
// ChainConfig returns the chain configuration for the network type.
func (t NetworkType) ChainConfig() params.ChainConfig {
switch t {
case Mainnet:
return *params.MainnetChainConfig
case Pangaea:
return *params.PangaeaChainConfig
default:
return *params.TestnetChainConfig
}
}

@ -1,7 +1,14 @@
package nodeconfig package nodeconfig
import ( import (
"math/big"
"testing" "testing"
"github.com/golang/mock/gomock"
"github.com/harmony-one/bls/ffi/go/bls"
mock_shardingconfig "github.com/harmony-one/harmony/internal/configs/sharding/mock"
"github.com/harmony-one/harmony/internal/params"
) )
func TestNodeConfigSingleton(t *testing.T) { func TestNodeConfigSingleton(t *testing.T) {
@ -47,3 +54,79 @@ func TestNodeConfigMultiple(t *testing.T) {
t.Errorf("expecting false, got: %v", e.IsClient()) t.Errorf("expecting false, got: %v", e.IsClient())
} }
} }
func blsPubKeyFromHex(hex string) *bls.PublicKey {
var k bls.PublicKey
if err := k.DeserializeHexStr(hex); err != nil {
panic(err)
}
return &k
}
func TestConfigType_ShardIDFromConsensusKey(t *testing.T) {
type fields struct {
ConsensusPubKey *bls.PublicKey
networkType NetworkType
}
tests := []struct {
name string
fields fields
epoch *big.Int
shards uint32
want uint32
}{
{
"Mainnet",
fields{
blsPubKeyFromHex("ca23704be46ce9c4704681ac9c08ddc644f1858a5c28ce236e1b5d9dee67c1f5a28075b5ef089adeffa8a372c1762007"),
"mainnet",
},
params.MainnetChainConfig.StakingEpoch,
4,
3,
},
{
"Testnet",
fields{
blsPubKeyFromHex("e7f54994bc5c02edeeb178ce2d34db276a893bab5c59ac3d7eb9f077c893f9e31171de6236ba0e21be415d8631e45b91"),
"testnet",
},
params.TestnetChainConfig.StakingEpoch,
3,
1,
},
{
"Devnet",
fields{
blsPubKeyFromHex("e7f54994bc5c02edeeb178ce2d34db276a893bab5c59ac3d7eb9f077c893f9e31171de6236ba0e21be415d8631e45b91"),
"devnet",
},
params.TestnetChainConfig.StakingEpoch,
2,
1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mc := gomock.NewController(t)
defer mc.Finish()
instance := mock_shardingconfig.NewMockInstance(mc)
instance.EXPECT().NumShards().Return(tt.shards)
schedule := mock_shardingconfig.NewMockSchedule(mc)
schedule.EXPECT().InstanceForEpoch(tt.epoch).Return(instance)
conf := &ConfigType{
ConsensusPubKey: tt.fields.ConsensusPubKey,
networkType: tt.fields.networkType,
shardingSchedule: schedule,
}
got, err := conf.ShardIDFromConsensusKey()
if err != nil {
t.Errorf("ShardIDFromConsensusKey() error = %v", err)
return
}
if got != tt.want {
t.Errorf("ShardIDFromConsensusKey() got = %v, want %v", got, tt.want)
}
})
}
}

@ -0,0 +1,298 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: shardingconfig.go
// Package mock_shardingconfig is a generated GoMock package.
package mock_shardingconfig
import (
gomock "github.com/golang/mock/gomock"
sharding "github.com/harmony-one/harmony/internal/configs/sharding"
genesis "github.com/harmony-one/harmony/internal/genesis"
big "math/big"
reflect "reflect"
)
// MockSchedule is a mock of Schedule interface
type MockSchedule struct {
ctrl *gomock.Controller
recorder *MockScheduleMockRecorder
}
// MockScheduleMockRecorder is the mock recorder for MockSchedule
type MockScheduleMockRecorder struct {
mock *MockSchedule
}
// NewMockSchedule creates a new mock instance
func NewMockSchedule(ctrl *gomock.Controller) *MockSchedule {
mock := &MockSchedule{ctrl: ctrl}
mock.recorder = &MockScheduleMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockSchedule) EXPECT() *MockScheduleMockRecorder {
return m.recorder
}
// InstanceForEpoch mocks base method
func (m *MockSchedule) InstanceForEpoch(epoch *big.Int) sharding.Instance {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "InstanceForEpoch", epoch)
ret0, _ := ret[0].(sharding.Instance)
return ret0
}
// InstanceForEpoch indicates an expected call of InstanceForEpoch
func (mr *MockScheduleMockRecorder) InstanceForEpoch(epoch interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstanceForEpoch", reflect.TypeOf((*MockSchedule)(nil).InstanceForEpoch), epoch)
}
// BlocksPerEpoch mocks base method
func (m *MockSchedule) BlocksPerEpoch() uint64 {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "BlocksPerEpoch")
ret0, _ := ret[0].(uint64)
return ret0
}
// BlocksPerEpoch indicates an expected call of BlocksPerEpoch
func (mr *MockScheduleMockRecorder) BlocksPerEpoch() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlocksPerEpoch", reflect.TypeOf((*MockSchedule)(nil).BlocksPerEpoch))
}
// CalcEpochNumber mocks base method
func (m *MockSchedule) CalcEpochNumber(blockNum uint64) *big.Int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "CalcEpochNumber", blockNum)
ret0, _ := ret[0].(*big.Int)
return ret0
}
// CalcEpochNumber indicates an expected call of CalcEpochNumber
func (mr *MockScheduleMockRecorder) CalcEpochNumber(blockNum interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CalcEpochNumber", reflect.TypeOf((*MockSchedule)(nil).CalcEpochNumber), blockNum)
}
// IsLastBlock mocks base method
func (m *MockSchedule) IsLastBlock(blockNum uint64) bool {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "IsLastBlock", blockNum)
ret0, _ := ret[0].(bool)
return ret0
}
// IsLastBlock indicates an expected call of IsLastBlock
func (mr *MockScheduleMockRecorder) IsLastBlock(blockNum interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsLastBlock", reflect.TypeOf((*MockSchedule)(nil).IsLastBlock), blockNum)
}
// EpochLastBlock mocks base method
func (m *MockSchedule) EpochLastBlock(epochNum uint64) uint64 {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "EpochLastBlock", epochNum)
ret0, _ := ret[0].(uint64)
return ret0
}
// EpochLastBlock indicates an expected call of EpochLastBlock
func (mr *MockScheduleMockRecorder) EpochLastBlock(epochNum interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EpochLastBlock", reflect.TypeOf((*MockSchedule)(nil).EpochLastBlock), epochNum)
}
// VdfDifficulty mocks base method
func (m *MockSchedule) VdfDifficulty() int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "VdfDifficulty")
ret0, _ := ret[0].(int)
return ret0
}
// VdfDifficulty indicates an expected call of VdfDifficulty
func (mr *MockScheduleMockRecorder) VdfDifficulty() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VdfDifficulty", reflect.TypeOf((*MockSchedule)(nil).VdfDifficulty))
}
// ConsensusRatio mocks base method
func (m *MockSchedule) ConsensusRatio() float64 {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ConsensusRatio")
ret0, _ := ret[0].(float64)
return ret0
}
// ConsensusRatio indicates an expected call of ConsensusRatio
func (mr *MockScheduleMockRecorder) ConsensusRatio() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConsensusRatio", reflect.TypeOf((*MockSchedule)(nil).ConsensusRatio))
}
// RandomnessStartingEpoch mocks base method
func (m *MockSchedule) RandomnessStartingEpoch() uint64 {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "RandomnessStartingEpoch")
ret0, _ := ret[0].(uint64)
return ret0
}
// RandomnessStartingEpoch indicates an expected call of RandomnessStartingEpoch
func (mr *MockScheduleMockRecorder) RandomnessStartingEpoch() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RandomnessStartingEpoch", reflect.TypeOf((*MockSchedule)(nil).RandomnessStartingEpoch))
}
// GetNetworkID mocks base method
func (m *MockSchedule) GetNetworkID() sharding.NetworkID {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetNetworkID")
ret0, _ := ret[0].(sharding.NetworkID)
return ret0
}
// GetNetworkID indicates an expected call of GetNetworkID
func (mr *MockScheduleMockRecorder) GetNetworkID() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetworkID", reflect.TypeOf((*MockSchedule)(nil).GetNetworkID))
}
// GetShardingStructure mocks base method
func (m *MockSchedule) GetShardingStructure(arg0, arg1 int) []map[string]interface{} {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetShardingStructure", arg0, arg1)
ret0, _ := ret[0].([]map[string]interface{})
return ret0
}
// GetShardingStructure indicates an expected call of GetShardingStructure
func (mr *MockScheduleMockRecorder) GetShardingStructure(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetShardingStructure", reflect.TypeOf((*MockSchedule)(nil).GetShardingStructure), arg0, arg1)
}
// MockInstance is a mock of Instance interface
type MockInstance struct {
ctrl *gomock.Controller
recorder *MockInstanceMockRecorder
}
// MockInstanceMockRecorder is the mock recorder for MockInstance
type MockInstanceMockRecorder struct {
mock *MockInstance
}
// NewMockInstance creates a new mock instance
func NewMockInstance(ctrl *gomock.Controller) *MockInstance {
mock := &MockInstance{ctrl: ctrl}
mock.recorder = &MockInstanceMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockInstance) EXPECT() *MockInstanceMockRecorder {
return m.recorder
}
// NumShards mocks base method
func (m *MockInstance) NumShards() uint32 {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NumShards")
ret0, _ := ret[0].(uint32)
return ret0
}
// NumShards indicates an expected call of NumShards
func (mr *MockInstanceMockRecorder) NumShards() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NumShards", reflect.TypeOf((*MockInstance)(nil).NumShards))
}
// NumNodesPerShard mocks base method
func (m *MockInstance) NumNodesPerShard() int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NumNodesPerShard")
ret0, _ := ret[0].(int)
return ret0
}
// NumNodesPerShard indicates an expected call of NumNodesPerShard
func (mr *MockInstanceMockRecorder) NumNodesPerShard() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NumNodesPerShard", reflect.TypeOf((*MockInstance)(nil).NumNodesPerShard))
}
// NumHarmonyOperatedNodesPerShard mocks base method
func (m *MockInstance) NumHarmonyOperatedNodesPerShard() int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NumHarmonyOperatedNodesPerShard")
ret0, _ := ret[0].(int)
return ret0
}
// NumHarmonyOperatedNodesPerShard indicates an expected call of NumHarmonyOperatedNodesPerShard
func (mr *MockInstanceMockRecorder) NumHarmonyOperatedNodesPerShard() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NumHarmonyOperatedNodesPerShard", reflect.TypeOf((*MockInstance)(nil).NumHarmonyOperatedNodesPerShard))
}
// HmyAccounts mocks base method
func (m *MockInstance) HmyAccounts() []genesis.DeployAccount {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "HmyAccounts")
ret0, _ := ret[0].([]genesis.DeployAccount)
return ret0
}
// HmyAccounts indicates an expected call of HmyAccounts
func (mr *MockInstanceMockRecorder) HmyAccounts() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HmyAccounts", reflect.TypeOf((*MockInstance)(nil).HmyAccounts))
}
// FnAccounts mocks base method
func (m *MockInstance) FnAccounts() []genesis.DeployAccount {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FnAccounts")
ret0, _ := ret[0].([]genesis.DeployAccount)
return ret0
}
// FnAccounts indicates an expected call of FnAccounts
func (mr *MockInstanceMockRecorder) FnAccounts() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FnAccounts", reflect.TypeOf((*MockInstance)(nil).FnAccounts))
}
// FindAccount mocks base method
func (m *MockInstance) FindAccount(blsPubKey string) (bool, *genesis.DeployAccount) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FindAccount", blsPubKey)
ret0, _ := ret[0].(bool)
ret1, _ := ret[1].(*genesis.DeployAccount)
return ret0, ret1
}
// FindAccount indicates an expected call of FindAccount
func (mr *MockInstanceMockRecorder) FindAccount(blsPubKey interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindAccount", reflect.TypeOf((*MockInstance)(nil).FindAccount), blsPubKey)
}
// ReshardingEpoch mocks base method
func (m *MockInstance) ReshardingEpoch() []*big.Int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ReshardingEpoch")
ret0, _ := ret[0].([]*big.Int)
return ret0
}
// ReshardingEpoch indicates an expected call of ReshardingEpoch
func (mr *MockInstanceMockRecorder) ReshardingEpoch() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReshardingEpoch", reflect.TypeOf((*MockInstance)(nil).ReshardingEpoch))
}

@ -9,6 +9,8 @@ import (
"github.com/harmony-one/harmony/internal/genesis" "github.com/harmony-one/harmony/internal/genesis"
) )
//go:generate mockgen -source=shardingconfig.go -destination=mock/shardingconfig.go
// Schedule returns the sharding configuration instance for the given // Schedule returns the sharding configuration instance for the given
// epoch. // epoch.
type Schedule interface { type Schedule interface {

@ -1,28 +0,0 @@
package utils
import (
"fmt"
"testing"
)
func TestStringsToAddrs(t *testing.T) {
bn, err := StringsToAddrs(DefaultBootNodeAddrStrings)
if err != nil {
t.Fatalf("unable to convert string to addresses: %v", err)
}
if len(bn) == 0 {
t.Fatalf("should have more than one multiaddress returned")
}
}
func TestAddrListFunc(t *testing.T) {
addr := new(AddrList)
err := addr.Set("/ip4/127.0.0.1/tcp/9999/p2p/QmayB8NwxmfGE4Usb4H61M8uwbfc7LRbmXb3ChseJgbVuf,/ip4/127.0.0.1/tcp/9877/p2p/QmS374uzJ9yEEoWcEQ6JcbSUaVUj29SKakcmVvr3HVAjKP")
if err != nil || len(*addr) < 2 {
t.Fatalf("unable to set addr list")
}
s := fmt.Sprintf("addr: %s\n", addr)
if len(s) == 0 {
t.Fatalf("unable to print AddrList")
}
}

@ -3,10 +3,8 @@ package utils
import ( import (
"net" "net"
"os" "os"
"reflect"
"testing" "testing"
"github.com/harmony-one/harmony/p2p"
crypto "github.com/libp2p/go-libp2p-crypto" crypto "github.com/libp2p/go-libp2p-crypto"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -168,39 +166,3 @@ func TestIsPrivateIP(t *testing.T) {
} }
} }
} }
func TestStringsToPeers(t *testing.T) {
tests := []struct {
input string
expected []p2p.Peer
}{
{
"127.0.0.1:9000,192.168.192.1:8888,54.32.12.3:9898",
[]p2p.Peer{
{IP: "127.0.0.1", Port: "9000"},
{IP: "192.168.192.1", Port: "8888"},
{IP: "54.32.12.3", Port: "9898"},
},
},
{
"a:b,xx:XX,hello:world",
[]p2p.Peer{
{IP: "a", Port: "b"},
{IP: "xx", Port: "XX"},
{IP: "hello", Port: "world"},
},
},
}
for _, test := range tests {
peers := StringsToPeers(test.input)
if len(peers) != 3 {
t.Errorf("StringsToPeers failure")
}
for i, p := range peers {
if !reflect.DeepEqual(p, test.expected[i]) {
t.Errorf("StringToPeers: expected: %v, got: %v", test.expected[i], p)
}
}
}
}

@ -1,4 +1,4 @@
package utils package wallet
// this module in utils handles the ini file read/write // this module in utils handles the ini file read/write
import ( import (
@ -12,8 +12,8 @@ import (
"github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/p2p"
) )
// WalletProfile contains a section and key value pair map // Profile contains a section and key value pair map
type WalletProfile struct { type Profile struct {
Profile string Profile string
ChainID string ChainID string
Bootnodes []string Bootnodes []string
@ -22,13 +22,13 @@ type WalletProfile struct {
Network string Network string
} }
// ReadWalletProfile reads an ini file and return WalletProfile // ReadProfile reads an ini file and return Profile
func ReadWalletProfile(iniBytes []byte, profile string) (*WalletProfile, error) { func ReadProfile(iniBytes []byte, profile string) (*Profile, error) {
cfg, err := ini.ShadowLoad(iniBytes) cfg, err := ini.ShadowLoad(iniBytes)
if err != nil { if err != nil {
return nil, err return nil, err
} }
config := new(WalletProfile) config := new(Profile)
config.Profile = profile config.Profile = profile
// get the profile section // get the profile section

@ -1,4 +1,4 @@
package utils package wallet
import ( import (
"io/ioutil" "io/ioutil"
@ -10,7 +10,7 @@ import (
) )
func TestReadWalletProfile(t *testing.T) { func TestReadWalletProfile(t *testing.T) {
config := []*WalletProfile{ config := []*Profile{
{ {
Profile: "default", Profile: "default",
ChainID: params.MainnetChainID.String(), ChainID: params.MainnetChainID.String(),
@ -106,16 +106,16 @@ func TestReadWalletProfile(t *testing.T) {
t.Fatalf("Failed to read test.ini: %v", err) t.Fatalf("Failed to read test.ini: %v", err)
} }
config1, err := ReadWalletProfile(testIniBytes, "default") config1, err := ReadProfile(testIniBytes, "default")
if err != nil { if err != nil {
t.Fatalf("ReadWalletProfile Error: %v", err) t.Fatalf("ReadProfile Error: %v", err)
} }
if !reflect.DeepEqual(config[0], config1) { if !reflect.DeepEqual(config[0], config1) {
t.Errorf("Got: %v\nExpect: %v\n", config1, config[0]) t.Errorf("Got: %v\nExpect: %v\n", config1, config[0])
} }
config2, err := ReadWalletProfile(testIniBytes, "testnet") config2, err := ReadProfile(testIniBytes, "testnet")
if err != nil { if err != nil {
t.Fatalf("ReadWalletProfile Error: %v", err) t.Fatalf("ReadProfile Error: %v", err)
} }
if !reflect.DeepEqual(config[1], config2) { if !reflect.DeepEqual(config[1], config2) {
t.Errorf("Got: %v\nExpect: %v\n", config2, config[1]) t.Errorf("Got: %v\nExpect: %v\n", config2, config[1])

@ -407,13 +407,8 @@ func New(host p2p.Host, consensusObj *consensus.Consensus,
node.SelfPeer = host.GetSelfPeer() node.SelfPeer = host.GetSelfPeer()
} }
chainConfig := *params.TestnetChainConfig networkType := node.NodeConfig.GetNetworkType()
switch node.NodeConfig.GetNetworkType() { chainConfig := networkType.ChainConfig()
case nodeconfig.Mainnet:
chainConfig = *params.MainnetChainConfig
case nodeconfig.Pangaea:
chainConfig = *params.PangaeaChainConfig
}
node.chainConfig = chainConfig node.chainConfig = chainConfig
collection := shardchain.NewCollection( collection := shardchain.NewCollection(
@ -457,7 +452,7 @@ func New(host p2p.Host, consensusObj *consensus.Consensus,
node.Consensus.SetBlockNum(blockchain.CurrentBlock().NumberU64() + 1) node.Consensus.SetBlockNum(blockchain.CurrentBlock().NumberU64() + 1)
// Add Faucet contract to all shards, so that on testnet, we can demo wallet in explorer // Add Faucet contract to all shards, so that on testnet, we can demo wallet in explorer
if node.NodeConfig.GetNetworkType() != nodeconfig.Mainnet { if networkType != nodeconfig.Mainnet {
if node.isFirstTime { if node.isFirstTime {
// Setup one time smart contracts // Setup one time smart contracts
node.AddFaucetContractToPendingTransactions() node.AddFaucetContractToPendingTransactions()

@ -1,4 +1,4 @@
package utils package p2putils
import ( import (
"fmt" "fmt"

@ -0,0 +1,67 @@
package p2putils
import (
"fmt"
"reflect"
"testing"
"github.com/harmony-one/harmony/p2p"
)
func TestStringsToAddrs(t *testing.T) {
bn, err := StringsToAddrs(DefaultBootNodeAddrStrings)
if err != nil {
t.Fatalf("unable to convert string to addresses: %v", err)
}
if len(bn) == 0 {
t.Fatalf("should have more than one multiaddress returned")
}
}
func TestAddrListFunc(t *testing.T) {
addr := new(AddrList)
err := addr.Set("/ip4/127.0.0.1/tcp/9999/p2p/QmayB8NwxmfGE4Usb4H61M8uwbfc7LRbmXb3ChseJgbVuf,/ip4/127.0.0.1/tcp/9877/p2p/QmS374uzJ9yEEoWcEQ6JcbSUaVUj29SKakcmVvr3HVAjKP")
if err != nil || len(*addr) < 2 {
t.Fatalf("unable to set addr list")
}
s := fmt.Sprintf("addr: %s\n", addr)
if len(s) == 0 {
t.Fatalf("unable to print AddrList")
}
}
func TestStringsToPeers(t *testing.T) {
tests := []struct {
input string
expected []p2p.Peer
}{
{
"127.0.0.1:9000,192.168.192.1:8888,54.32.12.3:9898",
[]p2p.Peer{
{IP: "127.0.0.1", Port: "9000"},
{IP: "192.168.192.1", Port: "8888"},
{IP: "54.32.12.3", Port: "9898"},
},
},
{
"a:b,xx:XX,hello:world",
[]p2p.Peer{
{IP: "a", Port: "b"},
{IP: "xx", Port: "XX"},
{IP: "hello", Port: "world"},
},
},
}
for _, test := range tests {
peers := StringsToPeers(test.input)
if len(peers) != 3 {
t.Errorf("StringsToPeers failure")
}
for i, p := range peers {
if !reflect.DeepEqual(p, test.expected[i]) {
t.Errorf("StringToPeers: expected: %v, got: %v", test.expected[i], p)
}
}
}
}

@ -116,6 +116,8 @@ usage: ${progname} [-1ch] [-k KEYFILE]
-P enable public rpc end point (default:off) -P enable public rpc end point (default:off)
-v print out the version of the node.sh -v print out the version of the node.sh
-V print out the version of the Harmony binary -V print out the version of the Harmony binary
-z run in staking mode
-y run in legacy, foundational-node mode (default)
examples: examples:
@ -149,7 +151,7 @@ BUCKET=pub.harmony.one
OS=$(uname -s) OS=$(uname -s)
unset start_clean loop run_as_root blspass do_not_download download_only metrics network node_type shard_id download_harmony_db db_file_to_dl unset start_clean loop run_as_root blspass do_not_download download_only metrics network node_type shard_id download_harmony_db db_file_to_dl
unset upgrade_rel public_rpc unset upgrade_rel public_rpc staking_mode
start_clean=false start_clean=false
loop=true loop=true
run_as_root=true run_as_root=true
@ -161,11 +163,12 @@ node_type=validator
shard_id=1 shard_id=1
download_harmony_db=false download_harmony_db=false
public_rpc=false public_rpc=false
staking_mode=false
${BLSKEYFILE=} ${BLSKEYFILE=}
unset OPTIND OPTARG opt unset OPTIND OPTARG opt
OPTIND=1 OPTIND=1
while getopts :1chk:sSp:dDmN:tT:i:ba:U:PvV opt while getopts :1chk:sSp:dDmN:tT:i:ba:U:PvVyz opt
do do
case "${opt}" in case "${opt}" in
'?') usage "unrecognized option -${OPTARG}";; '?') usage "unrecognized option -${OPTARG}";;
@ -192,6 +195,8 @@ do
exit 0 ;; exit 0 ;;
V) LD_LIBRARY_PATH=. ./harmony -version V) LD_LIBRARY_PATH=. ./harmony -version
exit 0 ;; exit 0 ;;
z) staking_mode=true;;
y) staking_mode=false;;
*) err 70 "unhandled option -${OPTARG}";; # EX_SOFTWARE *) err 70 "unhandled option -${OPTARG}";; # EX_SOFTWARE
esac esac
done done
@ -659,6 +664,10 @@ do
args+=( args+=(
-shard_id="${shard_id}" -shard_id="${shard_id}"
) )
if ${staking_mode}
then
args+=(-staking="${staking_mode}")
fi
;; ;;
esac esac
;; ;;

Loading…
Cancel
Save