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

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
}