diff --git a/routes/server.go b/routes/server.go index 2da2c5f4..0ae9fd24 100644 --- a/routes/server.go +++ b/routes/server.go @@ -317,7 +317,8 @@ const ( RoutePathStateChecksum = "/api/v0/state-checksum" // validators.go - RoutePathValidators = "/api/v0/validators" + RoutePathValidators = "/api/v0/validators" + RoutePathCheckNodeStatus = "/api/v0/check-node-status" // stake.go RoutePathStake = "/api/v0/stake" @@ -1353,6 +1354,13 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { fes.GetValidatorByPublicKeyBase58Check, PublicAccess, }, + { + "CheckNodeStatus", + []string{"POST", "OPTIONS"}, + RoutePathCheckNodeStatus, + fes.CheckNodeStatus, + PublicAccess, + }, { "CreateStakeTxn", []string{"POST", "OPTIONS"}, diff --git a/routes/validators.go b/routes/validators.go index 8b447ebf..9c6278cd 100644 --- a/routes/validators.go +++ b/routes/validators.go @@ -9,7 +9,9 @@ import ( "github.com/gorilla/mux" "github.com/holiman/uint256" "io" + "net" "net/http" + "time" ) type RegisterAsValidatorRequest struct { @@ -352,6 +354,44 @@ func (fes *APIServer) GetValidatorByPublicKeyBase58Check(ww http.ResponseWriter, } } +type CheckNodeStatusRequest struct { + NodeHostPort string `safeForLogging:"true"` +} + +type CheckNodeStatusResponse struct { + Success bool `safeForLogging:"true"` +} + +func (fes *APIServer) CheckNodeStatus(ww http.ResponseWriter, req *http.Request) { + // Decode request body. + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := CheckNodeStatusRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, "UnjailValidator: problem parsing request body") + return + } + + // We do an *extremely* simple check for now, which is that we just check to see if the node + // is reachable at all. + // TODO: We should beef this up to test an actual version handshake or something more robust. + conn, err := net.DialTimeout("tcp", requestData.NodeHostPort, 5*time.Second) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "Problem connecting to %v: %v", requestData.NodeHostPort, err)) + return + } + // If we get here it means we succeeded. Close the connection to clean up. + conn.Close() + + res := CheckNodeStatusResponse{ + Success: true, + } + if err := json.NewEncoder(ww).Encode(res); err != nil { + _AddInternalServerError(ww, "UnjailValidator: problem encoding response as JSON") + return + } +} + func _convertValidatorEntryToResponse( utxoView *lib.UtxoView, validatorEntry *lib.ValidatorEntry, params *lib.DeSoParams, ) *ValidatorResponse {