From 77e2f576af49c191425f85d285cae39fbb4a4344 Mon Sep 17 00:00:00 2001 From: Luke Anderson Date: Wed, 28 Aug 2019 21:25:38 +1000 Subject: [PATCH] Further aligning the API & implementation. - Completed implementation of /beacon/head - renamed 'latest_finalized_checkpoint' to 'current_finalized_checkpoint' for consistency - Reorganised list of endpoints in both spec & router so that they match - Fixed the content-type modifications for /metrics - Added a new 'RFC' tag to the spec, to tag things that we have not implemented and aren't sure if it's useful. - Moved 'deposit_contract' under /spec --- beacon_node/rest_api/src/beacon.rs | 35 +++++-- beacon_node/rest_api/src/lib.rs | 27 +++-- beacon_node/rest_api/src/metrics.rs | 9 +- docs/rest_oapi.yaml | 154 ++++++++++++++-------------- 4 files changed, 128 insertions(+), 97 deletions(-) diff --git a/beacon_node/rest_api/src/beacon.rs b/beacon_node/rest_api/src/beacon.rs index fb8386661..b489f1fe7 100644 --- a/beacon_node/rest_api/src/beacon.rs +++ b/beacon_node/rest_api/src/beacon.rs @@ -12,11 +12,12 @@ pub struct HeadResponse { pub slot: Slot, pub block_root: Hash256, pub state_root: Hash256, - /* Not implemented: pub finalized_slot: Slot, pub finalized_block_root: Hash256, - pub justified_slot: Hash256, - */ + pub justified_slot: Slot, + pub justified_block_root: Hash256, + pub previous_justified_slot: Slot, + pub previous_justified_block_root: Hash256, } /// HTTP handler to return a `BeaconBlock` at a given `root` or `slot`. @@ -26,10 +27,30 @@ pub fn get_head(req: Request) -> ApiResult .get::>>() .ok_or_else(|| ApiError::ServerError("Beacon chain extension missing".to_string()))?; + let chain_head = beacon_chain.head(); + let head = HeadResponse { - slot: beacon_chain.head().beacon_state.slot, - block_root: beacon_chain.head().beacon_block_root, - state_root: beacon_chain.head().beacon_state_root, + slot: chain_head.beacon_state.slot, + block_root: chain_head.beacon_block_root, + state_root: chain_head.beacon_state_root, + finalized_slot: chain_head + .beacon_state + .finalized_checkpoint + .epoch + .start_slot(T::EthSpec::slots_per_epoch()), + finalized_block_root: chain_head.beacon_state.finalized_checkpoint.root, + justified_slot: chain_head + .beacon_state + .current_justified_checkpoint + .epoch + .start_slot(T::EthSpec::slots_per_epoch()), + justified_block_root: chain_head.beacon_state.current_justified_checkpoint.root, + previous_justified_slot: chain_head + .beacon_state + .previous_justified_checkpoint + .epoch + .start_slot(T::EthSpec::slots_per_epoch()), + previous_justified_block_root: chain_head.beacon_state.previous_justified_checkpoint.root, }; let json: String = serde_json::to_string(&head) @@ -178,7 +199,7 @@ pub fn get_state_root(req: Request) -> ApiR } /// HTTP handler to return the highest finalized slot. -pub fn get_latest_finalized_checkpoint( +pub fn get_current_finalized_checkpoint( req: Request, ) -> ApiResult { let beacon_chain = req diff --git a/beacon_node/rest_api/src/lib.rs b/beacon_node/rest_api/src/lib.rs index 770793491..99a8c6343 100644 --- a/beacon_node/rest_api/src/lib.rs +++ b/beacon_node/rest_api/src/lib.rs @@ -127,12 +127,8 @@ pub fn start_server( // Methods for Client (&Method::GET, "/node/version") => node::get_version(req), (&Method::GET, "/node/genesis_time") => node::get_genesis_time::(req), - (&Method::GET, "/node/deposit_contract") => { - helpers::implementation_pending_response(req) - } (&Method::GET, "/node/syncing") => helpers::implementation_pending_response(req), (&Method::GET, "/node/chain_id") => helpers::implementation_pending_response(req), - (&Method::GET, "/node/metrics") => metrics::get_prometheus::(req), // Methods for Network (&Method::GET, "/network/enr") => network::get_enr::(req), @@ -143,29 +139,30 @@ pub fn start_server( (&Method::GET, "/network/listen_addresses") => { network::get_listen_addresses::(req) } - (&Method::GET, "/network/stats") => helpers::implementation_pending_response(req), (&Method::GET, "/network/block_discovery") => { helpers::implementation_pending_response(req) } // Methods for Beacon Node - //TODO: Remove? - //(&Method::GET, "/beacon/best_slot") => beacon::get_best_slot::(req), (&Method::GET, "/beacon/head") => beacon::get_head::(req), (&Method::GET, "/beacon/block") => beacon::get_block::(req), (&Method::GET, "/beacon/block_root") => beacon::get_block_root::(req), (&Method::GET, "/beacon/blocks") => helpers::implementation_pending_response(req), (&Method::GET, "/beacon/fork") => helpers::implementation_pending_response(req), - (&Method::GET, "/beacon/latest_finalized_checkpoint") => { - beacon::get_latest_finalized_checkpoint::(req) - } (&Method::GET, "/beacon/attestations") => { helpers::implementation_pending_response(req) } (&Method::GET, "/beacon/attestations/pending") => { helpers::implementation_pending_response(req) } - (&Method::GET, "/beacon/attestations") => { + + (&Method::GET, "/beacon/validators") => { + helpers::implementation_pending_response(req) + } + (&Method::GET, "/beacon/validators/indicies") => { + helpers::implementation_pending_response(req) + } + (&Method::GET, "/beacon/validators/pubkeys") => { helpers::implementation_pending_response(req) } @@ -188,11 +185,19 @@ pub fn start_server( (&Method::GET, "/beacon/state") => beacon::get_state::(req), (&Method::GET, "/beacon/state_root") => beacon::get_state_root::(req), + (&Method::GET, "/beacon/state/current_finalized_checkpoint") => { + beacon::get_current_finalized_checkpoint::(req) + } //TODO: Add aggreggate/filtered state lookups here, e.g. /beacon/validators/balances // Methods for bootstrap and checking configuration (&Method::GET, "/spec") => spec::get_spec::(req), (&Method::GET, "/spec/slots_per_epoch") => spec::get_slots_per_epoch::(req), + (&Method::GET, "/spec/deposit_contract") => { + helpers::implementation_pending_response(req) + } + + (&Method::GET, "/metrics") => metrics::get_prometheus::(req), _ => Err(ApiError::NotFound( "Request path and/or method not found.".to_owned(), diff --git a/beacon_node/rest_api/src/metrics.rs b/beacon_node/rest_api/src/metrics.rs index 1a7ca886e..9d2ecc343 100644 --- a/beacon_node/rest_api/src/metrics.rs +++ b/beacon_node/rest_api/src/metrics.rs @@ -1,5 +1,6 @@ use crate::{success_response, ApiError, ApiResult, DBPath}; use beacon_chain::{BeaconChain, BeaconChainTypes}; +use http::HeaderValue; use hyper::{Body, Request}; use prometheus::{Encoder, TextEncoder}; use std::sync::Arc; @@ -67,10 +68,10 @@ pub fn get_prometheus(req: Request) -> ApiR .map(|string| { let mut response = success_response(Body::from(string)); // Need to change the header to text/plain for prometheius - response - .headers_mut() - .insert("content-type", "text/plain; charset=utf-8".parse().unwrap()) - .unwrap(); + response.headers_mut().insert( + "content-type", + HeaderValue::from_static("text/plain; charset=utf-8"), + ); response }) .map_err(|e| ApiError::ServerError(format!("Failed to encode prometheus info: {:?}", e))) diff --git a/docs/rest_oapi.yaml b/docs/rest_oapi.yaml index 0c2f8616d..be8991956 100644 --- a/docs/rest_oapi.yaml +++ b/docs/rest_oapi.yaml @@ -13,6 +13,8 @@ tags: description: Endpoints which will be implemented for phase 1 of Ethereum Serenity - name: Future description: Potential future endpoints or optional nice-to-haves + - name: RFC + description: Do we need these endpoints at all? This is a request for comments if you think they're useful. paths: /node/version: @@ -47,21 +49,6 @@ paths: 500: $ref: '#/components/responses/InternalError' - /node/deposit_contract: - get: - tags: - - Phase0 - summary: "Get the address of the Ethereum 1 deposit contract." - description: "Requests the address of the deposit contract on the Ethereum 1 chain, which was used to start the current beacon chain." - responses: - 200: - description: Request successful - content: - application/json: - schema: - $ref: '#/components/schemas/ethereum_address' - 500: - $ref: '#/components/responses/InternalError' /node/syncing: get: @@ -106,55 +93,6 @@ paths: 500: $ref: '#/components/responses/InternalError' - /node/metrics: - get: - tags: - - Phase0 - summary: "Get Promethius metrics for the node" - description: "Fetches a range of metrics for measuring nodes health. It is intended for this endpoint to be consumed by Promethius." - responses: - 200: - description: Request successful - content: - text/plain: - example: - summary: 'Promethius metrics' - value: "# HELP beacon_head_state_active_validators_total Count of active validators at the head of the chain - # TYPE beacon_head_state_active_validators_total gauge - beacon_head_state_active_validators_total 16 - # HELP beacon_head_state_current_justified_epoch Current justified epoch at the head of the chain - # TYPE beacon_head_state_current_justified_epoch gauge - beacon_head_state_current_justified_epoch 0 - # HELP beacon_head_state_current_justified_root Current justified root at the head of the chain - # TYPE beacon_head_state_current_justified_root gauge - beacon_head_state_current_justified_root 0 - # HELP beacon_head_state_eth1_deposit_index Eth1 deposit index at the head of the chain - # TYPE beacon_head_state_eth1_deposit_index gauge - beacon_head_state_eth1_deposit_index 16 - # HELP beacon_head_state_finalized_epoch Finalized epoch at the head of the chain - # TYPE beacon_head_state_finalized_epoch gauge - beacon_head_state_finalized_epoch 0 - # HELP beacon_head_state_finalized_root Finalized root at the head of the chain - # TYPE beacon_head_state_finalized_root gauge - beacon_head_state_finalized_root 0 - # HELP beacon_head_state_latest_block_slot Latest block slot at the head of the chain - # TYPE beacon_head_state_latest_block_slot gauge - beacon_head_state_latest_block_slot 0 - # HELP beacon_head_state_previous_justified_epoch Previous justified epoch at the head of the chain - # TYPE beacon_head_state_previous_justified_epoch gauge - beacon_head_state_previous_justified_epoch 0 - # HELP beacon_head_state_previous_justified_root Previous justified root at the head of the chain - # TYPE beacon_head_state_previous_justified_root gauge - beacon_head_state_previous_justified_root 0 - # HELP beacon_head_state_root Root of the block at the head of the chain - # TYPE beacon_head_state_root gauge - beacon_head_state_root -7566315470565629000 - # HELP beacon_head_state_shard_total Count of shards in the beacon chain - # TYPE beacon_head_state_shard_total gauge - beacon_head_state_shard_total 8 - # HELP beacon_head_state_slashed_validators_total Count of all slashed validators at the head of the chain - # TYPE beacon_head_state_slashed_validators_total gauge - beacon_head_state_slashed_validators_total 0" #TODO: Complete the /network/enr request /network/enr: @@ -251,7 +189,7 @@ paths: /network/stats: get: tags: - - Future + - RFC summary: "Get some simple network statistics from the node." description: "Request that the beacon node provide some historical summary information about its networking interface." #TODO: Do we actually collect these stats? Should we? @@ -280,7 +218,7 @@ paths: /network/block_discovery: get: tags: - - Future + - RFC summary: "Identify the time at which particular blocks were first seen." description: "Request the node to provide the time at which particular blocks were first seen on the network." parameters: @@ -369,7 +307,7 @@ paths: format: uint64 description: "The slot number of the second most recent justified slot." previous_justified_block_root: - type: integer + type: string format: bytes pattern: "^0x[a-fA-F0-9]{64}$" description: "The block root of the second most recent justified block." @@ -440,8 +378,6 @@ paths: schema: $ref: '#/components/schemas/Fork' - #TODO fill out latest_finalized_checkpoint - /beacon/latest_finalized_checkpoint: /beacon/attestations: get: @@ -506,7 +442,6 @@ paths: $ref: '#/components/responses/InvalidRequest' #TODO: Make this request error more specific if one of the parameters is not provided correctly. - #TODO: do all these '/beacon/validators' endpoints come under '/beacon/state' subqueries? /beacon/validators: get: tags: @@ -541,7 +476,7 @@ paths: /beacon/validators/activesetchanges: get: tags: - - Phase0 + - RFC summary: "Retrieve the changes in active validator set." description: "Request that the beacon node describe the changes that occurred at the specified epoch, as compared with the prior epoch." parameters: @@ -583,7 +518,7 @@ paths: /beacon/validators/assignments: get: tags: - - Phase0 + - RFC summary: "Retrieve the assigned responsibilities for validators in a particular epoch." description: "Request that the beacon node list the duties which have been assigned to the active validator set in a particular epoch." parameters: @@ -669,7 +604,7 @@ paths: /beacon/validators/balances: get: tags: - - Phase0 + - RFC summary: "Retrieve the balances of validators at a specified epoch." description: "Retrieve the balances of validators at a specified epoch (or the current epoch if none specified). The list of balances can be filtered by providing a list of validator public keys or indices." parameters: @@ -730,7 +665,7 @@ paths: /beacon/validators/participation: get: tags: - - Phase0 + - RFC summary: "Retrieve aggregate information about validator participation in an epoch." description: "Retrieve some aggregate information about the participation of validators in a specified epoch (or the current epoch if none specified)." parameters: @@ -775,7 +710,7 @@ paths: /beacon/validators/queue: get: tags: - - Phase0 + - RFC summary: "Retrieve information about the validator queue at the specified epoch." description: "Retrieve information about the queue of validators for the specified epoch (or the current epoch if none specified)." parameters: @@ -989,12 +924,81 @@ paths: #TODO fill out /beacon/state_root /beacon/state_root: + #TODO fill out current_finalized_checkpoint + /beacon/current_finalized_checkpoint: + #TODO fill spec /spec: #TODO fill spec/slots_per_epoch /spec/slots_per_epoch: + /spec/deposit_contract: + get: + tags: + - Phase0 + summary: "Get the address of the Ethereum 1 deposit contract." + description: "Requests the address of the deposit contract on the Ethereum 1 chain, which was used to start the current beacon chain." + responses: + 200: + description: Request successful + content: + application/json: + schema: + $ref: '#/components/schemas/ethereum_address' + 500: + $ref: '#/components/responses/InternalError' + + /metrics: + get: + tags: + - Phase0 + summary: "Get Promethius metrics for the node" + description: "Fetches a range of metrics for measuring nodes health. It is intended for this endpoint to be consumed by Promethius." + responses: + 200: + description: Request successful + content: + text/plain: + example: + summary: 'Promethius metrics' + value: "# HELP beacon_head_state_active_validators_total Count of active validators at the head of the chain + # TYPE beacon_head_state_active_validators_total gauge + beacon_head_state_active_validators_total 16 + # HELP beacon_head_state_current_justified_epoch Current justified epoch at the head of the chain + # TYPE beacon_head_state_current_justified_epoch gauge + beacon_head_state_current_justified_epoch 0 + # HELP beacon_head_state_current_justified_root Current justified root at the head of the chain + # TYPE beacon_head_state_current_justified_root gauge + beacon_head_state_current_justified_root 0 + # HELP beacon_head_state_eth1_deposit_index Eth1 deposit index at the head of the chain + # TYPE beacon_head_state_eth1_deposit_index gauge + beacon_head_state_eth1_deposit_index 16 + # HELP beacon_head_state_finalized_epoch Finalized epoch at the head of the chain + # TYPE beacon_head_state_finalized_epoch gauge + beacon_head_state_finalized_epoch 0 + # HELP beacon_head_state_finalized_root Finalized root at the head of the chain + # TYPE beacon_head_state_finalized_root gauge + beacon_head_state_finalized_root 0 + # HELP beacon_head_state_latest_block_slot Latest block slot at the head of the chain + # TYPE beacon_head_state_latest_block_slot gauge + beacon_head_state_latest_block_slot 0 + # HELP beacon_head_state_previous_justified_epoch Previous justified epoch at the head of the chain + # TYPE beacon_head_state_previous_justified_epoch gauge + beacon_head_state_previous_justified_epoch 0 + # HELP beacon_head_state_previous_justified_root Previous justified root at the head of the chain + # TYPE beacon_head_state_previous_justified_root gauge + beacon_head_state_previous_justified_root 0 + # HELP beacon_head_state_root Root of the block at the head of the chain + # TYPE beacon_head_state_root gauge + beacon_head_state_root -7566315470565629000 + # HELP beacon_head_state_shard_total Count of shards in the beacon chain + # TYPE beacon_head_state_shard_total gauge + beacon_head_state_shard_total 8 + # HELP beacon_head_state_slashed_validators_total Count of all slashed validators at the head of the chain + # TYPE beacon_head_state_slashed_validators_total gauge + beacon_head_state_slashed_validators_total 0" + components: schemas: pubkey: