Add beacon_block methods to rest api
This commit is contained in:
parent
4f98a3985f
commit
2bf0d5c071
@ -2,7 +2,7 @@ use reqwest::{Error as HttpError, Url};
|
|||||||
use types::{BeaconBlock, BeaconState, Checkpoint, EthSpec, Slot};
|
use types::{BeaconBlock, BeaconState, Checkpoint, EthSpec, Slot};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
enum Error {
|
||||||
UrlCannotBeBase,
|
UrlCannotBeBase,
|
||||||
HttpError(HttpError),
|
HttpError(HttpError),
|
||||||
}
|
}
|
||||||
@ -21,16 +21,22 @@ pub struct BootstrapParams<T: EthSpec> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: EthSpec> BootstrapParams<T> {
|
impl<T: EthSpec> BootstrapParams<T> {
|
||||||
pub fn from_http_api(url: Url) -> Result<Self, Error> {
|
pub fn from_http_api(url: Url) -> Result<Self, String> {
|
||||||
let slots_per_epoch = get_slots_per_epoch(url.clone())?;
|
let slots_per_epoch = get_slots_per_epoch(url.clone())
|
||||||
|
.map_err(|e| format!("Unable to get slots per epoch: {:?}", e))?;
|
||||||
let genesis_slot = Slot::new(0);
|
let genesis_slot = Slot::new(0);
|
||||||
let finalized_slot = get_finalized_slot(url.clone(), slots_per_epoch.as_u64())?;
|
let finalized_slot = get_finalized_slot(url.clone(), slots_per_epoch.as_u64())
|
||||||
|
.map_err(|e| format!("Unable to get finalized slot: {:?}", e))?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
finalized_block: get_block(url.clone(), finalized_slot)?,
|
finalized_block: get_block(url.clone(), finalized_slot)
|
||||||
finalized_state: get_state(url.clone(), finalized_slot)?,
|
.map_err(|e| format!("Unable to get finalized block: {:?}", e))?,
|
||||||
genesis_block: get_block(url.clone(), genesis_slot)?,
|
finalized_state: get_state(url.clone(), finalized_slot)
|
||||||
genesis_state: get_state(url.clone(), genesis_slot)?,
|
.map_err(|e| format!("Unable to get finalized state: {:?}", e))?,
|
||||||
|
genesis_block: get_block(url.clone(), genesis_slot)
|
||||||
|
.map_err(|e| format!("Unable to get genesis block: {:?}", e))?,
|
||||||
|
genesis_state: get_state(url.clone(), genesis_slot)
|
||||||
|
.map_err(|e| format!("Unable to get genesis state: {:?}", e))?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,75 @@ use beacon_chain::{BeaconChain, BeaconChainTypes};
|
|||||||
use hyper::{Body, Request};
|
use hyper::{Body, Request};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use store::Store;
|
use store::Store;
|
||||||
use types::BeaconState;
|
use types::{BeaconBlock, BeaconState};
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
.extensions()
|
||||||
|
.get::<Arc<BeaconChain<T>>>()
|
||||||
|
.ok_or_else(|| ApiError::ServerError("Beacon chain extension missing".to_string()))?;
|
||||||
|
|
||||||
|
let query_params = ["root", "slot"];
|
||||||
|
let (key, value) = UrlQuery::from_request(&req)?.first_of(&query_params)?;
|
||||||
|
|
||||||
|
let block_root = match (key.as_ref(), value) {
|
||||||
|
("slot", value) => {
|
||||||
|
let target = parse_slot(&value)?;
|
||||||
|
|
||||||
|
beacon_chain
|
||||||
|
.rev_iter_block_roots()
|
||||||
|
.take_while(|(_root, slot)| *slot >= target)
|
||||||
|
.find(|(_root, slot)| *slot == target)
|
||||||
|
.map(|(root, _slot)| root)
|
||||||
|
.ok_or_else(|| {
|
||||||
|
ApiError::NotFound(format!("Unable to find BeaconBlock for slot {}", target))
|
||||||
|
})?
|
||||||
|
}
|
||||||
|
("root", value) => parse_root(&value)?,
|
||||||
|
_ => return Err(ApiError::ServerError("Unexpected query parameter".into())),
|
||||||
|
};
|
||||||
|
|
||||||
|
let block = beacon_chain
|
||||||
|
.store
|
||||||
|
.get::<BeaconBlock<T::EthSpec>>(&block_root)?
|
||||||
|
.ok_or_else(|| {
|
||||||
|
ApiError::NotFound(format!(
|
||||||
|
"Unable to find BeaconBlock for root {}",
|
||||||
|
block_root
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let json: String = serde_json::to_string(&block)
|
||||||
|
.map_err(|e| ApiError::ServerError(format!("Unable to serialize BeaconBlock: {:?}", e)))?;
|
||||||
|
|
||||||
|
Ok(success_response(Body::from(json)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// HTTP handler to return a `BeaconBlock` root at a given `slot`.
|
||||||
|
pub fn get_block_root<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_string = UrlQuery::from_request(&req)?.only_one("slot")?;
|
||||||
|
let target = parse_slot(&slot_string)?;
|
||||||
|
|
||||||
|
let root = beacon_chain
|
||||||
|
.rev_iter_block_roots()
|
||||||
|
.take_while(|(_root, slot)| *slot >= target)
|
||||||
|
.find(|(_root, slot)| *slot == target)
|
||||||
|
.map(|(root, _slot)| root)
|
||||||
|
.ok_or_else(|| {
|
||||||
|
ApiError::NotFound(format!("Unable to find BeaconBlock for slot {}", target))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let json: String = serde_json::to_string(&root)
|
||||||
|
.map_err(|e| ApiError::ServerError(format!("Unable to serialize root: {:?}", e)))?;
|
||||||
|
|
||||||
|
Ok(success_response(Body::from(json)))
|
||||||
|
}
|
||||||
|
|
||||||
/// HTTP handler to return a `BeaconState` at a given `root` or `slot`.
|
/// HTTP handler to return a `BeaconState` at a given `root` or `slot`.
|
||||||
///
|
///
|
||||||
@ -29,7 +97,7 @@ pub fn get_state<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult
|
|||||||
.get(root)?
|
.get(root)?
|
||||||
.ok_or_else(|| ApiError::NotFound(format!("No state for root: {}", root)))?
|
.ok_or_else(|| ApiError::NotFound(format!("No state for root: {}", root)))?
|
||||||
}
|
}
|
||||||
_ => unreachable!("Guarded by UrlQuery::from_request()"),
|
_ => return Err(ApiError::ServerError("Unexpected query parameter".into())),
|
||||||
};
|
};
|
||||||
|
|
||||||
let json: String = serde_json::to_string(&state)
|
let json: String = serde_json::to_string(&state)
|
||||||
@ -38,7 +106,7 @@ pub fn get_state<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult
|
|||||||
Ok(success_response(Body::from(json)))
|
Ok(success_response(Body::from(json)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP handler to return a `BeaconState` root at a given or `slot`.
|
/// HTTP handler to return a `BeaconState` root at a given `slot`.
|
||||||
///
|
///
|
||||||
/// 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.
|
||||||
|
@ -102,6 +102,8 @@ pub fn start_server<T: BeaconChainTypes + Clone + 'static>(
|
|||||||
|
|
||||||
// Route the request to the correct handler.
|
// Route the request to the correct handler.
|
||||||
let result = match (req.method(), path.as_ref()) {
|
let result = match (req.method(), path.as_ref()) {
|
||||||
|
(&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") => {
|
(&Method::GET, "/beacon/latest_finalized_checkpoint") => {
|
||||||
beacon::get_latest_finalized_checkpoint::<T>(req)
|
beacon::get_latest_finalized_checkpoint::<T>(req)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user