Adopt asyncraises guarantees to most of the REST API handlers. (#5803)

* Adopt asyncraises guarantees to most of the REST API handlers.
Bump presto.

* Fix copyright year.

---------

Co-authored-by: Etan Kissling <etan@status.im>
This commit is contained in:
Eugene Kabanov 2024-01-20 18:06:28 +02:00 committed by GitHub
parent 9acb7b99fe
commit 525b994e7d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 403 additions and 382 deletions

View File

@ -129,14 +129,17 @@ proc toString*(kind: ValidatorFilterKind): string =
proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://github.com/ethereum/EIPs/blob/master/EIPS/eip-4881.md
router.api(MethodGet, "/eth/v1/beacon/deposit_snapshot") do () -> RestApiResponse:
router.api2(MethodGet, "/eth/v1/beacon/deposit_snapshot") do (
) -> RestApiResponse:
let snapshot = node.db.getDepositTreeSnapshot().valueOr:
# This can happen in a very short window after the client is started, but the
# snapshot record still haven't been upgraded in the database. Returning 404
# should be easy to handle for the clients - they just need to retry.
return RestApiResponse.jsonError(Http404, NoFinalizedSnapshotAvailableError)
# This can happen in a very short window after the client is started,
# but the snapshot record still haven't been upgraded in the database.
# Returning 404 should be easy to handle for the clients - they just need
# to retry.
return RestApiResponse.jsonError(Http404,
NoFinalizedSnapshotAvailableError)
return RestApiResponse.jsonResponse(
RestApiResponse.jsonResponse(
RestDepositSnapshot(
finalized: snapshot.depositContractState.branch,
deposit_root: snapshot.getDepositRoot(),
@ -145,8 +148,8 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
execution_block_height: snapshot.blockHeight))
# https://ethereum.github.io/beacon-APIs/#/Beacon/getGenesis
router.api(MethodGet, "/eth/v1/beacon/genesis") do () -> RestApiResponse:
return RestApiResponse.jsonResponse(
router.api2(MethodGet, "/eth/v1/beacon/genesis") do () -> RestApiResponse:
RestApiResponse.jsonResponse(
(
genesis_time: getStateField(node.dag.headState, genesis_time),
genesis_validators_root:
@ -156,7 +159,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateRoot
router.api(MethodGet, "/eth/v1/beacon/states/{state_id}/root") do (
router.api2(MethodGet, "/eth/v1/beacon/states/{state_id}/root") do (
state_id: StateIdent) -> RestApiResponse:
let
sid = state_id.valueOr:
@ -177,10 +180,10 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
node.dag.isFinalized(bslot.bid)
)
return RestApiResponse.jsonError(Http404, StateNotFoundError)
RestApiResponse.jsonError(Http404, StateNotFoundError)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateFork
router.api(MethodGet, "/eth/v1/beacon/states/{state_id}/fork") do (
router.api2(MethodGet, "/eth/v1/beacon/states/{state_id}/fork") do (
state_id: StateIdent) -> RestApiResponse:
let
sid = state_id.valueOr:
@ -207,11 +210,12 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
node.getStateOptimistic(state),
node.dag.isFinalized(bslot.bid)
)
return RestApiResponse.jsonError(Http404, StateNotFoundError)
RestApiResponse.jsonError(Http404, StateNotFoundError)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateFinalityCheckpoints
router.api(MethodGet,
"/eth/v1/beacon/states/{state_id}/finality_checkpoints") do (
router.api2(MethodGet,
"/eth/v1/beacon/states/{state_id}/finality_checkpoints") do (
state_id: StateIdent) -> RestApiResponse:
let
sid = state_id.valueOr:
@ -238,7 +242,8 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
node.getStateOptimistic(state),
node.dag.isFinalized(bslot.bid)
)
return RestApiResponse.jsonError(Http404, StateNotFoundError)
RestApiResponse.jsonError(Http404, StateNotFoundError)
proc getIndices(
node: BeaconNode,
@ -369,7 +374,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
RestApiResponse.jsonError(Http404, StateNotFoundError)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateValidators
router.api(MethodGet, "/eth/v1/beacon/states/{state_id}/validators") do (
router.api2(MethodGet, "/eth/v1/beacon/states/{state_id}/validators") do (
state_id: StateIdent, id: seq[ValidatorIdent],
status: seq[ValidatorFilter]) -> RestApiResponse:
let
@ -404,7 +409,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
getValidators(node, bslot, validatorsMask, validatorIds)
# https://ethereum.github.io/beacon-APIs/#/Beacon/postStateValidators
router.api(MethodPost, "/eth/v1/beacon/states/{state_id}/validators") do (
router.api2(MethodPost, "/eth/v1/beacon/states/{state_id}/validators") do (
state_id: StateIdent, contentBody: Option[ContentBody]) -> RestApiResponse:
let
(validatorIds, validatorsMask) =
@ -431,8 +436,8 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
getValidators(node, bslot, validatorsMask, validatorIds)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateValidator
router.api(MethodGet,
"/eth/v1/beacon/states/{state_id}/validators/{validator_id}") do (
router.api2(MethodGet,
"/eth/v1/beacon/states/{state_id}/validators/{validator_id}") do (
state_id: StateIdent, validator_id: ValidatorIdent) -> RestApiResponse:
let
sid = state_id.valueOr:
@ -465,7 +470,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
of ValidatorQueryKind.Index:
let vres = vid.index.toValidatorIndex()
if vres.isErr():
case vres.error()
case vres.error
of ValidatorIndexError.TooHighValue:
return RestApiResponse.jsonError(Http400,
TooHighValidatorIndexValueError)
@ -493,11 +498,12 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
node.getStateOptimistic(state),
node.dag.isFinalized(bslot.bid)
)
return RestApiResponse.jsonError(Http404, StateNotFoundError)
RestApiResponse.jsonError(Http404, StateNotFoundError)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateValidatorBalances
router.api(MethodGet,
"/eth/v1/beacon/states/{state_id}/validator_balances") do (
router.api2(MethodGet,
"/eth/v1/beacon/states/{state_id}/validator_balances") do (
state_id: StateIdent, id: seq[ValidatorIdent]) -> RestApiResponse:
let
sid = state_id.valueOr:
@ -522,8 +528,8 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
getBalances(node, bslot, validatorIds)
# https://ethereum.github.io/beacon-APIs/#/Beacon/postStateValidatorBalances
router.api(MethodPost,
"/eth/v1/beacon/states/{state_id}/validator_balances") do (
router.api2(MethodPost,
"/eth/v1/beacon/states/{state_id}/validator_balances") do (
state_id: StateIdent, contentBody: Option[ContentBody]) -> RestApiResponse:
let
validatorIds =
@ -546,8 +552,8 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
getBalances(node, bslot, validatorIds)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getEpochCommittees
router.api(MethodGet,
"/eth/v1/beacon/states/{state_id}/committees") do (
router.api2(MethodGet,
"/eth/v1/beacon/states/{state_id}/committees") do (
state_id: StateIdent, epoch: Option[Epoch], index: Option[CommitteeIndex],
slot: Option[Slot]) -> RestApiResponse:
let
@ -567,7 +573,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
let repoch = epoch.get()
if repoch.isErr():
return RestApiResponse.jsonError(Http400, InvalidEpochValueError,
$repoch.error())
$repoch.error)
let res = repoch.get()
if res > bslot.slot.epoch + MIN_SEED_LOOKAHEAD:
@ -590,7 +596,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
if rindex.isErr():
return RestApiResponse.jsonError(Http400,
InvalidCommitteeIndexValueError,
$rindex.error())
$rindex.error)
some(rindex.get())
else:
none[CommitteeIndex]()
@ -599,12 +605,13 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
let rslot = slot.get()
if rslot.isErr():
return RestApiResponse.jsonError(Http400, InvalidSlotValueError,
$rslot.error())
$rslot.error)
let res = rslot.get()
if vepoch.isSome():
if res.epoch != vepoch.get():
return RestApiResponse.jsonError(Http400, InvalidSlotValueError,
"Slot does not match requested epoch")
return RestApiResponse.jsonError(
Http400, InvalidSlotValueError,
"Slot does not match requested epoch")
else:
if res.epoch > bslot.slot.epoch + 1:
return RestApiResponse.jsonError(
@ -620,6 +627,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
some(res)
else:
none[Slot]()
node.withStateForBlockSlotId(bslot):
proc getCommittee(slot: Slot,
index: CommitteeIndex): RestBeaconStatesCommittees =
@ -660,11 +668,11 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
node.dag.isFinalized(bslot.bid)
)
return RestApiResponse.jsonError(Http404, StateNotFoundError)
RestApiResponse.jsonError(Http404, StateNotFoundError)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getEpochSyncCommittees
router.api(MethodGet,
"/eth/v1/beacon/states/{state_id}/sync_committees") do (
router.api2(MethodGet,
"/eth/v1/beacon/states/{state_id}/sync_committees") do (
state_id: StateIdent, epoch: Option[Epoch]) -> RestApiResponse:
let
sid = state_id.valueOr:
@ -683,7 +691,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
let repoch = epoch.get()
if repoch.isErr():
return RestApiResponse.jsonError(Http400, InvalidEpochValueError,
$repoch.error())
$repoch.error)
let res = repoch.get()
if res > MaxEpoch:
return RestApiResponse.jsonError(Http400, EpochOverflowValueError)
@ -702,7 +710,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
let res = syncCommitteeParticipants(state, qepoch)
if res.isErr():
return RestApiResponse.jsonError(Http400,
$res.error())
$res.error)
let kres = res.get()
if len(kres) == 0:
return RestApiResponse.jsonError(Http500, InternalServerError,
@ -742,12 +750,12 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
node.dag.isFinalized(bslot.bid)
)
return RestApiResponse.jsonError(Http404, StateNotFoundError)
RestApiResponse.jsonError(Http404, StateNotFoundError)
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getStateRandao
# https://github.com/ethereum/beacon-APIs/blob/b3c4defa238aaa74bf22aa602aa1b24b68a4c78e/apis/beacon/states/randao.yaml
router.api(MethodGet,
"/eth/v1/beacon/states/{state_id}/randao") do (
router.api2(MethodGet,
"/eth/v1/beacon/states/{state_id}/randao") do (
state_id: StateIdent, epoch: Option[Epoch]) -> RestApiResponse:
let
sid = state_id.valueOr:
@ -766,7 +774,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
let repoch = epoch.get()
if repoch.isErr():
return RestApiResponse.jsonError(Http400, InvalidEpochValueError,
$repoch.error())
$repoch.error)
let res = repoch.get()
if res > MaxEpoch:
return RestApiResponse.jsonError(Http400, EpochOverflowValueError)
@ -801,10 +809,10 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
node.dag.isFinalized(bslot.bid)
)
return RestApiResponse.jsonError(Http404, StateNotFoundError)
RestApiResponse.jsonError(Http404, StateNotFoundError)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockHeaders
router.api(MethodGet, "/eth/v1/beacon/headers") do (
router.api2(MethodGet, "/eth/v1/beacon/headers") do (
slot: Option[Slot], parent_root: Option[Eth2Digest]) -> RestApiResponse:
# TODO (cheatfate): This call is incomplete, because structure
# of database do not allow to query blocks by `parent_root`.
@ -813,7 +821,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
let rslot = slot.get()
if rslot.isErr():
return RestApiResponse.jsonError(Http400, InvalidSlotValueError,
$rslot.error())
$rslot.error)
rslot.get()
else:
node.dag.head.slot
@ -822,32 +830,31 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
let rroot = parent_root.get()
if rroot.isErr():
return RestApiResponse.jsonError(Http400, InvalidParentRootValueError,
$rroot.error())
$rroot.error)
return RestApiResponse.jsonError(Http500, NoImplementationError)
let bdata = node.getForkedBlock(BlockIdent.init(qslot)).valueOr:
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
return
withBlck(bdata):
let bid = BlockId(root: forkyBlck.root, slot: forkyBlck.message.slot)
RestApiResponse.jsonResponseFinalized(
[
(
root: forkyBlck.root,
canonical: node.dag.isCanonical(bid),
header: (
message: forkyBlck.toBeaconBlockHeader,
signature: forkyBlck.signature
)
withBlck(bdata):
let bid = BlockId(root: forkyBlck.root, slot: forkyBlck.message.slot)
RestApiResponse.jsonResponseFinalized(
[
(
root: forkyBlck.root,
canonical: node.dag.isCanonical(bid),
header: (
message: forkyBlck.toBeaconBlockHeader,
signature: forkyBlck.signature
)
],
node.getBlockOptimistic(bdata),
node.dag.isFinalized(bid)
)
)
],
node.getBlockOptimistic(bdata),
node.dag.isFinalized(bid)
)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockHeader
router.api(MethodGet, "/eth/v1/beacon/headers/{block_id}") do (
router.api2(MethodGet, "/eth/v1/beacon/headers/{block_id}") do (
block_id: BlockIdent) -> RestApiResponse:
let
bid = block_id.valueOr:
@ -857,21 +864,20 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
bdata = node.getForkedBlock(bid).valueOr:
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
return
withBlck(bdata):
let bid = BlockId(root: forkyBlck.root, slot: forkyBlck.message.slot)
RestApiResponse.jsonResponseFinalized(
(
root: forkyBlck.root,
canonical: node.dag.isCanonical(bid),
header: (
message: forkyBlck.toBeaconBlockHeader,
signature: forkyBlck.signature
)
),
node.getBlockOptimistic(bdata),
node.dag.isFinalized(bid)
)
withBlck(bdata):
let bid = BlockId(root: forkyBlck.root, slot: forkyBlck.message.slot)
RestApiResponse.jsonResponseFinalized(
(
root: forkyBlck.root,
canonical: node.dag.isCanonical(bid),
header: (
message: forkyBlck.toBeaconBlockHeader,
signature: forkyBlck.signature
)
),
node.getBlockOptimistic(bdata),
node.dag.isFinalized(bid)
)
# https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlock
router.api(MethodPost, "/eth/v1/beacon/blocks") do (
@ -924,11 +930,11 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
if res.isErr():
return RestApiResponse.jsonError(
Http503, BeaconNodeInSyncError, $res.error())
Http503, BeaconNodeInSyncError, $res.error)
if res.get().isNone():
return RestApiResponse.jsonError(Http202, BlockValidationError)
return RestApiResponse.jsonMsgResponse(BlockValidationSuccess)
RestApiResponse.jsonMsgResponse(BlockValidationSuccess)
# https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlockV2
router.api(MethodPost, "/eth/v2/beacon/blocks") do (
@ -1000,11 +1006,11 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
if res.isErr():
return RestApiResponse.jsonError(
Http503, BeaconNodeInSyncError, $res.error())
Http503, BeaconNodeInSyncError, $res.error)
if res.get().isNone():
return RestApiResponse.jsonError(Http202, BlockValidationError)
return RestApiResponse.jsonMsgResponse(BlockValidationSuccess)
RestApiResponse.jsonMsgResponse(BlockValidationSuccess)
# https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlindedBlock
# https://github.com/ethereum/beacon-APIs/blob/v2.4.0/apis/beacon/blocks/blinded_blocks.yaml
@ -1046,7 +1052,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
if res.isErr():
return RestApiResponse.jsonError(
Http500, InternalServerError, $res.error())
Http500, InternalServerError, $res.error)
if res.get().isNone():
return RestApiResponse.jsonError(Http202, BlockValidationError)
@ -1076,20 +1082,20 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
if res.isErr():
return RestApiResponse.jsonError(
Http503, BeaconNodeInSyncError, $res.error())
Http503, BeaconNodeInSyncError, $res.error)
elif res.get().isNone():
return RestApiResponse.jsonError(Http202, BlockValidationError)
return RestApiResponse.jsonMsgResponse(BlockValidationSuccess)
RestApiResponse.jsonMsgResponse(BlockValidationSuccess)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlock
router.api(MethodGet, "/eth/v1/beacon/blocks/{block_id}") do (
router.api2(MethodGet, "/eth/v1/beacon/blocks/{block_id}") do (
block_id: BlockIdent) -> RestApiResponse:
return RestApiResponse.jsonError(
RestApiResponse.jsonError(
Http410, DeprecatedRemovalBeaconBlocksDebugStateV1)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockV2
router.api(MethodGet, "/eth/v2/beacon/blocks/{block_id}") do (
router.api2(MethodGet, "/eth/v2/beacon/blocks/{block_id}") do (
block_id: BlockIdent) -> RestApiResponse:
let
blockIdent = block_id.valueOr:
@ -1105,31 +1111,31 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
if res.isErr():
return RestApiResponse.jsonError(Http406, ContentNotAcceptableError)
res.get()
return
if contentType == sszMediaType:
var data: seq[byte]
if not node.dag.getBlockSSZ(bid, data):
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
let
fork = node.dag.cfg.consensusForkAtEpoch(bid.slot.epoch)
headers = [("eth-consensus-version", fork.toString())]
if contentType == sszMediaType:
var data: seq[byte]
if not node.dag.getBlockSSZ(bid, data):
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
RestApiResponse.sszResponsePlain(data, headers)
elif contentType == jsonMediaType:
let bdata = node.dag.getForkedBlock(bid).valueOr:
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
let
fork = node.dag.cfg.consensusForkAtEpoch(bid.slot.epoch)
headers = [("eth-consensus-version", fork.toString())]
RestApiResponse.jsonResponseBlock(
bdata.asSigned(),
node.getBlockOptimistic(bdata),
node.dag.isFinalized(bid)
)
else:
RestApiResponse.jsonError(Http500, InvalidAcceptError)
RestApiResponse.sszResponsePlain(data, headers)
elif contentType == jsonMediaType:
let bdata = node.dag.getForkedBlock(bid).valueOr:
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
RestApiResponse.jsonResponseBlock(
bdata.asSigned(),
node.getBlockOptimistic(bdata),
node.dag.isFinalized(bid)
)
else:
RestApiResponse.jsonError(Http500, InvalidAcceptError)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockRoot
router.api(MethodGet, "/eth/v1/beacon/blocks/{block_id}/root") do (
router.api2(MethodGet, "/eth/v1/beacon/blocks/{block_id}/root") do (
block_id: BlockIdent) -> RestApiResponse:
let
blockIdent = block_id.valueOr:
@ -1142,14 +1148,14 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
bdata = node.dag.getForkedBlock(bid).valueOr:
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
return RestApiResponse.jsonResponseFinalized(
RestApiResponse.jsonResponseFinalized(
(root: bid.root),
node.getBlockOptimistic(bdata),
node.dag.isFinalized(bid)
)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockAttestations
router.api(MethodGet,
router.api2(MethodGet,
"/eth/v1/beacon/blocks/{block_id}/attestations") do (
block_id: BlockIdent) -> RestApiResponse:
let
@ -1159,17 +1165,16 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
bdata = node.getForkedBlock(blockIdent).valueOr:
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
return
withBlck(bdata):
let bid = BlockId(root: forkyBlck.root, slot: forkyBlck.message.slot)
RestApiResponse.jsonResponseFinalized(
forkyBlck.message.body.attestations.asSeq(),
node.getBlockOptimistic(bdata),
node.dag.isFinalized(bid)
)
withBlck(bdata):
let bid = BlockId(root: forkyBlck.root, slot: forkyBlck.message.slot)
RestApiResponse.jsonResponseFinalized(
forkyBlck.message.body.attestations.asSeq(),
node.getBlockOptimistic(bdata),
node.dag.isFinalized(bid)
)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getPoolAttestations
router.api(MethodGet, "/eth/v1/beacon/pool/attestations") do (
router.api2(MethodGet, "/eth/v1/beacon/pool/attestations") do (
slot: Option[Slot],
committee_index: Option[CommitteeIndex]) -> RestApiResponse:
let vindex =
@ -1178,7 +1183,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
if rindex.isErr():
return RestApiResponse.jsonError(Http400,
InvalidCommitteeIndexValueError,
$rindex.error())
$rindex.error)
Opt.some(rindex.get())
else:
Opt.none(CommitteeIndex)
@ -1187,17 +1192,17 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
let rslot = slot.get()
if rslot.isErr():
return RestApiResponse.jsonError(Http400, InvalidSlotValueError,
$rslot.error())
$rslot.error)
Opt.some(rslot.get())
else:
Opt.none(Slot)
var res: seq[Attestation]
for item in node.attestationPool[].attestations(vslot, vindex):
res.add(item)
return RestApiResponse.jsonResponse(res)
RestApiResponse.jsonResponse(res)
# https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolAttestations
router.api(MethodPost, "/eth/v1/beacon/pool/attestations") do (
router.api2(MethodPost, "/eth/v1/beacon/pool/attestations") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
let attestations =
block:
@ -1207,7 +1212,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
if dres.isErr():
return RestApiResponse.jsonError(Http400,
InvalidAttestationObjectError,
$dres.error())
$dres.error)
dres.get()
# Since our validation logic supports batch processing, we will submit all
@ -1224,29 +1229,29 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
await allFutures(pending)
for index, future in pending:
if future.completed():
let fres = future.read()
let fres = future.value()
if fres.isErr():
let failure = RestIndexedErrorMessageItem(index: index,
message: $fres.error())
message: $fres.error)
res.add(failure)
elif future.failed() or future.cancelled():
# This is unexpected failure, so we log the error message.
let exc = future.readError()
let exc = future.error()
let failure = RestIndexedErrorMessageItem(index: index,
message: $exc.msg)
res.add(failure)
res
if len(failures) > 0:
return RestApiResponse.jsonErrorList(Http400, AttestationValidationError,
failures)
RestApiResponse.jsonErrorList(Http400, AttestationValidationError,
failures)
else:
return RestApiResponse.jsonMsgResponse(AttestationValidationSuccess)
RestApiResponse.jsonMsgResponse(AttestationValidationSuccess)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getPoolAttesterSlashings
router.api(MethodGet, "/eth/v1/beacon/pool/attester_slashings") do (
router.api2(MethodGet, "/eth/v1/beacon/pool/attester_slashings") do (
) -> RestApiResponse:
return RestApiResponse.jsonResponse(
RestApiResponse.jsonResponse(
toSeq(node.validatorChangePool.attester_slashings))
# https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolAttesterSlashings
@ -1260,19 +1265,19 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
if dres.isErr():
return RestApiResponse.jsonError(Http400,
InvalidAttesterSlashingObjectError,
$dres.error())
$dres.error)
dres.get()
let res = await node.router.routeAttesterSlashing(slashing)
if res.isErr():
return RestApiResponse.jsonError(Http400,
AttesterSlashingValidationError,
$res.error())
return RestApiResponse.jsonMsgResponse(AttesterSlashingValidationSuccess)
$res.error)
RestApiResponse.jsonMsgResponse(AttesterSlashingValidationSuccess)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getPoolProposerSlashings
router.api(MethodGet, "/eth/v1/beacon/pool/proposer_slashings") do (
router.api2(MethodGet, "/eth/v1/beacon/pool/proposer_slashings") do (
) -> RestApiResponse:
return RestApiResponse.jsonResponse(
RestApiResponse.jsonResponse(
toSeq(node.validatorChangePool.proposer_slashings))
# https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolProposerSlashings
@ -1286,55 +1291,58 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
if dres.isErr():
return RestApiResponse.jsonError(Http400,
InvalidProposerSlashingObjectError,
$dres.error())
$dres.error)
dres.get()
let res = await node.router.routeProposerSlashing(slashing)
if res.isErr():
return RestApiResponse.jsonError(Http400,
ProposerSlashingValidationError,
$res.error())
return RestApiResponse.jsonMsgResponse(ProposerSlashingValidationSuccess)
$res.error)
RestApiResponse.jsonMsgResponse(ProposerSlashingValidationSuccess)
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getPoolBLSToExecutionChanges
# https://github.com/ethereum/beacon-APIs/blob/86850001845df9163da5ae9605dbf15cd318d5d0/apis/beacon/pool/bls_to_execution_changes.yaml
router.api(MethodGet, "/eth/v1/beacon/pool/bls_to_execution_changes") do (
router.api2(MethodGet, "/eth/v1/beacon/pool/bls_to_execution_changes") do (
) -> RestApiResponse:
return RestApiResponse.jsonResponse(
RestApiResponse.jsonResponse(
toSeq(node.validatorChangePool.bls_to_execution_changes_gossip) &
toSeq(node.validatorChangePool.bls_to_execution_changes_api))
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/submitPoolBLSToExecutionChange
# https://github.com/ethereum/beacon-APIs/blob/86850001845df9163da5ae9605dbf15cd318d5d0/apis/beacon/pool/bls_to_execution_changes.yaml
router.api(MethodPost, "/eth/v1/beacon/pool/bls_to_execution_changes") do (
router.api2(MethodPost, "/eth/v1/beacon/pool/bls_to_execution_changes") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
if node.currentSlot().epoch() < node.dag.cfg.CAPELLA_FORK_EPOCH:
return RestApiResponse.jsonError(Http400,
InvalidBlsToExecutionChangeObjectError,
"Attempt to add to BLS to execution change pool pre-Capella")
let bls_to_execution_changes =
block:
if contentBody.isNone():
return RestApiResponse.jsonError(Http400, EmptyRequestBodyError)
let dres = decodeBody(seq[SignedBLSToExecutionChange], contentBody.get())
if dres.isErr():
return RestApiResponse.jsonError(Http400,
InvalidBlsToExecutionChangeObjectError,
$dres.error())
dres.get()
let res = await allFinished(mapIt(
bls_to_execution_changes, node.router.routeBlsToExecutionChange(it)))
for individual_res in res:
doAssert individual_res.finished()
if individual_res.failed():
let
bls_to_execution_changes =
block:
if contentBody.isNone():
return RestApiResponse.jsonError(Http400, EmptyRequestBodyError)
let dres =
decodeBody(seq[SignedBLSToExecutionChange], contentBody.get())
if dres.isErr():
return RestApiResponse.jsonError(
Http400, InvalidBlsToExecutionChangeObjectError, $dres.error)
dres.get()
pending = mapIt(bls_to_execution_changes,
node.router.routeBlsToExecutionChange(it))
await allFutures(pending)
for future in pending:
if future.failed() or future.cancelled():
return RestApiResponse.jsonError(Http400,
BlsToExecutionChangeValidationError,
$individual_res.error[].msg)
let fut_result = individual_res.read()
if fut_result.isErr():
$future.error().msg)
let res = future.value()
if res.isErr():
return RestApiResponse.jsonError(Http400,
BlsToExecutionChangeValidationError,
$fut_result.error())
return RestApiResponse.jsonMsgResponse(BlsToExecutionChangeValidationSuccess)
$res.error)
RestApiResponse.jsonMsgResponse(BlsToExecutionChangeValidationSuccess)
# https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolSyncCommitteeSignatures
router.api(MethodPost, "/eth/v1/beacon/pool/sync_committees") do (
@ -1357,18 +1365,17 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
for index, item in results:
if item.isErr():
res.add(RestIndexedErrorMessageItem(index: index,
message: $item.error()))
message: $item.error))
res
if len(failures) > 0:
return RestApiResponse.jsonErrorList(Http400,
SyncCommitteeMessageValidationError,
failures)
RestApiResponse.jsonErrorList(
Http400, SyncCommitteeMessageValidationError, failures)
else:
return RestApiResponse.jsonMsgResponse(
RestApiResponse.jsonMsgResponse(
SyncCommitteeMessageValidationSuccess)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getPoolVoluntaryExits
router.api(MethodGet, "/eth/v1/beacon/pool/voluntary_exits") do (
router.api2(MethodGet, "/eth/v1/beacon/pool/voluntary_exits") do (
) -> RestApiResponse:
return RestApiResponse.jsonResponse(
toSeq(node.validatorChangePool.voluntary_exits))
@ -1384,18 +1391,17 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
if dres.isErr():
return RestApiResponse.jsonError(Http400,
InvalidVoluntaryExitObjectError,
$dres.error())
$dres.error)
dres.get()
let res = await node.router.routeSignedVoluntaryExit(exit)
if res.isErr():
return RestApiResponse.jsonError(Http400,
VoluntaryExitValidationError,
$res.error())
return RestApiResponse.jsonError(
Http400, VoluntaryExitValidationError, $res.error)
return RestApiResponse.jsonMsgResponse(VoluntaryExitValidationSuccess)
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=v2.4.2#/Beacon/getBlobSidecars
# https://github.com/ethereum/beacon-APIs/blob/v2.4.2/apis/beacon/blob_sidecars/blob_sidecars.yaml
router.api(MethodGet, "/eth/v1/beacon/blob_sidecars/{block_id}") do (
router.api2(MethodGet, "/eth/v1/beacon/blob_sidecars/{block_id}") do (
block_id: BlockIdent, indices: seq[uint64]) -> RestApiResponse:
let
blockIdent = block_id.valueOr:
@ -1429,12 +1435,11 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
if node.dag.db.getBlobSidecar(bid.root, blobIndex, blobSidecar[]):
discard data[].add blobSidecar[]
return
if contentType == sszMediaType:
RestApiResponse.sszResponse(
data[], headers = [("eth-consensus-version",
node.dag.cfg.consensusForkAtEpoch(bid.slot.epoch).toString())])
elif contentType == jsonMediaType:
RestApiResponse.jsonResponse(data)
else:
RestApiResponse.jsonError(Http500, InvalidAcceptError)
if contentType == sszMediaType:
RestApiResponse.sszResponse(
data[], headers = [("eth-consensus-version",
node.dag.cfg.consensusForkAtEpoch(bid.slot.epoch).toString())])
elif contentType == jsonMediaType:
RestApiResponse.jsonResponse(data)
else:
RestApiResponse.jsonError(Http500, InvalidAcceptError)

View File

@ -1,5 +1,5 @@
# beacon_chain
# Copyright (c) 2023 Status Research & Development GmbH
# Copyright (c) 2023-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).
@ -17,7 +17,8 @@ logScope: topics = "rest_builderapi"
proc installBuilderApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=v2.4.0#/Builder/getNextWithdrawals
# https://github.com/ethereum/beacon-APIs/blob/v2.4.0/apis/builder/states/expected_withdrawals.yaml
router.api(MethodGet, "/eth/v1/builder/states/{state_id}/expected_withdrawals") do (
router.api2(MethodGet,
"/eth/v1/builder/states/{state_id}/expected_withdrawals") do (
state_id: StateIdent) -> RestApiResponse:
let
sid = state_id.valueOr:
@ -41,4 +42,4 @@ proc installBuilderApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonError(
Http400, "The specified state is not a capella state")
return RestApiResponse.jsonError(Http404, StateNotFoundError)
RestApiResponse.jsonError(Http404, StateNotFoundError)

View File

@ -326,19 +326,16 @@ proc installConfigApiHandlers*(router: var RestRouter, node: BeaconNode) =
)
# https://ethereum.github.io/beacon-APIs/#/Config/getForkSchedule
router.api(MethodGet,
router.api2(MethodGet,
"/eth/v1/config/fork_schedule") do () -> RestApiResponse:
return RestApiResponse.response(cachedForkSchedule, Http200,
"application/json")
RestApiResponse.response(cachedForkSchedule, Http200, "application/json")
# https://ethereum.github.io/beacon-APIs/#/Config/getSpec
router.api(MethodGet,
router.api2(MethodGet,
"/eth/v1/config/spec") do () -> RestApiResponse:
return RestApiResponse.response(cachedConfigSpec, Http200,
"application/json")
RestApiResponse.response(cachedConfigSpec, Http200, "application/json")
# https://ethereum.github.io/beacon-APIs/#/Config/getDepositContract
router.api(MethodGet,
router.api2(MethodGet,
"/eth/v1/config/deposit_contract") do () -> RestApiResponse:
return RestApiResponse.response(cachedDepositContract, Http200,
"application/json")
RestApiResponse.response(cachedDepositContract, Http200, "application/json")

View File

@ -19,15 +19,15 @@ 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 (
router.api2(MethodGet,
"/eth/v1/debug/beacon/states/{state_id}") do (
state_id: StateIdent) -> RestApiResponse:
return RestApiResponse.jsonError(
RestApiResponse.jsonError(
Http410, DeprecatedRemovalBeaconBlocksDebugStateV1)
# https://ethereum.github.io/beacon-APIs/#/Debug/getStateV2
router.api(MethodGet,
"/eth/v2/debug/beacon/states/{state_id}") do (
router.api2(MethodGet,
"/eth/v2/debug/beacon/states/{state_id}") do (
state_id: StateIdent) -> RestApiResponse:
let bslot =
block:
@ -46,43 +46,40 @@ proc installDebugApiHandlers*(router: var RestRouter, node: BeaconNode) =
if res.isErr():
return RestApiResponse.jsonError(Http406, ContentNotAcceptableError)
res.get()
node.withStateForBlockSlotId(bslot):
return
if contentType == jsonMediaType:
RestApiResponse.jsonResponseState(
state,
node.getStateOptimistic(state)
)
state, node.getStateOptimistic(state))
elif contentType == sszMediaType:
let headers = [("eth-consensus-version", state.kind.toString())]
withState(state):
RestApiResponse.sszResponse(forkyState.data, headers)
else:
RestApiResponse.jsonError(Http500, InvalidAcceptError)
return RestApiResponse.jsonError(Http404, StateNotFoundError)
RestApiResponse.jsonError(Http404, StateNotFoundError)
# https://ethereum.github.io/beacon-APIs/#/Debug/getDebugChainHeads
router.api(MethodGet,
"/eth/v1/debug/beacon/heads") do () -> RestApiResponse:
return RestApiResponse.jsonError(
router.api2(MethodGet,
"/eth/v1/debug/beacon/heads") do () -> RestApiResponse:
RestApiResponse.jsonError(
Http410, DeprecatedRemovalGetDebugChainHeadsV1)
# https://ethereum.github.io/beacon-APIs/#/Debug/getDebugChainHeadsV2
router.api(MethodGet,
"/eth/v2/debug/beacon/heads") do () -> RestApiResponse:
return RestApiResponse.jsonResponse(
router.api2(MethodGet,
"/eth/v2/debug/beacon/heads") do () -> RestApiResponse:
RestApiResponse.jsonResponse(
node.dag.heads.mapIt(
(
root: it.root,
slot: it.slot,
execution_optimistic: not it.executionValid
)
(root: it.root, slot: it.slot,
execution_optimistic: not it.executionValid)
)
)
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Debug/getDebugForkChoice
router.api(MethodGet,
"/eth/v1/debug/fork_choice") do () -> RestApiResponse:
router.api2(MethodGet,
"/eth/v1/debug/fork_choice") do () -> RestApiResponse:
template forkChoice: auto = node.attestationPool[].forkChoice
var response = GetForkChoiceResponse(
@ -135,4 +132,4 @@ proc installDebugApiHandlers*(router: var RestRouter, node: BeaconNode) =
best_child: item.bestChild,
bestDescendant: item.bestDescendant))
return RestApiResponse.jsonResponsePlain(response)
RestApiResponse.jsonResponsePlain(response)

View File

@ -85,7 +85,7 @@ proc eventHandler*[T](response: HttpResponseRef,
proc installEventApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/#/Events/eventstream
router.api(MethodGet, "/eth/v1/events") do (
router.api2(MethodGet, "/eth/v1/events") do (
topics: seq[EventTopic]) -> RestApiResponse:
let eventTopics =
block:
@ -174,7 +174,10 @@ proc installEventApiHandlers*(router: var RestRouter, node: BeaconNode) =
res.add(handler)
res
discard await one(handlers)
try:
discard await race(handlers)
except ValueError:
raiseAssert "There should be more than one event handler at this point!"
# One of the handlers finished, it means that connection has been droped, so
# we cancelling all other handlers.
let pending =

View File

@ -142,17 +142,17 @@ proc handleAddRemoteValidatorReq(host: KeymanagerHost,
proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
# https://ethereum.github.io/keymanager-APIs/#/Keymanager/ListKeys
router.api(MethodGet, "/eth/v1/keystores") do () -> RestApiResponse:
router.api2(MethodGet, "/eth/v1/keystores") do () -> RestApiResponse:
let authStatus = checkAuthorization(request, host)
if authStatus.isErr():
return authErrorResponse authStatus.error
let response = GetKeystoresResponse(
data: listLocalValidators(host.validatorPool[]))
return RestApiResponse.jsonResponsePlain(response)
RestApiResponse.jsonResponsePlain(response)
# https://ethereum.github.io/keymanager-APIs/#/Keymanager/ImportKeystores
router.api(MethodPost, "/eth/v1/keystores") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
router.api2(MethodPost, "/eth/v1/keystores") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
let authStatus = checkAuthorization(request, host)
if authStatus.isErr():
return authErrorResponse authStatus.error
@ -167,14 +167,30 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
if request.slashing_protection.isSome():
let slashing_protection = request.slashing_protection.get()
let nodeSPDIR = toSPDIR(host.validatorPool[].slashingProtection)
let nodeSPDIR =
try:
toSPDIR(host.validatorPool[].slashingProtection)
except IOError as exc:
return keymanagerApiError(
Http500, "Internal server error; " & $exc.msg)
if nodeSPDIR.metadata.genesis_validators_root.Eth2Digest !=
slashing_protection.metadata.genesis_validators_root.Eth2Digest:
return keymanagerApiError(Http400,
"The slashing protection database and imported file refer to " &
"different blockchains.")
let res = inclSPDIR(host.validatorPool[].slashingProtection,
slashing_protection)
let res =
try:
inclSPDIR(host.validatorPool[].slashingProtection,
slashing_protection)
except SerializationError as exc:
return keymanagerApiError(
Http500, "Internal server error; Failed to import slashing " &
"protection data, reason: " &
exc.formatMsg("slashing_protection"))
except IOError as exc:
return keymanagerApiError(
Http500, "Internal server error; Failed to import slashing " &
"protection data, reason: " & $exc.msg)
if res == siFailure:
return keymanagerApiError(Http500,
"Internal server error; Failed to import slashing protection data")
@ -202,10 +218,10 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
response.data.add(
RequestItemStatus(status: $KeystoreStatus.imported))
return RestApiResponse.jsonResponsePlain(response)
RestApiResponse.jsonResponsePlain(response)
# https://ethereum.github.io/keymanager-APIs/#/Keymanager/DeleteKeys
router.api(MethodDelete, "/eth/v1/keystores") do (
router.api2(MethodDelete, "/eth/v1/keystores") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
let authStatus = checkAuthorization(request, host)
if authStatus.isErr():
@ -221,7 +237,12 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
var
response: DeleteKeystoresResponse
nodeSPDIR = toSPDIR(host.validatorPool[].slashingProtection)
nodeSPDIR =
try:
toSPDIR(host.validatorPool[].slashingProtection)
except IOError as exc:
return keymanagerApiError(
Http500, "Internal server error; " & $exc.msg)
# Hash table to keep the removal status of all keys form request
keysAndDeleteStatus = initTable[PubKeyBytes, RequestItemStatus]()
responseSPDIR: SPDIR
@ -263,23 +284,24 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
foundKeystore.status = $KeystoreStatus.notActive
for index, key in keys:
response.data.add(keysAndDeleteStatus[key.blob.PubKey0x.PubKeyBytes])
response.data.add(
keysAndDeleteStatus.getOrDefault(key.blob.PubKey0x.PubKeyBytes))
response.slashing_protection = RestJson.encode(responseSPDIR)
return RestApiResponse.jsonResponsePlain(response)
RestApiResponse.jsonResponsePlain(response)
# https://ethereum.github.io/keymanager-APIs/#/Remote%20Key%20Manager/ListRemoteKeys
router.api(MethodGet, "/eth/v1/remotekeys") do () -> RestApiResponse:
router.api2(MethodGet, "/eth/v1/remotekeys") do () -> RestApiResponse:
let authStatus = checkAuthorization(request, host)
if authStatus.isErr():
return authErrorResponse authStatus.error
let response = GetRemoteKeystoresResponse(
data: listRemoteValidators(host.validatorPool[]))
return RestApiResponse.jsonResponsePlain(response)
RestApiResponse.jsonResponsePlain(response)
# https://ethereum.github.io/keymanager-APIs/#/Remote%20Key%20Manager/ImportRemoteKeys
router.api(MethodPost, "/eth/v1/remotekeys") do (
router.api2(MethodPost, "/eth/v1/remotekeys") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
let authStatus = checkAuthorization(request, host)
if authStatus.isErr():
@ -307,10 +329,10 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
response.data.add handleAddRemoteValidatorReq(host, keystore)
return RestApiResponse.jsonResponsePlain(response)
RestApiResponse.jsonResponsePlain(response)
# https://ethereum.github.io/keymanager-APIs/#/Remote%20Key%20Manager/DeleteRemoteKeys
router.api(MethodDelete, "/eth/v1/remotekeys") do (
router.api2(MethodDelete, "/eth/v1/remotekeys") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
let authStatus = checkAuthorization(request, host)
if authStatus.isErr():
@ -327,10 +349,10 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
var response: DeleteRemoteKeystoresResponse
for index, key in keys:
response.data.add handleRemoveValidatorReq(host, key)
return RestApiResponse.jsonResponsePlain(response)
RestApiResponse.jsonResponsePlain(response)
# https://ethereum.github.io/keymanager-APIs/#/Fee%20Recipient/ListFeeRecipient
router.api(MethodGet, "/eth/v1/validator/{pubkey}/feerecipient") do (
router.api2(MethodGet, "/eth/v1/validator/{pubkey}/feerecipient") do (
pubkey: ValidatorPubKey) -> RestApiResponse:
let authStatus = checkAuthorization(request, host)
if authStatus.isErr():
@ -344,7 +366,7 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
ethaddress = host.getSuggestedFeeRecipient(
pubkey, perValidatorDefaultFeeRecipient)
return if ethaddress.isOk:
if ethaddress.isOk:
RestApiResponse.jsonResponse(ListFeeRecipientResponse(
pubkey: pubkey,
ethaddress: ethaddress.get))
@ -356,14 +378,14 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
keymanagerApiError(Http500, "Error reading fee recipient file")
# https://ethereum.github.io/keymanager-APIs/#/Fee%20Recipient/SetFeeRecipient
router.api(MethodPost, "/eth/v1/validator/{pubkey}/feerecipient") do (
pubkey: ValidatorPubKey,
contentBody: Option[ContentBody]) -> RestApiResponse:
router.api2(MethodPost, "/eth/v1/validator/{pubkey}/feerecipient") do (
pubkey: ValidatorPubKey,
contentBody: Option[ContentBody]) -> RestApiResponse:
let authStatus = checkAuthorization(request, host)
if authStatus.isErr():
return authErrorResponse authStatus.error
let
pubkey= pubkey.valueOr:
pubkey = pubkey.valueOr:
return keymanagerApiError(Http400, InvalidValidatorPublicKey)
feeRecipientReq =
block:
@ -376,14 +398,14 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
status = host.setFeeRecipient(pubkey, feeRecipientReq.ethaddress)
return if status.isOk:
if status.isOk:
RestApiResponse.response("", Http202, "text/plain")
else:
keymanagerApiError(
Http500, "Failed to set fee recipient: " & status.error)
# https://ethereum.github.io/keymanager-APIs/#/Fee%20Recipient/DeleteFeeRecipient
router.api(MethodDelete, "/eth/v1/validator/{pubkey}/feerecipient") do (
router.api2(MethodDelete, "/eth/v1/validator/{pubkey}/feerecipient") do (
pubkey: ValidatorPubKey) -> RestApiResponse:
let authStatus = checkAuthorization(request, host)
if authStatus.isErr():
@ -393,15 +415,15 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
return keymanagerApiError(Http400, InvalidValidatorPublicKey)
res = host.removeFeeRecipientFile(pubkey)
return if res.isOk:
if res.isOk:
RestApiResponse.response("", Http204, "text/plain")
else:
keymanagerApiError(
Http500, "Failed to remove fee recipient file: " & res.error)
# https://ethereum.github.io/keymanager-APIs/#/Gas%20Limit/getGasLimit
router.api(MethodGet, "/eth/v1/validator/{pubkey}/gas_limit") do (
pubkey: ValidatorPubKey) -> RestApiResponse:
router.api2(MethodGet, "/eth/v1/validator/{pubkey}/gas_limit") do (
pubkey: ValidatorPubKey) -> RestApiResponse:
let authStatus = checkAuthorization(request, host)
if authStatus.isErr():
return authErrorResponse authStatus.error
@ -411,7 +433,7 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
return keymanagerApiError(Http400, InvalidValidatorPublicKey)
gasLimit = host.getSuggestedGasLimit(pubkey)
return if gasLimit.isOk:
if gasLimit.isOk:
RestApiResponse.jsonResponse(GetValidatorGasLimitResponse(
pubkey: pubkey,
gas_limit: gasLimit.get))
@ -423,9 +445,9 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
keymanagerApiError(Http500, "Error reading gas limit file")
# https://ethereum.github.io/keymanager-APIs/#/Gas%20Limit/setGasLimit
router.api(MethodPost, "/eth/v1/validator/{pubkey}/gas_limit") do (
pubkey: ValidatorPubKey,
contentBody: Option[ContentBody]) -> RestApiResponse:
router.api2(MethodPost, "/eth/v1/validator/{pubkey}/gas_limit") do (
pubkey: ValidatorPubKey,
contentBody: Option[ContentBody]) -> RestApiResponse:
let authStatus = checkAuthorization(request, host)
if authStatus.isErr():
return authErrorResponse authStatus.error
@ -443,15 +465,15 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
status = host.setGasLimit(pubkey, gasLimitReq.gas_limit)
return if status.isOk:
if status.isOk:
RestApiResponse.response("", Http202, "text/plain")
else:
keymanagerApiError(
Http500, "Failed to set gas limit: " & status.error)
# https://ethereum.github.io/keymanager-APIs/#/Gas%20Limit/deleteGasLimit
router.api(MethodDelete, "/eth/v1/validator/{pubkey}/gas_limit") do (
pubkey: ValidatorPubKey) -> RestApiResponse:
router.api2(MethodDelete, "/eth/v1/validator/{pubkey}/gas_limit") do (
pubkey: ValidatorPubKey) -> RestApiResponse:
let authStatus = checkAuthorization(request, host)
if authStatus.isErr():
return authErrorResponse authStatus.error
@ -460,7 +482,7 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
return keymanagerApiError(Http400, InvalidValidatorPublicKey)
res = host.removeGasLimitFile(pubkey)
return if res.isOk:
if res.isOk:
RestApiResponse.response("", Http204, "text/plain")
else:
keymanagerApiError(
@ -468,17 +490,18 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
# TODO: These URLs will be changed once we submit a proposal for
# /eth/v2/remotekeys that supports distributed keys.
router.api(MethodGet, "/eth/v1/remotekeys/distributed") do () -> RestApiResponse:
router.api2(MethodGet, "/eth/v1/remotekeys/distributed") do (
) -> RestApiResponse:
let authStatus = checkAuthorization(request, host)
if authStatus.isErr():
return authErrorResponse authStatus.error
let response = GetDistributedKeystoresResponse(
data: listRemoteDistributedValidators(host.validatorPool[]))
return RestApiResponse.jsonResponsePlain(response)
RestApiResponse.jsonResponsePlain(response)
# TODO: These URLs will be changed once we submit a proposal for
# /eth/v2/remotekeys that supports distributed keys.
router.api(MethodPost, "/eth/v1/remotekeys/distributed") do (
router.api2(MethodPost, "/eth/v1/remotekeys/distributed") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
let authStatus = checkAuthorization(request, host)
if authStatus.isErr():
@ -504,9 +527,9 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
)
response.data.add handleAddRemoteValidatorReq(host, keystore)
return RestApiResponse.jsonResponsePlain(response)
RestApiResponse.jsonResponsePlain(response)
router.api(MethodDelete, "/eth/v1/remotekeys/distributed") do (
router.api2(MethodDelete, "/eth/v1/remotekeys/distributed") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
let authStatus = checkAuthorization(request, host)
if authStatus.isErr():
@ -524,10 +547,10 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
for index, key in keys:
response.data.add handleRemoveValidatorReq(host, key)
return RestApiResponse.jsonResponsePlain(response)
RestApiResponse.jsonResponsePlain(response)
# https://ethereum.github.io/keymanager-APIs/?urls.primaryName=dev#/Voluntary%20Exit/signVoluntaryExit
router.api(MethodPost, "/eth/v1/validator/{pubkey}/voluntary_exit") do (
router.api2(MethodPost, "/eth/v1/validator/{pubkey}/voluntary_exit") do (
pubkey: ValidatorPubKey, epoch: Option[Epoch],
contentBody: Option[ContentBody]) -> RestApiResponse:
@ -575,4 +598,4 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
message: voluntaryExit,
signature: signature
)
return RestApiResponse.jsonResponse(response)
RestApiResponse.jsonResponse(response)

View File

@ -15,8 +15,8 @@ logScope: topics = "rest_light_client"
proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getLightClientBootstrap
router.api(MethodGet,
"/eth/v1/beacon/light_client/bootstrap/{block_root}") do (
router.api2(MethodGet,
"/eth/v1/beacon/light_client/bootstrap/{block_root}") do (
block_root: Eth2Digest) -> RestApiResponse:
doAssert node.dag.lcDataStore.serve
let contentType =
@ -51,8 +51,8 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonError(Http404, LCBootstrapUnavailable)
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getLightClientUpdatesByRange
router.api(MethodGet,
"/eth/v1/beacon/light_client/updates") do (
router.api2(MethodGet,
"/eth/v1/beacon/light_client/updates") do (
start_period: Option[SyncCommitteePeriod], count: Option[uint64]
) -> RestApiResponse:
doAssert node.dag.lcDataStore.serve
@ -116,8 +116,8 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) =
RestApiResponse.jsonError(Http500, InvalidAcceptError)
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getLightClientFinalityUpdate
router.api(MethodGet,
"/eth/v1/beacon/light_client/finality_update") do (
router.api2(MethodGet,
"/eth/v1/beacon/light_client/finality_update") do (
) -> RestApiResponse:
doAssert node.dag.lcDataStore.serve
let contentType =
@ -147,8 +147,8 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonError(Http404, LCFinUpdateUnavailable)
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getLightClientOptimisticUpdate
router.api(MethodGet,
"/eth/v1/beacon/light_client/optimistic_update") do (
router.api2(MethodGet,
"/eth/v1/beacon/light_client/optimistic_update") do (
) -> RestApiResponse:
doAssert node.dag.lcDataStore.serve
let contentType =

View File

@ -152,16 +152,16 @@ proc toNode(v: PubSubPeer, backoff: Moment): RestPubSubPeer =
)
proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
router.api(MethodGet, "/nimbus/v1/beacon/head") do () -> RestApiResponse:
return RestApiResponse.jsonResponse(node.dag.head.slot)
router.api2(MethodGet, "/nimbus/v1/beacon/head") do () -> RestApiResponse:
RestApiResponse.jsonResponse(node.dag.head.slot)
router.api(MethodGet, "/nimbus/v1/chain/head") do() -> RestApiResponse:
router.api2(MethodGet, "/nimbus/v1/chain/head") do() -> RestApiResponse:
let
head = node.dag.head
finalized = getStateField(node.dag.headState, finalized_checkpoint)
justified =
getStateField(node.dag.headState, current_justified_checkpoint)
return RestApiResponse.jsonResponse(
RestApiResponse.jsonResponse(
(
head_slot: head.slot,
head_block_root: head.root.data.toHex(),
@ -172,26 +172,26 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
)
)
router.api(MethodGet, "/nimbus/v1/syncmanager/status") do (
router.api2(MethodGet, "/nimbus/v1/syncmanager/status") do (
) -> RestApiResponse:
return RestApiResponse.jsonResponse(node.syncManager.inProgress)
RestApiResponse.jsonResponse(node.syncManager.inProgress)
router.api(MethodGet, "/nimbus/v1/node/peerid") do (
router.api2(MethodGet, "/nimbus/v1/node/peerid") do (
) -> RestApiResponse:
return RestApiResponse.jsonResponse((peerid: $node.network.peerId()))
RestApiResponse.jsonResponse((peerid: $node.network.peerId()))
router.api(MethodGet, "/nimbus/v1/node/version") do (
router.api2(MethodGet, "/nimbus/v1/node/version") do (
) -> RestApiResponse:
return RestApiResponse.jsonResponse((version: "Nimbus/" & fullVersionStr))
RestApiResponse.jsonResponse((version: "Nimbus/" & fullVersionStr))
router.api(MethodGet, "/nimbus/v1/network/ids") do (
router.api2(MethodGet, "/nimbus/v1/network/ids") do (
) -> RestApiResponse:
var res: seq[PeerId]
for peerId, peer in node.network.peerPool:
res.add(peerId)
return RestApiResponse.jsonResponse((peerids: res))
RestApiResponse.jsonResponse((peerids: res))
router.api(MethodGet, "/nimbus/v1/network/peers") do (
router.api2(MethodGet, "/nimbus/v1/network/peers") do (
) -> RestApiResponse:
var res: seq[RestSimplePeer]
for id, peer in node.network.peerPool:
@ -202,9 +202,9 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
score: peer.score
)
)
return RestApiResponse.jsonResponse((peers: res))
RestApiResponse.jsonResponse((peers: res))
router.api(MethodPost, "/nimbus/v1/graffiti") do (
router.api2(MethodPost, "/nimbus/v1/graffiti") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
if contentBody.isNone:
return RestApiResponse.jsonError(Http400, EmptyRequestBodyError)
@ -225,20 +225,19 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonError(Http400, InvalidGraffitiBytesValue,
$graffitiBytes.error())
node.graffitiBytes = graffitiBytes.get()
return RestApiResponse.jsonResponse((result: true))
RestApiResponse.jsonResponse((result: true))
elif body.contentType == TextPlainMediaType:
return node.setGraffitiAux body.strData()
node.setGraffitiAux body.strData()
elif body.contentType == UrlEncodedMediaType:
return node.setGraffitiAux decodeUrl(body.strData())
node.setGraffitiAux decodeUrl(body.strData())
else:
return RestApiResponse.jsonError(Http400, "Unsupported content type: " &
$body.contentType)
RestApiResponse.jsonError(
Http400, "Unsupported content type: " & $body.contentType)
router.api(MethodGet, "/nimbus/v1/graffiti") do (
) -> RestApiResponse:
return RestApiResponse.jsonResponse(node.graffitiBytes)
router.api2(MethodGet, "/nimbus/v1/graffiti") do () -> RestApiResponse:
RestApiResponse.jsonResponse(node.graffitiBytes)
router.api(MethodPost, "/nimbus/v1/chronicles/settings") do (
router.api2(MethodPost, "/nimbus/v1/chronicles/settings") do (
log_level: Option[string]) -> RestApiResponse:
if log_level.isSome():
let level =
@ -249,15 +248,17 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
$res.error())
res.get()
{.gcsafe.}:
updateLogLevel(level)
return RestApiResponse.jsonResponse((result: true))
try:
updateLogLevel(level)
except ValueError:
return RestApiResponse.jsonResponse((result: false))
RestApiResponse.jsonResponse((result: true))
router.api(MethodGet, "/nimbus/v1/eth1/chain") do (
) -> RestApiResponse:
router.api2(MethodGet, "/nimbus/v1/eth1/chain") do () -> RestApiResponse:
let res = mapIt(node.elManager.eth1ChainBlocks, it)
return RestApiResponse.jsonResponse(res)
RestApiResponse.jsonResponse(res)
router.api(MethodGet, "/nimbus/v1/eth1/proposal_data") do (
router.api2(MethodGet, "/nimbus/v1/eth1/proposal_data") do (
) -> RestApiResponse:
let wallSlot = node.beaconClock.now.slotOrZero
let head =
@ -279,7 +280,7 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
do:
return RestApiResponse.jsonError(Http400, PrunedStateError)
router.api(MethodGet, "/nimbus/v1/debug/chronos/futures") do (
router.api2(MethodGet, "/nimbus/v1/debug/chronos/futures") do (
) -> RestApiResponse:
when defined(chronosFutureTracking):
var res: seq[RestFutureInfo]
@ -299,12 +300,12 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
state: $item.state
)
)
return RestApiResponse.jsonResponse(res)
RestApiResponse.jsonResponse(res)
else:
return RestApiResponse.jsonError(Http503,
RestApiResponse.jsonError(Http503,
"Compile with '-d:chronosFutureTracking' to get this request working")
router.api(MethodGet, "/nimbus/v1/debug/chronos/metrics") do (
router.api2(MethodGet, "/nimbus/v1/debug/chronos/metrics") do (
) -> RestApiResponse:
template getCount(name: string): uint64 =
@ -329,9 +330,9 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
http_body_readers: getCount(HttpBodyReaderTrackerName),
http_body_writers: getCount(HttpBodyWriterTrackerName)
)
return RestApiResponse.jsonResponse(res)
RestApiResponse.jsonResponse(res)
router.api(MethodGet, "/nimbus/v1/debug/chronos/restserver/connections") do (
router.api2(MethodGet, "/nimbus/v1/debug/chronos/restserver/connections") do (
) -> RestApiResponse:
var res: seq[RestConnectionInfo]
for connection in node.restServer.server.getConnections():
@ -378,9 +379,9 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
since_create: sinceCreate
)
)
return RestApiResponse.jsonResponse(res)
RestApiResponse.jsonResponse(res)
router.api(MethodPost, "/nimbus/v1/validator/activity/{epoch}") do (
router.api2(MethodPost, "/nimbus/v1/validator/activity/{epoch}") do (
epoch: Epoch, contentBody: Option[ContentBody]) -> RestApiResponse:
let indexList =
block:
@ -441,11 +442,10 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
active: node.attestationPool[].validatorSeenAtEpoch(qepoch, it)
)
)
return RestApiResponse.jsonResponse(response)
RestApiResponse.jsonResponse(response)
router.api(MethodGet, "/nimbus/v1/debug/gossip/peers") do (
router.api2(MethodGet, "/nimbus/v1/debug/gossip/peers") do (
) -> RestApiResponse:
let gossipPeers =
block:
var res: seq[tuple[topic: string, peers: seq[RestPubSubPeer]]]
@ -496,7 +496,7 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
for peerId, peer in node.network.pubsub.peers:
peers.add(RestPeerStatus(peerId: peerId, connected: peer.connected))
peers
return RestApiResponse.jsonResponse(
RestApiResponse.jsonResponse(
(
gossip_peers: gossipPeers,
mesh_peers: meshPeers,
@ -506,7 +506,7 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
)
)
router.api(MethodPost, "/nimbus/v1/timesync") do (
router.api2(MethodPost, "/nimbus/v1/timesync") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
let
timestamp2 = getTimestamp()
@ -528,4 +528,4 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
timestamp3: getTimestamp(),
delay: uint64(delay.nanoseconds)
)
return RestApiResponse.jsonResponsePlain(response)
RestApiResponse.jsonResponsePlain(response)

View File

@ -140,7 +140,7 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
RestApiResponse.prepareJsonResponse((version: "Nimbus/" & fullVersionStr))
# https://ethereum.github.io/beacon-APIs/#/Node/getNetworkIdentity
router.api(MethodGet, "/eth/v1/node/identity") do () -> RestApiResponse:
router.api2(MethodGet, "/eth/v1/node/identity") do () -> RestApiResponse:
let discoveryAddresses =
block:
let res = node.getDiscoveryAddresses()
@ -157,7 +157,7 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
else:
newSeq[string]()
return RestApiResponse.jsonResponse(
RestApiResponse.jsonResponse(
(
peer_id: $node.network.peerId(),
enr: node.network.enrRecord().toURI(),
@ -172,7 +172,7 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
)
# https://ethereum.github.io/beacon-APIs/#/Node/getPeers
router.api(MethodGet, "/eth/v1/node/peers") do (
router.api2(MethodGet, "/eth/v1/node/peers") do (
state: seq[PeerStateKind],
direction: seq[PeerDirectKind]) -> RestApiResponse:
let connectionMask =
@ -208,11 +208,10 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
proto: node.network.switch.peerStore[ProtoVersionBook][peer.peerId]
)
res.add(peer)
return RestApiResponse.jsonResponseWMeta(res,
(count: RestNumeric(len(res))))
RestApiResponse.jsonResponseWMeta(res, (count: RestNumeric(len(res))))
# https://ethereum.github.io/beacon-APIs/#/Node/getPeerCount
router.api(MethodGet, "/eth/v1/node/peer_count") do () -> RestApiResponse:
router.api2(MethodGet, "/eth/v1/node/peer_count") do () -> RestApiResponse:
var res: RestNodePeerCount
for item in node.network.peers.values():
case item.connectionState
@ -226,10 +225,10 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
inc(res.disconnected)
of ConnectionState.None:
discard
return RestApiResponse.jsonResponse(res)
RestApiResponse.jsonResponse(res)
# https://ethereum.github.io/beacon-APIs/#/Node/getPeer
router.api(MethodGet, "/eth/v1/node/peers/{peer_id}") do (
router.api2(MethodGet, "/eth/v1/node/peers/{peer_id}") do (
peer_id: PeerId) -> RestApiResponse:
let peer =
block:
@ -240,25 +239,26 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
if isNil(res):
return RestApiResponse.jsonError(Http404, PeerNotFoundError)
res
return RestApiResponse.jsonResponse(
RestApiResponse.jsonResponse(
(
peer_id: $peer.peerId,
enr: if peer.enr.isSome(): peer.enr.get().toURI() else: "",
last_seen_p2p_address: getLastSeenAddress(node, peer.peerId),
state: peer.connectionState.toString(),
direction: peer.direction.toString(),
agent: node.network.switch.peerStore[AgentBook][peer.peerId], # Fields `agent` and `proto` are not
proto: node.network.switch.peerStore[ProtoVersionBook][peer.peerId] # part of specification
agent: node.network.switch.peerStore[AgentBook][peer.peerId],
# Fields `agent` and `proto` are not part of specification
proto: node.network.switch.peerStore[ProtoVersionBook][peer.peerId]
# Fields `agent` and `proto` are not part of specification
)
)
# https://ethereum.github.io/beacon-APIs/#/Node/getNodeVersion
router.api(MethodGet, "/eth/v1/node/version") do () -> RestApiResponse:
return RestApiResponse.response(cachedVersion, Http200,
"application/json")
router.api2(MethodGet, "/eth/v1/node/version") do () -> RestApiResponse:
RestApiResponse.response(cachedVersion, Http200, "application/json")
# https://ethereum.github.io/beacon-APIs/#/Node/getSyncingStatus
router.api(MethodGet, "/eth/v1/node/syncing") do () -> RestApiResponse:
router.api2(MethodGet, "/eth/v1/node/syncing") do () -> RestApiResponse:
let
wallSlot = node.beaconClock.now().slotOrZero()
headSlot = node.dag.head.slot
@ -284,10 +284,10 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
is_syncing: isSyncing, is_optimistic: isOptimistic,
el_offline: elOffline
)
return RestApiResponse.jsonResponse(info)
RestApiResponse.jsonResponse(info)
# https://ethereum.github.io/beacon-APIs/#/Node/getHealth
router.api(MethodGet, "/eth/v1/node/health") do () -> RestApiResponse:
router.api2(MethodGet, "/eth/v1/node/health") do () -> RestApiResponse:
# TODO: Add ability to detect node's issues and return 503 error according
# to specification.
let status =
@ -295,4 +295,4 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
Http206
else:
Http200
return RestApiResponse.response("", status, contentType = "")
RestApiResponse.response("", status, contentType = "")

View File

@ -24,7 +24,7 @@ logScope: topics = "rest_validatorapi"
proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/#/Validator/getAttesterDuties
router.api(MethodPost, "/eth/v1/validator/duties/attester/{epoch}") do (
router.api2(MethodPost, "/eth/v1/validator/duties/attester/{epoch}") do (
epoch: Epoch, contentBody: Option[ContentBody]) -> RestApiResponse:
let indexList =
block:
@ -107,11 +107,11 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
shufflingRef.attester_dependent_slot,
shufflingRef.attester_dependent_root)
return RestApiResponse.jsonResponseWRoot(
RestApiResponse.jsonResponseWRoot(
duties, shufflingRef.attester_dependent_root, optimistic)
# https://ethereum.github.io/beacon-APIs/#/Validator/getProposerDuties
router.api(MethodGet, "/eth/v1/validator/duties/proposer/{epoch}") do (
router.api2(MethodGet, "/eth/v1/validator/duties/proposer/{epoch}") do (
epoch: Epoch) -> RestApiResponse:
let qepoch =
block:
@ -159,11 +159,11 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
epochRef.proposer_dependent_slot,
epochRef.proposer_dependent_root)
return RestApiResponse.jsonResponseWRoot(
RestApiResponse.jsonResponseWRoot(
duties, epochRef.proposer_dependent_root, optimistic)
# https://ethereum.github.io/beacon-APIs/#/Validator/getSyncCommitteeDuties
router.api(MethodPost, "/eth/v1/validator/duties/sync/{epoch}") do (
router.api2(MethodPost, "/eth/v1/validator/duties/sync/{epoch}") do (
epoch: Epoch, contentBody: Option[ContentBody]) -> RestApiResponse:
let indexList =
block:
@ -311,13 +311,13 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
let res = emptyResponse()
return RestApiResponse.jsonResponseWOpt(res, execOpt = Opt.some(false))
return RestApiResponse.jsonError(Http404, StateNotFoundError)
RestApiResponse.jsonError(Http404, StateNotFoundError)
# https://ethereum.github.io/beacon-APIs/#/Validator/produceBlock
router.api(MethodGet, "/eth/v1/validator/blocks/{slot}") do (
router.api2(MethodGet, "/eth/v1/validator/blocks/{slot}") do (
slot: Slot, randao_reveal: Option[ValidatorSig],
graffiti: Option[GraffitiBytes]) -> RestApiResponse:
return RestApiResponse.jsonError(
RestApiResponse.jsonError(
Http410, DeprecatedRemovalValidatorBlocksV1)
# https://ethereum.github.io/beacon-APIs/#/Validator/produceBlockV2
@ -691,7 +691,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
raiseAssert "preferredContentType() returns invalid content type"
# https://ethereum.github.io/beacon-APIs/#/Validator/produceAttestationData
router.api(MethodGet, "/eth/v1/validator/attestation_data") do (
router.api2(MethodGet, "/eth/v1/validator/attestation_data") do (
slot: Option[Slot],
committee_index: Option[CommitteeIndex]) -> RestApiResponse:
let adata =
@ -751,10 +751,10 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
let epochRef = node.dag.getEpochRef(qhead, qslot.epoch, true).valueOr:
return RestApiResponse.jsonError(Http400, PrunedStateError, $error)
makeAttestationData(epochRef, qhead.atSlot(qslot), qindex)
return RestApiResponse.jsonResponse(adata)
RestApiResponse.jsonResponse(adata)
# https://ethereum.github.io/beacon-APIs/#/Validator/getAggregatedAttestation
router.api(MethodGet, "/eth/v1/validator/aggregate_attestation") do (
router.api2(MethodGet, "/eth/v1/validator/aggregate_attestation") do (
attestation_data_root: Option[Eth2Digest],
slot: Option[Slot]) -> RestApiResponse:
let attestation =
@ -784,10 +784,10 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonError(Http400,
UnableToGetAggregatedAttestationError)
res.get()
return RestApiResponse.jsonResponse(attestation)
RestApiResponse.jsonResponse(attestation)
# https://ethereum.github.io/beacon-APIs/#/Validator/publishAggregateAndProofs
router.api(MethodPost, "/eth/v1/validator/aggregate_and_proofs") do (
router.api2(MethodPost, "/eth/v1/validator/aggregate_and_proofs") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
let proofs =
block:
@ -810,7 +810,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
await allFutures(pending)
for future in pending:
if future.completed():
let res = future.read()
let res = future.value()
if res.isErr():
return RestApiResponse.jsonError(Http400,
AggregateAndProofValidationError,
@ -818,11 +818,11 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
else:
return RestApiResponse.jsonError(Http500,
"Unexpected server failure, while sending aggregate and proof")
return RestApiResponse.jsonMsgResponse(AggregateAndProofValidationSuccess)
RestApiResponse.jsonMsgResponse(AggregateAndProofValidationSuccess)
# https://ethereum.github.io/beacon-APIs/#/Validator/prepareBeaconCommitteeSubnet
router.api(MethodPost,
"/eth/v1/validator/beacon_committee_subscriptions") do (
router.api2(MethodPost,
"/eth/v1/validator/beacon_committee_subscriptions") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
let requests =
block:
@ -898,11 +898,11 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
node.validatorMonitor[].addAutoMonitor(
validator_pubkey, ValidatorIndex(request.validator_index))
return RestApiResponse.jsonMsgResponse(BeaconCommitteeSubscriptionSuccess)
RestApiResponse.jsonMsgResponse(BeaconCommitteeSubscriptionSuccess)
# https://ethereum.github.io/beacon-APIs/#/Validator/prepareSyncCommitteeSubnets
router.api(MethodPost,
"/eth/v1/validator/sync_committee_subscriptions") do (
router.api2(MethodPost,
"/eth/v1/validator/sync_committee_subscriptions") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
let subscriptions =
block:
@ -939,11 +939,11 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
node.validatorMonitor[].addAutoMonitor(
validator_pubkey, ValidatorIndex(item.validator_index))
return RestApiResponse.jsonMsgResponse(SyncCommitteeSubscriptionSuccess)
RestApiResponse.jsonMsgResponse(SyncCommitteeSubscriptionSuccess)
# https://ethereum.github.io/beacon-APIs/#/Validator/produceSyncCommitteeContribution
router.api(MethodGet,
"/eth/v1/validator/sync_committee_contribution") do (
router.api2(MethodGet,
"/eth/v1/validator/sync_committee_contribution") do (
slot: Option[Slot], subcommittee_index: Option[SyncSubCommitteeIndex],
beacon_block_root: Option[Eth2Digest]) -> RestApiResponse:
let qslot = block:
@ -1003,11 +1003,11 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
qslot, blck.bid, qindex, contribution)
if not(res):
return RestApiResponse.jsonError(Http400, ProduceContributionError)
return RestApiResponse.jsonResponse(contribution)
RestApiResponse.jsonResponse(contribution)
# https://ethereum.github.io/beacon-APIs/#/Validator/publishContributionAndProofs
router.api(MethodPost,
"/eth/v1/validator/contribution_and_proofs") do (
router.api2(MethodPost,
"/eth/v1/validator/contribution_and_proofs") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
let proofs =
block:
@ -1033,31 +1033,28 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
await allFutures(pending)
for index, future in pending:
if future.completed():
let fres = future.read()
let fres = future.value()
if fres.isErr():
let failure = RestIndexedErrorMessageItem(index: index,
message: $fres.error())
res.add(failure)
elif future.failed() or future.cancelled():
# This is unexpected failure, so we log the error message.
let exc = future.readError()
let exc = future.error()
let failure = RestIndexedErrorMessageItem(index: index,
message: $exc.msg)
res.add(failure)
res
if len(failures) > 0:
return RestApiResponse.jsonErrorList(Http400,
ContributionAndProofValidationError,
failures)
RestApiResponse.jsonErrorList(
Http400, ContributionAndProofValidationError, failures)
else:
return RestApiResponse.jsonMsgResponse(
ContributionAndProofValidationSuccess
)
RestApiResponse.jsonMsgResponse(ContributionAndProofValidationSuccess)
# https://ethereum.github.io/beacon-APIs/#/ValidatorRequiredApi/prepareBeaconProposer
router.api(MethodPost,
"/eth/v1/validator/prepare_beacon_proposer") do (
router.api2(MethodPost,
"/eth/v1/validator/prepare_beacon_proposer") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
let
body =
@ -1087,12 +1084,12 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
numUpdatedFeeRecipients = numUpdated,
numRefreshedFeeRecipients = numRefreshed
return RestApiResponse.response("", Http200, "text/plain")
RestApiResponse.response("", Http200, "text/plain")
# https://ethereum.github.io/beacon-APIs/#/Validator/registerValidator
# https://github.com/ethereum/beacon-APIs/blob/v2.3.0/apis/validator/register_validator.yaml
router.api(MethodPost,
"/eth/v1/validator/register_validator") do (
router.api2(MethodPost,
"/eth/v1/validator/register_validator") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
let
body =
@ -1114,10 +1111,10 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
node.externalBuilderRegistrations[signedValidatorRegistration.message.pubkey] =
signedValidatorRegistration
return RestApiResponse.response("", Http200, "text/plain")
RestApiResponse.response("", Http200, "text/plain")
# https://ethereum.github.io/beacon-APIs/#/Validator/getLiveness
router.api(MethodPost, "/eth/v1/validator/liveness/{epoch}") do (
router.api2(MethodPost, "/eth/v1/validator/liveness/{epoch}") do (
epoch: Epoch, contentBody: Option[ContentBody]) -> RestApiResponse:
let
qepoch =
@ -1183,10 +1180,10 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
is_live: node.attestationPool[].validatorSeenAtEpoch(qepoch, it)
)
)
return RestApiResponse.jsonResponse(response)
RestApiResponse.jsonResponse(response)
# https://github.com/ethereum/beacon-APIs/blob/f087fbf2764e657578a6c29bdf0261b36ee8db1e/apis/validator/beacon_committee_selections.yaml
router.api(MethodPost, "/eth/v1/validator/beacon_committee_selections") do (
router.api2(MethodPost, "/eth/v1/validator/beacon_committee_selections") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
# "Consensus clients need not support this endpoint and may return a 501."
# https://github.com/ethereum/beacon-APIs/pull/224: "This endpoint need not
@ -1194,11 +1191,10 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
# able to use it when a feature flag is turned on, the intercepting
# middleware can handle and swallow the request. I suggest a CL either
# returns 501 Not Implemented [or] 400 Bad Request."
return RestApiResponse.jsonError(
Http501, AggregationSelectionNotImplemented)
RestApiResponse.jsonError(Http501, AggregationSelectionNotImplemented)
# https://github.com/ethereum/beacon-APIs/blob/f087fbf2764e657578a6c29bdf0261b36ee8db1e/apis/validator/sync_committee_selections.yaml
router.api(MethodPost, "/eth/v1/validator/sync_committee_selections") do (
router.api2(MethodPost, "/eth/v1/validator/sync_committee_selections") do (
contentBody: Option[ContentBody]) -> RestApiResponse:
# "Consensus clients need not support this endpoint and may return a 501."
# https://github.com/ethereum/beacon-APIs/pull/224: "This endpoint need not
@ -1206,5 +1202,4 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
# able to use it when a feature flag is turned on, the intercepting
# middleware can handle and swallow the request. I suggest a CL either
# returns 501 Not Implemented [or] 400 Bad Request."
return RestApiResponse.jsonError(
Http501, AggregationSelectionNotImplemented)
RestApiResponse.jsonError(Http501, AggregationSelectionNotImplemented)