REST API client, JSON-RPC cleanups (#2756)
This refactoring puts the JSON-RPC and REST APIs on more equal footing by renaming and moving things around, creating a separation between client and server, and documenting what they are - the aim is to have a simple-to-use base to start from when developing API clients, as well as make it easier to navigate the code when looking for the legacy JSON-RPC interface vs the new REST API. * move REST client, serialization and supporting types to spec/eth2_apis * REST stuff now starts with `rest_`, JSON-RPC stuff starts with `rpc_`, more or less * simplify imports such that there's a simple module to import for both server and client * map REST type and proc names to yaml spec more closely - in particular, reuse operation and type names in `rest_types` to make comparisons against spec more easy * cleaner separation between client and server modules - modules common between server and client such as `rest_types` and serialization move to the spec folder - this allows the client to be built with less knowledge about server internals
This commit is contained in:
parent
d638ca0c7f
commit
3d7bee8502
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -8,7 +8,7 @@ import
|
|||
stew/results,
|
||||
chronicles,
|
||||
presto,
|
||||
./eth2_json_rest_serialization, ./rest_utils,
|
||||
./rest_utils,
|
||||
../beacon_node_common
|
||||
|
||||
logScope: topics = "rest_eventapi"
|
|
@ -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,
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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():
|
|
@ -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"
|
||||
|
|
@ -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"
|
|
@ -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:
|
|
@ -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
|
||||
|
|
|
@ -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)
|
|
@ -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")
|
|
@ -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
|
||||
|
|
@ -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")
|
|
@ -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]
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
|
@ -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]
|
|
@ -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")
|
|
@ -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]]
|
|
@ -1,7 +1,7 @@
|
|||
import
|
||||
callsigs_types
|
||||
rpc_types
|
||||
|
||||
export callsigs_types
|
||||
export rpc_types
|
||||
|
||||
proc getBeaconHead(): Slot
|
||||
proc getChainHead(): JsonNode
|
|
@ -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]
|
|
@ -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
|
|
@ -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,
|
|
@ -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()
|
||||
|
|
|
@ -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)):
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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/.
|
||||
|
|
Loading…
Reference in New Issue