Tidy API to be more consistent with recent decisions
This commit is contained in:
parent
a8daf46d5f
commit
b912e26b79
@ -33,7 +33,7 @@ pub struct Service {
|
||||
//TODO: Make this private
|
||||
pub swarm: Swarm<Libp2pStream, Libp2pBehaviour>,
|
||||
/// This node's PeerId.
|
||||
_local_peer_id: PeerId,
|
||||
pub local_peer_id: PeerId,
|
||||
/// The libp2p logger handle.
|
||||
pub log: slog::Logger,
|
||||
}
|
||||
@ -113,7 +113,7 @@ impl Service {
|
||||
info!(log, "Subscribed to topics: {:?}", subscribed_topics);
|
||||
|
||||
Ok(Service {
|
||||
_local_peer_id: local_peer_id,
|
||||
local_peer_id,
|
||||
swarm,
|
||||
log,
|
||||
})
|
||||
|
@ -75,6 +75,11 @@ impl<T: BeaconChainTypes + 'static> Service<T> {
|
||||
.clone()
|
||||
}
|
||||
|
||||
/// Returns the local libp2p PeerID.
|
||||
pub fn local_peer_id(&self) -> PeerId {
|
||||
self.libp2p_service.lock().local_peer_id.clone()
|
||||
}
|
||||
|
||||
/// Returns the list of `Multiaddr` that the underlying libp2p instance is listening on.
|
||||
pub fn listen_multiaddrs(&self) -> Vec<Multiaddr> {
|
||||
Swarm::listeners(&self.libp2p_service.lock().swarm)
|
||||
|
@ -2,25 +2,44 @@ use super::{success_response, ApiResult};
|
||||
use crate::{helpers::*, ApiError, UrlQuery};
|
||||
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
||||
use hyper::{Body, Request};
|
||||
use serde::Serialize;
|
||||
use std::sync::Arc;
|
||||
use store::Store;
|
||||
use types::{BeaconBlock, BeaconState};
|
||||
use types::{BeaconBlock, BeaconState, EthSpec, Hash256, Slot};
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct HeadResponse {
|
||||
pub slot: Slot,
|
||||
pub block_root: Hash256,
|
||||
pub state_root: Hash256,
|
||||
}
|
||||
|
||||
/// HTTP handler to return a `BeaconBlock` at a given `root` or `slot`.
|
||||
pub fn get_best_slot<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
||||
pub fn get_head<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 slot = beacon_chain.head().beacon_state.slot;
|
||||
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,
|
||||
};
|
||||
|
||||
let json: String = serde_json::to_string(&slot)
|
||||
.map_err(|e| ApiError::ServerError(format!("Unable to serialize Slot: {:?}", e)))?;
|
||||
let json: String = serde_json::to_string(&head)
|
||||
.map_err(|e| ApiError::ServerError(format!("Unable to serialize HeadResponse: {:?}", e)))?;
|
||||
|
||||
Ok(success_response(Body::from(json)))
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(bound = "T: EthSpec")]
|
||||
struct BlockResponse<T: EthSpec> {
|
||||
pub root: Hash256,
|
||||
pub beacon_block: BeaconBlock<T>,
|
||||
}
|
||||
|
||||
/// HTTP handler to return a `BeaconBlock` at a given `root` or `slot`.
|
||||
pub fn get_block<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
||||
let beacon_chain = req
|
||||
@ -58,8 +77,14 @@ pub fn get_block<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult
|
||||
))
|
||||
})?;
|
||||
|
||||
let json: String = serde_json::to_string(&block)
|
||||
.map_err(|e| ApiError::ServerError(format!("Unable to serialize BeaconBlock: {:?}", e)))?;
|
||||
let response = BlockResponse {
|
||||
root: block_root,
|
||||
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)))
|
||||
}
|
||||
@ -89,6 +114,13 @@ pub fn get_block_root<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiR
|
||||
Ok(success_response(Body::from(json)))
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(bound = "T: EthSpec")]
|
||||
struct StateResponse<T: EthSpec> {
|
||||
pub root: Hash256,
|
||||
pub beacon_state: BeaconState<T>,
|
||||
}
|
||||
|
||||
/// 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
|
||||
@ -102,21 +134,29 @@ pub fn get_state<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult
|
||||
let query_params = ["root", "slot"];
|
||||
let (key, value) = UrlQuery::from_request(&req)?.first_of(&query_params)?;
|
||||
|
||||
let state: BeaconState<T::EthSpec> = match (key.as_ref(), value) {
|
||||
let (root, state): (Hash256, BeaconState<T::EthSpec>) = match (key.as_ref(), value) {
|
||||
("slot", value) => state_at_slot(&beacon_chain, parse_slot(&value)?)?,
|
||||
("root", value) => {
|
||||
let root = &parse_root(&value)?;
|
||||
|
||||
beacon_chain
|
||||
let state = beacon_chain
|
||||
.store
|
||||
.get(root)?
|
||||
.ok_or_else(|| ApiError::NotFound(format!("No state for root: {}", root)))?
|
||||
.ok_or_else(|| ApiError::NotFound(format!("No state for root: {}", root)))?;
|
||||
|
||||
(*root, state)
|
||||
}
|
||||
_ => return Err(ApiError::ServerError("Unexpected query parameter".into())),
|
||||
};
|
||||
|
||||
let json: String = serde_json::to_string(&state)
|
||||
.map_err(|e| ApiError::ServerError(format!("Unable to serialize BeaconState: {:?}", e)))?;
|
||||
let response = StateResponse {
|
||||
root,
|
||||
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)))
|
||||
}
|
||||
|
@ -31,22 +31,25 @@ pub fn parse_root(string: &str) -> Result<Hash256, ApiError> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a `BeaconState` in the canonical chain of `beacon_chain` at the given `slot`, if
|
||||
/// possible.
|
||||
/// Returns a `BeaconState` and it's root in the canonical chain of `beacon_chain` at the given
|
||||
/// `slot`, if possible.
|
||||
///
|
||||
/// 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 state_at_slot<T: BeaconChainTypes>(
|
||||
beacon_chain: &BeaconChain<T>,
|
||||
slot: Slot,
|
||||
) -> Result<BeaconState<T::EthSpec>, ApiError> {
|
||||
) -> Result<(Hash256, BeaconState<T::EthSpec>), ApiError> {
|
||||
let head_state = &beacon_chain.head().beacon_state;
|
||||
|
||||
if head_state.slot == slot {
|
||||
// The request slot is the same as the best block (head) slot.
|
||||
|
||||
// I'm not sure if this `.clone()` will be optimized out. If not, it seems unnecessary.
|
||||
Ok(beacon_chain.head().beacon_state.clone())
|
||||
Ok((
|
||||
beacon_chain.head().beacon_state_root,
|
||||
beacon_chain.head().beacon_state.clone(),
|
||||
))
|
||||
} else {
|
||||
let root = state_root_at_slot(beacon_chain, slot)?;
|
||||
|
||||
@ -55,7 +58,7 @@ pub fn state_at_slot<T: BeaconChainTypes>(
|
||||
.get(&root)?
|
||||
.ok_or_else(|| ApiError::NotFound(format!("Unable to find state at root {}", root)))?;
|
||||
|
||||
Ok(state)
|
||||
Ok((root, state))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,7 +121,7 @@ pub fn start_server<T: BeaconChainTypes + Clone + Send + Sync + 'static>(
|
||||
|
||||
// Route the request to the correct handler.
|
||||
let result = match (req.method(), path.as_ref()) {
|
||||
(&Method::GET, "/beacon/best_slot") => beacon::get_best_slot::<T>(req),
|
||||
(&Method::GET, "/beacon/head") => beacon::get_head::<T>(req),
|
||||
(&Method::GET, "/beacon/block") => beacon::get_block::<T>(req),
|
||||
(&Method::GET, "/beacon/block_root") => beacon::get_block_root::<T>(req),
|
||||
(&Method::GET, "/beacon/latest_finalized_checkpoint") => {
|
||||
@ -130,14 +130,15 @@ pub fn start_server<T: BeaconChainTypes + Clone + Send + Sync + 'static>(
|
||||
(&Method::GET, "/beacon/state") => beacon::get_state::<T>(req),
|
||||
(&Method::GET, "/beacon/state_root") => beacon::get_state_root::<T>(req),
|
||||
(&Method::GET, "/metrics") => metrics::get_prometheus::<T>(req),
|
||||
(&Method::GET, "/node/version") => node::get_version(req),
|
||||
(&Method::GET, "/node/genesis_time") => node::get_genesis_time::<T>(req),
|
||||
(&Method::GET, "/node/network/enr") => network::get_enr::<T>(req),
|
||||
(&Method::GET, "/node/network/peer_count") => network::get_peer_count::<T>(req),
|
||||
(&Method::GET, "/node/network/peers") => network::get_peer_list::<T>(req),
|
||||
(&Method::GET, "/node/network/listen_addresses") => {
|
||||
(&Method::GET, "/network/enr") => network::get_enr::<T>(req),
|
||||
(&Method::GET, "/network/peer_count") => network::get_peer_count::<T>(req),
|
||||
(&Method::GET, "/network/peer_id") => network::get_peer_id::<T>(req),
|
||||
(&Method::GET, "/network/peers") => network::get_peer_list::<T>(req),
|
||||
(&Method::GET, "/network/listen_addresses") => {
|
||||
network::get_listen_addresses::<T>(req)
|
||||
}
|
||||
(&Method::GET, "/node/version") => node::get_version(req),
|
||||
(&Method::GET, "/node/genesis_time") => node::get_genesis_time::<T>(req),
|
||||
(&Method::GET, "/spec") => spec::get_spec::<T>(req),
|
||||
(&Method::GET, "/spec/slots_per_epoch") => spec::get_slots_per_epoch::<T>(req),
|
||||
_ => Err(ApiError::MethodNotAllowed(path.clone())),
|
||||
|
@ -40,6 +40,23 @@ pub fn get_enr<T: BeaconChainTypes + Send + Sync + 'static>(req: Request<Body>)
|
||||
)))
|
||||
}
|
||||
|
||||
/// HTTP handle to return the `PeerId` from the client's libp2p service.
|
||||
///
|
||||
/// PeerId is encoded as base58 string.
|
||||
pub fn get_peer_id<T: BeaconChainTypes + Send + Sync + 'static>(req: Request<Body>) -> ApiResult {
|
||||
let network = req
|
||||
.extensions()
|
||||
.get::<Arc<NetworkService<T>>>()
|
||||
.ok_or_else(|| ApiError::ServerError("NetworkService extension missing".to_string()))?;
|
||||
|
||||
let peer_id: PeerId = network.local_peer_id();
|
||||
|
||||
Ok(success_response(Body::from(
|
||||
serde_json::to_string(&peer_id.to_base58())
|
||||
.map_err(|e| ApiError::ServerError(format!("Unable to serialize Enr: {:?}", e)))?,
|
||||
)))
|
||||
}
|
||||
|
||||
/// HTTP handle to return the number of peers connected in the client's libp2p service.
|
||||
pub fn get_peer_count<T: BeaconChainTypes + Send + Sync + 'static>(
|
||||
req: Request<Body>,
|
||||
|
Loading…
Reference in New Issue
Block a user