mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-07 16:55:46 +00:00
Add API endpoint for fork choice
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -3352,6 +3352,7 @@ dependencies = [
|
|||||||
"eth2_ssz 0.1.2",
|
"eth2_ssz 0.1.2",
|
||||||
"futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"proto_array_fork_choice 0.1.0",
|
||||||
"reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
"reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rest_api 0.1.0",
|
"rest_api 0.1.0",
|
||||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ pub enum Error {
|
|||||||
UnknownBlockSlot(Hash256),
|
UnknownBlockSlot(Hash256),
|
||||||
UnknownJustifiedBlock(Hash256),
|
UnknownJustifiedBlock(Hash256),
|
||||||
UnknownJustifiedState(Hash256),
|
UnknownJustifiedState(Hash256),
|
||||||
|
UnableToJsonEncode(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ForkChoice<T: BeaconChainTypes> {
|
pub struct ForkChoice<T: BeaconChainTypes> {
|
||||||
@@ -230,6 +231,10 @@ impl<T: BeaconChainTypes> ForkChoice<T> {
|
|||||||
self.backend.maybe_prune(finalized_root).map_err(Into::into)
|
self.backend.maybe_prune(finalized_root).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_json(&self) -> Result<String> {
|
||||||
|
self.backend.as_json().map_err(Error::UnableToJsonEncode)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a `SszForkChoice` which contains the current state of `Self`.
|
/// Returns a `SszForkChoice` which contains the current state of `Self`.
|
||||||
pub fn as_ssz_container(&self) -> SszForkChoice {
|
pub fn as_ssz_container(&self) -> SszForkChoice {
|
||||||
SszForkChoice {
|
SszForkChoice {
|
||||||
|
|||||||
18
beacon_node/rest_api/src/advanced.rs
Normal file
18
beacon_node/rest_api/src/advanced.rs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
use crate::response_builder::ResponseBuilder;
|
||||||
|
use crate::{ApiError, ApiResult};
|
||||||
|
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
||||||
|
use hyper::{Body, Request};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
/// Returns the `proto_array` fork choice struct, encoded as JSON.
|
||||||
|
///
|
||||||
|
/// Useful for debugging or advanced inspection of the chain.
|
||||||
|
pub fn get_fork_choice<T: BeaconChainTypes>(
|
||||||
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
) -> ApiResult {
|
||||||
|
let json = beacon_chain.fork_choice.as_json().map_err(|e| {
|
||||||
|
ApiError::ServerError(format!("Unable to encode fork choice as JSON: {:?}", e))
|
||||||
|
})?;
|
||||||
|
ResponseBuilder::new(&req)?.body_no_ssz(&json)
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ mod macros;
|
|||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
extern crate network as client_network;
|
extern crate network as client_network;
|
||||||
|
|
||||||
|
mod advanced;
|
||||||
mod beacon;
|
mod beacon;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
mod consensus;
|
mod consensus;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
beacon, consensus, error::ApiError, helpers, metrics, network, node, spec, validator, BoxFut,
|
advanced, beacon, consensus, error::ApiError, helpers, metrics, network, node, spec, validator,
|
||||||
NetworkChannel,
|
BoxFut, NetworkChannel,
|
||||||
};
|
};
|
||||||
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
||||||
use client_network::Service as NetworkService;
|
use client_network::Service as NetworkService;
|
||||||
@@ -147,6 +147,11 @@ pub fn route<T: BeaconChainTypes>(
|
|||||||
into_boxfut(spec::get_eth2_config::<T>(req, eth2_config))
|
into_boxfut(spec::get_eth2_config::<T>(req, eth2_config))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Methods for advanced parameters
|
||||||
|
(&Method::GET, "/advanced/fork_choice") => {
|
||||||
|
into_boxfut(advanced::get_fork_choice::<T>(req, beacon_chain))
|
||||||
|
}
|
||||||
|
|
||||||
(&Method::GET, "/metrics") => into_boxfut(metrics::get_prometheus::<T>(
|
(&Method::GET, "/metrics") => into_boxfut(metrics::get_prometheus::<T>(
|
||||||
req,
|
req,
|
||||||
beacon_chain,
|
beacon_chain,
|
||||||
|
|||||||
@@ -792,6 +792,24 @@ fn get_committees() {
|
|||||||
assert_eq!(result, expected, "result should be as expected");
|
assert_eq!(result, expected, "result should be as expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_fork_choice() {
|
||||||
|
let mut env = build_env();
|
||||||
|
|
||||||
|
let node = build_node(&mut env, testing_client_config());
|
||||||
|
let remote_node = node.remote_node().expect("should produce remote node");
|
||||||
|
|
||||||
|
// Ideally we would check that the returned fork choice is the same as the one in the
|
||||||
|
// `beacon_chain`, however that would involve exposing (making public) the core fork choice
|
||||||
|
// struct that is a bit messy.
|
||||||
|
//
|
||||||
|
// Given that serializing the fork choice is just vanilla serde, I think it's fair to assume it
|
||||||
|
// works.
|
||||||
|
env.runtime()
|
||||||
|
.block_on(remote_node.http.advanced().get_fork_choice())
|
||||||
|
.expect("should not error when getting fork choice");
|
||||||
|
}
|
||||||
|
|
||||||
fn compare_validator_response<T: EthSpec>(
|
fn compare_validator_response<T: EthSpec>(
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
response: &ValidatorResponse,
|
response: &ValidatorResponse,
|
||||||
|
|||||||
@@ -5,3 +5,7 @@ mod ssz_container;
|
|||||||
|
|
||||||
pub use crate::proto_array_fork_choice::ProtoArrayForkChoice;
|
pub use crate::proto_array_fork_choice::ProtoArrayForkChoice;
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
|
|
||||||
|
pub mod core {
|
||||||
|
pub use super::proto_array::ProtoArray;
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,3 +17,4 @@ hex = "0.3"
|
|||||||
eth2_ssz = { path = "../../../eth2/utils/ssz" }
|
eth2_ssz = { path = "../../../eth2/utils/ssz" }
|
||||||
serde_json = "^1.0"
|
serde_json = "^1.0"
|
||||||
eth2_config = { path = "../../../eth2/utils/eth2_config" }
|
eth2_config = { path = "../../../eth2/utils/eth2_config" }
|
||||||
|
proto_array_fork_choice = { path = "../../../eth2/proto_array_fork_choice" }
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
use eth2_config::Eth2Config;
|
use eth2_config::Eth2Config;
|
||||||
use futures::{future, Future, IntoFuture};
|
use futures::{future, Future, IntoFuture};
|
||||||
|
use proto_array_fork_choice::core::ProtoArray;
|
||||||
use reqwest::{
|
use reqwest::{
|
||||||
r#async::{Client, ClientBuilder, Response},
|
r#async::{Client, ClientBuilder, Response},
|
||||||
StatusCode,
|
StatusCode,
|
||||||
@@ -101,6 +102,10 @@ impl<E: EthSpec> HttpClient<E> {
|
|||||||
Node(self.clone())
|
Node(self.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn advanced(&self) -> Advanced<E> {
|
||||||
|
Advanced(self.clone())
|
||||||
|
}
|
||||||
|
|
||||||
fn url(&self, path: &str) -> Result<Url, Error> {
|
fn url(&self, path: &str) -> Result<Url, Error> {
|
||||||
self.url.join(path).map_err(|e| e.into())
|
self.url.join(path).map_err(|e| e.into())
|
||||||
}
|
}
|
||||||
@@ -536,6 +541,27 @@ impl<E: EthSpec> Node<E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Provides the functions on the `/advanced` endpoint of the node.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Advanced<E>(HttpClient<E>);
|
||||||
|
|
||||||
|
impl<E: EthSpec> Advanced<E> {
|
||||||
|
fn url(&self, path: &str) -> Result<Url, Error> {
|
||||||
|
self.0
|
||||||
|
.url("advanced/")
|
||||||
|
.and_then(move |url| url.join(path).map_err(Error::from))
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the core `ProtoArray` struct from the node.
|
||||||
|
pub fn get_fork_choice(&self) -> impl Future<Item = ProtoArray, Error = Error> {
|
||||||
|
let client = self.0.clone();
|
||||||
|
self.url("fork_choice")
|
||||||
|
.into_future()
|
||||||
|
.and_then(move |url| client.json_get(url, vec![]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(bound = "T: EthSpec")]
|
#[serde(bound = "T: EthSpec")]
|
||||||
pub struct BlockResponse<T: EthSpec> {
|
pub struct BlockResponse<T: EthSpec> {
|
||||||
|
|||||||
Reference in New Issue
Block a user