diff --git a/beacon_chain/rpc/rest_debug_api.nim b/beacon_chain/rpc/rest_debug_api.nim index cb4a305529..1013c09e75 100644 --- a/beacon_chain/rpc/rest_debug_api.nim +++ b/beacon_chain/rpc/rest_debug_api.nim @@ -138,52 +138,3 @@ proc installDebugApiHandlers*(router: var RestRouter, node: BeaconNode) = bestDescendant: item.bestDescendant)) RestApiResponse.jsonResponsePlain(response) - - router.metricsApi2( - MethodGet, - "/eth/v1/debug/beacon/states/{state_id}/historical_summaries", - {RestServerMetricsType.Status, Response}, - ) do(state_id: StateIdent) -> RestApiResponse: - let - sid = state_id.valueOr: - return RestApiResponse.jsonError(Http400, InvalidStateIdValueError, $error) - bslot = node.getBlockSlotId(sid).valueOr: - return RestApiResponse.jsonError(Http404, StateNotFoundError, $error) - contentType = preferredContentType(jsonMediaType, sszMediaType).valueOr: - return RestApiResponse.jsonError(Http406, ContentNotAcceptableError) - - node.withStateForBlockSlotId(bslot): - return withState(state): - when consensusFork >= ConsensusFork.Capella: - # Build the proof for historical_summaries field (28th field in BeaconState) - let gIndex = GeneralizedIndex(59) # 31 + 28 = 59 - var proof: array[5, Digest] - if forkyState.data.build_proof(gIndex, proof).isErr: - return RestApiResponse.jsonError(Http500, InvalidMerkleProofIndexError) - - if contentType == jsonMediaType: - let response = RestHistoricalSummaries( - historical_summaries: forkyState.data.historical_summaries.asSeq(), - proof: proof, - slot: bslot.slot, - ) - - RestApiResponse.jsonResponseFinalized( - response, node.getStateOptimistic(state), node.dag.isFinalized(bslot.bid) - ) - elif contentType == sszMediaType: - let - headers = [("eth-consensus-version", consensusFork.toString())] - response = GetHistoricalSummariesV1Response( - historical_summaries: forkyState.data.historical_summaries, - proof: proof, - slot: bslot.slot, - ) - - RestApiResponse.sszResponse(response, headers) - else: - RestApiResponse.jsonError(Http500, InvalidAcceptError) - else: - RestApiResponse.jsonError(Http404, HistoricalSummariesUnavailable) - - RestApiResponse.jsonError(Http404, StateNotFoundError) diff --git a/beacon_chain/rpc/rest_nimbus_api.nim b/beacon_chain/rpc/rest_nimbus_api.nim index 027ae72a62..09be4932c5 100644 --- a/beacon_chain/rpc/rest_nimbus_api.nim +++ b/beacon_chain/rpc/rest_nimbus_api.nim @@ -531,3 +531,52 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) = delay: uint64(delay.nanoseconds) ) RestApiResponse.jsonResponsePlain(response) + + router.metricsApi2( + MethodGet, + "/nimbus/v1/debug/beacon/states/{state_id}/historical_summaries", + {RestServerMetricsType.Status, Response}, + ) do(state_id: StateIdent) -> RestApiResponse: + let + sid = state_id.valueOr: + return RestApiResponse.jsonError(Http400, InvalidStateIdValueError, $error) + bslot = node.getBlockSlotId(sid).valueOr: + return RestApiResponse.jsonError(Http404, StateNotFoundError, $error) + contentType = preferredContentType(jsonMediaType, sszMediaType).valueOr: + return RestApiResponse.jsonError(Http406, ContentNotAcceptableError) + + node.withStateForBlockSlotId(bslot): + return withState(state): + when consensusFork >= ConsensusFork.Capella: + # Build the proof for historical_summaries field (28th field in BeaconState) + let gIndex = GeneralizedIndex(59) # 31 + 28 = 59 + var proof: array[5, Digest] + if forkyState.data.build_proof(gIndex, proof).isErr: + return RestApiResponse.jsonError(Http500, InvalidMerkleProofIndexError) + + if contentType == jsonMediaType: + let response = RestHistoricalSummaries( + historical_summaries: forkyState.data.historical_summaries.asSeq(), + proof: proof, + slot: bslot.slot, + ) + + RestApiResponse.jsonResponseFinalized( + response, node.getStateOptimistic(state), node.dag.isFinalized(bslot.bid) + ) + elif contentType == sszMediaType: + let + headers = [("eth-consensus-version", consensusFork.toString())] + response = GetHistoricalSummariesV1Response( + historical_summaries: forkyState.data.historical_summaries, + proof: proof, + slot: bslot.slot, + ) + + RestApiResponse.sszResponse(response, headers) + else: + RestApiResponse.jsonError(Http500, InvalidAcceptError) + else: + RestApiResponse.jsonError(Http404, HistoricalSummariesUnavailable) + + RestApiResponse.jsonError(Http404, StateNotFoundError) diff --git a/beacon_chain/spec/eth2_apis/rest_debug_calls.nim b/beacon_chain/spec/eth2_apis/rest_debug_calls.nim index 8592b3eaf3..c5c517d623 100644 --- a/beacon_chain/spec/eth2_apis/rest_debug_calls.nim +++ b/beacon_chain/spec/eth2_apis/rest_debug_calls.nim @@ -73,63 +73,3 @@ proc getStateV2*(client: RestClientRef, state_id: StateIdent, msg: msg, status: error.code, message: error.message) else: raiseRestResponseError(resp) - -proc getHistoricalSummariesV1Plain*( - state_id: StateIdent -): RestPlainResponse {. - rest, - endpoint: "/eth/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) diff --git a/beacon_chain/spec/eth2_apis/rest_nimbus_calls.nim b/beacon_chain/spec/eth2_apis/rest_nimbus_calls.nim index 3de4ceded1..3c488d475d 100644 --- a/beacon_chain/spec/eth2_apis/rest_nimbus_calls.nim +++ b/beacon_chain/spec/eth2_apis/rest_nimbus_calls.nim @@ -76,3 +76,63 @@ proc getTimeOffset*(client: RestClientRef, 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)