[service][node] Project Tech debt clean up, remove wallet (#2664)

* [project][p2p] Remove wallet, client roles & associated function calls

* [node][service] Remove unused service types

* [wallet] Remove internal wallet code

* [test] Remove wallet from debug.sh

* [test] More cleanup in debug.sh, deploy.sh

* [test] Adjust duration back into local test script

* [test] Increase duration

* [test] Exit with 0, remove RESULT_FILE as not made anymore
pull/2667/head
Edgar Aroutiounian 5 years ago committed by GitHub
parent afeeb69094
commit 4e85d7d866
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      api/proto/node/node.go
  2. 27
      api/service/manager.go
  3. 39
      api/service/manager_test.go
  4. 51
      api/service/randomness/service.go
  5. 5
      cmd/bootnode/main.go
  6. 2
      cmd/client/txgen/main.go
  7. 1
      cmd/client/wallet/README.md
  8. 84
      cmd/client/wallet/generated_wallet.ini.go
  9. 1024
      cmd/client/wallet/main.go
  10. 51
      cmd/client/wallet/validation_test.go
  11. 1
      cmd/client/wallet_stress_test/README.md
  12. 84
      cmd/client/wallet_stress_test/generated_wallet.ini.go
  13. 474
      cmd/client/wallet_stress_test/main.go
  14. 6
      cmd/harmony/main.go
  15. 11
      internal/configs/node/config.go
  16. 100
      internal/wallet/configfile.go
  17. 123
      internal/wallet/configfile_test.go
  18. 39
      internal/wallet/test.ini
  19. 1
      node/node.go
  20. 34
      node/node.md
  21. 81
      node/service_setup.go
  22. 5
      p2p/host/hostv2/hostv2.go
  23. 41
      scripts/go_executable_build.sh
  24. 71
      test/deploy.sh
  25. 2
      test/kill_node.sh

@ -96,11 +96,10 @@ type BlockMessageType int
// Block sync message subtype
const (
Sync BlockMessageType = iota
CrossLink // used for crosslink from beacon chain to shard chain
Receipt // cross-shard transaction receipts
SlashCandidate // A report of a double-signing event
Sync BlockMessageType = iota
CrossLink // used for crosslink from beacon chain to shard chain
Receipt // cross-shard transaction receipts
SlashCandidate // A report of a double-signing event
)
var (

@ -23,25 +23,17 @@ type Type byte
// Constants for Type.
const (
SupportSyncing Type = iota
ClientSupport
ClientSupport Type = iota
SupportExplorer
Consensus
Metrics
Randomness
BlockProposal
NetworkInfo
PeerDiscovery
Resharding
Staking
Test
Done
)
func (t Type) String() string {
switch t {
case SupportSyncing:
return "SyncingSupport"
case SupportExplorer:
return "SupportExplorer"
case ClientSupport:
@ -50,22 +42,12 @@ func (t Type) String() string {
return "Metrics"
case Consensus:
return "Consensus"
case Randomness:
return "Randomness"
case BlockProposal:
return "BlockProposal"
case NetworkInfo:
return "NetworkInfo"
case Staking:
return "Staking"
case PeerDiscovery:
return "PeerDiscovery"
case Resharding:
return "Resharding"
case Test:
return "Test"
case Done:
return "Done"
default:
return "Unknown"
}
@ -166,9 +148,6 @@ func (m *Manager) StartServiceManager() chan *Action {
select {
case action := <-ch:
m.TakeAction(action)
if action.ServiceType == Done {
return
}
case <-time.After(WaitForStatusUpdate):
utils.Logger().Info().Msg("Waiting for new action")
}
@ -189,7 +168,9 @@ func (m *Manager) RunServices() {
}
// SetupServiceMessageChan sets up message channel to services.
func (m *Manager) SetupServiceMessageChan(mapServiceTypeChan map[Type]chan *msg_pb.Message) {
func (m *Manager) SetupServiceMessageChan(
mapServiceTypeChan map[Type]chan *msg_pb.Message,
) {
for serviceType, service := range m.services {
// TODO(minhdoan): for performance, consider buffered channel.
mapServiceTypeChan[serviceType] = make(chan *msg_pb.Message)

@ -46,58 +46,21 @@ func (s *SupportSyncingTest) APIs() []rpc.API { return nil }
func TestTakeAction(t *testing.T) {
m := &Manager{}
m.SetupServiceManager()
m.RegisterService(SupportSyncing, &SupportSyncingTest{})
for i := 0; i < 2; i++ {
select {
case <-time.After(100 * time.Millisecond):
m.SendAction(&Action{Action: Start, ServiceType: SupportSyncing})
return
}
}
m.SendAction(&Action{ServiceType: Done})
}
func TestMessageChan(t *testing.T) {
m := &Manager{}
m.SetupServiceManager()
m.RegisterService(SupportSyncing, &SupportSyncingTest{})
msgChans := make(map[Type]chan *msg_pb.Message)
m.SetupServiceMessageChan(msgChans)
m.SendAction(&Action{
Action: Notify,
ServiceType: SupportSyncing,
Params: map[string]interface{}{
"chan": msgChans[SupportSyncing],
"test": t,
},
})
m.SendAction(&Action{ServiceType: Done})
}
func TestStopServices(t *testing.T) {
m := &Manager{}
m.SetupServiceManager()
status := 0
m.RegisterService(SupportSyncing, &SupportSyncingTest{status: &status})
msgChans := make(map[Type]chan *msg_pb.Message)
m.SetupServiceMessageChan(msgChans)
m.SendAction(&Action{
Action: Notify,
ServiceType: SupportSyncing,
Params: map[string]interface{}{
"chan": msgChans[SupportSyncing],
"test": t,
},
})
m.StopServicesByRole([]Type{})
if status != 2 {
t.Error("Service did not stop")
}
}
func TestInit(t *testing.T) {

@ -1,51 +0,0 @@
package randomness
import (
"github.com/ethereum/go-ethereum/rpc"
msg_pb "github.com/harmony-one/harmony/api/proto/message"
"github.com/harmony-one/harmony/drand"
"github.com/harmony-one/harmony/internal/utils"
)
// Service is the randomness generation service.
type Service struct {
stopChan chan struct{}
stoppedChan chan struct{}
DRand *drand.DRand
messageChan chan *msg_pb.Message
}
// New returns randomness generation service.
func New(dRand *drand.DRand) *Service {
return &Service{DRand: dRand}
}
// StartService starts randomness generation service.
func (s *Service) StartService() {
s.stopChan = make(chan struct{})
s.stoppedChan = make(chan struct{})
s.DRand.WaitForEpochBlock(s.DRand.ConfirmedBlockChannel, s.stopChan, s.stoppedChan)
}
// StopService stops randomness generation service.
func (s *Service) StopService() {
utils.Logger().Info().Msg("Stopping random generation service")
s.stopChan <- struct{}{}
<-s.stoppedChan
utils.Logger().Info().Msg("Random generation stopped")
}
// NotifyService notify service
func (s *Service) NotifyService(params map[string]interface{}) {
return
}
// SetMessageChan sets up message channel to service.
func (s *Service) SetMessageChan(messageChan chan *msg_pb.Message) {
s.messageChan = messageChan
}
// APIs for the services.
func (s *Service) APIs() []rpc.API {
return nil
}

@ -10,13 +10,10 @@ import (
"path"
"github.com/ethereum/go-ethereum/log"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/p2p"
"github.com/harmony-one/harmony/p2p/p2pimpl"
badger "github.com/ipfs/go-ds-badger"
kaddht "github.com/libp2p/go-libp2p-kad-dht"
)
@ -58,7 +55,7 @@ func main() {
utils.FatalErrMsg(err, "cannot load key from %s", *keyFile)
}
var selfPeer = p2p.Peer{IP: *ip, Port: *port}
selfPeer := p2p.Peer{IP: *ip, Port: *port}
host, err := p2pimpl.NewHost(&selfPeer, privKey)
if err != nil {

@ -116,7 +116,7 @@ func setUpTXGen() *node.Node {
pubs = append(pubs, pub)
}
consensusObj.Decider.UpdateParticipants(pubs)
txGen.NodeConfig.SetRole(nodeconfig.ClientNode)
txGen.NodeConfig.SetRole(nodeconfig.Validator)
if shardID == 0 {
txGen.NodeConfig.SetShardGroupID(nodeconfig.GroupIDBeacon)
} else {

@ -1 +0,0 @@
The wallet program is the demo wallet which talks to Harmony devnet for various kinds of operations. For detail, please compile and execute ./bin/wallet.

@ -1,84 +0,0 @@
package main
const (
defaultWalletIni = `[main]
chain_id = 1
bootnode = /ip4/100.26.90.187/tcp/9874/p2p/Qmdfjtk6hPoyrH1zVD9PEH4zfWLo38dP2mDvvKXfh3tnEv
bootnode = /ip4/54.213.43.194/tcp/9874/p2p/QmZJJx6AdaoEkGLrYG4JeLCKeCKDjnFz2wfHNHxAqFSGA9
bootnode = /ip4/13.113.101.219/tcp/12019/p2p/QmQayinFSgMMw5cSpDUiD9pQ2WeP6WNmGxpZ6ou3mdVFJX
bootnode = /ip4/99.81.170.167/tcp/12019/p2p/QmRVbTpEYup8dSaURZfF6ByrMTSKa4UyUzJhSjahFzRqNj
shards = 4
network = mainnet
[main.shard0.rpc]
rpc = l0.t.hmny.io:14555
rpc = s0.t.hmny.io:14555
[main.shard1.rpc]
rpc = l1.t.hmny.io:14555
rpc = s1.t.hmny.io:14555
[main.shard2.rpc]
rpc = l2.t.hmny.io:14555
rpc = s2.t.hmny.io:14555
[main.shard3.rpc]
rpc = l3.t.hmny.io:14555
rpc = s3.t.hmny.io:14555
[local]
chain_id = 2
bootnode = /ip4/127.0.0.1/tcp/19876/p2p/Qmc1V6W7BwX8Ugb42Ti8RnXF1rY5PF7nnZ6bKBryCgi6cv
shards = 2
network = localnet
[local.shard0.rpc]
rpc = 127.0.0.1:14555
rpc = 127.0.0.1:14557
rpc = 127.0.0.1:14559
[local.shard1.rpc]
rpc = 127.0.0.1:14556
rpc = 127.0.0.1:14558
rpc = 127.0.0.1:14560
[beta]
chain_id = 2
bootnode = /ip4/54.213.43.194/tcp/9868/p2p/QmZJJx6AdaoEkGLrYG4JeLCKeCKDjnFz2wfHNHxAqFSGA9
bootnode = /ip4/100.26.90.187/tcp/9868/p2p/Qmdfjtk6hPoyrH1zVD9PEH4zfWLo38dP2mDvvKXfh3tnEv
bootnode = /ip4/13.113.101.219/tcp/12018/p2p/QmQayinFSgMMw5cSpDUiD9pQ2WeP6WNmGxpZ6ou3mdVFJX
shards = 2
network = testnet
[beta.shard0.rpc]
rpc = l0.b.hmny.io:14555
rpc = s0.b.hmny.io:14555
[beta.shard1.rpc]
rpc = l1.b.hmny.io:14555
rpc = s1.b.hmny.io:14555
[pangaea]
chain_id = 3
bootnode = /ip4/54.86.126.90/tcp/9889/p2p/Qmdfjtk6hPoyrH1zVD9PEH4zfWLo38dP2mDvvKXfh3tnEv
bootnode = /ip4/52.40.84.2/tcp/9889/p2p/QmZJJx6AdaoEkGLrYG4JeLCKeCKDjnFz2wfHNHxAqFSGA9
shards = 4
network = pangaea
[pangaea.shard0.rpc]
rpc = l0.p.hmny.io:14555
rpc = s0.p.hmny.io:14555
[pangaea.shard1.rpc]
rpc = l1.p.hmny.io:14555
rpc = s1.p.hmny.io:14555
[pangaea.shard2.rpc]
rpc = l2.p.hmny.io:14555
rpc = s2.p.hmny.io:14555
[pangaea.shard3.rpc]
rpc = l3.p.hmny.io:14555
rpc = s3.p.hmny.io:14555
`
)

File diff suppressed because it is too large Load Diff

@ -1,51 +0,0 @@
package main
import (
"testing"
"github.com/harmony-one/harmony/internal/common"
)
func TestIsValidAddress(t *testing.T) {
tests := []struct {
str string
exp bool
}{
{"one1ay37rp2pc3kjarg7a322vu3sa8j9puahg679z3", true},
{"0x7c41E0668B551f4f902cFaec05B5Bdca68b124CE", true},
{"onefoofoo", false},
{"0xbarbar", false},
{"dsasdadsasaadsas", false},
{"32312123213213212321", false},
}
for _, test := range tests {
valid, _ := validateAddress(test.str, common.ParseAddr(test.str), "sender")
if valid != test.exp {
t.Errorf("validateAddress(\"%s\") returned %v, expected %v", test.str, valid, test.exp)
}
}
}
func TestIsValidShard(t *testing.T) {
readProfile("local")
tests := []struct {
shardID int
exp bool
}{
{0, true},
{1, true},
{-1, false},
{99, false},
}
for _, test := range tests {
valid := validShard(test.shardID, walletProfile.Shards)
if valid != test.exp {
t.Errorf("validShard(%d) returned %v, expected %v", test.shardID, valid, test.exp)
}
}
}

@ -1 +0,0 @@
The wallet program is the demo wallet which talks to Harmony devnet for stress testing transactions operations. For detail, please compile and execute ./bin/wallet_stress test stressTest.

@ -1,84 +0,0 @@
package main
const (
defaultWalletIni = `[main]
chain_id = 1
bootnode = /ip4/100.26.90.187/tcp/9874/p2p/Qmdfjtk6hPoyrH1zVD9PEH4zfWLo38dP2mDvvKXfh3tnEv
bootnode = /ip4/54.213.43.194/tcp/9874/p2p/QmZJJx6AdaoEkGLrYG4JeLCKeCKDjnFz2wfHNHxAqFSGA9
bootnode = /ip4/13.113.101.219/tcp/12019/p2p/QmQayinFSgMMw5cSpDUiD9pQ2WeP6WNmGxpZ6ou3mdVFJX
bootnode = /ip4/99.81.170.167/tcp/12019/p2p/QmRVbTpEYup8dSaURZfF6ByrMTSKa4UyUzJhSjahFzRqNj
shards = 4
network = mainnet
[main.shard0.rpc]
rpc = l0.t.hmny.io:14555
rpc = s0.t.hmny.io:14555
[main.shard1.rpc]
rpc = l1.t.hmny.io:14555
rpc = s1.t.hmny.io:14555
[main.shard2.rpc]
rpc = l2.t.hmny.io:14555
rpc = s2.t.hmny.io:14555
[main.shard3.rpc]
rpc = l3.t.hmny.io:14555
rpc = s3.t.hmny.io:14555
[local]
chain_id = 2
bootnode = /ip4/127.0.0.1/tcp/19876/p2p/Qmc1V6W7BwX8Ugb42Ti8RnXF1rY5PF7nnZ6bKBryCgi6cv
shards = 2
network = localnet
[local.shard0.rpc]
rpc = 127.0.0.1:14555
rpc = 127.0.0.1:14557
rpc = 127.0.0.1:14559
[local.shard1.rpc]
rpc = 127.0.0.1:14556
rpc = 127.0.0.1:14558
rpc = 127.0.0.1:14560
[beta]
chain_id = 2
bootnode = /ip4/54.213.43.194/tcp/9868/p2p/QmZJJx6AdaoEkGLrYG4JeLCKeCKDjnFz2wfHNHxAqFSGA9
bootnode = /ip4/100.26.90.187/tcp/9868/p2p/Qmdfjtk6hPoyrH1zVD9PEH4zfWLo38dP2mDvvKXfh3tnEv
bootnode = /ip4/13.113.101.219/tcp/12018/p2p/QmQayinFSgMMw5cSpDUiD9pQ2WeP6WNmGxpZ6ou3mdVFJX
shards = 2
network = testnet
[beta.shard0.rpc]
rpc = l0.b.hmny.io:14555
rpc = s0.b.hmny.io:14555
[beta.shard1.rpc]
rpc = l1.b.hmny.io:14555
rpc = s1.b.hmny.io:14555
[pangaea]
chain_id = 3
bootnode = /ip4/54.86.126.90/tcp/9889/p2p/Qmdfjtk6hPoyrH1zVD9PEH4zfWLo38dP2mDvvKXfh3tnEv
bootnode = /ip4/52.40.84.2/tcp/9889/p2p/QmZJJx6AdaoEkGLrYG4JeLCKeCKDjnFz2wfHNHxAqFSGA9
shards = 4
network = pangaea
[pangaea.shard0.rpc]
rpc = l0.p.hmny.io:14555
rpc = s0.p.hmny.io:14555
[pangaea.shard1.rpc]
rpc = l1.p.hmny.io:14555
rpc = s1.p.hmny.io:14555
[pangaea.shard2.rpc]
rpc = l2.p.hmny.io:14555
rpc = s2.p.hmny.io:14555
[pangaea.shard3.rpc]
rpc = l3.p.hmny.io:14555
rpc = s3.p.hmny.io:14555
`
)

@ -1,474 +0,0 @@
package main
import (
"flag"
"fmt"
"io/ioutil"
"math/big"
"math/rand"
"os"
"path"
"sync"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/harmony-one/harmony/accounts"
"github.com/harmony-one/harmony/accounts/keystore"
"github.com/harmony-one/harmony/api/client"
clientService "github.com/harmony-one/harmony/api/client/service"
proto_node "github.com/harmony-one/harmony/api/proto/node"
"github.com/harmony-one/harmony/common/denominations"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/types"
common2 "github.com/harmony-one/harmony/internal/common"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"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 (
version string
builtBy string
builtAt string
commit string
nextNonce uint64
)
func printVersion(me string) {
fmt.Fprintf(os.Stderr, "Harmony (C) 2019. %v, version %v-%v (%v %v)\n", path.Base(me), version, commit, builtBy, builtAt)
os.Exit(0)
}
// AccountState includes the balance and nonce of an account
type AccountState struct {
balance *big.Int
nonce uint64
}
const (
rpcRetry = 3
defaultConfigFile = ".hmy/wallet.ini"
defaultProfile = "default"
keystoreDir = ".hmy/keystore"
)
var (
// Transfer subcommands
transferCommand = flag.NewFlagSet("transfer", flag.ExitOnError)
transferSenderPtr = transferCommand.String("from", "0", "Specify the sender account address or index")
transferReceiverPtr = transferCommand.String("to", "", "Specify the receiver account")
transferAmountPtr = transferCommand.Float64("amount", 0, "Specify the amount to transfer")
transferGasPricePtr = transferCommand.Uint64("gasPrice", 0, "Specify the gas price amount. Unit is Nano.")
transferShardIDPtr = transferCommand.Int("shardID", 0, "Specify the shard ID for the transfer")
transferInputDataPtr = transferCommand.String("inputData", "", "Base64-encoded input data to embed in the transaction")
transferSenderPassPtr = transferCommand.String("pass", "", "Passphrase of the sender's private key")
)
var (
walletProfile *wallet.Profile
ks *keystore.KeyStore
)
// setupLog setup log for verbose output
func setupLog() {
// enable logging for wallet
h := log.StreamHandler(os.Stdout, log.TerminalFormat(true))
log.Root().SetHandler(h)
}
// The main wallet program entrance. Note the this wallet program is for demo-purpose only. It does not implement
// the secure storage of keys.
func main() {
rand.Seed(int64(time.Now().Nanosecond()))
// Verify that a subcommand has been provided
// os.Arg[0] is the main command
// os.Arg[1] will be the subcommand
if len(os.Args) < 2 {
fmt.Println("Usage:")
fmt.Println(" wallet -p profile <action> <params>")
fmt.Println(" -p profile - Specify the profile of the wallet, either testnet/devnet or others configured. Default is: testnet")
fmt.Println(" The profile is in file:", defaultConfigFile)
fmt.Println()
fmt.Println("Actions:")
fmt.Println(" 1. stressTest - Stress test transactions with corner cases.")
os.Exit(1)
}
ARG:
for {
lastArg := os.Args[len(os.Args)-1]
switch lastArg {
case "--verbose":
setupLog()
os.Args = os.Args[:len(os.Args)-1]
default:
break ARG
}
}
var profile string
if os.Args[1] == "-p" {
profile = os.Args[2]
os.Args = os.Args[2:]
} else {
profile = defaultProfile
}
if len(os.Args) == 1 {
fmt.Println("Missing action")
flag.PrintDefaults()
os.Exit(1)
}
// create new keystore backend
scryptN := keystore.StandardScryptN
scryptP := keystore.StandardScryptP
ks = keystore.NewKeyStore(keystoreDir, scryptN, scryptP)
// Switch on the subcommand
switch os.Args[1] {
case "-version":
printVersion(os.Args[0])
case "stressTest":
readProfile(profile)
processStressTestCommand()
default:
fmt.Printf("Unknown action: %s\n", os.Args[1])
flag.PrintDefaults()
os.Exit(1)
}
}
//go:generate go run ../../../scripts/wallet_embed_ini_files.go
func readProfile(profile string) {
fmt.Printf("Using %s profile for wallet\n", profile)
// try to load .hmy/wallet.ini from filesystem
// use default_wallet_ini if .hmy/wallet.ini doesn't exist
var err error
var iniBytes []byte
iniBytes, err = ioutil.ReadFile(defaultConfigFile)
if err != nil {
log.Debug(fmt.Sprintf("%s doesn't exist, using default ini\n", defaultConfigFile))
iniBytes = []byte(defaultWalletIni)
}
walletProfile, err = wallet.ReadProfile(iniBytes, profile)
if err != nil {
fmt.Printf("Read wallet profile error: %v\nExiting ...\n", err)
os.Exit(2)
}
}
// createWalletNode creates wallet server node.
func createWalletNode() *node.Node {
bootNodeAddrs, err := p2putils.StringsToAddrs(walletProfile.Bootnodes)
if err != nil {
utils.FatalErrMsg(err, "cannot parse bootnodes %#v", walletProfile.Bootnodes)
}
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
// we need to understand the impact to bootnode DHT with this dummy host ip added
self := p2p.Peer{IP: "127.0.0.1", Port: "6999"}
priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "6999")
host, err := p2pimpl.NewHost(&self, priKey)
if err != nil {
utils.FatalErrMsg(err, "cannot initialize network")
}
chainDBFactory := &shardchain.MemDBFactory{}
w := node.New(host, nil, chainDBFactory, nil, false)
w.Client = client.NewClient(w.GetHost(), uint32(shardID))
w.NodeConfig.SetRole(nodeconfig.ClientNode)
w.ServiceManagerSetup()
w.RunServices()
return w
}
// ./bin/wallet -p local transfer
// --from one1uyshu2jgv8w465yc8kkny36thlt2wvel89tcmg
// --to one1spshr72utf6rwxseaz339j09ed8p6f8ke370zj
// --amount 1 --shardID 1
func processStressTestCommand() {
/*
Account 17:
Address: one1spshr72utf6rwxseaz339j09ed8p6f8ke370zj
Balance in Shard 0: x.xxx, nonce: 0
Balance in Shard 1: 0.0000, nonce: 0
Account 18:
Address: one1uyshu2jgv8w465yc8kkny36thlt2wvel89tcmg
Balance in Shard 0: 0.0000, nonce: 0
Balance in Shard 1: x.xxx, nonce: 0
*/
chainID, ok := new(big.Int).SetString(walletProfile.ChainID, 0)
if !ok {
fmt.Printf("invalid chain ID %#v in config", walletProfile.ChainID)
return
}
fmt.Println("Creating wallet node")
walletNode := createWalletNode()
senderAddress := common2.ParseAddr("one1uyshu2jgv8w465yc8kkny36thlt2wvel89tcmg")
receiverAddress := common2.ParseAddr("one1spshr72utf6rwxseaz339j09ed8p6f8ke370zj")
shardID := 1
fmt.Printf("Sender account: %s:\n", common2.MustAddressToBech32(senderAddress))
// default inputData
data := make([]byte, 0)
gasLimit, _ := core.IntrinsicGas(data, false, true, false)
gasPrice := 0
gasPriceBigInt := big.NewInt(int64(gasPrice))
gasPriceBigInt = gasPriceBigInt.Mul(gasPriceBigInt, big.NewInt(denominations.Nano))
fmt.Printf("gas limit: %d, gas price: %d", gasLimit, gasPriceBigInt.Uint64())
senderPass := ""
var shardIDToAccountStateSender []*AccountState
var shardIDToAccountStateReceiver []*AccountState
var senderState *AccountState
var receiverState *AccountState
var retry uint32
for i := 0; ; i++ {
for retry = 0; retry < 10; retry++ {
shardIDToAccountStateSender = FetchBalance(senderAddress)
shardIDToAccountStateReceiver = FetchBalance(receiverAddress)
senderState = shardIDToAccountStateSender[shardID]
receiverState = shardIDToAccountStateReceiver[shardID]
if senderState.nonce == nextNonce {
break
}
time.Sleep(3 * time.Second)
fmt.Printf(".")
}
if retry == 10 {
fmt.Printf("\nRetry expired. Num txs made: %d\n", i)
break
}
nextNonce++
senderBalance := senderState.balance
receiverBalance := receiverState.balance
// amount 1/10th of the balance
amountBigInt := senderBalance.Div(senderBalance, big.NewInt(10))
fmt.Printf("\nsender: balance (shard %d: %s, nonce: %v)\n", shardID, convertBalanceIntoReadableFormat(senderBalance), senderState.nonce)
fmt.Printf("receiver balance (shard %d: %s, nonce: %v)\n", shardID, convertBalanceIntoReadableFormat(receiverBalance), receiverState.nonce)
// stop stress testing here after printing out the final balance
if i == 10 {
break
}
tx := types.NewTransaction(
senderState.nonce, receiverAddress, uint32(shardID), amountBigInt,
gasLimit, gasPriceBigInt, data)
account, _ := ks.Find(accounts.Account{Address: senderAddress})
ks.Unlock(account, senderPass)
tx, _ = ks.SignTx(account, tx, chainID)
if err := submitTransaction(tx, walletNode, uint32(shardID)); err != nil {
fmt.Println(ctxerror.New("submitTransaction failed",
"tx", tx, "shardID", shardID).WithCause(err))
}
}
for shardID, balanceNonce := range FetchBalance(senderAddress) {
fmt.Printf(" Final: Balance in Shard %d: %s, nonce: %v \n", shardID, convertBalanceIntoReadableFormat(balanceNonce.balance), balanceNonce.nonce)
}
}
func convertBalanceIntoReadableFormat(balance *big.Int) string {
balance = balance.Div(balance, big.NewInt(denominations.Nano))
strBalance := fmt.Sprintf("%d", balance.Uint64())
bytes := []byte(strBalance)
hasDecimal := false
for i := 0; i < 11; i++ {
if len(bytes)-1-i < 0 {
bytes = append([]byte{'0'}, bytes...)
}
if bytes[len(bytes)-1-i] != '0' && i < 9 {
hasDecimal = true
}
if i == 9 {
newBytes := append([]byte{'.'}, bytes[len(bytes)-i:]...)
bytes = append(bytes[:len(bytes)-i], newBytes...)
}
}
zerosToRemove := 0
for i := 0; i < len(bytes); i++ {
if hasDecimal {
if bytes[len(bytes)-1-i] == '0' {
bytes = bytes[:len(bytes)-1-i]
i--
} else {
break
}
} else {
if zerosToRemove < 5 {
bytes = bytes[:len(bytes)-1-i]
i--
zerosToRemove++
} else {
break
}
}
}
return string(bytes)
}
// FetchBalance fetches account balance of specified address from the Harmony network
func FetchBalance(address common.Address) []*AccountState {
result := []*AccountState{}
for shardID := 0; shardID < walletProfile.Shards; shardID++ {
// Fill in nil pointers for each shard; nil represent failed balance fetch.
result = append(result, nil)
}
var wg sync.WaitGroup
wg.Add(walletProfile.Shards)
for shardID := 0; shardID < walletProfile.Shards; shardID++ {
go func(shardID int) {
defer wg.Done()
balance := big.NewInt(0)
var nonce uint64
result[uint32(shardID)] = &AccountState{balance, 0}
var wgShard sync.WaitGroup
wgShard.Add(len(walletProfile.RPCServer[shardID]))
var mutexAccountState = &sync.Mutex{}
for rpcServerID := 0; rpcServerID < len(walletProfile.RPCServer[shardID]); rpcServerID++ {
go func(rpcServerID int) {
for retry := 0; retry < rpcRetry; retry++ {
server := walletProfile.RPCServer[shardID][rpcServerID]
client, err := clientService.NewClient(server.IP, server.Port)
if err != nil {
continue
}
log.Debug("FetchBalance", "server", server)
response, err := client.GetBalance(address)
if err != nil {
log.Info("failed to get balance, retrying ...")
time.Sleep(200 * time.Millisecond)
continue
}
log.Debug("FetchBalance", "response", response)
respBalance := big.NewInt(0)
respBalance.SetBytes(response.Balance)
mutexAccountState.Lock()
if balance.Cmp(respBalance) < 0 {
balance.SetBytes(response.Balance)
nonce = response.Nonce
}
mutexAccountState.Unlock()
break
}
wgShard.Done()
}(rpcServerID)
}
wgShard.Wait()
result[shardID] = &AccountState{balance, nonce}
}(shardID)
}
wg.Wait()
return result
}
// GetFreeToken requests for token test token on each shard
func GetFreeToken(address common.Address) {
for i := 0; i < walletProfile.Shards; i++ {
// use the 1st server (leader) to make the getFreeToken call
server := walletProfile.RPCServer[i][0]
client, err := clientService.NewClient(server.IP, server.Port)
if err != nil {
continue
}
log.Debug("GetFreeToken", "server", server)
for retry := 0; retry < rpcRetry; retry++ {
response, err := client.GetFreeToken(address)
if err != nil {
log.Info("failed to get free token, retrying ...")
time.Sleep(200 * time.Millisecond)
continue
}
log.Debug("GetFreeToken", "response", response)
txID := common.Hash{}
txID.SetBytes(response.TxId)
fmt.Printf("Transaction Id requesting free token in shard %d: %s\n", i, txID.Hex())
break
}
}
}
// clearKeystore deletes all data in the local keystore
func clearKeystore() {
dir, err := ioutil.ReadDir(keystoreDir)
if err != nil {
utils.FatalErrMsg(err, "cannot read keystore directory %s", keystoreDir)
}
for _, d := range dir {
subdir := path.Join([]string{keystoreDir, d.Name()}...)
if err := os.RemoveAll(subdir); err != nil {
fmt.Println(ctxerror.New("cannot remove directory",
"path", subdir).WithCause(err))
}
}
fmt.Println("All existing accounts deleted...")
}
// submitTransaction submits the transaction to the Harmony network
func submitTransaction(tx *types.Transaction, walletNode *node.Node, shardID uint32) error {
msg := proto_node.ConstructTransactionListMessageAccount(types.Transactions{tx})
clientGroup := nodeconfig.NewClientGroupIDByShardID(nodeconfig.ShardID(shardID))
err := walletNode.GetHost().SendMessageToGroups([]nodeconfig.GroupID{clientGroup}, p2p_host.ConstructP2pMessage(byte(0), msg))
if err != nil {
fmt.Printf("Error in SubmitTransaction: %v\n", err)
return err
}
fmt.Printf("Transaction Id for shard %d: %s\n", int(shardID), tx.Hash().Hex())
// FIXME (leo): how to we know the tx was successful sent to the network
// this is a hacky way to wait for sometime
time.Sleep(3 * time.Second)
return nil
}

@ -395,7 +395,11 @@ func createGlobalConfig() (*nodeconfig.ConfigType, error) {
*keyFile)
}
selfPeer := p2p.Peer{IP: *ip, Port: *port, ConsensusPubKey: nodeConfig.ConsensusPubKey.PublicKey[0]}
selfPeer := p2p.Peer{
IP: *ip,
Port: *port,
ConsensusPubKey: nodeConfig.ConsensusPubKey.PublicKey[0],
}
myHost, err = p2pimpl.NewHost(&selfPeer, nodeConfig.P2pPriKey)
if err != nil {

@ -25,25 +25,18 @@ type Role byte
const (
Unknown Role = iota
Validator
ClientNode
WalletNode
ExplorerNode
)
func (role Role) String() string {
switch role {
case Unknown:
return "Unknown"
case Validator:
return "Validator"
case ClientNode:
return "ClientNode"
case WalletNode:
return "WalletNode"
case ExplorerNode:
return "ExplorerNode"
default:
return "Unknown"
}
return "Unknown"
}
// NetworkType describes the type of Harmony network

@ -1,100 +0,0 @@
package wallet
// this module in utils handles the ini file read/write
import (
"fmt"
"os"
"strings"
ini "gopkg.in/ini.v1"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/p2p"
)
// Profile contains a section and key value pair map
type Profile struct {
Profile string
ChainID string
Bootnodes []string
Shards int
RPCServer [][]p2p.Peer
Network string
}
// 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(Profile)
config.Profile = profile
// get the profile section
sec, err := cfg.GetSection(profile)
if err != nil {
return nil, err
}
profile = sec.Name() // sanitized name
if sec.HasKey("bootnode") {
config.Bootnodes = sec.Key("bootnode").ValueWithShadows()
} else {
return nil, fmt.Errorf("can't find bootnode key")
}
if sec.HasKey("network") {
config.Network = sec.Key("network").String()
} else {
config.Network = "devnet"
}
if sec.HasKey("chain_id") {
config.ChainID = sec.Key("chain_id").String()
} else {
// backward compatibility; use profile name to determine
// (deprecated; require chain_id after 2010-01).
switch profile {
case "main", "default":
config.ChainID = params.MainnetChainID.String()
case "pangaea":
config.ChainID = params.PangaeaChainID.String()
case "partner":
config.ChainID = params.PartnerChainID.String()
case "stressnet":
config.ChainID = params.StressnetChainID.String()
default:
config.ChainID = params.TestnetChainID.String()
}
_, _ = fmt.Fprintf(os.Stderr,
"NOTICE: Chain ID not found in config profile, assuming %s; "+
"please add \"chain_id = %s\" to section [%s] of wallet.ini "+
"before 2020-01\n",
config.ChainID, config.ChainID, profile)
}
if sec.HasKey("shards") {
config.Shards = sec.Key("shards").MustInt()
config.RPCServer = make([][]p2p.Peer, config.Shards)
} else {
return nil, fmt.Errorf("can't find shards key")
}
for i := 0; i < config.Shards; i++ {
rpcSec, err := cfg.GetSection(fmt.Sprintf("%s.shard%v.rpc", profile, i))
if err != nil {
return nil, err
}
rpcKey := rpcSec.Key("rpc").ValueWithShadows()
for _, key := range rpcKey {
v := strings.Split(key, ":")
rpc := p2p.Peer{
IP: v[0],
Port: v[1],
}
config.RPCServer[i] = append(config.RPCServer[i], rpc)
}
}
return config, nil
}

@ -1,123 +0,0 @@
package wallet
import (
"io/ioutil"
"reflect"
"testing"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/p2p"
)
func TestReadWalletProfile(t *testing.T) {
config := []*Profile{
{
Profile: "default",
ChainID: params.MainnetChainID.String(),
Bootnodes: []string{"127.0.0.1:9000/abcd", "127.0.0.1:9999/daeg"},
Shards: 4,
Network: "mainnet",
RPCServer: [][]p2p.Peer{
{
{
IP: "127.0.0.4",
Port: "8888",
},
{
IP: "192.168.0.4",
Port: "9876",
},
},
{
{
IP: "127.0.0.1",
Port: "8888",
},
{
IP: "192.168.0.1",
Port: "9876",
},
},
{
{
IP: "127.0.0.2",
Port: "8888",
},
{
IP: "192.168.0.2",
Port: "9876",
},
},
{
{
IP: "127.0.0.3",
Port: "8888",
},
{
IP: "192.168.0.3",
Port: "9876",
},
},
},
},
{
Profile: "testnet",
ChainID: params.TestnetChainID.String(),
Bootnodes: []string{"192.168.0.1:9990/abcd", "127.0.0.1:8888/daeg"},
Shards: 3,
Network: "testnet",
RPCServer: [][]p2p.Peer{
{
{
IP: "192.168.2.3",
Port: "8888",
},
{
IP: "192.168.192.3",
Port: "9877",
},
},
{
{
IP: "192.168.2.1",
Port: "8888",
},
{
IP: "192.168.192.1",
Port: "9877",
},
},
{
{
IP: "192.168.2.2",
Port: "8888",
},
{
IP: "192.168.192.2",
Port: "9877",
},
},
},
},
}
testIniBytes, err := ioutil.ReadFile("test.ini")
if err != nil {
t.Fatalf("Failed to read test.ini: %v", err)
}
config1, err := ReadProfile(testIniBytes, "default")
if err != nil {
t.Fatalf("ReadProfile Error: %v", err)
}
if !reflect.DeepEqual(config[0], config1) {
t.Errorf("Got: %v\nExpect: %v\n", config1, config[0])
}
config2, err := ReadProfile(testIniBytes, "testnet")
if err != nil {
t.Fatalf("ReadProfile Error: %v", err)
}
if !reflect.DeepEqual(config[1], config2) {
t.Errorf("Got: %v\nExpect: %v\n", config2, config[1])
}
}

@ -1,39 +0,0 @@
[default]
bootnode = 127.0.0.1:9000/abcd
bootnode = 127.0.0.1:9999/daeg
shards = 4
network = mainnet
[default.shard0.rpc]
rpc = 127.0.0.4:8888
rpc = 192.168.0.4:9876
[default.shard1.rpc]
rpc = 127.0.0.1:8888
rpc = 192.168.0.1:9876
[default.shard2.rpc]
rpc = 127.0.0.2:8888
rpc = 192.168.0.2:9876
[default.shard3.rpc]
rpc = 127.0.0.3:8888
rpc = 192.168.0.3:9876
[testnet]
bootnode = 192.168.0.1:9990/abcd
bootnode = 127.0.0.1:8888/daeg
shards = 3
network = testnet
[testnet.shard0.rpc]
rpc = 192.168.2.3:8888
rpc = 192.168.192.3:9877
[testnet.shard1.rpc]
rpc = 192.168.2.1:8888
rpc = 192.168.192.1:9877
[testnet.shard2.rpc]
rpc = 192.168.2.2:8888
rpc = 192.168.192.2:9877

@ -719,7 +719,6 @@ func (node *Node) AddBeaconPeer(p *p2p.Peer) bool {
}
// isBeacon = true if the node is beacon node
// isClient = true if the node light client(wallet)
func (node *Node) initNodeConfiguration() (service.NodeConfig, chan p2p.Peer) {
chanPeer := make(chan p2p.Peer)

@ -2,17 +2,21 @@
### Services
In Harmony network, a node can be treated as one of the roles: validator, leader, beacon validator, beacon leader depending on its context. With each role, a node can run a certian set of services.
In Harmony network, a node can be treated as one of the roles: validator, leader, beacon validator,
beacon leader depending on its context. With each role, a node can run a certian set of services.
For example, a leader needs to run explorer support service, client support service, syncing support service etc.. while a normal validator does not run such many.
For example, a leader needs to run explorer support service, syncing support
service etc.. while a normal validator does not run such many.
### Service Manager
To support such behavior, we architecture Node logic with service manager which can wait for actions which each triggers its management operation such as starting some service, stopping some service.
To support such behavior, we architecture Node logic with service manager which can wait for actions
which each triggers its management operation such as starting some service, stopping some service.
Each service needs to implement minimal interace behavior like Start, Stop so that the service manager can handle those operation.
Each service needs to implement minimal interace behavior like Start, Stop so that the service
manager can handle those operation.
```golang
```go
// ServiceInterface is the collection of functions any service needs to implement.
type ServiceInterface interface {
StartService()
@ -22,15 +26,18 @@ type ServiceInterface interface {
### Creating a service.
To create a service, you need to have an struct which implements above interface function `StartService`, `StopService`.
To create a service, you need to have an struct which implements above interface function
`StartService`, `StopService`.
Since different services may have different ways to be created you may need to have a method `NewServiceABC` for service ABC with its own hooked params which returns the service object.
Since different services may have different ways to be created you may need to have a method
`NewServiceABC` for service ABC with its own hooked params which returns the service object.
### Action
Action is the input to operate Service Manager. We can send action to action channel of service manager to start or stop a service.
Action is the input to operate Service Manager. We can send action to action channel of service
manager to start or stop a service.
```golang
```go
// Action is type of service action.
type Action struct {
action ActionType
@ -41,12 +48,13 @@ type Action struct {
### Resharding
Service Manager is very handy to transform a node role from validator to leader or anything else. All we need to do is to stop all current services and start all services of the new role.
Service Manager is very handy to transform a node role from validator to leader or anything
else. All we need to do is to stop all current services and start all services of the new role.
### LibP2P Integration
We have enabled libp2p based gossiping using pubsub. Nodes no longer send messages to individual nodes.
All message communication is via SendMessageToGroups function.
We have enabled libp2p based gossiping using pubsub. Nodes no longer send messages to individual
nodes. All message communication is via SendMessageToGroups function.
- There would be 4 topics for sending and receiving of messages
@ -60,7 +68,7 @@ All message communication is via SendMessageToGroups function.
- **GroupIDBeacon**
- **GroupIDBeaconClient**.
- Every new node other than beacon chain nodes, wallet needs to subscribe to _THREE_ topics.
- Every new node other than beacon chain nodes
- **GroupIDBeaconClient**
- **GroupIDShard**
- **GroupIDShardClient**

@ -20,60 +20,67 @@ func (node *Node) setupForValidator() {
nodeConfig, chanPeer := node.initNodeConfiguration()
// Register peer discovery service. No need to do staking for beacon chain node.
node.serviceManager.RegisterService(service.PeerDiscovery, discovery.New(node.host, nodeConfig, chanPeer, node.AddBeaconPeer))
node.serviceManager.RegisterService(
service.PeerDiscovery,
discovery.New(node.host, nodeConfig, chanPeer, node.AddBeaconPeer),
)
// Register networkinfo service. "0" is the beacon shard ID
node.serviceManager.RegisterService(service.NetworkInfo, networkinfo.MustNew(node.host, node.NodeConfig.GetShardGroupID(), chanPeer, nil, node.networkInfoDHTPath()))
node.serviceManager.RegisterService(
service.NetworkInfo,
networkinfo.MustNew(
node.host, node.NodeConfig.GetShardGroupID(), chanPeer, nil, node.networkInfoDHTPath(),
),
)
// Register consensus service.
node.serviceManager.RegisterService(service.Consensus, consensus.New(node.BlockChannel, node.Consensus, node.startConsensus))
node.serviceManager.RegisterService(
service.Consensus,
consensus.New(node.BlockChannel, node.Consensus, node.startConsensus),
)
// Register new block service.
node.serviceManager.RegisterService(service.BlockProposal, blockproposal.New(node.Consensus.ReadySignal, node.WaitForConsensusReadyV2))
node.serviceManager.RegisterService(
service.BlockProposal,
blockproposal.New(node.Consensus.ReadySignal, node.WaitForConsensusReadyV2),
)
if node.NodeConfig.GetNetworkType() != nodeconfig.Mainnet {
// Register client support service.
node.serviceManager.RegisterService(service.ClientSupport, clientsupport.New(node.Blockchain().State, node.CallFaucetContract, node.SelfPeer.IP, node.SelfPeer.Port))
node.serviceManager.RegisterService(
service.ClientSupport,
clientsupport.New(
node.Blockchain().State, node.CallFaucetContract, node.SelfPeer.IP, node.SelfPeer.Port,
),
)
}
// Register new metrics service
if node.NodeConfig.GetMetricsFlag() {
node.serviceManager.RegisterService(service.Metrics, metrics.New(&node.SelfPeer, node.NodeConfig.ConsensusPubKey.SerializeToHexStr(), node.NodeConfig.GetPushgatewayIP(), node.NodeConfig.GetPushgatewayPort()))
node.serviceManager.RegisterService(
service.Metrics,
metrics.New(
&node.SelfPeer,
node.NodeConfig.ConsensusPubKey.SerializeToHexStr(),
node.NodeConfig.GetPushgatewayIP(),
node.NodeConfig.GetPushgatewayPort()),
)
}
// Register randomness service
// TODO: Disable drand. Currently drand isn't functioning but we want to compeletely turn it off for full protection.
// Enable it back after mainnet.
// Need Dynamically enable for beacon validators
// node.serviceManager.RegisterService(service.Randomness, randomness.New(node.DRand))
}
func (node *Node) setupForNewNode() {
// TODO determine the role of new node, currently assume it is beacon node
nodeConfig, chanPeer := node.initNodeConfiguration()
// Register peer discovery service. "0" is the beacon shard ID
node.serviceManager.RegisterService(service.PeerDiscovery, discovery.New(node.host, nodeConfig, chanPeer, node.AddBeaconPeer))
// Register networkinfo service. "0" is the beacon shard ID
node.serviceManager.RegisterService(service.NetworkInfo, networkinfo.MustNew(node.host, node.NodeConfig.GetBeaconGroupID(), chanPeer, nil, node.networkInfoDHTPath()))
// Register new metrics service
if node.NodeConfig.GetMetricsFlag() {
node.serviceManager.RegisterService(service.Metrics, metrics.New(&node.SelfPeer, node.NodeConfig.ConsensusPubKey.SerializeToHexStr(), node.NodeConfig.GetPushgatewayIP(), node.NodeConfig.GetPushgatewayPort()))
}
}
func (node *Node) setupForClientNode() {
// Register networkinfo service. "0" is the beacon shard ID
node.serviceManager.RegisterService(service.NetworkInfo, networkinfo.MustNew(node.host, nodeconfig.NewGroupIDByShardID(0), nil, nil, ""))
}
func (node *Node) setupForExplorerNode() {
nodeConfig, chanPeer := node.initNodeConfiguration()
// Register peer discovery service.
node.serviceManager.RegisterService(service.PeerDiscovery, discovery.New(node.host, nodeConfig, chanPeer, nil))
node.serviceManager.RegisterService(
service.PeerDiscovery, discovery.New(node.host, nodeConfig, chanPeer, nil),
)
// Register networkinfo service.
node.serviceManager.RegisterService(service.NetworkInfo, networkinfo.MustNew(node.host, node.NodeConfig.GetShardGroupID(), chanPeer, nil, node.networkInfoDHTPath()))
// Register explorer service.
node.serviceManager.RegisterService(service.SupportExplorer, explorer.New(&node.SelfPeer))
node.serviceManager.RegisterService(
service.NetworkInfo,
networkinfo.MustNew(
node.host, node.NodeConfig.GetShardGroupID(), chanPeer, nil, node.networkInfoDHTPath()),
)
// Register explorer service.
node.serviceManager.RegisterService(
service.SupportExplorer, explorer.New(&node.SelfPeer),
)
}
// ServiceManagerSetup setups service store.
@ -83,8 +90,6 @@ func (node *Node) ServiceManagerSetup() {
switch node.NodeConfig.Role() {
case nodeconfig.Validator:
node.setupForValidator()
case nodeconfig.ClientNode:
node.setupForClientNode()
case nodeconfig.ExplorerNode:
node.setupForExplorerNode()
}

@ -227,10 +227,7 @@ func New(self *p2p.Peer, priKey libp2p_crypto.PrivKey) (*HostV2, error) {
return nil, errors.Wrapf(err, "cannot initialize libp2p host")
}
traceFile := os.Getenv("P2P_TRACEFILE")
var options = make([]libp2p_pubsub.Option, 0, 0)
// increase the peer outbound queue size from default 32 to 64
options = append(options, libp2p_pubsub.WithPeerOutboundQueueSize(64))
options := []libp2p_pubsub.Option{libp2p_pubsub.WithPeerOutboundQueueSize(64)}
if len(traceFile) > 0 {
tracer, _ := libp2p_pubsub.NewJSONTracer(traceFile)
options = append(options, libp2p_pubsub.WithEventTracer(tracer))

@ -6,8 +6,6 @@ declare -A SRC
SRC[harmony]=cmd/harmony/main.go
# SRC[txgen]=cmd/client/txgen/main.go
SRC[bootnode]=cmd/bootnode/main.go
SRC[wallet]="cmd/client/wallet/main.go cmd/client/wallet/generated_wallet.ini.go"
# SRC[wallet_stress_test]="cmd/client/wallet_stress_test/main.go cmd/client/wallet_stress_test/generated_wallet.ini.go"
BINDIR=bin
BUCKET=unique-bucket-bin
@ -69,10 +67,9 @@ OPTIONS:
ACTION:
build build binaries only (default action)
upload upload binaries to s3
pubwallet upload wallet to public bucket (bucket: $PUBBUCKET)
release upload binaries to release bucket
harmony|txgen|bootnode|wallet
harmony|txgen|bootnode|
only build the specified binary
EXAMPLES:
@ -231,39 +228,6 @@ function release
[ -e $BINDIR/md5sum.txt ] && $AWSCLI s3 cp $BINDIR/md5sum.txt s3://${PUBBUCKET}/$FOLDER/md5sum.txt --acl public-read
}
function upload_wallet
{
AWSCLI=aws
if [ -n "$PROFILE" ]; then
AWSCLI+=" --profile $PROFILE"
fi
OS=$(uname -s)
case "$OS" in
"Linux")
FOLDER=release/linux-x86_64/$REL ;;
"Darwin")
FOLDER=release/darwin-x86_64/$REL ;;
*)
echo "Unsupported OS: $OS"
return ;;
esac
$AWSCLI s3 cp $BINDIR/wallet s3://$PUBBUCKET/$FOLDER/wallet --acl public-read
for lib in "${!LIB[@]}"; do
if [ -e ${LIB[$lib]} ]; then
$AWSCLI s3 cp ${LIB[$lib]} s3://${PUBBUCKET}/$FOLDER/$lib --acl public-read
else
echo "!! MISSING ${LIB[$lib]} !!"
fi
done
}
################################ MAIN FUNCTION ##############################
while getopts "hp:a:o:b:f:rvsdN:" option; do
@ -308,7 +272,6 @@ case "$ACTION" in
"build") build_only ;;
"upload") upload ;;
"release") release ;;
"pubwallet") upload_wallet ;;
"harmony"|"wallet"|"txgen"|"bootnode") build_only $ACTION ;;
"harmony"|"txgen"|"bootnode") build_only $ACTION ;;
*) usage ;;
esac

@ -24,39 +24,12 @@ else
touch .hmy/blspass.txt
fi
function check_result() {
err=false
echo "====== WALLET BALANCES ======" > $RESULT_FILE
$ROOT/bin/wallet -p local balances --address $ACC1 >> $RESULT_FILE
$ROOT/bin/wallet -p local balances --address $ACC2 >> $RESULT_FILE
$ROOT/bin/wallet -p local balances --address $ACC3 >> $RESULT_FILE
echo "====== RESULTS ======" >> $RESULT_FILE
TEST_ACC1=$($ROOT/bin/wallet -p local balances --address $ACC1 | grep 'Shard 0' | grep -oE 'nonce:.[0-9]+' | awk ' { print $2 } ')
TEST_ACC2=$($ROOT/bin/wallet -p local balances --address $ACC2 | grep 'Shard 1' | grep -oE 'nonce:.[0-9]+' | awk ' { print $2 } ')
BAL0_ACC3=$($ROOT/bin/wallet -p local balances --address $ACC3 | grep 'Shard 0' | grep -oE '[0-9]\.[0-9]+,' | awk -F\. ' { print $1 } ')
BAL1_ACC3=$($ROOT/bin/wallet -p local balances --address $ACC3 | grep 'Shard 1' | grep -oE '[0-9]\.[0-9]+,' | awk -F\. ' { print $1 } ')
if [[ $TEST_ACC1 -ne $NUM_TEST || $TEST_ACC2 -ne $NUM_TEST ]]; then
echo -e "FAIL number of nonce. Expected Result: $NUM_TEST.\nAccount1:$TEST_ACC1\nAccount2:$TEST_ACC2\n" >> $RESULT_FILE
err=true
fi
if [[ $BAL0_ACC3 -ne 1 || $BAL1_ACC3 -ne 1 ]]; then
echo "FAIL balance of $ACC3. Expected Result: 1.\nShard0:$BAL0_ACC3\nShard1:$BAL1_ACC3\n" >> $RESULT_FILE
err=true
fi
$err || echo "PASS" >> $RESULT_FILE
}
function cleanup() {
"${progdir}/kill_node.sh"
}
function cleanup_and_result() {
"${ROOT}/test/kill_node.sh" 2> /dev/null
[ -e $RESULT_FILE ] && cat $RESULT_FILE
"${ROOT}/test/kill_node.sh" 2> /dev/null || true
}
function debug_staking() {
@ -98,7 +71,6 @@ function usage {
USAGE: $ME [OPTIONS] config_file_name [extra args to node]
-h print this help message
-t disable wallet test (default: $DOTEST)
-D duration test run duration (default: $DURATION)
-m min_peers minimal number of peers to start consensus (default: $MIN)
-s shards number of shards (default: $SHARDS)
@ -117,25 +89,16 @@ EOU
exit 0
}
DEFAULT_DURATION_NOSYNC=60
DEFAULT_DURATION_SYNC=200
DOTEST=true
DURATION=
DURATION=60000
MIN=3
SHARDS=2
DRYRUN=
SYNC=true
NETWORK=localnet
NUM_TEST=10
ACC1=one1spshr72utf6rwxseaz339j09ed8p6f8ke370zj
ACC2=one1uyshu2jgv8w465yc8kkny36thlt2wvel89tcmg
ACC3=one1r4zyyjqrulf935a479sgqlpa78kz7zlcg2jfen
while getopts "htD:m:s:nBN:" option; do
while getopts "hD:m:s:nBN:" option; do
case $option in
h) usage ;;
t) DOTEST=false ;;
D) DURATION=$OPTARG ;;
m) MIN=$OPTARG ;;
s) SHARDS=$OPTARG ;;
@ -153,15 +116,6 @@ unset -v extra_args
declare -a extra_args
extra_args=("$@")
case "${DURATION-}" in
"")
case "${SYNC}" in
false) DURATION="${DEFAULT_DURATION_NOSYNC}";;
true) DURATION="${DEFAULT_DURATION_SYNC}";;
esac
;;
esac
# Kill nodes if any
cleanup
@ -182,7 +136,6 @@ log_folder="tmp_log/log-$t"
mkdir -p $log_folder
LOG_FILE=$log_folder/r.log
RESULT_FILE=$log_folder/result.txt
echo "launching boot node ..."
$DRYRUN $ROOT/bin/bootnode -port 19876 > $log_folder/bootnode.log 2>&1 | tee -a $LOG_FILE &
@ -221,24 +174,6 @@ while IFS='' read -r line || [[ -n "$line" ]]; do
i=$((i+1))
done < $config
if [ "$DOTEST" == "true" ]; then
# debug_staking
echo "waiting for some block rewards"
sleep 60
i=1
echo "launching wallet cross shard transfer test"
while [ $i -le $NUM_TEST ]; do
"${ROOT}/bin/wallet" -p local transfer --from $ACC1 --to $ACC3 --shardID 0 --toShardID 1 --amount 0.1 --pass pass:"" 2>&1 | tee -a "${LOG_FILE}"
"${ROOT}/bin/wallet" -p local transfer --from $ACC2 --to $ACC3 --shardID 1 --toShardID 0 --amount 0.1 --pass pass:"" 2>&1 | tee -a "${LOG_FILE}"
sleep 25
i=$((i+1))
done
echo "waiting for the result"
sleep 20
check_result
[ -e $RESULT_FILE ] && cat $RESULT_FILE
fi
sleep $DURATION
cleanup_and_result

@ -1,3 +1,3 @@
#!/bin/bash
pkill -9 '^(harmony|txgen|soldier|commander|profiler|beacon|bootnode)$' | sed 's/^/Killed process: /'
pkill -9 '^(harmony|txgen|soldier|commander|profiler|bootnode)$' | sed 's/^/Killed process: /'
rm -rf db-127.0.0.1-*

Loading…
Cancel
Save