Skip to content

Commit

Permalink
tmpnet: Add a UUID to temporary networks to support metrics collection
Browse files Browse the repository at this point in the history
Previously, tmpnet networks were only identified by their path on
disk. In anticipation of centralizing metrics collection for temporary
networks, tmpnet will now generate a UUID for each temporary network
to ensure a unique identifier across execution environments.
  • Loading branch information
marun committed Feb 23, 2024
1 parent 7c04667 commit e4134ca
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 62 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ concurrency:

env:
go_version: '~1.21.7'
tmpnet_data_path: ~/.tmpnet/networks/1000
tmpnet_data_path: ~/.tmpnet/networks

jobs:
Unit:
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ require (
github.com/ethereum/go-ethereum v1.12.0
github.com/google/btree v1.1.2
github.com/google/renameio/v2 v2.0.0
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
github.com/gorilla/rpc v1.2.0
github.com/gorilla/websocket v1.4.2
Expand Down Expand Up @@ -100,7 +101,6 @@ require (
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect
github.com/hashicorp/go-bexpr v0.1.10 // indirect
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
Expand Down
83 changes: 23 additions & 60 deletions tests/fixture/tmpnet/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ import (
"errors"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"strconv"
"strings"
"time"

"github.com/google/uuid"

"github.com/ava-labs/avalanchego/config"
"github.com/ava-labs/avalanchego/genesis"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/constants"
"github.com/ava-labs/avalanchego/utils/crypto/secp256k1"
"github.com/ava-labs/avalanchego/utils/perms"
"github.com/ava-labs/avalanchego/utils/set"
Expand All @@ -40,6 +40,9 @@ const (
// increase the time for a network's nodes to be seen as healthy.
networkHealthCheckInterval = 200 * time.Millisecond

// All temporary network will use this arbitrary default network ID by default.
defaultNetworkID = 88888

// eth address: 0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC
HardHatKeyStr = "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027"
)
Expand All @@ -61,6 +64,13 @@ func init() {

// Collects the configuration for running a temporary avalanchego network
type Network struct {
// Uniquely identifies the temporary network for storage on disk and
// metrics collection. Distinct from avalanchego's concept of network ID
// since the utility of special network ID values (e.g. to trigger specific
// fork behavior in a given network) precludes requiring unique network ID
// values across all temporary networks.
UUID string

// Path where network configuration and data is stored
Dir string

Expand Down Expand Up @@ -208,6 +218,7 @@ func (n *Network) EnsureDefaultConfig(w io.Writer, avalancheGoPath string, plugi

// Creates the network on disk, choosing its network id and generating its genesis in the process.
func (n *Network) Create(rootDir string) error {
// Ensure creation of the root dir
if len(rootDir) == 0 {
// Use the default root dir
var err error
Expand All @@ -216,48 +227,30 @@ func (n *Network) Create(rootDir string) error {
return err
}
}

// Ensure creation of the root dir
if err := os.MkdirAll(rootDir, perms.ReadWriteExecute); err != nil {
return fmt.Errorf("failed to create root network dir: %w", err)
}

// Determine the network path and ID
var (
networkDir string
networkID uint32
)
if n.Genesis != nil && n.Genesis.NetworkID > 0 {
// Use the network ID defined in the provided genesis
networkID = n.Genesis.NetworkID
// Ensure creation of the network dir
if len(n.UUID) == 0 {
n.UUID = uuid.NewString()
}
if networkID > 0 {
// Use a directory with a random suffix
var err error
networkDir, err = os.MkdirTemp(rootDir, fmt.Sprintf("%d.", n.Genesis.NetworkID))
if err != nil {
return fmt.Errorf("failed to create network dir: %w", err)
}
} else {
// Find the next available network ID based on the contents of the root dir
var err error
networkID, networkDir, err = findNextNetworkID(rootDir)
if err != nil {
return err
}
networkDir := filepath.Join(rootDir, n.UUID)
if err := os.MkdirAll(networkDir, perms.ReadWriteExecute); err != nil {
return fmt.Errorf("failed to create network dir: %w", err)
}
canonicalDir, err := toCanonicalDir(networkDir)
if err != nil {
return err
}
n.Dir = canonicalDir

// Ensure the existence of the plugin directory or nodes won't be able to start.
pluginDir, err := n.DefaultFlags.GetStringVal(config.PluginDirKey)
if err != nil {
return err
}
if len(pluginDir) > 0 {
// Ensure the existence of the plugin directory or nodes won't be able to start.
if err := os.MkdirAll(pluginDir, perms.ReadWriteExecute); err != nil {
return fmt.Errorf("failed to create plugin dir: %w", err)
}
Expand All @@ -275,7 +268,7 @@ func (n *Network) Create(rootDir string) error {
}
keysToFund = append(keysToFund, n.PreFundedKeys...)

genesis, err := NewTestGenesis(networkID, n.Nodes, keysToFund)
genesis, err := NewTestGenesis(defaultNetworkID, n.Nodes, keysToFund)
if err != nil {
return err
}
Expand All @@ -296,7 +289,7 @@ func (n *Network) Create(rootDir string) error {

// Starts all nodes in the network
func (n *Network) Start(ctx context.Context, w io.Writer) error {
if _, err := fmt.Fprintf(w, "Starting network %d @ %s\n", n.Genesis.NetworkID, n.Dir); err != nil {
if _, err := fmt.Fprintf(w, "Starting network %s\n", n.Dir); err != nil {
return err
}

Expand All @@ -313,7 +306,7 @@ func (n *Network) Start(ctx context.Context, w io.Writer) error {
if err := n.WaitForHealthy(ctx, w); err != nil {
return err
}
if _, err := fmt.Fprintf(w, "\nStarted network %d @ %s\n", n.Genesis.NetworkID, n.Dir); err != nil {
if _, err := fmt.Fprintf(w, "\nStarted network %s\n", n.Dir); err != nil {
return err
}

Expand Down Expand Up @@ -676,33 +669,3 @@ func getDefaultRootDir() (string, error) {
}
return filepath.Join(homeDir, ".tmpnet", "networks"), nil
}

// Finds the next available network ID by attempting to create a
// directory numbered from 1000 until creation succeeds. Returns the
// network id and the full path of the created directory.
func findNextNetworkID(rootDir string) (uint32, string, error) {
var (
networkID uint32 = 1000
dirPath string
)
for {
_, reserved := constants.NetworkIDToNetworkName[networkID]
if reserved {
networkID++
continue
}

dirPath = filepath.Join(rootDir, strconv.FormatUint(uint64(networkID), 10))
err := os.Mkdir(dirPath, perms.ReadWriteExecute)
if err == nil {
return networkID, dirPath, nil
}

if !errors.Is(err, fs.ErrExist) {
return 0, "", fmt.Errorf("failed to create network directory: %w", err)
}

// Directory already exists, keep iterating
networkID++
}
}
2 changes: 2 additions & 0 deletions tests/fixture/tmpnet/network_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,15 @@ func (n *Network) readConfig() error {

// The subset of network fields to store in the network config file.
type serializedNetworkConfig struct {
UUID string
DefaultFlags FlagsMap
DefaultRuntimeConfig NodeRuntimeConfig
PreFundedKeys []*secp256k1.PrivateKey
}

func (n *Network) writeNetworkConfig() error {
config := &serializedNetworkConfig{
UUID: n.UUID,
DefaultFlags: n.DefaultFlags,
DefaultRuntimeConfig: n.DefaultRuntimeConfig,
PreFundedKeys: n.PreFundedKeys,
Expand Down

0 comments on commit e4134ca

Please sign in to comment.