Merge branch 'bootstrap' into interop
This commit is contained in:
commit
112e323c1e
@ -77,7 +77,7 @@ pub enum AttestationProcessingOutcome {
|
|||||||
Invalid(AttestationValidationError),
|
Invalid(AttestationValidationError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BeaconChainTypes {
|
pub trait BeaconChainTypes: Send + Sync + 'static {
|
||||||
type Store: store::Store;
|
type Store: store::Store;
|
||||||
type SlotClock: slot_clock::SlotClock;
|
type SlotClock: slot_clock::SlotClock;
|
||||||
type LmdGhost: LmdGhost<Self::Store, Self::EthSpec>;
|
type LmdGhost: LmdGhost<Self::Store, Self::EthSpec>;
|
||||||
|
@ -54,8 +54,8 @@ where
|
|||||||
|
|
||||||
impl<L, E> BeaconChainTypes for CommonTypes<L, E>
|
impl<L, E> BeaconChainTypes for CommonTypes<L, E>
|
||||||
where
|
where
|
||||||
L: LmdGhost<MemoryStore, E>,
|
L: LmdGhost<MemoryStore, E> + 'static,
|
||||||
E: EthSpec,
|
E: EthSpec + 'static,
|
||||||
{
|
{
|
||||||
type Store = MemoryStore;
|
type Store = MemoryStore;
|
||||||
type SlotClock = TestingSlotClock;
|
type SlotClock = TestingSlotClock;
|
||||||
@ -69,8 +69,8 @@ where
|
|||||||
/// Used for testing.
|
/// Used for testing.
|
||||||
pub struct BeaconChainHarness<L, E>
|
pub struct BeaconChainHarness<L, E>
|
||||||
where
|
where
|
||||||
L: LmdGhost<MemoryStore, E>,
|
L: LmdGhost<MemoryStore, E> + 'static,
|
||||||
E: EthSpec,
|
E: EthSpec + 'static,
|
||||||
{
|
{
|
||||||
pub chain: BeaconChain<CommonTypes<L, E>>,
|
pub chain: BeaconChain<CommonTypes<L, E>>,
|
||||||
pub keypairs: Vec<Keypair>,
|
pub keypairs: Vec<Keypair>,
|
||||||
|
@ -36,7 +36,11 @@ pub struct ClientType<S: Store, E: EthSpec> {
|
|||||||
_phantom_u: PhantomData<E>,
|
_phantom_u: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Store, E: EthSpec + Clone> BeaconChainTypes for ClientType<S, E> {
|
impl<S, E> BeaconChainTypes for ClientType<S, E>
|
||||||
|
where
|
||||||
|
S: Store + 'static,
|
||||||
|
E: EthSpec + 'static + Clone,
|
||||||
|
{
|
||||||
type Store = S;
|
type Store = S;
|
||||||
type SlotClock = SystemTimeSlotClock;
|
type SlotClock = SystemTimeSlotClock;
|
||||||
type LmdGhost = ThreadSafeReducedTree<S, E>;
|
type LmdGhost = ThreadSafeReducedTree<S, E>;
|
||||||
|
@ -10,7 +10,7 @@ use url::Host;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Error {
|
enum Error {
|
||||||
UrlCannotBeBase,
|
InvalidUrl,
|
||||||
HttpError(HttpError),
|
HttpError(HttpError),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ impl Bootstrapper {
|
|||||||
|
|
||||||
/// Build a multiaddr using the HTTP server URL that is not guaranteed to be correct.
|
/// Build a multiaddr using the HTTP server URL that is not guaranteed to be correct.
|
||||||
///
|
///
|
||||||
/// The address is created by querying the HTTP server for it's listening libp2p addresses.
|
/// The address is created by querying the HTTP server for its listening libp2p addresses.
|
||||||
/// Then, we find the first TCP port in those addresses and combine the port with the URL of
|
/// Then, we find the first TCP port in those addresses and combine the port with the URL of
|
||||||
/// the server.
|
/// the server.
|
||||||
///
|
///
|
||||||
@ -124,7 +124,7 @@ fn get_slots_per_epoch(mut url: Url) -> Result<Slot, Error> {
|
|||||||
.map(|mut url| {
|
.map(|mut url| {
|
||||||
url.push("spec").push("slots_per_epoch");
|
url.push("spec").push("slots_per_epoch");
|
||||||
})
|
})
|
||||||
.map_err(|_| Error::UrlCannotBeBase)?;
|
.map_err(|_| Error::InvalidUrl)?;
|
||||||
|
|
||||||
reqwest::get(url)?
|
reqwest::get(url)?
|
||||||
.error_for_status()?
|
.error_for_status()?
|
||||||
@ -137,7 +137,7 @@ fn get_finalized_slot(mut url: Url, slots_per_epoch: u64) -> Result<Slot, Error>
|
|||||||
.map(|mut url| {
|
.map(|mut url| {
|
||||||
url.push("beacon").push("latest_finalized_checkpoint");
|
url.push("beacon").push("latest_finalized_checkpoint");
|
||||||
})
|
})
|
||||||
.map_err(|_| Error::UrlCannotBeBase)?;
|
.map_err(|_| Error::InvalidUrl)?;
|
||||||
|
|
||||||
let checkpoint: Checkpoint = reqwest::get(url)?.error_for_status()?.json()?;
|
let checkpoint: Checkpoint = reqwest::get(url)?.error_for_status()?.json()?;
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ fn get_state<T: EthSpec>(mut url: Url, slot: Slot) -> Result<BeaconState<T>, Err
|
|||||||
.map(|mut url| {
|
.map(|mut url| {
|
||||||
url.push("beacon").push("state");
|
url.push("beacon").push("state");
|
||||||
})
|
})
|
||||||
.map_err(|_| Error::UrlCannotBeBase)?;
|
.map_err(|_| Error::InvalidUrl)?;
|
||||||
|
|
||||||
url.query_pairs_mut()
|
url.query_pairs_mut()
|
||||||
.append_pair("slot", &format!("{}", slot.as_u64()));
|
.append_pair("slot", &format!("{}", slot.as_u64()));
|
||||||
@ -165,7 +165,7 @@ fn get_block<T: EthSpec>(mut url: Url, slot: Slot) -> Result<BeaconBlock<T>, Err
|
|||||||
.map(|mut url| {
|
.map(|mut url| {
|
||||||
url.push("beacon").push("block");
|
url.push("beacon").push("block");
|
||||||
})
|
})
|
||||||
.map_err(|_| Error::UrlCannotBeBase)?;
|
.map_err(|_| Error::InvalidUrl)?;
|
||||||
|
|
||||||
url.query_pairs_mut()
|
url.query_pairs_mut()
|
||||||
.append_pair("slot", &format!("{}", slot.as_u64()));
|
.append_pair("slot", &format!("{}", slot.as_u64()));
|
||||||
@ -181,7 +181,7 @@ fn get_enr(mut url: Url) -> Result<Enr, Error> {
|
|||||||
.map(|mut url| {
|
.map(|mut url| {
|
||||||
url.push("node").push("network").push("enr");
|
url.push("node").push("network").push("enr");
|
||||||
})
|
})
|
||||||
.map_err(|_| Error::UrlCannotBeBase)?;
|
.map_err(|_| Error::InvalidUrl)?;
|
||||||
|
|
||||||
reqwest::get(url)?
|
reqwest::get(url)?
|
||||||
.error_for_status()?
|
.error_for_status()?
|
||||||
@ -194,7 +194,7 @@ fn get_listen_addresses(mut url: Url) -> Result<Vec<Multiaddr>, Error> {
|
|||||||
.map(|mut url| {
|
.map(|mut url| {
|
||||||
url.push("node").push("network").push("listen_addresses");
|
url.push("node").push("network").push("listen_addresses");
|
||||||
})
|
})
|
||||||
.map_err(|_| Error::UrlCannotBeBase)?;
|
.map_err(|_| Error::InvalidUrl)?;
|
||||||
|
|
||||||
reqwest::get(url)?
|
reqwest::get(url)?
|
||||||
.error_for_status()?
|
.error_for_status()?
|
||||||
|
@ -49,7 +49,7 @@ pub struct Client<T: BeaconChainTypes> {
|
|||||||
|
|
||||||
impl<T> Client<T>
|
impl<T> Client<T>
|
||||||
where
|
where
|
||||||
T: BeaconChainTypes + InitialiseBeaconChain<T> + Clone + Send + Sync + 'static,
|
T: BeaconChainTypes + InitialiseBeaconChain<T> + Clone,
|
||||||
{
|
{
|
||||||
/// Generate an instance of the client. Spawn and link all internal sub-processes.
|
/// Generate an instance of the client. Spawn and link all internal sub-processes.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
@ -17,11 +17,7 @@ pub const WARN_PEER_COUNT: usize = 1;
|
|||||||
/// durations.
|
/// durations.
|
||||||
///
|
///
|
||||||
/// Presently unused, but remains for future use.
|
/// Presently unused, but remains for future use.
|
||||||
pub fn run<T: BeaconChainTypes + Send + Sync + 'static>(
|
pub fn run<T: BeaconChainTypes>(client: &Client<T>, executor: TaskExecutor, exit: Exit) {
|
||||||
client: &Client<T>,
|
|
||||||
executor: TaskExecutor,
|
|
||||||
exit: Exit,
|
|
||||||
) {
|
|
||||||
// notification heartbeat
|
// notification heartbeat
|
||||||
let interval = Interval::new(
|
let interval = Interval::new(
|
||||||
Instant::now(),
|
Instant::now(),
|
||||||
|
@ -33,7 +33,7 @@ pub struct Service {
|
|||||||
//TODO: Make this private
|
//TODO: Make this private
|
||||||
pub swarm: Swarm<Libp2pStream, Libp2pBehaviour>,
|
pub swarm: Swarm<Libp2pStream, Libp2pBehaviour>,
|
||||||
/// This node's PeerId.
|
/// This node's PeerId.
|
||||||
_local_peer_id: PeerId,
|
pub local_peer_id: PeerId,
|
||||||
/// The libp2p logger handle.
|
/// The libp2p logger handle.
|
||||||
pub log: slog::Logger,
|
pub log: slog::Logger,
|
||||||
}
|
}
|
||||||
@ -113,7 +113,7 @@ impl Service {
|
|||||||
info!(log, "Subscribed to topics: {:?}", subscribed_topics);
|
info!(log, "Subscribed to topics: {:?}", subscribed_topics);
|
||||||
|
|
||||||
Ok(Service {
|
Ok(Service {
|
||||||
_local_peer_id: local_peer_id,
|
local_peer_id,
|
||||||
swarm,
|
swarm,
|
||||||
log,
|
log,
|
||||||
})
|
})
|
||||||
|
@ -75,6 +75,11 @@ impl<T: BeaconChainTypes + 'static> Service<T> {
|
|||||||
.clone()
|
.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.
|
/// Returns the list of `Multiaddr` that the underlying libp2p instance is listening on.
|
||||||
pub fn listen_multiaddrs(&self) -> Vec<Multiaddr> {
|
pub fn listen_multiaddrs(&self) -> Vec<Multiaddr> {
|
||||||
Swarm::listeners(&self.libp2p_service.lock().swarm)
|
Swarm::listeners(&self.libp2p_service.lock().swarm)
|
||||||
|
@ -2,25 +2,44 @@ use super::{success_response, ApiResult};
|
|||||||
use crate::{helpers::*, ApiError, UrlQuery};
|
use crate::{helpers::*, ApiError, UrlQuery};
|
||||||
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
||||||
use hyper::{Body, Request};
|
use hyper::{Body, Request};
|
||||||
|
use serde::Serialize;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use store::Store;
|
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`.
|
/// 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
|
let beacon_chain = req
|
||||||
.extensions()
|
.extensions()
|
||||||
.get::<Arc<BeaconChain<T>>>()
|
.get::<Arc<BeaconChain<T>>>()
|
||||||
.ok_or_else(|| ApiError::ServerError("Beacon chain extension missing".to_string()))?;
|
.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)
|
let json: String = serde_json::to_string(&head)
|
||||||
.map_err(|e| ApiError::ServerError(format!("Unable to serialize Slot: {:?}", e)))?;
|
.map_err(|e| ApiError::ServerError(format!("Unable to serialize HeadResponse: {:?}", e)))?;
|
||||||
|
|
||||||
Ok(success_response(Body::from(json)))
|
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`.
|
/// 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>(req: Request<Body>) -> ApiResult {
|
||||||
let beacon_chain = req
|
let beacon_chain = req
|
||||||
@ -35,14 +54,9 @@ pub fn get_block<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult
|
|||||||
("slot", value) => {
|
("slot", value) => {
|
||||||
let target = parse_slot(&value)?;
|
let target = parse_slot(&value)?;
|
||||||
|
|
||||||
beacon_chain
|
block_root_at_slot(&beacon_chain, target).ok_or_else(|| {
|
||||||
.rev_iter_block_roots()
|
ApiError::NotFound(format!("Unable to find BeaconBlock for slot {}", target))
|
||||||
.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)?,
|
("root", value) => parse_root(&value)?,
|
||||||
_ => return Err(ApiError::ServerError("Unexpected query parameter".into())),
|
_ => return Err(ApiError::ServerError("Unexpected query parameter".into())),
|
||||||
@ -58,8 +72,14 @@ pub fn get_block<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult
|
|||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let json: String = serde_json::to_string(&block)
|
let response = BlockResponse {
|
||||||
.map_err(|e| ApiError::ServerError(format!("Unable to serialize BeaconBlock: {:?}", e)))?;
|
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)))
|
Ok(success_response(Body::from(json)))
|
||||||
}
|
}
|
||||||
@ -74,14 +94,9 @@ pub fn get_block_root<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiR
|
|||||||
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)?;
|
||||||
|
|
||||||
let root = beacon_chain
|
let root = block_root_at_slot(&beacon_chain, target).ok_or_else(|| {
|
||||||
.rev_iter_block_roots()
|
ApiError::NotFound(format!("Unable to find BeaconBlock for slot {}", target))
|
||||||
.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)
|
let json: String = serde_json::to_string(&root)
|
||||||
.map_err(|e| ApiError::ServerError(format!("Unable to serialize root: {:?}", e)))?;
|
.map_err(|e| ApiError::ServerError(format!("Unable to serialize root: {:?}", e)))?;
|
||||||
@ -89,6 +104,13 @@ pub fn get_block_root<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiR
|
|||||||
Ok(success_response(Body::from(json)))
|
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`.
|
/// 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
|
/// Will not return a state if the request slot is in the future. Will return states higher than
|
||||||
@ -102,21 +124,29 @@ pub fn get_state<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult
|
|||||||
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)?;
|
||||||
|
|
||||||
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)?)?,
|
("slot", value) => state_at_slot(&beacon_chain, parse_slot(&value)?)?,
|
||||||
("root", value) => {
|
("root", value) => {
|
||||||
let root = &parse_root(&value)?;
|
let root = &parse_root(&value)?;
|
||||||
|
|
||||||
beacon_chain
|
let state = beacon_chain
|
||||||
.store
|
.store
|
||||||
.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)))?;
|
||||||
|
|
||||||
|
(*root, state)
|
||||||
}
|
}
|
||||||
_ => return Err(ApiError::ServerError("Unexpected query parameter".into())),
|
_ => return Err(ApiError::ServerError("Unexpected query parameter".into())),
|
||||||
};
|
};
|
||||||
|
|
||||||
let json: String = serde_json::to_string(&state)
|
let response = StateResponse {
|
||||||
.map_err(|e| ApiError::ServerError(format!("Unable to serialize BeaconState: {:?}", e)))?;
|
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)))
|
Ok(success_response(Body::from(json)))
|
||||||
}
|
}
|
||||||
|
@ -31,22 +31,40 @@ pub fn parse_root(string: &str) -> Result<Hash256, ApiError> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a `BeaconState` in the canonical chain of `beacon_chain` at the given `slot`, if
|
/// Returns the root of the `BeaconBlock` in the canonical chain of `beacon_chain` at the given
|
||||||
/// possible.
|
/// `slot`, if possible.
|
||||||
|
///
|
||||||
|
/// May return a root for a previous slot, in the case of skip slots.
|
||||||
|
pub fn block_root_at_slot<T: BeaconChainTypes>(
|
||||||
|
beacon_chain: &BeaconChain<T>,
|
||||||
|
target: Slot,
|
||||||
|
) -> Option<Hash256> {
|
||||||
|
beacon_chain
|
||||||
|
.rev_iter_block_roots()
|
||||||
|
.take_while(|(_root, slot)| *slot >= target)
|
||||||
|
.find(|(_root, slot)| *slot == target)
|
||||||
|
.map(|(root, _slot)| root)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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
|
/// 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 state_at_slot<T: BeaconChainTypes>(
|
pub fn state_at_slot<T: BeaconChainTypes>(
|
||||||
beacon_chain: &BeaconChain<T>,
|
beacon_chain: &BeaconChain<T>,
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
) -> Result<BeaconState<T::EthSpec>, ApiError> {
|
) -> Result<(Hash256, BeaconState<T::EthSpec>), ApiError> {
|
||||||
let head_state = &beacon_chain.head().beacon_state;
|
let head_state = &beacon_chain.head().beacon_state;
|
||||||
|
|
||||||
if head_state.slot == slot {
|
if head_state.slot == slot {
|
||||||
// The request slot is the same as the best block (head) 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.
|
// 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 {
|
} else {
|
||||||
let root = state_root_at_slot(beacon_chain, slot)?;
|
let root = state_root_at_slot(beacon_chain, slot)?;
|
||||||
|
|
||||||
@ -55,7 +73,7 @@ pub fn state_at_slot<T: BeaconChainTypes>(
|
|||||||
.get(&root)?
|
.get(&root)?
|
||||||
.ok_or_else(|| ApiError::NotFound(format!("Unable to find state at root {}", root)))?;
|
.ok_or_else(|| ApiError::NotFound(format!("Unable to find state at root {}", root)))?;
|
||||||
|
|
||||||
Ok(state)
|
Ok((root, state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ impl From<state_processing::per_slot_processing::Error> for ApiError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_server<T: BeaconChainTypes + Clone + Send + Sync + 'static>(
|
pub fn start_server<T: BeaconChainTypes>(
|
||||||
config: &ApiConfig,
|
config: &ApiConfig,
|
||||||
executor: &TaskExecutor,
|
executor: &TaskExecutor,
|
||||||
beacon_chain: Arc<BeaconChain<T>>,
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
@ -121,7 +121,7 @@ pub fn start_server<T: BeaconChainTypes + Clone + Send + Sync + '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/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") => beacon::get_block::<T>(req),
|
||||||
(&Method::GET, "/beacon/block_root") => beacon::get_block_root::<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") => {
|
||||||
@ -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") => beacon::get_state::<T>(req),
|
||||||
(&Method::GET, "/beacon/state_root") => beacon::get_state_root::<T>(req),
|
(&Method::GET, "/beacon/state_root") => beacon::get_state_root::<T>(req),
|
||||||
(&Method::GET, "/metrics") => metrics::get_prometheus::<T>(req),
|
(&Method::GET, "/metrics") => metrics::get_prometheus::<T>(req),
|
||||||
(&Method::GET, "/node/version") => node::get_version(req),
|
(&Method::GET, "/network/enr") => network::get_enr::<T>(req),
|
||||||
(&Method::GET, "/node/genesis_time") => node::get_genesis_time::<T>(req),
|
(&Method::GET, "/network/peer_count") => network::get_peer_count::<T>(req),
|
||||||
(&Method::GET, "/node/network/enr") => network::get_enr::<T>(req),
|
(&Method::GET, "/network/peer_id") => network::get_peer_id::<T>(req),
|
||||||
(&Method::GET, "/node/network/peer_count") => network::get_peer_count::<T>(req),
|
(&Method::GET, "/network/peers") => network::get_peer_list::<T>(req),
|
||||||
(&Method::GET, "/node/network/peers") => network::get_peer_list::<T>(req),
|
(&Method::GET, "/network/listen_addresses") => {
|
||||||
(&Method::GET, "/node/network/listen_addresses") => {
|
|
||||||
network::get_listen_addresses::<T>(req)
|
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") => spec::get_spec::<T>(req),
|
||||||
(&Method::GET, "/spec/slots_per_epoch") => spec::get_slots_per_epoch::<T>(req),
|
(&Method::GET, "/spec/slots_per_epoch") => spec::get_slots_per_epoch::<T>(req),
|
||||||
_ => Err(ApiError::MethodNotAllowed(path.clone())),
|
_ => Err(ApiError::MethodNotAllowed(path.clone())),
|
||||||
|
@ -7,9 +7,7 @@ use std::sync::Arc;
|
|||||||
/// HTTP handle to return the list of libp2p multiaddr the client is listening on.
|
/// HTTP handle 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 + Send + Sync + 'static>(
|
pub fn get_listen_addresses<T: BeaconChainTypes>(req: Request<Body>) -> ApiResult {
|
||||||
req: Request<Body>,
|
|
||||||
) -> ApiResult {
|
|
||||||
let network = req
|
let network = req
|
||||||
.extensions()
|
.extensions()
|
||||||
.get::<Arc<NetworkService<T>>>()
|
.get::<Arc<NetworkService<T>>>()
|
||||||
@ -26,7 +24,7 @@ pub fn get_listen_addresses<T: BeaconChainTypes + Send + Sync + 'static>(
|
|||||||
/// HTTP handle to return the Discv5 ENR from the client's libp2p service.
|
/// HTTP handle 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 + Send + Sync + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_enr<T: BeaconChainTypes>(req: Request<Body>) -> ApiResult {
|
||||||
let network = req
|
let network = req
|
||||||
.extensions()
|
.extensions()
|
||||||
.get::<Arc<NetworkService<T>>>()
|
.get::<Arc<NetworkService<T>>>()
|
||||||
@ -40,10 +38,25 @@ 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>(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.
|
/// 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>(
|
pub fn get_peer_count<T: BeaconChainTypes>(req: Request<Body>) -> ApiResult {
|
||||||
req: Request<Body>,
|
|
||||||
) -> ApiResult {
|
|
||||||
let network = req
|
let network = req
|
||||||
.extensions()
|
.extensions()
|
||||||
.get::<Arc<NetworkService<T>>>()
|
.get::<Arc<NetworkService<T>>>()
|
||||||
@ -60,7 +73,7 @@ pub fn get_peer_count<T: BeaconChainTypes + Send + Sync + 'static>(
|
|||||||
/// HTTP handle to return the list of peers connected to the client's libp2p service.
|
/// HTTP handle 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 + Send + Sync + 'static>(req: Request<Body>) -> ApiResult {
|
pub fn get_peer_list<T: BeaconChainTypes>(req: Request<Body>) -> ApiResult {
|
||||||
let network = req
|
let network = req
|
||||||
.extensions()
|
.extensions()
|
||||||
.get::<Arc<NetworkService<T>>>()
|
.get::<Arc<NetworkService<T>>>()
|
||||||
|
@ -118,7 +118,7 @@ fn run<T>(
|
|||||||
log: &slog::Logger,
|
log: &slog::Logger,
|
||||||
) -> error::Result<()>
|
) -> error::Result<()>
|
||||||
where
|
where
|
||||||
T: BeaconChainTypes + InitialiseBeaconChain<T> + Clone + Send + Sync + 'static,
|
T: BeaconChainTypes + InitialiseBeaconChain<T> + Clone,
|
||||||
T::Store: OpenDatabase,
|
T::Store: OpenDatabase,
|
||||||
{
|
{
|
||||||
let store = T::Store::open_database(&db_path)?;
|
let store = T::Store::open_database(&db_path)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user