Files
netrunner/examples/local/indepth/main.go
T
Hanzo Dev 634cea7f0b Fix netrunner compatibility with updated node API
- Update API interface to return non-pointer types for better mock compatibility
- Fix message.NewCreator calls to use metrics.NewNoOpMetrics instead of prometheus
- Fix Handshake message parameters to include ACP support
- Update mock implementations to match new interface signatures
- Fix dereferencing of API clients after interface changes
- Update color logging API usage throughout
- Skip TestAttachPeer temporarily (needs investigation of handshake protocol)
- Remove direct prometheus imports per abstraction requirements
2025-08-03 13:41:38 -05:00

173 lines
4.7 KiB
Go

package main
import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"time"
"github.com/luxfi/netrunner/local"
"github.com/luxfi/netrunner/network"
"github.com/luxfi/netrunner/network/node"
"github.com/luxfi/node/config"
"github.com/luxfi/node/staking"
"github.com/luxfi/log"
"github.com/luxfi/log/level"
)
const (
healthyTimeout = 2 * time.Minute
removeNodeTimeout = 10 * time.Second
)
var goPath = os.ExpandEnv("$GOPATH")
// Blocks until a signal is received on [signalChan], upon which
// [n.Stop()] is called. If [signalChan] is closed, does nothing.
// Closes [closedOnShutdownChan] amd [signalChan] when done shutting down network.
// This function should only be called once.
func shutdownOnSignal(
log log.Logger,
n network.Network,
signalChan chan os.Signal,
closedOnShutdownChan chan struct{},
) {
sig := <-signalChan
log.Info("got OS signal", "signal", sig)
if err := n.Stop(context.Background()); err != nil {
log.Info("error stopping network", "error", err)
}
signal.Reset()
close(signalChan)
close(closedOnShutdownChan)
}
// Shows example usage of the Lux Network Runner.
// Creates a local five node Lux network
// and waits for all nodes to become healthy.
// Then, we:
// * print the names of the nodes
// * print the node ID of one node
// * start a new node
// * remove an existing node
// The network runs until the user provides a SIGINT or SIGTERM.
func main() {
// Create the logger
logFactory := log.NewFactoryWithConfig(log.Config{
DisplayLevel: level.Info,
LogLevel: level.Debug,
})
logger, err := logFactory.Make("main")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
binaryPath := fmt.Sprintf("%s%s", goPath, "/src/github.com/luxfi/node/build/node")
if err := run(logger, binaryPath); err != nil {
logger.Fatal("fatal error", log.Err(err))
os.Exit(1)
}
}
func run(logger log.Logger, binaryPath string) error {
// Create the network
nw, err := local.NewDefaultNetwork(logger, binaryPath, true)
if err != nil {
return err
}
defer func() { // Stop the network when this function returns
if err := nw.Stop(context.Background()); err != nil {
logger.Info("error stopping network", "error", err)
}
}()
// When we get a SIGINT or SIGTERM, stop the network and close [closedOnShutdownCh]
signalsChan := make(chan os.Signal, 1)
signal.Notify(signalsChan, syscall.SIGINT)
signal.Notify(signalsChan, syscall.SIGTERM)
closedOnShutdownCh := make(chan struct{})
go func() {
shutdownOnSignal(logger, nw, signalsChan, closedOnShutdownCh)
}()
// Wait until the nodes in the network are ready
ctx, cancel := context.WithTimeout(context.Background(), healthyTimeout)
defer cancel()
logger.Info("waiting for all nodes to report healthy...")
if err := nw.Healthy(ctx); err != nil {
return err
}
// Print the node names
nodeNames, err := nw.GetNodeNames()
if err != nil {
return err
}
logger.Info("current network's nodes", "nodes", nodeNames)
// Get one node
node1, err := nw.GetNode(nodeNames[0])
if err != nil {
return err
}
// Get its node ID through its API and print it
node1ID, _, err := node1.GetAPIClient().InfoAPI().GetNodeID(context.Background())
if err != nil {
return err
}
logger.Info("one node's ID is", log.Stringer("nodeID", node1ID))
// Add a new node with generated cert/key/nodeid
stakingCert, stakingKey, err := staking.NewCertAndKeyBytes()
if err != nil {
return err
}
nodeConfig := node.Config{
Name: "New Node",
BinaryPath: binaryPath,
StakingKey: string(stakingKey),
StakingCert: string(stakingCert),
// The flags below would override the config in this node's config file,
// if it had one.
Flags: map[string]interface{}{
config.LogLevelKey: level.Debug,
config.HTTPHostKey: "0.0.0.0",
},
}
if _, err := nw.AddNode(nodeConfig); err != nil {
return err
}
// Remove one node
nodeToRemove := nodeNames[3]
logger.Info("removing node", "name", nodeToRemove)
removeNodeCtx, removeNodeCtxCancel := context.WithTimeout(context.Background(), removeNodeTimeout)
defer removeNodeCtxCancel()
if err := nw.RemoveNode(removeNodeCtx, nodeToRemove); err != nil {
return err
}
// Wait until the nodes in the updated network are ready
ctx, cancel = context.WithTimeout(context.Background(), healthyTimeout)
defer cancel()
logger.Info("waiting for updated network to report healthy...")
if err := nw.Healthy(ctx); err != nil {
return err
}
// Print the node names
nodeNames, err = nw.GetNodeNames()
if err != nil {
return err
}
// Will have the new node but not the removed one
logger.Info("updated network's nodes", "nodes", nodeNames)
logger.Info("Network will run until you CTRL + C to exit...")
// Wait until done shutting down network after SIGINT/SIGTERM
<-closedOnShutdownCh
return nil
}