diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 70c1d93d38..9ea39fe1e0 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -286,11 +286,12 @@ func createNodeConfigs(baseConfig gethConfig, initDir string, ips []string, port // Create the nodes enodes := make([]*enode.Node, size) for i := 0; i < size; i++ { - stack, err := node.New(&baseConfig.Node) + nodeConfig := baseConfig.Node + nodeConfig.DataDir = path.Join(initDir, fmt.Sprintf("node%d", i)) + stack, err := node.New(&nodeConfig) if err != nil { return nil, err } - stack.Config().DataDir = path.Join(initDir, fmt.Sprintf("node%d", i)) pk := stack.Config().NodeKey() enodes[i] = enode.NewV4(&pk.PublicKey, net.ParseIP(ips[i]), ports[i], ports[i]) } diff --git a/cmd/geth/initnetwork_test.go b/cmd/geth/initnetwork_test.go new file mode 100644 index 0000000000..1473f056e4 --- /dev/null +++ b/cmd/geth/initnetwork_test.go @@ -0,0 +1,147 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "strconv" + "strings" + "testing" +) + +var size int +var basePort int +var configPath string +var genesisPath string + +func setup(t *testing.T) { + size = 4 + _, filename, _, ok := runtime.Caller(0) + if !ok { + t.Fatalf("error getting current file path") + } + currentDirectory := filepath.Dir(filename) + configPath = filepath.Join(currentDirectory, "testdata/config.toml") + genesisPath = filepath.Join(currentDirectory, "testdata/parlia.json") + basePort = 30311 +} + +func TestInitNetworkLocalhost(t *testing.T) { + setup(t) + ipStr := "" + testInitNetwork(t, size, basePort, ipStr, configPath, genesisPath) +} + +func TestInitNetworkRemoteHosts(t *testing.T) { + setup(t) + ipStr := "192.168.24.103,172.15.67.89,10.0.17.36,203.113.45.76" + testInitNetwork(t, size, basePort, ipStr, configPath, genesisPath) +} + +func testInitNetwork(t *testing.T, size, basePort int, ipStr, configPath, genesisPath string) { + dir := t.TempDir() + geth := runGeth(t, "init-network", "--init.dir", dir, "--init.size", strconv.Itoa(size), + "--init.ips", ipStr, "--init.p2p-port", strconv.Itoa(basePort), "--config", configPath, + genesisPath) + // expect the command to complete first + geth.WaitExit() + + // Read the output of the command + files, err := os.ReadDir(dir) + if err != nil { + t.Fatal(err) + } + + if len(files) != size { + t.Fatalf("expected %d node folders but found %d instead", size, len(files)) + } + + for i, file := range files { + if file.IsDir() { + expectedNodeDirName := fmt.Sprintf("node%d", i) + if file.Name() != expectedNodeDirName { + t.Fatalf("node dir name is %s but %s was expected", file.Name(), expectedNodeDirName) + } + configFilePath := filepath.Join(dir, file.Name(), "config.toml") + var config gethConfig + err := loadConfig(configFilePath, &config) + if err != nil { + t.Fatalf("failed to load config.toml : %v", err) + } + if ipStr == "" { + verifyConfigFileLocalhost(t, &config, i, basePort, size) + } else { + verifyConfigFileRemoteHosts(t, &config, ipStr, i, basePort, size) + } + } + } +} + +func verifyConfigFileRemoteHosts(t *testing.T, config *gethConfig, ipStr string, i, basePort, size int) { + // 1. check ip string + ips := strings.Split(ipStr, ",") + if len(ips) != size { + t.Fatalf("found %d ips in ipStr=%s instead of %d", len(ips), ipStr, size) + } + + // 2. check listening port + expectedListenAddr := fmt.Sprintf(":%d", basePort) + if config.Node.P2P.ListenAddr != expectedListenAddr { + t.Fatalf("expected ListenAddr to be %s but it is %s instead", expectedListenAddr, config.Node.P2P.ListenAddr) + } + + bootnodes := config.Node.P2P.BootstrapNodes + + // 3. check correctness of peers' hosts + for j := 0; j < i; j++ { + ip := bootnodes[j].IP().String() + if ip != ips[j] { + t.Fatalf("expected IP of bootnode to be %s but found %s instead", ips[j], ip) + } + } + + for j := i + 1; j < size; j++ { + ip := bootnodes[j-1].IP().String() + if ip != ips[j] { + t.Fatalf("expected IP of bootnode to be %s but found %s instead", ips[j-1], ip) + } + } + + // 4. check correctness of peer port numbers + for j := 0; j < size-1; j++ { + if bootnodes[j].UDP() != basePort { + t.Fatalf("expected bootnode port at position %d to be %d but got %d instead", j, basePort, bootnodes[j].UDP()) + } + } +} + +func verifyConfigFileLocalhost(t *testing.T, config *gethConfig, i int, basePort int, size int) { + // 1. check listening port + expectedListenAddr := fmt.Sprintf(":%d", basePort+i) + if config.Node.P2P.ListenAddr != expectedListenAddr { + t.Fatalf("expected ListenAddr to be %s but it is %s instead", expectedListenAddr, config.Node.P2P.ListenAddr) + } + + bootnodes := config.Node.P2P.BootstrapNodes + // 2. check correctness of peers' hosts + localhost := "127.0.0.1" + for j := 0; j < size-1; j++ { + ip := bootnodes[j].IP().String() + if ip != localhost { + t.Fatalf("expected IP of bootnode to be %s but found %s instead", localhost, ip) + } + } + + // 3. check correctness of peer port numbers + for j := 0; j < i; j++ { + if bootnodes[j].UDP() != basePort+j { + t.Fatalf("expected bootnode port at position %d to be %d but got %d instead", j, basePort+j, bootnodes[j].UDP()) + } + } + for j := i + 1; j < size; j++ { + if bootnodes[j-1].UDP() != basePort+j { + t.Fatalf("expected bootnode port at position %d to be %d but got %d instead", j-1, basePort+j, bootnodes[j-1].UDP()) + } + } +} diff --git a/cmd/geth/testdata/config.toml b/cmd/geth/testdata/config.toml new file mode 100644 index 0000000000..cf1c7e58a6 --- /dev/null +++ b/cmd/geth/testdata/config.toml @@ -0,0 +1,62 @@ +[Eth] +NetworkId = 714 +SyncMode = "full" +NoPruning = false +NoPrefetch = false +LightPeers = 100 +DatabaseCache = 512 +DatabaseFreezer = "" +TrieCleanCache = 256 +TrieDirtyCache = 256 +TriesInMemory = 128 +TrieTimeout = 3600000000000 +EnablePreimageRecording = false + +[Eth.Miner] +GasFloor = 30000000 +GasCeil = 40000000 +GasPrice = 10000000000 +Recommit = 10000000000 + +[Eth.TxPool] +Locals = [] +NoLocals = true +Journal = "transactions.rlp" +Rejournal = 3600000000000 +PriceLimit = 10000000000 +PriceBump = 10 +AccountSlots = 16 +GlobalSlots = 4096 +AccountQueue = 64 +GlobalQueue = 1024 +Lifetime = 10800000000000 + + +[Node] +IPCPath = "geth.ipc" +HTTPHost = "0.0.0.0" +NoUSB = true +InsecureUnlockAllowed = true +HTTPPort = 8545 +HTTPVirtualHosts = ["*"] +HTTPModules = ["eth", "net", "web3", "txpool", "parlia"] +WSHost = "0.0.0.0" +WSPort = 8545 + +[Node.P2P] +MaxPeers = 50 +NoDiscovery = false +StaticNodes = [] +TrustedNodes = [] +EnableMsgEvents = false + +[Node.HTTPTimeouts] +ReadTimeout = 30000000000 +WriteTimeout = 30000000000 +IdleTimeout = 120000000000 + +[Node.LogConfig] +FilePath = "bsc.log" +MaxBytesSize = 10485760 +Level = "info" +FileRoot = "" \ No newline at end of file diff --git a/cmd/geth/testdata/parlia.json b/cmd/geth/testdata/parlia.json new file mode 100644 index 0000000000..6d8ca98d05 --- /dev/null +++ b/cmd/geth/testdata/parlia.json @@ -0,0 +1,33 @@ +{ + "config": { + "chainId": 714, + "homesteadBlock": 0, + "eip150Block": 0, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "ramanujanBlock": 0, + "nielsBlock": 0, + "mirrorSyncBlock":1, + "brunoBlock": 1, + "eulerBlock": 2, + "gibbsBlock": 3, + "parlia": { + "period": 3, + "epoch": 200 + } + }, + "nonce": "0x0", + "timestamp": "0x5e9da7ce", + "extraData": "0x00000000000000000000000000000000000000000000000000000000000000009fb29aac15b9a4b7f17c3385939b007540f4d7910000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x2625a00", + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE", + "alloc": {} +} \ No newline at end of file