Some checks are pending
docker-build-cometbft / vars (push) Waiting to run
docker-build-cometbft / build-images (amd64, ubuntu-24.04) (push) Blocked by required conditions
docker-build-cometbft / build-images (arm64, ubuntu-24.04-arm) (push) Blocked by required conditions
docker-build-cometbft / merge-images (push) Blocked by required conditions
docker-build-e2e-node / vars (push) Waiting to run
docker-build-e2e-node / build-images (amd64, ubuntu-24.04) (push) Blocked by required conditions
docker-build-e2e-node / build-images (arm64, ubuntu-24.04-arm) (push) Blocked by required conditions
docker-build-e2e-node / merge-images (push) Blocked by required conditions
135 lines
3.5 KiB
Go
135 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sort"
|
|
"time"
|
|
|
|
"git.cw.tr/mukan-network/mukan-consensus/libs/log"
|
|
e2e "git.cw.tr/mukan-network/mukan-consensus/test/e2e/pkg"
|
|
"git.cw.tr/mukan-network/mukan-consensus/test/e2e/pkg/infra"
|
|
)
|
|
|
|
func Start(ctx context.Context, testnet *e2e.Testnet, p infra.Provider) 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...")
|
|
nodesAtZero := make([]*e2e.Node, 0)
|
|
for len(nodeQueue) > 0 && nodeQueue[0].StartAt == 0 {
|
|
nodesAtZero = append(nodesAtZero, nodeQueue[0])
|
|
nodeQueue = nodeQueue[1:]
|
|
}
|
|
err := p.StartNodes(context.Background(), nodesAtZero...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, node := range nodesAtZero {
|
|
if _, err := waitForNode(ctx, node, 0, 15*time.Second); err != nil {
|
|
return err
|
|
}
|
|
if node.PrometheusProxyPort > 0 {
|
|
logger.Info("start", "msg",
|
|
log.NewLazySprintf("Node %v up on http://%s:%v; with Prometheus on http://%s:%v/metrics",
|
|
node.Name,
|
|
node.ExternalIP,
|
|
node.ProxyPort,
|
|
node.ExternalIP,
|
|
node.PrometheusProxyPort,
|
|
),
|
|
)
|
|
} else {
|
|
logger.Info("start", "msg", log.NewLazySprintf("Node %v up on http://%s:%v",
|
|
node.Name,
|
|
node.ExternalIP,
|
|
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
|
|
}
|
|
|
|
// Update any state sync nodes with a trusted height and hash
|
|
for _, node := range nodeQueue {
|
|
if node.StateSync || node.Mode == e2e.ModeLight {
|
|
err = UpdateConfigStateSync(node, block.Height, blockID.Hash.Bytes())
|
|
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.
|
|
|
|
networkHeight = node.StartAt
|
|
|
|
logger.Info("Waiting for network to advance before starting catch up node",
|
|
"node", node.Name,
|
|
"height", networkHeight)
|
|
|
|
if _, _, err := waitForHeight(ctx, testnet, networkHeight); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
logger.Info("Starting catch up node", "node", node.Name, "height", node.StartAt)
|
|
|
|
err := p.StartNodes(context.Background(), node)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
status, err := waitForNode(ctx, node, node.StartAt, 3*time.Minute)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
logger.Info("start", "msg", log.NewLazySprintf("Node %v up on http://%s:%v at height %v",
|
|
node.Name, node.ExternalIP, node.ProxyPort, status.SyncInfo.LatestBlockHeight))
|
|
}
|
|
|
|
return nil
|
|
}
|