github.com/prysmaticlabs/prysm@v1.4.4/endtoend/components/boot_node.go (about)

     1  package components
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"os/exec"
     9  	"strings"
    10  
    11  	"github.com/bazelbuild/rules_go/go/tools/bazel"
    12  	"github.com/prysmaticlabs/prysm/endtoend/helpers"
    13  	e2e "github.com/prysmaticlabs/prysm/endtoend/params"
    14  	e2etypes "github.com/prysmaticlabs/prysm/endtoend/types"
    15  )
    16  
    17  var _ e2etypes.ComponentRunner = (*BootNode)(nil)
    18  
    19  // BootNode represents boot node.
    20  type BootNode struct {
    21  	e2etypes.ComponentRunner
    22  	started chan struct{}
    23  	enr     string
    24  }
    25  
    26  // NewBootNode creates and returns boot node.
    27  func NewBootNode() *BootNode {
    28  	return &BootNode{
    29  		started: make(chan struct{}, 1),
    30  	}
    31  }
    32  
    33  // ENR exposes node's ENR.
    34  func (node *BootNode) ENR() string {
    35  	return node.enr
    36  }
    37  
    38  // Start starts a bootnode blocks up until ctx is cancelled.
    39  func (node *BootNode) Start(ctx context.Context) error {
    40  	binaryPath, found := bazel.FindBinary("tools/bootnode", "bootnode")
    41  	if !found {
    42  		log.Info(binaryPath)
    43  		return errors.New("boot node binary not found")
    44  	}
    45  
    46  	stdOutFile, err := helpers.DeleteAndCreateFile(e2e.TestParams.LogPath, e2e.BootNodeLogFileName)
    47  	if err != nil {
    48  		return err
    49  	}
    50  
    51  	args := []string{
    52  		fmt.Sprintf("--log-file=%s", stdOutFile.Name()),
    53  		fmt.Sprintf("--discv5-port=%d", e2e.TestParams.BootNodePort),
    54  		fmt.Sprintf("--metrics-port=%d", e2e.TestParams.BootNodePort+20),
    55  		"--debug",
    56  	}
    57  
    58  	cmd := exec.CommandContext(ctx, binaryPath, args...)
    59  	cmd.Stdout = stdOutFile
    60  	cmd.Stderr = stdOutFile
    61  	log.Infof("Starting boot node with flags: %s", strings.Join(args[1:], " "))
    62  	if err = cmd.Start(); err != nil {
    63  		return fmt.Errorf("failed to start beacon node: %w", err)
    64  	}
    65  
    66  	if err = helpers.WaitForTextInFile(stdOutFile, "Running bootnode"); err != nil {
    67  		return fmt.Errorf("could not find enr for bootnode, this means the bootnode had issues starting: %w", err)
    68  	}
    69  
    70  	node.enr, err = enrFromLogFile(stdOutFile.Name())
    71  	if err != nil {
    72  		return fmt.Errorf("could not get enr for bootnode: %w", err)
    73  	}
    74  
    75  	// Mark node as ready.
    76  	close(node.started)
    77  
    78  	return cmd.Wait()
    79  }
    80  
    81  // Started checks whether a boot node is started and ready to be queried.
    82  func (node *BootNode) Started() <-chan struct{} {
    83  	return node.started
    84  }
    85  
    86  func enrFromLogFile(name string) (string, error) {
    87  	byteContent, err := ioutil.ReadFile(name)
    88  	if err != nil {
    89  		return "", err
    90  	}
    91  	contents := string(byteContent)
    92  
    93  	searchText := "Running bootnode: "
    94  	startIdx := strings.Index(contents, searchText)
    95  	if startIdx == -1 {
    96  		return "", fmt.Errorf("did not find ENR text in %s", contents)
    97  	}
    98  	startIdx += len(searchText)
    99  	endIdx := strings.Index(contents[startIdx:], " prefix=bootnode")
   100  	if endIdx == -1 {
   101  		return "", fmt.Errorf("did not find ENR text in %s", contents)
   102  	}
   103  	return contents[startIdx : startIdx+endIdx-1], nil
   104  }