You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
3.4 KiB

  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "sort"
  6. "time"
  7. e2e "github.com/tendermint/tendermint/test/e2e/pkg"
  8. )
  9. func Start(ctx context.Context, testnet *e2e.Testnet) error {
  10. if len(testnet.Nodes) == 0 {
  11. return fmt.Errorf("no nodes in testnet")
  12. }
  13. // Nodes are already sorted by name. Sort them by name then startAt,
  14. // which gives the overall order startAt, mode, name.
  15. nodeQueue := testnet.Nodes
  16. sort.SliceStable(nodeQueue, func(i, j int) bool {
  17. a, b := nodeQueue[i], nodeQueue[j]
  18. switch {
  19. case a.Mode == b.Mode:
  20. return false
  21. case a.Mode == e2e.ModeSeed:
  22. return true
  23. case a.Mode == e2e.ModeValidator && b.Mode == e2e.ModeFull:
  24. return true
  25. }
  26. return false
  27. })
  28. sort.SliceStable(nodeQueue, func(i, j int) bool {
  29. return nodeQueue[i].StartAt < nodeQueue[j].StartAt
  30. })
  31. if nodeQueue[0].StartAt > 0 {
  32. return fmt.Errorf("no initial nodes in testnet")
  33. }
  34. // Start initial nodes (StartAt: 0)
  35. logger.Info("Starting initial network nodes...")
  36. for len(nodeQueue) > 0 && nodeQueue[0].StartAt == 0 {
  37. node := nodeQueue[0]
  38. nodeQueue = nodeQueue[1:]
  39. if err := execCompose(testnet.Dir, "up", "-d", node.Name); err != nil {
  40. return err
  41. }
  42. if err := func() error {
  43. ctx, cancel := context.WithTimeout(ctx, time.Minute)
  44. defer cancel()
  45. _, err := waitForNode(ctx, node, 0)
  46. return err
  47. }(); err != nil {
  48. return err
  49. }
  50. node.HasStarted = true
  51. logger.Info(fmt.Sprintf("Node %v up on http://127.0.0.1:%v", node.Name, node.ProxyPort))
  52. }
  53. networkHeight := testnet.InitialHeight
  54. // Wait for initial height
  55. logger.Info("Waiting for initial height",
  56. "height", networkHeight,
  57. "nodes", len(testnet.Nodes)-len(nodeQueue),
  58. "pending", len(nodeQueue))
  59. block, blockID, err := waitForHeight(ctx, testnet, networkHeight)
  60. if err != nil {
  61. return err
  62. }
  63. for _, node := range nodeQueue {
  64. if node.StartAt > networkHeight {
  65. // if we're starting a node that's ahead of
  66. // the last known height of the network, then
  67. // we should make sure that the rest of the
  68. // network has reached at least the height
  69. // that this node will start at before we
  70. // start the node.
  71. logger.Info("Waiting for network to advance to height",
  72. "node", node.Name,
  73. "last_height", networkHeight,
  74. "waiting_for", node.StartAt,
  75. "size", len(testnet.Nodes)-len(nodeQueue),
  76. "pending", len(nodeQueue))
  77. networkHeight = node.StartAt
  78. block, blockID, err = waitForHeight(ctx, testnet, networkHeight)
  79. if err != nil {
  80. return err
  81. }
  82. }
  83. // Update any state sync nodes with a trusted height and hash
  84. if node.StateSync != e2e.StateSyncDisabled || node.Mode == e2e.ModeLight {
  85. err = UpdateConfigStateSync(node, block.Height, blockID.Hash.Bytes())
  86. if err != nil {
  87. return err
  88. }
  89. }
  90. if err := execCompose(testnet.Dir, "up", "-d", node.Name); err != nil {
  91. return err
  92. }
  93. wctx, wcancel := context.WithTimeout(ctx, 8*time.Minute)
  94. status, err := waitForNode(wctx, node, node.StartAt)
  95. if err != nil {
  96. wcancel()
  97. return err
  98. }
  99. wcancel()
  100. node.HasStarted = true
  101. var lastNodeHeight int64
  102. // If the node is a light client, we fetch its current height
  103. if node.Mode == e2e.ModeLight {
  104. lastNodeHeight = status.LightClientInfo.LastTrustedHeight
  105. } else {
  106. lastNodeHeight = status.SyncInfo.LatestBlockHeight
  107. }
  108. logger.Info(fmt.Sprintf("Node %v up on http://127.0.0.1:%v at height %v",
  109. node.Name, node.ProxyPort, lastNodeHeight))
  110. }
  111. return nil
  112. }