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 }