From dd49904baa0cf705a66af7875d2f1719a8244515 Mon Sep 17 00:00:00 2001 From: Maru Newby Date: Tue, 7 May 2024 18:06:31 -0700 Subject: [PATCH 1/2] [tmpnet] Enable single node networks --- tests/e2e/c/dynamic_fees.go | 4 +-- tests/e2e/e2e_test.go | 6 +---- tests/fixture/e2e/flags.go | 11 ++++++++ tests/fixture/e2e/helpers.go | 1 - tests/fixture/tmpnet/README.md | 5 ++-- tests/fixture/tmpnet/cmd/main.go | 2 +- tests/fixture/tmpnet/network.go | 39 +++++++++++++++++----------- tests/fixture/tmpnet/network_test.go | 4 +-- tests/fixture/tmpnet/node.go | 6 ++--- tests/upgrade/upgrade_test.go | 4 +-- 10 files changed, 47 insertions(+), 35 deletions(-) diff --git a/tests/e2e/c/dynamic_fees.go b/tests/e2e/c/dynamic_fees.go index 9af074894afc..c3dda77b985c 100644 --- a/tests/e2e/c/dynamic_fees.go +++ b/tests/e2e/c/dynamic_fees.go @@ -37,9 +37,7 @@ var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { ginkgo.It("should ensure that the gas price is affected by load", func() { ginkgo.By("creating a new private network to ensure isolation from other tests") - privateNetwork := &tmpnet.Network{ - Owner: "avalanchego-e2e-dynamic-fees", - } + privateNetwork := tmpnet.NewDefaultNetwork("avalanchego-e2e-dynamic-fees") e2e.Env.StartPrivateNetwork(privateNetwork) ginkgo.By("allocating a pre-funded key") diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 443a781281a3..08b0f2d2c03c 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/onsi/gomega" - "github.com/stretchr/testify/require" // ensure test packages are scanned by ginkgo _ "github.com/ava-labs/avalanchego/tests/e2e/banff" @@ -38,11 +37,8 @@ func init() { var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { // Run only once in the first ginkgo process - nodes, err := tmpnet.NewNodes(tmpnet.DefaultNodeCount) - require.NoError(ginkgo.GinkgoT(), err) - + nodes := tmpnet.NewNodesOrDie(flagVars.NodeCount()) subnets := vms.XSVMSubnets(nodes...) - return e2e.NewTestEnvironment( flagVars, &tmpnet.Network{ diff --git a/tests/fixture/e2e/flags.go b/tests/fixture/e2e/flags.go index 8af3cce6d787..bc752adaf7df 100644 --- a/tests/fixture/e2e/flags.go +++ b/tests/fixture/e2e/flags.go @@ -19,6 +19,7 @@ type FlagVars struct { reuseNetwork bool networkShutdownDelay time.Duration stopNetwork bool + nodeCount int } func (v *FlagVars) AvalancheGoExecPath() string { @@ -51,6 +52,10 @@ func (v *FlagVars) StopNetwork() bool { return v.stopNetwork } +func (v *FlagVars) NodeCount() int { + return v.nodeCount +} + func RegisterFlags() *FlagVars { vars := FlagVars{} flag.StringVar( @@ -89,6 +94,12 @@ func RegisterFlags() *FlagVars { false, "[optional] stop an existing network and exit without executing any tests.", ) + flag.IntVar( + &vars.nodeCount, + "node-count", + tmpnet.DefaultNodeCount, + "number of nodes the network should initially consist of", + ) return &vars } diff --git a/tests/fixture/e2e/helpers.go b/tests/fixture/e2e/helpers.go index 1395db1f8c29..358f07946055 100644 --- a/tests/fixture/e2e/helpers.go +++ b/tests/fixture/e2e/helpers.go @@ -233,7 +233,6 @@ func StartNetwork( DefaultNetworkDir, avalancheGoExecPath, pluginDir, - tmpnet.DefaultNodeCount, ), ) diff --git a/tests/fixture/tmpnet/README.md b/tests/fixture/tmpnet/README.md index b1158773d628..a7652ce43d8c 100644 --- a/tests/fixture/tmpnet/README.md +++ b/tests/fixture/tmpnet/README.md @@ -49,7 +49,7 @@ A temporary network can be managed by the `tmpnetctl` cli tool: # Build the tmpnetctl binary $ ./scripts/build_tmpnetctl.sh -# Start a new network +# Start a new network. Possible to specify the number of nodes (> 1) with --node-count. $ ./build/tmpnetctl start-network --avalanchego-path=/path/to/avalanchego ... Started network /home/me/.tmpnet/networks/20240306-152305.924531 (UUID: abaab590-b375-44f6-9ca5-f8a6dc061725) @@ -87,6 +87,7 @@ network := &tmpnet.Network{ // Configure non-default values fo DefaultFlags: tmpnet.FlagsMap{ config.LogLevelKey: "INFO", // Change one of the network's defaults }, + Nodes: tmpnet.NewNodesOrDie(5), // Number of initial validating nodes Subnets: []*tmpnet.Subnet{ // Subnets to create on the new network once it is running { Name: "xsvm-a", // User-defined name used to reference subnet in code and on disk @@ -97,6 +98,7 @@ network := &tmpnet.Network{ // Configure non-default values fo PreFundedKey: , // (Optional) A private key that is funded in the genesis bytes }, }, + ValidatorIDs: , // The IDs of nodes that validate the subnet }, }, } @@ -108,7 +110,6 @@ _ := tmpnet.StartNewNetwork( // Start the network "", // Empty string uses the default network path (~/tmpnet/networks) "/path/to/avalanchego", // The path to the binary that nodes will execute "/path/to/plugins", // The path nodes will use for plugin binaries (suggested value ~/.avalanchego/plugins) - 5, // Number of initial validating nodes ) uris := network.GetNodeURIs() diff --git a/tests/fixture/tmpnet/cmd/main.go b/tests/fixture/tmpnet/cmd/main.go index 7b415b32788b..039dd4c0b4da 100644 --- a/tests/fixture/tmpnet/cmd/main.go +++ b/tests/fixture/tmpnet/cmd/main.go @@ -66,6 +66,7 @@ func main() { network := &tmpnet.Network{ Owner: networkOwner, + Nodes: tmpnet.NewNodesOrDie(int(nodeCount)), } // Extreme upper bound, should never take this long @@ -80,7 +81,6 @@ func main() { rootDir, avalancheGoPath, pluginDir, - int(nodeCount), ) if err != nil { return err diff --git a/tests/fixture/tmpnet/network.go b/tests/fixture/tmpnet/network.go index faea1dde50f7..5e7eea3be807 100644 --- a/tests/fixture/tmpnet/network.go +++ b/tests/fixture/tmpnet/network.go @@ -47,9 +47,13 @@ const ( HardHatKeyStr = "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027" ) -// HardhatKey is a legacy used for hardhat testing in subnet-evm -// TODO(marun) Remove when no longer needed. -var HardhatKey *secp256k1.PrivateKey +var ( + // Key expected to be funded for subnet-evm hardhat testing + // TODO(marun) Remove when subnet-evm configures the genesis with this key. + HardhatKey *secp256k1.PrivateKey + + errInsufficientNodes = errors.New("network needs at least one node to start") +) func init() { hardhatKeyBytes, err := hex.DecodeString(HardHatKeyStr) @@ -105,6 +109,13 @@ type Network struct { Subnets []*Subnet } +func NewDefaultNetwork(owner string) *Network { + return &Network{ + Owner: owner, + Nodes: NewNodesOrDie(DefaultNodeCount), + } +} + // Ensure a real and absolute network dir so that node // configuration that embeds the network path will continue to // work regardless of symlink and working directory changes. @@ -123,9 +134,11 @@ func StartNewNetwork( rootNetworkDir string, avalancheGoExecPath string, pluginDir string, - nodeCount int, ) error { - if err := network.EnsureDefaultConfig(w, avalancheGoExecPath, pluginDir, nodeCount); err != nil { + if len(network.Nodes) == 0 { + return errInsufficientNodes + } + if err := network.EnsureDefaultConfig(w, avalancheGoExecPath, pluginDir); err != nil { return err } if err := network.Create(rootNetworkDir); err != nil { @@ -171,7 +184,7 @@ func ReadNetwork(dir string) (*Network, error) { } // Initializes a new network with default configuration. -func (n *Network) EnsureDefaultConfig(w io.Writer, avalancheGoPath string, pluginDir string, nodeCount int) error { +func (n *Network) EnsureDefaultConfig(w io.Writer, avalancheGoPath string, pluginDir string) error { if _, err := fmt.Fprintf(w, "Preparing configuration for new network with %s\n", avalancheGoPath); err != nil { return err } @@ -187,6 +200,11 @@ func (n *Network) EnsureDefaultConfig(w io.Writer, avalancheGoPath string, plugi } n.DefaultFlags.SetDefaults(DefaultFlags()) + if len(n.Nodes) == 1 { + // Sybil protection needs to be disabled for a single node network to start + n.DefaultFlags[config.SybilProtectionEnabledKey] = false + } + // Only configure the plugin dir with a non-empty value to ensure // the use of the default value (`[datadir]/plugins`) when // no plugin dir is configured. @@ -222,15 +240,6 @@ func (n *Network) EnsureDefaultConfig(w io.Writer, avalancheGoPath string, plugi n.DefaultRuntimeConfig.AvalancheGoPath = avalancheGoPath } - // Ensure nodes are created - if len(n.Nodes) == 0 { - nodes, err := NewNodes(nodeCount) - if err != nil { - return err - } - n.Nodes = nodes - } - // Ensure nodes are configured for i := range n.Nodes { if err := n.EnsureNodeConfig(n.Nodes[i]); err != nil { diff --git a/tests/fixture/tmpnet/network_test.go b/tests/fixture/tmpnet/network_test.go index c04c497c2485..db8d1c404716 100644 --- a/tests/fixture/tmpnet/network_test.go +++ b/tests/fixture/tmpnet/network_test.go @@ -15,8 +15,8 @@ func TestNetworkSerialization(t *testing.T) { tmpDir := t.TempDir() - network := &Network{} - require.NoError(network.EnsureDefaultConfig(&bytes.Buffer{}, "/path/to/avalanche/go", "", 1)) + network := NewDefaultNetwork("testnet") + require.NoError(network.EnsureDefaultConfig(&bytes.Buffer{}, "/path/to/avalanche/go", "")) require.NoError(network.Create(tmpDir)) // Ensure node runtime is initialized require.NoError(network.readNodes()) diff --git a/tests/fixture/tmpnet/node.go b/tests/fixture/tmpnet/node.go index 452d8d8e78ad..6b5d8759c951 100644 --- a/tests/fixture/tmpnet/node.go +++ b/tests/fixture/tmpnet/node.go @@ -104,16 +104,16 @@ func NewEphemeralNode(flags FlagsMap) *Node { } // Initializes the specified number of nodes. -func NewNodes(count int) ([]*Node, error) { +func NewNodesOrDie(count int) []*Node { nodes := make([]*Node, count) for i := range nodes { node := NewNode("") if err := node.EnsureKeys(); err != nil { - return nil, err + panic(err) } nodes[i] = node } - return nodes, nil + return nodes } // Reads a node's configuration from the specified directory. diff --git a/tests/upgrade/upgrade_test.go b/tests/upgrade/upgrade_test.go index 7114ac291d43..d3632853bc31 100644 --- a/tests/upgrade/upgrade_test.go +++ b/tests/upgrade/upgrade_test.go @@ -45,9 +45,7 @@ var _ = ginkgo.Describe("[Upgrade]", func() { require := require.New(ginkgo.GinkgoT()) ginkgo.It("can upgrade versions", func() { - network := &tmpnet.Network{ - Owner: "avalanchego-upgrade", - } + network := tmpnet.NewDefaultNetwork("avalanchego-upgrade") e2e.StartNetwork(network, avalancheGoExecPath, "" /* pluginDir */, 0 /* shutdownDelay */, false /* reuseNetwork */) ginkgo.By(fmt.Sprintf("restarting all nodes with %q binary", avalancheGoExecPathToUpgradeTo)) From b5c6acc059fa8a287af89e474853ad52c9cd03a2 Mon Sep 17 00:00:00 2001 From: Maru Newby Date: Tue, 7 May 2024 18:27:00 -0700 Subject: [PATCH 2/2] fixup: s/NewNodesOrDie/NewNodesOrPanic/ --- tests/e2e/e2e_test.go | 2 +- tests/fixture/tmpnet/README.md | 2 +- tests/fixture/tmpnet/cmd/main.go | 2 +- tests/fixture/tmpnet/network.go | 2 +- tests/fixture/tmpnet/node.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 08b0f2d2c03c..73c29b3bc83f 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -37,7 +37,7 @@ func init() { var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { // Run only once in the first ginkgo process - nodes := tmpnet.NewNodesOrDie(flagVars.NodeCount()) + nodes := tmpnet.NewNodesOrPanic(flagVars.NodeCount()) subnets := vms.XSVMSubnets(nodes...) return e2e.NewTestEnvironment( flagVars, diff --git a/tests/fixture/tmpnet/README.md b/tests/fixture/tmpnet/README.md index a7652ce43d8c..3c0679b4410d 100644 --- a/tests/fixture/tmpnet/README.md +++ b/tests/fixture/tmpnet/README.md @@ -87,7 +87,7 @@ network := &tmpnet.Network{ // Configure non-default values fo DefaultFlags: tmpnet.FlagsMap{ config.LogLevelKey: "INFO", // Change one of the network's defaults }, - Nodes: tmpnet.NewNodesOrDie(5), // Number of initial validating nodes + Nodes: tmpnet.NewNodesOrPanic(5), // Number of initial validating nodes Subnets: []*tmpnet.Subnet{ // Subnets to create on the new network once it is running { Name: "xsvm-a", // User-defined name used to reference subnet in code and on disk diff --git a/tests/fixture/tmpnet/cmd/main.go b/tests/fixture/tmpnet/cmd/main.go index 039dd4c0b4da..0e6bcb1fd0a0 100644 --- a/tests/fixture/tmpnet/cmd/main.go +++ b/tests/fixture/tmpnet/cmd/main.go @@ -66,7 +66,7 @@ func main() { network := &tmpnet.Network{ Owner: networkOwner, - Nodes: tmpnet.NewNodesOrDie(int(nodeCount)), + Nodes: tmpnet.NewNodesOrPanic(int(nodeCount)), } // Extreme upper bound, should never take this long diff --git a/tests/fixture/tmpnet/network.go b/tests/fixture/tmpnet/network.go index 5e7eea3be807..bd5b1b914efc 100644 --- a/tests/fixture/tmpnet/network.go +++ b/tests/fixture/tmpnet/network.go @@ -112,7 +112,7 @@ type Network struct { func NewDefaultNetwork(owner string) *Network { return &Network{ Owner: owner, - Nodes: NewNodesOrDie(DefaultNodeCount), + Nodes: NewNodesOrPanic(DefaultNodeCount), } } diff --git a/tests/fixture/tmpnet/node.go b/tests/fixture/tmpnet/node.go index 6b5d8759c951..99777e674c04 100644 --- a/tests/fixture/tmpnet/node.go +++ b/tests/fixture/tmpnet/node.go @@ -104,7 +104,7 @@ func NewEphemeralNode(flags FlagsMap) *Node { } // Initializes the specified number of nodes. -func NewNodesOrDie(count int) []*Node { +func NewNodesOrPanic(count int) []*Node { nodes := make([]*Node, count) for i := range nodes { node := NewNode("")