mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-08 09:16:00 +00:00
Refactor http router
This commit is contained in:
@@ -23,12 +23,10 @@ pub struct HeadResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP handler to return a `BeaconBlock` at a given `root` or `slot`.
|
/// HTTP handler to return a `BeaconBlock` at a given `root` or `slot`.
|
||||||
pub fn get_head<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_head<T: BeaconChainTypes + 'static>(
|
||||||
let beacon_chain = req
|
req: Request<Body>,
|
||||||
.extensions()
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
.get::<Arc<BeaconChain<T>>>()
|
) -> ApiResult {
|
||||||
.ok_or_else(|| ApiError::ServerError("Beacon chain extension missing".to_string()))?;
|
|
||||||
|
|
||||||
let chain_head = beacon_chain.head();
|
let chain_head = beacon_chain.head();
|
||||||
|
|
||||||
let head = HeadResponse {
|
let head = HeadResponse {
|
||||||
@@ -66,12 +64,10 @@ pub struct BlockResponse<T: EthSpec> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP handler to return a `BeaconBlock` at a given `root` or `slot`.
|
/// HTTP handler to return a `BeaconBlock` at a given `root` or `slot`.
|
||||||
pub fn get_block<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_block<T: BeaconChainTypes + 'static>(
|
||||||
let beacon_chain = req
|
req: Request<Body>,
|
||||||
.extensions()
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
.get::<Arc<BeaconChain<T>>>()
|
) -> ApiResult {
|
||||||
.ok_or_else(|| ApiError::ServerError("Beacon chain extension missing".to_string()))?;
|
|
||||||
|
|
||||||
let query_params = ["root", "slot"];
|
let query_params = ["root", "slot"];
|
||||||
let (key, value) = UrlQuery::from_request(&req)?.first_of(&query_params)?;
|
let (key, value) = UrlQuery::from_request(&req)?.first_of(&query_params)?;
|
||||||
|
|
||||||
@@ -106,9 +102,10 @@ pub fn get_block<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP handler to return a `BeaconBlock` root at a given `slot`.
|
/// HTTP handler to return a `BeaconBlock` root at a given `slot`.
|
||||||
pub fn get_block_root<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_block_root<T: BeaconChainTypes + 'static>(
|
||||||
let beacon_chain = get_beacon_chain_from_request::<T>(&req)?;
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
) -> ApiResult {
|
||||||
let slot_string = UrlQuery::from_request(&req)?.only_one("slot")?;
|
let slot_string = UrlQuery::from_request(&req)?.only_one("slot")?;
|
||||||
let target = parse_slot(&slot_string)?;
|
let target = parse_slot(&slot_string)?;
|
||||||
|
|
||||||
@@ -120,8 +117,10 @@ pub fn get_block_root<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiR
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP handler to return the `Fork` of the current head.
|
/// HTTP handler to return the `Fork` of the current head.
|
||||||
pub fn get_fork<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_fork<T: BeaconChainTypes + 'static>(
|
||||||
let beacon_chain = get_beacon_chain_from_request::<T>(&req)?;
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
) -> ApiResult {
|
||||||
ResponseBuilder::new(&req)?.body(&beacon_chain.head().beacon_state.fork)
|
ResponseBuilder::new(&req)?.body(&beacon_chain.head().beacon_state.fork)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,9 +128,10 @@ pub fn get_fork<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult
|
|||||||
///
|
///
|
||||||
/// The `Epoch` parameter can be any epoch number. If it is not specified,
|
/// The `Epoch` parameter can be any epoch number. If it is not specified,
|
||||||
/// the current epoch is assumed.
|
/// the current epoch is assumed.
|
||||||
pub fn get_validators<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_validators<T: BeaconChainTypes + 'static>(
|
||||||
let beacon_chain = get_beacon_chain_from_request::<T>(&req)?;
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
) -> ApiResult {
|
||||||
let epoch = match UrlQuery::from_request(&req) {
|
let epoch = match UrlQuery::from_request(&req) {
|
||||||
// We have some parameters, so make sure it's the epoch one and parse it
|
// We have some parameters, so make sure it's the epoch one and parse it
|
||||||
Ok(query) => query
|
Ok(query) => query
|
||||||
@@ -168,8 +168,10 @@ pub struct StateResponse<T: EthSpec> {
|
|||||||
///
|
///
|
||||||
/// Will not return a state if the request slot is in the future. Will return states higher than
|
/// Will not return a state if the request slot is in the future. Will return states higher than
|
||||||
/// the current head by skipping slots.
|
/// the current head by skipping slots.
|
||||||
pub fn get_state<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_state<T: BeaconChainTypes + 'static>(
|
||||||
let beacon_chain = get_beacon_chain_from_request::<T>(&req)?;
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
) -> ApiResult {
|
||||||
let head_state = beacon_chain.head().beacon_state;
|
let head_state = beacon_chain.head().beacon_state;
|
||||||
|
|
||||||
let (key, value) = match UrlQuery::from_request(&req) {
|
let (key, value) = match UrlQuery::from_request(&req) {
|
||||||
@@ -214,9 +216,10 @@ pub fn get_state<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult
|
|||||||
///
|
///
|
||||||
/// Will not return a state if the request slot is in the future. Will return states higher than
|
/// Will not return a state if the request slot is in the future. Will return states higher than
|
||||||
/// the current head by skipping slots.
|
/// the current head by skipping slots.
|
||||||
pub fn get_state_root<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_state_root<T: BeaconChainTypes + 'static>(
|
||||||
let beacon_chain = get_beacon_chain_from_request::<T>(&req)?;
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
) -> ApiResult {
|
||||||
let slot_string = UrlQuery::from_request(&req)?.only_one("slot")?;
|
let slot_string = UrlQuery::from_request(&req)?.only_one("slot")?;
|
||||||
let slot = parse_slot(&slot_string)?;
|
let slot = parse_slot(&slot_string)?;
|
||||||
|
|
||||||
@@ -228,8 +231,8 @@ pub fn get_state_root<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiR
|
|||||||
/// HTTP handler to return the highest finalized slot.
|
/// HTTP handler to return the highest finalized slot.
|
||||||
pub fn get_current_finalized_checkpoint<T: BeaconChainTypes + 'static>(
|
pub fn get_current_finalized_checkpoint<T: BeaconChainTypes + 'static>(
|
||||||
req: Request<Body>,
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
) -> ApiResult {
|
) -> ApiResult {
|
||||||
let beacon_chain = get_beacon_chain_from_request::<T>(&req)?;
|
|
||||||
let head_state = beacon_chain.head().beacon_state;
|
let head_state = beacon_chain.head().beacon_state;
|
||||||
|
|
||||||
let checkpoint = head_state.finalized_checkpoint.clone();
|
let checkpoint = head_state.finalized_checkpoint.clone();
|
||||||
@@ -238,9 +241,10 @@ pub fn get_current_finalized_checkpoint<T: BeaconChainTypes + 'static>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP handler to return a `BeaconState` at the genesis block.
|
/// HTTP handler to return a `BeaconState` at the genesis block.
|
||||||
pub fn get_genesis_state<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_genesis_state<T: BeaconChainTypes + 'static>(
|
||||||
let beacon_chain = get_beacon_chain_from_request::<T>(&req)?;
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
) -> ApiResult {
|
||||||
let (_root, state) = state_at_slot(&beacon_chain, Slot::new(0))?;
|
let (_root, state) = state_at_slot(&beacon_chain, Slot::new(0))?;
|
||||||
|
|
||||||
ResponseBuilder::new(&req)?.body(&state)
|
ResponseBuilder::new(&req)?.body(&state)
|
||||||
|
|||||||
@@ -213,26 +213,6 @@ pub fn implementation_pending_response(_req: Request<Body>) -> ApiResult {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_beacon_chain_from_request<T: BeaconChainTypes + 'static>(
|
|
||||||
req: &Request<Body>,
|
|
||||||
) -> Result<(Arc<BeaconChain<T>>), ApiError> {
|
|
||||||
// Get beacon state
|
|
||||||
let beacon_chain = req
|
|
||||||
.extensions()
|
|
||||||
.get::<Arc<BeaconChain<T>>>()
|
|
||||||
.ok_or_else(|| ApiError::ServerError("Beacon chain extension missing".into()))?;
|
|
||||||
|
|
||||||
Ok(beacon_chain.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_logger_from_request(req: &Request<Body>) -> slog::Logger {
|
|
||||||
let log = req
|
|
||||||
.extensions()
|
|
||||||
.get::<slog::Logger>()
|
|
||||||
.expect("Should always get the logger from the request, since we put it in there.");
|
|
||||||
log.to_owned()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn publish_beacon_block_to_network<T: BeaconChainTypes + 'static>(
|
pub fn publish_beacon_block_to_network<T: BeaconChainTypes + 'static>(
|
||||||
chan: Arc<RwLock<mpsc::UnboundedSender<NetworkMessage>>>,
|
chan: Arc<RwLock<mpsc::UnboundedSender<NetworkMessage>>>,
|
||||||
block: BeaconBlock<T::EthSpec>,
|
block: BeaconBlock<T::EthSpec>,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ mod metrics;
|
|||||||
mod network;
|
mod network;
|
||||||
mod node;
|
mod node;
|
||||||
mod response_builder;
|
mod response_builder;
|
||||||
|
mod router;
|
||||||
mod spec;
|
mod spec;
|
||||||
mod url_query;
|
mod url_query;
|
||||||
mod validator;
|
mod validator;
|
||||||
@@ -22,10 +23,10 @@ use client_network::Service as NetworkService;
|
|||||||
pub use config::ApiEncodingFormat;
|
pub use config::ApiEncodingFormat;
|
||||||
use error::{ApiError, ApiResult};
|
use error::{ApiError, ApiResult};
|
||||||
use eth2_config::Eth2Config;
|
use eth2_config::Eth2Config;
|
||||||
use futures::future::IntoFuture;
|
|
||||||
use hyper::rt::Future;
|
use hyper::rt::Future;
|
||||||
use hyper::service::Service;
|
use hyper::server::conn::AddrStream;
|
||||||
use hyper::{Body, Method, Request, Response, Server};
|
use hyper::service::{make_service_fn, service_fn};
|
||||||
|
use hyper::{Body, Request, Response, Server};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use slog::{info, warn};
|
use slog::{info, warn};
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
@@ -41,162 +42,14 @@ pub use beacon::{BlockResponse, HeadResponse, StateResponse};
|
|||||||
pub use config::Config;
|
pub use config::Config;
|
||||||
pub use validator::ValidatorDuty;
|
pub use validator::ValidatorDuty;
|
||||||
|
|
||||||
type BoxFut = Box<dyn Future<Item = Response<Body>, Error = ApiError> + Send>;
|
pub type BoxFut = Box<dyn Future<Item = Response<Body>, Error = ApiError> + Send>;
|
||||||
|
pub type NetworkChannel = Arc<RwLock<mpsc::UnboundedSender<NetworkMessage>>>;
|
||||||
pub struct ApiService<T: BeaconChainTypes + 'static> {
|
|
||||||
log: slog::Logger,
|
|
||||||
beacon_chain: Arc<BeaconChain<T>>,
|
|
||||||
db_path: DBPath,
|
|
||||||
network_service: Arc<NetworkService<T>>,
|
|
||||||
network_channel: Arc<RwLock<mpsc::UnboundedSender<NetworkMessage>>>,
|
|
||||||
eth2_config: Arc<Eth2Config>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct NetworkInfo<T: BeaconChainTypes> {
|
pub struct NetworkInfo<T: BeaconChainTypes> {
|
||||||
pub network_service: Arc<NetworkService<T>>,
|
pub network_service: Arc<NetworkService<T>>,
|
||||||
pub network_chan: mpsc::UnboundedSender<NetworkMessage>,
|
pub network_chan: mpsc::UnboundedSender<NetworkMessage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_boxfut<F: IntoFuture + 'static>(item: F) -> BoxFut
|
|
||||||
where
|
|
||||||
F: IntoFuture<Item = Response<Body>, Error = ApiError>,
|
|
||||||
F::Future: Send,
|
|
||||||
{
|
|
||||||
Box::new(item.into_future())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: BeaconChainTypes> Service for ApiService<T> {
|
|
||||||
type ReqBody = Body;
|
|
||||||
type ResBody = Body;
|
|
||||||
type Error = ApiError;
|
|
||||||
type Future = BoxFut;
|
|
||||||
|
|
||||||
fn call(&mut self, mut req: Request<Body>) -> Self::Future {
|
|
||||||
metrics::inc_counter(&metrics::REQUEST_COUNT);
|
|
||||||
let timer = metrics::start_timer(&metrics::REQUEST_RESPONSE_TIME);
|
|
||||||
|
|
||||||
// Add all the useful bits into the request, so that we can pull them out in the individual
|
|
||||||
// functions.
|
|
||||||
req.extensions_mut()
|
|
||||||
.insert::<slog::Logger>(self.log.clone());
|
|
||||||
req.extensions_mut()
|
|
||||||
.insert::<Arc<BeaconChain<T>>>(self.beacon_chain.clone());
|
|
||||||
req.extensions_mut().insert::<DBPath>(self.db_path.clone());
|
|
||||||
req.extensions_mut()
|
|
||||||
.insert::<Arc<NetworkService<T>>>(self.network_service.clone());
|
|
||||||
req.extensions_mut()
|
|
||||||
.insert::<Arc<RwLock<mpsc::UnboundedSender<NetworkMessage>>>>(
|
|
||||||
self.network_channel.clone(),
|
|
||||||
);
|
|
||||||
req.extensions_mut()
|
|
||||||
.insert::<Arc<Eth2Config>>(self.eth2_config.clone());
|
|
||||||
|
|
||||||
let path = req.uri().path().to_string();
|
|
||||||
|
|
||||||
// Route the request to the correct handler.
|
|
||||||
let result = match (req.method(), path.as_ref()) {
|
|
||||||
// Methods for Client
|
|
||||||
(&Method::GET, "/node/version") => into_boxfut(node::get_version(req)),
|
|
||||||
(&Method::GET, "/node/genesis_time") => into_boxfut(node::get_genesis_time::<T>(req)),
|
|
||||||
(&Method::GET, "/node/syncing") => {
|
|
||||||
into_boxfut(helpers::implementation_pending_response(req))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Methods for Network
|
|
||||||
(&Method::GET, "/network/enr") => into_boxfut(network::get_enr::<T>(req)),
|
|
||||||
(&Method::GET, "/network/peer_count") => into_boxfut(network::get_peer_count::<T>(req)),
|
|
||||||
(&Method::GET, "/network/peer_id") => into_boxfut(network::get_peer_id::<T>(req)),
|
|
||||||
(&Method::GET, "/network/peers") => into_boxfut(network::get_peer_list::<T>(req)),
|
|
||||||
(&Method::GET, "/network/listen_port") => {
|
|
||||||
into_boxfut(network::get_listen_port::<T>(req))
|
|
||||||
}
|
|
||||||
(&Method::GET, "/network/listen_addresses") => {
|
|
||||||
into_boxfut(network::get_listen_addresses::<T>(req))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Methods for Beacon Node
|
|
||||||
(&Method::GET, "/beacon/head") => into_boxfut(beacon::get_head::<T>(req)),
|
|
||||||
(&Method::GET, "/beacon/block") => into_boxfut(beacon::get_block::<T>(req)),
|
|
||||||
(&Method::GET, "/beacon/block_root") => into_boxfut(beacon::get_block_root::<T>(req)),
|
|
||||||
(&Method::GET, "/beacon/blocks") => {
|
|
||||||
into_boxfut(helpers::implementation_pending_response(req))
|
|
||||||
}
|
|
||||||
(&Method::GET, "/beacon/fork") => into_boxfut(beacon::get_fork::<T>(req)),
|
|
||||||
(&Method::GET, "/beacon/attestations") => {
|
|
||||||
into_boxfut(helpers::implementation_pending_response(req))
|
|
||||||
}
|
|
||||||
(&Method::GET, "/beacon/attestations/pending") => {
|
|
||||||
into_boxfut(helpers::implementation_pending_response(req))
|
|
||||||
}
|
|
||||||
|
|
||||||
(&Method::GET, "/beacon/validators") => into_boxfut(beacon::get_validators::<T>(req)),
|
|
||||||
(&Method::GET, "/beacon/validators/indicies") => {
|
|
||||||
into_boxfut(helpers::implementation_pending_response(req))
|
|
||||||
}
|
|
||||||
(&Method::GET, "/beacon/validators/pubkeys") => {
|
|
||||||
into_boxfut(helpers::implementation_pending_response(req))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Methods for Validator
|
|
||||||
(&Method::GET, "/validator/duties") => {
|
|
||||||
into_boxfut(validator::get_validator_duties::<T>(req))
|
|
||||||
}
|
|
||||||
(&Method::GET, "/validator/block") => {
|
|
||||||
into_boxfut(validator::get_new_beacon_block::<T>(req))
|
|
||||||
}
|
|
||||||
(&Method::POST, "/validator/block") => validator::publish_beacon_block::<T>(req),
|
|
||||||
(&Method::GET, "/validator/attestation") => {
|
|
||||||
into_boxfut(validator::get_new_attestation::<T>(req))
|
|
||||||
}
|
|
||||||
(&Method::POST, "/validator/attestation") => validator::publish_attestation::<T>(req),
|
|
||||||
|
|
||||||
(&Method::GET, "/beacon/state") => into_boxfut(beacon::get_state::<T>(req)),
|
|
||||||
(&Method::GET, "/beacon/state_root") => into_boxfut(beacon::get_state_root::<T>(req)),
|
|
||||||
(&Method::GET, "/beacon/state/current_finalized_checkpoint") => {
|
|
||||||
into_boxfut(beacon::get_current_finalized_checkpoint::<T>(req))
|
|
||||||
}
|
|
||||||
(&Method::GET, "/beacon/state/genesis") => {
|
|
||||||
into_boxfut(beacon::get_genesis_state::<T>(req))
|
|
||||||
}
|
|
||||||
//TODO: Add aggreggate/filtered state lookups here, e.g. /beacon/validators/balances
|
|
||||||
|
|
||||||
// Methods for bootstrap and checking configuration
|
|
||||||
(&Method::GET, "/spec") => into_boxfut(spec::get_spec::<T>(req)),
|
|
||||||
(&Method::GET, "/spec/slots_per_epoch") => {
|
|
||||||
into_boxfut(spec::get_slots_per_epoch::<T>(req))
|
|
||||||
}
|
|
||||||
(&Method::GET, "/spec/deposit_contract") => {
|
|
||||||
into_boxfut(helpers::implementation_pending_response(req))
|
|
||||||
}
|
|
||||||
(&Method::GET, "/spec/eth2_config") => into_boxfut(spec::get_eth2_config::<T>(req)),
|
|
||||||
|
|
||||||
(&Method::GET, "/metrics") => into_boxfut(metrics::get_prometheus::<T>(req)),
|
|
||||||
|
|
||||||
_ => Box::new(futures::future::err(ApiError::NotFound(
|
|
||||||
"Request path and/or method not found.".to_owned(),
|
|
||||||
))),
|
|
||||||
};
|
|
||||||
|
|
||||||
let response = match result.wait() {
|
|
||||||
// Return the `hyper::Response`.
|
|
||||||
Ok(response) => {
|
|
||||||
metrics::inc_counter(&metrics::SUCCESS_COUNT);
|
|
||||||
slog::debug!(self.log, "Request successful: {:?}", path);
|
|
||||||
response
|
|
||||||
}
|
|
||||||
// Map the `ApiError` into `hyper::Response`.
|
|
||||||
Err(e) => {
|
|
||||||
slog::debug!(self.log, "Request failure: {:?}", path);
|
|
||||||
e.into()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
metrics::stop_timer(timer);
|
|
||||||
|
|
||||||
Box::new(futures::future::ok(response))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start_server<T: BeaconChainTypes>(
|
pub fn start_server<T: BeaconChainTypes>(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
executor: &TaskExecutor,
|
executor: &TaskExecutor,
|
||||||
@@ -206,46 +59,53 @@ pub fn start_server<T: BeaconChainTypes>(
|
|||||||
eth2_config: Eth2Config,
|
eth2_config: Eth2Config,
|
||||||
log: slog::Logger,
|
log: slog::Logger,
|
||||||
) -> Result<(exit_future::Signal, SocketAddr), hyper::Error> {
|
) -> Result<(exit_future::Signal, SocketAddr), hyper::Error> {
|
||||||
// build a channel to kill the HTTP server
|
// Define the function that will build the request handler.
|
||||||
let (exit_signal, exit) = exit_future::signal();
|
let inner_log = log.clone();
|
||||||
|
let eth2_config = Arc::new(eth2_config);
|
||||||
|
let make_service = make_service_fn(move |_socket: &AddrStream| {
|
||||||
|
let beacon_chain = beacon_chain.clone();
|
||||||
|
let log = inner_log.clone();
|
||||||
|
let eth2_config = eth2_config.clone();
|
||||||
|
let network_service = network_info.network_service.clone();
|
||||||
|
let network_channel = Arc::new(RwLock::new(network_info.network_chan.clone()));
|
||||||
|
let db_path = db_path.clone();
|
||||||
|
|
||||||
let exit_log = log.clone();
|
service_fn(move |req: Request<Body>| {
|
||||||
let server_exit = exit.and_then(move |_| {
|
router::route(
|
||||||
info!(exit_log, "API service shutdown");
|
req,
|
||||||
Ok(())
|
beacon_chain.clone(),
|
||||||
|
network_service.clone(),
|
||||||
|
network_channel.clone(),
|
||||||
|
eth2_config.clone(),
|
||||||
|
log.clone(),
|
||||||
|
db_path.clone(),
|
||||||
|
)
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let db_path = DBPath(db_path);
|
|
||||||
|
|
||||||
// Get the address to bind to
|
|
||||||
let bind_addr = (config.listen_address, config.port).into();
|
let bind_addr = (config.listen_address, config.port).into();
|
||||||
|
let server = Server::bind(&bind_addr).serve(make_service);
|
||||||
|
|
||||||
// Clone our stateful objects, for use in service closure.
|
// Determine the address the server is actually listening on.
|
||||||
let server_log = log.clone();
|
//
|
||||||
let server_bc = beacon_chain.clone();
|
// This may be different to `bind_addr` if bind port was 0 (this allows the OS to choose a free
|
||||||
let eth2_config = Arc::new(eth2_config);
|
// port).
|
||||||
|
|
||||||
let service = move || -> futures::future::FutureResult<ApiService<T>, String> {
|
|
||||||
futures::future::ok(ApiService {
|
|
||||||
log: server_log.clone(),
|
|
||||||
beacon_chain: server_bc.clone(),
|
|
||||||
db_path: db_path.clone(),
|
|
||||||
network_service: network_info.network_service.clone(),
|
|
||||||
network_channel: Arc::new(RwLock::new(network_info.network_chan.clone())),
|
|
||||||
eth2_config: eth2_config.clone(),
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let log_clone = log.clone();
|
|
||||||
let server = Server::bind(&bind_addr).serve(service);
|
|
||||||
|
|
||||||
let actual_listen_addr = server.local_addr();
|
let actual_listen_addr = server.local_addr();
|
||||||
|
|
||||||
|
// Build a channel to kill the HTTP server.
|
||||||
|
let (exit_signal, exit) = exit_future::signal();
|
||||||
|
let inner_log = log.clone();
|
||||||
|
let server_exit = exit.and_then(move |_| {
|
||||||
|
info!(inner_log, "API service shutdown");
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
// Configure the `hyper` server to gracefully shutdown when the shutdown channel is triggered.
|
||||||
|
let inner_log = log.clone();
|
||||||
let server_future = server
|
let server_future = server
|
||||||
.with_graceful_shutdown(server_exit)
|
.with_graceful_shutdown(server_exit)
|
||||||
.map_err(move |e| {
|
.map_err(move |e| {
|
||||||
warn!(
|
warn!(
|
||||||
log_clone,
|
inner_log,
|
||||||
"API failed to start, Unable to bind"; "address" => format!("{:?}", e)
|
"API failed to start, Unable to bind"; "address" => format!("{:?}", e)
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
use crate::helpers::get_beacon_chain_from_request;
|
|
||||||
use crate::response_builder::ResponseBuilder;
|
use crate::response_builder::ResponseBuilder;
|
||||||
use crate::{ApiError, ApiResult, DBPath};
|
use crate::{ApiError, ApiResult};
|
||||||
use beacon_chain::BeaconChainTypes;
|
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
||||||
use hyper::{Body, Request};
|
use hyper::{Body, Request};
|
||||||
use lighthouse_metrics::{Encoder, TextEncoder};
|
use lighthouse_metrics::{Encoder, TextEncoder};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub use lighthouse_metrics::*;
|
pub use lighthouse_metrics::*;
|
||||||
|
|
||||||
@@ -27,16 +28,14 @@ lazy_static! {
|
|||||||
/// # Note
|
/// # Note
|
||||||
///
|
///
|
||||||
/// This is a HTTP handler method.
|
/// This is a HTTP handler method.
|
||||||
pub fn get_prometheus<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_prometheus<T: BeaconChainTypes + 'static>(
|
||||||
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
db_path: PathBuf,
|
||||||
|
) -> ApiResult {
|
||||||
let mut buffer = vec![];
|
let mut buffer = vec![];
|
||||||
let encoder = TextEncoder::new();
|
let encoder = TextEncoder::new();
|
||||||
|
|
||||||
let beacon_chain = get_beacon_chain_from_request::<T>(&req)?;
|
|
||||||
let db_path = req
|
|
||||||
.extensions()
|
|
||||||
.get::<DBPath>()
|
|
||||||
.ok_or_else(|| ApiError::ServerError("DBPath extension missing".to_string()))?;
|
|
||||||
|
|
||||||
// There are two categories of metrics:
|
// There are two categories of metrics:
|
||||||
//
|
//
|
||||||
// - Dynamically updated: things like histograms and event counters that are updated on the
|
// - Dynamically updated: things like histograms and event counters that are updated on the
|
||||||
|
|||||||
@@ -9,11 +9,10 @@ use std::sync::Arc;
|
|||||||
/// HTTP handler to return the list of libp2p multiaddr the client is listening on.
|
/// HTTP handler to return the list of libp2p multiaddr the client is listening on.
|
||||||
///
|
///
|
||||||
/// Returns a list of `Multiaddr`, serialized according to their `serde` impl.
|
/// Returns a list of `Multiaddr`, serialized according to their `serde` impl.
|
||||||
pub fn get_listen_addresses<T: BeaconChainTypes>(req: Request<Body>) -> ApiResult {
|
pub fn get_listen_addresses<T: BeaconChainTypes>(
|
||||||
let network = req
|
req: Request<Body>,
|
||||||
.extensions()
|
network: Arc<NetworkService<T>>,
|
||||||
.get::<Arc<NetworkService<T>>>()
|
) -> ApiResult {
|
||||||
.expect("The network service should always be there, we put it there");
|
|
||||||
let multiaddresses: Vec<Multiaddr> = network.listen_multiaddrs();
|
let multiaddresses: Vec<Multiaddr> = network.listen_multiaddrs();
|
||||||
ResponseBuilder::new(&req)?.body_no_ssz(&multiaddresses)
|
ResponseBuilder::new(&req)?.body_no_ssz(&multiaddresses)
|
||||||
}
|
}
|
||||||
@@ -21,54 +20,48 @@ pub fn get_listen_addresses<T: BeaconChainTypes>(req: Request<Body>) -> ApiResul
|
|||||||
/// HTTP handler to return the network port the client is listening on.
|
/// HTTP handler to return the network port the client is listening on.
|
||||||
///
|
///
|
||||||
/// Returns the TCP port number in its plain form (which is also valid JSON serialization)
|
/// Returns the TCP port number in its plain form (which is also valid JSON serialization)
|
||||||
pub fn get_listen_port<T: BeaconChainTypes>(req: Request<Body>) -> ApiResult {
|
pub fn get_listen_port<T: BeaconChainTypes>(
|
||||||
let network = req
|
req: Request<Body>,
|
||||||
.extensions()
|
network: Arc<NetworkService<T>>,
|
||||||
.get::<Arc<NetworkService<T>>>()
|
) -> ApiResult {
|
||||||
.expect("The network service should always be there, we put it there")
|
|
||||||
.clone();
|
|
||||||
ResponseBuilder::new(&req)?.body(&network.listen_port())
|
ResponseBuilder::new(&req)?.body(&network.listen_port())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP handler to return the Discv5 ENR from the client's libp2p service.
|
/// HTTP handler to return the Discv5 ENR from the client's libp2p service.
|
||||||
///
|
///
|
||||||
/// ENR is encoded as base64 string.
|
/// ENR is encoded as base64 string.
|
||||||
pub fn get_enr<T: BeaconChainTypes>(req: Request<Body>) -> ApiResult {
|
pub fn get_enr<T: BeaconChainTypes>(
|
||||||
let network = req
|
req: Request<Body>,
|
||||||
.extensions()
|
network: Arc<NetworkService<T>>,
|
||||||
.get::<Arc<NetworkService<T>>>()
|
) -> ApiResult {
|
||||||
.expect("The network service should always be there, we put it there");
|
|
||||||
ResponseBuilder::new(&req)?.body_no_ssz(&network.local_enr().to_base64())
|
ResponseBuilder::new(&req)?.body_no_ssz(&network.local_enr().to_base64())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP handler to return the `PeerId` from the client's libp2p service.
|
/// HTTP handler to return the `PeerId` from the client's libp2p service.
|
||||||
///
|
///
|
||||||
/// PeerId is encoded as base58 string.
|
/// PeerId is encoded as base58 string.
|
||||||
pub fn get_peer_id<T: BeaconChainTypes>(req: Request<Body>) -> ApiResult {
|
pub fn get_peer_id<T: BeaconChainTypes>(
|
||||||
let network = req
|
req: Request<Body>,
|
||||||
.extensions()
|
network: Arc<NetworkService<T>>,
|
||||||
.get::<Arc<NetworkService<T>>>()
|
) -> ApiResult {
|
||||||
.expect("The network service should always be there, we put it there");
|
|
||||||
ResponseBuilder::new(&req)?.body_no_ssz(&network.local_peer_id().to_base58())
|
ResponseBuilder::new(&req)?.body_no_ssz(&network.local_peer_id().to_base58())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP handler to return the number of peers connected in the client's libp2p service.
|
/// HTTP handler to return the number of peers connected in the client's libp2p service.
|
||||||
pub fn get_peer_count<T: BeaconChainTypes>(req: Request<Body>) -> ApiResult {
|
pub fn get_peer_count<T: BeaconChainTypes>(
|
||||||
let network = req
|
req: Request<Body>,
|
||||||
.extensions()
|
network: Arc<NetworkService<T>>,
|
||||||
.get::<Arc<NetworkService<T>>>()
|
) -> ApiResult {
|
||||||
.expect("The network service should always be there, we put it there");
|
|
||||||
ResponseBuilder::new(&req)?.body(&network.connected_peers())
|
ResponseBuilder::new(&req)?.body(&network.connected_peers())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP handler to return the list of peers connected to the client's libp2p service.
|
/// HTTP handler to return the list of peers connected to the client's libp2p service.
|
||||||
///
|
///
|
||||||
/// Peers are presented as a list of `PeerId::to_string()`.
|
/// Peers are presented as a list of `PeerId::to_string()`.
|
||||||
pub fn get_peer_list<T: BeaconChainTypes>(req: Request<Body>) -> ApiResult {
|
pub fn get_peer_list<T: BeaconChainTypes>(
|
||||||
let network = req
|
req: Request<Body>,
|
||||||
.extensions()
|
network: Arc<NetworkService<T>>,
|
||||||
.get::<Arc<NetworkService<T>>>()
|
) -> ApiResult {
|
||||||
.expect("The network service should always be there, we put it there");
|
|
||||||
let connected_peers: Vec<String> = network
|
let connected_peers: Vec<String> = network
|
||||||
.connected_peer_set()
|
.connected_peer_set()
|
||||||
.iter()
|
.iter()
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::helpers::get_beacon_chain_from_request;
|
|
||||||
use crate::response_builder::ResponseBuilder;
|
use crate::response_builder::ResponseBuilder;
|
||||||
use crate::ApiResult;
|
use crate::ApiResult;
|
||||||
use beacon_chain::BeaconChainTypes;
|
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
||||||
use hyper::{Body, Request};
|
use hyper::{Body, Request};
|
||||||
|
use std::sync::Arc;
|
||||||
use version;
|
use version;
|
||||||
|
|
||||||
/// Read the version string from the current Lighthouse build.
|
/// Read the version string from the current Lighthouse build.
|
||||||
@@ -11,7 +11,9 @@ pub fn get_version(req: Request<Body>) -> ApiResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Read the genesis time from the current beacon chain state.
|
/// Read the genesis time from the current beacon chain state.
|
||||||
pub fn get_genesis_time<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_genesis_time<T: BeaconChainTypes + 'static>(
|
||||||
let beacon_chain = get_beacon_chain_from_request::<T>(&req)?;
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
) -> ApiResult {
|
||||||
ResponseBuilder::new(&req)?.body(&beacon_chain.head().beacon_state.genesis_time)
|
ResponseBuilder::new(&req)?.body(&beacon_chain.head().beacon_state.genesis_time)
|
||||||
}
|
}
|
||||||
|
|||||||
169
beacon_node/rest_api/src/router.rs
Normal file
169
beacon_node/rest_api/src/router.rs
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
use crate::{
|
||||||
|
beacon, error::ApiError, helpers, metrics, network, node, spec, validator, BoxFut,
|
||||||
|
NetworkChannel,
|
||||||
|
};
|
||||||
|
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
||||||
|
use client_network::Service as NetworkService;
|
||||||
|
use eth2_config::Eth2Config;
|
||||||
|
use futures::{Future, IntoFuture};
|
||||||
|
use hyper::{Body, Error, Method, Request, Response};
|
||||||
|
use slog::debug;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
fn into_boxfut<F: IntoFuture + 'static>(item: F) -> BoxFut
|
||||||
|
where
|
||||||
|
F: IntoFuture<Item = Response<Body>, Error = ApiError>,
|
||||||
|
F::Future: Send,
|
||||||
|
{
|
||||||
|
Box::new(item.into_future())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn route<T: BeaconChainTypes>(
|
||||||
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
network_service: Arc<NetworkService<T>>,
|
||||||
|
network_channel: NetworkChannel,
|
||||||
|
eth2_config: Arc<Eth2Config>,
|
||||||
|
local_log: slog::Logger,
|
||||||
|
db_path: PathBuf,
|
||||||
|
) -> impl Future<Item = Response<Body>, Error = Error> {
|
||||||
|
metrics::inc_counter(&metrics::REQUEST_COUNT);
|
||||||
|
let timer = metrics::start_timer(&metrics::REQUEST_RESPONSE_TIME);
|
||||||
|
|
||||||
|
let path = req.uri().path().to_string();
|
||||||
|
|
||||||
|
let log = local_log.clone();
|
||||||
|
let request_result: Box<dyn Future<Item = Response<_>, Error = _> + Send> =
|
||||||
|
match (req.method(), path.as_ref()) {
|
||||||
|
// Methods for Client
|
||||||
|
(&Method::GET, "/node/version") => into_boxfut(node::get_version(req)),
|
||||||
|
(&Method::GET, "/node/genesis_time") => {
|
||||||
|
into_boxfut(node::get_genesis_time::<T>(req, beacon_chain))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/node/syncing") => {
|
||||||
|
into_boxfut(helpers::implementation_pending_response(req))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods for Network
|
||||||
|
(&Method::GET, "/network/enr") => {
|
||||||
|
into_boxfut(network::get_enr::<T>(req, network_service))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/network/peer_count") => {
|
||||||
|
into_boxfut(network::get_peer_count::<T>(req, network_service))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/network/peer_id") => {
|
||||||
|
into_boxfut(network::get_peer_id::<T>(req, network_service))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/network/peers") => {
|
||||||
|
into_boxfut(network::get_peer_list::<T>(req, network_service))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/network/listen_port") => {
|
||||||
|
into_boxfut(network::get_listen_port::<T>(req, network_service))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/network/listen_addresses") => {
|
||||||
|
into_boxfut(network::get_listen_addresses::<T>(req, network_service))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods for Beacon Node
|
||||||
|
(&Method::GET, "/beacon/head") => into_boxfut(beacon::get_head::<T>(req, beacon_chain)),
|
||||||
|
(&Method::GET, "/beacon/block") => {
|
||||||
|
into_boxfut(beacon::get_block::<T>(req, beacon_chain))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/beacon/block_root") => {
|
||||||
|
into_boxfut(beacon::get_block_root::<T>(req, beacon_chain))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/beacon/blocks") => {
|
||||||
|
into_boxfut(helpers::implementation_pending_response(req))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/beacon/fork") => into_boxfut(beacon::get_fork::<T>(req, beacon_chain)),
|
||||||
|
(&Method::GET, "/beacon/attestations") => {
|
||||||
|
into_boxfut(helpers::implementation_pending_response(req))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/beacon/attestations/pending") => {
|
||||||
|
into_boxfut(helpers::implementation_pending_response(req))
|
||||||
|
}
|
||||||
|
|
||||||
|
(&Method::GET, "/beacon/validators") => {
|
||||||
|
into_boxfut(beacon::get_validators::<T>(req, beacon_chain))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/beacon/validators/indicies") => {
|
||||||
|
into_boxfut(helpers::implementation_pending_response(req))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/beacon/validators/pubkeys") => {
|
||||||
|
into_boxfut(helpers::implementation_pending_response(req))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods for Validator
|
||||||
|
(&Method::GET, "/validator/duties") => {
|
||||||
|
into_boxfut(validator::get_validator_duties::<T>(req, beacon_chain, log))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/validator/block") => {
|
||||||
|
into_boxfut(validator::get_new_beacon_block::<T>(req, beacon_chain))
|
||||||
|
}
|
||||||
|
(&Method::POST, "/validator/block") => {
|
||||||
|
validator::publish_beacon_block::<T>(req, beacon_chain, network_channel, log)
|
||||||
|
}
|
||||||
|
(&Method::GET, "/validator/attestation") => {
|
||||||
|
into_boxfut(validator::get_new_attestation::<T>(req, beacon_chain))
|
||||||
|
}
|
||||||
|
(&Method::POST, "/validator/attestation") => {
|
||||||
|
validator::publish_attestation::<T>(req, beacon_chain, network_channel, log)
|
||||||
|
}
|
||||||
|
|
||||||
|
(&Method::GET, "/beacon/state") => {
|
||||||
|
into_boxfut(beacon::get_state::<T>(req, beacon_chain))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/beacon/state_root") => {
|
||||||
|
into_boxfut(beacon::get_state_root::<T>(req, beacon_chain))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/beacon/state/current_finalized_checkpoint") => into_boxfut(
|
||||||
|
beacon::get_current_finalized_checkpoint::<T>(req, beacon_chain),
|
||||||
|
),
|
||||||
|
(&Method::GET, "/beacon/state/genesis") => {
|
||||||
|
into_boxfut(beacon::get_genesis_state::<T>(req, beacon_chain))
|
||||||
|
}
|
||||||
|
//TODO: Add aggreggate/filtered state lookups here, e.g. /beacon/validators/balances
|
||||||
|
|
||||||
|
// Methods for bootstrap and checking configuration
|
||||||
|
(&Method::GET, "/spec") => into_boxfut(spec::get_spec::<T>(req, beacon_chain)),
|
||||||
|
(&Method::GET, "/spec/slots_per_epoch") => {
|
||||||
|
into_boxfut(spec::get_slots_per_epoch::<T>(req))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/spec/deposit_contract") => {
|
||||||
|
into_boxfut(helpers::implementation_pending_response(req))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/spec/eth2_config") => {
|
||||||
|
into_boxfut(spec::get_eth2_config::<T>(req, eth2_config))
|
||||||
|
}
|
||||||
|
|
||||||
|
(&Method::GET, "/metrics") => {
|
||||||
|
into_boxfut(metrics::get_prometheus::<T>(req, beacon_chain, db_path))
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => Box::new(futures::future::err(ApiError::NotFound(
|
||||||
|
"Request path and/or method not found.".to_owned(),
|
||||||
|
))),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Map the Rust-friendly `Result` in to a http-friendly response. In effect, this ensures that
|
||||||
|
// any `Err` returned from our response handlers becomes a valid http response to the client
|
||||||
|
// (e.g., a response with a 404 or 500 status).
|
||||||
|
request_result.then(move |result| match result {
|
||||||
|
Ok(response) => {
|
||||||
|
debug!(local_log, "Request successful: {:?}", path);
|
||||||
|
metrics::inc_counter(&metrics::SUCCESS_COUNT);
|
||||||
|
metrics::stop_timer(timer);
|
||||||
|
|
||||||
|
Ok(response)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
let error_response = e.into();
|
||||||
|
|
||||||
|
debug!(local_log, "Request failure: {:?}", path);
|
||||||
|
metrics::stop_timer(timer);
|
||||||
|
|
||||||
|
Ok(error_response)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,26 +1,24 @@
|
|||||||
use super::ApiResult;
|
use super::ApiResult;
|
||||||
use crate::helpers::get_beacon_chain_from_request;
|
|
||||||
use crate::response_builder::ResponseBuilder;
|
use crate::response_builder::ResponseBuilder;
|
||||||
use crate::ApiError;
|
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
||||||
use beacon_chain::BeaconChainTypes;
|
|
||||||
use eth2_config::Eth2Config;
|
use eth2_config::Eth2Config;
|
||||||
use hyper::{Body, Request};
|
use hyper::{Body, Request};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::EthSpec;
|
use types::EthSpec;
|
||||||
|
|
||||||
/// HTTP handler to return the full spec object.
|
/// HTTP handler to return the full spec object.
|
||||||
pub fn get_spec<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_spec<T: BeaconChainTypes + 'static>(
|
||||||
let beacon_chain = get_beacon_chain_from_request::<T>(&req)?;
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
) -> ApiResult {
|
||||||
ResponseBuilder::new(&req)?.body_no_ssz(&beacon_chain.spec)
|
ResponseBuilder::new(&req)?.body_no_ssz(&beacon_chain.spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP handler to return the full Eth2Config object.
|
/// HTTP handler to return the full Eth2Config object.
|
||||||
pub fn get_eth2_config<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_eth2_config<T: BeaconChainTypes + 'static>(
|
||||||
let eth2_config = req
|
req: Request<Body>,
|
||||||
.extensions()
|
eth2_config: Arc<Eth2Config>,
|
||||||
.get::<Arc<Eth2Config>>()
|
) -> ApiResult {
|
||||||
.ok_or_else(|| ApiError::ServerError("Eth2Config extension missing".to_string()))?;
|
|
||||||
|
|
||||||
ResponseBuilder::new(&req)?.body_no_ssz(eth2_config.as_ref())
|
ResponseBuilder::new(&req)?.body_no_ssz(eth2_config.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
use crate::helpers::{
|
use crate::helpers::{
|
||||||
check_content_type_for_json, get_beacon_chain_from_request, get_logger_from_request,
|
check_content_type_for_json, parse_pubkey, parse_signature, publish_attestation_to_network,
|
||||||
parse_pubkey, parse_signature, publish_attestation_to_network, publish_beacon_block_to_network,
|
publish_beacon_block_to_network,
|
||||||
};
|
};
|
||||||
use crate::response_builder::ResponseBuilder;
|
use crate::response_builder::ResponseBuilder;
|
||||||
use crate::{ApiError, ApiResult, BoxFut, UrlQuery};
|
use crate::{ApiError, ApiResult, BoxFut, NetworkChannel, UrlQuery};
|
||||||
use beacon_chain::{AttestationProcessingOutcome, BeaconChainTypes, BlockProcessingOutcome};
|
use beacon_chain::{
|
||||||
|
AttestationProcessingOutcome, BeaconChain, BeaconChainTypes, BlockProcessingOutcome,
|
||||||
|
};
|
||||||
use bls::{AggregateSignature, PublicKey, BLS_PUBLIC_KEY_BYTE_SIZE};
|
use bls::{AggregateSignature, PublicKey, BLS_PUBLIC_KEY_BYTE_SIZE};
|
||||||
use futures::future::Future;
|
use futures::future::Future;
|
||||||
use futures::stream::Stream;
|
use futures::stream::Stream;
|
||||||
use hyper::{Body, Request};
|
use hyper::{Body, Request};
|
||||||
use network::NetworkMessage;
|
|
||||||
use parking_lot::RwLock;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use slog::{info, trace, warn};
|
use slog::{info, trace, warn, Logger};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio;
|
|
||||||
use tokio::sync::mpsc;
|
|
||||||
use types::beacon_state::EthSpec;
|
use types::beacon_state::EthSpec;
|
||||||
use types::{Attestation, BeaconBlock, BitList, Epoch, RelativeEpoch, Shard, Slot};
|
use types::{Attestation, BeaconBlock, BitList, Epoch, RelativeEpoch, Shard, Slot};
|
||||||
|
|
||||||
@@ -44,10 +42,12 @@ impl ValidatorDuty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP Handler to retrieve a the duties for a set of validators during a particular epoch
|
/// HTTP Handler to retrieve a the duties for a set of validators during a particular epoch
|
||||||
pub fn get_validator_duties<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_validator_duties<T: BeaconChainTypes + 'static>(
|
||||||
let log = get_logger_from_request(&req);
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
log: Logger,
|
||||||
|
) -> ApiResult {
|
||||||
slog::trace!(log, "Validator duties requested of API: {:?}", &req);
|
slog::trace!(log, "Validator duties requested of API: {:?}", &req);
|
||||||
let beacon_chain = get_beacon_chain_from_request::<T>(&req)?;
|
|
||||||
let mut head_state = beacon_chain.head().beacon_state;
|
let mut head_state = beacon_chain.head().beacon_state;
|
||||||
|
|
||||||
slog::trace!(log, "Got head state from request.");
|
slog::trace!(log, "Got head state from request.");
|
||||||
@@ -154,9 +154,10 @@ pub fn get_validator_duties<T: BeaconChainTypes + 'static>(req: Request<Body>) -
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP Handler to produce a new BeaconBlock from the current state, ready to be signed by a validator.
|
/// HTTP Handler to produce a new BeaconBlock from the current state, ready to be signed by a validator.
|
||||||
pub fn get_new_beacon_block<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_new_beacon_block<T: BeaconChainTypes + 'static>(
|
||||||
let beacon_chain = get_beacon_chain_from_request::<T>(&req)?;
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
) -> ApiResult {
|
||||||
let query = UrlQuery::from_request(&req)?;
|
let query = UrlQuery::from_request(&req)?;
|
||||||
let slot = query
|
let slot = query
|
||||||
.first_of(&["slot"])
|
.first_of(&["slot"])
|
||||||
@@ -186,17 +187,13 @@ pub fn get_new_beacon_block<T: BeaconChainTypes + 'static>(req: Request<Body>) -
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP Handler to publish a BeaconBlock, which has been signed by a validator.
|
/// HTTP Handler to publish a BeaconBlock, which has been signed by a validator.
|
||||||
pub fn publish_beacon_block<T: BeaconChainTypes + 'static>(req: Request<Body>) -> BoxFut {
|
pub fn publish_beacon_block<T: BeaconChainTypes + 'static>(
|
||||||
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
network_chan: NetworkChannel,
|
||||||
|
log: Logger,
|
||||||
|
) -> BoxFut {
|
||||||
try_future!(check_content_type_for_json(&req));
|
try_future!(check_content_type_for_json(&req));
|
||||||
let log = get_logger_from_request(&req);
|
|
||||||
let beacon_chain = try_future!(get_beacon_chain_from_request::<T>(&req));
|
|
||||||
// Get the network sending channel from the request, for later transmission
|
|
||||||
let network_chan = req
|
|
||||||
.extensions()
|
|
||||||
.get::<Arc<RwLock<mpsc::UnboundedSender<NetworkMessage>>>>()
|
|
||||||
.expect("Should always get the network channel from the request, since we put it in there.")
|
|
||||||
.clone();
|
|
||||||
|
|
||||||
let response_builder = ResponseBuilder::new(&req);
|
let response_builder = ResponseBuilder::new(&req);
|
||||||
|
|
||||||
let body = req.into_body();
|
let body = req.into_body();
|
||||||
@@ -239,8 +236,10 @@ pub fn publish_beacon_block<T: BeaconChainTypes + 'static>(req: Request<Body>) -
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP Handler to produce a new Attestation from the current state, ready to be signed by a validator.
|
/// HTTP Handler to produce a new Attestation from the current state, ready to be signed by a validator.
|
||||||
pub fn get_new_attestation<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_new_attestation<T: BeaconChainTypes + 'static>(
|
||||||
let beacon_chain = get_beacon_chain_from_request::<T>(&req)?;
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
) -> ApiResult {
|
||||||
let mut head_state = beacon_chain.head().beacon_state;
|
let mut head_state = beacon_chain.head().beacon_state;
|
||||||
|
|
||||||
let query = UrlQuery::from_request(&req)?;
|
let query = UrlQuery::from_request(&req)?;
|
||||||
@@ -347,17 +346,13 @@ pub fn get_new_attestation<T: BeaconChainTypes + 'static>(req: Request<Body>) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP Handler to publish an Attestation, which has been signed by a validator.
|
/// HTTP Handler to publish an Attestation, which has been signed by a validator.
|
||||||
pub fn publish_attestation<T: BeaconChainTypes + 'static>(req: Request<Body>) -> BoxFut {
|
pub fn publish_attestation<T: BeaconChainTypes + 'static>(
|
||||||
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
network_chan: NetworkChannel,
|
||||||
|
log: Logger,
|
||||||
|
) -> BoxFut {
|
||||||
try_future!(check_content_type_for_json(&req));
|
try_future!(check_content_type_for_json(&req));
|
||||||
let log = get_logger_from_request(&req);
|
|
||||||
let beacon_chain = try_future!(get_beacon_chain_from_request::<T>(&req));
|
|
||||||
// Get the network sending channel from the request, for later transmission
|
|
||||||
let network_chan = req
|
|
||||||
.extensions()
|
|
||||||
.get::<Arc<RwLock<mpsc::UnboundedSender<NetworkMessage>>>>()
|
|
||||||
.expect("Should always get the network channel from the request, since we put it in there.")
|
|
||||||
.clone();
|
|
||||||
|
|
||||||
let response_builder = ResponseBuilder::new(&req);
|
let response_builder = ResponseBuilder::new(&req);
|
||||||
|
|
||||||
let body = req.into_body();
|
let body = req.into_body();
|
||||||
|
|||||||
Reference in New Issue
Block a user