REST JSON support improvements (#3232)

* support downloading blocks / states via JSON in addition to SSZ -
slow, but needed for infura support - SSZ is still used when server
supports it
* use common forked block/state reader in REST API
* fix stack overflows in REST JSON decoder
* fix invalid serialization of `justification_bits` in
`/eth/v1/debug/beacon/states` and `/eth/v2/debug/beacon/states`
* fix REST client to use `/eth/...` instead of `/api/eth/...`, update
"default" urls to expose REST api via `/eth` as well as this is what the
standard says - `/api` was added early on based on an example "base url"
in the spec that has been removed since
* expose Nimbus REST extensions via `/nimbus` in addition to
`/api/nimbus` to stay consistent with `/eth`
* fix invalid state root when reading states via REST
* fix recursive imports in `spec/ssz_codec`
* remove usages of `serialization.useCustomSerialization` - fickle
This commit is contained in:
Jacek Sieka 2022-01-06 08:38:40 +01:00 committed by GitHub
parent 0a4728a241
commit 0e2b4e39fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 393 additions and 384 deletions

View File

@ -58,10 +58,7 @@ type
HashList[PendingAttestation, Limit(MAX_ATTESTATIONS * SLOTS_PER_EPOCH)] HashList[PendingAttestation, Limit(MAX_ATTESTATIONS * SLOTS_PER_EPOCH)]
# Finality # Finality
justification_bits*: uint8 ##\ justification_bits*: JustificationBits
## Bit set for every recent justified epoch
## Model a Bitvector[4] as a one-byte uint, which should remain consistent
## with ssz/hashing.
previous_justified_checkpoint*: Checkpoint ##\ previous_justified_checkpoint*: Checkpoint ##\
## Previous epoch snapshot ## Previous epoch snapshot
@ -113,10 +110,7 @@ type
HashList[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT] HashList[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT]
# Finality # Finality
justification_bits*: uint8 ##\ justification_bits*: JustificationBits
## Bit set for every recent justified epoch
## Model a Bitvector[4] as a one-byte uint, which should remain consistent
## with ssz/hashing.
previous_justified_checkpoint*: Checkpoint ##\ previous_justified_checkpoint*: Checkpoint ##\
## Previous epoch snapshot ## Previous epoch snapshot
@ -175,10 +169,7 @@ type
HashList[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT] HashList[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT]
# Finality # Finality
justification_bits*: uint8 ##\ justification_bits*: JustificationBits
## Bit set for every recent justified epoch
## Model a Bitvector[4] as a one-byte uint, which should remain consistent
## with ssz/hashing.
previous_justified_checkpoint*: Checkpoint ##\ previous_justified_checkpoint*: Checkpoint ##\
## Previous epoch snapshot ## Previous epoch snapshot

View File

@ -184,8 +184,9 @@ proc init*(T: type BeaconNode,
try: try:
# Checkpoint block might come from an earlier fork than the state with # Checkpoint block might come from an earlier fork than the state with
# the state having empty slots processed past the fork epoch. # the state having empty slots processed past the fork epoch.
checkpointBlock = readSszForkedTrustedSignedBeaconBlock( let tmp = readSszForkedSignedBeaconBlock(
cfg, readAllBytes(checkpointBlockPath).tryGet()) cfg, readAllBytes(checkpointBlockPath).tryGet())
checkpointBlock = tmp.asTrusted()
except SszError as err: except SszError as err:
fatal "Invalid checkpoint block", err = err.formatMsg(checkpointBlockPath) fatal "Invalid checkpoint block", err = err.formatMsg(checkpointBlockPath)
quit 1 quit 1

View File

@ -103,7 +103,7 @@ proc toString*(kind: ValidatorFilterKind): string =
proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) = proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/#/Beacon/getGenesis # https://ethereum.github.io/beacon-APIs/#/Beacon/getGenesis
router.api(MethodGet, "/api/eth/v1/beacon/genesis") do () -> RestApiResponse: router.api(MethodGet, "/eth/v1/beacon/genesis") do () -> RestApiResponse:
return RestApiResponse.jsonResponse( return RestApiResponse.jsonResponse(
( (
genesis_time: getStateField(node.dag.headState.data, genesis_time), genesis_time: getStateField(node.dag.headState.data, genesis_time),
@ -114,7 +114,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, "/api/eth/v1/beacon/states/{state_id}/root") do ( router.api(MethodGet, "/eth/v1/beacon/states/{state_id}/root") do (
state_id: StateIdent) -> RestApiResponse: state_id: StateIdent) -> RestApiResponse:
let bslot = let bslot =
block: block:
@ -137,7 +137,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonError(Http404, StateNotFoundError) return RestApiResponse.jsonError(Http404, StateNotFoundError)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateFork # https://ethereum.github.io/beacon-APIs/#/Beacon/getStateFork
router.api(MethodGet, "/api/eth/v1/beacon/states/{state_id}/fork") do ( router.api(MethodGet, "/eth/v1/beacon/states/{state_id}/fork") do (
state_id: StateIdent) -> RestApiResponse: state_id: StateIdent) -> RestApiResponse:
let bslot = let bslot =
block: block:
@ -170,7 +170,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateFinalityCheckpoints # https://ethereum.github.io/beacon-APIs/#/Beacon/getStateFinalityCheckpoints
router.api(MethodGet, router.api(MethodGet,
"/api/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 bslot = let bslot =
block: block:
@ -201,7 +201,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonError(Http404, StateNotFoundError) return RestApiResponse.jsonError(Http404, StateNotFoundError)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateValidators # https://ethereum.github.io/beacon-APIs/#/Beacon/getStateValidators
router.api(MethodGet, "/api/eth/v1/beacon/states/{state_id}/validators") do ( router.api(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 bslot = let bslot =
@ -331,7 +331,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateValidator # https://ethereum.github.io/beacon-APIs/#/Beacon/getStateValidator
router.api(MethodGet, router.api(MethodGet,
"/api/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 bslot = let bslot =
block: block:
@ -400,7 +400,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/#/Beacon/getStateValidatorBalances # https://ethereum.github.io/beacon-APIs/#/Beacon/getStateValidatorBalances
router.api(MethodGet, router.api(MethodGet,
"/api/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 bslot = let bslot =
block: block:
@ -493,7 +493,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/#/Beacon/getEpochCommittees # https://ethereum.github.io/beacon-APIs/#/Beacon/getEpochCommittees
router.api(MethodGet, router.api(MethodGet,
"/api/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 bslot = let bslot =
@ -583,7 +583,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/#/Beacon/getEpochSyncCommittees # https://ethereum.github.io/beacon-APIs/#/Beacon/getEpochSyncCommittees
router.api(MethodGet, router.api(MethodGet,
"/api/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 bslot = let bslot =
block: block:
@ -664,7 +664,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonError(Http404, StateNotFoundError) return RestApiResponse.jsonError(Http404, StateNotFoundError)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockHeaders # https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockHeaders
router.api(MethodGet, "/api/eth/v1/beacon/headers") do ( router.api(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`.
@ -717,7 +717,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
) )
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockHeader # https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockHeader
router.api(MethodGet, "/api/eth/v1/beacon/headers/{block_id}") do ( router.api(MethodGet, "/eth/v1/beacon/headers/{block_id}") do (
block_id: BlockIdent) -> RestApiResponse: block_id: BlockIdent) -> RestApiResponse:
let bdata = let bdata =
block: block:
@ -749,7 +749,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
) )
# https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlock # https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlock
router.api(MethodPost, "/api/eth/v1/beacon/blocks") do ( router.api(MethodPost, "/eth/v1/beacon/blocks") do (
contentBody: Option[ContentBody]) -> RestApiResponse: contentBody: Option[ContentBody]) -> RestApiResponse:
let forked = let forked =
block: block:
@ -798,7 +798,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonMsgResponse(BlockValidationSuccess) return RestApiResponse.jsonMsgResponse(BlockValidationSuccess)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlock # https://ethereum.github.io/beacon-APIs/#/Beacon/getBlock
router.api(MethodGet, "/api/eth/v1/beacon/blocks/{block_id}") do ( router.api(MethodGet, "/eth/v1/beacon/blocks/{block_id}") do (
block_id: BlockIdent) -> RestApiResponse: block_id: BlockIdent) -> RestApiResponse:
let bdata = let bdata =
block: block:
@ -830,7 +830,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
RestApiResponse.jsonError(Http404, BlockNotFoundError) RestApiResponse.jsonError(Http404, BlockNotFoundError)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockV2 # https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockV2
router.api(MethodGet, "/api/eth/v2/beacon/blocks/{block_id}") do ( router.api(MethodGet, "/eth/v2/beacon/blocks/{block_id}") do (
block_id: BlockIdent) -> RestApiResponse: block_id: BlockIdent) -> RestApiResponse:
let bdata = let bdata =
block: block:
@ -864,7 +864,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
RestApiResponse.jsonError(Http500, InvalidAcceptError) RestApiResponse.jsonError(Http500, InvalidAcceptError)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockRoot # https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockRoot
router.api(MethodGet, "/api/eth/v1/beacon/blocks/{block_id}/root") do ( router.api(MethodGet, "/eth/v1/beacon/blocks/{block_id}/root") do (
block_id: BlockIdent) -> RestApiResponse: block_id: BlockIdent) -> RestApiResponse:
let blck = let blck =
block: block:
@ -879,7 +879,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockAttestations # https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockAttestations
router.api(MethodGet, router.api(MethodGet,
"/api/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 bdata = let bdata =
block: block:
@ -895,7 +895,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
RestApiResponse.jsonResponse(blck.message.body.attestations.asSeq()) RestApiResponse.jsonResponse(blck.message.body.attestations.asSeq())
# https://ethereum.github.io/beacon-APIs/#/Beacon/getPoolAttestations # https://ethereum.github.io/beacon-APIs/#/Beacon/getPoolAttestations
router.api(MethodGet, "/api/eth/v1/beacon/pool/attestations") do ( router.api(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 =
@ -923,7 +923,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonResponse(res) return RestApiResponse.jsonResponse(res)
# https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolAttestations # https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolAttestations
router.api(MethodPost, "/api/eth/v1/beacon/pool/attestations") do ( router.api(MethodPost, "/eth/v1/beacon/pool/attestations") do (
contentBody: Option[ContentBody]) -> RestApiResponse: contentBody: Option[ContentBody]) -> RestApiResponse:
let attestations = let attestations =
block: block:
@ -970,7 +970,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonMsgResponse(AttestationValidationSuccess) return RestApiResponse.jsonMsgResponse(AttestationValidationSuccess)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getPoolAttesterSlashings # https://ethereum.github.io/beacon-APIs/#/Beacon/getPoolAttesterSlashings
router.api(MethodGet, "/api/eth/v1/beacon/pool/attester_slashings") do ( router.api(MethodGet, "/eth/v1/beacon/pool/attester_slashings") do (
) -> RestApiResponse: ) -> RestApiResponse:
var res: seq[AttesterSlashing] var res: seq[AttesterSlashing]
if isNil(node.exitPool): if isNil(node.exitPool):
@ -982,7 +982,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonResponse(res) return RestApiResponse.jsonResponse(res)
# https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolAttesterSlashings # https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolAttesterSlashings
router.api(MethodPost, "/api/eth/v1/beacon/pool/attester_slashings") do ( router.api(MethodPost, "/eth/v1/beacon/pool/attester_slashings") do (
contentBody: Option[ContentBody]) -> RestApiResponse: contentBody: Option[ContentBody]) -> RestApiResponse:
let slashing = let slashing =
block: block:
@ -1002,7 +1002,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonMsgResponse(AttesterSlashingValidationSuccess) return RestApiResponse.jsonMsgResponse(AttesterSlashingValidationSuccess)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getPoolProposerSlashings # https://ethereum.github.io/beacon-APIs/#/Beacon/getPoolProposerSlashings
router.api(MethodGet, "/api/eth/v1/beacon/pool/proposer_slashings") do ( router.api(MethodGet, "/eth/v1/beacon/pool/proposer_slashings") do (
) -> RestApiResponse: ) -> RestApiResponse:
var res: seq[ProposerSlashing] var res: seq[ProposerSlashing]
if isNil(node.exitPool): if isNil(node.exitPool):
@ -1014,7 +1014,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonResponse(res) return RestApiResponse.jsonResponse(res)
# https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolProposerSlashings # https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolProposerSlashings
router.api(MethodPost, "/api/eth/v1/beacon/pool/proposer_slashings") do ( router.api(MethodPost, "/eth/v1/beacon/pool/proposer_slashings") do (
contentBody: Option[ContentBody]) -> RestApiResponse: contentBody: Option[ContentBody]) -> RestApiResponse:
let slashing = let slashing =
block: block:
@ -1034,7 +1034,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonMsgResponse(ProposerSlashingValidationSuccess) return RestApiResponse.jsonMsgResponse(ProposerSlashingValidationSuccess)
# https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolSyncCommitteeSignatures # https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolSyncCommitteeSignatures
router.api(MethodPost, "/api/eth/v1/beacon/pool/sync_committees") do ( router.api(MethodPost, "/eth/v1/beacon/pool/sync_committees") do (
contentBody: Option[ContentBody]) -> RestApiResponse: contentBody: Option[ContentBody]) -> RestApiResponse:
let messages = let messages =
block: block:
@ -1065,7 +1065,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
SyncCommitteeMessageValidationSuccess) SyncCommitteeMessageValidationSuccess)
# https://ethereum.github.io/beacon-APIs/#/Beacon/getPoolVoluntaryExits # https://ethereum.github.io/beacon-APIs/#/Beacon/getPoolVoluntaryExits
router.api(MethodGet, "/api/eth/v1/beacon/pool/voluntary_exits") do ( router.api(MethodGet, "/eth/v1/beacon/pool/voluntary_exits") do (
) -> RestApiResponse: ) -> RestApiResponse:
var res: seq[SignedVoluntaryExit] var res: seq[SignedVoluntaryExit]
if isNil(node.exitPool): if isNil(node.exitPool):
@ -1077,7 +1077,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonResponse(res) return RestApiResponse.jsonResponse(res)
# https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolVoluntaryExit # https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolVoluntaryExit
router.api(MethodPost, "/api/eth/v1/beacon/pool/voluntary_exits") do ( router.api(MethodPost, "/eth/v1/beacon/pool/voluntary_exits") do (
contentBody: Option[ContentBody]) -> RestApiResponse: contentBody: Option[ContentBody]) -> RestApiResponse:
let exit = let exit =
block: block:
@ -1096,128 +1096,130 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
$res.error()) $res.error())
return RestApiResponse.jsonMsgResponse(VoluntaryExitValidationSuccess) return RestApiResponse.jsonMsgResponse(VoluntaryExitValidationSuccess)
# Legacy URLS - Nimbus <= 1.5.5 used to expose the REST API with an additional
# `/api` path component
router.redirect( router.redirect(
MethodGet, MethodGet,
"/api/eth/v1/beacon/genesis",
"/eth/v1/beacon/genesis", "/eth/v1/beacon/genesis",
"/api/eth/v1/beacon/genesis"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/api/eth/v1/beacon/states/{state_id}/root",
"/eth/v1/beacon/states/{state_id}/root", "/eth/v1/beacon/states/{state_id}/root",
"/api/eth/v1/beacon/states/{state_id}/root"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/api/eth/v1/beacon/states/{state_id}/fork",
"/eth/v1/beacon/states/{state_id}/fork", "/eth/v1/beacon/states/{state_id}/fork",
"/api/eth/v1/beacon/states/{state_id}/fork"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/beacon/states/{state_id}/finality_checkpoints", "/api/eth/v1/beacon/states/{state_id}/finality_checkpoints",
"/api/eth/v1/beacon/states/{state_id}/finality_checkpoints" "/eth/v1/beacon/states/{state_id}/finality_checkpoints"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/beacon/states/{state_id}/validators", "/api/eth/v1/beacon/states/{state_id}/validators",
"/api/eth/v1/beacon/states/{state_id}/validators" "/eth/v1/beacon/states/{state_id}/validators"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/beacon/states/{state_id}/validators/{validator_id}", "/api/eth/v1/beacon/states/{state_id}/validators/{validator_id}",
"/api/eth/v1/beacon/states/{state_id}/validators/{validator_id}" "/eth/v1/beacon/states/{state_id}/validators/{validator_id}"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/beacon/states/{state_id}/validator_balances", "/api/eth/v1/beacon/states/{state_id}/validator_balances",
"/api/eth/v1/beacon/states/{state_id}/validator_balances" "/eth/v1/beacon/states/{state_id}/validator_balances"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/beacon/states/{state_id}/committees", "/api/eth/v1/beacon/states/{state_id}/committees",
"/api/eth/v1/beacon/states/{state_id}/committees" "/eth/v1/beacon/states/{state_id}/committees"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/beacon/states/{state_id}/sync_committees", "/api/eth/v1/beacon/states/{state_id}/sync_committees",
"/api/eth/v1/beacon/states/{state_id}/sync_committees" "/eth/v1/beacon/states/{state_id}/sync_committees"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/beacon/headers", "/api/eth/v1/beacon/headers",
"/api/eth/v1/beacon/headers" "/eth/v1/beacon/headers"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/beacon/headers/{block_id}", "/api/eth/v1/beacon/headers/{block_id}",
"/api/eth/v1/beacon/headers/{block_id}" "/eth/v1/beacon/headers/{block_id}"
) )
router.redirect( router.redirect(
MethodPost, MethodPost,
"/eth/v1/beacon/blocks", "/api/eth/v1/beacon/blocks",
"/api/eth/v1/beacon/blocks" "/eth/v1/beacon/blocks"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/beacon/blocks/{block_id}", "/api/eth/v1/beacon/blocks/{block_id}",
"/api/eth/v1/beacon/blocks/{block_id}" "/eth/v1/beacon/blocks/{block_id}"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v2/beacon/blocks/{block_id}", "/api/eth/v2/beacon/blocks/{block_id}",
"/api/eth/v2/beacon/blocks/{block_id}" "/eth/v2/beacon/blocks/{block_id}"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/beacon/blocks/{block_id}/root", "/api/eth/v1/beacon/blocks/{block_id}/root",
"/api/eth/v1/beacon/blocks/{block_id}/root" "/eth/v1/beacon/blocks/{block_id}/root"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/beacon/blocks/{block_id}/attestations", "/api/eth/v1/beacon/blocks/{block_id}/attestations",
"/api/eth/v1/beacon/blocks/{block_id}/attestations" "/eth/v1/beacon/blocks/{block_id}/attestations"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/beacon/pool/attestations", "/api/eth/v1/beacon/pool/attestations",
"/api/eth/v1/beacon/pool/attestations" "/eth/v1/beacon/pool/attestations"
) )
router.redirect( router.redirect(
MethodPost, MethodPost,
"/eth/v1/beacon/pool/attestations", "/api/eth/v1/beacon/pool/attestations",
"/api/eth/v1/beacon/pool/attestations" "/eth/v1/beacon/pool/attestations"
) )
router.redirect( router.redirect(
MethodPost, MethodPost,
"/eth/v1/beacon/pool/attester_slashings", "/api/eth/v1/beacon/pool/attester_slashings",
"/api/eth/v1/beacon/pool/attester_slashings" "/eth/v1/beacon/pool/attester_slashings"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/beacon/pool/attester_slashings", "/api/eth/v1/beacon/pool/attester_slashings",
"/api/eth/v1/beacon/pool/attester_slashings" "/eth/v1/beacon/pool/attester_slashings"
) )
router.redirect( router.redirect(
MethodPost, MethodPost,
"/eth/v1/beacon/pool/proposer_slashings", "/api/eth/v1/beacon/pool/proposer_slashings",
"/api/eth/v1/beacon/pool/proposer_slashings" "/eth/v1/beacon/pool/proposer_slashings"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/beacon/pool/proposer_slashings", "/api/eth/v1/beacon/pool/proposer_slashings",
"/api/eth/v1/beacon/pool/proposer_slashings" "/eth/v1/beacon/pool/proposer_slashings"
) )
router.redirect( router.redirect(
MethodPost, MethodPost,
"/eth/v1/beacon/pool/sync_committees", "/api/eth/v1/beacon/pool/sync_committees",
"/api/eth/v1/beacon/pool/sync_committees" "/eth/v1/beacon/pool/sync_committees"
) )
router.redirect( router.redirect(
MethodPost, MethodPost,
"/eth/v1/beacon/pool/voluntary_exits", "/api/eth/v1/beacon/pool/voluntary_exits",
"/api/eth/v1/beacon/pool/voluntary_exits" "/eth/v1/beacon/pool/voluntary_exits"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/beacon/pool/voluntary_exits", "/api/eth/v1/beacon/pool/voluntary_exits",
"/api/eth/v1/beacon/pool/voluntary_exits" "/eth/v1/beacon/pool/voluntary_exits"
) )

View File

@ -253,34 +253,36 @@ 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.api(MethodGet,
"/api/eth/v1/config/fork_schedule") do () -> RestApiResponse: "/eth/v1/config/fork_schedule") do () -> RestApiResponse:
return RestApiResponse.response(cachedForkSchedule, Http200, return 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.api(MethodGet,
"/api/eth/v1/config/spec") do () -> RestApiResponse: "/eth/v1/config/spec") do () -> RestApiResponse:
return RestApiResponse.response(cachedConfigSpec, Http200, return 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.api(MethodGet,
"/api/eth/v1/config/deposit_contract") do () -> RestApiResponse: "/eth/v1/config/deposit_contract") do () -> RestApiResponse:
return RestApiResponse.response(cachedDepositContract, Http200, return RestApiResponse.response(cachedDepositContract, Http200,
"application/json") "application/json")
# Legacy URLS - Nimbus <= 1.5.5 used to expose the REST API with an additional
# `/api` path component
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/config/fork_schedule", "/api/eth/v1/config/fork_schedule",
"/api/eth/v1/config/fork_schedule" "/eth/v1/config/fork_schedule"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/config/spec", "/api/eth/v1/config/spec",
"/api/eth/v1/config/spec" "/eth/v1/config/spec"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/config/deposit_contract", "/api/eth/v1/config/deposit_contract",
"/api/eth/v1/config/deposit_contract" "/eth/v1/config/deposit_contract"
) )

View File

@ -18,7 +18,7 @@ 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.api(MethodGet,
"/api/eth/v1/debug/beacon/states/{state_id}") do ( "/eth/v1/debug/beacon/states/{state_id}") do (
state_id: StateIdent) -> RestApiResponse: state_id: StateIdent) -> RestApiResponse:
let bslot = let bslot =
block: block:
@ -54,7 +54,7 @@ proc installDebugApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/#/Debug/getStateV2 # https://ethereum.github.io/beacon-APIs/#/Debug/getStateV2
router.api(MethodGet, router.api(MethodGet,
"/api/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:
@ -87,23 +87,25 @@ proc installDebugApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/#/Debug/getDebugChainHeads # https://ethereum.github.io/beacon-APIs/#/Debug/getDebugChainHeads
router.api(MethodGet, router.api(MethodGet,
"/api/eth/v1/debug/beacon/heads") do () -> RestApiResponse: "/eth/v1/debug/beacon/heads") do () -> RestApiResponse:
return RestApiResponse.jsonResponse( return RestApiResponse.jsonResponse(
node.dag.heads.mapIt((root: it.root, slot: it.slot)) node.dag.heads.mapIt((root: it.root, slot: it.slot))
) )
# Legacy URLS - Nimbus <= 1.5.5 used to expose the REST API with an additional
# `/api` path component
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/debug/beacon/states/{state_id}", "/api/eth/v1/debug/beacon/states/{state_id}",
"/api/eth/v1/debug/beacon/states/{state_id}" "/eth/v1/debug/beacon/states/{state_id}"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v2/debug/beacon/states/{state_id}", "/api/eth/v2/debug/beacon/states/{state_id}",
"/api/eth/v2/debug/beacon/states/{state_id}" "/eth/v2/debug/beacon/states/{state_id}"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/debug/beacon/heads", "/api/eth/v1/debug/beacon/heads",
"/api/eth/v1/debug/beacon/heads" "/eth/v1/debug/beacon/heads"
) )

View File

@ -95,7 +95,7 @@ proc eventHandler*(response: HttpResponseRef, node: BeaconNode,
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, "/api/eth/v1/events") do ( router.api(MethodGet, "/eth/v1/events") do (
topics: seq[EventTopic]) -> RestApiResponse: topics: seq[EventTopic]) -> RestApiResponse:
let eventTopics = let eventTopics =
block: block:
@ -175,8 +175,10 @@ proc installEventApiHandlers*(router: var RestRouter, node: BeaconNode) =
await allFutures(pending) await allFutures(pending)
return return
# Legacy URLS - Nimbus <= 1.5.5 used to expose the REST API with an additional
# `/api` path component
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/events", "/api/eth/v1/events",
"/api/eth/v1/events" "/eth/v1/events"
) )

View File

@ -112,10 +112,10 @@ proc toNode(v: PubSubPeer, backoff: Moment): RestPubSubPeer =
) )
proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) = proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
router.api(MethodGet, "/api/nimbus/v1/beacon/head") do () -> RestApiResponse: router.api(MethodGet, "/nimbus/v1/beacon/head") do () -> RestApiResponse:
return RestApiResponse.jsonResponse(node.dag.head.slot) return RestApiResponse.jsonResponse(node.dag.head.slot)
router.api(MethodGet, "/api/nimbus/v1/chain/head") do() -> RestApiResponse: router.api(MethodGet, "/nimbus/v1/chain/head") do() -> RestApiResponse:
let let
head = node.dag.head head = node.dag.head
finalized = getStateField(node.dag.headState.data, finalized_checkpoint) finalized = getStateField(node.dag.headState.data, finalized_checkpoint)
@ -132,26 +132,26 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
) )
) )
router.api(MethodGet, "/api/nimbus/v1/syncmanager/status") do ( router.api(MethodGet, "/nimbus/v1/syncmanager/status") do (
) -> RestApiResponse: ) -> RestApiResponse:
return RestApiResponse.jsonResponse(node.syncManager.inProgress) return RestApiResponse.jsonResponse(node.syncManager.inProgress)
router.api(MethodGet, "/api/nimbus/v1/node/peerid") do ( router.api(MethodGet, "/nimbus/v1/node/peerid") do (
) -> RestApiResponse: ) -> RestApiResponse:
return RestApiResponse.jsonResponse((peerid: $node.network.peerId())) return RestApiResponse.jsonResponse((peerid: $node.network.peerId()))
router.api(MethodGet, "/api/nimbus/v1/node/version") do ( router.api(MethodGet, "/nimbus/v1/node/version") do (
) -> RestApiResponse: ) -> RestApiResponse:
return RestApiResponse.jsonResponse((version: "Nimbus/" & fullVersionStr)) return RestApiResponse.jsonResponse((version: "Nimbus/" & fullVersionStr))
router.api(MethodGet, "/api/nimbus/v1/network/ids") do ( router.api(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)) return RestApiResponse.jsonResponse((peerids: res))
router.api(MethodGet, "/api/nimbus/v1/network/peers") do ( router.api(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:
@ -164,7 +164,7 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
) )
return RestApiResponse.jsonResponse((peers: res)) return RestApiResponse.jsonResponse((peers: res))
router.api(MethodPost, "/api/nimbus/v1/graffiti") do ( router.api(MethodPost, "/nimbus/v1/graffiti") do (
value: Option[GraffitiBytes]) -> RestApiResponse: value: Option[GraffitiBytes]) -> RestApiResponse:
if value.isSome() and value.get().isOk(): if value.isSome() and value.get().isOk():
node.graffitiBytes = value.get().get() node.graffitiBytes = value.get().get()
@ -172,11 +172,11 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
else: else:
return RestApiResponse.jsonError(Http400, InvalidGraffitiBytesValye) return RestApiResponse.jsonError(Http400, InvalidGraffitiBytesValye)
router.api(MethodGet, "/api/nimbus/v1/graffiti") do ( router.api(MethodGet, "/nimbus/v1/graffiti") do (
) -> RestApiResponse: ) -> RestApiResponse:
return RestApiResponse.jsonResponse(node.graffitiBytes) return RestApiResponse.jsonResponse(node.graffitiBytes)
router.api(MethodPost, "/api/nimbus/v1/chronicles/settings") do ( router.api(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 =
@ -190,7 +190,7 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
updateLogLevel(level) updateLogLevel(level)
return RestApiResponse.jsonResponse((result: true)) return RestApiResponse.jsonResponse((result: true))
router.api(MethodGet, "/api/nimbus/v1/eth1/chain") do ( router.api(MethodGet, "/nimbus/v1/eth1/chain") do (
) -> RestApiResponse: ) -> RestApiResponse:
let res = let res =
if not(isNil(node.eth1Monitor)): if not(isNil(node.eth1Monitor)):
@ -199,7 +199,7 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
@[] @[]
return RestApiResponse.jsonResponse(res) return RestApiResponse.jsonResponse(res)
router.api(MethodGet, "/api/nimbus/v1/eth1/proposal_data") do ( router.api(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 =
@ -215,7 +215,7 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
do: do:
return RestApiResponse.jsonError(Http400, PrunedStateError) return RestApiResponse.jsonError(Http400, PrunedStateError)
router.api(MethodGet, "/api/nimbus/v1/debug/chronos/futures") do ( router.api(MethodGet, "/nimbus/v1/debug/chronos/futures") do (
) -> RestApiResponse: ) -> RestApiResponse:
when defined(chronosFutureTracking): when defined(chronosFutureTracking):
var res: seq[RestFutureInfo] var res: seq[RestFutureInfo]
@ -240,7 +240,7 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonError(Http503, return RestApiResponse.jsonError(Http503,
"Compile with '-d:chronosFutureTracking' to get this request working") "Compile with '-d:chronosFutureTracking' to get this request working")
router.api(MethodGet, "/api/nimbus/v1/debug/gossip/peers") do ( router.api(MethodGet, "/nimbus/v1/debug/gossip/peers") do (
) -> RestApiResponse: ) -> RestApiResponse:
let gossipPeers = let gossipPeers =
@ -302,3 +302,62 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
all_peers: allPeers all_peers: allPeers
) )
) )
# Legacy URLS - Nimbus <= 1.5.5 used to expose the REST API with an additional
# `/api` path component
router.redirect(
MethodGet,
"/api/nimbus/v1/beacon/head",
"/nimbus/v1/beacon/head")
router.redirect(
MethodGet,
"/api/nimbus/v1/chain/head",
"/nimbus/v1/chain/head")
router.redirect(
MethodGet,
"/api/nimbus/v1/syncmanager/status",
"/nimbus/v1/syncmanager/status")
router.redirect(
MethodGet,
"/api/nimbus/v1/node/peerid",
"/nimbus/v1/node/peerid")
router.redirect(
MethodGet,
"/api/nimbus/v1/node/version",
"/nimbus/v1/node/version")
router.redirect(
MethodGet,
"/api/nimbus/v1/network/ids",
"/nimbus/v1/network/ids")
router.redirect(
MethodGet,
"/api/nimbus/v1/network/peers",
"/nimbus/v1/network/peers")
router.redirect(
MethodPost,
"/api/nimbus/v1/graffiti",
"/nimbus/v1/graffiti")
router.redirect(
MethodGet,
"/api/nimbus/v1/graffiti",
"/nimbus/v1/graffiti")
router.redirect(
MethodPost,
"/api/nimbus/v1/chronicles/settings",
"/nimbus/v1/chronicles/settings")
router.redirect(
MethodGet,
"/api/nimbus/v1/eth1/chain",
"/nimbus/v1/eth1/chain")
router.redirect(
MethodGet,
"/api/nimbus/v1/eth1/proposal_data",
"/nimbus/v1/eth1/proposal_data")
router.redirect(
MethodGet,
"/api/nimbus/v1/debug/chronos/futures",
"/nimbus/v1/debug/chronos/futures")
router.redirect(
MethodGet,
"/api/nimbus/v1/debug/gossip/peers",
"/nimbus/v1/debug/gossip/peers")

View File

@ -133,7 +133,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, "/api/eth/v1/node/identity") do () -> RestApiResponse: router.api(MethodGet, "/eth/v1/node/identity") do () -> RestApiResponse:
let discoveryAddresses = let discoveryAddresses =
block: block:
let res = node.getDiscoveryAddresses() let res = node.getDiscoveryAddresses()
@ -165,7 +165,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, "/api/eth/v1/node/peers") do ( router.api(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,7 +208,7 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonResponseWMeta(res, (count: uint64(len(res)))) return RestApiResponse.jsonResponseWMeta(res, (count: uint64(len(res))))
# https://ethereum.github.io/beacon-APIs/#/Node/getPeerCount # https://ethereum.github.io/beacon-APIs/#/Node/getPeerCount
router.api(MethodGet, "/api/eth/v1/node/peer_count") do () -> RestApiResponse: router.api(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
@ -225,7 +225,7 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonResponse(res) return RestApiResponse.jsonResponse(res)
# https://ethereum.github.io/beacon-APIs/#/Node/getPeer # https://ethereum.github.io/beacon-APIs/#/Node/getPeer
router.api(MethodGet, "/api/eth/v1/node/peers/{peer_id}") do ( router.api(MethodGet, "/eth/v1/node/peers/{peer_id}") do (
peer_id: PeerID) -> RestApiResponse: peer_id: PeerID) -> RestApiResponse:
let peer = let peer =
block: block:
@ -249,16 +249,16 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
) )
# https://ethereum.github.io/beacon-APIs/#/Node/getNodeVersion # https://ethereum.github.io/beacon-APIs/#/Node/getNodeVersion
router.api(MethodGet, "/api/eth/v1/node/version") do () -> RestApiResponse: router.api(MethodGet, "/eth/v1/node/version") do () -> RestApiResponse:
return RestApiResponse.response(cachedVersion, Http200, return 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, "/api/eth/v1/node/syncing") do () -> RestApiResponse: router.api(MethodGet, "/eth/v1/node/syncing") do () -> RestApiResponse:
return RestApiResponse.jsonResponse(node.syncManager.getInfo()) return RestApiResponse.jsonResponse(node.syncManager.getInfo())
# https://ethereum.github.io/beacon-APIs/#/Node/getHealth # https://ethereum.github.io/beacon-APIs/#/Node/getHealth
router.api(MethodGet, "/api/eth/v1/node/health") do () -> RestApiResponse: router.api(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 res = let res =
@ -268,38 +268,40 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) =
(health: 200) (health: 200)
return RestApiResponse.jsonResponse(res) return RestApiResponse.jsonResponse(res)
# Legacy URLS - Nimbus <= 1.5.5 used to expose the REST API with an additional
# `/api` path component
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/node/identity", "/api/eth/v1/node/identity",
"/api/eth/v1/node/identity" "/eth/v1/node/identity"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/node/peers", "/api/eth/v1/node/peers",
"/api/eth/v1/node/peers" "/eth/v1/node/peers"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/node/peer_count", "/api/eth/v1/node/peer_count",
"/api/eth/v1/node/peer_count" "/eth/v1/node/peer_count"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/node/peers/{peer_id}", "/api/eth/v1/node/peers/{peer_id}",
"/api/eth/v1/node/peers/{peer_id}" "/eth/v1/node/peers/{peer_id}"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/node/version", "/api/eth/v1/node/version",
"/api/eth/v1/node/version" "/eth/v1/node/version"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/node/syncing", "/api/eth/v1/node/syncing",
"/api/eth/v1/node/syncing" "/eth/v1/node/syncing"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/node/health", "/api/eth/v1/node/health",
"/api/eth/v1/node/health" "/eth/v1/node/health"
) )

View File

@ -21,7 +21,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, "/api/eth/v1/validator/duties/attester/{epoch}") do ( router.api(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:
@ -105,7 +105,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonResponseWRoot(duties, droot) return RestApiResponse.jsonResponseWRoot(duties, droot)
# https://ethereum.github.io/beacon-APIs/#/Validator/getProposerDuties # https://ethereum.github.io/beacon-APIs/#/Validator/getProposerDuties
router.api(MethodGet, "/api/eth/v1/validator/duties/proposer/{epoch}") do ( router.api(MethodGet, "/eth/v1/validator/duties/proposer/{epoch}") do (
epoch: Epoch) -> RestApiResponse: epoch: Epoch) -> RestApiResponse:
let qepoch = let qepoch =
block: block:
@ -152,7 +152,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
res res
return RestApiResponse.jsonResponseWRoot(duties, droot) return RestApiResponse.jsonResponseWRoot(duties, droot)
router.api(MethodPost, "/api/eth/v1/validator/duties/sync/{epoch}") do ( router.api(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:
@ -285,7 +285,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonError(Http404, StateNotFoundError) return RestApiResponse.jsonError(Http404, StateNotFoundError)
# https://ethereum.github.io/beacon-APIs/#/Validator/produceBlock # https://ethereum.github.io/beacon-APIs/#/Validator/produceBlock
router.api(MethodGet, "/api/eth/v1/validator/blocks/{slot}") do ( router.api(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:
let message = let message =
@ -343,7 +343,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
"Unable to produce block for altair fork") "Unable to produce block for altair fork")
# https://ethereum.github.io/beacon-APIs/#/Validator/produceBlockV2 # https://ethereum.github.io/beacon-APIs/#/Validator/produceBlockV2
router.api(MethodGet, "/api/eth/v2/validator/blocks/{slot}") do ( router.api(MethodGet, "/eth/v2/validator/blocks/{slot}") do (
slot: Slot, randao_reveal: Option[ValidatorSig], slot: Slot, randao_reveal: Option[ValidatorSig],
graffiti: Option[GraffitiBytes]) -> RestApiResponse: graffiti: Option[GraffitiBytes]) -> RestApiResponse:
let message = let message =
@ -395,7 +395,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonResponsePlain(message) return RestApiResponse.jsonResponsePlain(message)
# https://ethereum.github.io/beacon-APIs/#/Validator/produceAttestationData # https://ethereum.github.io/beacon-APIs/#/Validator/produceAttestationData
router.api(MethodGet, "/api/eth/v1/validator/attestation_data") do ( router.api(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 =
@ -435,7 +435,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonResponse(adata) return RestApiResponse.jsonResponse(adata)
# https://ethereum.github.io/beacon-APIs/#/Validator/getAggregatedAttestation # https://ethereum.github.io/beacon-APIs/#/Validator/getAggregatedAttestation
router.api(MethodGet, "/api/eth/v1/validator/aggregate_attestation") do ( router.api(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 =
@ -467,7 +467,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonResponse(attestation) return RestApiResponse.jsonResponse(attestation)
# https://ethereum.github.io/beacon-APIs/#/Validator/publishAggregateAndProofs # https://ethereum.github.io/beacon-APIs/#/Validator/publishAggregateAndProofs
router.api(MethodPost, "/api/eth/v1/validator/aggregate_and_proofs") do ( router.api(MethodPost, "/eth/v1/validator/aggregate_and_proofs") do (
contentBody: Option[ContentBody]) -> RestApiResponse: contentBody: Option[ContentBody]) -> RestApiResponse:
let proofs = let proofs =
block: block:
@ -502,7 +502,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/#/Validator/prepareBeaconCommitteeSubnet # https://ethereum.github.io/beacon-APIs/#/Validator/prepareBeaconCommitteeSubnet
router.api(MethodPost, router.api(MethodPost,
"/api/eth/v1/validator/beacon_committee_subscriptions") do ( "/eth/v1/validator/beacon_committee_subscriptions") do (
contentBody: Option[ContentBody]) -> RestApiResponse: contentBody: Option[ContentBody]) -> RestApiResponse:
# TODO (cheatfate): This call could not be finished because more complex # TODO (cheatfate): This call could not be finished because more complex
# peer manager implementation needed. # peer manager implementation needed.
@ -575,7 +575,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/#/Validator/prepareSyncCommitteeSubnets # https://ethereum.github.io/beacon-APIs/#/Validator/prepareSyncCommitteeSubnets
router.api(MethodPost, router.api(MethodPost,
"/api/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:
@ -610,7 +610,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/#/Validator/produceSyncCommitteeContribution # https://ethereum.github.io/beacon-APIs/#/Validator/produceSyncCommitteeContribution
router.api(MethodGet, router.api(MethodGet,
"/api/eth/v1/validator/sync_committee_contribution") do ( "/eth/v1/validator/sync_committee_contribution") do (
slot: Option[Slot], subcommittee_index: Option[uint64], slot: Option[Slot], subcommittee_index: Option[uint64],
beacon_block_root: Option[Eth2Digest]) -> RestApiResponse: beacon_block_root: Option[Eth2Digest]) -> RestApiResponse:
# We doing this check to avoid any confusion in future. # We doing this check to avoid any confusion in future.
@ -670,7 +670,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
# https://ethereum.github.io/beacon-APIs/#/Validator/publishContributionAndProofs # https://ethereum.github.io/beacon-APIs/#/Validator/publishContributionAndProofs
router.api(MethodPost, router.api(MethodPost,
"/api/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:
@ -718,63 +718,65 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
ContributionAndProofValidationSuccess ContributionAndProofValidationSuccess
) )
# Legacy URLS - Nimbus <= 1.5.5 used to expose the REST API with an additional
# `/api` path component
router.redirect( router.redirect(
MethodPost, MethodPost,
"/eth/v1/validator/duties/attester/{epoch}", "/api/eth/v1/validator/duties/attester/{epoch}",
"/api/eth/v1/validator/duties/attester/{epoch}" "/eth/v1/validator/duties/attester/{epoch}"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/validator/duties/proposer/{epoch}", "/api/eth/v1/validator/duties/proposer/{epoch}",
"/api/eth/v1/validator/duties/proposer/{epoch}" "/eth/v1/validator/duties/proposer/{epoch}"
) )
router.redirect( router.redirect(
MethodPost, MethodPost,
"/eth/v1/validator/duties/sync/{epoch}", "/api/eth/v1/validator/duties/sync/{epoch}",
"/api/eth/v1/validator/duties/sync/{epoch}" "/eth/v1/validator/duties/sync/{epoch}"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/validator/blocks/{slot}", "/api/eth/v1/validator/blocks/{slot}",
"/api/eth/v1/validator/blocks/{slot}" "/eth/v1/validator/blocks/{slot}"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v2/validator/blocks/{slot}", "/api/eth/v2/validator/blocks/{slot}",
"/api/eth/v2/validator/blocks/{slot}" "/eth/v2/validator/blocks/{slot}"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/validator/attestation_data", "/api/eth/v1/validator/attestation_data",
"/api/eth/v1/validator/attestation_data" "/eth/v1/validator/attestation_data"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/validator/aggregate_attestation", "/api/eth/v1/validator/aggregate_attestation",
"/api/eth/v1/validator/aggregate_attestation" "/eth/v1/validator/aggregate_attestation"
) )
router.redirect( router.redirect(
MethodPost, MethodPost,
"/eth/v1/validator/aggregate_and_proofs", "/api/eth/v1/validator/aggregate_and_proofs",
"/api/eth/v1/validator/aggregate_and_proofs" "/eth/v1/validator/aggregate_and_proofs"
) )
router.redirect( router.redirect(
MethodPost, MethodPost,
"/eth/v1/validator/beacon_committee_subscriptions", "/api/eth/v1/validator/beacon_committee_subscriptions",
"/api/eth/v1/validator/beacon_committee_subscriptions" "/eth/v1/validator/beacon_committee_subscriptions"
) )
router.redirect( router.redirect(
MethodPost, MethodPost,
"/eth/v1/validator/sync_committee_subscriptions", "/api/eth/v1/validator/sync_committee_subscriptions",
"/api/eth/v1/validator/sync_committee_subscriptions" "/eth/v1/validator/sync_committee_subscriptions"
) )
router.redirect( router.redirect(
MethodGet, MethodGet,
"/eth/v1/validator/sync_committee_contribution", "/api/eth/v1/validator/sync_committee_contribution",
"/api/eth/v1/validator/sync_committee_contribution" "/eth/v1/validator/sync_committee_contribution"
) )
router.redirect( router.redirect(
MethodPost, MethodPost,
"/eth/v1/validator/contribution_and_proofs", "/api/eth/v1/validator/contribution_and_proofs",
"/api/eth/v1/validator/contribution_and_proofs" "/eth/v1/validator/contribution_and_proofs"
) )

View File

@ -25,13 +25,12 @@
{.push raises: [Defect].} {.push raises: [Defect].}
import import
std/[macros, typetraits, sets, hashes], std/[typetraits, sets, hashes],
chronicles, chronicles,
stew/[assign2, bitops2], stew/[assign2, bitops2],
json_serialization/types as jsonTypes "."/[base, phase0]
import ./base, ./phase0 export base, sets
export base
from ssz_serialization/merkleization import GeneralizedIndex from ssz_serialization/merkleization import GeneralizedIndex
export merkleization.GeneralizedIndex export merkleization.GeneralizedIndex
@ -232,10 +231,7 @@ type
HashList[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT] HashList[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT]
# Finality # Finality
justification_bits*: uint8 ##\ justification_bits*: JustificationBits
## Bit set for every recent justified epoch
## Model a Bitvector[4] as a one-byte uint, which should remain consistent
## with ssz/hashing.
previous_justified_checkpoint*: Checkpoint ##\ previous_justified_checkpoint*: Checkpoint ##\
## Previous epoch snapshot ## Previous epoch snapshot
@ -491,7 +487,7 @@ type
current_epoch_participation*: current_epoch_participation*:
List[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT] List[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT]
justification_bits*: uint8 justification_bits*: JustificationBits
previous_justified_checkpoint*: Checkpoint previous_justified_checkpoint*: Checkpoint
current_justified_checkpoint*: Checkpoint current_justified_checkpoint*: Checkpoint
finalized_checkpoint*: Checkpoint finalized_checkpoint*: Checkpoint
@ -536,21 +532,6 @@ template validateSyncCommitteeIndexOr*(
template asUInt8*(x: SyncSubcommitteeIndex): uint8 = uint8(x) template asUInt8*(x: SyncSubcommitteeIndex): uint8 = uint8(x)
Json.useCustomSerialization(BeaconState.justification_bits):
read:
let s = reader.readValue(string)
if s.len != 4:
raiseUnexpectedValue(reader, "A string with 4 characters expected")
try:
s.parseHexInt.uint8
except ValueError:
raiseUnexpectedValue(reader, "The `justification_bits` value must be a hex string")
write:
writer.writeValue "0x" & value.toHex
func shortLog*(v: SomeBeaconBlock): auto = func shortLog*(v: SomeBeaconBlock): auto =
( (
slot: shortLog(v.slot), slot: shortLog(v.slot),

View File

@ -163,6 +163,10 @@ type
Gwei* = uint64 Gwei* = uint64
# BitVector[4] in the spec, ie 4 bits which end up encoded as a byte for
# SSZ / hashing purposes
JustificationBits* = distinct uint8
# https://github.com/ethereum/consensus-specs/blob/v1.1.8/specs/phase0/beacon-chain.md#proposerslashing # https://github.com/ethereum/consensus-specs/blob/v1.1.8/specs/phase0/beacon-chain.md#proposerslashing
ProposerSlashing* = object ProposerSlashing* = object
signed_header_1*: SignedBeaconBlockHeader signed_header_1*: SignedBeaconBlockHeader
@ -622,6 +626,21 @@ proc readValue*(reader: var JsonReader, value: var ForkDigest)
except ValueError: except ValueError:
raiseUnexpectedValue(reader, "Hex string of 4 bytes expected") raiseUnexpectedValue(reader, "Hex string of 4 bytes expected")
proc `$`*(x: JustificationBits): string =
"0x" & toHex(uint8(x))
proc readValue*(reader: var JsonReader, value: var JustificationBits)
{.raises: [IOError, SerializationError, Defect].} =
let hex = reader.readValue(string)
try:
value = JustificationBits(hexToByteArray(hex, 1)[0])
except ValueError:
raiseUnexpectedValue(reader, "Hex string of 1 byte expected")
proc writeValue*(writer: var JsonWriter, value: JustificationBits)
{.raises: [IOError, Defect].} =
writer.writeValue $value
# In general, ValidatorIndex is assumed to be convertible to/from an int. This # In general, ValidatorIndex is assumed to be convertible to/from an int. This
# should be valid for a long time, because # should be valid for a long time, because
# https://github.com/ethereum/annotated-spec/blob/master/phase0/beacon-chain.md#configuration # https://github.com/ethereum/annotated-spec/blob/master/phase0/beacon-chain.md#configuration
@ -675,6 +694,9 @@ template `$`*(x: CommitteeIndex): auto =
template `==`*(x, y: SubnetId): bool = template `==`*(x, y: SubnetId): bool =
distinctBase(x) == distinctBase(y) distinctBase(x) == distinctBase(y)
template `==`*(x, y: JustificationBits): bool =
distinctBase(x) == distinctBase(y)
template `$`*(x: SubnetId): string = template `$`*(x: SubnetId): string =
$ distinctBase(x) $ distinctBase(x)

View File

@ -13,14 +13,13 @@
{.push raises: [Defect].} {.push raises: [Defect].}
import import
std/macros, stew/[assign2, byteutils],
stew/assign2,
json_serialization, json_serialization,
json_serialization/types as jsonTypes,
ssz_serialization/types as sszTypes, ssz_serialization/types as sszTypes,
../digest, ../digest,
./phase0, ./altair, "."/[base, phase0, altair]
nimcrypto/utils
export json_serialization, base
type type
# https://github.com/ethereum/consensus-specs/blob/v1.1.8/specs/bellatrix/beacon-chain.md#custom-types # https://github.com/ethereum/consensus-specs/blob/v1.1.8/specs/bellatrix/beacon-chain.md#custom-types
@ -123,10 +122,7 @@ type
HashList[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT] HashList[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT]
# Finality # Finality
justification_bits*: uint8 ##\ justification_bits*: JustificationBits
## Bit set for every recent justified epoch
## Model a Bitvector[4] as a one-byte uint, which should remain consistent
## with ssz/hashing.
previous_justified_checkpoint*: Checkpoint ##\ previous_justified_checkpoint*: Checkpoint ##\
## Previous epoch snapshot ## Previous epoch snapshot
@ -345,11 +341,11 @@ type
func encodeQuantityHex*(x: auto): string = func encodeQuantityHex*(x: auto): string =
"0x" & x.toHex "0x" & x.toHex
proc fromHex*(T: typedesc[BloomLogs], s: string): T = proc fromHex*(T: typedesc[BloomLogs], s: string): T {.raises: [Defect, ValueError].} =
hexToBytes(s, result.data) hexToByteArray(s, result.data)
proc fromHex*(T: typedesc[ExecutionAddress], s: string): T = proc fromHex*(T: typedesc[ExecutionAddress], s: string): T {.raises: [Defect, ValueError].} =
hexToBytes(s, result.data) hexToByteArray(s, result.data)
proc writeValue*(w: var JsonWriter, a: ExecutionAddress) {.raises: [Defect, IOError, SerializationError].} = proc writeValue*(w: var JsonWriter, a: ExecutionAddress) {.raises: [Defect, IOError, SerializationError].} =
w.writeValue $a w.writeValue $a

View File

@ -24,13 +24,12 @@
{.push raises: [Defect].} {.push raises: [Defect].}
import ./base
export base
import import
std/[macros, json, strutils, tables], stew/[assign2],
stew/[assign2, byteutils], chronicles, chronicles,
json_serialization/types as jsonTypes ./base
export base
type type
# https://github.com/ethereum/consensus-specs/blob/v1.1.8/specs/phase0/beacon-chain.md#beaconstate # https://github.com/ethereum/consensus-specs/blob/v1.1.8/specs/phase0/beacon-chain.md#beaconstate
@ -75,10 +74,7 @@ type
HashList[PendingAttestation, Limit(MAX_ATTESTATIONS * SLOTS_PER_EPOCH)] HashList[PendingAttestation, Limit(MAX_ATTESTATIONS * SLOTS_PER_EPOCH)]
# Finality # Finality
justification_bits*: uint8 ##\ justification_bits*: JustificationBits
## Bit set for every recent justified epoch
## Model a Bitvector[4] as a one-byte uint, which should remain consistent
## with ssz/hashing.
previous_justified_checkpoint*: Checkpoint ##\ previous_justified_checkpoint*: Checkpoint ##\
## Previous epoch snapshot ## Previous epoch snapshot
@ -253,21 +249,6 @@ func clear*(info: var EpochInfo) =
info.validators.setLen(0) info.validators.setLen(0)
info.balances = TotalBalances() info.balances = TotalBalances()
Json.useCustomSerialization(BeaconState.justification_bits):
read:
let s = reader.readValue(string)
if s.len != 4:
raiseUnexpectedValue(reader, "A string with 4 characters expected")
try:
s.parseHexInt.uint8
except ValueError:
raiseUnexpectedValue(reader, "The `justification_bits` value must be a hex string")
write:
writer.writeValue "0x" & value.toHex
func shortLog*(v: SomeBeaconBlock): auto = func shortLog*(v: SomeBeaconBlock): auto =
( (
slot: shortLog(v.slot), slot: shortLog(v.slot),

View File

@ -22,7 +22,7 @@
import import
# Standard library # Standard library
std/[tables, typetraits], std/[typetraits],
# Nimble packages # Nimble packages
stew/byteutils, stew/byteutils,
@ -75,6 +75,10 @@ proc fromJson*(n: JsonNode, argName: string, result: var Version) {.raises: [Def
n.kind.expect(JString, argName) n.kind.expect(JString, argName)
hexToByteArray(n.getStr(), array[4, byte](result)) hexToByteArray(n.getStr(), array[4, byte](result))
proc fromJson*(n: JsonNode, argName: string, result: var JustificationBits) {.raises: [Defect, ValueError].} =
n.kind.expect(JString, argName)
result = JustificationBits(hexToByteArray(n.getStr(), 1)[0])
proc `%`*(value: Version): JsonNode = proc `%`*(value: Version): JsonNode =
newJString(toJsonHex(distinctBase(value))) newJString(toJsonHex(distinctBase(value)))
@ -141,3 +145,6 @@ proc `%`*(value: BitSeq): JsonNode =
proc fromJson*(n: JsonNode, argName: string, result: var BitSeq) {.raises: [Defect, ValueError].} = proc fromJson*(n: JsonNode, argName: string, result: var BitSeq) {.raises: [Defect, ValueError].} =
n.kind.expect(JString, argName) n.kind.expect(JString, argName)
result = BitSeq(hexToSeqByte(n.getStr())) result = BitSeq(hexToSeqByte(n.getStr()))
proc `%`*(value: JustificationBits): JsonNode =
newJString(toJsonHex([distinctBase(value)]))

View File

@ -89,11 +89,7 @@ type
SszDecodeTypes* = SszDecodeTypes* =
GetPhase0StateSszResponse | GetPhase0StateSszResponse |
GetAltairStateSszResponse | GetPhase0BlockSszResponse
GetPhase0BlockSszResponse |
GetAltairBlockSszResponse |
GetBlockV2Header |
GetStateV2Header
{.push raises: [Defect].} {.push raises: [Defect].}
@ -346,7 +342,33 @@ proc readValue*(reader: var JsonReader[RestJson], value: var uint64) {.
if res.isOk(): if res.isOk():
value = res.get() value = res.get()
else: else:
reader.raiseUnexpectedValue($res.error()) reader.raiseUnexpectedValue($res.error() & ": " & svalue)
proc writeValue*(w: var JsonWriter[RestJson], value: uint8) {.
raises: [IOError, Defect].} =
writeValue(w, Base10.toString(value))
proc readValue*(reader: var JsonReader[RestJson], value: var uint8) {.
raises: [IOError, SerializationError, Defect].} =
let svalue = reader.readValue(string)
let res = Base10.decode(uint8, svalue)
if res.isOk():
value = res.get()
else:
reader.raiseUnexpectedValue($res.error() & ": " & svalue)
proc writeValue*(w: var JsonWriter[RestJson], value: JustificationBits) {.
raises: [IOError, Defect].} =
w.writeValue hexOriginal([uint8(value)])
proc readValue*(reader: var JsonReader[RestJson], value: var JustificationBits) {.
raises: [IOError, SerializationError, Defect].} =
let hex = reader.readValue(string)
try:
value = JustificationBits(hexToByteArray(hex, 1)[0])
except ValueError:
raiseUnexpectedValue(reader,
"The `justification_bits` value must be a hex string")
## UInt256 ## UInt256
proc writeValue*(w: var JsonWriter[RestJson], value: UInt256) {. proc writeValue*(w: var JsonWriter[RestJson], value: UInt256) {.
@ -362,23 +384,6 @@ proc readValue*(reader: var JsonReader[RestJson], value: var UInt256) {.
raiseUnexpectedValue(reader, raiseUnexpectedValue(reader,
"UInt256 value should be a valid decimal string") "UInt256 value should be a valid decimal string")
## byte
proc writeValue*(w: var JsonWriter[RestJson], value: byte) {.
raises: [IOError, Defect].} =
var data: array[1, byte]
data[0] = value
writeValue(w, hexOriginal(data))
proc readValue*(reader: var JsonReader[RestJson], value: var byte) {.
raises: [IOError, SerializationError, Defect].} =
var data: array[1, byte]
try:
hexToByteArray(reader.readValue(string), data)
value = data[0]
except ValueError:
raiseUnexpectedValue(reader,
"byte value should be a valid hex string")
## DomainType ## DomainType
proc writeValue*(w: var JsonWriter[RestJson], value: DomainType) {. proc writeValue*(w: var JsonWriter[RestJson], value: DomainType) {.
raises: [IOError, Defect].} = raises: [IOError, Defect].} =
@ -898,7 +903,7 @@ proc readValue*(reader: var JsonReader[RestJson],
assign(value.field, tmp[].field) assign(value.field, tmp[].field)
else: else:
value = tmp[] # slow, but rare (hopefully) value = tmp[] # slow, but rare (hopefully)
value.field.root = hash_tree_root(value.field.data) value.field.root = hash_tree_root(value.field.data)
case version.get(): case version.get():
of BeaconStateFork.Phase0: of BeaconStateFork.Phase0:
@ -1328,19 +1333,6 @@ proc decodeBody*[T](t: typedesc[T],
return err("Unexpected deserialization error") return err("Unexpected deserialization error")
ok(data) ok(data)
RestJson.useCustomSerialization(phase0.BeaconState.justification_bits):
read:
let s = reader.readValue(string)
if s.len != 4:
raiseUnexpectedValue(reader, "A string with 4 characters expected")
try:
hexToByteArray(s, 1)[0]
except ValueError:
raiseUnexpectedValue(reader,
"The `justification_bits` value must be a hex string")
write:
writer.writeValue "0x" & toHex([value])
proc encodeBytes*[T: EncodeTypes](value: T, proc encodeBytes*[T: EncodeTypes](value: T,
contentType: string): RestResult[seq[byte]] = contentType: string): RestResult[seq[byte]] =
case contentType case contentType

View File

@ -36,7 +36,7 @@ proc getStateFork*(state_id: StateIdent): RestResponse[GetStateForkResponse] {.
proc getStateFinalityCheckpoints*(state_id: StateIdent proc getStateFinalityCheckpoints*(state_id: StateIdent
): RestResponse[GetStateFinalityCheckpointsResponse] {. ): RestResponse[GetStateFinalityCheckpointsResponse] {.
rest, endpoint: "/api/eth/v1/beacon/states/{state_id}/finality_checkpoints", rest, endpoint: "/eth/v1/beacon/states/{state_id}/finality_checkpoints",
meth: MethodGet.} meth: MethodGet.}
## https://ethereum.github.io/beacon-APIs/#/Beacon/getStateFinalityCheckpoints ## https://ethereum.github.io/beacon-APIs/#/Beacon/getStateFinalityCheckpoints
@ -75,12 +75,12 @@ proc getEpochSyncCommittees*(state_id: StateIdent, epoch: Option[Epoch],
proc getBlockHeaders*(slot: Option[Slot], parent_root: Option[Eth2Digest] proc getBlockHeaders*(slot: Option[Slot], parent_root: Option[Eth2Digest]
): RestResponse[GetBlockHeadersResponse] {. ): RestResponse[GetBlockHeadersResponse] {.
rest, endpoint: "/api/eth/v1/beacon/headers", rest, endpoint: "/eth/v1/beacon/headers",
meth: MethodGet.} meth: MethodGet.}
## https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockHeaders ## https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockHeaders
proc getBlockHeader*(block_id: BlockIdent): RestResponse[GetBlockHeaderResponse] {. proc getBlockHeader*(block_id: BlockIdent): RestResponse[GetBlockHeaderResponse] {.
rest, endpoint: "/api/eth/v1/beacon/headers/{block_id}", rest, endpoint: "/eth/v1/beacon/headers/{block_id}",
meth: MethodGet.} meth: MethodGet.}
## https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockHeader ## https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockHeader
@ -95,7 +95,7 @@ proc publishBlock*(body: altair.SignedBeaconBlock): RestPlainResponse {.
## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlock ## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlock
proc getBlockPlain*(block_id: BlockIdent): RestPlainResponse {. proc getBlockPlain*(block_id: BlockIdent): RestPlainResponse {.
rest, endpoint: "/api/eth/v1/beacon/blocks/{block_id}", rest, endpoint: "/eth/v1/beacon/blocks/{block_id}",
accept: "application/octet-stream,application-json;q=0.9", accept: "application/octet-stream,application-json;q=0.9",
meth: MethodGet.} meth: MethodGet.}
## https://ethereum.github.io/beacon-APIs/#/Beacon/getBlock ## https://ethereum.github.io/beacon-APIs/#/Beacon/getBlock
@ -156,21 +156,24 @@ proc getBlock*(client: RestClientRef, block_id: BlockIdent,
return data return data
proc getBlockV2Plain*(block_id: BlockIdent): RestPlainResponse {. proc getBlockV2Plain*(block_id: BlockIdent): RestPlainResponse {.
rest, endpoint: "/api/eth/v2/beacon/blocks/{block_id}", rest, endpoint: "/eth/v2/beacon/blocks/{block_id}",
accept: "application/octet-stream,application-json;q=0.9", accept: "application/octet-stream,application-json;q=0.9",
meth: MethodGet.} meth: MethodGet.}
## https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockV2 ## https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockV2
proc getBlockV2*(client: RestClientRef, block_id: BlockIdent, proc getBlockV2*(client: RestClientRef, block_id: BlockIdent,
forks: array[2, Fork], cfg: RuntimeConfig,
restAccept = ""): Future[ForkedSignedBeaconBlock] {. restAccept = ""): Future[Option[ForkedSignedBeaconBlock]] {.
async.} = async.} =
# Return the asked-for block, or None in case 404 is returned from the server.
# Raises on other errors
let resp = let resp =
if len(restAccept) > 0: if len(restAccept) > 0:
await client.getBlockV2Plain(block_id, restAcceptType = restAccept) await client.getBlockV2Plain(block_id, restAcceptType = restAccept)
else: else:
await client.getBlockV2Plain(block_id) await client.getBlockV2Plain(block_id)
let data =
return
case resp.status case resp.status
of 200: of 200:
case resp.contentType case resp.contentType
@ -182,35 +185,18 @@ proc getBlockV2*(client: RestClientRef, block_id: BlockIdent,
if res.isErr(): if res.isErr():
raise newException(RestError, $res.error()) raise newException(RestError, $res.error())
res.get() res.get()
blck some blck
of "application/octet-stream": of "application/octet-stream":
let header = try:
block: some readSszForkedSignedBeaconBlock(cfg, resp.data)
let res = decodeBytes(GetBlockV2Header, resp.data, resp.contentType) except CatchableError as exc:
if res.isErr(): raise newException(RestError, exc.msg)
raise newException(RestError, $res.error())
res.get()
if header.slot.epoch() < forks[1].epoch:
let blck =
block:
let res = decodeBytes(GetPhase0BlockSszResponse, resp.data,
resp.contentType)
if res.isErr():
raise newException(RestError, $res.error())
res.get()
ForkedSignedBeaconBlock.init(blck)
else:
let blck =
block:
let res = decodeBytes(GetAltairBlockSszResponse, resp.data,
resp.contentType)
if res.isErr():
raise newException(RestError, $res.error())
res.get()
ForkedSignedBeaconBlock.init(blck)
else: else:
raise newException(RestError, "Unsupported content-type") raise newException(RestError, "Unsupported content-type")
of 400, 404, 500: of 404:
none(ForkedSignedBeaconBlock)
of 400, 500:
let error = let error =
block: block:
let res = decodeBytes(RestGenericError, resp.data, resp.contentType) let res = decodeBytes(RestGenericError, resp.data, resp.contentType)
@ -224,7 +210,6 @@ proc getBlockV2*(client: RestClientRef, block_id: BlockIdent,
else: else:
let msg = "Unknown response status error (" & $resp.status & ")" let msg = "Unknown response status error (" & $resp.status & ")"
raise newException(RestError, msg) raise newException(RestError, msg)
return data
proc getBlockRoot*(block_id: BlockIdent): RestResponse[GetBlockRootResponse] {. proc getBlockRoot*(block_id: BlockIdent): RestResponse[GetBlockRootResponse] {.
rest, endpoint: "/eth/v1/beacon/blocks/{block_id}/root", rest, endpoint: "/eth/v1/beacon/blocks/{block_id}/root",

View File

@ -78,8 +78,10 @@ proc getStateV2Plain*(state_id: StateIdent): RestPlainResponse {.
## https://ethereum.github.io/beacon-APIs/#/Debug/getStateV2 ## https://ethereum.github.io/beacon-APIs/#/Debug/getStateV2
proc getStateV2*(client: RestClientRef, state_id: StateIdent, proc getStateV2*(client: RestClientRef, state_id: StateIdent,
forks: array[2, Fork], cfg: RuntimeConfig,
restAccept = ""): Future[ForkedHashedBeaconState] {.async.} = restAccept = ""): Future[ref ForkedHashedBeaconState] {.async.} =
# nil is returned if the state is not found due to a 404 - `ref` is needed
# to manage stack usage
let resp = let resp =
if len(restAccept) > 0: if len(restAccept) > 0:
await client.getStateV2Plain(state_id, restAcceptType = restAccept) await client.getStateV2Plain(state_id, restAcceptType = restAccept)
@ -92,42 +94,22 @@ proc getStateV2*(client: RestClientRef, state_id: StateIdent,
of "application/json": of "application/json":
let state = let state =
block: block:
let res = decodeBytes(GetStateV2Response, resp.data, let res = newClone(decodeBytes(GetStateV2Response, resp.data,
resp.contentType) resp.contentType))
if res.isErr(): if res[].isErr():
raise newException(RestError, $res.error()) raise newException(RestError, $res[].error())
res.get() newClone(res[].get())
state state
of "application/octet-stream": of "application/octet-stream":
let header = try:
block: newClone(readSszForkedHashedBeaconState(cfg, resp.data))
let res = decodeBytes(GetStateV2Header, resp.data, resp.contentType) except CatchableError as exc:
if res.isErr(): raise newException(RestError, exc.msg)
raise newException(RestError, $res.error())
res.get()
if header.slot.epoch() < forks[1].epoch:
let state = newClone(
block:
let res = newClone(decodeBytes(
GetPhase0StateSszResponse, resp.data, resp.contentType))
if res[].isErr():
raise newException(RestError, $res[].error())
res[].get())
ForkedHashedBeaconState.init(phase0.HashedBeaconState(
data: state[], root: hash_tree_root(state[])))
else:
let state = newClone(
block:
let res = newClone(decodeBytes(
GetAltairStateSszResponse, resp.data, resp.contentType))
if res[].isErr():
raise newException(RestError, $res[].error())
res[].get())
ForkedHashedBeaconState.init(altair.HashedBeaconState(
data: state[], root: hash_tree_root(state[])))
else: else:
raise newException(RestError, "Unsupported content-type") raise newException(RestError, "Unsupported content-type")
of 400, 404, 500: of 404:
nil
of 400, 500:
let error = let error =
block: block:
let res = decodeBytes(RestGenericError, resp.data, resp.contentType) let res = decodeBytes(RestGenericError, resp.data, resp.contentType)

View File

@ -408,11 +408,6 @@ type
signature*: ValidatorSig signature*: ValidatorSig
slot*: Slot slot*: Slot
ForkedBeaconStateHeader* = object
genesis_time*: uint64
genesis_validators_root*: Eth2Digest
slot*: Slot
Web3SignerKeysResponse* = object Web3SignerKeysResponse* = object
keys*: seq[ValidatorPubKey] keys*: seq[ValidatorPubKey]
@ -495,9 +490,7 @@ type
GetBlockResponse* = DataEnclosedObject[phase0.SignedBeaconBlock] GetBlockResponse* = DataEnclosedObject[phase0.SignedBeaconBlock]
GetStateResponse* = DataEnclosedObject[phase0.BeaconState] GetStateResponse* = DataEnclosedObject[phase0.BeaconState]
GetBlockV2Response* = ForkedSignedBeaconBlock GetBlockV2Response* = ForkedSignedBeaconBlock
GetBlockV2Header* = ForkedSignedBlockHeader GetStateV2Response* = ref ForkedHashedBeaconState
GetStateV2Response* = ForkedHashedBeaconState
GetStateV2Header* = ForkedBeaconStateHeader
GetPhase0StateSszResponse* = phase0.BeaconState GetPhase0StateSszResponse* = phase0.BeaconState
GetAltairStateSszResponse* = altair.BeaconState GetAltairStateSszResponse* = altair.BeaconState
GetPhase0BlockSszResponse* = phase0.SignedBeaconBlock GetPhase0BlockSszResponse* = phase0.SignedBeaconBlock

View File

@ -446,9 +446,9 @@ type
signature*: ValidatorSig signature*: ValidatorSig
slot: Slot # start of BeaconBlock slot: Slot # start of BeaconBlock
func readSszForkedTrustedSignedBeaconBlock*( func readSszForkedSignedBeaconBlock*(
cfg: RuntimeConfig, data: openArray[byte]): cfg: RuntimeConfig, data: openArray[byte]):
ForkedTrustedSignedBeaconBlock {.raises: [Defect, SszError].} = ForkedSignedBeaconBlock {.raises: [Defect, SszError].} =
## Helper to read a header from bytes when it's not certain what kind of block ## Helper to read a header from bytes when it's not certain what kind of block
## it is ## it is
if data.len() < sizeof(ForkedBeaconBlockHeader): if data.len() < sizeof(ForkedBeaconBlockHeader):
@ -459,7 +459,7 @@ func readSszForkedTrustedSignedBeaconBlock*(
# careful - `result` is used, RVO didn't seem to work without # careful - `result` is used, RVO didn't seem to work without
# TODO move time helpers somewhere to avoid circular imports # TODO move time helpers somewhere to avoid circular imports
result = ForkedTrustedSignedBeaconBlock( result = ForkedSignedBeaconBlock(
kind: cfg.blockForkAtEpoch(Epoch(header.slot div SLOTS_PER_EPOCH))) kind: cfg.blockForkAtEpoch(Epoch(header.slot div SLOTS_PER_EPOCH)))
withBlck(result): withBlck(result):

View File

@ -11,10 +11,9 @@
import import
std/[typetraits], std/[typetraits],
ssz_serialization/codec, ssz_serialization/codec,
../spec/datatypes/[phase0, altair], ./datatypes/base
./eth2_merkleization
export codec, phase0, altair, typetraits, eth2_merkleization export codec, base, typetraits
# Coding and decoding of SSZ to spec-specific types # Coding and decoding of SSZ to spec-specific types
@ -22,6 +21,7 @@ template toSszType*(v: Slot|Epoch): auto = uint64(v)
template toSszType*(v: BlsCurveType): auto = toRaw(v) template toSszType*(v: BlsCurveType): auto = toRaw(v)
template toSszType*(v: ForkDigest|GraffitiBytes): auto = distinctBase(v) template toSszType*(v: ForkDigest|GraffitiBytes): auto = distinctBase(v)
template toSszType*(v: Version): auto = distinctBase(v) template toSszType*(v: Version): auto = distinctBase(v)
template toSszType*(v: JustificationBits): auto = distinctBase(v)
func fromSszBytes*(T: type GraffitiBytes, data: openArray[byte]): T {.raisesssz.} = func fromSszBytes*(T: type GraffitiBytes, data: openArray[byte]): T {.raisesssz.} =
if data.len != sizeof(result): if data.len != sizeof(result):
@ -43,3 +43,8 @@ func fromSszBytes*(T: type Version, bytes: openArray[byte]): T {.raisesssz.} =
if bytes.len != sizeof(result): if bytes.len != sizeof(result):
raiseIncorrectSize T raiseIncorrectSize T
copyMem(result.addr, unsafeAddr bytes[0], sizeof(result)) copyMem(result.addr, unsafeAddr bytes[0], sizeof(result))
func fromSszBytes*(T: type JustificationBits, bytes: openArray[byte]): T {.raisesssz.} =
if bytes.len != sizeof(result):
raiseIncorrectSize T
copyMem(result.addr, unsafeAddr bytes[0], sizeof(result))

View File

@ -259,8 +259,9 @@ proc process_justification_and_finalization*(state: var phase0.BeaconState,
# https://github.com/ethereum/consensus-specs/blob/v1.1.8/specs/phase0/beacon-chain.md#misc # https://github.com/ethereum/consensus-specs/blob/v1.1.8/specs/phase0/beacon-chain.md#misc
const JUSTIFICATION_BITS_LENGTH = 4 const JUSTIFICATION_BITS_LENGTH = 4
state.justification_bits = (state.justification_bits shl 1) and state.justification_bits = JustificationBits(
cast[uint8]((2^JUSTIFICATION_BITS_LENGTH) - 1) (uint8(state.justification_bits) shl 1) and
uint8((2^JUSTIFICATION_BITS_LENGTH) - 1))
let total_active_balance = balances.current_epoch let total_active_balance = balances.current_epoch
if balances.previous_epoch_target_attesters * 3 >= if balances.previous_epoch_target_attesters * 3 >=
@ -268,7 +269,7 @@ proc process_justification_and_finalization*(state: var phase0.BeaconState,
state.current_justified_checkpoint = state.current_justified_checkpoint =
Checkpoint(epoch: previous_epoch, Checkpoint(epoch: previous_epoch,
root: get_block_root(state, previous_epoch)) root: get_block_root(state, previous_epoch))
state.justification_bits.setBit 1 uint8(state.justification_bits).setBit 1
trace "Justified with previous epoch", trace "Justified with previous epoch",
current_epoch = current_epoch, current_epoch = current_epoch,
@ -282,14 +283,14 @@ proc process_justification_and_finalization*(state: var phase0.BeaconState,
state.current_justified_checkpoint = state.current_justified_checkpoint =
Checkpoint(epoch: current_epoch, Checkpoint(epoch: current_epoch,
root: get_block_root(state, current_epoch)) root: get_block_root(state, current_epoch))
state.justification_bits.setBit 0 uint8(state.justification_bits).setBit 0
trace "Justified with current epoch", trace "Justified with current epoch",
current_epoch = current_epoch, current_epoch = current_epoch,
checkpoint = shortLog(state.current_justified_checkpoint) checkpoint = shortLog(state.current_justified_checkpoint)
# Process finalizations # Process finalizations
let bitfield = state.justification_bits let bitfield = uint8(state.justification_bits)
## The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th ## The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th
## as source ## as source
@ -355,14 +356,15 @@ proc weigh_justification_and_finalization(state: var (altair.BeaconState | merge
# https://github.com/ethereum/consensus-specs/blob/v1.1.8/specs/phase0/beacon-chain.md#misc # https://github.com/ethereum/consensus-specs/blob/v1.1.8/specs/phase0/beacon-chain.md#misc
const JUSTIFICATION_BITS_LENGTH = 4 const JUSTIFICATION_BITS_LENGTH = 4
state.justification_bits = (state.justification_bits shl 1) and state.justification_bits = JustificationBits(
cast[uint8]((2^JUSTIFICATION_BITS_LENGTH) - 1) (uint8(state.justification_bits) shl 1) and
uint8((2^JUSTIFICATION_BITS_LENGTH) - 1))
if previous_epoch_target_balance * 3 >= total_active_balance * 2: if previous_epoch_target_balance * 3 >= total_active_balance * 2:
state.current_justified_checkpoint = state.current_justified_checkpoint =
Checkpoint(epoch: previous_epoch, Checkpoint(epoch: previous_epoch,
root: get_block_root(state, previous_epoch)) root: get_block_root(state, previous_epoch))
state.justification_bits.setBit 1 uint8(state.justification_bits).setBit 1
trace "Justified with previous epoch", trace "Justified with previous epoch",
current_epoch = current_epoch, current_epoch = current_epoch,
@ -378,14 +380,14 @@ proc weigh_justification_and_finalization(state: var (altair.BeaconState | merge
state.current_justified_checkpoint = state.current_justified_checkpoint =
Checkpoint(epoch: current_epoch, Checkpoint(epoch: current_epoch,
root: get_block_root(state, current_epoch)) root: get_block_root(state, current_epoch))
state.justification_bits.setBit 0 uint8(state.justification_bits).setBit 0
trace "Justified with current epoch", trace "Justified with current epoch",
current_epoch = current_epoch, current_epoch = current_epoch,
checkpoint = shortLog(state.current_justified_checkpoint) checkpoint = shortLog(state.current_justified_checkpoint)
# Process finalizations # Process finalizations
let bitfield = state.justification_bits let bitfield = uint8(state.justification_bits)
## The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th ## The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th
## as source ## as source

View File

@ -359,10 +359,10 @@ proc cmdPutBlock(conf: DbConf, cfg: RuntimeConfig) =
defer: db.close() defer: db.close()
for file in conf.blckFile: for file in conf.blckFile:
let blck = readSszForkedTrustedSignedBeaconBlock( let blck = readSszForkedSignedBeaconBlock(
cfg, readAllBytes(file).tryGet()) cfg, readAllBytes(file).tryGet())
withBlck(blck): withBlck(blck.asTrusted()):
db.putBlock(blck) db.putBlock(blck)
if conf.setHead: if conf.setHead:
db.putHeadBlock(blck.root) db.putHeadBlock(blck.root)

View File

@ -44,11 +44,11 @@ proc finalizeOn234(
# Mock the state # Mock the state
getStateField(state, previous_justified_checkpoint) = c4 getStateField(state, previous_justified_checkpoint) = c4
getStateField(state, current_justified_checkpoint) = c3 getStateField(state, current_justified_checkpoint) = c3
getStateField(state, justification_bits) = 0'u8 # Bitvector of length 4 getStateField(state, justification_bits) = JustificationBits(0'u8) # Bitvector of length 4
# mock 3rd and 4th latest epochs as justified # mock 3rd and 4th latest epochs as justified
# indices are pre-shift # indices are pre-shift
getStateField(state, justification_bits).setBit 1 uint8(getStateField(state, justification_bits)).setBit 1
getStateField(state, justification_bits).setBit 2 uint8(getStateField(state, justification_bits)).setBit 2
# mock the 2nd latest epoch as justifiable, with 4th as the source # mock the 2nd latest epoch as justifiable, with 4th as the source
addMockAttestations( addMockAttestations(
state.phase0Data.data, state.phase0Data.data,
@ -90,10 +90,10 @@ proc finalizeOn23(state: var ForkedHashedBeaconState, epoch: Epoch, sufficient_s
# Mock the state # Mock the state
getStateField(state, previous_justified_checkpoint) = c3 getStateField(state, previous_justified_checkpoint) = c3
getStateField(state, current_justified_checkpoint) = c3 getStateField(state, current_justified_checkpoint) = c3
getStateField(state, justification_bits) = 0'u8 # Bitvector of length 4 getStateField(state, justification_bits) = JustificationBits(0'u8) # Bitvector of length 4
# mock 3rd as justified # mock 3rd as justified
# indices are pre-shift # indices are pre-shift
getStateField(state, justification_bits).setBit 1 uint8(getStateField(state, justification_bits)).setBit 1
# mock the 2nd latest epoch as justifiable, with 3rd as the source # mock the 2nd latest epoch as justifiable, with 3rd as the source
addMockAttestations( addMockAttestations(
state.phase0Data.data, state.phase0Data.data,
@ -135,10 +135,10 @@ proc finalizeOn123(state: var ForkedHashedBeaconState, epoch: Epoch, sufficient_
# Mock the state # Mock the state
getStateField(state, previous_justified_checkpoint) = c5 getStateField(state, previous_justified_checkpoint) = c5
getStateField(state, current_justified_checkpoint) = c3 getStateField(state, current_justified_checkpoint) = c3
getStateField(state, justification_bits) = 0'u8 # Bitvector of length 4 getStateField(state, justification_bits) = JustificationBits(0'u8) # Bitvector of length 4
# mock 3rd as justified # mock 3rd as justified
# indices are pre-shift # indices are pre-shift
getStateField(state, justification_bits).setBit 1 uint8(getStateField(state, justification_bits)).setBit 1
# mock the 2nd latest epoch as justifiable, with 5th as the source # mock the 2nd latest epoch as justifiable, with 5th as the source
addMockAttestations( addMockAttestations(
state.phase0Data.data, state.phase0Data.data,
@ -188,10 +188,10 @@ proc finalizeOn12(state: var ForkedHashedBeaconState, epoch: Epoch, sufficient_s
# Mock the state # Mock the state
getStateField(state, previous_justified_checkpoint) = c2 getStateField(state, previous_justified_checkpoint) = c2
getStateField(state, current_justified_checkpoint) = c2 getStateField(state, current_justified_checkpoint) = c2
getStateField(state, justification_bits) = 0'u8 # Bitvector of length 4 getStateField(state, justification_bits) = JustificationBits(0'u8) # Bitvector of length 4
# mock 3rd as justified # mock 3rd as justified
# indices are pre-shift # indices are pre-shift
getStateField(state, justification_bits).setBit 0 uint8(getStateField(state, justification_bits)).setBit 0
# mock the 2nd latest epoch as justifiable, with 3rd as the source # mock the 2nd latest epoch as justifiable, with 3rd as the source
addMockAttestations( addMockAttestations(
state.phase0Data.data, state.phase0Data.data,

View File

@ -27,9 +27,9 @@ template testTrustedSignedBeaconBlock(T: type, s: Slot) =
let let
bytes = SSZ.encode(blck[]) bytes = SSZ.encode(blck[])
forked = (ref ForkedTrustedSignedBeaconBlock)() forked = (ref ForkedSignedBeaconBlock)()
forked[] = readSszForkedTrustedSignedBeaconBlock(cfg, bytes) forked[] = readSszForkedSignedBeaconBlock(cfg, bytes)
check: check:
forked.kind == T.toFork() forked.kind == T.toFork()
@ -97,4 +97,4 @@ suite "Forked SSZ readers":
let let
bytes = SSZ.encode(AttestationData()) bytes = SSZ.encode(AttestationData())
expect(SszError): expect(SszError):
discard newClone(readSszForkedTrustedSignedBeaconBlock(cfg, bytes)) discard newClone(readSszForkedSignedBeaconBlock(cfg, bytes))