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:
parent
9acb7b99fe
commit
525b994e7d
|
@ -129,14 +129,17 @@ proc toString*(kind: ValidatorFilterKind): string =
|
||||||
|
|
||||||
proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
# https://github.com/ethereum/EIPs/blob/master/EIPS/eip-4881.md
|
# 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:
|
let snapshot = node.db.getDepositTreeSnapshot().valueOr:
|
||||||
# This can happen in a very short window after the client is started, but the
|
# This can happen in a very short window after the client is started,
|
||||||
# snapshot record still haven't been upgraded in the database. Returning 404
|
# but the snapshot record still haven't been upgraded in the database.
|
||||||
# should be easy to handle for the clients - they just need to retry.
|
# Returning 404 should be easy to handle for the clients - they just need
|
||||||
return RestApiResponse.jsonError(Http404, NoFinalizedSnapshotAvailableError)
|
# to retry.
|
||||||
|
return RestApiResponse.jsonError(Http404,
|
||||||
|
NoFinalizedSnapshotAvailableError)
|
||||||
|
|
||||||
return RestApiResponse.jsonResponse(
|
RestApiResponse.jsonResponse(
|
||||||
RestDepositSnapshot(
|
RestDepositSnapshot(
|
||||||
finalized: snapshot.depositContractState.branch,
|
finalized: snapshot.depositContractState.branch,
|
||||||
deposit_root: snapshot.getDepositRoot(),
|
deposit_root: snapshot.getDepositRoot(),
|
||||||
|
@ -145,8 +148,8 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
execution_block_height: snapshot.blockHeight))
|
execution_block_height: snapshot.blockHeight))
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getGenesis
|
# https://ethereum.github.io/beacon-APIs/#/Beacon/getGenesis
|
||||||
router.api(MethodGet, "/eth/v1/beacon/genesis") do () -> RestApiResponse:
|
router.api2(MethodGet, "/eth/v1/beacon/genesis") do () -> RestApiResponse:
|
||||||
return RestApiResponse.jsonResponse(
|
RestApiResponse.jsonResponse(
|
||||||
(
|
(
|
||||||
genesis_time: getStateField(node.dag.headState, genesis_time),
|
genesis_time: getStateField(node.dag.headState, genesis_time),
|
||||||
genesis_validators_root:
|
genesis_validators_root:
|
||||||
|
@ -156,7 +159,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
)
|
)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateRoot
|
# 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:
|
state_id: StateIdent) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
sid = state_id.valueOr:
|
sid = state_id.valueOr:
|
||||||
|
@ -177,10 +180,10 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
node.dag.isFinalized(bslot.bid)
|
node.dag.isFinalized(bslot.bid)
|
||||||
)
|
)
|
||||||
|
|
||||||
return RestApiResponse.jsonError(Http404, StateNotFoundError)
|
RestApiResponse.jsonError(Http404, StateNotFoundError)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateFork
|
# 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:
|
state_id: StateIdent) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
sid = state_id.valueOr:
|
sid = state_id.valueOr:
|
||||||
|
@ -207,11 +210,12 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
node.getStateOptimistic(state),
|
node.getStateOptimistic(state),
|
||||||
node.dag.isFinalized(bslot.bid)
|
node.dag.isFinalized(bslot.bid)
|
||||||
)
|
)
|
||||||
return RestApiResponse.jsonError(Http404, StateNotFoundError)
|
|
||||||
|
RestApiResponse.jsonError(Http404, StateNotFoundError)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateFinalityCheckpoints
|
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateFinalityCheckpoints
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/beacon/states/{state_id}/finality_checkpoints") do (
|
"/eth/v1/beacon/states/{state_id}/finality_checkpoints") do (
|
||||||
state_id: StateIdent) -> RestApiResponse:
|
state_id: StateIdent) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
sid = state_id.valueOr:
|
sid = state_id.valueOr:
|
||||||
|
@ -238,7 +242,8 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
node.getStateOptimistic(state),
|
node.getStateOptimistic(state),
|
||||||
node.dag.isFinalized(bslot.bid)
|
node.dag.isFinalized(bslot.bid)
|
||||||
)
|
)
|
||||||
return RestApiResponse.jsonError(Http404, StateNotFoundError)
|
|
||||||
|
RestApiResponse.jsonError(Http404, StateNotFoundError)
|
||||||
|
|
||||||
proc getIndices(
|
proc getIndices(
|
||||||
node: BeaconNode,
|
node: BeaconNode,
|
||||||
|
@ -369,7 +374,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
RestApiResponse.jsonError(Http404, StateNotFoundError)
|
RestApiResponse.jsonError(Http404, StateNotFoundError)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateValidators
|
# 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],
|
state_id: StateIdent, id: seq[ValidatorIdent],
|
||||||
status: seq[ValidatorFilter]) -> RestApiResponse:
|
status: seq[ValidatorFilter]) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
|
@ -404,7 +409,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
getValidators(node, bslot, validatorsMask, validatorIds)
|
getValidators(node, bslot, validatorsMask, validatorIds)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/postStateValidators
|
# 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:
|
state_id: StateIdent, contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
(validatorIds, validatorsMask) =
|
(validatorIds, validatorsMask) =
|
||||||
|
@ -431,8 +436,8 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
getValidators(node, bslot, validatorsMask, validatorIds)
|
getValidators(node, bslot, validatorsMask, validatorIds)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateValidator
|
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateValidator
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/beacon/states/{state_id}/validators/{validator_id}") do (
|
"/eth/v1/beacon/states/{state_id}/validators/{validator_id}") do (
|
||||||
state_id: StateIdent, validator_id: ValidatorIdent) -> RestApiResponse:
|
state_id: StateIdent, validator_id: ValidatorIdent) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
sid = state_id.valueOr:
|
sid = state_id.valueOr:
|
||||||
|
@ -465,7 +470,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
of ValidatorQueryKind.Index:
|
of ValidatorQueryKind.Index:
|
||||||
let vres = vid.index.toValidatorIndex()
|
let vres = vid.index.toValidatorIndex()
|
||||||
if vres.isErr():
|
if vres.isErr():
|
||||||
case vres.error()
|
case vres.error
|
||||||
of ValidatorIndexError.TooHighValue:
|
of ValidatorIndexError.TooHighValue:
|
||||||
return RestApiResponse.jsonError(Http400,
|
return RestApiResponse.jsonError(Http400,
|
||||||
TooHighValidatorIndexValueError)
|
TooHighValidatorIndexValueError)
|
||||||
|
@ -493,11 +498,12 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
node.getStateOptimistic(state),
|
node.getStateOptimistic(state),
|
||||||
node.dag.isFinalized(bslot.bid)
|
node.dag.isFinalized(bslot.bid)
|
||||||
)
|
)
|
||||||
return RestApiResponse.jsonError(Http404, StateNotFoundError)
|
|
||||||
|
RestApiResponse.jsonError(Http404, StateNotFoundError)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateValidatorBalances
|
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateValidatorBalances
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/beacon/states/{state_id}/validator_balances") do (
|
"/eth/v1/beacon/states/{state_id}/validator_balances") do (
|
||||||
state_id: StateIdent, id: seq[ValidatorIdent]) -> RestApiResponse:
|
state_id: StateIdent, id: seq[ValidatorIdent]) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
sid = state_id.valueOr:
|
sid = state_id.valueOr:
|
||||||
|
@ -522,8 +528,8 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
getBalances(node, bslot, validatorIds)
|
getBalances(node, bslot, validatorIds)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/postStateValidatorBalances
|
# https://ethereum.github.io/beacon-APIs/#/Beacon/postStateValidatorBalances
|
||||||
router.api(MethodPost,
|
router.api2(MethodPost,
|
||||||
"/eth/v1/beacon/states/{state_id}/validator_balances") do (
|
"/eth/v1/beacon/states/{state_id}/validator_balances") do (
|
||||||
state_id: StateIdent, contentBody: Option[ContentBody]) -> RestApiResponse:
|
state_id: StateIdent, contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
validatorIds =
|
validatorIds =
|
||||||
|
@ -546,8 +552,8 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
getBalances(node, bslot, validatorIds)
|
getBalances(node, bslot, validatorIds)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getEpochCommittees
|
# https://ethereum.github.io/beacon-APIs/#/Beacon/getEpochCommittees
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/beacon/states/{state_id}/committees") do (
|
"/eth/v1/beacon/states/{state_id}/committees") do (
|
||||||
state_id: StateIdent, epoch: Option[Epoch], index: Option[CommitteeIndex],
|
state_id: StateIdent, epoch: Option[Epoch], index: Option[CommitteeIndex],
|
||||||
slot: Option[Slot]) -> RestApiResponse:
|
slot: Option[Slot]) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
|
@ -567,7 +573,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
let repoch = epoch.get()
|
let repoch = epoch.get()
|
||||||
if repoch.isErr():
|
if repoch.isErr():
|
||||||
return RestApiResponse.jsonError(Http400, InvalidEpochValueError,
|
return RestApiResponse.jsonError(Http400, InvalidEpochValueError,
|
||||||
$repoch.error())
|
$repoch.error)
|
||||||
let res = repoch.get()
|
let res = repoch.get()
|
||||||
|
|
||||||
if res > bslot.slot.epoch + MIN_SEED_LOOKAHEAD:
|
if res > bslot.slot.epoch + MIN_SEED_LOOKAHEAD:
|
||||||
|
@ -590,7 +596,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
if rindex.isErr():
|
if rindex.isErr():
|
||||||
return RestApiResponse.jsonError(Http400,
|
return RestApiResponse.jsonError(Http400,
|
||||||
InvalidCommitteeIndexValueError,
|
InvalidCommitteeIndexValueError,
|
||||||
$rindex.error())
|
$rindex.error)
|
||||||
some(rindex.get())
|
some(rindex.get())
|
||||||
else:
|
else:
|
||||||
none[CommitteeIndex]()
|
none[CommitteeIndex]()
|
||||||
|
@ -599,12 +605,13 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
let rslot = slot.get()
|
let rslot = slot.get()
|
||||||
if rslot.isErr():
|
if rslot.isErr():
|
||||||
return RestApiResponse.jsonError(Http400, InvalidSlotValueError,
|
return RestApiResponse.jsonError(Http400, InvalidSlotValueError,
|
||||||
$rslot.error())
|
$rslot.error)
|
||||||
let res = rslot.get()
|
let res = rslot.get()
|
||||||
if vepoch.isSome():
|
if vepoch.isSome():
|
||||||
if res.epoch != vepoch.get():
|
if res.epoch != vepoch.get():
|
||||||
return RestApiResponse.jsonError(Http400, InvalidSlotValueError,
|
return RestApiResponse.jsonError(
|
||||||
"Slot does not match requested epoch")
|
Http400, InvalidSlotValueError,
|
||||||
|
"Slot does not match requested epoch")
|
||||||
else:
|
else:
|
||||||
if res.epoch > bslot.slot.epoch + 1:
|
if res.epoch > bslot.slot.epoch + 1:
|
||||||
return RestApiResponse.jsonError(
|
return RestApiResponse.jsonError(
|
||||||
|
@ -620,6 +627,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
some(res)
|
some(res)
|
||||||
else:
|
else:
|
||||||
none[Slot]()
|
none[Slot]()
|
||||||
|
|
||||||
node.withStateForBlockSlotId(bslot):
|
node.withStateForBlockSlotId(bslot):
|
||||||
proc getCommittee(slot: Slot,
|
proc getCommittee(slot: Slot,
|
||||||
index: CommitteeIndex): RestBeaconStatesCommittees =
|
index: CommitteeIndex): RestBeaconStatesCommittees =
|
||||||
|
@ -660,11 +668,11 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
node.dag.isFinalized(bslot.bid)
|
node.dag.isFinalized(bslot.bid)
|
||||||
)
|
)
|
||||||
|
|
||||||
return RestApiResponse.jsonError(Http404, StateNotFoundError)
|
RestApiResponse.jsonError(Http404, StateNotFoundError)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getEpochSyncCommittees
|
# https://ethereum.github.io/beacon-APIs/#/Beacon/getEpochSyncCommittees
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/beacon/states/{state_id}/sync_committees") do (
|
"/eth/v1/beacon/states/{state_id}/sync_committees") do (
|
||||||
state_id: StateIdent, epoch: Option[Epoch]) -> RestApiResponse:
|
state_id: StateIdent, epoch: Option[Epoch]) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
sid = state_id.valueOr:
|
sid = state_id.valueOr:
|
||||||
|
@ -683,7 +691,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
let repoch = epoch.get()
|
let repoch = epoch.get()
|
||||||
if repoch.isErr():
|
if repoch.isErr():
|
||||||
return RestApiResponse.jsonError(Http400, InvalidEpochValueError,
|
return RestApiResponse.jsonError(Http400, InvalidEpochValueError,
|
||||||
$repoch.error())
|
$repoch.error)
|
||||||
let res = repoch.get()
|
let res = repoch.get()
|
||||||
if res > MaxEpoch:
|
if res > MaxEpoch:
|
||||||
return RestApiResponse.jsonError(Http400, EpochOverflowValueError)
|
return RestApiResponse.jsonError(Http400, EpochOverflowValueError)
|
||||||
|
@ -702,7 +710,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
let res = syncCommitteeParticipants(state, qepoch)
|
let res = syncCommitteeParticipants(state, qepoch)
|
||||||
if res.isErr():
|
if res.isErr():
|
||||||
return RestApiResponse.jsonError(Http400,
|
return RestApiResponse.jsonError(Http400,
|
||||||
$res.error())
|
$res.error)
|
||||||
let kres = res.get()
|
let kres = res.get()
|
||||||
if len(kres) == 0:
|
if len(kres) == 0:
|
||||||
return RestApiResponse.jsonError(Http500, InternalServerError,
|
return RestApiResponse.jsonError(Http500, InternalServerError,
|
||||||
|
@ -742,12 +750,12 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
node.dag.isFinalized(bslot.bid)
|
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://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getStateRandao
|
||||||
# https://github.com/ethereum/beacon-APIs/blob/b3c4defa238aaa74bf22aa602aa1b24b68a4c78e/apis/beacon/states/randao.yaml
|
# https://github.com/ethereum/beacon-APIs/blob/b3c4defa238aaa74bf22aa602aa1b24b68a4c78e/apis/beacon/states/randao.yaml
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/beacon/states/{state_id}/randao") do (
|
"/eth/v1/beacon/states/{state_id}/randao") do (
|
||||||
state_id: StateIdent, epoch: Option[Epoch]) -> RestApiResponse:
|
state_id: StateIdent, epoch: Option[Epoch]) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
sid = state_id.valueOr:
|
sid = state_id.valueOr:
|
||||||
|
@ -766,7 +774,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
let repoch = epoch.get()
|
let repoch = epoch.get()
|
||||||
if repoch.isErr():
|
if repoch.isErr():
|
||||||
return RestApiResponse.jsonError(Http400, InvalidEpochValueError,
|
return RestApiResponse.jsonError(Http400, InvalidEpochValueError,
|
||||||
$repoch.error())
|
$repoch.error)
|
||||||
let res = repoch.get()
|
let res = repoch.get()
|
||||||
if res > MaxEpoch:
|
if res > MaxEpoch:
|
||||||
return RestApiResponse.jsonError(Http400, EpochOverflowValueError)
|
return RestApiResponse.jsonError(Http400, EpochOverflowValueError)
|
||||||
|
@ -801,10 +809,10 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
node.dag.isFinalized(bslot.bid)
|
node.dag.isFinalized(bslot.bid)
|
||||||
)
|
)
|
||||||
|
|
||||||
return RestApiResponse.jsonError(Http404, StateNotFoundError)
|
RestApiResponse.jsonError(Http404, StateNotFoundError)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockHeaders
|
# 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:
|
slot: Option[Slot], parent_root: Option[Eth2Digest]) -> RestApiResponse:
|
||||||
# TODO (cheatfate): This call is incomplete, because structure
|
# TODO (cheatfate): This call is incomplete, because structure
|
||||||
# of database do not allow to query blocks by `parent_root`.
|
# 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()
|
let rslot = slot.get()
|
||||||
if rslot.isErr():
|
if rslot.isErr():
|
||||||
return RestApiResponse.jsonError(Http400, InvalidSlotValueError,
|
return RestApiResponse.jsonError(Http400, InvalidSlotValueError,
|
||||||
$rslot.error())
|
$rslot.error)
|
||||||
rslot.get()
|
rslot.get()
|
||||||
else:
|
else:
|
||||||
node.dag.head.slot
|
node.dag.head.slot
|
||||||
|
@ -822,32 +830,31 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
let rroot = parent_root.get()
|
let rroot = parent_root.get()
|
||||||
if rroot.isErr():
|
if rroot.isErr():
|
||||||
return RestApiResponse.jsonError(Http400, InvalidParentRootValueError,
|
return RestApiResponse.jsonError(Http400, InvalidParentRootValueError,
|
||||||
$rroot.error())
|
$rroot.error)
|
||||||
return RestApiResponse.jsonError(Http500, NoImplementationError)
|
return RestApiResponse.jsonError(Http500, NoImplementationError)
|
||||||
|
|
||||||
let bdata = node.getForkedBlock(BlockIdent.init(qslot)).valueOr:
|
let bdata = node.getForkedBlock(BlockIdent.init(qslot)).valueOr:
|
||||||
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
|
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
|
||||||
|
|
||||||
return
|
withBlck(bdata):
|
||||||
withBlck(bdata):
|
let bid = BlockId(root: forkyBlck.root, slot: forkyBlck.message.slot)
|
||||||
let bid = BlockId(root: forkyBlck.root, slot: forkyBlck.message.slot)
|
RestApiResponse.jsonResponseFinalized(
|
||||||
RestApiResponse.jsonResponseFinalized(
|
[
|
||||||
[
|
(
|
||||||
(
|
root: forkyBlck.root,
|
||||||
root: forkyBlck.root,
|
canonical: node.dag.isCanonical(bid),
|
||||||
canonical: node.dag.isCanonical(bid),
|
header: (
|
||||||
header: (
|
message: forkyBlck.toBeaconBlockHeader,
|
||||||
message: forkyBlck.toBeaconBlockHeader,
|
signature: forkyBlck.signature
|
||||||
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
|
# 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:
|
block_id: BlockIdent) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
bid = block_id.valueOr:
|
bid = block_id.valueOr:
|
||||||
|
@ -857,21 +864,20 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
bdata = node.getForkedBlock(bid).valueOr:
|
bdata = node.getForkedBlock(bid).valueOr:
|
||||||
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
|
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
|
||||||
|
|
||||||
return
|
withBlck(bdata):
|
||||||
withBlck(bdata):
|
let bid = BlockId(root: forkyBlck.root, slot: forkyBlck.message.slot)
|
||||||
let bid = BlockId(root: forkyBlck.root, slot: forkyBlck.message.slot)
|
RestApiResponse.jsonResponseFinalized(
|
||||||
RestApiResponse.jsonResponseFinalized(
|
(
|
||||||
(
|
root: forkyBlck.root,
|
||||||
root: forkyBlck.root,
|
canonical: node.dag.isCanonical(bid),
|
||||||
canonical: node.dag.isCanonical(bid),
|
header: (
|
||||||
header: (
|
message: forkyBlck.toBeaconBlockHeader,
|
||||||
message: forkyBlck.toBeaconBlockHeader,
|
signature: forkyBlck.signature
|
||||||
signature: forkyBlck.signature
|
)
|
||||||
)
|
),
|
||||||
),
|
node.getBlockOptimistic(bdata),
|
||||||
node.getBlockOptimistic(bdata),
|
node.dag.isFinalized(bid)
|
||||||
node.dag.isFinalized(bid)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlock
|
# https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlock
|
||||||
router.api(MethodPost, "/eth/v1/beacon/blocks") do (
|
router.api(MethodPost, "/eth/v1/beacon/blocks") do (
|
||||||
|
@ -924,11 +930,11 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
|
|
||||||
if res.isErr():
|
if res.isErr():
|
||||||
return RestApiResponse.jsonError(
|
return RestApiResponse.jsonError(
|
||||||
Http503, BeaconNodeInSyncError, $res.error())
|
Http503, BeaconNodeInSyncError, $res.error)
|
||||||
if res.get().isNone():
|
if res.get().isNone():
|
||||||
return RestApiResponse.jsonError(Http202, BlockValidationError)
|
return RestApiResponse.jsonError(Http202, BlockValidationError)
|
||||||
|
|
||||||
return RestApiResponse.jsonMsgResponse(BlockValidationSuccess)
|
RestApiResponse.jsonMsgResponse(BlockValidationSuccess)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlockV2
|
# https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlockV2
|
||||||
router.api(MethodPost, "/eth/v2/beacon/blocks") do (
|
router.api(MethodPost, "/eth/v2/beacon/blocks") do (
|
||||||
|
@ -1000,11 +1006,11 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
|
|
||||||
if res.isErr():
|
if res.isErr():
|
||||||
return RestApiResponse.jsonError(
|
return RestApiResponse.jsonError(
|
||||||
Http503, BeaconNodeInSyncError, $res.error())
|
Http503, BeaconNodeInSyncError, $res.error)
|
||||||
if res.get().isNone():
|
if res.get().isNone():
|
||||||
return RestApiResponse.jsonError(Http202, BlockValidationError)
|
return RestApiResponse.jsonError(Http202, BlockValidationError)
|
||||||
|
|
||||||
return RestApiResponse.jsonMsgResponse(BlockValidationSuccess)
|
RestApiResponse.jsonMsgResponse(BlockValidationSuccess)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlindedBlock
|
# https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlindedBlock
|
||||||
# https://github.com/ethereum/beacon-APIs/blob/v2.4.0/apis/beacon/blocks/blinded_blocks.yaml
|
# 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():
|
if res.isErr():
|
||||||
return RestApiResponse.jsonError(
|
return RestApiResponse.jsonError(
|
||||||
Http500, InternalServerError, $res.error())
|
Http500, InternalServerError, $res.error)
|
||||||
if res.get().isNone():
|
if res.get().isNone():
|
||||||
return RestApiResponse.jsonError(Http202, BlockValidationError)
|
return RestApiResponse.jsonError(Http202, BlockValidationError)
|
||||||
|
|
||||||
|
@ -1076,20 +1082,20 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
|
|
||||||
if res.isErr():
|
if res.isErr():
|
||||||
return RestApiResponse.jsonError(
|
return RestApiResponse.jsonError(
|
||||||
Http503, BeaconNodeInSyncError, $res.error())
|
Http503, BeaconNodeInSyncError, $res.error)
|
||||||
elif res.get().isNone():
|
elif res.get().isNone():
|
||||||
return RestApiResponse.jsonError(Http202, BlockValidationError)
|
return RestApiResponse.jsonError(Http202, BlockValidationError)
|
||||||
|
|
||||||
return RestApiResponse.jsonMsgResponse(BlockValidationSuccess)
|
RestApiResponse.jsonMsgResponse(BlockValidationSuccess)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlock
|
# 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:
|
block_id: BlockIdent) -> RestApiResponse:
|
||||||
return RestApiResponse.jsonError(
|
RestApiResponse.jsonError(
|
||||||
Http410, DeprecatedRemovalBeaconBlocksDebugStateV1)
|
Http410, DeprecatedRemovalBeaconBlocksDebugStateV1)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockV2
|
# 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:
|
block_id: BlockIdent) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
blockIdent = block_id.valueOr:
|
blockIdent = block_id.valueOr:
|
||||||
|
@ -1105,31 +1111,31 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
if res.isErr():
|
if res.isErr():
|
||||||
return RestApiResponse.jsonError(Http406, ContentNotAcceptableError)
|
return RestApiResponse.jsonError(Http406, ContentNotAcceptableError)
|
||||||
res.get()
|
res.get()
|
||||||
return
|
|
||||||
if contentType == sszMediaType:
|
|
||||||
var data: seq[byte]
|
|
||||||
if not node.dag.getBlockSSZ(bid, data):
|
|
||||||
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
|
|
||||||
|
|
||||||
let
|
if contentType == sszMediaType:
|
||||||
fork = node.dag.cfg.consensusForkAtEpoch(bid.slot.epoch)
|
var data: seq[byte]
|
||||||
headers = [("eth-consensus-version", fork.toString())]
|
if not node.dag.getBlockSSZ(bid, data):
|
||||||
|
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
|
||||||
|
|
||||||
RestApiResponse.sszResponsePlain(data, headers)
|
let
|
||||||
elif contentType == jsonMediaType:
|
fork = node.dag.cfg.consensusForkAtEpoch(bid.slot.epoch)
|
||||||
let bdata = node.dag.getForkedBlock(bid).valueOr:
|
headers = [("eth-consensus-version", fork.toString())]
|
||||||
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
|
|
||||||
|
|
||||||
RestApiResponse.jsonResponseBlock(
|
RestApiResponse.sszResponsePlain(data, headers)
|
||||||
bdata.asSigned(),
|
elif contentType == jsonMediaType:
|
||||||
node.getBlockOptimistic(bdata),
|
let bdata = node.dag.getForkedBlock(bid).valueOr:
|
||||||
node.dag.isFinalized(bid)
|
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
|
||||||
)
|
|
||||||
else:
|
RestApiResponse.jsonResponseBlock(
|
||||||
RestApiResponse.jsonError(Http500, InvalidAcceptError)
|
bdata.asSigned(),
|
||||||
|
node.getBlockOptimistic(bdata),
|
||||||
|
node.dag.isFinalized(bid)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
RestApiResponse.jsonError(Http500, InvalidAcceptError)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockRoot
|
# 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:
|
block_id: BlockIdent) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
blockIdent = block_id.valueOr:
|
blockIdent = block_id.valueOr:
|
||||||
|
@ -1142,14 +1148,14 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
bdata = node.dag.getForkedBlock(bid).valueOr:
|
bdata = node.dag.getForkedBlock(bid).valueOr:
|
||||||
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
|
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
|
||||||
|
|
||||||
return RestApiResponse.jsonResponseFinalized(
|
RestApiResponse.jsonResponseFinalized(
|
||||||
(root: bid.root),
|
(root: bid.root),
|
||||||
node.getBlockOptimistic(bdata),
|
node.getBlockOptimistic(bdata),
|
||||||
node.dag.isFinalized(bid)
|
node.dag.isFinalized(bid)
|
||||||
)
|
)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockAttestations
|
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockAttestations
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/beacon/blocks/{block_id}/attestations") do (
|
"/eth/v1/beacon/blocks/{block_id}/attestations") do (
|
||||||
block_id: BlockIdent) -> RestApiResponse:
|
block_id: BlockIdent) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
|
@ -1159,17 +1165,16 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
bdata = node.getForkedBlock(blockIdent).valueOr:
|
bdata = node.getForkedBlock(blockIdent).valueOr:
|
||||||
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
|
return RestApiResponse.jsonError(Http404, BlockNotFoundError)
|
||||||
|
|
||||||
return
|
withBlck(bdata):
|
||||||
withBlck(bdata):
|
let bid = BlockId(root: forkyBlck.root, slot: forkyBlck.message.slot)
|
||||||
let bid = BlockId(root: forkyBlck.root, slot: forkyBlck.message.slot)
|
RestApiResponse.jsonResponseFinalized(
|
||||||
RestApiResponse.jsonResponseFinalized(
|
forkyBlck.message.body.attestations.asSeq(),
|
||||||
forkyBlck.message.body.attestations.asSeq(),
|
node.getBlockOptimistic(bdata),
|
||||||
node.getBlockOptimistic(bdata),
|
node.dag.isFinalized(bid)
|
||||||
node.dag.isFinalized(bid)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getPoolAttestations
|
# 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],
|
slot: Option[Slot],
|
||||||
committee_index: Option[CommitteeIndex]) -> RestApiResponse:
|
committee_index: Option[CommitteeIndex]) -> RestApiResponse:
|
||||||
let vindex =
|
let vindex =
|
||||||
|
@ -1178,7 +1183,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
if rindex.isErr():
|
if rindex.isErr():
|
||||||
return RestApiResponse.jsonError(Http400,
|
return RestApiResponse.jsonError(Http400,
|
||||||
InvalidCommitteeIndexValueError,
|
InvalidCommitteeIndexValueError,
|
||||||
$rindex.error())
|
$rindex.error)
|
||||||
Opt.some(rindex.get())
|
Opt.some(rindex.get())
|
||||||
else:
|
else:
|
||||||
Opt.none(CommitteeIndex)
|
Opt.none(CommitteeIndex)
|
||||||
|
@ -1187,17 +1192,17 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
let rslot = slot.get()
|
let rslot = slot.get()
|
||||||
if rslot.isErr():
|
if rslot.isErr():
|
||||||
return RestApiResponse.jsonError(Http400, InvalidSlotValueError,
|
return RestApiResponse.jsonError(Http400, InvalidSlotValueError,
|
||||||
$rslot.error())
|
$rslot.error)
|
||||||
Opt.some(rslot.get())
|
Opt.some(rslot.get())
|
||||||
else:
|
else:
|
||||||
Opt.none(Slot)
|
Opt.none(Slot)
|
||||||
var res: seq[Attestation]
|
var res: seq[Attestation]
|
||||||
for item in node.attestationPool[].attestations(vslot, vindex):
|
for item in node.attestationPool[].attestations(vslot, vindex):
|
||||||
res.add(item)
|
res.add(item)
|
||||||
return RestApiResponse.jsonResponse(res)
|
RestApiResponse.jsonResponse(res)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolAttestations
|
# 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:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let attestations =
|
let attestations =
|
||||||
block:
|
block:
|
||||||
|
@ -1207,7 +1212,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
if dres.isErr():
|
if dres.isErr():
|
||||||
return RestApiResponse.jsonError(Http400,
|
return RestApiResponse.jsonError(Http400,
|
||||||
InvalidAttestationObjectError,
|
InvalidAttestationObjectError,
|
||||||
$dres.error())
|
$dres.error)
|
||||||
dres.get()
|
dres.get()
|
||||||
|
|
||||||
# Since our validation logic supports batch processing, we will submit all
|
# 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)
|
await allFutures(pending)
|
||||||
for index, future in pending:
|
for index, future in pending:
|
||||||
if future.completed():
|
if future.completed():
|
||||||
let fres = future.read()
|
let fres = future.value()
|
||||||
if fres.isErr():
|
if fres.isErr():
|
||||||
let failure = RestIndexedErrorMessageItem(index: index,
|
let failure = RestIndexedErrorMessageItem(index: index,
|
||||||
message: $fres.error())
|
message: $fres.error)
|
||||||
res.add(failure)
|
res.add(failure)
|
||||||
elif future.failed() or future.cancelled():
|
elif future.failed() or future.cancelled():
|
||||||
# This is unexpected failure, so we log the error message.
|
# This is unexpected failure, so we log the error message.
|
||||||
let exc = future.readError()
|
let exc = future.error()
|
||||||
let failure = RestIndexedErrorMessageItem(index: index,
|
let failure = RestIndexedErrorMessageItem(index: index,
|
||||||
message: $exc.msg)
|
message: $exc.msg)
|
||||||
res.add(failure)
|
res.add(failure)
|
||||||
res
|
res
|
||||||
|
|
||||||
if len(failures) > 0:
|
if len(failures) > 0:
|
||||||
return RestApiResponse.jsonErrorList(Http400, AttestationValidationError,
|
RestApiResponse.jsonErrorList(Http400, AttestationValidationError,
|
||||||
failures)
|
failures)
|
||||||
else:
|
else:
|
||||||
return RestApiResponse.jsonMsgResponse(AttestationValidationSuccess)
|
RestApiResponse.jsonMsgResponse(AttestationValidationSuccess)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getPoolAttesterSlashings
|
# 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:
|
) -> RestApiResponse:
|
||||||
return RestApiResponse.jsonResponse(
|
RestApiResponse.jsonResponse(
|
||||||
toSeq(node.validatorChangePool.attester_slashings))
|
toSeq(node.validatorChangePool.attester_slashings))
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolAttesterSlashings
|
# https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolAttesterSlashings
|
||||||
|
@ -1260,19 +1265,19 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
if dres.isErr():
|
if dres.isErr():
|
||||||
return RestApiResponse.jsonError(Http400,
|
return RestApiResponse.jsonError(Http400,
|
||||||
InvalidAttesterSlashingObjectError,
|
InvalidAttesterSlashingObjectError,
|
||||||
$dres.error())
|
$dres.error)
|
||||||
dres.get()
|
dres.get()
|
||||||
let res = await node.router.routeAttesterSlashing(slashing)
|
let res = await node.router.routeAttesterSlashing(slashing)
|
||||||
if res.isErr():
|
if res.isErr():
|
||||||
return RestApiResponse.jsonError(Http400,
|
return RestApiResponse.jsonError(Http400,
|
||||||
AttesterSlashingValidationError,
|
AttesterSlashingValidationError,
|
||||||
$res.error())
|
$res.error)
|
||||||
return RestApiResponse.jsonMsgResponse(AttesterSlashingValidationSuccess)
|
RestApiResponse.jsonMsgResponse(AttesterSlashingValidationSuccess)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getPoolProposerSlashings
|
# 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:
|
) -> RestApiResponse:
|
||||||
return RestApiResponse.jsonResponse(
|
RestApiResponse.jsonResponse(
|
||||||
toSeq(node.validatorChangePool.proposer_slashings))
|
toSeq(node.validatorChangePool.proposer_slashings))
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolProposerSlashings
|
# https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolProposerSlashings
|
||||||
|
@ -1286,55 +1291,58 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
if dres.isErr():
|
if dres.isErr():
|
||||||
return RestApiResponse.jsonError(Http400,
|
return RestApiResponse.jsonError(Http400,
|
||||||
InvalidProposerSlashingObjectError,
|
InvalidProposerSlashingObjectError,
|
||||||
$dres.error())
|
$dres.error)
|
||||||
dres.get()
|
dres.get()
|
||||||
let res = await node.router.routeProposerSlashing(slashing)
|
let res = await node.router.routeProposerSlashing(slashing)
|
||||||
if res.isErr():
|
if res.isErr():
|
||||||
return RestApiResponse.jsonError(Http400,
|
return RestApiResponse.jsonError(Http400,
|
||||||
ProposerSlashingValidationError,
|
ProposerSlashingValidationError,
|
||||||
$res.error())
|
$res.error)
|
||||||
return RestApiResponse.jsonMsgResponse(ProposerSlashingValidationSuccess)
|
RestApiResponse.jsonMsgResponse(ProposerSlashingValidationSuccess)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getPoolBLSToExecutionChanges
|
# 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
|
# 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:
|
) -> RestApiResponse:
|
||||||
return RestApiResponse.jsonResponse(
|
RestApiResponse.jsonResponse(
|
||||||
toSeq(node.validatorChangePool.bls_to_execution_changes_gossip) &
|
toSeq(node.validatorChangePool.bls_to_execution_changes_gossip) &
|
||||||
toSeq(node.validatorChangePool.bls_to_execution_changes_api))
|
toSeq(node.validatorChangePool.bls_to_execution_changes_api))
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/submitPoolBLSToExecutionChange
|
# 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
|
# 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:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
if node.currentSlot().epoch() < node.dag.cfg.CAPELLA_FORK_EPOCH:
|
if node.currentSlot().epoch() < node.dag.cfg.CAPELLA_FORK_EPOCH:
|
||||||
return RestApiResponse.jsonError(Http400,
|
return RestApiResponse.jsonError(Http400,
|
||||||
InvalidBlsToExecutionChangeObjectError,
|
InvalidBlsToExecutionChangeObjectError,
|
||||||
"Attempt to add to BLS to execution change pool pre-Capella")
|
"Attempt to add to BLS to execution change pool pre-Capella")
|
||||||
let bls_to_execution_changes =
|
let
|
||||||
block:
|
bls_to_execution_changes =
|
||||||
if contentBody.isNone():
|
block:
|
||||||
return RestApiResponse.jsonError(Http400, EmptyRequestBodyError)
|
if contentBody.isNone():
|
||||||
let dres = decodeBody(seq[SignedBLSToExecutionChange], contentBody.get())
|
return RestApiResponse.jsonError(Http400, EmptyRequestBodyError)
|
||||||
if dres.isErr():
|
let dres =
|
||||||
return RestApiResponse.jsonError(Http400,
|
decodeBody(seq[SignedBLSToExecutionChange], contentBody.get())
|
||||||
InvalidBlsToExecutionChangeObjectError,
|
if dres.isErr():
|
||||||
$dres.error())
|
return RestApiResponse.jsonError(
|
||||||
dres.get()
|
Http400, InvalidBlsToExecutionChangeObjectError, $dres.error)
|
||||||
let res = await allFinished(mapIt(
|
dres.get()
|
||||||
bls_to_execution_changes, node.router.routeBlsToExecutionChange(it)))
|
pending = mapIt(bls_to_execution_changes,
|
||||||
for individual_res in res:
|
node.router.routeBlsToExecutionChange(it))
|
||||||
doAssert individual_res.finished()
|
|
||||||
if individual_res.failed():
|
await allFutures(pending)
|
||||||
|
|
||||||
|
for future in pending:
|
||||||
|
if future.failed() or future.cancelled():
|
||||||
return RestApiResponse.jsonError(Http400,
|
return RestApiResponse.jsonError(Http400,
|
||||||
BlsToExecutionChangeValidationError,
|
BlsToExecutionChangeValidationError,
|
||||||
$individual_res.error[].msg)
|
$future.error().msg)
|
||||||
let fut_result = individual_res.read()
|
let res = future.value()
|
||||||
if fut_result.isErr():
|
if res.isErr():
|
||||||
return RestApiResponse.jsonError(Http400,
|
return RestApiResponse.jsonError(Http400,
|
||||||
BlsToExecutionChangeValidationError,
|
BlsToExecutionChangeValidationError,
|
||||||
$fut_result.error())
|
$res.error)
|
||||||
return RestApiResponse.jsonMsgResponse(BlsToExecutionChangeValidationSuccess)
|
RestApiResponse.jsonMsgResponse(BlsToExecutionChangeValidationSuccess)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolSyncCommitteeSignatures
|
# https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolSyncCommitteeSignatures
|
||||||
router.api(MethodPost, "/eth/v1/beacon/pool/sync_committees") do (
|
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:
|
for index, item in results:
|
||||||
if item.isErr():
|
if item.isErr():
|
||||||
res.add(RestIndexedErrorMessageItem(index: index,
|
res.add(RestIndexedErrorMessageItem(index: index,
|
||||||
message: $item.error()))
|
message: $item.error))
|
||||||
res
|
res
|
||||||
if len(failures) > 0:
|
if len(failures) > 0:
|
||||||
return RestApiResponse.jsonErrorList(Http400,
|
RestApiResponse.jsonErrorList(
|
||||||
SyncCommitteeMessageValidationError,
|
Http400, SyncCommitteeMessageValidationError, failures)
|
||||||
failures)
|
|
||||||
else:
|
else:
|
||||||
return RestApiResponse.jsonMsgResponse(
|
RestApiResponse.jsonMsgResponse(
|
||||||
SyncCommitteeMessageValidationSuccess)
|
SyncCommitteeMessageValidationSuccess)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Beacon/getPoolVoluntaryExits
|
# 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:
|
) -> RestApiResponse:
|
||||||
return RestApiResponse.jsonResponse(
|
return RestApiResponse.jsonResponse(
|
||||||
toSeq(node.validatorChangePool.voluntary_exits))
|
toSeq(node.validatorChangePool.voluntary_exits))
|
||||||
|
@ -1384,18 +1391,17 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
if dres.isErr():
|
if dres.isErr():
|
||||||
return RestApiResponse.jsonError(Http400,
|
return RestApiResponse.jsonError(Http400,
|
||||||
InvalidVoluntaryExitObjectError,
|
InvalidVoluntaryExitObjectError,
|
||||||
$dres.error())
|
$dres.error)
|
||||||
dres.get()
|
dres.get()
|
||||||
let res = await node.router.routeSignedVoluntaryExit(exit)
|
let res = await node.router.routeSignedVoluntaryExit(exit)
|
||||||
if res.isErr():
|
if res.isErr():
|
||||||
return RestApiResponse.jsonError(Http400,
|
return RestApiResponse.jsonError(
|
||||||
VoluntaryExitValidationError,
|
Http400, VoluntaryExitValidationError, $res.error)
|
||||||
$res.error())
|
|
||||||
return RestApiResponse.jsonMsgResponse(VoluntaryExitValidationSuccess)
|
return RestApiResponse.jsonMsgResponse(VoluntaryExitValidationSuccess)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=v2.4.2#/Beacon/getBlobSidecars
|
# 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
|
# 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:
|
block_id: BlockIdent, indices: seq[uint64]) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
blockIdent = block_id.valueOr:
|
blockIdent = block_id.valueOr:
|
||||||
|
@ -1429,12 +1435,11 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
if node.dag.db.getBlobSidecar(bid.root, blobIndex, blobSidecar[]):
|
if node.dag.db.getBlobSidecar(bid.root, blobIndex, blobSidecar[]):
|
||||||
discard data[].add blobSidecar[]
|
discard data[].add blobSidecar[]
|
||||||
|
|
||||||
return
|
if contentType == sszMediaType:
|
||||||
if contentType == sszMediaType:
|
RestApiResponse.sszResponse(
|
||||||
RestApiResponse.sszResponse(
|
data[], headers = [("eth-consensus-version",
|
||||||
data[], headers = [("eth-consensus-version",
|
node.dag.cfg.consensusForkAtEpoch(bid.slot.epoch).toString())])
|
||||||
node.dag.cfg.consensusForkAtEpoch(bid.slot.epoch).toString())])
|
elif contentType == jsonMediaType:
|
||||||
elif contentType == jsonMediaType:
|
RestApiResponse.jsonResponse(data)
|
||||||
RestApiResponse.jsonResponse(data)
|
else:
|
||||||
else:
|
RestApiResponse.jsonError(Http500, InvalidAcceptError)
|
||||||
RestApiResponse.jsonError(Http500, InvalidAcceptError)
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# beacon_chain
|
# beacon_chain
|
||||||
# Copyright (c) 2023 Status Research & Development GmbH
|
# Copyright (c) 2023-2024 Status Research & Development GmbH
|
||||||
# Licensed and distributed under either of
|
# Licensed and distributed under either of
|
||||||
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
# * 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).
|
# * 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) =
|
proc installBuilderApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=v2.4.0#/Builder/getNextWithdrawals
|
# 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
|
# 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:
|
state_id: StateIdent) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
sid = state_id.valueOr:
|
sid = state_id.valueOr:
|
||||||
|
@ -41,4 +42,4 @@ proc installBuilderApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
return RestApiResponse.jsonError(
|
return RestApiResponse.jsonError(
|
||||||
Http400, "The specified state is not a capella state")
|
Http400, "The specified state is not a capella state")
|
||||||
|
|
||||||
return RestApiResponse.jsonError(Http404, StateNotFoundError)
|
RestApiResponse.jsonError(Http404, StateNotFoundError)
|
||||||
|
|
|
@ -326,19 +326,16 @@ proc installConfigApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
)
|
)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Config/getForkSchedule
|
# https://ethereum.github.io/beacon-APIs/#/Config/getForkSchedule
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/config/fork_schedule") do () -> RestApiResponse:
|
"/eth/v1/config/fork_schedule") do () -> RestApiResponse:
|
||||||
return RestApiResponse.response(cachedForkSchedule, Http200,
|
RestApiResponse.response(cachedForkSchedule, Http200, "application/json")
|
||||||
"application/json")
|
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Config/getSpec
|
# https://ethereum.github.io/beacon-APIs/#/Config/getSpec
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/config/spec") do () -> RestApiResponse:
|
"/eth/v1/config/spec") do () -> RestApiResponse:
|
||||||
return RestApiResponse.response(cachedConfigSpec, Http200,
|
RestApiResponse.response(cachedConfigSpec, Http200, "application/json")
|
||||||
"application/json")
|
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Config/getDepositContract
|
# https://ethereum.github.io/beacon-APIs/#/Config/getDepositContract
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/config/deposit_contract") do () -> RestApiResponse:
|
"/eth/v1/config/deposit_contract") do () -> RestApiResponse:
|
||||||
return RestApiResponse.response(cachedDepositContract, Http200,
|
RestApiResponse.response(cachedDepositContract, Http200, "application/json")
|
||||||
"application/json")
|
|
||||||
|
|
|
@ -19,15 +19,15 @@ logScope: topics = "rest_debug"
|
||||||
|
|
||||||
proc installDebugApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
proc installDebugApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Debug/getState
|
# https://ethereum.github.io/beacon-APIs/#/Debug/getState
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/debug/beacon/states/{state_id}") do (
|
"/eth/v1/debug/beacon/states/{state_id}") do (
|
||||||
state_id: StateIdent) -> RestApiResponse:
|
state_id: StateIdent) -> RestApiResponse:
|
||||||
return RestApiResponse.jsonError(
|
RestApiResponse.jsonError(
|
||||||
Http410, DeprecatedRemovalBeaconBlocksDebugStateV1)
|
Http410, DeprecatedRemovalBeaconBlocksDebugStateV1)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Debug/getStateV2
|
# https://ethereum.github.io/beacon-APIs/#/Debug/getStateV2
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v2/debug/beacon/states/{state_id}") do (
|
"/eth/v2/debug/beacon/states/{state_id}") do (
|
||||||
state_id: StateIdent) -> RestApiResponse:
|
state_id: StateIdent) -> RestApiResponse:
|
||||||
let bslot =
|
let bslot =
|
||||||
block:
|
block:
|
||||||
|
@ -46,43 +46,40 @@ proc installDebugApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
if res.isErr():
|
if res.isErr():
|
||||||
return RestApiResponse.jsonError(Http406, ContentNotAcceptableError)
|
return RestApiResponse.jsonError(Http406, ContentNotAcceptableError)
|
||||||
res.get()
|
res.get()
|
||||||
|
|
||||||
node.withStateForBlockSlotId(bslot):
|
node.withStateForBlockSlotId(bslot):
|
||||||
return
|
return
|
||||||
if contentType == jsonMediaType:
|
if contentType == jsonMediaType:
|
||||||
RestApiResponse.jsonResponseState(
|
RestApiResponse.jsonResponseState(
|
||||||
state,
|
state, node.getStateOptimistic(state))
|
||||||
node.getStateOptimistic(state)
|
|
||||||
)
|
|
||||||
elif contentType == sszMediaType:
|
elif contentType == sszMediaType:
|
||||||
let headers = [("eth-consensus-version", state.kind.toString())]
|
let headers = [("eth-consensus-version", state.kind.toString())]
|
||||||
withState(state):
|
withState(state):
|
||||||
RestApiResponse.sszResponse(forkyState.data, headers)
|
RestApiResponse.sszResponse(forkyState.data, headers)
|
||||||
else:
|
else:
|
||||||
RestApiResponse.jsonError(Http500, InvalidAcceptError)
|
RestApiResponse.jsonError(Http500, InvalidAcceptError)
|
||||||
return RestApiResponse.jsonError(Http404, StateNotFoundError)
|
|
||||||
|
RestApiResponse.jsonError(Http404, StateNotFoundError)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Debug/getDebugChainHeads
|
# https://ethereum.github.io/beacon-APIs/#/Debug/getDebugChainHeads
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/debug/beacon/heads") do () -> RestApiResponse:
|
"/eth/v1/debug/beacon/heads") do () -> RestApiResponse:
|
||||||
return RestApiResponse.jsonError(
|
RestApiResponse.jsonError(
|
||||||
Http410, DeprecatedRemovalGetDebugChainHeadsV1)
|
Http410, DeprecatedRemovalGetDebugChainHeadsV1)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Debug/getDebugChainHeadsV2
|
# https://ethereum.github.io/beacon-APIs/#/Debug/getDebugChainHeadsV2
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v2/debug/beacon/heads") do () -> RestApiResponse:
|
"/eth/v2/debug/beacon/heads") do () -> RestApiResponse:
|
||||||
return RestApiResponse.jsonResponse(
|
RestApiResponse.jsonResponse(
|
||||||
node.dag.heads.mapIt(
|
node.dag.heads.mapIt(
|
||||||
(
|
(root: it.root, slot: it.slot,
|
||||||
root: it.root,
|
execution_optimistic: not it.executionValid)
|
||||||
slot: it.slot,
|
|
||||||
execution_optimistic: not it.executionValid
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Debug/getDebugForkChoice
|
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Debug/getDebugForkChoice
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/debug/fork_choice") do () -> RestApiResponse:
|
"/eth/v1/debug/fork_choice") do () -> RestApiResponse:
|
||||||
template forkChoice: auto = node.attestationPool[].forkChoice
|
template forkChoice: auto = node.attestationPool[].forkChoice
|
||||||
|
|
||||||
var response = GetForkChoiceResponse(
|
var response = GetForkChoiceResponse(
|
||||||
|
@ -135,4 +132,4 @@ proc installDebugApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
best_child: item.bestChild,
|
best_child: item.bestChild,
|
||||||
bestDescendant: item.bestDescendant))
|
bestDescendant: item.bestDescendant))
|
||||||
|
|
||||||
return RestApiResponse.jsonResponsePlain(response)
|
RestApiResponse.jsonResponsePlain(response)
|
||||||
|
|
|
@ -85,7 +85,7 @@ proc eventHandler*[T](response: HttpResponseRef,
|
||||||
|
|
||||||
proc installEventApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
proc installEventApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Events/eventstream
|
# 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:
|
topics: seq[EventTopic]) -> RestApiResponse:
|
||||||
let eventTopics =
|
let eventTopics =
|
||||||
block:
|
block:
|
||||||
|
@ -174,7 +174,10 @@ proc installEventApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
res.add(handler)
|
res.add(handler)
|
||||||
res
|
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
|
# One of the handlers finished, it means that connection has been droped, so
|
||||||
# we cancelling all other handlers.
|
# we cancelling all other handlers.
|
||||||
let pending =
|
let pending =
|
||||||
|
|
|
@ -142,17 +142,17 @@ proc handleAddRemoteValidatorReq(host: KeymanagerHost,
|
||||||
|
|
||||||
proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
# https://ethereum.github.io/keymanager-APIs/#/Keymanager/ListKeys
|
# 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)
|
let authStatus = checkAuthorization(request, host)
|
||||||
if authStatus.isErr():
|
if authStatus.isErr():
|
||||||
return authErrorResponse authStatus.error
|
return authErrorResponse authStatus.error
|
||||||
let response = GetKeystoresResponse(
|
let response = GetKeystoresResponse(
|
||||||
data: listLocalValidators(host.validatorPool[]))
|
data: listLocalValidators(host.validatorPool[]))
|
||||||
return RestApiResponse.jsonResponsePlain(response)
|
RestApiResponse.jsonResponsePlain(response)
|
||||||
|
|
||||||
# https://ethereum.github.io/keymanager-APIs/#/Keymanager/ImportKeystores
|
# https://ethereum.github.io/keymanager-APIs/#/Keymanager/ImportKeystores
|
||||||
router.api(MethodPost, "/eth/v1/keystores") do (
|
router.api2(MethodPost, "/eth/v1/keystores") do (
|
||||||
contentBody: Option[ContentBody]) -> RestApiResponse:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let authStatus = checkAuthorization(request, host)
|
let authStatus = checkAuthorization(request, host)
|
||||||
if authStatus.isErr():
|
if authStatus.isErr():
|
||||||
return authErrorResponse authStatus.error
|
return authErrorResponse authStatus.error
|
||||||
|
@ -167,14 +167,30 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
|
|
||||||
if request.slashing_protection.isSome():
|
if request.slashing_protection.isSome():
|
||||||
let slashing_protection = request.slashing_protection.get()
|
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 !=
|
if nodeSPDIR.metadata.genesis_validators_root.Eth2Digest !=
|
||||||
slashing_protection.metadata.genesis_validators_root.Eth2Digest:
|
slashing_protection.metadata.genesis_validators_root.Eth2Digest:
|
||||||
return keymanagerApiError(Http400,
|
return keymanagerApiError(Http400,
|
||||||
"The slashing protection database and imported file refer to " &
|
"The slashing protection database and imported file refer to " &
|
||||||
"different blockchains.")
|
"different blockchains.")
|
||||||
let res = inclSPDIR(host.validatorPool[].slashingProtection,
|
let res =
|
||||||
slashing_protection)
|
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:
|
if res == siFailure:
|
||||||
return keymanagerApiError(Http500,
|
return keymanagerApiError(Http500,
|
||||||
"Internal server error; Failed to import slashing protection data")
|
"Internal server error; Failed to import slashing protection data")
|
||||||
|
@ -202,10 +218,10 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
response.data.add(
|
response.data.add(
|
||||||
RequestItemStatus(status: $KeystoreStatus.imported))
|
RequestItemStatus(status: $KeystoreStatus.imported))
|
||||||
|
|
||||||
return RestApiResponse.jsonResponsePlain(response)
|
RestApiResponse.jsonResponsePlain(response)
|
||||||
|
|
||||||
# https://ethereum.github.io/keymanager-APIs/#/Keymanager/DeleteKeys
|
# 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:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let authStatus = checkAuthorization(request, host)
|
let authStatus = checkAuthorization(request, host)
|
||||||
if authStatus.isErr():
|
if authStatus.isErr():
|
||||||
|
@ -221,7 +237,12 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
|
|
||||||
var
|
var
|
||||||
response: DeleteKeystoresResponse
|
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
|
# Hash table to keep the removal status of all keys form request
|
||||||
keysAndDeleteStatus = initTable[PubKeyBytes, RequestItemStatus]()
|
keysAndDeleteStatus = initTable[PubKeyBytes, RequestItemStatus]()
|
||||||
responseSPDIR: SPDIR
|
responseSPDIR: SPDIR
|
||||||
|
@ -263,23 +284,24 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
foundKeystore.status = $KeystoreStatus.notActive
|
foundKeystore.status = $KeystoreStatus.notActive
|
||||||
|
|
||||||
for index, key in keys:
|
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)
|
response.slashing_protection = RestJson.encode(responseSPDIR)
|
||||||
|
|
||||||
return RestApiResponse.jsonResponsePlain(response)
|
RestApiResponse.jsonResponsePlain(response)
|
||||||
|
|
||||||
# https://ethereum.github.io/keymanager-APIs/#/Remote%20Key%20Manager/ListRemoteKeys
|
# 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)
|
let authStatus = checkAuthorization(request, host)
|
||||||
if authStatus.isErr():
|
if authStatus.isErr():
|
||||||
return authErrorResponse authStatus.error
|
return authErrorResponse authStatus.error
|
||||||
let response = GetRemoteKeystoresResponse(
|
let response = GetRemoteKeystoresResponse(
|
||||||
data: listRemoteValidators(host.validatorPool[]))
|
data: listRemoteValidators(host.validatorPool[]))
|
||||||
return RestApiResponse.jsonResponsePlain(response)
|
RestApiResponse.jsonResponsePlain(response)
|
||||||
|
|
||||||
# https://ethereum.github.io/keymanager-APIs/#/Remote%20Key%20Manager/ImportRemoteKeys
|
# 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:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let authStatus = checkAuthorization(request, host)
|
let authStatus = checkAuthorization(request, host)
|
||||||
if authStatus.isErr():
|
if authStatus.isErr():
|
||||||
|
@ -307,10 +329,10 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
|
|
||||||
response.data.add handleAddRemoteValidatorReq(host, keystore)
|
response.data.add handleAddRemoteValidatorReq(host, keystore)
|
||||||
|
|
||||||
return RestApiResponse.jsonResponsePlain(response)
|
RestApiResponse.jsonResponsePlain(response)
|
||||||
|
|
||||||
# https://ethereum.github.io/keymanager-APIs/#/Remote%20Key%20Manager/DeleteRemoteKeys
|
# 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:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let authStatus = checkAuthorization(request, host)
|
let authStatus = checkAuthorization(request, host)
|
||||||
if authStatus.isErr():
|
if authStatus.isErr():
|
||||||
|
@ -327,10 +349,10 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
var response: DeleteRemoteKeystoresResponse
|
var response: DeleteRemoteKeystoresResponse
|
||||||
for index, key in keys:
|
for index, key in keys:
|
||||||
response.data.add handleRemoveValidatorReq(host, key)
|
response.data.add handleRemoveValidatorReq(host, key)
|
||||||
return RestApiResponse.jsonResponsePlain(response)
|
RestApiResponse.jsonResponsePlain(response)
|
||||||
|
|
||||||
# https://ethereum.github.io/keymanager-APIs/#/Fee%20Recipient/ListFeeRecipient
|
# 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:
|
pubkey: ValidatorPubKey) -> RestApiResponse:
|
||||||
let authStatus = checkAuthorization(request, host)
|
let authStatus = checkAuthorization(request, host)
|
||||||
if authStatus.isErr():
|
if authStatus.isErr():
|
||||||
|
@ -344,7 +366,7 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
ethaddress = host.getSuggestedFeeRecipient(
|
ethaddress = host.getSuggestedFeeRecipient(
|
||||||
pubkey, perValidatorDefaultFeeRecipient)
|
pubkey, perValidatorDefaultFeeRecipient)
|
||||||
|
|
||||||
return if ethaddress.isOk:
|
if ethaddress.isOk:
|
||||||
RestApiResponse.jsonResponse(ListFeeRecipientResponse(
|
RestApiResponse.jsonResponse(ListFeeRecipientResponse(
|
||||||
pubkey: pubkey,
|
pubkey: pubkey,
|
||||||
ethaddress: ethaddress.get))
|
ethaddress: ethaddress.get))
|
||||||
|
@ -356,14 +378,14 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
keymanagerApiError(Http500, "Error reading fee recipient file")
|
keymanagerApiError(Http500, "Error reading fee recipient file")
|
||||||
|
|
||||||
# https://ethereum.github.io/keymanager-APIs/#/Fee%20Recipient/SetFeeRecipient
|
# https://ethereum.github.io/keymanager-APIs/#/Fee%20Recipient/SetFeeRecipient
|
||||||
router.api(MethodPost, "/eth/v1/validator/{pubkey}/feerecipient") do (
|
router.api2(MethodPost, "/eth/v1/validator/{pubkey}/feerecipient") do (
|
||||||
pubkey: ValidatorPubKey,
|
pubkey: ValidatorPubKey,
|
||||||
contentBody: Option[ContentBody]) -> RestApiResponse:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let authStatus = checkAuthorization(request, host)
|
let authStatus = checkAuthorization(request, host)
|
||||||
if authStatus.isErr():
|
if authStatus.isErr():
|
||||||
return authErrorResponse authStatus.error
|
return authErrorResponse authStatus.error
|
||||||
let
|
let
|
||||||
pubkey= pubkey.valueOr:
|
pubkey = pubkey.valueOr:
|
||||||
return keymanagerApiError(Http400, InvalidValidatorPublicKey)
|
return keymanagerApiError(Http400, InvalidValidatorPublicKey)
|
||||||
feeRecipientReq =
|
feeRecipientReq =
|
||||||
block:
|
block:
|
||||||
|
@ -376,14 +398,14 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
|
|
||||||
status = host.setFeeRecipient(pubkey, feeRecipientReq.ethaddress)
|
status = host.setFeeRecipient(pubkey, feeRecipientReq.ethaddress)
|
||||||
|
|
||||||
return if status.isOk:
|
if status.isOk:
|
||||||
RestApiResponse.response("", Http202, "text/plain")
|
RestApiResponse.response("", Http202, "text/plain")
|
||||||
else:
|
else:
|
||||||
keymanagerApiError(
|
keymanagerApiError(
|
||||||
Http500, "Failed to set fee recipient: " & status.error)
|
Http500, "Failed to set fee recipient: " & status.error)
|
||||||
|
|
||||||
# https://ethereum.github.io/keymanager-APIs/#/Fee%20Recipient/DeleteFeeRecipient
|
# 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:
|
pubkey: ValidatorPubKey) -> RestApiResponse:
|
||||||
let authStatus = checkAuthorization(request, host)
|
let authStatus = checkAuthorization(request, host)
|
||||||
if authStatus.isErr():
|
if authStatus.isErr():
|
||||||
|
@ -393,15 +415,15 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
return keymanagerApiError(Http400, InvalidValidatorPublicKey)
|
return keymanagerApiError(Http400, InvalidValidatorPublicKey)
|
||||||
res = host.removeFeeRecipientFile(pubkey)
|
res = host.removeFeeRecipientFile(pubkey)
|
||||||
|
|
||||||
return if res.isOk:
|
if res.isOk:
|
||||||
RestApiResponse.response("", Http204, "text/plain")
|
RestApiResponse.response("", Http204, "text/plain")
|
||||||
else:
|
else:
|
||||||
keymanagerApiError(
|
keymanagerApiError(
|
||||||
Http500, "Failed to remove fee recipient file: " & res.error)
|
Http500, "Failed to remove fee recipient file: " & res.error)
|
||||||
|
|
||||||
# https://ethereum.github.io/keymanager-APIs/#/Gas%20Limit/getGasLimit
|
# https://ethereum.github.io/keymanager-APIs/#/Gas%20Limit/getGasLimit
|
||||||
router.api(MethodGet, "/eth/v1/validator/{pubkey}/gas_limit") do (
|
router.api2(MethodGet, "/eth/v1/validator/{pubkey}/gas_limit") do (
|
||||||
pubkey: ValidatorPubKey) -> RestApiResponse:
|
pubkey: ValidatorPubKey) -> RestApiResponse:
|
||||||
let authStatus = checkAuthorization(request, host)
|
let authStatus = checkAuthorization(request, host)
|
||||||
if authStatus.isErr():
|
if authStatus.isErr():
|
||||||
return authErrorResponse authStatus.error
|
return authErrorResponse authStatus.error
|
||||||
|
@ -411,7 +433,7 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
return keymanagerApiError(Http400, InvalidValidatorPublicKey)
|
return keymanagerApiError(Http400, InvalidValidatorPublicKey)
|
||||||
gasLimit = host.getSuggestedGasLimit(pubkey)
|
gasLimit = host.getSuggestedGasLimit(pubkey)
|
||||||
|
|
||||||
return if gasLimit.isOk:
|
if gasLimit.isOk:
|
||||||
RestApiResponse.jsonResponse(GetValidatorGasLimitResponse(
|
RestApiResponse.jsonResponse(GetValidatorGasLimitResponse(
|
||||||
pubkey: pubkey,
|
pubkey: pubkey,
|
||||||
gas_limit: gasLimit.get))
|
gas_limit: gasLimit.get))
|
||||||
|
@ -423,9 +445,9 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
keymanagerApiError(Http500, "Error reading gas limit file")
|
keymanagerApiError(Http500, "Error reading gas limit file")
|
||||||
|
|
||||||
# https://ethereum.github.io/keymanager-APIs/#/Gas%20Limit/setGasLimit
|
# https://ethereum.github.io/keymanager-APIs/#/Gas%20Limit/setGasLimit
|
||||||
router.api(MethodPost, "/eth/v1/validator/{pubkey}/gas_limit") do (
|
router.api2(MethodPost, "/eth/v1/validator/{pubkey}/gas_limit") do (
|
||||||
pubkey: ValidatorPubKey,
|
pubkey: ValidatorPubKey,
|
||||||
contentBody: Option[ContentBody]) -> RestApiResponse:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let authStatus = checkAuthorization(request, host)
|
let authStatus = checkAuthorization(request, host)
|
||||||
if authStatus.isErr():
|
if authStatus.isErr():
|
||||||
return authErrorResponse authStatus.error
|
return authErrorResponse authStatus.error
|
||||||
|
@ -443,15 +465,15 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
|
|
||||||
status = host.setGasLimit(pubkey, gasLimitReq.gas_limit)
|
status = host.setGasLimit(pubkey, gasLimitReq.gas_limit)
|
||||||
|
|
||||||
return if status.isOk:
|
if status.isOk:
|
||||||
RestApiResponse.response("", Http202, "text/plain")
|
RestApiResponse.response("", Http202, "text/plain")
|
||||||
else:
|
else:
|
||||||
keymanagerApiError(
|
keymanagerApiError(
|
||||||
Http500, "Failed to set gas limit: " & status.error)
|
Http500, "Failed to set gas limit: " & status.error)
|
||||||
|
|
||||||
# https://ethereum.github.io/keymanager-APIs/#/Gas%20Limit/deleteGasLimit
|
# https://ethereum.github.io/keymanager-APIs/#/Gas%20Limit/deleteGasLimit
|
||||||
router.api(MethodDelete, "/eth/v1/validator/{pubkey}/gas_limit") do (
|
router.api2(MethodDelete, "/eth/v1/validator/{pubkey}/gas_limit") do (
|
||||||
pubkey: ValidatorPubKey) -> RestApiResponse:
|
pubkey: ValidatorPubKey) -> RestApiResponse:
|
||||||
let authStatus = checkAuthorization(request, host)
|
let authStatus = checkAuthorization(request, host)
|
||||||
if authStatus.isErr():
|
if authStatus.isErr():
|
||||||
return authErrorResponse authStatus.error
|
return authErrorResponse authStatus.error
|
||||||
|
@ -460,7 +482,7 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
return keymanagerApiError(Http400, InvalidValidatorPublicKey)
|
return keymanagerApiError(Http400, InvalidValidatorPublicKey)
|
||||||
res = host.removeGasLimitFile(pubkey)
|
res = host.removeGasLimitFile(pubkey)
|
||||||
|
|
||||||
return if res.isOk:
|
if res.isOk:
|
||||||
RestApiResponse.response("", Http204, "text/plain")
|
RestApiResponse.response("", Http204, "text/plain")
|
||||||
else:
|
else:
|
||||||
keymanagerApiError(
|
keymanagerApiError(
|
||||||
|
@ -468,17 +490,18 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
|
|
||||||
# TODO: These URLs will be changed once we submit a proposal for
|
# TODO: These URLs will be changed once we submit a proposal for
|
||||||
# /eth/v2/remotekeys that supports distributed keys.
|
# /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)
|
let authStatus = checkAuthorization(request, host)
|
||||||
if authStatus.isErr():
|
if authStatus.isErr():
|
||||||
return authErrorResponse authStatus.error
|
return authErrorResponse authStatus.error
|
||||||
let response = GetDistributedKeystoresResponse(
|
let response = GetDistributedKeystoresResponse(
|
||||||
data: listRemoteDistributedValidators(host.validatorPool[]))
|
data: listRemoteDistributedValidators(host.validatorPool[]))
|
||||||
return RestApiResponse.jsonResponsePlain(response)
|
RestApiResponse.jsonResponsePlain(response)
|
||||||
|
|
||||||
# TODO: These URLs will be changed once we submit a proposal for
|
# TODO: These URLs will be changed once we submit a proposal for
|
||||||
# /eth/v2/remotekeys that supports distributed keys.
|
# /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:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let authStatus = checkAuthorization(request, host)
|
let authStatus = checkAuthorization(request, host)
|
||||||
if authStatus.isErr():
|
if authStatus.isErr():
|
||||||
|
@ -504,9 +527,9 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
)
|
)
|
||||||
response.data.add handleAddRemoteValidatorReq(host, keystore)
|
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:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let authStatus = checkAuthorization(request, host)
|
let authStatus = checkAuthorization(request, host)
|
||||||
if authStatus.isErr():
|
if authStatus.isErr():
|
||||||
|
@ -524,10 +547,10 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
for index, key in keys:
|
for index, key in keys:
|
||||||
response.data.add handleRemoveValidatorReq(host, key)
|
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
|
# 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],
|
pubkey: ValidatorPubKey, epoch: Option[Epoch],
|
||||||
contentBody: Option[ContentBody]) -> RestApiResponse:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
|
|
||||||
|
@ -575,4 +598,4 @@ proc installKeymanagerHandlers*(router: var RestRouter, host: KeymanagerHost) =
|
||||||
message: voluntaryExit,
|
message: voluntaryExit,
|
||||||
signature: signature
|
signature: signature
|
||||||
)
|
)
|
||||||
return RestApiResponse.jsonResponse(response)
|
RestApiResponse.jsonResponse(response)
|
||||||
|
|
|
@ -15,8 +15,8 @@ logScope: topics = "rest_light_client"
|
||||||
|
|
||||||
proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getLightClientBootstrap
|
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getLightClientBootstrap
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/beacon/light_client/bootstrap/{block_root}") do (
|
"/eth/v1/beacon/light_client/bootstrap/{block_root}") do (
|
||||||
block_root: Eth2Digest) -> RestApiResponse:
|
block_root: Eth2Digest) -> RestApiResponse:
|
||||||
doAssert node.dag.lcDataStore.serve
|
doAssert node.dag.lcDataStore.serve
|
||||||
let contentType =
|
let contentType =
|
||||||
|
@ -51,8 +51,8 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
return RestApiResponse.jsonError(Http404, LCBootstrapUnavailable)
|
return RestApiResponse.jsonError(Http404, LCBootstrapUnavailable)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getLightClientUpdatesByRange
|
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getLightClientUpdatesByRange
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/beacon/light_client/updates") do (
|
"/eth/v1/beacon/light_client/updates") do (
|
||||||
start_period: Option[SyncCommitteePeriod], count: Option[uint64]
|
start_period: Option[SyncCommitteePeriod], count: Option[uint64]
|
||||||
) -> RestApiResponse:
|
) -> RestApiResponse:
|
||||||
doAssert node.dag.lcDataStore.serve
|
doAssert node.dag.lcDataStore.serve
|
||||||
|
@ -116,8 +116,8 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
RestApiResponse.jsonError(Http500, InvalidAcceptError)
|
RestApiResponse.jsonError(Http500, InvalidAcceptError)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getLightClientFinalityUpdate
|
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getLightClientFinalityUpdate
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/beacon/light_client/finality_update") do (
|
"/eth/v1/beacon/light_client/finality_update") do (
|
||||||
) -> RestApiResponse:
|
) -> RestApiResponse:
|
||||||
doAssert node.dag.lcDataStore.serve
|
doAssert node.dag.lcDataStore.serve
|
||||||
let contentType =
|
let contentType =
|
||||||
|
@ -147,8 +147,8 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
return RestApiResponse.jsonError(Http404, LCFinUpdateUnavailable)
|
return RestApiResponse.jsonError(Http404, LCFinUpdateUnavailable)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getLightClientOptimisticUpdate
|
# https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getLightClientOptimisticUpdate
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/beacon/light_client/optimistic_update") do (
|
"/eth/v1/beacon/light_client/optimistic_update") do (
|
||||||
) -> RestApiResponse:
|
) -> RestApiResponse:
|
||||||
doAssert node.dag.lcDataStore.serve
|
doAssert node.dag.lcDataStore.serve
|
||||||
let contentType =
|
let contentType =
|
||||||
|
|
|
@ -152,16 +152,16 @@ proc toNode(v: PubSubPeer, backoff: Moment): RestPubSubPeer =
|
||||||
)
|
)
|
||||||
|
|
||||||
proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
router.api(MethodGet, "/nimbus/v1/beacon/head") do () -> RestApiResponse:
|
router.api2(MethodGet, "/nimbus/v1/beacon/head") do () -> RestApiResponse:
|
||||||
return RestApiResponse.jsonResponse(node.dag.head.slot)
|
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
|
let
|
||||||
head = node.dag.head
|
head = node.dag.head
|
||||||
finalized = getStateField(node.dag.headState, finalized_checkpoint)
|
finalized = getStateField(node.dag.headState, finalized_checkpoint)
|
||||||
justified =
|
justified =
|
||||||
getStateField(node.dag.headState, current_justified_checkpoint)
|
getStateField(node.dag.headState, current_justified_checkpoint)
|
||||||
return RestApiResponse.jsonResponse(
|
RestApiResponse.jsonResponse(
|
||||||
(
|
(
|
||||||
head_slot: head.slot,
|
head_slot: head.slot,
|
||||||
head_block_root: head.root.data.toHex(),
|
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:
|
) -> 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:
|
) -> 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:
|
) -> 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:
|
) -> RestApiResponse:
|
||||||
var res: seq[PeerId]
|
var res: seq[PeerId]
|
||||||
for peerId, peer in node.network.peerPool:
|
for peerId, peer in node.network.peerPool:
|
||||||
res.add(peerId)
|
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:
|
) -> RestApiResponse:
|
||||||
var res: seq[RestSimplePeer]
|
var res: seq[RestSimplePeer]
|
||||||
for id, peer in node.network.peerPool:
|
for id, peer in node.network.peerPool:
|
||||||
|
@ -202,9 +202,9 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
score: peer.score
|
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:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
if contentBody.isNone:
|
if contentBody.isNone:
|
||||||
return RestApiResponse.jsonError(Http400, EmptyRequestBodyError)
|
return RestApiResponse.jsonError(Http400, EmptyRequestBodyError)
|
||||||
|
@ -225,20 +225,19 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
return RestApiResponse.jsonError(Http400, InvalidGraffitiBytesValue,
|
return RestApiResponse.jsonError(Http400, InvalidGraffitiBytesValue,
|
||||||
$graffitiBytes.error())
|
$graffitiBytes.error())
|
||||||
node.graffitiBytes = graffitiBytes.get()
|
node.graffitiBytes = graffitiBytes.get()
|
||||||
return RestApiResponse.jsonResponse((result: true))
|
RestApiResponse.jsonResponse((result: true))
|
||||||
elif body.contentType == TextPlainMediaType:
|
elif body.contentType == TextPlainMediaType:
|
||||||
return node.setGraffitiAux body.strData()
|
node.setGraffitiAux body.strData()
|
||||||
elif body.contentType == UrlEncodedMediaType:
|
elif body.contentType == UrlEncodedMediaType:
|
||||||
return node.setGraffitiAux decodeUrl(body.strData())
|
node.setGraffitiAux decodeUrl(body.strData())
|
||||||
else:
|
else:
|
||||||
return RestApiResponse.jsonError(Http400, "Unsupported content type: " &
|
RestApiResponse.jsonError(
|
||||||
$body.contentType)
|
Http400, "Unsupported content type: " & $body.contentType)
|
||||||
|
|
||||||
router.api(MethodGet, "/nimbus/v1/graffiti") do (
|
router.api2(MethodGet, "/nimbus/v1/graffiti") do () -> RestApiResponse:
|
||||||
) -> RestApiResponse:
|
RestApiResponse.jsonResponse(node.graffitiBytes)
|
||||||
return 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:
|
log_level: Option[string]) -> RestApiResponse:
|
||||||
if log_level.isSome():
|
if log_level.isSome():
|
||||||
let level =
|
let level =
|
||||||
|
@ -249,15 +248,17 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
$res.error())
|
$res.error())
|
||||||
res.get()
|
res.get()
|
||||||
{.gcsafe.}:
|
{.gcsafe.}:
|
||||||
updateLogLevel(level)
|
try:
|
||||||
return RestApiResponse.jsonResponse((result: true))
|
updateLogLevel(level)
|
||||||
|
except ValueError:
|
||||||
|
return RestApiResponse.jsonResponse((result: false))
|
||||||
|
RestApiResponse.jsonResponse((result: true))
|
||||||
|
|
||||||
router.api(MethodGet, "/nimbus/v1/eth1/chain") do (
|
router.api2(MethodGet, "/nimbus/v1/eth1/chain") do () -> RestApiResponse:
|
||||||
) -> RestApiResponse:
|
|
||||||
let res = mapIt(node.elManager.eth1ChainBlocks, it)
|
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:
|
) -> RestApiResponse:
|
||||||
let wallSlot = node.beaconClock.now.slotOrZero
|
let wallSlot = node.beaconClock.now.slotOrZero
|
||||||
let head =
|
let head =
|
||||||
|
@ -279,7 +280,7 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
do:
|
do:
|
||||||
return RestApiResponse.jsonError(Http400, PrunedStateError)
|
return RestApiResponse.jsonError(Http400, PrunedStateError)
|
||||||
|
|
||||||
router.api(MethodGet, "/nimbus/v1/debug/chronos/futures") do (
|
router.api2(MethodGet, "/nimbus/v1/debug/chronos/futures") do (
|
||||||
) -> RestApiResponse:
|
) -> RestApiResponse:
|
||||||
when defined(chronosFutureTracking):
|
when defined(chronosFutureTracking):
|
||||||
var res: seq[RestFutureInfo]
|
var res: seq[RestFutureInfo]
|
||||||
|
@ -299,12 +300,12 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
state: $item.state
|
state: $item.state
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return RestApiResponse.jsonResponse(res)
|
RestApiResponse.jsonResponse(res)
|
||||||
else:
|
else:
|
||||||
return RestApiResponse.jsonError(Http503,
|
RestApiResponse.jsonError(Http503,
|
||||||
"Compile with '-d:chronosFutureTracking' to get this request working")
|
"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:
|
) -> RestApiResponse:
|
||||||
|
|
||||||
template getCount(name: string): uint64 =
|
template getCount(name: string): uint64 =
|
||||||
|
@ -329,9 +330,9 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
http_body_readers: getCount(HttpBodyReaderTrackerName),
|
http_body_readers: getCount(HttpBodyReaderTrackerName),
|
||||||
http_body_writers: getCount(HttpBodyWriterTrackerName)
|
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:
|
) -> RestApiResponse:
|
||||||
var res: seq[RestConnectionInfo]
|
var res: seq[RestConnectionInfo]
|
||||||
for connection in node.restServer.server.getConnections():
|
for connection in node.restServer.server.getConnections():
|
||||||
|
@ -378,9 +379,9 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
since_create: sinceCreate
|
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:
|
epoch: Epoch, contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let indexList =
|
let indexList =
|
||||||
block:
|
block:
|
||||||
|
@ -441,11 +442,10 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
active: node.attestationPool[].validatorSeenAtEpoch(qepoch, it)
|
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:
|
) -> RestApiResponse:
|
||||||
|
|
||||||
let gossipPeers =
|
let gossipPeers =
|
||||||
block:
|
block:
|
||||||
var res: seq[tuple[topic: string, peers: seq[RestPubSubPeer]]]
|
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:
|
for peerId, peer in node.network.pubsub.peers:
|
||||||
peers.add(RestPeerStatus(peerId: peerId, connected: peer.connected))
|
peers.add(RestPeerStatus(peerId: peerId, connected: peer.connected))
|
||||||
peers
|
peers
|
||||||
return RestApiResponse.jsonResponse(
|
RestApiResponse.jsonResponse(
|
||||||
(
|
(
|
||||||
gossip_peers: gossipPeers,
|
gossip_peers: gossipPeers,
|
||||||
mesh_peers: meshPeers,
|
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:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
timestamp2 = getTimestamp()
|
timestamp2 = getTimestamp()
|
||||||
|
@ -528,4 +528,4 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
timestamp3: getTimestamp(),
|
timestamp3: getTimestamp(),
|
||||||
delay: uint64(delay.nanoseconds)
|
delay: uint64(delay.nanoseconds)
|
||||||
)
|
)
|
||||||
return RestApiResponse.jsonResponsePlain(response)
|
RestApiResponse.jsonResponsePlain(response)
|
||||||
|
|
|
@ -140,7 +140,7 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
RestApiResponse.prepareJsonResponse((version: "Nimbus/" & fullVersionStr))
|
RestApiResponse.prepareJsonResponse((version: "Nimbus/" & fullVersionStr))
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Node/getNetworkIdentity
|
# 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 =
|
let discoveryAddresses =
|
||||||
block:
|
block:
|
||||||
let res = node.getDiscoveryAddresses()
|
let res = node.getDiscoveryAddresses()
|
||||||
|
@ -157,7 +157,7 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
else:
|
else:
|
||||||
newSeq[string]()
|
newSeq[string]()
|
||||||
|
|
||||||
return RestApiResponse.jsonResponse(
|
RestApiResponse.jsonResponse(
|
||||||
(
|
(
|
||||||
peer_id: $node.network.peerId(),
|
peer_id: $node.network.peerId(),
|
||||||
enr: node.network.enrRecord().toURI(),
|
enr: node.network.enrRecord().toURI(),
|
||||||
|
@ -172,7 +172,7 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
)
|
)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Node/getPeers
|
# 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],
|
state: seq[PeerStateKind],
|
||||||
direction: seq[PeerDirectKind]) -> RestApiResponse:
|
direction: seq[PeerDirectKind]) -> RestApiResponse:
|
||||||
let connectionMask =
|
let connectionMask =
|
||||||
|
@ -208,11 +208,10 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
proto: node.network.switch.peerStore[ProtoVersionBook][peer.peerId]
|
proto: node.network.switch.peerStore[ProtoVersionBook][peer.peerId]
|
||||||
)
|
)
|
||||||
res.add(peer)
|
res.add(peer)
|
||||||
return RestApiResponse.jsonResponseWMeta(res,
|
RestApiResponse.jsonResponseWMeta(res, (count: RestNumeric(len(res))))
|
||||||
(count: RestNumeric(len(res))))
|
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Node/getPeerCount
|
# 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
|
var res: RestNodePeerCount
|
||||||
for item in node.network.peers.values():
|
for item in node.network.peers.values():
|
||||||
case item.connectionState
|
case item.connectionState
|
||||||
|
@ -226,10 +225,10 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
inc(res.disconnected)
|
inc(res.disconnected)
|
||||||
of ConnectionState.None:
|
of ConnectionState.None:
|
||||||
discard
|
discard
|
||||||
return RestApiResponse.jsonResponse(res)
|
RestApiResponse.jsonResponse(res)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Node/getPeer
|
# 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:
|
peer_id: PeerId) -> RestApiResponse:
|
||||||
let peer =
|
let peer =
|
||||||
block:
|
block:
|
||||||
|
@ -240,25 +239,26 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
if isNil(res):
|
if isNil(res):
|
||||||
return RestApiResponse.jsonError(Http404, PeerNotFoundError)
|
return RestApiResponse.jsonError(Http404, PeerNotFoundError)
|
||||||
res
|
res
|
||||||
return RestApiResponse.jsonResponse(
|
RestApiResponse.jsonResponse(
|
||||||
(
|
(
|
||||||
peer_id: $peer.peerId,
|
peer_id: $peer.peerId,
|
||||||
enr: if peer.enr.isSome(): peer.enr.get().toURI() else: "",
|
enr: if peer.enr.isSome(): peer.enr.get().toURI() else: "",
|
||||||
last_seen_p2p_address: getLastSeenAddress(node, peer.peerId),
|
last_seen_p2p_address: getLastSeenAddress(node, peer.peerId),
|
||||||
state: peer.connectionState.toString(),
|
state: peer.connectionState.toString(),
|
||||||
direction: peer.direction.toString(),
|
direction: peer.direction.toString(),
|
||||||
agent: node.network.switch.peerStore[AgentBook][peer.peerId], # Fields `agent` and `proto` are not
|
agent: node.network.switch.peerStore[AgentBook][peer.peerId],
|
||||||
proto: node.network.switch.peerStore[ProtoVersionBook][peer.peerId] # part of specification
|
# 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
|
# https://ethereum.github.io/beacon-APIs/#/Node/getNodeVersion
|
||||||
router.api(MethodGet, "/eth/v1/node/version") do () -> RestApiResponse:
|
router.api2(MethodGet, "/eth/v1/node/version") do () -> RestApiResponse:
|
||||||
return RestApiResponse.response(cachedVersion, Http200,
|
RestApiResponse.response(cachedVersion, Http200, "application/json")
|
||||||
"application/json")
|
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Node/getSyncingStatus
|
# 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
|
let
|
||||||
wallSlot = node.beaconClock.now().slotOrZero()
|
wallSlot = node.beaconClock.now().slotOrZero()
|
||||||
headSlot = node.dag.head.slot
|
headSlot = node.dag.head.slot
|
||||||
|
@ -284,10 +284,10 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
is_syncing: isSyncing, is_optimistic: isOptimistic,
|
is_syncing: isSyncing, is_optimistic: isOptimistic,
|
||||||
el_offline: elOffline
|
el_offline: elOffline
|
||||||
)
|
)
|
||||||
return RestApiResponse.jsonResponse(info)
|
RestApiResponse.jsonResponse(info)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Node/getHealth
|
# 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
|
# TODO: Add ability to detect node's issues and return 503 error according
|
||||||
# to specification.
|
# to specification.
|
||||||
let status =
|
let status =
|
||||||
|
@ -295,4 +295,4 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
Http206
|
Http206
|
||||||
else:
|
else:
|
||||||
Http200
|
Http200
|
||||||
return RestApiResponse.response("", status, contentType = "")
|
RestApiResponse.response("", status, contentType = "")
|
||||||
|
|
|
@ -24,7 +24,7 @@ logScope: topics = "rest_validatorapi"
|
||||||
|
|
||||||
proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Validator/getAttesterDuties
|
# 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:
|
epoch: Epoch, contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let indexList =
|
let indexList =
|
||||||
block:
|
block:
|
||||||
|
@ -107,11 +107,11 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
shufflingRef.attester_dependent_slot,
|
shufflingRef.attester_dependent_slot,
|
||||||
shufflingRef.attester_dependent_root)
|
shufflingRef.attester_dependent_root)
|
||||||
|
|
||||||
return RestApiResponse.jsonResponseWRoot(
|
RestApiResponse.jsonResponseWRoot(
|
||||||
duties, shufflingRef.attester_dependent_root, optimistic)
|
duties, shufflingRef.attester_dependent_root, optimistic)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Validator/getProposerDuties
|
# 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:
|
epoch: Epoch) -> RestApiResponse:
|
||||||
let qepoch =
|
let qepoch =
|
||||||
block:
|
block:
|
||||||
|
@ -159,11 +159,11 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
epochRef.proposer_dependent_slot,
|
epochRef.proposer_dependent_slot,
|
||||||
epochRef.proposer_dependent_root)
|
epochRef.proposer_dependent_root)
|
||||||
|
|
||||||
return RestApiResponse.jsonResponseWRoot(
|
RestApiResponse.jsonResponseWRoot(
|
||||||
duties, epochRef.proposer_dependent_root, optimistic)
|
duties, epochRef.proposer_dependent_root, optimistic)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Validator/getSyncCommitteeDuties
|
# 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:
|
epoch: Epoch, contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let indexList =
|
let indexList =
|
||||||
block:
|
block:
|
||||||
|
@ -311,13 +311,13 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
let res = emptyResponse()
|
let res = emptyResponse()
|
||||||
return RestApiResponse.jsonResponseWOpt(res, execOpt = Opt.some(false))
|
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
|
# 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],
|
slot: Slot, randao_reveal: Option[ValidatorSig],
|
||||||
graffiti: Option[GraffitiBytes]) -> RestApiResponse:
|
graffiti: Option[GraffitiBytes]) -> RestApiResponse:
|
||||||
return RestApiResponse.jsonError(
|
RestApiResponse.jsonError(
|
||||||
Http410, DeprecatedRemovalValidatorBlocksV1)
|
Http410, DeprecatedRemovalValidatorBlocksV1)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Validator/produceBlockV2
|
# 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"
|
raiseAssert "preferredContentType() returns invalid content type"
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Validator/produceAttestationData
|
# 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],
|
slot: Option[Slot],
|
||||||
committee_index: Option[CommitteeIndex]) -> RestApiResponse:
|
committee_index: Option[CommitteeIndex]) -> RestApiResponse:
|
||||||
let adata =
|
let adata =
|
||||||
|
@ -751,10 +751,10 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
let epochRef = node.dag.getEpochRef(qhead, qslot.epoch, true).valueOr:
|
let epochRef = node.dag.getEpochRef(qhead, qslot.epoch, true).valueOr:
|
||||||
return RestApiResponse.jsonError(Http400, PrunedStateError, $error)
|
return RestApiResponse.jsonError(Http400, PrunedStateError, $error)
|
||||||
makeAttestationData(epochRef, qhead.atSlot(qslot), qindex)
|
makeAttestationData(epochRef, qhead.atSlot(qslot), qindex)
|
||||||
return RestApiResponse.jsonResponse(adata)
|
RestApiResponse.jsonResponse(adata)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Validator/getAggregatedAttestation
|
# 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],
|
attestation_data_root: Option[Eth2Digest],
|
||||||
slot: Option[Slot]) -> RestApiResponse:
|
slot: Option[Slot]) -> RestApiResponse:
|
||||||
let attestation =
|
let attestation =
|
||||||
|
@ -784,10 +784,10 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
return RestApiResponse.jsonError(Http400,
|
return RestApiResponse.jsonError(Http400,
|
||||||
UnableToGetAggregatedAttestationError)
|
UnableToGetAggregatedAttestationError)
|
||||||
res.get()
|
res.get()
|
||||||
return RestApiResponse.jsonResponse(attestation)
|
RestApiResponse.jsonResponse(attestation)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Validator/publishAggregateAndProofs
|
# 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:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let proofs =
|
let proofs =
|
||||||
block:
|
block:
|
||||||
|
@ -810,7 +810,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
await allFutures(pending)
|
await allFutures(pending)
|
||||||
for future in pending:
|
for future in pending:
|
||||||
if future.completed():
|
if future.completed():
|
||||||
let res = future.read()
|
let res = future.value()
|
||||||
if res.isErr():
|
if res.isErr():
|
||||||
return RestApiResponse.jsonError(Http400,
|
return RestApiResponse.jsonError(Http400,
|
||||||
AggregateAndProofValidationError,
|
AggregateAndProofValidationError,
|
||||||
|
@ -818,11 +818,11 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
else:
|
else:
|
||||||
return RestApiResponse.jsonError(Http500,
|
return RestApiResponse.jsonError(Http500,
|
||||||
"Unexpected server failure, while sending aggregate and proof")
|
"Unexpected server failure, while sending aggregate and proof")
|
||||||
return RestApiResponse.jsonMsgResponse(AggregateAndProofValidationSuccess)
|
RestApiResponse.jsonMsgResponse(AggregateAndProofValidationSuccess)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Validator/prepareBeaconCommitteeSubnet
|
# https://ethereum.github.io/beacon-APIs/#/Validator/prepareBeaconCommitteeSubnet
|
||||||
router.api(MethodPost,
|
router.api2(MethodPost,
|
||||||
"/eth/v1/validator/beacon_committee_subscriptions") do (
|
"/eth/v1/validator/beacon_committee_subscriptions") do (
|
||||||
contentBody: Option[ContentBody]) -> RestApiResponse:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let requests =
|
let requests =
|
||||||
block:
|
block:
|
||||||
|
@ -898,11 +898,11 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
node.validatorMonitor[].addAutoMonitor(
|
node.validatorMonitor[].addAutoMonitor(
|
||||||
validator_pubkey, ValidatorIndex(request.validator_index))
|
validator_pubkey, ValidatorIndex(request.validator_index))
|
||||||
|
|
||||||
return RestApiResponse.jsonMsgResponse(BeaconCommitteeSubscriptionSuccess)
|
RestApiResponse.jsonMsgResponse(BeaconCommitteeSubscriptionSuccess)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Validator/prepareSyncCommitteeSubnets
|
# https://ethereum.github.io/beacon-APIs/#/Validator/prepareSyncCommitteeSubnets
|
||||||
router.api(MethodPost,
|
router.api2(MethodPost,
|
||||||
"/eth/v1/validator/sync_committee_subscriptions") do (
|
"/eth/v1/validator/sync_committee_subscriptions") do (
|
||||||
contentBody: Option[ContentBody]) -> RestApiResponse:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let subscriptions =
|
let subscriptions =
|
||||||
block:
|
block:
|
||||||
|
@ -939,11 +939,11 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
node.validatorMonitor[].addAutoMonitor(
|
node.validatorMonitor[].addAutoMonitor(
|
||||||
validator_pubkey, ValidatorIndex(item.validator_index))
|
validator_pubkey, ValidatorIndex(item.validator_index))
|
||||||
|
|
||||||
return RestApiResponse.jsonMsgResponse(SyncCommitteeSubscriptionSuccess)
|
RestApiResponse.jsonMsgResponse(SyncCommitteeSubscriptionSuccess)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Validator/produceSyncCommitteeContribution
|
# https://ethereum.github.io/beacon-APIs/#/Validator/produceSyncCommitteeContribution
|
||||||
router.api(MethodGet,
|
router.api2(MethodGet,
|
||||||
"/eth/v1/validator/sync_committee_contribution") do (
|
"/eth/v1/validator/sync_committee_contribution") do (
|
||||||
slot: Option[Slot], subcommittee_index: Option[SyncSubCommitteeIndex],
|
slot: Option[Slot], subcommittee_index: Option[SyncSubCommitteeIndex],
|
||||||
beacon_block_root: Option[Eth2Digest]) -> RestApiResponse:
|
beacon_block_root: Option[Eth2Digest]) -> RestApiResponse:
|
||||||
let qslot = block:
|
let qslot = block:
|
||||||
|
@ -1003,11 +1003,11 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
qslot, blck.bid, qindex, contribution)
|
qslot, blck.bid, qindex, contribution)
|
||||||
if not(res):
|
if not(res):
|
||||||
return RestApiResponse.jsonError(Http400, ProduceContributionError)
|
return RestApiResponse.jsonError(Http400, ProduceContributionError)
|
||||||
return RestApiResponse.jsonResponse(contribution)
|
RestApiResponse.jsonResponse(contribution)
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Validator/publishContributionAndProofs
|
# https://ethereum.github.io/beacon-APIs/#/Validator/publishContributionAndProofs
|
||||||
router.api(MethodPost,
|
router.api2(MethodPost,
|
||||||
"/eth/v1/validator/contribution_and_proofs") do (
|
"/eth/v1/validator/contribution_and_proofs") do (
|
||||||
contentBody: Option[ContentBody]) -> RestApiResponse:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let proofs =
|
let proofs =
|
||||||
block:
|
block:
|
||||||
|
@ -1033,31 +1033,28 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
await allFutures(pending)
|
await allFutures(pending)
|
||||||
for index, future in pending:
|
for index, future in pending:
|
||||||
if future.completed():
|
if future.completed():
|
||||||
let fres = future.read()
|
let fres = future.value()
|
||||||
if fres.isErr():
|
if fres.isErr():
|
||||||
let failure = RestIndexedErrorMessageItem(index: index,
|
let failure = RestIndexedErrorMessageItem(index: index,
|
||||||
message: $fres.error())
|
message: $fres.error())
|
||||||
res.add(failure)
|
res.add(failure)
|
||||||
elif future.failed() or future.cancelled():
|
elif future.failed() or future.cancelled():
|
||||||
# This is unexpected failure, so we log the error message.
|
# This is unexpected failure, so we log the error message.
|
||||||
let exc = future.readError()
|
let exc = future.error()
|
||||||
let failure = RestIndexedErrorMessageItem(index: index,
|
let failure = RestIndexedErrorMessageItem(index: index,
|
||||||
message: $exc.msg)
|
message: $exc.msg)
|
||||||
res.add(failure)
|
res.add(failure)
|
||||||
res
|
res
|
||||||
|
|
||||||
if len(failures) > 0:
|
if len(failures) > 0:
|
||||||
return RestApiResponse.jsonErrorList(Http400,
|
RestApiResponse.jsonErrorList(
|
||||||
ContributionAndProofValidationError,
|
Http400, ContributionAndProofValidationError, failures)
|
||||||
failures)
|
|
||||||
else:
|
else:
|
||||||
return RestApiResponse.jsonMsgResponse(
|
RestApiResponse.jsonMsgResponse(ContributionAndProofValidationSuccess)
|
||||||
ContributionAndProofValidationSuccess
|
|
||||||
)
|
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/ValidatorRequiredApi/prepareBeaconProposer
|
# https://ethereum.github.io/beacon-APIs/#/ValidatorRequiredApi/prepareBeaconProposer
|
||||||
router.api(MethodPost,
|
router.api2(MethodPost,
|
||||||
"/eth/v1/validator/prepare_beacon_proposer") do (
|
"/eth/v1/validator/prepare_beacon_proposer") do (
|
||||||
contentBody: Option[ContentBody]) -> RestApiResponse:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
body =
|
body =
|
||||||
|
@ -1087,12 +1084,12 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
numUpdatedFeeRecipients = numUpdated,
|
numUpdatedFeeRecipients = numUpdated,
|
||||||
numRefreshedFeeRecipients = numRefreshed
|
numRefreshedFeeRecipients = numRefreshed
|
||||||
|
|
||||||
return RestApiResponse.response("", Http200, "text/plain")
|
RestApiResponse.response("", Http200, "text/plain")
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Validator/registerValidator
|
# https://ethereum.github.io/beacon-APIs/#/Validator/registerValidator
|
||||||
# https://github.com/ethereum/beacon-APIs/blob/v2.3.0/apis/validator/register_validator.yaml
|
# https://github.com/ethereum/beacon-APIs/blob/v2.3.0/apis/validator/register_validator.yaml
|
||||||
router.api(MethodPost,
|
router.api2(MethodPost,
|
||||||
"/eth/v1/validator/register_validator") do (
|
"/eth/v1/validator/register_validator") do (
|
||||||
contentBody: Option[ContentBody]) -> RestApiResponse:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
body =
|
body =
|
||||||
|
@ -1114,10 +1111,10 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
node.externalBuilderRegistrations[signedValidatorRegistration.message.pubkey] =
|
node.externalBuilderRegistrations[signedValidatorRegistration.message.pubkey] =
|
||||||
signedValidatorRegistration
|
signedValidatorRegistration
|
||||||
|
|
||||||
return RestApiResponse.response("", Http200, "text/plain")
|
RestApiResponse.response("", Http200, "text/plain")
|
||||||
|
|
||||||
# https://ethereum.github.io/beacon-APIs/#/Validator/getLiveness
|
# 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:
|
epoch: Epoch, contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
let
|
let
|
||||||
qepoch =
|
qepoch =
|
||||||
|
@ -1183,10 +1180,10 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
is_live: node.attestationPool[].validatorSeenAtEpoch(qepoch, it)
|
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
|
# 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:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
# "Consensus clients need not support this endpoint and may return a 501."
|
# "Consensus clients need not support this endpoint and may return a 501."
|
||||||
# https://github.com/ethereum/beacon-APIs/pull/224: "This endpoint need not
|
# 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
|
# 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
|
# middleware can handle and swallow the request. I suggest a CL either
|
||||||
# returns 501 Not Implemented [or] 400 Bad Request."
|
# returns 501 Not Implemented [or] 400 Bad Request."
|
||||||
return RestApiResponse.jsonError(
|
RestApiResponse.jsonError(Http501, AggregationSelectionNotImplemented)
|
||||||
Http501, AggregationSelectionNotImplemented)
|
|
||||||
|
|
||||||
# https://github.com/ethereum/beacon-APIs/blob/f087fbf2764e657578a6c29bdf0261b36ee8db1e/apis/validator/sync_committee_selections.yaml
|
# 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:
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
||||||
# "Consensus clients need not support this endpoint and may return a 501."
|
# "Consensus clients need not support this endpoint and may return a 501."
|
||||||
# https://github.com/ethereum/beacon-APIs/pull/224: "This endpoint need not
|
# 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
|
# 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
|
# middleware can handle and swallow the request. I suggest a CL either
|
||||||
# returns 501 Not Implemented [or] 400 Bad Request."
|
# returns 501 Not Implemented [or] 400 Bad Request."
|
||||||
return RestApiResponse.jsonError(
|
RestApiResponse.jsonError(Http501, AggregationSelectionNotImplemented)
|
||||||
Http501, AggregationSelectionNotImplemented)
|
|
||||||
|
|
Loading…
Reference in New Issue