diff --git a/api/service/networkinfo/service.go b/api/service/networkinfo/service.go index 4fab2891f..e09c34d0a 100644 --- a/api/service/networkinfo/service.go +++ b/api/service/networkinfo/service.go @@ -15,6 +15,7 @@ import ( nodeconfig "github.com/harmony-one/harmony/internal/configs/node" "github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/p2p" + p2putils "github.com/harmony-one/harmony/p2p/utils" badger "github.com/ipfs/go-ds-badger" coredis "github.com/libp2p/go-libp2p-core/discovery" libp2pdis "github.com/libp2p/go-libp2p-discovery" @@ -27,7 +28,7 @@ import ( type Service struct { Host p2p.Host Rendezvous nodeconfig.GroupID - bootnodes utils.AddrList + bootnodes p2putils.AddrList dht *libp2pdht.IpfsDHT cancel context.CancelFunc stopChan chan struct{} @@ -60,7 +61,7 @@ const ( // points to a persistent database directory to use. func New( h p2p.Host, rendezvous nodeconfig.GroupID, peerChan chan p2p.Peer, - bootnodes utils.AddrList, dataStorePath string, + bootnodes p2putils.AddrList, dataStorePath string, ) (*Service, error) { ctx, cancel := context.WithCancel(context.Background()) var dhtOpts []libp2pdhtopts.Option @@ -98,7 +99,7 @@ func New( // MustNew is a panic-on-error version of New. func MustNew( h p2p.Host, rendezvous nodeconfig.GroupID, peerChan chan p2p.Peer, - bootnodes utils.AddrList, dataStorePath string, + bootnodes p2putils.AddrList, dataStorePath string, ) *Service { service, err := New(h, rendezvous, peerChan, bootnodes, dataStorePath) if err != nil { @@ -134,7 +135,7 @@ func (s *Service) Init() error { var wg sync.WaitGroup if s.bootnodes == nil { // TODO: should've passed in bootnodes through constructor. - s.bootnodes = utils.BootNodes + s.bootnodes = p2putils.BootNodes } connected := false diff --git a/cmd/client/txgen/main.go b/cmd/client/txgen/main.go index 3bd00f460..ea30eac66 100644 --- a/cmd/client/txgen/main.go +++ b/cmd/client/txgen/main.go @@ -30,6 +30,7 @@ import ( "github.com/harmony-one/harmony/p2p" p2p_host "github.com/harmony-one/harmony/p2p/host" "github.com/harmony-one/harmony/p2p/p2pimpl" + p2putils "github.com/harmony-one/harmony/p2p/utils" "github.com/harmony-one/harmony/shard" ) @@ -129,7 +130,7 @@ func setUpTXGen() *node.Node { } func main() { - flag.Var(&utils.BootNodes, "bootnodes", "a list of bootnode multiaddress") + flag.Var(&p2putils.BootNodes, "bootnodes", "a list of bootnode multiaddress") flag.Parse() if *versionFlag { printVersion(os.Args[0]) @@ -137,12 +138,12 @@ func main() { // Logging setup utils.SetLogContext(*port, *ip) utils.SetLogVerbosity(log.Lvl(*verbosity)) - if len(utils.BootNodes) == 0 { - bootNodeAddrs, err := utils.StringsToAddrs(utils.DefaultBootNodeAddrStrings) + if len(p2putils.BootNodes) == 0 { + bootNodeAddrs, err := p2putils.StringsToAddrs(p2putils.DefaultBootNodeAddrStrings) if err != nil { panic(err) } - utils.BootNodes = bootNodeAddrs + p2putils.BootNodes = bootNodeAddrs } // Init with LibP2P enabled, FIXME: (leochen) right now we support only one shard setting := Settings{ diff --git a/cmd/client/wallet/main.go b/cmd/client/wallet/main.go index a639f64c8..4fe6170ec 100644 --- a/cmd/client/wallet/main.go +++ b/cmd/client/wallet/main.go @@ -33,10 +33,12 @@ import ( "github.com/harmony-one/harmony/internal/ctxerror" "github.com/harmony-one/harmony/internal/shardchain" "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/p2p" p2p_host "github.com/harmony-one/harmony/p2p/host" "github.com/harmony-one/harmony/p2p/p2pimpl" + p2putils "github.com/harmony-one/harmony/p2p/utils" ) var ( @@ -124,7 +126,7 @@ var ( var ( networkType string - walletProfile *utils.WalletProfile + walletProfile *wallet.Profile ks *keystore.KeyStore ) @@ -278,7 +280,7 @@ func readProfile(profile string) { iniBytes = []byte(defaultWalletIni) } - walletProfile, err = utils.ReadWalletProfile(iniBytes, profile) + walletProfile, err = wallet.ReadProfile(iniBytes, profile) if err != nil { fmt.Printf("Read wallet profile error: %v\nExiting ...\n", err) os.Exit(2) @@ -287,11 +289,11 @@ func readProfile(profile string) { // createWalletNode creates wallet server node. func createWalletNode() *node.Node { - bootNodeAddrs, err := utils.StringsToAddrs(walletProfile.Bootnodes) + bootNodeAddrs, err := p2putils.StringsToAddrs(walletProfile.Bootnodes) if err != nil { panic(err) } - utils.BootNodes = bootNodeAddrs + p2putils.BootNodes = bootNodeAddrs shardID := 0 // dummy host for wallet // TODO: potentially, too many dummy IP may flush out good IP address from our bootnode DHT diff --git a/cmd/client/wallet_stress_test/main.go b/cmd/client/wallet_stress_test/main.go index 6b1574db8..bf7f7dd02 100644 --- a/cmd/client/wallet_stress_test/main.go +++ b/cmd/client/wallet_stress_test/main.go @@ -27,10 +27,12 @@ import ( "github.com/harmony-one/harmony/internal/ctxerror" "github.com/harmony-one/harmony/internal/shardchain" "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/p2p" p2p_host "github.com/harmony-one/harmony/p2p/host" "github.com/harmony-one/harmony/p2p/p2pimpl" + p2putils "github.com/harmony-one/harmony/p2p/utils" ) var ( @@ -72,7 +74,7 @@ var ( ) var ( - walletProfile *utils.WalletProfile + walletProfile *wallet.Profile ks *keystore.KeyStore ) @@ -162,7 +164,7 @@ func readProfile(profile string) { iniBytes = []byte(defaultWalletIni) } - walletProfile, err = utils.ReadWalletProfile(iniBytes, profile) + walletProfile, err = wallet.ReadProfile(iniBytes, profile) if err != nil { fmt.Printf("Read wallet profile error: %v\nExiting ...\n", err) os.Exit(2) @@ -171,11 +173,11 @@ func readProfile(profile string) { // createWalletNode creates wallet server node. func createWalletNode() *node.Node { - bootNodeAddrs, err := utils.StringsToAddrs(walletProfile.Bootnodes) + bootNodeAddrs, err := p2putils.StringsToAddrs(walletProfile.Bootnodes) if err != nil { panic(err) } - utils.BootNodes = bootNodeAddrs + p2putils.BootNodes = bootNodeAddrs shardID := 0 // dummy host for wallet // TODO: potentially, too many dummy IP may flush out good IP address from our bootnode DHT diff --git a/cmd/harmony/main.go b/cmd/harmony/main.go index 527ffcce6..24ab475d4 100644 --- a/cmd/harmony/main.go +++ b/cmd/harmony/main.go @@ -15,6 +15,8 @@ import ( ethCommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "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/consensus" "github.com/harmony-one/harmony/consensus/quorum" @@ -31,6 +33,7 @@ import ( "github.com/harmony-one/harmony/node" "github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/p2p/p2pimpl" + p2putils "github.com/harmony-one/harmony/p2p/utils" "github.com/harmony-one/harmony/shard" ) @@ -48,7 +51,7 @@ var ( ) func printVersion() { - fmt.Fprintln(os.Stderr, nodeconfig.GetVersion()) + _, _ = fmt.Fprintln(os.Stderr, nodeconfig.GetVersion()) os.Exit(0) } @@ -85,6 +88,8 @@ var ( // 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.") 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 = flag.Int("shard_id", -1, "the shard ID of this node") enableMemProfiling = flag.Bool("enableMemProfiling", false, "Enable memsize logging.") @@ -138,6 +143,9 @@ func initSetup() { nodeconfig.GetDefaultConfig().Port = *port nodeconfig.GetDefaultConfig().IP = *ip + // Set sharding schedule + nodeconfig.SetShardingSchedule(shard.Schedule) + // Setup mem profiling. memprofiling.GetMemProfiling().Config() @@ -147,12 +155,12 @@ func initSetup() { // Set up randomization seed. rand.Seed(int64(time.Now().Nanosecond())) - if len(utils.BootNodes) == 0 { - bootNodeAddrs, err := utils.StringsToAddrs(utils.DefaultBootNodeAddrStrings) + if len(p2putils.BootNodes) == 0 { + bootNodeAddrs, err := p2putils.StringsToAddrs(p2putils.DefaultBootNodeAddrStrings) if err != nil { panic(err) } - utils.BootNodes = bootNodeAddrs + p2putils.BootNodes = bootNodeAddrs } } @@ -169,47 +177,54 @@ func passphraseForBls() { } passphrase, err := utils.GetPassphraseFromSource(*blsPass) 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) } blsPassphrase = passphrase } -func setupInitialAccount() (isLeader bool) { +func setupLegacyNodeAccount() error { genesisShardingConfig := shard.Schedule.InstanceForEpoch(big.NewInt(core.GenesisEpoch)) pubKey := setupConsensusKey(nodeconfig.GetDefaultConfig()) reshardingEpoch := genesisShardingConfig.ReshardingEpoch() - // TODO: after staking, what if the FN validator uses the old bls pub keys? if reshardingEpoch != nil && len(reshardingEpoch) > 0 { for _, epoch := range reshardingEpoch { config := shard.Schedule.InstanceForEpoch(epoch) - isLeader, initialAccount = config.FindAccount(pubKey.SerializeToHexStr()) + _, initialAccount = config.FindAccount(pubKey.SerializeToHexStr()) if initialAccount != nil { break } } } else { - isLeader, initialAccount = genesisShardingConfig.FindAccount(pubKey.SerializeToHexStr()) + _, initialAccount = genesisShardingConfig.FindAccount(pubKey.SerializeToHexStr()) } if initialAccount == nil { - initialAccount = &genesis.DeployAccount{} - initialAccount.ShardID = uint32(*shardID) - initialAccount.BlsPublicKey = pubKey.SerializeToHexStr() - blsAddressBytes := pubKey.GetAddress() - initialAccount.Address = hex.EncodeToString(blsAddressBytes[:]) - } else { - fmt.Printf("My Genesis Account: %v\n", *initialAccount) + return errors.Errorf("cannot find key %s in table", pubKey.SerializeToHexStr()) } + fmt.Printf("My Genesis Account: %v\n", *initialAccount) + return nil +} - return isLeader +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.ShardID = shardID + initialAccount.BlsPublicKey = pubKey.SerializeToHexStr() + blsAddressBytes := pubKey.GetAddress() + initialAccount.Address = hex.EncodeToString(blsAddressBytes[:]) + return nil } func setupConsensusKey(nodeConfig *nodeconfig.ConfigType) *bls.PublicKey { consensusPriKey, err := blsgen.LoadBlsKeyWithPassPhrase(*blsKeyFile, blsPassphrase) 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) } pubKey := consensusPriKey.GetPublicKey() @@ -223,7 +238,7 @@ func setupConsensusKey(nodeConfig *nodeconfig.ConfigType) *bls.PublicKey { return pubKey } -func createGlobalConfig() *nodeconfig.ConfigType { +func createGlobalConfig() (*nodeconfig.ConfigType, error) { var err error nodeConfig := nodeconfig.GetShardConfig(initialAccount.ShardID) @@ -236,13 +251,7 @@ func createGlobalConfig() *nodeconfig.ConfigType { // Set network type netType := nodeconfig.NetworkType(*networkType) - switch netType { - case nodeconfig.Mainnet, nodeconfig.Testnet, nodeconfig.Pangaea, nodeconfig.Localnet, nodeconfig.Devnet: - nodeconfig.SetNetworkType(netType) - default: - panic(fmt.Sprintf("invalid network type: %s", *networkType)) - } - + nodeconfig.SetNetworkType(netType) // sets for both global and shard configs nodeConfig.SetPushgatewayIP(*pushgatewayIP) nodeConfig.SetPushgatewayPort(*pushgatewayPort) nodeConfig.SetMetricsFlag(*metricsFlag) @@ -250,22 +259,23 @@ func createGlobalConfig() *nodeconfig.ConfigType { // P2p private key is used for secure message transfer between p2p nodes. nodeConfig.P2pPriKey, _, err = utils.LoadKeyFromFile(*keyFile) 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} 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 { myHost.GetP2PHost().Network().Notify(utils.NewConnLogger(utils.GetLogger())) } - if err != nil { - panic("unable to new host in harmony") - } nodeConfig.DBDir = *dbDir - return nodeConfig + return nodeConfig, nil } func setupConsensusAndNode(nodeConfig *nodeconfig.ConfigType) *node.Node { @@ -287,7 +297,7 @@ func setupConsensusAndNode(nodeConfig *nodeconfig.ConfigType) *node.Node { currentConsensus.SelfAddress = common.ParseAddr(initialAccount.Address) if err != nil { - fmt.Fprintf(os.Stderr, "Error :%v \n", err) + _, _ = fmt.Fprintf(os.Stderr, "Error :%v \n", err) os.Exit(1) } commitDelay, err := time.ParseDuration(*delayCommit) @@ -396,7 +406,7 @@ func setupConsensusAndNode(nodeConfig *nodeconfig.ConfigType) *node.Node { } 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() switch *nodeType { @@ -404,7 +414,7 @@ func main() { case "explorer": break default: - fmt.Fprintf(os.Stderr, "Unknown node type: %s\n", *nodeType) + _, _ = fmt.Fprintf(os.Stderr, "Unknown node type: %s\n", *nodeType) os.Exit(1) } @@ -436,6 +446,9 @@ func main() { os.Exit(1) } shard.Schedule = shardingconfig.NewFixedSchedule(devnetConfig) + default: + _, _ = fmt.Fprintf(os.Stderr, "invalid network type: %#v\n", *networkType) + os.Exit(2) } initSetup() @@ -446,8 +459,21 @@ func main() { } 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 { utils.Logger().Info(). @@ -457,7 +483,11 @@ func main() { 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) //setup state syncing and beacon syncing frequency currentNode.SetSyncFreq(*syncFreq) diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 37c3919f3..cd62c58c1 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -428,7 +428,7 @@ func ReadShardState( if err2 != nil { return nil, ctxerror.New("cannot decode sharding state", "epoch", epoch, - ).WithCause(err) + ).WithCause(err2) } return ss, nil } diff --git a/internal/configs/node/config.go b/internal/configs/node/config.go index d633a1790..75908ee04 100644 --- a/internal/configs/node/config.go +++ b/internal/configs/node/config.go @@ -5,12 +5,17 @@ package nodeconfig import ( "crypto/ecdsa" - "errors" "fmt" + "math/big" "sync" "github.com/harmony-one/bls/ffi/go/bls" 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. @@ -70,7 +75,7 @@ type ConfigType struct { client GroupID // the client group ID of the shard isClient bool // whether this node is a client node, such as wallet 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 Port string // Port of the node. IP string // IP of the node. @@ -88,6 +93,8 @@ type ConfigType struct { DBDir string networkType NetworkType + + shardingSchedule shardingconfig.Schedule } // configs is a list of node configuration. @@ -97,30 +104,22 @@ var shardConfigs []ConfigType var defaultConfig ConfigType var onceForConfigs sync.Once -// GetShardConfig return the shard's ConfigType variable -func GetShardConfig(shardID uint32) *ConfigType { +func ensureShardConfigs() { onceForConfigs.Do(func() { shardConfigs = make([]ConfigType, MaxShards) for i := range shardConfigs { shardConfigs[i].ShardID = uint32(i) } }) - if int(shardID) >= cap(shardConfigs) { - return nil - } - return &shardConfigs[shardID] } -// SetConfigs set ConfigType in the right index. -func SetConfigs(config ConfigType, shardID uint32) error { - onceForConfigs.Do(func() { - shardConfigs = make([]ConfigType, MaxShards) - }) +// GetShardConfig return the shard's ConfigType variable +func GetShardConfig(shardID uint32) *ConfigType { + ensureShardConfigs() if int(shardID) >= cap(shardConfigs) { - return errors.New("Failed to set ConfigType") + return nil } - shardConfigs[int(shardID)] = config - return nil + return &shardConfigs[shardID] } // GetDefaultConfig returns default config. @@ -224,6 +223,7 @@ func (conf *ConfigType) Role() Role { // SetNetworkType set the networkType func SetNetworkType(networkType NetworkType) { + ensureShardConfigs() defaultConfig.networkType = networkType for i := range shardConfigs { shardConfigs[i].networkType = networkType @@ -254,3 +254,49 @@ func SetPublicRPC(v bool) { func GetPublicRPC() bool { 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 + } +} diff --git a/internal/configs/node/config_test.go b/internal/configs/node/config_test.go index a3306bbb6..421935e9d 100644 --- a/internal/configs/node/config_test.go +++ b/internal/configs/node/config_test.go @@ -1,7 +1,14 @@ package nodeconfig import ( + "math/big" "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) { @@ -47,3 +54,79 @@ func TestNodeConfigMultiple(t *testing.T) { 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) + } + }) + } +} diff --git a/internal/configs/sharding/mock/shardingconfig.go b/internal/configs/sharding/mock/shardingconfig.go new file mode 100644 index 000000000..946c8ddb7 --- /dev/null +++ b/internal/configs/sharding/mock/shardingconfig.go @@ -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)) +} diff --git a/internal/configs/sharding/shardingconfig.go b/internal/configs/sharding/shardingconfig.go index d46c9eaeb..7453cdf67 100644 --- a/internal/configs/sharding/shardingconfig.go +++ b/internal/configs/sharding/shardingconfig.go @@ -9,6 +9,8 @@ import ( "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 // epoch. type Schedule interface { diff --git a/internal/utils/flags_test.go b/internal/utils/flags_test.go deleted file mode 100644 index 39343d93e..000000000 --- a/internal/utils/flags_test.go +++ /dev/null @@ -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") - } -} diff --git a/internal/utils/utils_test.go b/internal/utils/utils_test.go index 0cb2dc76b..97c87fcda 100644 --- a/internal/utils/utils_test.go +++ b/internal/utils/utils_test.go @@ -3,10 +3,8 @@ package utils import ( "net" "os" - "reflect" "testing" - "github.com/harmony-one/harmony/p2p" crypto "github.com/libp2p/go-libp2p-crypto" "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) - } - } - } -} diff --git a/internal/utils/configfile.go b/internal/wallet/configfile.go similarity index 88% rename from internal/utils/configfile.go rename to internal/wallet/configfile.go index aa2123d1a..477c8bd83 100644 --- a/internal/utils/configfile.go +++ b/internal/wallet/configfile.go @@ -1,4 +1,4 @@ -package utils +package wallet // this module in utils handles the ini file read/write import ( @@ -12,8 +12,8 @@ import ( "github.com/harmony-one/harmony/p2p" ) -// WalletProfile contains a section and key value pair map -type WalletProfile struct { +// Profile contains a section and key value pair map +type Profile struct { Profile string ChainID string Bootnodes []string @@ -22,13 +22,13 @@ type WalletProfile struct { Network string } -// ReadWalletProfile reads an ini file and return WalletProfile -func ReadWalletProfile(iniBytes []byte, profile string) (*WalletProfile, error) { +// ReadProfile reads an ini file and return Profile +func ReadProfile(iniBytes []byte, profile string) (*Profile, error) { cfg, err := ini.ShadowLoad(iniBytes) if err != nil { return nil, err } - config := new(WalletProfile) + config := new(Profile) config.Profile = profile // get the profile section diff --git a/internal/utils/configfile_test.go b/internal/wallet/configfile_test.go similarity index 88% rename from internal/utils/configfile_test.go rename to internal/wallet/configfile_test.go index 681a18d28..4703e1d28 100644 --- a/internal/utils/configfile_test.go +++ b/internal/wallet/configfile_test.go @@ -1,4 +1,4 @@ -package utils +package wallet import ( "io/ioutil" @@ -10,7 +10,7 @@ import ( ) func TestReadWalletProfile(t *testing.T) { - config := []*WalletProfile{ + config := []*Profile{ { Profile: "default", ChainID: params.MainnetChainID.String(), @@ -106,16 +106,16 @@ func TestReadWalletProfile(t *testing.T) { t.Fatalf("Failed to read test.ini: %v", err) } - config1, err := ReadWalletProfile(testIniBytes, "default") + config1, err := ReadProfile(testIniBytes, "default") if err != nil { - t.Fatalf("ReadWalletProfile Error: %v", err) + t.Fatalf("ReadProfile Error: %v", err) } if !reflect.DeepEqual(config[0], config1) { t.Errorf("Got: %v\nExpect: %v\n", config1, config[0]) } - config2, err := ReadWalletProfile(testIniBytes, "testnet") + config2, err := ReadProfile(testIniBytes, "testnet") if err != nil { - t.Fatalf("ReadWalletProfile Error: %v", err) + t.Fatalf("ReadProfile Error: %v", err) } if !reflect.DeepEqual(config[1], config2) { t.Errorf("Got: %v\nExpect: %v\n", config2, config[1]) diff --git a/internal/utils/test.ini b/internal/wallet/test.ini similarity index 100% rename from internal/utils/test.ini rename to internal/wallet/test.ini diff --git a/node/node.go b/node/node.go index 1e3aee129..8c584f4dc 100644 --- a/node/node.go +++ b/node/node.go @@ -407,13 +407,8 @@ func New(host p2p.Host, consensusObj *consensus.Consensus, node.SelfPeer = host.GetSelfPeer() } - chainConfig := *params.TestnetChainConfig - switch node.NodeConfig.GetNetworkType() { - case nodeconfig.Mainnet: - chainConfig = *params.MainnetChainConfig - case nodeconfig.Pangaea: - chainConfig = *params.PangaeaChainConfig - } + networkType := node.NodeConfig.GetNetworkType() + chainConfig := networkType.ChainConfig() node.chainConfig = chainConfig collection := shardchain.NewCollection( @@ -457,7 +452,7 @@ func New(host p2p.Host, consensusObj *consensus.Consensus, node.Consensus.SetBlockNum(blockchain.CurrentBlock().NumberU64() + 1) // 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 { // Setup one time smart contracts node.AddFaucetContractToPendingTransactions() diff --git a/internal/utils/flags.go b/p2p/utils/flags.go similarity index 99% rename from internal/utils/flags.go rename to p2p/utils/flags.go index 0f8d4ec9d..28ff73b28 100644 --- a/internal/utils/flags.go +++ b/p2p/utils/flags.go @@ -1,4 +1,4 @@ -package utils +package p2putils import ( "fmt" diff --git a/p2p/utils/flags_test.go b/p2p/utils/flags_test.go new file mode 100644 index 000000000..43b21cc39 --- /dev/null +++ b/p2p/utils/flags_test.go @@ -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) + } + } + } +} diff --git a/scripts/node.sh b/scripts/node.sh index a9e500a38..a25741efd 100755 --- a/scripts/node.sh +++ b/scripts/node.sh @@ -116,6 +116,8 @@ usage: ${progname} [-1ch] [-k KEYFILE] -P enable public rpc end point (default:off) -v print out the version of the node.sh -V print out the version of the Harmony binary + -z run in staking mode + -y run in legacy, foundational-node mode (default) examples: @@ -149,7 +151,7 @@ BUCKET=pub.harmony.one 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 upgrade_rel public_rpc +unset upgrade_rel public_rpc staking_mode start_clean=false loop=true run_as_root=true @@ -161,11 +163,12 @@ node_type=validator shard_id=1 download_harmony_db=false public_rpc=false +staking_mode=false ${BLSKEYFILE=} unset OPTIND OPTARG opt 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 case "${opt}" in '?') usage "unrecognized option -${OPTARG}";; @@ -192,6 +195,8 @@ do exit 0 ;; V) LD_LIBRARY_PATH=. ./harmony -version exit 0 ;; + z) staking_mode=true;; + y) staking_mode=false;; *) err 70 "unhandled option -${OPTARG}";; # EX_SOFTWARE esac done @@ -659,6 +664,10 @@ do args+=( -shard_id="${shard_id}" ) + if ${staking_mode} + then + args+=(-staking="${staking_mode}") + fi ;; esac ;;