mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-20 05:14:35 +00:00
Fixed merge conflict, updated calls.
- Fixed function re-names - Updated the function which gets the beacon_chain from the request, and makes sure caches are updated. - Updated this api-alignment branch with the new code from interop branch.
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
use super::{success_response, ApiResult};
|
||||
use super::{success_response, ApiResult, ResponseBuilder};
|
||||
use crate::{helpers::*, ApiError, UrlQuery};
|
||||
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
||||
use hyper::{Body, Request};
|
||||
use serde::Serialize;
|
||||
use ssz_derive::Encode;
|
||||
use std::sync::Arc;
|
||||
use store::Store;
|
||||
use types::{BeaconBlock, BeaconState, EthSpec, Hash256, Slot};
|
||||
@@ -59,7 +60,7 @@ pub fn get_head<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult
|
||||
Ok(success_response(Body::from(json)))
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Serialize, Encode)]
|
||||
#[serde(bound = "T: EthSpec")]
|
||||
pub struct BlockResponse<T: EthSpec> {
|
||||
pub root: Hash256,
|
||||
@@ -103,11 +104,7 @@ pub fn get_block<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult
|
||||
beacon_block: block,
|
||||
};
|
||||
|
||||
let json: String = serde_json::to_string(&response).map_err(|e| {
|
||||
ApiError::ServerError(format!("Unable to serialize BlockResponse: {:?}", e))
|
||||
})?;
|
||||
|
||||
Ok(success_response(Body::from(json)))
|
||||
ResponseBuilder::new(&req).body(&response)
|
||||
}
|
||||
|
||||
/// HTTP handler to return a `BeaconBlock` root at a given `slot`.
|
||||
@@ -132,11 +129,7 @@ pub fn get_block_root<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiR
|
||||
|
||||
/// HTTP handler to return the `Fork` of the current head.
|
||||
pub fn get_fork<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
||||
let beacon_chain = req
|
||||
.extensions()
|
||||
.get::<Arc<BeaconChain<T>>>()
|
||||
.ok_or_else(|| ApiError::ServerError("Beacon chain extension missing".to_string()))?;
|
||||
|
||||
let beacon_chain = get_beacon_chain_from_request::<T>(&req)?;
|
||||
let chain_head = beacon_chain.head();
|
||||
|
||||
let json: String = serde_json::to_string(&chain_head.beacon_state.fork).map_err(|e| {
|
||||
@@ -146,7 +139,19 @@ pub fn get_fork<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult
|
||||
Ok(success_response(Body::from(json)))
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
/// HTTP handler to return a `BeaconState` at a given `root` or `slot`.
|
||||
///
|
||||
/// Will not return a state if the request slot is in the future. Will return states higher than
|
||||
/// the current head by skipping slots.
|
||||
pub fn get_genesis_state<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
||||
let beacon_chain = get_beacon_chain_from_request::<T>(&req)?;
|
||||
|
||||
let (_root, state) = state_at_slot(&beacon_chain, Slot::new(0))?;
|
||||
|
||||
ResponseBuilder::new(&req).body(&state)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Encode)]
|
||||
#[serde(bound = "T: EthSpec")]
|
||||
pub struct StateResponse<T: EthSpec> {
|
||||
pub root: Hash256,
|
||||
@@ -207,11 +212,7 @@ pub fn get_state<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult
|
||||
beacon_state: state,
|
||||
};
|
||||
|
||||
let json: String = serde_json::to_string(&response).map_err(|e| {
|
||||
ApiError::ServerError(format!("Unable to serialize StateResponse: {:?}", e))
|
||||
})?;
|
||||
|
||||
Ok(success_response(Body::from(json)))
|
||||
ResponseBuilder::new(&req).body(&response)
|
||||
}
|
||||
|
||||
/// HTTP handler to return a `BeaconState` root at a given `slot`.
|
||||
|
||||
@@ -16,7 +16,7 @@ pub struct Config {
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Config {
|
||||
enabled: true, // rest_api enabled by default
|
||||
enabled: true,
|
||||
listen_address: Ipv4Addr::new(127, 0, 0, 1),
|
||||
port: 5052,
|
||||
}
|
||||
@@ -25,8 +25,8 @@ impl Default for Config {
|
||||
|
||||
impl Config {
|
||||
pub fn apply_cli_args(&mut self, args: &ArgMatches) -> Result<(), &'static str> {
|
||||
if args.is_present("api") {
|
||||
self.enabled = true;
|
||||
if args.is_present("no-api") {
|
||||
self.enabled = false;
|
||||
}
|
||||
|
||||
if let Some(rpc_address) = args.value_of("api-address") {
|
||||
|
||||
@@ -109,8 +109,8 @@ pub fn state_root_at_slot<T: BeaconChainTypes>(
|
||||
) -> Result<Hash256, ApiError> {
|
||||
let head_state = &beacon_chain.head().beacon_state;
|
||||
let current_slot = beacon_chain
|
||||
.read_slot_clock()
|
||||
.ok_or_else(|| ApiError::ServerError("Unable to read slot clock".to_string()))?;
|
||||
.slot()
|
||||
.map_err(|_| ApiError::ServerError("Unable to read slot clock".to_string()))?;
|
||||
|
||||
// There are four scenarios when obtaining a state for a given slot:
|
||||
//
|
||||
@@ -177,12 +177,18 @@ pub fn get_beacon_chain_from_request<T: BeaconChainTypes + 'static>(
|
||||
let beacon_chain = req
|
||||
.extensions()
|
||||
.get::<Arc<BeaconChain<T>>>()
|
||||
.ok_or_else(|| {
|
||||
ApiError::ServerError("Request is missing the beacon chain extension".into())
|
||||
})?;
|
||||
let _ = beacon_chain
|
||||
.ensure_state_caches_are_built()
|
||||
.ok_or_else(|| ApiError::ServerError("Beacon chain extension missing".into()))?;
|
||||
|
||||
let _state_now = beacon_chain
|
||||
.state_now()
|
||||
.map_err(|e| ApiError::ServerError(format!("Unable to get current BeaconState {:?}", e)))?
|
||||
.maybe_as_mut_ref()
|
||||
.ok_or(ApiError::ServerError(
|
||||
"Unable to get mutable BeaconState".into(),
|
||||
))?
|
||||
.build_all_caches(&beacon_chain.spec)
|
||||
.map_err(|e| ApiError::ServerError(format!("Unable to build state caches: {:?}", e)))?;
|
||||
|
||||
Ok(beacon_chain.clone())
|
||||
}
|
||||
|
||||
|
||||
@@ -8,15 +8,18 @@ mod helpers;
|
||||
mod metrics;
|
||||
mod network;
|
||||
mod node;
|
||||
mod response_builder;
|
||||
mod spec;
|
||||
mod url_query;
|
||||
mod validator;
|
||||
|
||||
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
||||
use client_network::Service as NetworkService;
|
||||
use eth2_config::Eth2Config;
|
||||
use hyper::rt::Future;
|
||||
use hyper::service::service_fn_ok;
|
||||
use hyper::{Body, Method, Response, Server, StatusCode};
|
||||
use response_builder::ResponseBuilder;
|
||||
use slog::{info, o, warn};
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
@@ -80,6 +83,7 @@ pub fn start_server<T: BeaconChainTypes>(
|
||||
beacon_chain: Arc<BeaconChain<T>>,
|
||||
network_service: Arc<NetworkService<T>>,
|
||||
db_path: PathBuf,
|
||||
eth2_config: Eth2Config,
|
||||
log: &slog::Logger,
|
||||
) -> Result<exit_future::Signal, hyper::Error> {
|
||||
let log = log.new(o!("Service" => "Api"));
|
||||
@@ -101,12 +105,14 @@ pub fn start_server<T: BeaconChainTypes>(
|
||||
// Clone our stateful objects, for use in service closure.
|
||||
let server_log = log.clone();
|
||||
let server_bc = beacon_chain.clone();
|
||||
let eth2_config = Arc::new(eth2_config);
|
||||
|
||||
let service = move || {
|
||||
let log = server_log.clone();
|
||||
let beacon_chain = server_bc.clone();
|
||||
let db_path = db_path.clone();
|
||||
let network_service = network_service.clone();
|
||||
let eth2_config = eth2_config.clone();
|
||||
|
||||
// Create a simple handler for the router, inject our stateful objects into the request.
|
||||
service_fn_ok(move |mut req| {
|
||||
@@ -119,6 +125,8 @@ pub fn start_server<T: BeaconChainTypes>(
|
||||
req.extensions_mut().insert::<DBPath>(db_path.clone());
|
||||
req.extensions_mut()
|
||||
.insert::<Arc<NetworkService<T>>>(network_service.clone());
|
||||
req.extensions_mut()
|
||||
.insert::<Arc<Eth2Config>>(eth2_config.clone());
|
||||
|
||||
let path = req.uri().path().to_string();
|
||||
|
||||
@@ -184,6 +192,7 @@ pub fn start_server<T: BeaconChainTypes>(
|
||||
(&Method::GET, "/beacon/state/current_finalized_checkpoint") => {
|
||||
beacon::get_current_finalized_checkpoint::<T>(req)
|
||||
}
|
||||
(&Method::GET, "/beacon/state/genesis") => beacon::get_genesis_state::<T>(req),
|
||||
//TODO: Add aggreggate/filtered state lookups here, e.g. /beacon/validators/balances
|
||||
|
||||
// Methods for bootstrap and checking configuration
|
||||
@@ -192,6 +201,7 @@ pub fn start_server<T: BeaconChainTypes>(
|
||||
(&Method::GET, "/spec/deposit_contract") => {
|
||||
helpers::implementation_pending_response(req)
|
||||
}
|
||||
(&Method::GET, "/spec/eth2_config") => spec::get_eth2_config::<T>(req),
|
||||
|
||||
(&Method::GET, "/metrics") => metrics::get_prometheus::<T>(req),
|
||||
|
||||
|
||||
50
beacon_node/rest_api/src/response_builder.rs
Normal file
50
beacon_node/rest_api/src/response_builder.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
use super::{ApiError, ApiResult};
|
||||
use http::header;
|
||||
use hyper::{Body, Request, Response, StatusCode};
|
||||
use serde::Serialize;
|
||||
use ssz::Encode;
|
||||
|
||||
pub enum Encoding {
|
||||
JSON,
|
||||
SSZ,
|
||||
YAML,
|
||||
}
|
||||
|
||||
pub struct ResponseBuilder {
|
||||
encoding: Encoding,
|
||||
}
|
||||
|
||||
impl ResponseBuilder {
|
||||
pub fn new(req: &Request<Body>) -> Self {
|
||||
let encoding = match req.headers().get(header::CONTENT_TYPE) {
|
||||
Some(h) if h == "application/ssz" => Encoding::SSZ,
|
||||
Some(h) if h == "application/yaml" => Encoding::YAML,
|
||||
_ => Encoding::JSON,
|
||||
};
|
||||
|
||||
Self { encoding }
|
||||
}
|
||||
|
||||
pub fn body<T: Serialize + Encode>(self, item: &T) -> ApiResult {
|
||||
let body: Body = match self.encoding {
|
||||
Encoding::JSON => Body::from(serde_json::to_string(&item).map_err(|e| {
|
||||
ApiError::ServerError(format!(
|
||||
"Unable to serialize response body as JSON: {:?}",
|
||||
e
|
||||
))
|
||||
})?),
|
||||
Encoding::SSZ => Body::from(item.as_ssz_bytes()),
|
||||
Encoding::YAML => Body::from(serde_yaml::to_string(&item).map_err(|e| {
|
||||
ApiError::ServerError(format!(
|
||||
"Unable to serialize response body as YAML: {:?}",
|
||||
e
|
||||
))
|
||||
})?),
|
||||
};
|
||||
|
||||
Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
.body(Body::from(body))
|
||||
.map_err(|e| ApiError::ServerError(format!("Failed to build response: {:?}", e)))
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
use super::{success_response, ApiResult};
|
||||
use crate::ApiError;
|
||||
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
||||
use eth2_config::Eth2Config;
|
||||
use hyper::{Body, Request};
|
||||
use std::sync::Arc;
|
||||
use types::EthSpec;
|
||||
@@ -18,6 +19,19 @@ pub fn get_spec<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult
|
||||
Ok(success_response(Body::from(json)))
|
||||
}
|
||||
|
||||
/// HTTP handler to return the full Eth2Config object.
|
||||
pub fn get_eth2_config<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
||||
let eth2_config = req
|
||||
.extensions()
|
||||
.get::<Arc<Eth2Config>>()
|
||||
.ok_or_else(|| ApiError::ServerError("Eth2Config extension missing".to_string()))?;
|
||||
|
||||
let json: String = serde_json::to_string(eth2_config.as_ref())
|
||||
.map_err(|e| ApiError::ServerError(format!("Unable to serialize Eth2Config: {:?}", e)))?;
|
||||
|
||||
Ok(success_response(Body::from(json)))
|
||||
}
|
||||
|
||||
/// HTTP handler to return the full spec object.
|
||||
pub fn get_slots_per_epoch<T: BeaconChainTypes + 'static>(_req: Request<Body>) -> ApiResult {
|
||||
let json: String = serde_json::to_string(&T::EthSpec::slots_per_epoch())
|
||||
|
||||
@@ -206,8 +206,8 @@ pub fn get_new_attestation<T: BeaconChainTypes + 'static>(req: Request<Body>) ->
|
||||
.ok_or(ApiError::InvalidQueryParams("No validator duties could be found for the requested validator. Cannot provide valid attestation.".into()))?;
|
||||
|
||||
// Check that we are requesting an attestation during the slot where it is relevant.
|
||||
let present_slot = beacon_chain.read_slot_clock().ok_or(ApiError::ServerError(
|
||||
"Beacon node is unable to determine present slot, either the state isn't generated or the chain hasn't begun.".into()
|
||||
let present_slot = beacon_chain.slot().map_err(|e| ApiError::ServerError(
|
||||
format!("Beacon node is unable to determine present slot, either the state isn't generated or the chain hasn't begun. {:?}", e)
|
||||
))?;
|
||||
if val_duty.slot != present_slot {
|
||||
return Err(ApiError::InvalidQueryParams(format!("Validator is only able to request an attestation during the slot they are allocated. Current slot: {:?}, allocated slot: {:?}", head_state.slot, val_duty.slot)));
|
||||
@@ -257,7 +257,7 @@ pub fn get_new_attestation<T: BeaconChainTypes + 'static>(req: Request<Body>) ->
|
||||
})?;
|
||||
|
||||
let attestation_data = beacon_chain
|
||||
.produce_attestation_data(shard)
|
||||
.produce_attestation_data(shard, current_slot.into())
|
||||
.map_err(|e| ApiError::ServerError(format!("Could not produce an attestation: {:?}", e)))?;
|
||||
|
||||
let attestation: Attestation<T::EthSpec> = Attestation {
|
||||
|
||||
Reference in New Issue
Block a user