diff --git a/catchup/service.go b/catchup/service.go index 21c104ea48..2178f92eec 100644 --- a/catchup/service.go +++ b/catchup/service.go @@ -83,7 +83,7 @@ type Service struct { deadlineTimeout time.Duration blockValidationPool execpool.BacklogPool - // suspendForCatchpointWriting defines whether we've ran into a state where the ledger is currently busy writing the + // suspendForCatchpointWriting defines whether we've run into a state where the ledger is currently busy writing the // catchpoint file. If so, we want to suspend the catchup process until the catchpoint file writing is complete, // and resume from there without stopping the catchup timer. suspendForCatchpointWriting bool @@ -233,10 +233,10 @@ func (s *Service) innerFetch(r basics.Round, peer network.Peer) (blk *bookkeepin // fetchAndWrite fetches a block, checks the cert, and writes it to the ledger. Cert checking and ledger writing both wait for the ledger to advance if necessary. // Returns false if we should stop trying to catch up. This may occur for several reasons: -// - If the context is canceled (e.g. if the node is shutting down) -// - If we couldn't fetch the block (e.g. if there are no peers available or we've reached the catchupRetryLimit) -// - If the block is already in the ledger (e.g. if agreement service has already written it) -// - If the retrieval of the previous block was unsuccessful +// - If the context is canceled (e.g. if the node is shutting down) +// - If we couldn't fetch the block (e.g. if there are no peers available, or we've reached the catchupRetryLimit) +// - If the block is already in the ledger (e.g. if agreement service has already written it) +// - If the retrieval of the previous block was unsuccessful func (s *Service) fetchAndWrite(r basics.Round, prevFetchCompleteChan chan bool, lookbackComplete chan bool, peerSelector *peerSelector) bool { // If sync-ing this round is not intended, don't fetch it if dontSyncRound := s.GetDisableSyncRound(); dontSyncRound != 0 && r >= basics.Round(dontSyncRound) { @@ -258,10 +258,10 @@ func (s *Service) fetchAndWrite(r basics.Round, prevFetchCompleteChan chan bool, loggedMessage := fmt.Sprintf("fetchAndWrite(%d): block retrieval exceeded retry limit", r) if _, initialSync := s.IsSynchronizing(); initialSync { // on the initial sync, it's completly expected that we won't be able to get all the "next" blocks. - // Therefore info should suffice. + // Therefore, info should suffice. s.log.Info(loggedMessage) } else { - // On any subsequent sync, we migth be looking for multiple rounds into the future, so it's completly + // On any subsequent sync, we might be looking for multiple rounds into the future, so it's completely // reasonable that we would fail retrieving the future block. // Generate a warning here only if we're failing to retrieve X+1 or below. // All other block retrievals should not generate a warning. @@ -294,7 +294,7 @@ func (s *Service) fetchAndWrite(r basics.Round, prevFetchCompleteChan chan bool, s.log.Debugf("fetchAndWrite(%v): Could not fetch: %v (attempt %d)", r, err, i) peerSelector.rankPeer(psp, peerRankDownloadFailed) // we've just failed to retrieve a block; wait until the previous block is fetched before trying again - // to avoid the usecase where the first block doesn't exists and we're making many requests down the chain + // to avoid the usecase where the first block doesn't exist, and we're making many requests down the chain // for no reason. if !hasLookback { select { @@ -479,7 +479,7 @@ func (s *Service) pipelinedFetch(seedLookback uint64) { go func() { defer wg.Done() for t := range taskCh { - completed <- t() // This write to completed comes after a read from taskCh, so the invariant is preserved. + completed <- t() // This write comes after a read from taskCh, so the invariant is preserved. } }() } @@ -632,10 +632,10 @@ func (s *Service) periodicSync() { } // Syncs the client with the network. sync asks the network for last known block and tries to sync the system -// up the to the highest number it gets. +// up to the highest number it gets. func (s *Service) sync() { // Only run sync once at a time - // Store start time of sync - in NS so we can compute time.Duration (which is based on NS) + // Store start time of sync - in NS, so we can compute time.Duration (which is based on NS) start := time.Now() timeInNS := start.UnixNano() diff --git a/daemon/algod/api/algod.oas2.json b/daemon/algod/api/algod.oas2.json index fc8ae526cf..9c82d14c77 100644 --- a/daemon/algod/api/algod.oas2.json +++ b/daemon/algod/api/algod.oas2.json @@ -47,6 +47,36 @@ } } }, + "/ready": { + "get": { + "tags": [ + "public", + "common" + ], + "produces": [ + "application/json" + ], + "scheme": [ + "http" + ], + "summary": "Returns OK if healthy and fully caught up.", + "operationId": "GetReady", + "responses": { + "200": { + "description": "OK." + }, + "500": { + "description": "Internal Error" + }, + "503": { + "description": "Node not ready yet" + }, + "default": { + "description": "Unknown Error" + } + } + } + }, "/metrics": { "get": { "tags": [ diff --git a/daemon/algod/api/algod.oas3.yml b/daemon/algod/api/algod.oas3.yml index b8ae23ef22..687c0c8a6a 100644 --- a/daemon/algod/api/algod.oas3.yml +++ b/daemon/algod/api/algod.oas3.yml @@ -2126,6 +2126,34 @@ ] } }, + "/ready": { + "get": { + "operationId": "GetReady", + "responses": { + "200": { + "content": {}, + "description": "OK." + }, + "500": { + "content": {}, + "description": "Internal Error" + }, + "503": { + "content": {}, + "description": "Node not ready yet" + }, + "default": { + "content": {}, + "description": "Unknown Error" + } + }, + "summary": "Returns OK if healthy and fully caught up.", + "tags": [ + "public", + "common" + ] + } + }, "/swagger.json": { "get": { "description": "Returns the entire swagger spec in json.", diff --git a/daemon/algod/api/client/restClient.go b/daemon/algod/api/client/restClient.go index c9bdb0a833..65c895c50d 100644 --- a/daemon/algod/api/client/restClient.go +++ b/daemon/algod/api/client/restClient.go @@ -291,6 +291,12 @@ func (client RestClient) HealthCheck() error { return client.get(nil, "/health", nil) } +// ReadyCheck does a readiness check on the potentially running node, +// returning an error if the node is not ready (caught up and healthy) +func (client RestClient) ReadyCheck() error { + return client.get(nil, "/ready", nil) +} + // StatusAfterBlock waits for a block to occur then returns the StatusResponse after that block // blocks on the node end // Not supported diff --git a/daemon/algod/api/server/common/handlers.go b/daemon/algod/api/server/common/handlers.go index 0aa107f427..95a1dbcce1 100644 --- a/daemon/algod/api/server/common/handlers.go +++ b/daemon/algod/api/server/common/handlers.go @@ -18,14 +18,17 @@ package common import ( "encoding/json" + "fmt" "net/http" "github.com/labstack/echo/v4" + "github.com/algorand/go-algorand/agreement" "github.com/algorand/go-algorand/config" "github.com/algorand/go-algorand/daemon/algod/api" "github.com/algorand/go-algorand/daemon/algod/api/server/lib" "github.com/algorand/go-algorand/daemon/algod/api/spec/common" + "github.com/algorand/go-algorand/node" ) // GenesisJSON is an httpHandler for route GET /genesis @@ -89,6 +92,63 @@ func HealthCheck(ctx lib.ReqContext, context echo.Context) { json.NewEncoder(w).Encode(nil) } +// Ready is a httpHandler for route GET /ready +// it serves "readiness" probe on if the node is healthy and fully caught-up. +func Ready(ctx lib.ReqContext, context echo.Context) { + // swagger:operation GET /ready Ready + //--- + // Summary: Returns OK if healthy and fully caught up. + // Produces: + // - application/json + // Schemes: + // - http + // Responses: + // 200: + // description: OK. + // 500: + // description: Internal Error. + // 503: + // description: Node not ready yet. + // default: { description: Unknown Error } + w := context.Response().Writer + w.Header().Set("Content-Type", "application/json") + + stat, err := ctx.Node.Status() + code := http.StatusOK + + // isReadyFromStat checks the `Node.Status()` result + // and decide if the node is at the latest round + // must satisfy following sub conditions: + // 1. the node is not in a fast-catchup stage + // 2. the node's time since last round should be [0, deadline), + // while deadline = bigLambda + smallLambda = 17s + // 3. the node's catchup time is 0 + isReadyFromStat := func(status node.StatusReport) bool { + timeSinceLastRound := status.TimeSinceLastRound().Milliseconds() + + return len(status.Catchpoint) == 0 && + timeSinceLastRound >= 0 && + timeSinceLastRound < agreement.DeadlineTimeout().Milliseconds() && + status.CatchupTime.Milliseconds() == 0 + } + + if err != nil { + code = http.StatusInternalServerError + ctx.Log.Error(err) + } else if stat.StoppedAtUnsupportedRound { + code = http.StatusInternalServerError + err = fmt.Errorf("stopped at an unsupported round") + ctx.Log.Error(err) + } else if !isReadyFromStat(stat) { + code = http.StatusServiceUnavailable + err = fmt.Errorf("ready failed as the node is catching up") + ctx.Log.Info(err) + } + + w.WriteHeader(code) + _ = json.NewEncoder(w).Encode(nil) +} + // VersionsHandler is an httpHandler for route GET /versions func VersionsHandler(ctx lib.ReqContext, context echo.Context) { // swagger:route GET /versions GetVersion diff --git a/daemon/algod/api/server/common/routes.go b/daemon/algod/api/server/common/routes.go index 545d92bb27..1a78fe00ac 100644 --- a/daemon/algod/api/server/common/routes.go +++ b/daemon/algod/api/server/common/routes.go @@ -41,6 +41,13 @@ var Routes = lib.Routes{ HandlerFunc: HealthCheck, }, + lib.Route{ + Name: "ready", + Method: "GET", + Path: "/ready", + HandlerFunc: Ready, + }, + lib.Route{ Name: "swagger.json", Method: "GET", diff --git a/daemon/algod/api/server/common/test/handlers_test.go b/daemon/algod/api/server/common/test/handlers_test.go new file mode 100644 index 0000000000..c602b5bde0 --- /dev/null +++ b/daemon/algod/api/server/common/test/handlers_test.go @@ -0,0 +1,88 @@ +// Copyright (C) 2019-2023 Algorand, Inc. +// This file is part of go-algorand +// +// go-algorand is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// go-algorand is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with go-algorand. If not, see . + +package test + +import ( + "fmt" + "net/http" + "net/http/httptest" + "testing" + + "github.com/labstack/echo/v4" + "github.com/stretchr/testify/require" + + "github.com/algorand/go-algorand/daemon/algod/api/server/common" + "github.com/algorand/go-algorand/daemon/algod/api/server/lib" + "github.com/algorand/go-algorand/logging" + "github.com/algorand/go-algorand/node" + "github.com/algorand/go-algorand/test/partitiontest" +) + +func mockNodeStatusInRangeHelper( + t *testing.T, statusCode MockNodeCatchupStatus, + expectedErr error, expectedStatus node.StatusReport) { + mockNodeInstance := makeMockNode(statusCode) + status, err := mockNodeInstance.Status() + if expectedErr != nil { + require.Error(t, err, expectedErr) + } else { + require.Equal(t, expectedStatus, status) + } +} + +func TestMockNodeStatus(t *testing.T) { + partitiontest.PartitionTest(t) + + mockNodeStatusInRangeHelper( + t, CaughtUpAndReady, nil, cannedStatusReportCaughtUpAndReadyGolden) + mockNodeStatusInRangeHelper( + t, CatchingUpFast, nil, cannedStatusReportCatchingUpFastGolden) + mockNodeStatusInRangeHelper( + t, StoppedAtUnsupported, nil, cannedStatusReportStoppedAtUnsupportedGolden) + mockNodeStatusInRangeHelper( + t, 399, fmt.Errorf("catchup status out of scope error"), node.StatusReport{}) +} + +func readyEndpointTestHelper( + t *testing.T, node *mockNode, expectedCode int) { + reqCtx := lib.ReqContext{ + Node: node, + Log: logging.NewLogger(), + Shutdown: make(chan struct{}), + } + + e := echo.New() + req := httptest.NewRequest(http.MethodGet, "/", nil) + rec := httptest.NewRecorder() + c := e.NewContext(req, rec) + + common.Ready(reqCtx, c) + require.Equal(t, expectedCode, rec.Code) +} + +func TestReadyEndpoint(t *testing.T) { + partitiontest.PartitionTest(t) + + mockNodeInstance := makeMockNode(CaughtUpAndReady) + readyEndpointTestHelper(t, mockNodeInstance, http.StatusOK) + + mockNodeInstance.catchupStatus = CatchingUpFast + readyEndpointTestHelper(t, mockNodeInstance, http.StatusServiceUnavailable) + + mockNodeInstance.catchupStatus = StoppedAtUnsupported + readyEndpointTestHelper(t, mockNodeInstance, http.StatusInternalServerError) +} diff --git a/daemon/algod/api/server/common/test/helpers.go b/daemon/algod/api/server/common/test/helpers.go new file mode 100644 index 0000000000..27d534ad53 --- /dev/null +++ b/daemon/algod/api/server/common/test/helpers.go @@ -0,0 +1,139 @@ +// Copyright (C) 2019-2023 Algorand, Inc. +// This file is part of go-algorand +// +// go-algorand is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// go-algorand is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with go-algorand. If not, see . + +package test + +import ( + "fmt" + + "github.com/stretchr/testify/mock" + + "github.com/algorand/go-algorand/crypto" + "github.com/algorand/go-algorand/data/basics" + "github.com/algorand/go-algorand/node" + "github.com/algorand/go-algorand/protocol" +) + +var cannedStatusReportCaughtUpAndReadyGolden = node.StatusReport{ + LastRound: basics.Round(1), + LastVersion: protocol.ConsensusCurrentVersion, + NextVersion: protocol.ConsensusCurrentVersion, + NextVersionRound: basics.Round(2), + NextVersionSupported: true, + StoppedAtUnsupportedRound: false, + Catchpoint: "", + CatchpointCatchupAcquiredBlocks: 0, + CatchpointCatchupProcessedAccounts: 0, + CatchpointCatchupVerifiedAccounts: 0, + CatchpointCatchupTotalAccounts: 0, + CatchpointCatchupTotalKVs: 0, + CatchpointCatchupProcessedKVs: 0, + CatchpointCatchupVerifiedKVs: 0, + CatchpointCatchupTotalBlocks: 0, + LastCatchpoint: "", + CatchupTime: 0, +} + +var cannedStatusReportCatchingUpFastGolden = node.StatusReport{ + LastRound: basics.Round(97000), + LastVersion: protocol.ConsensusCurrentVersion, + NextVersion: protocol.ConsensusCurrentVersion, + NextVersionRound: 200000, + NextVersionSupported: true, + StoppedAtUnsupportedRound: false, + Catchpoint: "5894690#DVFRZUYHEFKRLK5N6DNJRR4IABEVN2D6H76F3ZSEPIE6MKXMQWQA", + CatchpointCatchupAcquiredBlocks: 0, + CatchpointCatchupProcessedAccounts: 0, + CatchpointCatchupVerifiedAccounts: 0, + CatchpointCatchupTotalAccounts: 0, + CatchpointCatchupTotalKVs: 0, + CatchpointCatchupProcessedKVs: 0, + CatchpointCatchupVerifiedKVs: 0, + CatchpointCatchupTotalBlocks: 0, + LastCatchpoint: "", + UpgradePropose: "upgradePropose", + UpgradeApprove: false, + UpgradeDelay: 0, + NextProtocolVoteBefore: 100000, + NextProtocolApprovals: 5000, + CatchupTime: 10000, +} + +var cannedStatusReportStoppedAtUnsupportedGolden = node.StatusReport{ + LastRound: basics.Round(97000), + LastVersion: protocol.ConsensusCurrentVersion, + NextVersion: protocol.ConsensusCurrentVersion, + NextVersionRound: 200000, + NextVersionSupported: true, + StoppedAtUnsupportedRound: true, + Catchpoint: "", + CatchpointCatchupAcquiredBlocks: 0, + CatchpointCatchupProcessedAccounts: 0, + CatchpointCatchupVerifiedAccounts: 0, + CatchpointCatchupTotalAccounts: 0, + CatchpointCatchupTotalKVs: 0, + CatchpointCatchupProcessedKVs: 0, + CatchpointCatchupVerifiedKVs: 0, + CatchpointCatchupTotalBlocks: 0, + LastCatchpoint: "", + UpgradePropose: "upgradePropose", + UpgradeApprove: false, + UpgradeDelay: 0, + NextProtocolVoteBefore: 100000, + NextProtocolApprovals: 5000, + CatchupTime: 0, +} + +// MockNodeCatchupStatus enumerates over possible mock status of a mock node in testing +type MockNodeCatchupStatus uint + +const ( + // CaughtUpAndReady stands for testing mock node is finishing catching up, /ready should return 200 + CaughtUpAndReady = iota + // CatchingUpFast stands for mock node is mocking fast catch up state, /ready should return 400 + CatchingUpFast + // StoppedAtUnsupported stands for mock node stopped at unsupported round, /ready should return 500 + StoppedAtUnsupported +) + +// mockNode is the "node" we use in common endpoint testing, implements NodeInterface +type mockNode struct { + mock.Mock + catchupStatus MockNodeCatchupStatus +} + +// makeMockNode creates a mock common node for ready endpoint testing. +func makeMockNode(catchupStatus MockNodeCatchupStatus) *mockNode { + return &mockNode{catchupStatus: catchupStatus} +} + +func (m *mockNode) Status() (s node.StatusReport, err error) { + switch m.catchupStatus { + case CaughtUpAndReady: + s = cannedStatusReportCaughtUpAndReadyGolden + case CatchingUpFast: + s = cannedStatusReportCatchingUpFastGolden + case StoppedAtUnsupported: + s = cannedStatusReportStoppedAtUnsupportedGolden + default: + err = fmt.Errorf("catchup status out of scope error") + } + return +} + +func (m *mockNode) GenesisID() string { panic("not implemented") } + +func (m *mockNode) GenesisHash() crypto.Digest { panic("not implemented") } diff --git a/daemon/algod/api/server/lib/common.go b/daemon/algod/api/server/lib/common.go index a04d85a951..e44e624c1b 100644 --- a/daemon/algod/api/server/lib/common.go +++ b/daemon/algod/api/server/lib/common.go @@ -23,6 +23,7 @@ import ( "github.com/algorand/go-algorand/crypto" "github.com/algorand/go-algorand/logging" + "github.com/algorand/go-algorand/node" ) // GenesisJSONText is initialized when the node starts. @@ -32,6 +33,7 @@ var GenesisJSONText string type NodeInterface interface { GenesisHash() crypto.Digest GenesisID() string + Status() (s node.StatusReport, err error) } // HandlerFunc defines a wrapper for http.HandlerFunc that includes a context @@ -57,8 +59,8 @@ type ReqContext struct { Shutdown <-chan struct{} } -// ErrorResponse sets the specified status code (should != 200), and fills in the -// a human readable error. +// ErrorResponse sets the specified status code (should != 200), and fills in +// a human-readable error. func ErrorResponse(w http.ResponseWriter, status int, internalErr error, publicErr string, logger logging.Logger) { logger.Info(internalErr) diff --git a/daemon/algod/api/server/v2/generated/data/routes.go b/daemon/algod/api/server/v2/generated/data/routes.go index 3630513e70..3400c168d6 100644 --- a/daemon/algod/api/server/v2/generated/data/routes.go +++ b/daemon/algod/api/server/v2/generated/data/routes.go @@ -299,22 +299,22 @@ var swaggerSpec = []string{ "L54vHmePnz5ePH389Itnz9MnTx8tnn7x/G/3jBwyKFtEZz5xf/Z/8F2/5OTNaXJukG1oQktWv8lu2Ng/", "TkRT3IlQUJbPjv1P/9vvsINUFA14/+vM5QXP1lqX6vjwcLPZHIRdDlfojkq0qNL1oR+n/xb2m9M6t8te", "ynFFbdqON7Z4VjjBb2+/OTsnJ29OD4K3Vo9nRwdHB4/wKc4SOC3Z7Hj2BH/C3bPGdT90zDY7/ng1nx2u", - "geYYvWH+KEBLlvpPakNXK5AH7pUm89Pl40OvShx+dK64q7Fvh2HB88OPLY9ltqcnFkQ+/Ojr/Iy3bhXS", - "cZ7aoMNELMaaHS4wfXhqU1BB4+Gp4AVDHX5EFXnw90OXUxn/iFcVuwcOvVs/3rJFpY96a3Dt9EipTtdV", - "efgR/4M8GaBlI5gDdGerWHmx70D79EPbw8Xn1YF5NW+fZrZ5L17MVfCyJU2P30170QH8cOammIFirswb", - "SgmzBZpN7FOVGhGtZQVh+c2xQjVX88jjp0u2qmTnUefOc9GEKfKfZz++JkISdyd+Q9OLOnKPnC5teRgp", - "LhkmNWVBJpzpWU/ntwrkrpmPOy7DCfgnI1yqWKFWZTuvolbFP2DtDUQUhcTjo6M7e7att7JX1txfg/N4", - "3QZiT6a+8Cdliw2NbHx69OjO5tYO1771xLrgerM65RgtZSQ/sScbTujpX3ZCL/AGbTh+yXhm39zQFPe0", - "3aA4vy//svPTrPA+WI7PF4FCBeDZHW6wT8+ERg+nOcGWdjZP/rKzOQN5yVIg51CUQlLJ8h35idf5yUFN", - "sv4x9xO/4GLDPSGMol0VBZU7dwRS0hVV/hiwx2HwgqTR8OhKoYsYq8DP5jOXfAjbEiQrgGNdkyt3Erd+", - "rc9nK+0O7bPk/Z933KUQ5hALyPuJK7BmV187YMfToUMbG5/tePq2Pkl7Jwju3j+O0/uLWeOLMgUjtv5g", - "kT9NRj/7lFT4tBv0k+2ot1CIS1D1S9wNcxoty9xc7KPcUhQBDx8M7qwPeO2Pa6/OG9EfyXtiGuA9VXbP", - "nrjpq9Yj8XiT8NwTQGvBT3kEuH5kt5OwY4e6F1ug2b8Ewb8EwR0KAl1JPrhFg/MLg8qhtPFyJKXpGsbk", - "Qf+0DG+6pYhV7DkbERauTsmQrDhry4o/9X33w5/ifH9Bud/PrRW3UYxU5gxkzQWU90vH/EsK/I+RArYG", - "lrMpzYmGPFfh3tcC974NJXC5QtyGeEyUA90nYmM/H35sP1HUMu6pdaUzsQn6okPYRjP0bX71o52tvw83", - "lOlkKaTLE8IS0v3OGmh+6CrgdH5tks57XzCTPvgxDG6L/npYV+iPfuwaXmNfneFxoJGvX+Y/N46X0JGB", - "ErJ2Ybz7YOQT1n91wrOxyx8fHmLs/VoofTi7mn/s2OzDjx9qlvCFAWelZJdYZ+DD1f8PAAD//5glD8aS", - "xwAA", + "geYYvWH+KEBLlvpPEmi2c/9XG7pagTxwLzaZny4fH3q14vCjc8tdjX07DIufH35seS+zPT2xOPLhR1/z", + "Z7x1q6iO89oGHSZiMdbscIGpxFObggoaD08FLxvq8COqy4O/H7r8yvhHvLbY/XDoXfzxli0qfdRbg2un", + "R0p1uq7Kw4/4H+TPAC0bzRygO1vFSo19B9qnItoeLlavDtKr+fw0s817sWOumpctb3r8btrrDuCHM7fG", + "DBRzJd9QYpjt0Gxon7bUiGstKwhLcY4VrbmaRx5CXbJVJTsPPHeejiZMkf88+/E1EZK4+/Ebml7UUXzk", + "dGlLxUhxyTDBKQuy4kzPejq/VSB3zXzc0RlOwD8f4dLGCrUq2zkWtVr+AetwIKIoMB4fHd3ZE269lb2y", + "pv8anMfrNhB78vWFPzVbbGjk5NOjR3c2t3bo9q0n1gXXm9Upx8gpcwoQe8rhhJ7+ZSf0Am/ThuOXjGf2", + "/Q1NcU/bDYrz+/IvOz/NCu+P5fiUEShUBp7d4Qb79ExodHKaE2xpZ/PkLzubM5CXLAVyDkUpJJUs35Gf", + "eJ2rHNQn6x9zP/ELLjbcE8Io3VVRULlzRyAlXVHljwF7HAavSRptj64UuouxIvxsPnOJiLAtQbICONY4", + "uXIncevX+ny20u7QPlHe/3nHXTphDrHgvJ+4AmuC9XUEdjwdOrSx8dmOp2/rk7R3guDu/eM4vb+YNb4o", + "UzB66w8W+dNk9LNPSYVPu0E/2Y56C4W4BFW/yt0wp9GyzC3GPtAtRRHw8MHgzvqAJoC49uo8E/2RvFem", + "Ad5TZffsiZu+cD0SmzcJzz3BtBb8lAeB6wd3O8k7dqh7sQWa/UsQ/EsQ3KEg0JXkg1s0OL8wwBxKGztH", + "UpquYUwe9E/L8KZbilj1nrMRYeFqlgzJirO2rPhT33c//CnO9xeU+/3cWnEb0UhlzkDWXEB5v4zMv6TA", + "/xgpYOthOZvSnGjIcxXufS1w79uwApc3xG24x0Q50H0uNvbz4cf2c0Ut455aVzoTm6AvOodtZEPf5lc/", + "4Nn6+3BDmU6WQrqcISwn3e+sgeaHrhpO59cmAb33BbPqgx/DQLfor4d1tf7ox67hNfbVGR4HGvlaZv5z", + "44QJnRooIWt3xrsPRj5hLVgnPBsb/fHhIcbhr4XSh7Or+ceO/T78+KFmCV8kcFZKdok1Bz5c/f8AAAD/", + "/12EssOexwAA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/daemon/algod/api/server/v2/generated/experimental/routes.go b/daemon/algod/api/server/v2/generated/experimental/routes.go index dbd1717c60..5978473978 100644 --- a/daemon/algod/api/server/v2/generated/experimental/routes.go +++ b/daemon/algod/api/server/v2/generated/experimental/routes.go @@ -229,14 +229,14 @@ var swaggerSpec = []string{ "Fy8XT7Onz58unj99/uKrl+mz508Wz1+8/MsDI4cMyhbRmU/cn/1vfNcvOXl3mpwbZBua0JLVb7IbNvaP", "E9EUdyIUlOWzY//T//Q77CAVRQPe/zpzecGztdalOj483Gw2B2GXwxW6oxItqnR96Mfpv4X97rTO7bKX", "clxRm7bjjS2eFU7w2/tvz87JybvTg+Ct1ePZ0cHRwRN8irMETks2O549w59w96xx3Q8ds82OP13PZ4dr", - "oDlGb5g/CtCSpf6T2tDVCuSBe6XJ/HT19NCrEoefnCvueuzbYVjw/PBTy2OZ7emJBZEPP/k6P+OtW4V0", - "nKc26DARi7FmhwtMH57aFFTQeHgqeMFQh59QRR78/dDlVMY/4lXF7oFD79aPt2xR6ZPeGlw7PVKq03VV", - "Hn7C/yBPBmjZCOY+urAtQTKjZNkAhpUtOlaz8Gk2O559GzR6tYb0EktsWyMD8ubTo6NIWkXQi9itQhc5", - "ZIbPnx89n9CBCx12csVg+h1/5pdcbDjBIFwrN6uioHKH+oiuJFfkpx8IWxLoDsGUHwH3Kl0pNPZjPd/Z", - "fNYiz8drRzSboHlo35BtaOl/3vE0+mOf+t23TGI/H35q19JtcaFaVzoTm6Av3lzstbs/Xv26ROvvww1l", - "2ugiLqAFax31O2ug+aFL1er82kRH975gyHfwY2iFjf56WJeSi37sSojYV7dDBhr5RFv/udEQwhN3dvwh", - "OGs/fLz+aL5J0xo/NQfI8eEhOonXQunD2fX8U+dwCT9+rHnMZ7DPSsmuMCD+4/X/CwAA//9Ow4gVO7YA", - "AA==", + "oDlGb5g/CtCSpf6TBJrt3P/Vhq5WIA/ci03mp6unh16tOPzk3HLXY98Ow+Lnh59a3stsT08sjnz4ydf8", + "GW/dKqrjvLZBh4lYjDU7XGAq8dSmoILGw1PBy4Y6/ITq8uDvhy6/Mv4Rry12Pxx6F3+8ZYtKn/TW4Nrp", + "kVKdrqvy8BP+B/kzQMtGM/fRhW0JkhmFywYzrGwBspqdT7PZ8ezboNGrNaSXWG7bGhyQT58eHUVSLIJe", + "xG4busghMzz//Oj5hA5c6LCTKwzT7/gzv+RiwwkG5FoZWhUFlTvUTXQluSI//UDYkkB3CKb8CLhv6Uqh", + "4R9r+87msxZ5Pl47otlkzUP7nmxDS//zjqfRH/vU775rEvv58FO7rm6LC9W60pnYBH3xFmOv4P3x6pcm", + "Wn8fbijTRi9xwS1Y96jfWQPND13aVufXJlK69wXDv4MfQ4ts9NfDuqxc9GNXQsS+uh0y0Mgn3frPjbYQ", + "nr6z4w/Bufvh4/VH802a1vipOUyODw/RYbwWSh/OruefOgdN+PFjzWM+m31WSnaFwfEfr/9fAAAA//8X", + "+h8qR7YAAA==", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/daemon/algod/api/server/v2/generated/nonparticipating/private/routes.go b/daemon/algod/api/server/v2/generated/nonparticipating/private/routes.go index 5a78c685d7..4644cf9f12 100644 --- a/daemon/algod/api/server/v2/generated/nonparticipating/private/routes.go +++ b/daemon/algod/api/server/v2/generated/nonparticipating/private/routes.go @@ -284,19 +284,19 @@ var swaggerSpec = []string{ "5y9mj7PHTx/Pnj5++vzZi/TJ00ezp89f/PWelUMWZUJ04hP3J/8X3/VLTt6eJucW2YYmvBD1m+yWjf3j", "RDzFnQgrLvLJsf/pf/sddpCqVQPe/zpxecGTpTGFPj48vLq6Ogi7HC7QHZUYVaXLQz9O/y3st6d1bhdd", "ynFFKW3HG1s8K5zgt3ffnJ2zk7enB8Fbq8eTo4Ojg0f4FGcBkhdicjx5gj/h7lniuh86Zpscf7qeTg6X", - "wHOM3rB/rMCUIvWf9BVfLKA8cK802Z8uHx96VeLwk3PFXW/7dhgWPD/81PJYZjt6YkHkw0++zs/21q1C", - "Os5TG3QYicW2ZoczTB8e2xR00Hh4KnjB0IefUEUe/P3Q5VTGP+JVhfbAoXfrx1u2qPTJrC2unR4pN+my", - "Kg4/4X+QJ69JSOQQc+JTKiJnTfMpE4bxmSqxwI5Jl1Yu+MoeQgctJ8ipxOSnmWVu2+slYeBreFFR0+P3", - "fZMJAmIeEkoCy+bNRm2N1MhiU1YQ1tmsT5pW++a8eX+UvPj46dH00dH1X+x54v589uR6ZDTOyxouO6sP", - "i5ENP2JZDDTE4P59fHR0iwdjT2RAflqk4F3iXqUpWolhq61bqg4gVhNjR/p+B3zsBbrr6eTpnjPeaj9q", - "xVdHXpL7mmfMZ+fi2I8+39inEmOhrFxndG5dTyfPPufsT6VleZ4zbBnUY+ov/U/yQqor6VtaJaNarXi5", - "8dtYt4QCc4uNRxlfaPSFleKSo24nlWw9MjP5iP7XWIb0gLzRht9A3pzZXv+WN59L3uAi3YW8aQO6Y3nz", - "eM89/+ef8b8l7J9Nwp6RuLuVhHUKHyWl9TVQWBdQihVIKo3lfqWiEof07n3/541Moz/2wXffX4v9fPip", - "Xf+/pTnrZWUydUUVT6JHBRa55bmriIem0fqaZRTzAJpAbfajS6TKN2gPFhkwjhUeVGWae7DtXHvIa0+F", - "hdC8zbgQEgdAkzOOQqUfeRACqSFVkl4y6xxLDrM3KoP+sYQHz28VlJvm5HE4TqYtueQYK1Jo8dZivi9G", - "rvdjOzSNk1+nzxz182Wtvw+vuDD28HIR00jRfmcDPD90tQA6vzbpd70vmFMY/Bi6+aO/Hta1iqMfu1fQ", - "2Fd3BRto5Cu5+M+NCSo06SBL1Mac9x/tymIlPMctjYXi+PAQoxCXSpvDyfX0U8d6EX78WC+mL5FUL+r1", - "x+v/CQAA//8iVBu0nMAAAA==", + "wHOM3rB/rMCUIvWfSuDZxv1fX/HFAsoD92KT/eny8aFXKw4/Obfc9bZvh2Hx88NPLe9ltqMnFkc+/ORr", + "/mxv3Sqq47y2QYeRWGxrdjjDVOKxTUEHjYengpcNffgJ1eXB3w9dfmX8I15baD8cehd/vGWLSp/M2uLa", + "6ZFyky6r4vAT/gf585oERg4xhz6lJXLWNJ8yYRifqRKL7Zh0aWWEr/IhdNByglxLDH+aWUa3vV4SBr6e", + "FxU4PX7fN58gIOYhoVSwLN9s2tZIjVw2ZQVhzc361Gm1b86e90fJi4+fHk0fHV3/xZ4t7s9nT65HRua8", + "rOGys/rgGNnwI5bIQKMM7uXHR0e3eDz2RAbkp0UK3ijuVZ2ilRi24Lql6gBiNTF2pPJ3wMdeo7ueTp7u", + "OeOttqRWrHXkVbmvecZ8pi6O/ejzjX0qMS7KynhGZ9j1dPLsc87+VFqW5znDlkFtpv7S/yQvpLqSvqVV", + "OKrVipcbv411Sygwt9h4rPGFRr9YKS456nlSydaDM5OP6IuNZUsPyBtt+A3kzZnt9W9587nkDS7SXcib", + "NqA7ljeP99zzf/4Z/1vC/tkk7BmJu1tJWKfwUYJaXwOFdQGlWIGkMlnuVyowcUhv4Pd/3sg0+mMffPct", + "ttjPh5/abwG0NGe9rEymrqj6SfSowIK3PHfV8dBMWl+5jGIeQBO0zX50SVX5Bm3DIgPGsdqDqkxzJ7ad", + "a2957bWwEJp3GhdC4gBofsZRqAwkD8IhNaRK0qtmnWPJYfZGZdA/lvDg+a2CctOcPA7HybQllxxjRYou", + "3lrM98XI9X5sh2Zy8vH0maN+yqz19+EVF8YeXi56Gina72yA54euLkDn1yYVr/cF8wuDH0OXf/TXw7pu", + "cfRj9woa++quYAONfFUX/7kxR4XmHWSJ2rDz/qNdWayK57ilsVYcHx5iROJSaXM4uZ5+6lgywo8f68X0", + "5ZLqRb3+eP0/AQAA//8BfTNVqMAAAA==", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/daemon/algod/api/server/v2/generated/nonparticipating/public/routes.go b/daemon/algod/api/server/v2/generated/nonparticipating/public/routes.go index 05c0d6704b..92f483a663 100644 --- a/daemon/algod/api/server/v2/generated/nonparticipating/public/routes.go +++ b/daemon/algod/api/server/v2/generated/nonparticipating/public/routes.go @@ -726,82 +726,82 @@ var swaggerSpec = []string{ "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", - "Sjxv3///AQAA//9vBJZkzUsBAA==", + "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", + "j4xKsgusxPP2/f8fAAD//3fZs+vZSwEA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/daemon/algod/api/server/v2/generated/participating/private/routes.go b/daemon/algod/api/server/v2/generated/participating/private/routes.go index 0e5265896a..e36f4942e9 100644 --- a/daemon/algod/api/server/v2/generated/participating/private/routes.go +++ b/daemon/algod/api/server/v2/generated/participating/private/routes.go @@ -312,21 +312,21 @@ var swaggerSpec = []string{ "8pvni8fZ46ePF08fP/3m2fP0ydNHi6ffPP/TPcOHDMgW0JlP3J/9X3zXLzl5e5qcG2AbnNCS1W+yGzL2", "jxPRFE8iFJTls2P/0//2J+wgFUUzvP915vKCZ2utS3V8eHh1dXUQdjlcoTsq0aJK14d+nv5b2G9P69wu", "q5Tjjtq0HW9s8aRwgt/efXd2Tk7enh4Eb60ez44Ojg4e4VOcJXBastnx7An+hKdnjft+6Ihtdvzpej47", - "XAPNMXrD/FGAliz1n9QVXa1AHrhXmsxPl48PvShx+Mm54q7Hvh2GBc8PP7U8ltmOnlgQ+fCTr/Mz3rpV", - "SMd5aoMOE6EYa3a4wPThqU1BBY2Hl4IKhjr8hCLy4O+HLqcy/hFVFXsGDr1bP96yhaVPemNg7fRIqU7X", - "VXn4Cf+DNBmAZSOY++DCpgTJjJCFAQzuV5uBeGgfSe3/vOVp9Mf+8L3HOlYQTZ7ENEZaPyLfLxk8w7Nh", - "j9VphtxOdwN+bOVva/vAI/P46GivR8ymuQ+7YUb9+yPyaP7Iyq7ns6d7AjpqaWlFIkeAeUEz4vNYce5H", - "n2/uU45RQ4YDEsvhEYKnnw+Cdpn1H2FL3ghNvkdV5Ho+e/Y5d+KUG8GI5gRbBlWU+kfkZ37BxRX3LY1o", - "UBUFldvJx0fTlUJHlmSX1Almwcsbs4/oObW5ze2jdpJlPaK3IhIo/UJk2xGMFWpVuryjBmmNhMi4WUJf", - "xew/ZbqGSMSejSvxjhcuMpiFspuWFVzfkie0hWQDwmnEYoKmP3wLY+nrngWgRsPPuv5FO/Kkxxw7g9e1", - "6+un5L/ylK88peYpz46efL7pz0BeshTIORSlkFSyfEt+5nXW+I153EmWRWN220d/J48z2ncqMlgBTxwD", - "SxYi2/rKmK0JLsAqgz1B5vBTu7y9FQxnGeSgo/GI5vf64dH+IhZbcvqqJ+HYbl3O+2KLTYOy8cfvP1lt", - "yqgKjbLTBbHHGcOK5V3e9DHONcfI3ixkJTSxWMjcor4yoq+M6FbCzeTDM0W+iWoftiYL7d3Zc19eJVZY", - "i+o+KFN0lC96fO9k4/v6T0zfsbHPkJHgg/W/d9H8lUV8ZRG3YxE/QOQw4ql1TCNCdPvpQ1MZBgYvZd1H", - "pNCh4JtXOZVEwVQzxwmO6Iwbn4NrfG6lLoorq9NR3ryzF9nAu9XzvrK8ryzv34flnexmNG3B5Naa0QVs", - "C1rW+pBaVzoTV4F/AWGx8T59O3D9rG3r78MrynSyFNJl0mGR9X5nDTQ/dDWiOr82ZRl6X7DWRPBjGP4Z", - "/fWwfsMi+rHrmoh9dab5gUa+wp//3LgmQ1cfsvbayff+o2HLWCHZcf3Gc3V8eIjZKWuh9OHsev6p49UK", - "P36sSeBTfVc4Urj+eP0/AQAA///yZJv4tMoAAA==", + "XAPNMXrD/FGAliz1nyTQbOv+r67oagXywL3YZH66fHzoxYrDT84tdz327TAsfn74qeW9zHb0xOLIh598", + "zZ/x1q2iOs5rG3SYCMVYs8MFphJPbQoqaDy8FFQ21OEnFJcHfz90+ZXxj6i22PNw6F388ZYtLH3SGwNr", + "p0dKdbquysNP+B+kzwAsG83cBxc2JUhmBC4MZnC/2mzEQ/tgav/nLU+jP/aH7z3csYJoIiWmNNL6Qfl+", + "+eAZnhN7xE4z5Hy6G/xjq4BbOwgen8dHR3s9aDbNldgNOerfJZEH9EdWdj2fPd0T0FGrSysqOQLMC5oR", + "n9OKcz/6fHOfcowgMtyQWG6PEDz9fBC0S67/CFvyRmjyPaol1/PZs8+5E6fcCEk0J9gyqKjUPyI/8wsu", + "rrhvacSEqiio3E4+PpquFDq1JLukTkgLXuGYfUQvqs1zbh+1kyzrEb0Vl0DpFwLvnSGMFWpVuhykBmmN", + "tMi4WUJf3ew/a7qGSPSejTHxThguMpiFcpyWFVzfkie0BWYDwmnEeoJmQHwXY+lroAWgRkPRur5GO/Kk", + "hx07g9d17Otn5b/ylK88peYpz46efL7pz0BeshTIORSlkFSyfEt+5nUG+Y153EmWReN320d/J48zmngq", + "MlgBTxwDSxYi2/oqma0JLsAqhj1B5vBTu9S9FQxnGeSgo7GJ5vf6EdL+IhZbcvqqJ+HYbl3O+2KLTYMS", + "8sfvP1nNyqgNjeLTBbHHGcPq5V3e9DHONcfI3ixkJTSxWMjcor4yoq+M6FbCzeTDM0W+iWoftj4L7d3Z", + "c19qJVZki+o+KFN0lC96fO9k4/v6T0zfsXHQkJHgg/XFd9H8lUV8ZRG3YxE/QOQw4ql1TCNCdPvpQ1MZ", + "BgYyZd0HpdC54JtXOZVEwVQzxwmO6Iwbn4NrfG6lLoorq9NR3ry5F9nAu9XzvrK8ryzv34flnexmNG3B", + "5Naa0QVsC1rW+pBaVzoTV4F/AWGxsT99O3D9xG3r78MrynSyFNJl1WHB9X5nDTQ/dPWiOr82JRp6X7Du", + "RPBjGAoa/fWwfs8i+rHrmoh9dab5gUa+2p//3LgpQ7cfsvba4ff+o2HLWC3Zcf3Gi3V8eIiZKmuh9OHs", + "ev6p4+EKP36sSeBTfVc4Urj+eP0/AQAA//9LIy4uwMoAAA==", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/daemon/algod/api/server/v2/generated/participating/public/routes.go b/daemon/algod/api/server/v2/generated/participating/public/routes.go index 446e3e3558..d510355028 100644 --- a/daemon/algod/api/server/v2/generated/participating/public/routes.go +++ b/daemon/algod/api/server/v2/generated/participating/public/routes.go @@ -177,184 +177,184 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "Q9kAAA==", + "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", + "AP//DNixnk/ZAAA=", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/daemon/algod/api/server/v2/test/helpers.go b/daemon/algod/api/server/v2/test/helpers.go index e8837e3f97..d0409eadac 100644 --- a/daemon/algod/api/server/v2/test/helpers.go +++ b/daemon/algod/api/server/v2/test/helpers.go @@ -149,7 +149,6 @@ func makeMockNode(ledger v2.LedgerForAPI, genesisID string, nodeError error, sta func (m *mockNode) LedgerForAPI() v2.LedgerForAPI { return m.ledger } - func (m *mockNode) Status() (node.StatusReport, error) { return m.status, nil } diff --git a/node/follower_node.go b/node/follower_node.go index 34dc48c241..46b9136785 100644 --- a/node/follower_node.go +++ b/node/follower_node.go @@ -389,7 +389,7 @@ func (node *AlgorandFollowerNode) SetCatchpointCatchupMode(catchpointCatchupMode outCtxCh = ctxCh go func() { node.mu.Lock() - // check that the node wasn't canceled. If it have been canceled, it means that the node.Stop() was called, in which case + // check that the node wasn't canceled. If it has been canceled, it means that the node.Stop() was called, in which case // we should close the channel. if node.ctx.Err() == context.Canceled { close(ctxCh) diff --git a/test/e2e-go/features/catchup/basicCatchup_test.go b/test/e2e-go/features/catchup/basicCatchup_test.go index 435393f70d..7663e54b3e 100644 --- a/test/e2e-go/features/catchup/basicCatchup_test.go +++ b/test/e2e-go/features/catchup/basicCatchup_test.go @@ -35,9 +35,6 @@ func TestBasicCatchup(t *testing.T) { partitiontest.PartitionTest(t) defer fixtures.ShutdownSynchronizedTest(t) - if testing.Short() { - t.Skip() - } t.Parallel() a := require.New(fixtures.SynchronizedTest(t)) @@ -48,12 +45,12 @@ func TestBasicCatchup(t *testing.T) { var fixture fixtures.RestClientFixture // Give the second node (which starts up last) all the stake so that its proposal always has better credentials, - // and so that its proposal isn't dropped. Otherwise the test burns 17s to recover. We don't care about stake + // and so that its proposal isn't dropped. Otherwise, the test burns 17s to recover. We don't care about stake // distribution for catchup so this is fine. fixture.Setup(t, filepath.Join("nettemplates", "TwoNodes100Second.json")) defer fixture.Shutdown() - // Get 2nd node so we wait until we know they're at target block + // Get 2nd node, so we wait until we know they're at target block nc, err := fixture.GetNodeController("Node") a.NoError(err) @@ -75,6 +72,24 @@ func TestBasicCatchup(t *testing.T) { // Now, catch up err = fixture.LibGoalFixture.ClientWaitForRoundWithTimeout(cloneClient, waitForRound) a.NoError(err) + + cloneNC := fixture.GetNodeControllerForDataDir(cloneDataDir) + cloneRestClient := fixture.GetAlgodClientForController(cloneNC) + + // an immediate call for ready will error, for sync time != 0 + a.Error(cloneRestClient.ReadyCheck()) + + for { + status, err := cloneRestClient.Status() + a.NoError(err) + + if status.LastRound < 10 { + time.Sleep(250 * time.Millisecond) + continue + } + a.NoError(cloneRestClient.ReadyCheck()) + break + } } // TestCatchupOverGossip tests catchup across network versions diff --git a/test/e2e-go/features/catchup/catchpointCatchup_test.go b/test/e2e-go/features/catchup/catchpointCatchup_test.go index 1663a14192..5d4e9b1940 100644 --- a/test/e2e-go/features/catchup/catchpointCatchup_test.go +++ b/test/e2e-go/features/catchup/catchpointCatchup_test.go @@ -535,6 +535,161 @@ outer: a.NoError(err) } +// TestReadyEndpoint starts a two-node network (derived mainly from TestNodeTxHandlerRestart) +// Lets the primary node have the majority of the stake +// Waits until a catchpoint is created +// Let primary node catch up against the catchpoint, confirm ready endpoint is 503 +// Wait the primary node catch up to target round, and confirm ready endpoint is 200 +func TestReadyEndpoint(t *testing.T) { + partitiontest.PartitionTest(t) + defer fixtures.ShutdownSynchronizedTest(t) + + if testing.Short() { + t.Skip() + } + a := require.New(fixtures.SynchronizedTest(t)) + + consensus := make(config.ConsensusProtocols) + protoVersion := protocol.ConsensusCurrentVersion + catchpointCatchupProtocol := config.Consensus[protoVersion] + applyCatchpointConsensusChanges(&catchpointCatchupProtocol) + catchpointCatchupProtocol.StateProofInterval = 0 + consensus[protoVersion] = catchpointCatchupProtocol + + var fixture fixtures.RestClientFixture + fixture.SetConsensus(consensus) + fixture.SetupNoStart(t, filepath.Join("nettemplates", "TwoNodes50EachWithRelay.json")) + + // Get primary node + primaryNode, err := fixture.GetNodeController("Node1") + a.NoError(err) + // Get secondary node + secondNode, err := fixture.GetNodeController("Node2") + a.NoError(err) + // Get the relay + relayNode, err := fixture.GetNodeController("Relay") + a.NoError(err) + + // prepare its configuration file to set it to generate a catchpoint every 16 rounds. + cfg, err := config.LoadConfigFromDisk(primaryNode.GetDataDir()) + a.NoError(err) + const catchpointInterval = 16 + cfg.CatchpointInterval = catchpointInterval + cfg.CatchpointTracking = 2 + cfg.MaxAcctLookback = 2 + cfg.Archival = false + cfg.TxSyncIntervalSeconds = 200000 // disable txSync + + err = cfg.SaveToDisk(primaryNode.GetDataDir()) + a.NoError(err) + err = cfg.SaveToDisk(secondNode.GetDataDir()) + a.NoError(err) + + cfg, err = config.LoadConfigFromDisk(relayNode.GetDataDir()) + a.NoError(err) + cfg.TxSyncIntervalSeconds = 200000 // disable txSync + cfg.SaveToDisk(relayNode.GetDataDir()) + + fixture.Start() + defer fixture.LibGoalFixture.Shutdown() + + client1 := fixture.GetLibGoalClientFromNodeController(primaryNode) + client2 := fixture.GetLibGoalClientFromNodeController(secondNode) + wallet1, err := client1.GetUnencryptedWalletHandle() + a.NoError(err) + wallet2, err := client2.GetUnencryptedWalletHandle() + a.NoError(err) + addrs1, err := client1.ListAddresses(wallet1) + a.NoError(err) + addrs2, err := client2.ListAddresses(wallet2) + a.NoError(err) + + // let the second node have insufficient stake for proposing a block + tx, err := client2.SendPaymentFromUnencryptedWallet(addrs2[0], addrs1[0], 1000, 4999999999000000, nil) + a.NoError(err) + status, err := client1.Status() + a.NoError(err) + _, err = fixture.WaitForConfirmedTxn(status.LastRound+100, addrs1[0], tx.ID().String()) + a.NoError(err) + targetCatchpointRound := status.LastRound + + // ensure the catchpoint is created for targetCatchpointRound + timer := time.NewTimer(100 * time.Second) +outer: + for { + status, err = client1.Status() + a.NoError(err) + + var round basics.Round + if status.LastCatchpoint != nil && len(*status.LastCatchpoint) > 0 { + round, _, err = ledgercore.ParseCatchpointLabel(*status.LastCatchpoint) + a.NoError(err) + if uint64(round) >= targetCatchpointRound { + break + } + } + select { + case <-timer.C: + a.Failf("timeout waiting a catchpoint", "target: %d, got %d", targetCatchpointRound, round) + break outer + default: + time.Sleep(250 * time.Millisecond) + } + } + + ////////// + // NOTE // + ////////// + // THE *REAL* TEST STARTS HERE: + // We first ensure when a primary node is catching up, it is not ready + // Then when the primary node is at target round, it should satisfy ready 200 condition + + // let the primary node catchup + err = client1.Catchup(*status.LastCatchpoint) + a.NoError(err) + + // The primary node is catching up with its previous catchpoint + // Its status contain a catchpoint it is catching-up against, + // so it should not be ready, and ready-ness endpoint should 503 err. + a.Error(fixture.GetAlgodClientForController(primaryNode).ReadyCheck()) + + status1, err := client1.Status() + a.NoError(err) + targetRound := status1.LastRound + 5 + + // Wait for the network to start making progress again + primaryNodeRestClient := fixture.GetAlgodClientForController(primaryNode) + err = fixture.ClientWaitForRound(primaryNodeRestClient, targetRound, + 10*catchpointCatchupProtocol.AgreementFilterTimeout) + a.NoError(err) + + // The primary node has reached the target round, + // - the sync-time (aka catchup time should be 0.0) + // - the catchpoint should be empty (len == 0) + timer = time.NewTimer(100 * time.Second) + + for { + err = primaryNodeRestClient.ReadyCheck() + + if err != nil { + select { + case <-timer.C: + a.Fail("timeout") + break + default: + time.Sleep(250 * time.Millisecond) + continue + } + } + + status1, err = client1.Status() + a.NoError(err) + a.Equal(status1.CatchupTime, uint64(0)) + a.Empty(status1.Catchpoint) + break + } +} + // TestNodeTxSyncRestart starts a two-node and one relay network // Waits until a catchpoint is created // Lets the primary node have the majority of the stake diff --git a/test/e2e-go/features/followerNode/syncDeltas_test.go b/test/e2e-go/features/followerNode/syncDeltas_test.go index 83c131512a..2a8d2b9618 100644 --- a/test/e2e-go/features/followerNode/syncDeltas_test.go +++ b/test/e2e-go/features/followerNode/syncDeltas_test.go @@ -43,7 +43,7 @@ func TestBasicSyncMode(t *testing.T) { var fixture fixtures.RestClientFixture // Give the second node (which starts up last) all the stake so that its proposal always has better credentials, - // and so that its proposal isn't dropped. Otherwise the test burns 17s to recover. We don't care about stake + // and so that its proposal isn't dropped. Otherwise, the test burns 17s to recover. We don't care about stake // distribution so this is fine. fixture.Setup(t, filepath.Join("nettemplates", "TwoNodesFollower100Second.json")) defer fixture.Shutdown() @@ -53,7 +53,6 @@ func TestBasicSyncMode(t *testing.T) { a.NoError(err) // Let the network make some progress - a.NoError(err) waitForRound := uint64(5) err = fixture.ClientWaitForRoundWithTimeout(fixture.GetAlgodClientForController(nc), waitForRound) a.NoError(err) @@ -68,6 +67,7 @@ func TestBasicSyncMode(t *testing.T) { rResp, err := followClient.GetSyncRound() a.NoError(err) a.Equal(round, rResp.Round) + // make some progress to round err = fixture.ClientWaitForRoundWithTimeout(followClient, round) a.NoError(err) // retrieve state delta