- package main
-
- import (
- "context"
- "fmt"
- "sort"
- "time"
-
- e2e "github.com/tendermint/tendermint/test/e2e/pkg"
- )
-
- func Start(ctx context.Context, testnet *e2e.Testnet) error {
- if len(testnet.Nodes) == 0 {
- return fmt.Errorf("no nodes in testnet")
- }
-
- // Nodes are already sorted by name. Sort them by name then startAt,
- // which gives the overall order startAt, mode, name.
- nodeQueue := testnet.Nodes
- sort.SliceStable(nodeQueue, func(i, j int) bool {
- a, b := nodeQueue[i], nodeQueue[j]
- switch {
- case a.Mode == b.Mode:
- return false
- case a.Mode == e2e.ModeSeed:
- return true
- case a.Mode == e2e.ModeValidator && b.Mode == e2e.ModeFull:
- return true
- }
- return false
- })
-
- sort.SliceStable(nodeQueue, func(i, j int) bool {
- return nodeQueue[i].StartAt < nodeQueue[j].StartAt
- })
-
- if nodeQueue[0].StartAt > 0 {
- return fmt.Errorf("no initial nodes in testnet")
- }
-
- // Start initial nodes (StartAt: 0)
- logger.Info("Starting initial network nodes...")
- for len(nodeQueue) > 0 && nodeQueue[0].StartAt == 0 {
- node := nodeQueue[0]
- nodeQueue = nodeQueue[1:]
- if err := execCompose(testnet.Dir, "up", "-d", node.Name); err != nil {
- return err
- }
-
- if err := func() error {
- ctx, cancel := context.WithTimeout(ctx, time.Minute)
- defer cancel()
-
- _, err := waitForNode(ctx, node, 0)
- return err
- }(); err != nil {
- return err
- }
- node.HasStarted = true
- logger.Info(fmt.Sprintf("Node %v up on http://127.0.0.1:%v", node.Name, node.ProxyPort))
- }
-
- networkHeight := testnet.InitialHeight
-
- // Wait for initial height
- logger.Info("Waiting for initial height",
- "height", networkHeight,
- "nodes", len(testnet.Nodes)-len(nodeQueue),
- "pending", len(nodeQueue))
-
- block, blockID, err := waitForHeight(ctx, testnet, networkHeight)
- if err != nil {
- return err
- }
-
- for _, node := range nodeQueue {
- if node.StartAt > networkHeight {
- // if we're starting a node that's ahead of
- // the last known height of the network, then
- // we should make sure that the rest of the
- // network has reached at least the height
- // that this node will start at before we
- // start the node.
-
- logger.Info("Waiting for network to advance to height",
- "node", node.Name,
- "last_height", networkHeight,
- "waiting_for", node.StartAt,
- "size", len(testnet.Nodes)-len(nodeQueue),
- "pending", len(nodeQueue))
-
- networkHeight = node.StartAt
-
- block, blockID, err = waitForHeight(ctx, testnet, networkHeight)
- if err != nil {
- return err
- }
- }
-
- // Update any state sync nodes with a trusted height and hash
- if node.StateSync != e2e.StateSyncDisabled || node.Mode == e2e.ModeLight {
- err = UpdateConfigStateSync(node, block.Height, blockID.Hash.Bytes())
- if err != nil {
- return err
- }
- }
-
- if err := execCompose(testnet.Dir, "up", "-d", node.Name); err != nil {
- return err
- }
-
- wctx, wcancel := context.WithTimeout(ctx, 8*time.Minute)
- status, err := waitForNode(wctx, node, node.StartAt)
- if err != nil {
- wcancel()
- return err
- }
- wcancel()
-
- node.HasStarted = true
-
- var lastNodeHeight int64
-
- // If the node is a light client, we fetch its current height
- if node.Mode == e2e.ModeLight {
- lastNodeHeight = status.LightClientInfo.LastTrustedHeight
- } else {
- lastNodeHeight = status.SyncInfo.LatestBlockHeight
- }
- logger.Info(fmt.Sprintf("Node %v up on http://127.0.0.1:%v at height %v",
- node.Name, node.ProxyPort, lastNodeHeight))
- }
-
- return nil
- }
|