nimbus-eth2/beacon_chain/rpc/rest_debug_api.nim
Jacek Sieka 0e2b4e39fa
REST JSON support improvements (#3232)
* support downloading blocks / states via JSON in addition to SSZ -
slow, but needed for infura support - SSZ is still used when server
supports it
* use common forked block/state reader in REST API
* fix stack overflows in REST JSON decoder
* fix invalid serialization of `justification_bits` in
`/eth/v1/debug/beacon/states` and `/eth/v2/debug/beacon/states`
* fix REST client to use `/eth/...` instead of `/api/eth/...`, update
"default" urls to expose REST api via `/eth` as well as this is what the
standard says - `/api` was added early on based on an example "base url"
in the spec that has been removed since
* expose Nimbus REST extensions via `/nimbus` in addition to
`/api/nimbus` to stay consistent with `/eth`
* fix invalid state root when reading states via REST
* fix recursive imports in `spec/ssz_codec`
* remove usages of `serialization.useCustomSerialization` - fickle
2022-01-06 08:38:40 +01:00

112 lines
4.2 KiB
Nim

# beacon_chain
# Copyright (c) 2021-2022 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.
import std/sequtils
import chronicles
import ".."/[version, beacon_node],
".."/spec/forks,
"."/[rest_utils, state_ttl_cache]
export rest_utils
logScope: topics = "rest_debug"
proc installDebugApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/#/Debug/getState
router.api(MethodGet,
"/eth/v1/debug/beacon/states/{state_id}") do (
state_id: StateIdent) -> RestApiResponse:
let bslot =
block:
if state_id.isErr():
return RestApiResponse.jsonError(Http400, InvalidStateIdValueError,
$state_id.error())
let bres = node.getBlockSlot(state_id.get())
if bres.isErr():
return RestApiResponse.jsonError(Http404, StateNotFoundError,
$bres.error())
bres.get()
let contentType =
block:
let res = preferredContentType("application/octet-stream",
"application/json")
if res.isErr():
return RestApiResponse.jsonError(Http406, ContentNotAcceptableError)
res.get()
node.withStateForBlockSlot(bslot):
return
case stateData.data.kind
of BeaconStateFork.Phase0:
case contentType
of "application/octet-stream":
RestApiResponse.sszResponse(stateData.data.phase0Data.data)
of "application/json":
RestApiResponse.jsonResponse(stateData.data.phase0Data.data)
else:
RestApiResponse.jsonError(Http500, InvalidAcceptError)
of BeaconStateFork.Altair, BeaconStateFork.Bellatrix:
RestApiResponse.jsonError(Http404, StateNotFoundError)
return RestApiResponse.jsonError(Http404, StateNotFoundError)
# https://ethereum.github.io/beacon-APIs/#/Debug/getStateV2
router.api(MethodGet,
"/eth/v2/debug/beacon/states/{state_id}") do (
state_id: StateIdent) -> RestApiResponse:
let bslot =
block:
if state_id.isErr():
return RestApiResponse.jsonError(Http400, InvalidStateIdValueError,
$state_id.error())
let bres = node.getBlockSlot(state_id.get())
if bres.isErr():
return RestApiResponse.jsonError(Http404, StateNotFoundError,
$bres.error())
bres.get()
let contentType =
block:
let res = preferredContentType("application/octet-stream",
"application/json")
if res.isErr():
return RestApiResponse.jsonError(Http406, ContentNotAcceptableError)
res.get()
node.withStateForBlockSlot(bslot):
return
case contentType
of "application/json":
RestApiResponse.jsonResponsePlain(stateData.data)
of "application/octet-stream":
withState(stateData.data):
RestApiResponse.sszResponse(state.data)
else:
RestApiResponse.jsonError(Http500, InvalidAcceptError)
return RestApiResponse.jsonError(Http404, StateNotFoundError)
# https://ethereum.github.io/beacon-APIs/#/Debug/getDebugChainHeads
router.api(MethodGet,
"/eth/v1/debug/beacon/heads") do () -> RestApiResponse:
return RestApiResponse.jsonResponse(
node.dag.heads.mapIt((root: it.root, slot: it.slot))
)
# Legacy URLS - Nimbus <= 1.5.5 used to expose the REST API with an additional
# `/api` path component
router.redirect(
MethodGet,
"/api/eth/v1/debug/beacon/states/{state_id}",
"/eth/v1/debug/beacon/states/{state_id}"
)
router.redirect(
MethodGet,
"/api/eth/v2/debug/beacon/states/{state_id}",
"/eth/v2/debug/beacon/states/{state_id}"
)
router.redirect(
MethodGet,
"/api/eth/v1/debug/beacon/heads",
"/eth/v1/debug/beacon/heads"
)