github.com/badrootd/nibiru-cometbft@v0.37.5-0.20240307173500-2a75559eee9b/test/e2e/runner/rpc.go (about) 1 package main 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "time" 8 9 rpchttp "github.com/badrootd/nibiru-cometbft/rpc/client/http" 10 rpctypes "github.com/badrootd/nibiru-cometbft/rpc/core/types" 11 e2e "github.com/badrootd/nibiru-cometbft/test/e2e/pkg" 12 "github.com/badrootd/nibiru-cometbft/types" 13 ) 14 15 // waitForHeight waits for the network to reach a certain height (or above), 16 // returning the highest height seen. Errors if the network is not making 17 // progress at all. 18 func waitForHeight(testnet *e2e.Testnet, height int64) (*types.Block, *types.BlockID, error) { 19 var ( 20 err error 21 maxResult *rpctypes.ResultBlock 22 clients = map[string]*rpchttp.HTTP{} 23 lastIncrease = time.Now() 24 ) 25 26 for { 27 for _, node := range testnet.Nodes { 28 if node.Mode == e2e.ModeSeed { 29 continue 30 } 31 client, ok := clients[node.Name] 32 if !ok { 33 client, err = node.Client() 34 if err != nil { 35 continue 36 } 37 clients[node.Name] = client 38 } 39 40 ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) 41 defer cancel() 42 result, err := client.Block(ctx, nil) 43 if err != nil { 44 continue 45 } 46 if result.Block != nil && (maxResult == nil || result.Block.Height >= maxResult.Block.Height) { 47 maxResult = result 48 lastIncrease = time.Now() 49 } 50 if maxResult != nil && maxResult.Block.Height >= height { 51 return maxResult.Block, &maxResult.BlockID, nil 52 } 53 } 54 55 if len(clients) == 0 { 56 return nil, nil, errors.New("unable to connect to any network nodes") 57 } 58 if time.Since(lastIncrease) >= 20*time.Second { 59 if maxResult == nil { 60 return nil, nil, errors.New("chain stalled at unknown height") 61 } 62 return nil, nil, fmt.Errorf("chain stalled at height %v", maxResult.Block.Height) 63 } 64 time.Sleep(1 * time.Second) 65 } 66 } 67 68 // waitForNode waits for a node to become available and catch up to the given block height. 69 func waitForNode(node *e2e.Node, height int64, timeout time.Duration) (*rpctypes.ResultStatus, error) { 70 client, err := node.Client() 71 if err != nil { 72 return nil, err 73 } 74 75 var curHeight int64 76 lastChanged := time.Now() 77 for { 78 status, err := client.Status(context.Background()) 79 switch { 80 case err != nil: 81 continue 82 case status.SyncInfo.LatestBlockHeight >= height && (height == 0 || !status.SyncInfo.CatchingUp): 83 return status, nil 84 case curHeight < status.SyncInfo.LatestBlockHeight: 85 curHeight = status.SyncInfo.LatestBlockHeight 86 lastChanged = time.Now() 87 case time.Since(lastChanged) > timeout: 88 return nil, fmt.Errorf("timed out waiting for %v to reach height %v", node.Name, height) 89 } 90 91 time.Sleep(300 * time.Millisecond) 92 } 93 } 94 95 // waitForAllNodes waits for all nodes to become available and catch up to the given block height. 96 func waitForAllNodes(testnet *e2e.Testnet, height int64, timeout time.Duration) (int64, error) { 97 var lastHeight int64 98 99 deadline := time.Now().Add(timeout) 100 101 for _, node := range testnet.Nodes { 102 if node.Mode == e2e.ModeSeed { 103 continue 104 } 105 106 status, err := waitForNode(node, height, time.Until(deadline)) 107 if err != nil { 108 return 0, err 109 } 110 111 if status.SyncInfo.LatestBlockHeight > lastHeight { 112 lastHeight = status.SyncInfo.LatestBlockHeight 113 } 114 } 115 116 return lastHeight, nil 117 }