diff --git a/beacon_chain/beacon_node_common.nim b/beacon_chain/beacon_node_common.nim index c611dfe53..93cb394a6 100644 --- a/beacon_chain/beacon_node_common.nim +++ b/beacon_chain/beacon_node_common.nim @@ -24,7 +24,7 @@ import ./sync/[sync_manager, request_manager] export - osproc, chronos, httpserver, conf, beacon_clock, beacon_chain_db, + osproc, chronos, httpserver, presto, conf, beacon_clock, beacon_chain_db, attestation_pool, eth2_network, beacon_node_types, eth1_monitor, request_manager, sync_manager, eth2_processor, blockchain_dag, block_quarantine, base diff --git a/beacon_chain/nimbus_beacon_node.nim b/beacon_chain/nimbus_beacon_node.nim index 724999526..3778500fb 100644 --- a/beacon_chain/nimbus_beacon_node.nim +++ b/beacon_chain/nimbus_beacon_node.nim @@ -34,13 +34,10 @@ import attestation_aggregation, validator_duties, validator_pool, slashing_protection, keystore_management], ./sync/[sync_manager, sync_protocol, request_manager], - ./rpc/[rest_utils, config_rest_api, debug_rest_api, node_rest_api, - beacon_rest_api, event_rest_api, validator_rest_api, nimbus_rest_api], - ./rpc/[beacon_api, config_api, debug_api, event_api, nimbus_api, node_api, - validator_api], + ./rpc/[rest_api, rpc_api], ./spec/[ datatypes/phase0, datatypes/altair, digest, crypto, - forkedbeaconstate_helpers, beaconstate, eth2_apis/beacon_rpc_client, + forkedbeaconstate_helpers, beaconstate, eth2_apis/rpc_beacon_client, helpers, network, presets, weak_subjectivity, signatures], ./consensus_object_pools/[ blockchain_dag, block_quarantine, block_clearance, block_pools_types, diff --git a/beacon_chain/nimbus_validator_client.nim b/beacon_chain/nimbus_validator_client.nim index 54432947b..d9b42739a 100644 --- a/beacon_chain/nimbus_validator_client.nim +++ b/beacon_chain/nimbus_validator_client.nim @@ -7,14 +7,14 @@ import validator_client/[common, fallback_service, duties_service, attestation_service, fork_service] -proc initGenesis*(vc: ValidatorClientRef): Future[RestBeaconGenesis] {.async.} = +proc initGenesis*(vc: ValidatorClientRef): Future[RestGenesis] {.async.} = info "Initializing genesis", nodes_count = len(vc.beaconNodes) var nodes = vc.beaconNodes while true: - var pending: seq[Future[RestResponse[DataRestBeaconGenesis]]] + var pending: seq[Future[RestResponse[GetGenesisResponse]]] for node in nodes: debug "Requesting genesis information", endpoint = node - pending.add(node.client.getBeaconGenesis()) + pending.add(node.client.getGenesis()) try: await allFutures(pending) @@ -24,7 +24,7 @@ proc initGenesis*(vc: ValidatorClientRef): Future[RestBeaconGenesis] {.async.} = let (errorNodes, genesisList) = block: - var gres: seq[RestBeaconGenesis] + var gres: seq[RestGenesis] var bres: seq[BeaconNodeServerRef] for i in 0 ..< len(pending): let fut = pending[i] @@ -60,7 +60,7 @@ proc initGenesis*(vc: ValidatorClientRef): Future[RestBeaconGenesis] {.async.} = nodes = errorNodes else: # Boyer-Moore majority vote algorithm - var melem: RestBeaconGenesis + var melem: RestGenesis var counter = 0 for item in genesisList: if counter == 0: diff --git a/beacon_chain/rpc/eth_merge_web3.nim b/beacon_chain/rpc/eth_merge_web3.nim index fffdbd5a2..517ac6da5 100644 --- a/beacon_chain/rpc/eth_merge_web3.nim +++ b/beacon_chain/rpc/eth_merge_web3.nim @@ -2,7 +2,7 @@ import strutils, json_serialization/std/[sets, net], serialization/errors, ../spec/datatypes/base, - ../spec/[crypto, digest, eth2_apis/beacon_rpc_client], + ../spec/[crypto, digest, eth2_apis/rpc_beacon_client], json_rpc/[client, jsonmarshal] from os import DirSep, AltSep diff --git a/beacon_chain/rpc/rest_api.nim b/beacon_chain/rpc/rest_api.nim new file mode 100644 index 000000000..1d55b0e38 --- /dev/null +++ b/beacon_chain/rpc/rest_api.nim @@ -0,0 +1,22 @@ +# Copyright (c) 2018-2021 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +## The `rest_api` module is a server implementation for the common REST API for +## Ethereum 2 found at https://ethereum.github.io/eth2.0-APIs/# +## along with several nimbus-specific extensions. It is used by the validator +## client as well as many community utilities. +## A corresponding client can be found in the +## `spec/eth2_apis/rest_beacon_client` module +import + "."/[ + rest_utils, + rest_beacon_api, rest_config_api, rest_debug_api, rest_event_api, + rest_nimbus_api, rest_node_api, rest_validator_api] + +export + rest_utils, + rest_beacon_api, rest_config_api, rest_debug_api, rest_event_api, + rest_nimbus_api, rest_node_api, rest_validator_api diff --git a/beacon_chain/rpc/beacon_rest_api.nim b/beacon_chain/rpc/rest_beacon_api.nim similarity index 95% rename from beacon_chain/rpc/beacon_rest_api.nim rename to beacon_chain/rpc/rest_beacon_api.nim index 4e49f599e..4cc9f5a1c 100644 --- a/beacon_chain/rpc/beacon_rest_api.nim +++ b/beacon_chain/rpc/rest_beacon_api.nim @@ -15,15 +15,10 @@ import ../spec/[crypto, digest, forkedbeaconstate_helpers, network], ../spec/datatypes/phase0, ../ssz/merkleization, - ./eth2_json_rest_serialization, ./rest_utils + ./rest_utils logScope: topics = "rest_beaconapi" -const - # https://github.com/ethereum/eth2.0-APIs/blob/master/apis/beacon/states/validator_balances.yaml#L17 - # https://github.com/ethereum/eth2.0-APIs/blob/master/apis/beacon/states/validators.yaml#L17 - MaximumValidatorIds* = 30 - proc validateFilter(filters: seq[ValidatorFilter]): Result[ValidatorFilter, cstring] = var res: ValidatorFilter @@ -940,38 +935,3 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) = "/eth/v1/beacon/pool/voluntary_exits", "/api/eth/v1/beacon/pool/voluntary_exits" ) - -proc getBeaconGenesis*(): RestResponse[DataRestBeaconGenesis] {. - rest, endpoint: "/eth/v1/beacon/genesis", - meth: MethodGet.} - ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getGenesis - -proc getStateFork*(state_id: StateIdent): RestResponse[DataRestFork] {. - rest, endpoint: "/eth/v1/beacon/states/{state_id}/fork", - meth: MethodGet.} - ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getStateFork - -proc publishBlock*(body: phase0.SignedBeaconBlock): RestPlainResponse {. - rest, endpoint: "/eth/v1/beacon/blocks", - meth: MethodPost.} - ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/publishBlock - -proc getStateValidator*(state_id: StateIdent, - validator_id: ValidatorIdent - ): RestResponse[DataRestValidator] {. - rest, - endpoint: "/eth/v1/beacon/states/{state_id}/validators/{validator_id}", - meth: MethodGet.} - ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getStateValidator - -proc getStateValidators*(state_id: StateIdent, - id: seq[ValidatorIdent] - ): RestResponse[DataRestValidatorList] {. - rest, endpoint: "/eth/v1/beacon/states/{state_id}/validators", - meth: MethodGet.} - ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getStateValidators - -proc submitPoolAttestations*(body: seq[Attestation]): RestPlainResponse {. - rest, endpoint: "/eth/v1/beacon/pool/attestations", - meth: MethodPost.} - ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/submitPoolAttestations diff --git a/beacon_chain/rpc/config_rest_api.nim b/beacon_chain/rpc/rest_config_api.nim similarity index 96% rename from beacon_chain/rpc/config_rest_api.nim rename to beacon_chain/rpc/rest_config_api.nim index 66a03239c..9bca20e3e 100644 --- a/beacon_chain/rpc/config_rest_api.nim +++ b/beacon_chain/rpc/rest_config_api.nim @@ -7,13 +7,12 @@ import stew/[endians2, base10], presto, - rest_utils, chronicles, nimcrypto/utils as ncrutils, ../beacon_node_common, ../eth1/eth1_monitor, ../spec/datatypes/base, ../spec/[digest, forkedbeaconstate_helpers, presets], - ./eth2_json_rest_serialization, ./rest_utils + ./rest_utils logScope: topics = "rest_config" @@ -180,7 +179,3 @@ proc installConfigApiHandlers*(router: var RestRouter, node: BeaconNode) = "/eth/v1/config/deposit_contract", "/api/eth/v1/config/deposit_contract" ) - -proc getConfig*(): RestResponse[DataRestConfig] {. - rest, endpoint: "/eth/v1/config/spec", meth: MethodGet.} - ## https://ethereum.github.io/eth2.0-APIs/#/Config/getSpec diff --git a/beacon_chain/rpc/debug_rest_api.nim b/beacon_chain/rpc/rest_debug_api.nim similarity index 85% rename from beacon_chain/rpc/debug_rest_api.nim rename to beacon_chain/rpc/rest_debug_api.nim index 323d03244..5bf75cd85 100644 --- a/beacon_chain/rpc/debug_rest_api.nim +++ b/beacon_chain/rpc/rest_debug_api.nim @@ -4,7 +4,7 @@ import chronicles, ../version, ../beacon_node_common, ../spec/[datatypes, digest, presets], - ./eth2_json_rest_serialization, ./rest_utils + ./rest_utils logScope: topics = "rest_debug" @@ -42,3 +42,8 @@ proc installDebugApiHandlers*(router: var RestRouter, node: BeaconNode) = "/eth/v1/debug/beacon/heads", "/api/eth/v1/debug/beacon/heads" ) + +proc getDebugChainHeads*(): RestResponse[GetDebugChainHeadsResponse] {. + rest, endpoint: "/eth/v1/debug/beacon/heads", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getDebugChainHeads diff --git a/beacon_chain/rpc/event_rest_api.nim b/beacon_chain/rpc/rest_event_api.nim similarity index 98% rename from beacon_chain/rpc/event_rest_api.nim rename to beacon_chain/rpc/rest_event_api.nim index 18bb7afee..e33b44743 100644 --- a/beacon_chain/rpc/event_rest_api.nim +++ b/beacon_chain/rpc/rest_event_api.nim @@ -8,7 +8,7 @@ import stew/results, chronicles, presto, - ./eth2_json_rest_serialization, ./rest_utils, + ./rest_utils, ../beacon_node_common logScope: topics = "rest_eventapi" diff --git a/beacon_chain/rpc/nimbus_rest_api.nim b/beacon_chain/rpc/rest_nimbus_api.nim similarity index 99% rename from beacon_chain/rpc/nimbus_rest_api.nim rename to beacon_chain/rpc/rest_nimbus_api.nim index ad4ffefe1..cfe08b68d 100644 --- a/beacon_chain/rpc/nimbus_rest_api.nim +++ b/beacon_chain/rpc/rest_nimbus_api.nim @@ -11,7 +11,7 @@ import presto, libp2p/[multiaddress, multicodec], libp2p/protocols/pubsub/pubsubpeer, - ./eth2_json_rest_serialization, ./rest_utils, + ./rest_utils, ../eth1/eth1_monitor, ../validators/validator_duties, ../spec/forkedbeaconstate_helpers, diff --git a/beacon_chain/rpc/node_rest_api.nim b/beacon_chain/rpc/rest_node_api.nim similarity index 95% rename from beacon_chain/rpc/node_rest_api.nim rename to beacon_chain/rpc/rest_node_api.nim index 71be6aee1..1787ff648 100644 --- a/beacon_chain/rpc/node_rest_api.nim +++ b/beacon_chain/rpc/rest_node_api.nim @@ -9,8 +9,8 @@ import ../networking/[eth2_network, peer_pool], ../spec/datatypes/base, ../spec/[digest, presets], - ../spec/eth2_apis/callsigs_types, - ./eth2_json_rest_serialization, ./rest_utils + ../spec/eth2_apis/rpc_types, + ./rest_utils logScope: topics = "rest_node" @@ -183,7 +183,7 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) = $dres.error()) dres.get() - var res: seq[NodePeerTuple] + var res: seq[RpcNodePeer] for item in node.network.peers.values(): if (item.connectionState in connectionMask) and (item.direction in directionMask): @@ -291,13 +291,3 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) = "/eth/v1/node/health", "/api/eth/v1/node/health" ) - -proc getSyncingStatus*(): RestResponse[DataRestSyncInfo] {. - rest, endpoint: "/eth/v1/node/syncing", - meth: MethodGet.} - ## https://ethereum.github.io/eth2.0-APIs/#/Node/getSyncingStatus - -proc getVersion*(): RestResponse[DataRestVersion] {. - rest, endpoint: "/eth/v1/node/version", - meth: MethodGet.} - ## https://ethereum.github.io/eth2.0-APIs/#/Node/getNodeVersion diff --git a/beacon_chain/rpc/rest_utils.nim b/beacon_chain/rpc/rest_utils.nim index f4c207b12..556d7270d 100644 --- a/beacon_chain/rpc/rest_utils.nim +++ b/beacon_chain/rpc/rest_utils.nim @@ -1,32 +1,14 @@ import presto, presto/client as presto_client, - libp2p/peerid, - stew/[base10, byteutils], - faststreams/[outputs], - serialization, json_serialization, nimcrypto/utils as ncrutils, ../spec/[crypto, datatypes, digest, forkedbeaconstate_helpers], + ../spec/eth2_apis/[rest_types, eth2_rest_serialization], ../beacon_node_common, ../consensus_object_pools/[block_pools_types, blockchain_dag] -export blockchain_dag, presto, presto_client + +export + blockchain_dag, presto, presto_client, rest_types, eth2_rest_serialization const - DecimalSet = {'0' .. '9'} - # Base10 (decimal) set of chars - HexadecimalSet = {'0'..'9', 'A'..'F', 'a'..'f'} - # Base16 (hexadecimal) set of chars - Base58Set = {'1'..'9', 'A'..'H', 'J'..'N', 'P'..'Z', 'a'..'k', 'm'..'z'} - # Base58 set of chars - MaxDecimalSize = len($high(uint64)) - # Maximum size of `uint64` decimal value - MaxPeerIdSize = 128 - # Maximum size of `PeerID` base58 encoded value - ValidatorKeySize = RawPubKeySize * 2 - # Size of `ValidatorPubKey` hexadecimal value (without 0x) - ValidatorSigSize = RawSigSize * 2 - # Size of `ValidatorSig` hexadecimal value (without 0x) - RootHashSize = sizeof(Eth2Digest) * 2 - # Size of `xxx_root` hexadecimal value (without 0x) - FarFutureEpochString* = "18446744073709551615" MaxEpoch* = compute_epoch_at_slot(not(0'u64)) BlockValidationError* = @@ -159,69 +141,9 @@ const "Not implemented yet" type - ValidatorQueryKind* {.pure.} = enum - Index, Key - - RestValidatorIndex* = distinct uint64 - ValidatorIndexError* {.pure.} = enum UnsupportedValue, TooHighValue - ValidatorIdent* = object - case kind*: ValidatorQueryKind - of ValidatorQueryKind.Index: - index*: RestValidatorIndex - of ValidatorQueryKind.Key: - key*: ValidatorPubKey - - ValidatorFilterKind* {.pure.} = enum - PendingInitialized, PendingQueued, - ActiveOngoing, ActiveExiting, ActiveSlashed, - ExitedUnslashed, ExitedSlashed, - WithdrawalPossible, WithdrawalDone - - ValidatorFilter* = set[ValidatorFilterKind] - - StateQueryKind* {.pure.} = enum - Slot, Root, Named - - StateIdentType* {.pure.} = enum - Head, Genesis, Finalized, Justified - - StateIdent* = object - case kind*: StateQueryKind - of StateQueryKind.Slot: - slot*: Slot - of StateQueryKind.Root: - root*: Eth2Digest - of StateQueryKind.Named: - value*: StateIdentType - - BlockQueryKind* {.pure.} = enum - Slot, Root, Named - BlockIdentType* {.pure.} = enum - Head, Genesis, Finalized - - BlockIdent* = object - case kind*: BlockQueryKind - of BlockQueryKind.Slot: - slot*: Slot - of BlockQueryKind.Root: - root*: Eth2Digest - of BlockQueryKind.Named: - value*: BlockIdentType - - PeerStateKind* {.pure.} = enum - Disconnected, Connecting, Connected, Disconnecting - - PeerDirectKind* {.pure.} = enum - Inbound, Outbound - - EventTopic* {.pure.} = enum - Head, Block, Attestation, VoluntaryExit, FinalizedCheckpoint, ChainReorg - - EventTopics* = set[EventTopic] - func match(data: openarray[char], charset: set[char]): int = for ch in data: if ch notin charset: @@ -247,228 +169,6 @@ proc validate(key: string, value: string): int = else: 1 -proc parseRoot(value: string): Result[Eth2Digest, cstring] = - try: - ok(Eth2Digest(data: hexToByteArray[32](value))) - except ValueError: - err("Unable to decode root value") - -proc decodeString*(t: typedesc[Slot], value: string): Result[Slot, cstring] = - let res = ? Base10.decode(uint64, value) - ok(Slot(res)) - -proc decodeString*(t: typedesc[Epoch], value: string): Result[Epoch, cstring] = - let res = ? Base10.decode(uint64, value) - ok(Epoch(res)) - -proc decodeString*(t: typedesc[StateIdent], - value: string): Result[StateIdent, cstring] = - if len(value) > 2: - if (value[0] == '0') and (value[1] == 'x'): - if len(value) != RootHashSize + 2: - err("Incorrect state root value length") - else: - let res = ? parseRoot(value) - ok(StateIdent(kind: StateQueryKind.Root, root: res)) - elif (value[0] in DecimalSet) and (value[1] in DecimalSet): - let res = ? Base10.decode(uint64, value) - ok(StateIdent(kind: StateQueryKind.Slot, slot: Slot(res))) - else: - case value - of "head": - ok(StateIdent(kind: StateQueryKind.Named, - value: StateIdentType.Head)) - of "genesis": - ok(StateIdent(kind: StateQueryKind.Named, - value: StateIdentType.Genesis)) - of "finalized": - ok(StateIdent(kind: StateQueryKind.Named, - value: StateIdentType.Finalized)) - of "justified": - ok(StateIdent(kind: StateQueryKind.Named, - value: StateIdentType.Justified)) - else: - err("Incorrect state identifier value") - else: - let res = ? Base10.decode(uint64, value) - ok(StateIdent(kind: StateQueryKind.Slot, slot: Slot(res))) - -proc decodeString*(t: typedesc[BlockIdent], - value: string): Result[BlockIdent, cstring] = - if len(value) > 2: - if (value[0] == '0') and (value[1] == 'x'): - if len(value) != RootHashSize + 2: - err("Incorrect block root value length") - else: - let res = ? parseRoot(value) - ok(BlockIdent(kind: BlockQueryKind.Root, root: res)) - elif (value[0] in DecimalSet) and (value[1] in DecimalSet): - let res = ? Base10.decode(uint64, value) - ok(BlockIdent(kind: BlockQueryKind.Slot, slot: Slot(res))) - else: - case value - of "head": - ok(BlockIdent(kind: BlockQueryKind.Named, - value: BlockIdentType.Head)) - of "genesis": - ok(BlockIdent(kind: BlockQueryKind.Named, - value: BlockIdentType.Genesis)) - of "finalized": - ok(BlockIdent(kind: BlockQueryKind.Named, - value: BlockIdentType.Finalized)) - else: - err("Incorrect block identifier value") - else: - let res = ? Base10.decode(uint64, value) - ok(BlockIdent(kind: BlockQueryKind.Slot, slot: Slot(res))) - -proc decodeString*(t: typedesc[ValidatorIdent], - value: string): Result[ValidatorIdent, cstring] = - if len(value) > 2: - if (value[0] == '0') and (value[1] == 'x'): - if len(value) != ValidatorKeySize + 2: - err("Incorrect validator's key value length") - else: - let res = ? ValidatorPubKey.fromHex(value) - ok(ValidatorIdent(kind: ValidatorQueryKind.Key, - key: res)) - elif (value[0] in DecimalSet) and (value[1] in DecimalSet): - let res = ? Base10.decode(uint64, value) - ok(ValidatorIdent(kind: ValidatorQueryKind.Index, - index: RestValidatorIndex(res))) - else: - err("Incorrect validator identifier value") - else: - let res = ? Base10.decode(uint64, value) - ok(ValidatorIdent(kind: ValidatorQueryKind.Index, - index: RestValidatorIndex(res))) - -proc decodeString*(t: typedesc[PeerID], - value: string): Result[PeerID, cstring] = - PeerID.init(value) - -proc decodeString*(t: typedesc[CommitteeIndex], - value: string): Result[CommitteeIndex, cstring] = - let res = ? Base10.decode(uint64, value) - ok(CommitteeIndex(res)) - -proc decodeString*(t: typedesc[Eth2Digest], - value: string): Result[Eth2Digest, cstring] = - if len(value) != RootHashSize + 2: - return err("Incorrect root value length") - if value[0] != '0' and value[1] != 'x': - return err("Incorrect root value encoding") - parseRoot(value) - -proc decodeString*(t: typedesc[ValidatorFilter], - value: string): Result[ValidatorFilter, cstring] = - case value - of "pending_initialized": - ok({ValidatorFilterKind.PendingInitialized}) - of "pending_queued": - ok({ValidatorFilterKind.PendingQueued}) - of "active_ongoing": - ok({ValidatorFilterKind.ActiveOngoing}) - of "active_exiting": - ok({ValidatorFilterKind.ActiveExiting}) - of "active_slashed": - ok({ValidatorFilterKind.ActiveSlashed}) - of "exited_unslashed": - ok({ValidatorFilterKind.ExitedUnslashed}) - of "exited_slashed": - ok({ValidatorFilterKind.ExitedSlashed}) - of "withdrawal_possible": - ok({ValidatorFilterKind.WithdrawalPossible}) - of "withdrawal_done": - ok({ValidatorFilterKind.WithdrawalDone}) - of "pending": - ok({ - ValidatorFilterKind.PendingInitialized, - ValidatorFilterKind.PendingQueued - }) - of "active": - ok({ - ValidatorFilterKind.ActiveOngoing, - ValidatorFilterKind.ActiveExiting, - ValidatorFilterKind.ActiveSlashed - }) - of "exited": - ok({ - ValidatorFilterKind.ExitedUnslashed, - ValidatorFilterKind.ExitedSlashed - }) - of "withdrawal": - ok({ - ValidatorFilterKind.WithdrawalPossible, - ValidatorFilterKind.WithdrawalDone - }) - else: - err("Incorrect validator state identifier value") - -proc decodeString*(t: typedesc[PeerStateKind], - value: string): Result[PeerStateKind, cstring] = - case value - of "disconnected": - ok(PeerStateKind.Disconnected) - of "connecting": - ok(PeerStateKind.Connecting) - of "connected": - ok(PeerStateKind.Connected) - of "disconnecting": - ok(PeerStateKind.Disconnecting) - else: - err("Incorrect peer's state value") - -proc decodeString*(t: typedesc[PeerDirectKind], - value: string): Result[PeerDirectKind, cstring] = - case value - of "inbound": - ok(PeerDirectKind.Inbound) - of "outbound": - ok(PeerDirectKind.Outbound) - else: - err("Incorrect peer's direction value") - -proc decodeString*(t: typedesc[EventTopic], - value: string): Result[EventTopic, cstring] = - case value - of "head": - ok(EventTopic.Head) - of "block": - ok(EventTopic.Block) - of "attestation": - ok(EventTopic.Attestation) - of "voluntary_exit": - ok(EventTopic.VoluntaryExit) - of "finalized_checkpoint": - ok(EventTopic.FinalizedCheckpoint) - of "chain_reorg": - ok(EventTopic.ChainReorg) - else: - err("Incorrect event's topic value") - -proc decodeString*(t: typedesc[ValidatorSig], - value: string): Result[ValidatorSig, cstring] = - if len(value) != ValidatorSigSize + 2: - return err("Incorrect validator signature value length") - if value[0] != '0' and value[1] != 'x': - return err("Incorrect validator signature encoding") - ValidatorSig.fromHex(value) - -proc decodeString*(t: typedesc[GraffitiBytes], - value: string): Result[GraffitiBytes, cstring] = - try: - ok(GraffitiBytes.init(value)) - except ValueError: - err("Unable to decode graffiti value") - -proc decodeString*(t: typedesc[string], - value: string): Result[string, cstring] = - ok(value) - -proc getRouter*(): RestRouter = - RestRouter.init(validate) - proc getCurrentHead*(node: BeaconNode, slot: Slot): Result[BlockRef, cstring] = let res = node.dag.head @@ -570,17 +270,5 @@ proc toValidatorIndex*(value: RestValidatorIndex): Result[ValidatorIndex, else: doAssert(false, "ValidatorIndex type size is incorrect") -proc init*(t: typedesc[StateIdent], v: StateIdentType): StateIdent = - StateIdent(kind: StateQueryKind.Named, value: v) - -proc init*(t: typedesc[StateIdent], v: Slot): StateIdent = - StateIdent(kind: StateQueryKind.Slot, slot: v) - -proc init*(t: typedesc[StateIdent], v: Eth2Digest): StateIdent = - StateIdent(kind: StateQueryKind.Root, root: v) - -proc init*(t: typedesc[ValidatorIdent], v: ValidatorIndex): ValidatorIdent = - ValidatorIdent(kind: ValidatorQueryKind.Index, index: RestValidatorIndex(v)) - -proc init*(t: typedesc[ValidatorIdent], v: ValidatorPubKey): ValidatorIdent = - ValidatorIdent(kind: ValidatorQueryKind.Key, key: v) +proc getRouter*(): RestRouter = + RestRouter.init(validate) diff --git a/beacon_chain/rpc/validator_rest_api.nim b/beacon_chain/rpc/rest_validator_api.nim similarity index 88% rename from beacon_chain/rpc/validator_rest_api.nim rename to beacon_chain/rpc/rest_validator_api.nim index 7f825443a..5ad8f4058 100644 --- a/beacon_chain/rpc/validator_rest_api.nim +++ b/beacon_chain/rpc/rest_validator_api.nim @@ -15,7 +15,7 @@ import ../spec/[crypto, digest, forkedbeaconstate_helpers, network], ../spec/datatypes/base, ../ssz/merkleization, - ./eth2_json_rest_serialization, ./rest_utils + ./rest_utils logScope: topics = "rest_validatorapi" @@ -386,47 +386,3 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) = "/eth/v1/validator/beacon_committee_subscriptions", "/api/eth/v1/validator/beacon_committee_subscriptions" ) - -proc getProposerDuties*(epoch: Epoch): RestResponse[DataRestProposerDuties] {. - rest, endpoint: "/eth/v1/validator/duties/proposer/{epoch}", - meth: MethodGet.} - ## https://ethereum.github.io/eth2.0-APIs/#/Validator/getProposerDuties - -proc getAttesterDuties*(epoch: Epoch, - body: seq[ValidatorIndex] - ): RestResponse[DataRestAttesterDuties] {. - rest, endpoint: "/eth/v1/validator/duties/attester/{epoch}", - meth: MethodPost.} - ## https://ethereum.github.io/eth2.0-APIs/#/Validator/getAttesterDuties - -proc produceBlock*(slot: Slot, randao_reveal: ValidatorSig, - graffiti: GraffitiBytes - ): RestResponse[DataRestBeaconBlock] {. - rest, endpoint: "/eth/v1/validator/blocks/{slot}", - meth: MethodGet.} - ## https://ethereum.github.io/eth2.0-APIs/#/Validator/produceBlock - -proc produceAttestationData*(slot: Slot, - committee_index: CommitteeIndex - ): RestResponse[DataRestAttestationData] {. - rest, endpoint: "/eth/v1/validator/attestation_data", - meth: MethodGet.} - ## https://ethereum.github.io/eth2.0-APIs/#/Validator/produceAttestationData - -proc getAggregatedAttestation*(attestation_data_root: Eth2Digest, - slot: Slot): RestResponse[DataRestAttestation] {. - rest, endpoint: "/eth/v1/validator/aggregate_attestation" - meth: MethodGet.} - ## https://ethereum.github.io/eth2.0-APIs/#/Validator/getAggregatedAttestation - -proc publishAggregateAndProofs*(body: seq[SignedAggregateAndProof] - ): RestPlainResponse {. - rest, endpoint: "/eth/v1/validator/aggregate_and_proofs", - meth: MethodPost.} - ## https://ethereum.github.io/eth2.0-APIs/#/Validator/publishAggregateAndProofs - -proc prepareBeaconCommitteeSubnet*(body: seq[RestCommitteeSubscription] - ): RestPlainResponse {. - rest, endpoint: "/eth/v1/validator/beacon_committee_subscriptions", - meth: MethodPost.} - ## https://ethereum.github.io/eth2.0-APIs/#/Validator/prepareBeaconCommitteeSubnet diff --git a/beacon_chain/rpc/rpc_api.nim b/beacon_chain/rpc/rpc_api.nim new file mode 100644 index 000000000..d0e3507c3 --- /dev/null +++ b/beacon_chain/rpc/rpc_api.nim @@ -0,0 +1,24 @@ +# Copyright (c) 2018-2021 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +## The `rpc_api` module is a server implementation of a JSON-RPC-based API +## for Nimbus - it is based on the common REST API for Ethereum 2 found at +## https://ethereum.github.io/eth2.0-APIs/# but uses JSON-RPC as transport +## instead. There are also minor historical differences in encoding and data - +## these differences will likely remain so as to not break old tooling. +## +## The JSON-RPC is used by community utilities and tools and is kept for +## backwards compatibility mainly. +## A corresponding client can be found in the +## `spec/eth2_apis/rpc_beacon_client` module. +import + "."/[ + rpc_beacon_api, rpc_config_api, rpc_debug_api, rpc_event_api, + rpc_nimbus_api, rpc_node_api, rpc_validator_api] + +export + rpc_beacon_api, rpc_config_api, rpc_debug_api, rpc_event_api, + rpc_nimbus_api, rpc_node_api, rpc_validator_api diff --git a/beacon_chain/rpc/beacon_api.nim b/beacon_chain/rpc/rpc_beacon_api.nim similarity index 96% rename from beacon_chain/rpc/beacon_api.nim rename to beacon_chain/rpc/rpc_beacon_api.nim index cdb28e2b6..aafd73188 100644 --- a/beacon_chain/rpc/beacon_api.nim +++ b/beacon_chain/rpc/rpc_beacon_api.nim @@ -19,9 +19,8 @@ import ../gossip_processing/gossip_validation, ../consensus_object_pools/blockchain_dag, ../spec/[crypto, datatypes/phase0, digest, forkedbeaconstate_helpers, network], - ../spec/eth2_apis/callsigs_types, ../ssz/merkleization, - ./rpc_utils, ./eth2_json_rpc_serialization + ./rpc_utils logScope: topics = "beaconapi" @@ -180,7 +179,7 @@ proc getBlockDataFromBlockId(node: BeaconNode, blockId: string): BlockData {.rai proc installBeaconApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. raises: [Exception].} = # TODO fix json-rpc - rpcServer.rpc("get_v1_beacon_genesis") do () -> BeaconGenesisTuple: + rpcServer.rpc("get_v1_beacon_genesis") do () -> RpcBeaconGenesis: return ( genesis_time: getStateField(node.dag.headState.data, genesis_time), genesis_validators_root: @@ -197,7 +196,7 @@ proc installBeaconApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. return getStateField(stateData.data, fork) rpcServer.rpc("get_v1_beacon_states_finality_checkpoints") do ( - stateId: string) -> BeaconStatesFinalityCheckpointsTuple: + stateId: string) -> RpcBeaconStatesFinalityCheckpoints: withStateForStateId(stateId): return (previous_justified: getStateField(stateData.data, previous_justified_checkpoint), @@ -207,7 +206,7 @@ proc installBeaconApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. rpcServer.rpc("get_v1_beacon_states_stateId_validators") do ( stateId: string, validatorIds: Option[seq[string]], - status: Option[seq[string]]) -> seq[BeaconStatesValidatorsTuple]: + status: Option[seq[string]]) -> seq[RpcBeaconStatesValidators]: var vquery: ValidatorQuery var squery: StatusQuery let current_epoch = getStateField(node.dag.headState.data, slot).epoch @@ -221,7 +220,7 @@ proc installBeaconApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. else: false - var res: seq[BeaconStatesValidatorsTuple] + var res: seq[RpcBeaconStatesValidators] withStateForStateId(stateId): if status.isSome: @@ -279,7 +278,7 @@ proc installBeaconApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. return res rpcServer.rpc("get_v1_beacon_states_stateId_validators_validatorId") do ( - stateId: string, validatorId: string) -> BeaconStatesValidatorsTuple: + stateId: string, validatorId: string) -> RpcBeaconStatesValidators: let current_epoch = getStateField(node.dag.headState.data, slot).epoch let vqres = createIdQuery([validatorId]) if vqres.isErr: @@ -310,9 +309,9 @@ proc installBeaconApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. raise newException(CatchableError, "Incorrect validator's state") rpcServer.rpc("get_v1_beacon_states_stateId_validator_balances") do ( - stateId: string, validatorsId: Option[seq[string]]) -> seq[BalanceTuple]: + stateId: string, validatorsId: Option[seq[string]]) -> seq[RpcBalance]: - var res: seq[BalanceTuple] + var res: seq[RpcBalance] withStateForStateId(stateId): if validatorsId.isNone(): for index, value in getStateField(stateData.data, balances).pairs(): @@ -341,15 +340,15 @@ proc installBeaconApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. rpcServer.rpc("get_v1_beacon_states_stateId_committees_epoch") do ( stateId: string, epoch: Option[uint64], index: Option[uint64], - slot: Option[uint64]) -> seq[BeaconStatesCommitteesTuple]: + slot: Option[uint64]) -> seq[RpcBeaconStatesCommittees]: withStateForStateId(stateId): proc getCommittee(slot: Slot, - index: CommitteeIndex): BeaconStatesCommitteesTuple = + index: CommitteeIndex): RpcBeaconStatesCommittees = let vals = get_beacon_committee( stateData.data, slot, index, cache).mapIt(it.uint64) return (index: index.uint64, slot: slot.uint64, validators: vals) - proc forSlot(slot: Slot, res: var seq[BeaconStatesCommitteesTuple]) = + proc forSlot(slot: Slot, res: var seq[RpcBeaconStatesCommittees]) = let committees_per_slot = get_committee_count_per_slot(stateData.data, slot.epoch, cache) @@ -360,7 +359,7 @@ proc installBeaconApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. if index.get() < committees_per_slot: res.add(getCommittee(slot, CommitteeIndex(index.get()))) - var res: seq[BeaconStatesCommitteesTuple] + var res: seq[RpcBeaconStatesCommittees] let qepoch = if epoch.isNone: @@ -378,7 +377,7 @@ proc installBeaconApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. rpcServer.rpc("get_v1_beacon_headers") do ( slot: Option[uint64], parent_root: Option[string]) -> - seq[BeaconHeadersTuple]: + seq[RpcBeaconHeaders]: unimplemented() rpcServer.rpc("get_v1_beacon_headers_blockId") do ( @@ -443,9 +442,9 @@ proc installBeaconApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. rpcServer.rpc("get_v1_beacon_pool_attestations") do ( slot: Option[uint64], committee_index: Option[uint64]) -> - seq[AttestationTuple]: + seq[RpcAttestation]: - var res: seq[AttestationTuple] + var res: seq[RpcAttestation] let qslot = if slot.isSome(): diff --git a/beacon_chain/rpc/config_api.nim b/beacon_chain/rpc/rpc_config_api.nim similarity index 100% rename from beacon_chain/rpc/config_api.nim rename to beacon_chain/rpc/rpc_config_api.nim diff --git a/beacon_chain/rpc/debug_api.nim b/beacon_chain/rpc/rpc_debug_api.nim similarity index 96% rename from beacon_chain/rpc/debug_api.nim rename to beacon_chain/rpc/rpc_debug_api.nim index 00426d911..1c10b883e 100644 --- a/beacon_chain/rpc/debug_api.nim +++ b/beacon_chain/rpc/rpc_debug_api.nim @@ -15,7 +15,7 @@ import ../networking/[eth2_network, peer_pool], ../spec/datatypes/phase0, ../spec/[digest, presets], - ./rpc_utils, ./eth2_json_rpc_serialization + ./rpc_utils logScope: topics = "debugapi" diff --git a/beacon_chain/rpc/event_api.nim b/beacon_chain/rpc/rpc_event_api.nim similarity index 100% rename from beacon_chain/rpc/event_api.nim rename to beacon_chain/rpc/rpc_event_api.nim diff --git a/beacon_chain/rpc/nimbus_api.nim b/beacon_chain/rpc/rpc_nimbus_api.nim similarity index 98% rename from beacon_chain/rpc/nimbus_api.nim rename to beacon_chain/rpc/rpc_nimbus_api.nim index 218b5fc38..cb5308385 100644 --- a/beacon_chain/rpc/nimbus_api.nim +++ b/beacon_chain/rpc/rpc_nimbus_api.nim @@ -14,12 +14,12 @@ import json_rpc/servers/httpserver, libp2p/protocols/pubsub/pubsubpeer, - "."/[rpc_utils, eth2_json_rpc_serialization], ".."/[ beacon_node_common, nimbus_binary_common, networking/eth2_network, eth1/eth1_monitor, validators/validator_duties], ../spec/datatypes/base, - ../spec/[digest, forkedbeaconstate_helpers, presets] + ../spec/[digest, forkedbeaconstate_helpers, presets], + ./rpc_utils logScope: topics = "nimbusapi" diff --git a/beacon_chain/rpc/node_api.nim b/beacon_chain/rpc/rpc_node_api.nim similarity index 95% rename from beacon_chain/rpc/node_api.nim rename to beacon_chain/rpc/rpc_node_api.nim index 1e1e9d4da..d2bcb9410 100644 --- a/beacon_chain/rpc/node_api.nim +++ b/beacon_chain/rpc/rpc_node_api.nim @@ -13,13 +13,12 @@ import std/options, eth/p2p/discoveryv5/enr, libp2p/[multiaddress, multicodec], nimcrypto/utils as ncrutils, - ./eth2_json_rpc_serialization, ../beacon_node_common, ../version, ../networking/[eth2_network, peer_pool], ../sync/sync_manager, ../spec/datatypes/base, ../spec/[digest, presets], - ../spec/eth2_apis/callsigs_types + ./rpc_utils logScope: topics = "nodeapi" @@ -152,7 +151,7 @@ proc getP2PAddresses(node: BeaconNode): Option[seq[string]] = proc installNodeApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. raises: [Exception].} = # TODO fix json-rpc - rpcServer.rpc("get_v1_node_identity") do () -> NodeIdentityTuple: + rpcServer.rpc("get_v1_node_identity") do () -> RpcNodeIdentity: let discoveryAddresses = block: let res = node.getDiscoveryAddresses() @@ -179,8 +178,8 @@ proc installNodeApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. ) rpcServer.rpc("get_v1_node_peers") do (state: Option[seq[string]], - direction: Option[seq[string]]) -> seq[NodePeerTuple]: - var res = newSeq[NodePeerTuple]() + direction: Option[seq[string]]) -> seq[RpcNodePeer]: + var res = newSeq[RpcNodePeer]() let rstates = validateState(state) if rstates.isNone(): raise newException(CatchableError, "Incorrect state parameter") @@ -203,8 +202,8 @@ proc installNodeApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. res.add(peer) return res - rpcServer.rpc("get_v1_node_peer_count") do () -> NodePeerCountTuple: - var res: NodePeerCountTuple + rpcServer.rpc("get_v1_node_peer_count") do () -> RpcNodePeerCount: + var res: RpcNodePeerCount for item in node.network.peers.values(): case item.connectionState of ConnectionState.Connecting: @@ -220,7 +219,7 @@ proc installNodeApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. return res rpcServer.rpc("get_v1_node_peers_peerId") do ( - peer_id: string) -> NodePeerTuple: + peer_id: string) -> RpcNodePeer: let pres = PeerID.init(peer_id) if pres.isErr(): raise newException(CatchableError, @@ -243,7 +242,7 @@ proc installNodeApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. rpcServer.rpc("get_v1_node_version") do () -> JsonNode: return %*{"version": "Nimbus/" & fullVersionStr} - rpcServer.rpc("get_v1_node_syncing") do () -> SyncInfo: + rpcServer.rpc("get_v1_node_syncing") do () -> RpcSyncInfo: return node.syncManager.getInfo() rpcServer.rpc("get_v1_node_health") do () -> JsonNode: diff --git a/beacon_chain/rpc/rpc_utils.nim b/beacon_chain/rpc/rpc_utils.nim index 45a270b26..620da4676 100644 --- a/beacon_chain/rpc/rpc_utils.nim +++ b/beacon_chain/rpc/rpc_utils.nim @@ -13,9 +13,10 @@ import ../beacon_node_common, ../validators/validator_duties, ../consensus_object_pools/[block_pools_types, blockchain_dag], ../spec/datatypes/base, - ../spec/[digest, forkedbeaconstate_helpers, helpers] + ../spec/[digest, forkedbeaconstate_helpers, helpers], + ../spec/eth2_apis/[rpc_types, eth2_json_rpc_serialization] -export blockchain_dag +export rpc_types, eth2_json_rpc_serialization, blockchain_dag template withStateForStateId*(stateId: string, body: untyped): untyped = let diff --git a/beacon_chain/rpc/validator_api.nim b/beacon_chain/rpc/rpc_validator_api.nim similarity index 97% rename from beacon_chain/rpc/validator_api.nim rename to beacon_chain/rpc/rpc_validator_api.nim index c640d545b..432dabc2f 100644 --- a/beacon_chain/rpc/validator_api.nim +++ b/beacon_chain/rpc/rpc_validator_api.nim @@ -19,12 +19,11 @@ import # Local modules ../spec/[crypto, digest, forkedbeaconstate_helpers, helpers, network, signatures], ../spec/datatypes/phase0, - ../spec/eth2_apis/callsigs_types, + ../spec/eth2_apis/rpc_types, ../consensus_object_pools/[blockchain_dag, spec_cache, attestation_pool], ../ssz/merkleization, ../beacon_node_common, ../beacon_node_types, ../validators/validator_duties, ../networking/eth2_network, - ./eth2_json_rpc_serialization, ./rpc_utils logScope: topics = "valapi" @@ -86,7 +85,7 @@ proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. signature = shortLog(payload.signature) rpcServer.rpc("get_v1_validator_duties_attester") do ( - epoch: Epoch, public_keys: seq[ValidatorPubKey]) -> seq[AttesterDuties]: + epoch: Epoch, public_keys: seq[ValidatorPubKey]) -> seq[RpcAttesterDuties]: debug "get_v1_validator_duties_attester", epoch = epoch let head = node.doChecksAndGetCurrentHead(epoch) @@ -109,7 +108,7 @@ proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {. slot: slot)) rpcServer.rpc("get_v1_validator_duties_proposer") do ( - epoch: Epoch) -> seq[ValidatorDutiesTuple]: + epoch: Epoch) -> seq[RpcValidatorDuties]: debug "get_v1_validator_duties_proposer", epoch = epoch let head = node.doChecksAndGetCurrentHead(epoch) diff --git a/beacon_chain/spec/eth2_apis/beacon_rpc_client.nim b/beacon_chain/spec/eth2_apis/beacon_rpc_client.nim deleted file mode 100644 index 04d76e08e..000000000 --- a/beacon_chain/spec/eth2_apis/beacon_rpc_client.nim +++ /dev/null @@ -1,16 +0,0 @@ -import - std/os, - json_rpc/rpcclient, - ../../rpc/eth2_json_rpc_serialization, - ./callsigs_types - -export - rpcclient, - callsigs_types, - eth2_json_rpc_serialization - -createRpcSigs(RpcClient, currentSourcePath.parentDir / "beacon_callsigs.nim") -createRpcSigs(RpcClient, currentSourcePath.parentDir / "debug_callsigs.nim") -createRpcSigs(RpcClient, currentSourcePath.parentDir / "nimbus_callsigs.nim") -createRpcSigs(RpcClient, currentSourcePath.parentDir / "node_callsigs.nim") -createRpcSigs(RpcClient, currentSourcePath.parentDir / "validator_callsigs.nim") diff --git a/beacon_chain/rpc/eth2_json_rpc_serialization.nim b/beacon_chain/spec/eth2_apis/eth2_json_rpc_serialization.nim similarity index 99% rename from beacon_chain/rpc/eth2_json_rpc_serialization.nim rename to beacon_chain/spec/eth2_apis/eth2_json_rpc_serialization.nim index 7d0e10f91..715ec3331 100644 --- a/beacon_chain/rpc/eth2_json_rpc_serialization.nim +++ b/beacon_chain/spec/eth2_apis/eth2_json_rpc_serialization.nim @@ -29,8 +29,8 @@ import json_rpc/jsonmarshal, # Local modules - ../ssz/types, - ../spec/[datatypes, crypto, digest] + ../../ssz/types, + ".."/[datatypes, crypto, digest] export jsonmarshal, datatypes, crypto, digest diff --git a/beacon_chain/rpc/eth2_json_rest_serialization.nim b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim similarity index 64% rename from beacon_chain/rpc/eth2_json_rest_serialization.nim rename to beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim index 07658a5dc..1ea3ce427 100644 --- a/beacon_chain/rpc/eth2_json_rest_serialization.nim +++ b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim @@ -1,135 +1,34 @@ +# Copyright (c) 2018-2021 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + import std/[typetraits], stew/[results, base10, byteutils, endians2], - chronicles, presto, - faststreams/[outputs], - serialization, json_serialization, + presto, + libp2p/peerid, + json_serialization, json_serialization/std/[options, net], nimcrypto/utils as ncrutils, - ../beacon_node_common, ../networking/eth2_network, - ../consensus_object_pools/[blockchain_dag, exit_pool], - ../spec/[crypto, digest, datatypes/phase0, eth2_apis/callsigs_types], - ../ssz/merkleization, - rest_utils -export json_serialization + ../datatypes/[phase0, altair], + ./rest_types + +export results, peerid, presto, json_serialization, options, net, rest_types Json.createFlavor RestJson +const + DecimalSet = {'0' .. '9'} + # Base10 (decimal) set of chars + ValidatorKeySize = RawPubKeySize * 2 + # Size of `ValidatorPubKey` hexadecimal value (without 0x) + ValidatorSigSize = RawSigSize * 2 + # Size of `ValidatorSig` hexadecimal value (without 0x) + RootHashSize = sizeof(Eth2Digest) * 2 + # Size of `xxx_root` hexadecimal value (without 0x) + type - RestAttesterDuty* = object - pubkey*: ValidatorPubKey - validator_index*: ValidatorIndex - committee_index*: CommitteeIndex - committee_length*: uint64 - committees_at_slot*: uint64 - validator_committee_index*: ValidatorIndex - slot*: Slot - - RestProposerDuty* = object - pubkey*: ValidatorPubKey - validator_index*: ValidatorIndex - slot*: Slot - - RestCommitteeSubscription* = object - validator_index*: ValidatorIndex - committee_index*: CommitteeIndex - committees_at_slot*: uint64 - slot*: Slot - is_aggregator*: bool - - RestBeaconGenesis* = object - genesis_time*: uint64 - genesis_validators_root*: Eth2Digest - genesis_fork_version*: Version - - RestValidatorBalance* = object - index*: ValidatorIndex - balance*: string - - RestBeaconStatesCommittees* = object - index*: CommitteeIndex - slot*: Slot - validators*: seq[ValidatorIndex] - - RestAttestationsFailure* = object - index*: uint64 - message*: string - - RestValidator* = object - index*: ValidatorIndex - balance*: string - status*: string - validator*: Validator - - RestVersion* = object - version*: string - - RestSyncInfo* = object - head_slot*: Slot - sync_distance*: uint64 - is_syncing*: bool - - RestConfig* = object - CONFIG_NAME*: string - MAX_COMMITTEES_PER_SLOT*: uint64 - TARGET_COMMITTEE_SIZE*: uint64 - MAX_VALIDATORS_PER_COMMITTEE*: uint64 - MIN_PER_EPOCH_CHURN_LIMIT*: uint64 - CHURN_LIMIT_QUOTIENT*: uint64 - SHUFFLE_ROUND_COUNT*: uint64 - MIN_GENESIS_ACTIVE_VALIDATOR_COUNT*: uint64 - MIN_GENESIS_TIME*: uint64 - HYSTERESIS_QUOTIENT*: uint64 - HYSTERESIS_DOWNWARD_MULTIPLIER*: uint64 - HYSTERESIS_UPWARD_MULTIPLIER*: uint64 - SAFE_SLOTS_TO_UPDATE_JUSTIFIED*: uint64 - ETH1_FOLLOW_DISTANCE*: uint64 - TARGET_AGGREGATORS_PER_COMMITTEE*: uint64 - RANDOM_SUBNETS_PER_VALIDATOR*: uint64 - EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION*: uint64 - SECONDS_PER_ETH1_BLOCK*: uint64 - DEPOSIT_CHAIN_ID*: uint64 - DEPOSIT_NETWORK_ID*: uint64 - DEPOSIT_CONTRACT_ADDRESS*: Eth1Address - MIN_DEPOSIT_AMOUNT*: uint64 - MAX_EFFECTIVE_BALANCE*: uint64 - EJECTION_BALANCE*: uint64 - EFFECTIVE_BALANCE_INCREMENT*: uint64 - GENESIS_FORK_VERSION*: Version - BLS_WITHDRAWAL_PREFIX*: byte - GENESIS_DELAY*: uint64 - SECONDS_PER_SLOT*: uint64 - MIN_ATTESTATION_INCLUSION_DELAY*: uint64 - SLOTS_PER_EPOCH*: uint64 - MIN_SEED_LOOKAHEAD*: uint64 - MAX_SEED_LOOKAHEAD*: uint64 - EPOCHS_PER_ETH1_VOTING_PERIOD*: uint64 - SLOTS_PER_HISTORICAL_ROOT*: uint64 - MIN_VALIDATOR_WITHDRAWABILITY_DELAY*: uint64 - SHARD_COMMITTEE_PERIOD*: uint64 - MIN_EPOCHS_TO_INACTIVITY_PENALTY*: uint64 - EPOCHS_PER_HISTORICAL_VECTOR*: uint64 - EPOCHS_PER_SLASHINGS_VECTOR*: uint64 - HISTORICAL_ROOTS_LIMIT*: uint64 - VALIDATOR_REGISTRY_LIMIT*: uint64 - BASE_REWARD_FACTOR*: uint64 - WHISTLEBLOWER_REWARD_QUOTIENT*: uint64 - PROPOSER_REWARD_QUOTIENT*: uint64 - INACTIVITY_PENALTY_QUOTIENT*: uint64 - MIN_SLASHING_PENALTY_QUOTIENT*: uint64 - PROPORTIONAL_SLASHING_MULTIPLIER*: uint64 - MAX_PROPOSER_SLASHINGS*: uint64 - MAX_ATTESTER_SLASHINGS*: uint64 - MAX_ATTESTATIONS*: uint64 - MAX_DEPOSITS*: uint64 - MAX_VOLUNTARY_EXITS*: uint64 - DOMAIN_BEACON_PROPOSER*: DomainType - DOMAIN_BEACON_ATTESTER*: DomainType - DOMAIN_RANDAO*: DomainType - DOMAIN_DEPOSIT*: DomainType - DOMAIN_VOLUNTARY_EXIT*: DomainType - DOMAIN_SELECTION_PROOF*: DomainType - DOMAIN_AGGREGATE_AND_PROOF*: DomainType - RestGenericError* = object code*: uint64 message*: string @@ -140,36 +39,24 @@ type message*: string failures*: seq[RestAttestationsFailure] - DataEnclosedObject*[T] = object - data*: T + EncodeTypes* = + AttesterSlashing | + ProposerSlashing | + phase0.SignedBeaconBlock | + SignedVoluntaryExit - DataRootEnclosedObject*[T] = object - dependent_root*: Eth2Digest - data*: T + EncodeArrays* = + seq[ValidatorIndex] | + seq[Attestation] | + seq[SignedAggregateAndProof] | + seq[RestCommitteeSubscription] - DataRestBeaconGenesis* = DataEnclosedObject[RestBeaconGenesis] - DataRestFork* = DataEnclosedObject[Fork] - DataRestProposerDuties* = DataRootEnclosedObject[seq[RestProposerDuty]] - DataRestAttesterDuties* = DataRootEnclosedObject[seq[RestAttesterDuty]] - DataRestBeaconBlock* = DataEnclosedObject[phase0.BeaconBlock] - DataRestAttestationData* = DataEnclosedObject[AttestationData] - DataRestAttestation* = DataEnclosedObject[Attestation] - DataRestSyncInfo* = DataEnclosedObject[RestSyncInfo] - DataRestValidator* = DataEnclosedObject[RestValidator] - DataRestValidatorList* = DataEnclosedObject[seq[RestValidator]] - DataRestVersion* = DataEnclosedObject[RestVersion] - DataRestConfig* = DataEnclosedObject[RestConfig] - - EncodeTypes* = phase0.SignedBeaconBlock - EncodeArrays* = seq[ValidatorIndex] | seq[Attestation] | - seq[SignedAggregateAndProof] | seq[RestCommitteeSubscription] - - DecodeTypes* = DataRestBeaconGenesis | DataRestFork | DataRestProposerDuties | - DataRestAttesterDuties | DataRestBeaconBlock | - DataRestAttestationData | DataRestAttestation | - DataRestSyncInfo | DataRestValidator | - DataRestValidatorList | DataRestVersion | - DataRestConfig | RestGenericError | RestAttestationError + DecodeTypes* = + DataEnclosedObject | + DataMetaEnclosedObject | + DataRootEnclosedObject | + RestAttestationError | + RestGenericError proc jsonResponseWRoot*(t: typedesc[RestApiResponse], data: auto, @@ -568,6 +455,12 @@ proc writeValue*(writer: var JsonWriter[RestJson], value: GraffitiBytes) {. raises: [IOError, Defect].} = writeValue(writer, hexOriginal(distinctBase(value))) +proc parseRoot(value: string): Result[Eth2Digest, cstring] = + try: + ok(Eth2Digest(data: hexToByteArray[32](value))) + except ValueError: + err("Unable to decode root value") + proc decodeBody*[T](t: typedesc[T], body: ContentBody): Result[T, cstring] = if body.contentType != "application/json": @@ -620,12 +513,10 @@ proc decodeBytes*[T: DecodeTypes](t: typedesc[T], value: openarray[byte], contentType: string): RestResult[T] = case contentType of "application/json": - let res = - try: - RestJson.decode(value, T) - except SerializationError: - return err("Serialization error") - ok(res) + try: + ok RestJson.decode(value, T) + except SerializationError as exc: + err("Serialization error") else: err("Content-Type not supported") @@ -667,3 +558,252 @@ proc encodeString*(value: StateIdent): RestResult[string] = ok("finalized") of StateIdentType.Justified: ok("justified") + +proc encodeString*(value: BlockIdent): RestResult[string] = + case value.kind + of BlockQueryKind.Slot: + ok(Base10.toString(uint64(value.slot))) + of BlockQueryKind.Root: + ok(hexOriginal(value.root.data)) + of BlockQueryKind.Named: + case value.value + of BlockIdentType.Head: + ok("head") + of BlockIdentType.Genesis: + ok("genesis") + of BlockIdentType.Finalized: + ok("finalized") + +proc decodeString*(t: typedesc[PeerStateKind], + value: string): Result[PeerStateKind, cstring] = + case value + of "disconnected": + ok(PeerStateKind.Disconnected) + of "connecting": + ok(PeerStateKind.Connecting) + of "connected": + ok(PeerStateKind.Connected) + of "disconnecting": + ok(PeerStateKind.Disconnecting) + else: + err("Incorrect peer's state value") + +proc encodeString*(value: PeerStateKind): Result[string, cstring] = + case value + of PeerStateKind.Disconnected: + ok("disconnected") + of PeerStateKind.Connecting: + ok("connecting") + of PeerStateKind.Connected: + ok("connected") + of PeerStateKind.Disconnecting: + ok("disconnecting") + +proc decodeString*(t: typedesc[PeerDirectKind], + value: string): Result[PeerDirectKind, cstring] = + case value + of "inbound": + ok(PeerDirectKind.Inbound) + of "outbound": + ok(PeerDirectKind.Outbound) + else: + err("Incorrect peer's direction value") + +proc encodeString*(value: PeerDirectKind): Result[string, cstring] = + case value + of PeerDirectKind.Inbound: + ok("inbound") + of PeerDirectKind.Outbound: + ok("outbound") + +proc encodeString*(peerid: PeerID): Result[string, cstring] = + ok($peerid) + +proc decodeString*(t: typedesc[EventTopic], + value: string): Result[EventTopic, cstring] = + case value + of "head": + ok(EventTopic.Head) + of "block": + ok(EventTopic.Block) + of "attestation": + ok(EventTopic.Attestation) + of "voluntary_exit": + ok(EventTopic.VoluntaryExit) + of "finalized_checkpoint": + ok(EventTopic.FinalizedCheckpoint) + of "chain_reorg": + ok(EventTopic.ChainReorg) + else: + err("Incorrect event's topic value") + +proc decodeString*(t: typedesc[ValidatorSig], + value: string): Result[ValidatorSig, cstring] = + if len(value) != ValidatorSigSize + 2: + return err("Incorrect validator signature value length") + if value[0] != '0' and value[1] != 'x': + return err("Incorrect validator signature encoding") + ValidatorSig.fromHex(value) + +proc decodeString*(t: typedesc[GraffitiBytes], + value: string): Result[GraffitiBytes, cstring] = + try: + ok(GraffitiBytes.init(value)) + except ValueError: + err("Unable to decode graffiti value") + +proc decodeString*(t: typedesc[string], + value: string): Result[string, cstring] = + ok(value) + +proc decodeString*(t: typedesc[Slot], value: string): Result[Slot, cstring] = + let res = ? Base10.decode(uint64, value) + ok(Slot(res)) + +proc decodeString*(t: typedesc[Epoch], value: string): Result[Epoch, cstring] = + let res = ? Base10.decode(uint64, value) + ok(Epoch(res)) + +proc decodeString*(t: typedesc[StateIdent], + value: string): Result[StateIdent, cstring] = + if len(value) > 2: + if (value[0] == '0') and (value[1] == 'x'): + if len(value) != RootHashSize + 2: + err("Incorrect state root value length") + else: + let res = ? parseRoot(value) + ok(StateIdent(kind: StateQueryKind.Root, root: res)) + elif (value[0] in DecimalSet) and (value[1] in DecimalSet): + let res = ? Base10.decode(uint64, value) + ok(StateIdent(kind: StateQueryKind.Slot, slot: Slot(res))) + else: + case value + of "head": + ok(StateIdent(kind: StateQueryKind.Named, + value: StateIdentType.Head)) + of "genesis": + ok(StateIdent(kind: StateQueryKind.Named, + value: StateIdentType.Genesis)) + of "finalized": + ok(StateIdent(kind: StateQueryKind.Named, + value: StateIdentType.Finalized)) + of "justified": + ok(StateIdent(kind: StateQueryKind.Named, + value: StateIdentType.Justified)) + else: + err("Incorrect state identifier value") + else: + let res = ? Base10.decode(uint64, value) + ok(StateIdent(kind: StateQueryKind.Slot, slot: Slot(res))) + +proc decodeString*(t: typedesc[BlockIdent], + value: string): Result[BlockIdent, cstring] = + if len(value) > 2: + if (value[0] == '0') and (value[1] == 'x'): + if len(value) != RootHashSize + 2: + err("Incorrect block root value length") + else: + let res = ? parseRoot(value) + ok(BlockIdent(kind: BlockQueryKind.Root, root: res)) + elif (value[0] in DecimalSet) and (value[1] in DecimalSet): + let res = ? Base10.decode(uint64, value) + ok(BlockIdent(kind: BlockQueryKind.Slot, slot: Slot(res))) + else: + case value + of "head": + ok(BlockIdent(kind: BlockQueryKind.Named, + value: BlockIdentType.Head)) + of "genesis": + ok(BlockIdent(kind: BlockQueryKind.Named, + value: BlockIdentType.Genesis)) + of "finalized": + ok(BlockIdent(kind: BlockQueryKind.Named, + value: BlockIdentType.Finalized)) + else: + err("Incorrect block identifier value") + else: + let res = ? Base10.decode(uint64, value) + ok(BlockIdent(kind: BlockQueryKind.Slot, slot: Slot(res))) + +proc decodeString*(t: typedesc[ValidatorIdent], + value: string): Result[ValidatorIdent, cstring] = + if len(value) > 2: + if (value[0] == '0') and (value[1] == 'x'): + if len(value) != ValidatorKeySize + 2: + err("Incorrect validator's key value length") + else: + let res = ? ValidatorPubKey.fromHex(value) + ok(ValidatorIdent(kind: ValidatorQueryKind.Key, + key: res)) + elif (value[0] in DecimalSet) and (value[1] in DecimalSet): + let res = ? Base10.decode(uint64, value) + ok(ValidatorIdent(kind: ValidatorQueryKind.Index, + index: RestValidatorIndex(res))) + else: + err("Incorrect validator identifier value") + else: + let res = ? Base10.decode(uint64, value) + ok(ValidatorIdent(kind: ValidatorQueryKind.Index, + index: RestValidatorIndex(res))) + +proc decodeString*(t: typedesc[PeerID], + value: string): Result[PeerID, cstring] = + PeerID.init(value) + +proc decodeString*(t: typedesc[CommitteeIndex], + value: string): Result[CommitteeIndex, cstring] = + let res = ? Base10.decode(uint64, value) + ok(CommitteeIndex(res)) + +proc decodeString*(t: typedesc[Eth2Digest], + value: string): Result[Eth2Digest, cstring] = + if len(value) != RootHashSize + 2: + return err("Incorrect root value length") + if value[0] != '0' and value[1] != 'x': + return err("Incorrect root value encoding") + parseRoot(value) + +proc decodeString*(t: typedesc[ValidatorFilter], + value: string): Result[ValidatorFilter, cstring] = + case value + of "pending_initialized": + ok({ValidatorFilterKind.PendingInitialized}) + of "pending_queued": + ok({ValidatorFilterKind.PendingQueued}) + of "active_ongoing": + ok({ValidatorFilterKind.ActiveOngoing}) + of "active_exiting": + ok({ValidatorFilterKind.ActiveExiting}) + of "active_slashed": + ok({ValidatorFilterKind.ActiveSlashed}) + of "exited_unslashed": + ok({ValidatorFilterKind.ExitedUnslashed}) + of "exited_slashed": + ok({ValidatorFilterKind.ExitedSlashed}) + of "withdrawal_possible": + ok({ValidatorFilterKind.WithdrawalPossible}) + of "withdrawal_done": + ok({ValidatorFilterKind.WithdrawalDone}) + of "pending": + ok({ + ValidatorFilterKind.PendingInitialized, + ValidatorFilterKind.PendingQueued + }) + of "active": + ok({ + ValidatorFilterKind.ActiveOngoing, + ValidatorFilterKind.ActiveExiting, + ValidatorFilterKind.ActiveSlashed + }) + of "exited": + ok({ + ValidatorFilterKind.ExitedUnslashed, + ValidatorFilterKind.ExitedSlashed + }) + of "withdrawal": + ok({ + ValidatorFilterKind.WithdrawalPossible, + ValidatorFilterKind.WithdrawalDone + }) + else: + err("Incorrect validator state identifier value") diff --git a/beacon_chain/spec/eth2_apis/node_callsigs.nim b/beacon_chain/spec/eth2_apis/node_callsigs.nim deleted file mode 100644 index 286e3bddb..000000000 --- a/beacon_chain/spec/eth2_apis/node_callsigs.nim +++ /dev/null @@ -1,11 +0,0 @@ -import - options, - callsigs_types - -proc get_v1_node_identity(): NodeIdentityTuple -proc get_v1_node_version(): JsonNode -proc get_v1_node_syncing(): SyncInfo -proc get_v1_node_health(): JsonNode - -proc get_v1_node_peers(state: Option[seq[string]], - direction: Option[seq[string]]): seq[NodePeerTuple] diff --git a/beacon_chain/spec/eth2_apis/rest_beacon_calls.nim b/beacon_chain/spec/eth2_apis/rest_beacon_calls.nim new file mode 100644 index 000000000..95f3a7359 --- /dev/null +++ b/beacon_chain/spec/eth2_apis/rest_beacon_calls.nim @@ -0,0 +1,155 @@ +# Copyright (c) 2018-2021 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.push raises: [Defect].} + +import + presto/client, + ../datatypes/[phase0, altair], + "."/[rest_types, eth2_rest_serialization] + +export client, rest_types, eth2_rest_serialization + +proc getGenesis*(): RestResponse[GetGenesisResponse] {. + rest, endpoint: "/eth/v1/beacon/genesis", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getGenesis + +proc getStateRoot*(state_id: StateIdent): RestResponse[GetStateRootResponse] {. + rest, endpoint: "/eth/v1/beacon/states/{state_id}/root", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getStateRoot + +proc getStateFork*(state_id: StateIdent): RestResponse[GetStateForkResponse] {. + rest, endpoint: "/eth/v1/beacon/states/{state_id}/fork", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getStateFork + +proc getStateFinalityCheckpoints*(state_id: StateIdent + ): RestResponse[GetStateFinalityCheckpointsResponse] {. + rest, endpoint: "/api/eth/v1/beacon/states/{state_id}/finality_checkpoints", + meth: MethodGet.} + +proc getStateValidators*(state_id: StateIdent, + id: seq[ValidatorIdent] + ): RestResponse[GetStateValidatorsResponse] {. + rest, endpoint: "/eth/v1/beacon/states/{state_id}/validators", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getStateValidators + +proc getStateValidator*(state_id: StateIdent, + validator_id: ValidatorIdent + ): RestResponse[GetStateValidatorResponse] {. + rest, + endpoint: "/eth/v1/beacon/states/{state_id}/validators/{validator_id}", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getStateValidator + +proc getStateValidatorBalances*(state_id: StateIdent + ): RestResponse[GetStateValidatorBalancesResponse] {. + rest, endpoint: "/eth/v1/beacon/states/{state_id}/validator_balances", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getStateValidators + +proc getEpochCommittees*(state_id: StateIdent + ): RestResponse[GetEpochCommitteesResponse] {. + rest, endpoint: "/eth/v1/beacon/states/{state_id}/committees", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getEpochCommittees + +# TODO altair +# proc getEpochSyncCommittees*(state_id: StateIdent +# ): RestResponse[GetEpochSyncCommitteesResponse] {. +# rest, endpoint: "/eth/v1/beacon/states/{state_id}/sync_committees", +# meth: MethodGet.} +# ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getEpochSyncCommittees + +proc getBlockHeaders*(slot: Option[Slot], parent_root: Option[Eth2Digest] + ): RestResponse[GetBlockHeadersResponse] {. + rest, endpoint: "/api/eth/v1/beacon/headers", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getBlockHeaders + +proc getBlockHeader*(block_id: BlockIdent): RestResponse[GetBlockHeaderResponse] {. + rest, endpoint: "/api/eth/v1/beacon/headers/{block_id}", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getBlockHeader + +proc publishBlock*(body: phase0.SignedBeaconBlock): RestPlainResponse {. + rest, endpoint: "/eth/v1/beacon/blocks", + meth: MethodPost.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/publishBlock + +proc getBlock*(block_id: BlockIdent): RestResponse[GetBlockResponse] {. + rest, endpoint: "/api/eth/v1/beacon/blocks/{block_id}", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getBlock + +# TODO altair +# proc getBlockV2*(block_id: BlockIdent): RestResponse[GetBlockV2Response] {. +# rest, endpoint: "/api/eth/v2/beacon/blocks/{block_id}", +# meth: MethodGet.} +# ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getBlockV2 + +proc getBlockRoot*(block_id: BlockIdent): RestResponse[GetBlockRootResponse] {. + rest, endpoint: "/eth/v1/beacon/blocks/{block_id}/root", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getBlockRoot + +proc getBlockAttestations*(block_id: BlockIdent + ): RestResponse[GetBlockAttestationsResponse] {. + rest, endpoint: "/eth/v1/beacon/blocks/{block_id}/attestations", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getBlockAttestations + +proc getPoolAttestations*( + slot: Option[Slot], + committee_index: Option[CommitteeIndex] + ): RestResponse[GetPoolAttestationsResponse] {. + rest, endpoint: "/api/eth/v1/beacon/pool/attestations", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getPoolAttestations + +proc submitPoolAttestations*(body: seq[Attestation]): RestPlainResponse {. + rest, endpoint: "/eth/v1/beacon/pool/attestations", + meth: MethodPost.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/submitPoolAttestations + +proc getPoolAttesterSlashings*(): RestResponse[GetPoolAttesterSlashingsResponse] {. + rest, endpoint: "/api/eth/v1/beacon/pool/attester_slashings", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getPoolAttesterSlashings + +proc submitPoolAttesterSlashings*(body: AttesterSlashing): RestPlainResponse {. + rest, endpoint: "/api/eth/v1/beacon/pool/attester_slashings", + meth: MethodPost.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/submitPoolAttesterSlashings + +proc getPoolProposerSlashings*(): RestResponse[GetPoolProposerSlashingsResponse] {. + rest, endpoint: "/api/eth/v1/beacon/pool/proposer_slashings", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getPoolProposerSlashings + +proc submitPoolProposerSlashings*(body: ProposerSlashing): RestPlainResponse {. + rest, endpoint: "/api/eth/v1/beacon/pool/proposer_slashings", + meth: MethodPost.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/submitPoolProposerSlashings + +# TODO Altair +# proc submitPoolSyncCommitteeSignatures*(body: seq[RestSyncCommitteeSignature]): RestPlainResponse {. +# rest, endpoint: "/eth/v1/beacon/pool/sync_committees", +# meth: MethodPost.} +# ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/submitPoolSyncCommitteeSignatures + +proc getPoolVoluntaryExits*(): RestResponse[GetPoolVoluntaryExitsResponse] {. + rest, endpoint: "/api/eth/v1/beacon/pool/voluntary_exits", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getPoolVoluntaryExits + +proc submitPoolVoluntaryExit*(body: SignedVoluntaryExit): RestPlainResponse {. + rest, endpoint: "/api/eth/v1/beacon/pool/voluntary_exits", + meth: MethodPost.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/submitPoolVoluntaryExit diff --git a/beacon_chain/spec/eth2_apis/rest_beacon_client.nim b/beacon_chain/spec/eth2_apis/rest_beacon_client.nim new file mode 100644 index 000000000..276128088 --- /dev/null +++ b/beacon_chain/spec/eth2_apis/rest_beacon_client.nim @@ -0,0 +1,19 @@ +# Copyright (c) 2018-2021 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.push raises: [Defect].} + +import + presto/client, + "."/[ + rest_beacon_calls, rest_config_calls, rest_debug_calls, + rest_node_calls, rest_validator_calls + ] + +export + client, + rest_beacon_calls, rest_config_calls, rest_debug_calls, + rest_node_calls, rest_validator_calls diff --git a/beacon_chain/spec/eth2_apis/rest_config_calls.nim b/beacon_chain/spec/eth2_apis/rest_config_calls.nim new file mode 100644 index 000000000..23a6fe3b7 --- /dev/null +++ b/beacon_chain/spec/eth2_apis/rest_config_calls.nim @@ -0,0 +1,25 @@ +# Copyright (c) 2018-2021 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.push raises: [Defect].} + +import + presto/client, + "."/[rest_types, eth2_rest_serialization] + +export client, rest_types, eth2_rest_serialization + +proc getForkSchedule*(): RestResponse[GetForkScheduleResponse] {. + rest, endpoint: "/eth/v1/config/fork_schedule", meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Config/getForkSchedule + +proc getSpec*(): RestResponse[GetSpecResponse] {. + rest, endpoint: "/eth/v1/config/spec", meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Config/getSpec + +proc getDepositContract*(): RestResponse[GetDepositContractResponse] {. + rest, endpoint: "/eth/v1/config/deposit_contract", meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Config/getDepositContract diff --git a/beacon_chain/spec/eth2_apis/rest_debug_calls.nim b/beacon_chain/spec/eth2_apis/rest_debug_calls.nim new file mode 100644 index 000000000..f9d5bec4b --- /dev/null +++ b/beacon_chain/spec/eth2_apis/rest_debug_calls.nim @@ -0,0 +1,29 @@ +# Copyright (c) 2018-2021 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.push raises: [Defect].} + +import + presto/client, + "."/[rest_types, eth2_rest_serialization] + +export client, rest_types, eth2_rest_serialization + +proc getState*(state_id: StateIdent): RestResponse[GetStateResponse] {. + rest, endpoint: "/eth/v1/debug/beacon/states/{state_id}", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getState + +# TODO altair +# proc getStateV2*(state_id: StateIdent): RestResponse[GetStateV2Response] {. +# rest, endpoint: "/eth/v2/debug/beacon/states/{state_id}", +# meth: MethodGet.} +# ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getState + +proc getDebugChainHeads*(): RestResponse[GetDebugChainHeadsResponse] {. + rest, endpoint: "/eth/v1/debug/beacon/heads", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Beacon/getDebugChainHeads diff --git a/beacon_chain/spec/eth2_apis/rest_node_calls.nim b/beacon_chain/spec/eth2_apis/rest_node_calls.nim new file mode 100644 index 000000000..6c0e1359d --- /dev/null +++ b/beacon_chain/spec/eth2_apis/rest_node_calls.nim @@ -0,0 +1,50 @@ +# Copyright (c) 2018-2021 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.push raises: [Defect].} + +import + presto/client, + "."/[rest_types, eth2_rest_serialization] + +export client, rest_types, eth2_rest_serialization + +proc getNetworkIdentity*(): RestResponse[GetNetworkIdentityResponse] {. + rest, endpoint: "/eth/v1/node/identity", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Node/getNetworkIdentity + +proc getPeers*( + state: seq[PeerStateKind], + direction: seq[PeerDirectKind]): RestResponse[GetPeersResponse] {. + rest, endpoint: "/eth/v1/node/peers", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Node/getPeers + +proc getPeer*(peer_id: PeerId): RestResponse[GetPeerResponse] {. + rest, endpoint: "/eth/v1/node/peers/{peer_id}", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Node/getPeer + +proc getPeerCount*(): RestResponse[GetPeerCountResponse] {. + rest, endpoint: "/eth/v1/node/peer_count", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Node/getPeerCount + +proc getNodeVersion*(): RestResponse[GetVersionResponse] {. + rest, endpoint: "/eth/v1/node/version", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Node/getNodeVersion + +proc getSyncingStatus*(): RestResponse[GetSyncingStatusResponse] {. + rest, endpoint: "/eth/v1/node/syncing", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Node/getSyncingStatus + +proc getHealth*(): RestPlainResponse {. + rest, endpoint: "/eth/v1/node/health", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Node/getHealth diff --git a/beacon_chain/spec/eth2_apis/rest_types.nim b/beacon_chain/spec/eth2_apis/rest_types.nim new file mode 100644 index 000000000..958f59ad5 --- /dev/null +++ b/beacon_chain/spec/eth2_apis/rest_types.nim @@ -0,0 +1,327 @@ +# beacon_chain +# Copyright (c) 2018-2021 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +# Types used by both client and server in the common REST API: +# https://ethereum.github.io/eth2.0-APIs/#/ +# Be mindful that changing these changes the serialization and deserialization +# in the API which may lead to incompatibilities between clients - tread +# carefully! + +{.push raises: [Defect].} + +import + std/json, + ".."/datatypes/[phase0, altair], + ".."/[crypto, digest] + +export phase0, altair, crypto, digest + +const + # https://github.com/ethereum/eth2.0-APIs/blob/master/apis/beacon/states/validator_balances.yaml#L17 + # https://github.com/ethereum/eth2.0-APIs/blob/master/apis/beacon/states/validators.yaml#L17 + MaximumValidatorIds* = 30 + +type + EventTopic* {.pure.} = enum + Head, Block, Attestation, VoluntaryExit, FinalizedCheckpoint, ChainReorg + + EventTopics* = set[EventTopic] + + RestValidatorIndex* = distinct uint64 + + ValidatorQueryKind* {.pure.} = enum + Index, Key + + ValidatorIdent* = object + case kind*: ValidatorQueryKind + of ValidatorQueryKind.Index: + index*: RestValidatorIndex + of ValidatorQueryKind.Key: + key*: ValidatorPubKey + + ValidatorFilterKind* {.pure.} = enum + PendingInitialized, PendingQueued, + ActiveOngoing, ActiveExiting, ActiveSlashed, + ExitedUnslashed, ExitedSlashed, + WithdrawalPossible, WithdrawalDone + + ValidatorFilter* = set[ValidatorFilterKind] + + StateQueryKind* {.pure.} = enum + Slot, Root, Named + + StateIdentType* {.pure.} = enum + Head, Genesis, Finalized, Justified + + StateIdent* = object + case kind*: StateQueryKind + of StateQueryKind.Slot: + slot*: Slot + of StateQueryKind.Root: + root*: Eth2Digest + of StateQueryKind.Named: + value*: StateIdentType + + BlockQueryKind* {.pure.} = enum + Slot, Root, Named + BlockIdentType* {.pure.} = enum + Head, Genesis, Finalized + + BlockIdent* = object + case kind*: BlockQueryKind + of BlockQueryKind.Slot: + slot*: Slot + of BlockQueryKind.Root: + root*: Eth2Digest + of BlockQueryKind.Named: + value*: BlockIdentType + + PeerStateKind* {.pure.} = enum + Disconnected, Connecting, Connected, Disconnecting + + PeerDirectKind* {.pure.} = enum + Inbound, Outbound + + RestAttesterDuty* = object + pubkey*: ValidatorPubKey + validator_index*: ValidatorIndex + committee_index*: CommitteeIndex + committee_length*: uint64 + committees_at_slot*: uint64 + validator_committee_index*: ValidatorIndex + slot*: Slot + + RestProposerDuty* = object + pubkey*: ValidatorPubKey + validator_index*: ValidatorIndex + slot*: Slot + + RestCommitteeSubscription* = object + validator_index*: ValidatorIndex + committee_index*: CommitteeIndex + committees_at_slot*: uint64 + slot*: Slot + is_aggregator*: bool + + RestBeaconStatesFinalityCheckpoints* = object + previous_justified*: Checkpoint + current_justified*: Checkpoint + finalized*: Checkpoint + + RestGenesis* = object + genesis_time*: uint64 + genesis_validators_root*: Eth2Digest + genesis_fork_version*: Version + + RestValidatorBalance* = object + index*: ValidatorIndex + balance*: string + + RestBeaconStatesCommittees* = object + index*: CommitteeIndex + slot*: Slot + validators*: seq[ValidatorIndex] + + RestAttestationsFailure* = object + index*: uint64 + message*: string + + RestValidator* = object + index*: ValidatorIndex + balance*: string + status*: string + validator*: Validator + + RestBlockHeader* = object + slot*: Slot + proposer_index*: ValidatorIndex + parent_root*: Eth2Digest + state_root*: Eth2Digest + body_root*: Eth2Digest + + RestSignedBlockHeader* = object + message*: RestBlockHeader + signature*: ValidatorSig + + RestBlockHeaderInfo* = object + root*: Eth2Digest + canonical*: bool + header*: RestSignedBlockHeader + + RestNodePeer* = object + peer_id*: string + enr*: string + last_seen_p2p_address*: string + state*: string + direction*: string + agent*: string # This is not part of specification + proto*: string # This is not part of specification + + RestNodeVersion* = object + version*: string + + RestSyncInfo* = object + head_slot*: Slot + sync_distance*: uint64 + is_syncing*: bool + + RestPeerCount* = object + disconnected*: uint64 + connecting*: uint64 + connected*: uint64 + disconnecting*: uint64 + + RestChainHead* = object + root*: Eth2Digest + slot*: Slot + + RestMetadata* = object + seq_number*: string + attnets*: string + + RestNetworkIdentity* = object + peer_id*: string + enr*: string + p2p_addresses*: seq[string] + discovery_addresses*: seq[string] + metadata*: RestMetadata + + RestSpec* = object + CONFIG_NAME*: string + MAX_COMMITTEES_PER_SLOT*: uint64 + TARGET_COMMITTEE_SIZE*: uint64 + MAX_VALIDATORS_PER_COMMITTEE*: uint64 + MIN_PER_EPOCH_CHURN_LIMIT*: uint64 + CHURN_LIMIT_QUOTIENT*: uint64 + SHUFFLE_ROUND_COUNT*: uint64 + MIN_GENESIS_ACTIVE_VALIDATOR_COUNT*: uint64 + MIN_GENESIS_TIME*: uint64 + HYSTERESIS_QUOTIENT*: uint64 + HYSTERESIS_DOWNWARD_MULTIPLIER*: uint64 + HYSTERESIS_UPWARD_MULTIPLIER*: uint64 + SAFE_SLOTS_TO_UPDATE_JUSTIFIED*: uint64 + ETH1_FOLLOW_DISTANCE*: uint64 + TARGET_AGGREGATORS_PER_COMMITTEE*: uint64 + RANDOM_SUBNETS_PER_VALIDATOR*: uint64 + EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION*: uint64 + SECONDS_PER_ETH1_BLOCK*: uint64 + DEPOSIT_CHAIN_ID*: uint64 + DEPOSIT_NETWORK_ID*: uint64 + DEPOSIT_CONTRACT_ADDRESS*: Eth1Address + MIN_DEPOSIT_AMOUNT*: uint64 + MAX_EFFECTIVE_BALANCE*: uint64 + EJECTION_BALANCE*: uint64 + EFFECTIVE_BALANCE_INCREMENT*: uint64 + GENESIS_FORK_VERSION*: Version + BLS_WITHDRAWAL_PREFIX*: byte + GENESIS_DELAY*: uint64 + SECONDS_PER_SLOT*: uint64 + MIN_ATTESTATION_INCLUSION_DELAY*: uint64 + SLOTS_PER_EPOCH*: uint64 + MIN_SEED_LOOKAHEAD*: uint64 + MAX_SEED_LOOKAHEAD*: uint64 + EPOCHS_PER_ETH1_VOTING_PERIOD*: uint64 + SLOTS_PER_HISTORICAL_ROOT*: uint64 + MIN_VALIDATOR_WITHDRAWABILITY_DELAY*: uint64 + SHARD_COMMITTEE_PERIOD*: uint64 + MIN_EPOCHS_TO_INACTIVITY_PENALTY*: uint64 + EPOCHS_PER_HISTORICAL_VECTOR*: uint64 + EPOCHS_PER_SLASHINGS_VECTOR*: uint64 + HISTORICAL_ROOTS_LIMIT*: uint64 + VALIDATOR_REGISTRY_LIMIT*: uint64 + BASE_REWARD_FACTOR*: uint64 + WHISTLEBLOWER_REWARD_QUOTIENT*: uint64 + PROPOSER_REWARD_QUOTIENT*: uint64 + INACTIVITY_PENALTY_QUOTIENT*: uint64 + MIN_SLASHING_PENALTY_QUOTIENT*: uint64 + PROPORTIONAL_SLASHING_MULTIPLIER*: uint64 + MAX_PROPOSER_SLASHINGS*: uint64 + MAX_ATTESTER_SLASHINGS*: uint64 + MAX_ATTESTATIONS*: uint64 + MAX_DEPOSITS*: uint64 + MAX_VOLUNTARY_EXITS*: uint64 + DOMAIN_BEACON_PROPOSER*: DomainType + DOMAIN_BEACON_ATTESTER*: DomainType + DOMAIN_RANDAO*: DomainType + DOMAIN_DEPOSIT*: DomainType + DOMAIN_VOLUNTARY_EXIT*: DomainType + DOMAIN_SELECTION_PROOF*: DomainType + DOMAIN_AGGREGATE_AND_PROOF*: DomainType + + RestDepositContract* = object + chain_id*: string + address*: string + + DataEnclosedObject*[T] = object + data*: T + + DataMetaEnclosedObject*[T] = object + data*: T + meta*: JsonNode + + DataRootEnclosedObject*[T] = object + dependent_root*: Eth2Digest + data*: T + + # Types based on the OAPI yaml file - used in responses to requests + GetAggregatedAttestationResponse* = DataEnclosedObject[Attestation] + GetAttesterDutiesResponse* = DataRootEnclosedObject[seq[RestAttesterDuty]] + GetBlockAttestationsResponse* = DataEnclosedObject[seq[Attestation]] + GetBlockHeaderResponse* = DataEnclosedObject[RestBlockHeaderInfo] + GetBlockHeadersResponse* = DataEnclosedObject[seq[RestBlockHeaderInfo]] + GetBlockResponse* = DataEnclosedObject[phase0.SignedBeaconBlock] + GetBlockRootResponse* = DataEnclosedObject[Eth2Digest] + GetDebugChainHeadsResponse* = DataEnclosedObject[seq[RestChainHead]] + GetDepositContractResponse* = DataEnclosedObject[RestDepositContract] + GetEpochCommitteesResponse* = DataEnclosedObject[RestGenesis] + GetForkScheduleResponse* = DataEnclosedObject[Fork] + GetGenesisResponse* = DataEnclosedObject[RestGenesis] + GetNetworkIdentityResponse* = DataEnclosedObject[RestNetworkIdentity] + GetPeerCountResponse* = DataMetaEnclosedObject[RestPeerCount] + GetPeerResponse* = DataMetaEnclosedObject[RestNodePeer] + GetPeersResponse* = DataMetaEnclosedObject[seq[RestNodePeer]] + GetPoolAttestationsResponse* = DataEnclosedObject[seq[Attestation]] + GetPoolAttesterSlashingsResponse* = DataEnclosedObject[seq[AttesterSlashing]] + GetPoolProposerSlashingsResponse* = DataEnclosedObject[seq[ProposerSlashing]] + GetPoolVoluntaryExitsResponse* = DataEnclosedObject[seq[SignedVoluntaryExit]] + GetProposerDutiesResponse* = DataRootEnclosedObject[seq[RestProposerDuty]] + GetSpecResponse* = DataEnclosedObject[RestSpec] + GetStateFinalityCheckpointsResponse* = DataEnclosedObject[RestBeaconStatesFinalityCheckpoints] + GetStateForkResponse* = DataEnclosedObject[Fork] + GetStateResponse* = DataEnclosedObject[phase0.BeaconState] + GetStateRootResponse* = DataEnclosedObject[Eth2Digest] + GetStateValidatorBalancesResponse* = DataEnclosedObject[seq[RestValidatorBalance]] + GetStateValidatorResponse* = DataEnclosedObject[RestValidator] + GetStateValidatorsResponse* = DataEnclosedObject[seq[RestValidator]] + GetSyncingStatusResponse* = DataEnclosedObject[RestSyncInfo] + GetVersionResponse* = DataEnclosedObject[RestNodeVersion] + ProduceAttestationDataResponse* = DataEnclosedObject[AttestationData] + ProduceBlockResponse* = DataEnclosedObject[phase0.BeaconBlock] + +func init*(t: typedesc[StateIdent], v: StateIdentType): StateIdent = + StateIdent(kind: StateQueryKind.Named, value: v) + +func init*(t: typedesc[StateIdent], v: Slot): StateIdent = + StateIdent(kind: StateQueryKind.Slot, slot: v) + +func init*(t: typedesc[StateIdent], v: Eth2Digest): StateIdent = + StateIdent(kind: StateQueryKind.Root, root: v) + +func init*(t: typedesc[BlockIdent], v: BlockIdentType): BlockIdent = + BlockIdent(kind: BlockQueryKind.Named, value: v) + +func init*(t: typedesc[BlockIdent], v: Slot): BlockIdent = + BlockIdent(kind: BlockQueryKind.Slot, slot: v) + +func init*(t: typedesc[BlockIdent], v: Eth2Digest): BlockIdent = + BlockIdent(kind: BlockQueryKind.Root, root: v) + +func init*(t: typedesc[ValidatorIdent], v: ValidatorIndex): ValidatorIdent = + ValidatorIdent(kind: ValidatorQueryKind.Index, index: RestValidatorIndex(v)) + +func init*(t: typedesc[ValidatorIdent], v: ValidatorPubKey): ValidatorIdent = + ValidatorIdent(kind: ValidatorQueryKind.Key, key: v) diff --git a/beacon_chain/spec/eth2_apis/rest_validator_calls.nim b/beacon_chain/spec/eth2_apis/rest_validator_calls.nim new file mode 100644 index 000000000..e74b3bdf0 --- /dev/null +++ b/beacon_chain/spec/eth2_apis/rest_validator_calls.nim @@ -0,0 +1,89 @@ +# Copyright (c) 2018-2021 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.push raises: [Defect].} + +import + presto/client, + "."/[rest_types, eth2_rest_serialization] + +export client, rest_types, eth2_rest_serialization + +proc getAttesterDuties*(epoch: Epoch, + body: seq[ValidatorIndex] + ): RestResponse[GetAttesterDutiesResponse] {. + rest, endpoint: "/eth/v1/validator/duties/attester/{epoch}", + meth: MethodPost.} + ## https://ethereum.github.io/eth2.0-APIs/#/Validator/getAttesterDuties + +proc getProposerDuties*(epoch: Epoch): RestResponse[GetProposerDutiesResponse] {. + rest, endpoint: "/eth/v1/validator/duties/proposer/{epoch}", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Validator/getProposerDuties + +# TODO altair +# proc getSyncCommitteeDuties*(epoch: Epoch): RestResponse[DataRestSyncCommitteeDuties] {. +# rest, endpoint: "/eth/v1/validator/duties/sync/{epoch}", +# meth: MethodPost.} +# ## https://ethereum.github.io/eth2.0-APIs/#/Validator/getSyncCommitteeDuties + +proc produceBlock*(slot: Slot, randao_reveal: ValidatorSig, + graffiti: GraffitiBytes + ): RestResponse[ProduceBlockResponse] {. + rest, endpoint: "/eth/v1/validator/blocks/{slot}", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Validator/produceBlock + +# TODO altair +# proc produceBlockV2*(slot: Slot, randao_reveal: ValidatorSig, +# graffiti: GraffitiBytes +# ): RestResponse[DataRestBlockV2] {. +# rest, endpoint: "/eth/v2/validator/blocks/{slot}", +# meth: MethodGet.} +# ## https://ethereum.github.io/eth2.0-APIs/#/Validator/produceBlockV2 + +proc produceAttestationData*(slot: Slot, + committee_index: CommitteeIndex + ): RestResponse[ProduceAttestationDataResponse] {. + rest, endpoint: "/eth/v1/validator/attestation_data", + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Validator/produceAttestationData + +proc getAggregatedAttestation*(attestation_data_root: Eth2Digest, + slot: Slot): RestResponse[GetAggregatedAttestationResponse] {. + rest, endpoint: "/eth/v1/validator/aggregate_attestation" + meth: MethodGet.} + ## https://ethereum.github.io/eth2.0-APIs/#/Validator/getAggregatedAttestation + +proc publishAggregateAndProofs*(body: seq[SignedAggregateAndProof] + ): RestPlainResponse {. + rest, endpoint: "/eth/v1/validator/aggregate_and_proofs", + meth: MethodPost.} + ## https://ethereum.github.io/eth2.0-APIs/#/Validator/publishAggregateAndProofs + +proc prepareBeaconCommitteeSubnet*(body: seq[RestCommitteeSubscription]): RestPlainResponse {. + rest, endpoint: "/eth/v1/validator/beacon_committee_subscriptions", + meth: MethodPost.} + ## https://ethereum.github.io/eth2.0-APIs/#/Validator/prepareBeaconCommitteeSubnet + +# TODO altair +# proc prepareSyncCommitteeSubnets*(body: seq[int] +# ): RestPlainResponse {. +# rest, endpoint: "/eth/v1/validator/sync_committee_subscriptions", +# meth: MethodPost.} +# ## https://ethereum.github.io/eth2.0-APIs/#/Validator/prepareSyncCommitteeSubnets + +# proc produceSyncCommitteeContribution*(body: seq[int] +# ): RestPlainResponse {. +# rest, endpoint: "/eth/v1/validator/sync_committee_contribution", +# meth: MethodPost.} +# ## https://ethereum.github.io/eth2.0-APIs/#/Validator/produceSyncCommitteeContribution + +# proc publishContributionAndProofs*(body: seq[RestCommitteeSubscription] +# ): RestPlainResponse {. +# rest, endpoint: "/eth/v1/validator/contribution_and_proofs", +# meth: MethodPost.} +# ## https://ethereum.github.io/eth2.0-APIs/#/Validator/publishContributionAndProofs diff --git a/beacon_chain/spec/eth2_apis/beacon_callsigs.nim b/beacon_chain/spec/eth2_apis/rpc_beacon_calls.nim similarity index 81% rename from beacon_chain/spec/eth2_apis/beacon_callsigs.nim rename to beacon_chain/spec/eth2_apis/rpc_beacon_calls.nim index 789cce519..ba85e68c1 100644 --- a/beacon_chain/spec/eth2_apis/beacon_callsigs.nim +++ b/beacon_chain/spec/eth2_apis/rpc_beacon_calls.nim @@ -1,8 +1,8 @@ import options, - callsigs_types + rpc_types -proc get_v1_beacon_genesis(): BeaconGenesisTuple +proc get_v1_beacon_genesis(): RpcBeaconGenesis # TODO stateId is part of the REST path proc get_v1_beacon_states_root(stateId: string): Eth2Digest @@ -12,22 +12,22 @@ proc get_v1_beacon_states_fork(stateId: string): Fork # TODO stateId is part of the REST path proc get_v1_beacon_states_finality_checkpoints( - stateId: string): BeaconStatesFinalityCheckpointsTuple + stateId: string): RpcBeaconStatesFinalityCheckpoints # TODO stateId is part of the REST path proc get_v1_beacon_states_stateId_validators( stateId: string, validatorIds: seq[string], - status: string): seq[BeaconStatesValidatorsTuple] + status: string): seq[RpcBeaconStatesValidators] # TODO stateId and validatorId are part of the REST path proc get_v1_beacon_states_stateId_validators_validatorId( - stateId: string, validatorId: string): BeaconStatesValidatorsTuple + stateId: string, validatorId: string): RpcBeaconStatesValidators # TODO stateId and epoch are part of the REST path proc get_v1_beacon_states_stateId_committees_epoch(stateId: string, - epoch: uint64, index: uint64, slot: uint64): seq[BeaconStatesCommitteesTuple] + epoch: uint64, index: uint64, slot: uint64): seq[RpcBeaconStatesCommittees] -proc get_v1_beacon_headers(slot: uint64, parent_root: Eth2Digest): seq[BeaconHeadersTuple] +proc get_v1_beacon_headers(slot: uint64, parent_root: Eth2Digest): seq[RpcBeaconHeaders] # TODO blockId is part of the REST path proc get_v1_beacon_headers_blockId(blockId: string): @@ -45,7 +45,7 @@ proc get_v1_beacon_blocks_blockId_attestations(blockId: string): seq[Attestation # TODO POST /v1/beacon/pool/attester_slashings # TODO POST /v1/beacon/pool/proposer_slashings # TODO POST /v1/beacon/pool/attestations -proc get_v1_beacon_pool_attestations(slot: Option[uint64], committee_index: Option[uint64]): seq[AttestationTuple] +proc get_v1_beacon_pool_attestations(slot: Option[uint64], committee_index: Option[uint64]): seq[RpcAttestation] proc post_v1_beacon_pool_attestations(attestation: Attestation): bool proc get_v1_beacon_pool_attester_slashings(): seq[AttesterSlashing] diff --git a/beacon_chain/spec/eth2_apis/rpc_beacon_client.nim b/beacon_chain/spec/eth2_apis/rpc_beacon_client.nim new file mode 100644 index 000000000..aaf5b02f0 --- /dev/null +++ b/beacon_chain/spec/eth2_apis/rpc_beacon_client.nim @@ -0,0 +1,15 @@ +import + std/os, + json_rpc/rpcclient, + "."/[rpc_types, eth2_json_rpc_serialization] + +export + rpcclient, + rpc_types, + eth2_json_rpc_serialization + +createRpcSigs(RpcClient, currentSourcePath.parentDir / "rpc_beacon_calls.nim") +createRpcSigs(RpcClient, currentSourcePath.parentDir / "rpc_debug_calls.nim") +createRpcSigs(RpcClient, currentSourcePath.parentDir / "rpc_nimbus_calls.nim") +createRpcSigs(RpcClient, currentSourcePath.parentDir / "rpc_node_calls.nim") +createRpcSigs(RpcClient, currentSourcePath.parentDir / "rpc_validator_calls.nim") diff --git a/beacon_chain/spec/eth2_apis/debug_callsigs.nim b/beacon_chain/spec/eth2_apis/rpc_debug_calls.nim similarity index 79% rename from beacon_chain/spec/eth2_apis/debug_callsigs.nim rename to beacon_chain/spec/eth2_apis/rpc_debug_calls.nim index 362e9bff2..adf2f5785 100644 --- a/beacon_chain/spec/eth2_apis/debug_callsigs.nim +++ b/beacon_chain/spec/eth2_apis/rpc_debug_calls.nim @@ -1,7 +1,7 @@ import - callsigs_types + rpc_types -export callsigs_types +export rpc_types proc get_v1_debug_beacon_states_stateId(stateId: string): BeaconState proc get_v1_debug_beacon_heads(): seq[tuple[root: Eth2Digest, slot: Slot]] diff --git a/beacon_chain/spec/eth2_apis/nimbus_callsigs.nim b/beacon_chain/spec/eth2_apis/rpc_nimbus_calls.nim similarity index 90% rename from beacon_chain/spec/eth2_apis/nimbus_callsigs.nim rename to beacon_chain/spec/eth2_apis/rpc_nimbus_calls.nim index da7684a8b..acb664915 100644 --- a/beacon_chain/spec/eth2_apis/nimbus_callsigs.nim +++ b/beacon_chain/spec/eth2_apis/rpc_nimbus_calls.nim @@ -1,7 +1,7 @@ import - callsigs_types + rpc_types -export callsigs_types +export rpc_types proc getBeaconHead(): Slot proc getChainHead(): JsonNode diff --git a/beacon_chain/spec/eth2_apis/rpc_node_calls.nim b/beacon_chain/spec/eth2_apis/rpc_node_calls.nim new file mode 100644 index 000000000..f75761c8c --- /dev/null +++ b/beacon_chain/spec/eth2_apis/rpc_node_calls.nim @@ -0,0 +1,11 @@ +import + options, + rpc_types + +proc get_v1_node_identity(): RpcNodeIdentity +proc get_v1_node_version(): JsonNode +proc get_v1_node_syncing(): RpcSyncInfo +proc get_v1_node_health(): JsonNode + +proc get_v1_node_peers(state: Option[seq[string]], + direction: Option[seq[string]]): seq[RpcNodePeer] diff --git a/beacon_chain/spec/eth2_apis/callsigs_types.nim b/beacon_chain/spec/eth2_apis/rpc_types.nim similarity index 60% rename from beacon_chain/spec/eth2_apis/callsigs_types.nim rename to beacon_chain/spec/eth2_apis/rpc_types.nim index ecfea61e4..05c203400 100644 --- a/beacon_chain/spec/eth2_apis/callsigs_types.nim +++ b/beacon_chain/spec/eth2_apis/rpc_types.nim @@ -1,3 +1,15 @@ +# beacon_chain +# Copyright (c) 2018-2021 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +# Types used in the JSON-RPC (legacy) API - these are generally derived from +# the common REST API, https://ethereum.github.io/eth2.0-APIs/#/ + +{.push raises: [Defect].} + import ".."/datatypes/base, ".."/[digest, crypto] @@ -5,7 +17,7 @@ import export base, crypto, digest type - AttesterDuties* = tuple + RpcAttesterDuties* = tuple public_key: ValidatorPubKey validator_index: ValidatorIndex committee_index: CommitteeIndex @@ -13,45 +25,45 @@ type validator_committee_index: uint64 slot: Slot - ValidatorDutiesTuple* = tuple + RpcValidatorDuties* = tuple public_key: ValidatorPubKey validator_index: ValidatorIndex slot: Slot - BeaconGenesisTuple* = tuple + RpcBeaconGenesis* = tuple genesis_time: uint64 genesis_validators_root: Eth2Digest genesis_fork_version: Version - BeaconStatesFinalityCheckpointsTuple* = tuple + RpcBeaconStatesFinalityCheckpoints* = tuple previous_justified: Checkpoint current_justified: Checkpoint finalized: Checkpoint - BeaconStatesValidatorsTuple* = tuple + RpcBeaconStatesValidators* = tuple validator: Validator index: uint64 status: string balance: uint64 - BeaconStatesCommitteesTuple* = tuple + RpcBeaconStatesCommittees* = tuple index: uint64 slot: uint64 validators: seq[uint64] # each object in the sequence should have an index field... - BeaconHeadersTuple* = tuple + RpcBeaconHeaders* = tuple root: Eth2Digest canonical: bool header: SignedBeaconBlockHeader - NodeIdentityTuple* = tuple + RpcNodeIdentity* = tuple peer_id: string enr: string p2p_addresses: seq[string] discovery_addresses: seq[string] metadata: tuple[seq_number: uint64, attnets: string] - NodePeerTuple* = tuple + RpcNodePeer* = tuple peer_id: string enr: string last_seen_p2p_address: string @@ -60,22 +72,22 @@ type agent: string # This is not part of specification proto: string # This is not part of specification - NodePeerCountTuple* = tuple + RpcNodePeerCount* = tuple disconnected: int connecting: int connected: int disconnecting: int - AttestationTuple* = tuple + RpcAttestation* = tuple aggregation_bits: string data: AttestationData signature: ValidatorSig - BalanceTuple* = tuple + RpcBalance* = tuple index: uint64 balance: uint64 - SyncInfo* = tuple + RpcSyncInfo* = tuple head_slot: Slot sync_distance: uint64 is_syncing: bool diff --git a/beacon_chain/spec/eth2_apis/validator_callsigs.nim b/beacon_chain/spec/eth2_apis/rpc_validator_calls.nim similarity index 89% rename from beacon_chain/spec/eth2_apis/validator_callsigs.nim rename to beacon_chain/spec/eth2_apis/rpc_validator_calls.nim index fcd33a302..f60101f3d 100644 --- a/beacon_chain/spec/eth2_apis/validator_callsigs.nim +++ b/beacon_chain/spec/eth2_apis/rpc_validator_calls.nim @@ -1,6 +1,6 @@ import options, - callsigs_types + rpc_types # calls that return a bool are actually without a return type in the main REST API # spec but nim-json-rpc requires that all RPC calls have a return type. @@ -16,10 +16,10 @@ proc get_v1_validator_aggregate_attestation(slot: Slot, attestation_data_root: E proc post_v1_validator_aggregate_and_proofs(payload: SignedAggregateAndProof): bool # TODO epoch is part of the REST path -proc get_v1_validator_duties_attester(epoch: Epoch, public_keys: seq[ValidatorPubKey]): seq[AttesterDuties] +proc get_v1_validator_duties_attester(epoch: Epoch, public_keys: seq[ValidatorPubKey]): seq[RpcAttesterDuties] # TODO epoch is part of the REST path -proc get_v1_validator_duties_proposer(epoch: Epoch): seq[ValidatorDutiesTuple] +proc get_v1_validator_duties_proposer(epoch: Epoch): seq[RpcValidatorDuties] proc post_v1_validator_beacon_committee_subscriptions(committee_index: CommitteeIndex, slot: Slot, diff --git a/beacon_chain/sync/sync_manager.nim b/beacon_chain/sync/sync_manager.nim index 80337795c..e2bea2669 100644 --- a/beacon_chain/sync/sync_manager.nim +++ b/beacon_chain/sync/sync_manager.nim @@ -10,7 +10,7 @@ import chronicles import options, deques, heapqueue, tables, strutils, sequtils, math, algorithm import stew/results, chronos, chronicles -import ../spec/[datatypes/phase0, datatypes/altair, digest, helpers, eth2_apis/callsigs_types, forkedbeaconstate_helpers], +import ../spec/[datatypes/phase0, datatypes/altair, digest, helpers, eth2_apis/rpc_types, forkedbeaconstate_helpers], ../networking/[peer_pool, eth2_network] import ../gossip_processing/block_processor @@ -1200,7 +1200,7 @@ proc start*[A, B](man: SyncManager[A, B]) = ## Starts SyncManager's main loop. man.syncFut = man.syncLoop() -proc getInfo*[A, B](man: SyncManager[A, B]): SyncInfo = +proc getInfo*[A, B](man: SyncManager[A, B]): RpcSyncInfo = ## Returns current synchronization information for RPC call. let wallSlot = man.getLocalWallSlot() let headSlot = man.getLocalHeadSlot() diff --git a/beacon_chain/validator_client/api.nim b/beacon_chain/validator_client/api.nim index 0799abedc..64661b844 100644 --- a/beacon_chain/validator_client/api.nim +++ b/beacon_chain/validator_client/api.nim @@ -1,4 +1,6 @@ -import common +import + ../spec/datatypes/[phase0, altair], + common type ApiResponse*[T] = Result[T, string] @@ -11,7 +13,7 @@ proc checkCompatible*(vc: ValidatorClientRef, let info = try: debug "Requesting beacon node network configuration" - let res = await node.client.getConfig() + let res = await node.client.getSpec() res.data.data except CancelledError as exc: error "Configuration request was interrupted" @@ -31,7 +33,7 @@ proc checkCompatible*(vc: ValidatorClientRef, let genesis = try: debug "Requesting beacon node genesis information" - let res = await node.client.getBeaconGenesis() + let res = await node.client.getGenesis() res.data.data except CancelledError as exc: error "Genesis request was interrupted" @@ -120,7 +122,7 @@ proc checkOnline*(node: BeaconNodeServerRef) {.async.} = debug "Checking beacon node status" let agent = try: - let res = await node.client.getVersion() + let res = await node.client.getNodeVersion() res.data.data except CancelledError as exc: error "Status request was interrupted" @@ -404,10 +406,10 @@ template firstSuccessTimeout*(vc: ValidatorClientRef, respType: typedesc, break proc getProposerDuties*(vc: ValidatorClientRef, - epoch: Epoch): Future[DataRestProposerDuties] {. + epoch: Epoch): Future[GetProposerDutiesResponse] {. async.} = logScope: request = "getProposerDuties" - vc.firstSuccessTimeout(RestResponse[DataRestProposerDuties], SlotDuration, + vc.firstSuccessTimeout(RestResponse[GetProposerDutiesResponse], SlotDuration, getProposerDuties(it, epoch)): if apiResponse.isErr(): debug "Unable to retrieve proposer duties", endpoint = node, @@ -440,9 +442,9 @@ proc getProposerDuties*(vc: ValidatorClientRef, proc getAttesterDuties*(vc: ValidatorClientRef, epoch: Epoch, validators: seq[ValidatorIndex] - ): Future[DataRestAttesterDuties] {.async.} = + ): Future[GetAttesterDutiesResponse] {.async.} = logScope: request = "getAttesterDuties" - vc.firstSuccessTimeout(RestResponse[DataRestAttesterDuties], SlotDuration, + vc.firstSuccessTimeout(RestResponse[GetAttesterDutiesResponse], SlotDuration, getAttesterDuties(it, epoch, validators)): if apiResponse.isErr(): debug "Unable to retrieve attester duties", endpoint = node, @@ -476,7 +478,7 @@ proc getAttesterDuties*(vc: ValidatorClientRef, epoch: Epoch, proc getHeadStateFork*(vc: ValidatorClientRef): Future[Fork] {.async.} = logScope: request = "getHeadStateFork" let stateIdent = StateIdent.init(StateIdentType.Head) - vc.firstSuccessTimeout(RestResponse[DataRestFork], SlotDuration, + vc.firstSuccessTimeout(RestResponse[GetStateForkResponse], SlotDuration, getStateFork(it, stateIdent)): if apiResponse.isErr(): debug "Unable to retrieve head state's fork", endpoint = node, @@ -508,7 +510,7 @@ proc getValidators*(vc: ValidatorClientRef, async.} = logScope: request = "getStateValidators" let stateIdent = StateIdent.init(StateIdentType.Head) - vc.firstSuccessTimeout(RestResponse[DataRestValidatorList], SlotDuration, + vc.firstSuccessTimeout(RestResponse[GetStateValidatorsResponse], SlotDuration, getStateValidators(it, stateIdent, id)): if apiResponse.isErr(): debug "Unable to retrieve head state's validator information", @@ -540,7 +542,7 @@ proc produceAttestationData*(vc: ValidatorClientRef, slot: Slot, committee_index: CommitteeIndex ): Future[AttestationData] {.async.} = logScope: request = "produceAttestationData" - vc.firstSuccessTimeout(RestResponse[DataRestAttestationData], + vc.firstSuccessTimeout(RestResponse[ProduceAttestationDataResponse], OneThirdDuration, produceAttestationData(it, slot, committee_index)): if apiResponse.isErr(): @@ -633,7 +635,7 @@ proc getAggregatedAttestation*(vc: ValidatorClientRef, slot: Slot, root: Eth2Digest): Future[Attestation] {. async.} = logScope: request = "getAggregatedAttestation" - vc.firstSuccessTimeout(RestResponse[DataRestAttestation], + vc.firstSuccessTimeout(RestResponse[GetAggregatedAttestationResponse], OneThirdDuration, getAggregatedAttestation(it, root, slot)): if apiResponse.isErr(): @@ -699,9 +701,9 @@ proc publishAggregateAndProofs*(vc: ValidatorClientRef, proc produceBlock*(vc: ValidatorClientRef, slot: Slot, randao_reveal: ValidatorSig, - graffiti: GraffitiBytes): Future[BeaconBlock] {.async.} = + graffiti: GraffitiBytes): Future[phase0.BeaconBlock] {.async.} = logScope: request = "produceBlock" - vc.firstSuccessTimeout(RestResponse[DataRestBeaconBlock], + vc.firstSuccessTimeout(RestResponse[ProduceBlockResponse], SlotDuration, produceBlock(it, slot, randao_reveal, graffiti)): if apiResponse.isErr(): @@ -734,7 +736,7 @@ proc produceBlock*(vc: ValidatorClientRef, slot: Slot, raise newException(ValidatorApiError, "Unable to retrieve block data") proc publishBlock*(vc: ValidatorClientRef, - data: SignedBeaconBlock): Future[bool] {.async.} = + data: phase0.SignedBeaconBlock): Future[bool] {.async.} = logScope: request = "publishBlock" vc.firstSuccessTimeout(RestPlainResponse, SlotDuration, publishBlock(it, data)): diff --git a/beacon_chain/validator_client/block_service.nim b/beacon_chain/validator_client/block_service.nim index b02b7d0d6..99791a794 100644 --- a/beacon_chain/validator_client/block_service.nim +++ b/beacon_chain/validator_client/block_service.nim @@ -1,3 +1,4 @@ +import ../spec/datatypes/[phase0, altair] import common, api import chronicles @@ -35,7 +36,7 @@ proc publishBlock(vc: ValidatorClientRef, currentSlot, slot: Slot, return let blockRoot = hash_tree_root(beaconBlock) - var signedBlock = SignedBeaconBlock(message: beaconBlock, + var signedBlock = phase0.SignedBeaconBlock(message: beaconBlock, root: hash_tree_root(beaconBlock)) # TODO: signing_root is recomputed in signBlockProposal just after @@ -49,7 +50,8 @@ proc publishBlock(vc: ValidatorClientRef, currentSlot, slot: Slot, if notSlashable.isOk(): let signature = await validator.signBlockProposal(fork, genesisRoot, slot, blockRoot) - let signedBlock = SignedBeaconBlock(message: beaconBlock, root: blockRoot, + let signedBlock = + phase0.SignedBeaconBlock(message: beaconBlock, root: blockRoot, signature: signature) let res = try: diff --git a/beacon_chain/validator_client/common.nim b/beacon_chain/validator_client/common.nim index 838a414ea..723882f76 100644 --- a/beacon_chain/validator_client/common.nim +++ b/beacon_chain/validator_client/common.nim @@ -1,26 +1,24 @@ import std/[tables, os, sequtils, strutils] import chronos, presto, presto/client as presto_client, chronicles, confutils, json_serialization/std/[options, net], - stew/[base10, results, byteutils] + stew/[base10, results, byteutils], + eth/db/[kvstore, kvstore_sqlite3] + # Local modules -import ".."/networking/[eth2_network, eth2_discovery], - ".."/spec/[datatypes, digest, crypto, helpers, signatures], - ".."/rpc/[beacon_rest_api, node_rest_api, validator_rest_api, - config_rest_api, rest_utils, eth2_json_rest_serialization], +import ".."/spec/[datatypes, digest, crypto, helpers, signatures], + ".."/spec/eth2_apis/rest_beacon_client, ".."/validators/[attestation_aggregation, keystore_management, validator_pool, slashing_protection], ".."/[conf, beacon_clock, version, beacon_node_types, nimbus_binary_common], - ".."/ssz/merkleization, - ./eth/db/[kvstore, kvstore_sqlite3] + ".."/ssz/merkleization export os, tables, sequtils, sequtils, chronos, presto, chronicles, confutils, nimbus_binary_common, version, conf, options, tables, results, base10, - byteutils, eth2_json_rest_serialization, presto_client + byteutils, presto_client -export beacon_rest_api, node_rest_api, validator_rest_api, config_rest_api, - rest_utils, - datatypes, crypto, digest, signatures, merkleization, +export rest_beacon_client, + datatypes, crypto, digest, helpers, signatures, merkleization, beacon_clock, kvstore, kvstore_sqlite3, keystore_management, slashing_protection, validator_pool, @@ -74,9 +72,9 @@ type BeaconNodeServer* = object client*: RestClientRef endpoint*: string - config*: Option[RestConfig] + config*: Option[RestSpec] ident*: Option[string] - genesis*: Option[RestBeaconGenesis] + genesis*: Option[RestGenesis] syncInfo*: Option[RestSyncInfo] status*: RestBeaconNodeStatus @@ -107,7 +105,7 @@ type fork*: Option[Fork] attesters*: AttesterMap proposers*: ProposerMap - beaconGenesis*: RestBeaconGenesis + beaconGenesis*: RestGenesis proposerTasks*: Table[Slot, seq[ProposerTask]] ValidatorClientRef* = ref ValidatorClient diff --git a/docs/the_nimbus_book/src/api.md b/docs/the_nimbus_book/src/api.md index 1043a2162..e101ea62b 100644 --- a/docs/the_nimbus_book/src/api.md +++ b/docs/the_nimbus_book/src/api.md @@ -1,8 +1,10 @@ # JSON-RPC API -`nimbus-eth2` exposes a collection of APIs for querying the state of the application at runtime. +The `JSON-RPC API` is a collection of APIs for querying the state of the application at runtime. -Where applicable, these APIs mimic the [eth2 APIs](https://github.com/ethereum/eth2.0-APIs) with the exception that `JSON-RPC` is used instead of [http `REST`](./rest-api.md) (the method names, parameters and results are all the same except for the encoding / access method). +The API is based on the common [eth2 APIs](https://github.com/ethereum/eth2.0-APIs) with the exception that `JSON-RPC` is used instead of [http `REST`](./rest-api.md) (the method names, parameters and results are all the same except for the encoding / access method). + +Nimbus also implements the [common REST API](./rest-api.md) - new applications should consider using it instead of JSON RPC. ## Introduction diff --git a/docs/the_nimbus_book/src/rest-api.md b/docs/the_nimbus_book/src/rest-api.md index 317cb9ac6..86ee8c8ed 100644 --- a/docs/the_nimbus_book/src/rest-api.md +++ b/docs/the_nimbus_book/src/rest-api.md @@ -1,6 +1,5 @@ # REST API +Nimbus supports the [common REST API](https://ethereum.github.io/eth2.0-APIs/#/) for runtime communication with the application. For historical reasons, a [JSON-RPC-based API](./api.md) is also supported. -The community has settled on REST as a common interface, as [documented here](https://ethereum.github.io/eth2.0-APIs/#/) -- the `REST` API is an updated version of the [`JSON-RPC` api](./api.md). - -If you're looking to use this more standard API, you can enable it by running the Beacon Node with the `--rest` parameter (note this is currently in Beta). +The REST API is currently in BETA -- to enable it, use the `--rest` option when starting the beacon node, then access the API from http://localhost:5052/.