139 lines
5.4 KiB
Nim
139 lines
5.4 KiB
Nim
# beacon_chain
|
|
# Copyright (c) 2018-2024 Status Research & Development GmbH
|
|
# Licensed and distributed under either of
|
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
{.push raises: [].}
|
|
|
|
import
|
|
chronicles, presto/client,
|
|
"."/[rest_types, eth2_rest_serialization, rest_common]
|
|
|
|
proc getValidatorsActivity*(epoch: Epoch,
|
|
body: seq[ValidatorIndex]
|
|
): RestPlainResponse {.
|
|
rest, endpoint: "/nimbus/v1/validator/activity/{epoch}",
|
|
meth: MethodPost.}
|
|
|
|
proc getTimesyncInifo*(body: RestNimbusTimestamp1): RestPlainResponse {.
|
|
rest, endpoint: "/nimbus/v1/timesync", meth: MethodPost.}
|
|
|
|
proc getTimeOffset*(client: RestClientRef,
|
|
delay: Duration): Future[int64] {.
|
|
async: (raises: [RestError, RestResponseError, CancelledError]).} =
|
|
let
|
|
timestamp1 = getTimestamp()
|
|
data = RestNimbusTimestamp1(timestamp1: timestamp1)
|
|
resp = await client.getTimesyncInifo(data)
|
|
timestamp4 = getTimestamp()
|
|
|
|
case resp.status
|
|
of 200:
|
|
if resp.contentType.isNone() or
|
|
isWildCard(resp.contentType.get().mediaType) or
|
|
resp.contentType.get().mediaType != ApplicationJsonMediaType:
|
|
raise newException(RestError, "Missing or incorrect Content-Type")
|
|
|
|
let stamps = decodeBytes(RestNimbusTimestamp2, resp.data,
|
|
resp.contentType).valueOr:
|
|
raise newException(RestError, $error)
|
|
|
|
trace "Time offset data",
|
|
timestamp1 = timestamp1,
|
|
timestamp2 = stamps.timestamp2,
|
|
timestamp3 = stamps.timestamp3,
|
|
timestamp4 = timestamp4,
|
|
delay14 = delay.nanoseconds,
|
|
delay23 = stamps.delay
|
|
|
|
# t1 - time when we sent request.
|
|
# t2 - time when remote server received request.
|
|
# t3 - time when remote server sent response.
|
|
# t4 - time when we received response.
|
|
# delay14 = validator client processing delay.
|
|
# delay23 = beacon node processing delay.
|
|
#
|
|
# Round-trip network delay `delta` = (t4 - t1) - (t3 - t2)
|
|
# but with delays this will be:
|
|
# `delta` = (t4 - t1 + delay14) - (t3 - t2 + delay23)
|
|
# Estimated server time is t3 + (delta div 2)
|
|
# Estimated clock skew `theta` = t3 + (delta div 2) - t4
|
|
let
|
|
delay14 = delay.nanoseconds
|
|
delay23 = int64(stamps.delay)
|
|
offset = (int64(stamps.timestamp2) - int64(timestamp1) +
|
|
int64(stamps.timestamp3) - int64(timestamp4) +
|
|
delay14 - delay23) div 2
|
|
offset
|
|
else:
|
|
let error = decodeBytes(RestErrorMessage, resp.data,
|
|
resp.contentType).valueOr:
|
|
let msg = "Incorrect response error format (" & $resp.status &
|
|
") [" & $error & "]"
|
|
raise (ref RestResponseError)(msg: msg, status: resp.status)
|
|
let msg = "Error response (" & $resp.status & ") [" & error.message & "]"
|
|
raise (ref RestResponseError)(
|
|
msg: msg, status: error.code, message: error.message)
|
|
|
|
proc getHistoricalSummariesV1Plain*(
|
|
state_id: StateIdent
|
|
): RestPlainResponse {.
|
|
rest,
|
|
endpoint: "/nimbus/v1/debug/beacon/states/{state_id}/historical_summaries",
|
|
accept: preferSSZ,
|
|
meth: MethodGet
|
|
.}
|
|
|
|
proc getHistoricalSummariesV1*(
|
|
client: RestClientRef, state_id: StateIdent, cfg: RuntimeConfig, restAccept = ""
|
|
): Future[Option[GetHistoricalSummariesV1Response]] {.
|
|
async: (
|
|
raises: [
|
|
CancelledError, RestEncodingError, RestDnsResolveError, RestCommunicationError,
|
|
RestDecodingError, RestResponseError,
|
|
]
|
|
)
|
|
.} =
|
|
let resp =
|
|
if len(restAccept) > 0:
|
|
await client.getHistoricalSummariesV1Plain(state_id, restAcceptType = restAccept)
|
|
else:
|
|
await client.getHistoricalSummariesV1Plain(state_id)
|
|
|
|
return
|
|
case resp.status
|
|
of 200:
|
|
if resp.contentType.isNone() or isWildCard(resp.contentType.get().mediaType):
|
|
raise newException(RestDecodingError, "Missing or incorrect Content-Type")
|
|
else:
|
|
let mediaType = resp.contentType.get().mediaType
|
|
if mediaType == ApplicationJsonMediaType:
|
|
let summaries = decodeBytes(
|
|
GetHistoricalSummariesV1Response, resp.data, resp.contentType
|
|
).valueOr:
|
|
raise newException(RestDecodingError, $error)
|
|
some(summaries)
|
|
elif mediaType == OctetStreamMediaType:
|
|
let summaries =
|
|
try:
|
|
SSZ.decode(resp.data, GetHistoricalSummariesV1Response)
|
|
except SerializationError as exc:
|
|
raise newException(RestDecodingError, exc.msg)
|
|
some(summaries)
|
|
else:
|
|
raise newException(RestDecodingError, "Unsupported Content-Type")
|
|
of 404:
|
|
none(GetHistoricalSummariesV1Response)
|
|
of 400, 500:
|
|
let error = decodeBytes(RestErrorMessage, resp.data, resp.contentType).valueOr:
|
|
let msg =
|
|
"Incorrect response error format (" & $resp.status & ") [" & $error & "]"
|
|
raise (ref RestResponseError)(msg: msg, status: resp.status)
|
|
let msg = "Error response (" & $resp.status & ") [" & error.message & "]"
|
|
raise
|
|
(ref RestResponseError)(msg: msg, status: error.code, message: error.message)
|
|
else:
|
|
raiseRestResponseError(resp)
|