Skip to content

Commit

Permalink
Add syncing endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
paulhauner committed Sep 10, 2020
1 parent 838464c commit e93f95c
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 2 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions beacon_node/http_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ state_processing = { path = "../../consensus/state_processing" }
store = { path = "../store" }
environment = { path = "../../lighthouse/environment" }
tree_hash = { path = "../../consensus/tree_hash" }
discv5 = { version = "0.1.0-alpha.10", features = ["libp2p"] }
52 changes: 51 additions & 1 deletion beacon_node/http_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use beacon_chain::{
use beacon_proposer_cache::BeaconProposerCache;
use block_id::BlockId;
use eth2::types::{self as api_types, ValidatorId};
use eth2_libp2p::PubsubMessage;
use eth2_libp2p::{NetworkGlobals, PubsubMessage};
use network::NetworkMessage;
use parking_lot::Mutex;
use serde::{Deserialize, Serialize};
Expand All @@ -34,6 +34,7 @@ pub struct Context<T: BeaconChainTypes> {
pub config: Config,
pub chain: Option<Arc<BeaconChain<T>>>,
pub network_tx: Option<UnboundedSender<NetworkMessage<T::EthSpec>>>,
pub network_globals: Option<Arc<NetworkGlobals<T::EthSpec>>>,
pub log: Logger,
}

Expand Down Expand Up @@ -110,6 +111,20 @@ pub fn serve<T: BeaconChainTypes>(
})
};

let inner_network_globals = ctx.network_globals.clone();
let network_globals = || {
warp::any()
.map(move || inner_network_globals.clone())
.and_then(|network_globals| async move {
match network_globals {
Some(globals) => Ok(globals),
None => Err(crate::reject::custom_not_found(
"network globals are not initialized.".to_string(),
)),
}
})
};

let inner_ctx = ctx.clone();
let chain_filter =
warp::any()
Expand Down Expand Up @@ -894,6 +909,40 @@ pub fn serve<T: BeaconChainTypes>(
})
});

/*
* node
*/

// GET node/syncing
let get_node_syncing = eth1_v1
.and(warp::path("node"))
.and(warp::path("syncing"))
.and(warp::path::end())
.and(network_globals())
.and(chain_filter.clone())
.and_then(
|network_globals: Arc<NetworkGlobals<T::EthSpec>>, chain: Arc<BeaconChain<T>>| {
blocking_json_task(move || {
let head_slot = chain
.head_info()
.map(|info| info.slot)
.map_err(crate::reject::beacon_chain_error)?;
let current_slot = chain.slot().map_err(crate::reject::beacon_chain_error)?;

// Taking advantage of saturating subtraction on slot.
let sync_distance = current_slot - head_slot;

let syncing_data = api_types::SyncingData {
is_syncing: network_globals.sync_state.read().is_syncing(),
head_slot,
sync_distance,
};

Ok(api_types::GenericResponse::from(syncing_data))
})
},
);

/*
* validator
*/
Expand Down Expand Up @@ -1159,6 +1208,7 @@ pub fn serve<T: BeaconChainTypes>(
.or(get_config_deposit_contract.boxed())
.or(get_debug_beacon_states.boxed())
.or(get_debug_beacon_heads.boxed())
.or(get_node_syncing.boxed())
.or(get_validator_duties_attester.boxed())
.or(get_validator_duties_proposer.boxed())
.or(get_validator_blocks.boxed())
Expand Down
32 changes: 31 additions & 1 deletion beacon_node/http_api/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ use beacon_chain::{
},
BeaconChain, StateSkipConfig,
};
use discv5::enr::{CombinedKey, EnrBuilder};
use environment::null_logger;
use eth2::{types::*, BeaconNodeClient, Url};
use eth2_libp2p::NetworkGlobals;
use http_api::{Config, Context};
use network::NetworkMessage;
use std::convert::TryInto;
Expand Down Expand Up @@ -128,6 +130,12 @@ impl ApiTester {

let (network_tx, network_rx) = mpsc::unbounded_channel();

let log = null_logger().unwrap();

let enr_key = CombinedKey::generate_secp256k1();
let enr = EnrBuilder::new("v4").build(&enr_key).unwrap();
let network_globals = NetworkGlobals::new(enr, 42, 42, &log);

let context = Arc::new(Context {
config: Config {
enabled: true,
Expand All @@ -136,7 +144,8 @@ impl ApiTester {
},
chain: Some(chain.clone()),
network_tx: Some(network_tx),
log: null_logger().unwrap(),
network_globals: Some(Arc::new(network_globals)),
log,
});
let ctx = context.clone();
let (shutdown_tx, shutdown_rx) = oneshot::channel();
Expand Down Expand Up @@ -952,6 +961,22 @@ impl ApiTester {
self
}

pub async fn test_get_node_syncing(self) -> Self {
let result = self.client.get_node_syncing().await.unwrap().data;
let head_slot = self.chain.head_info().unwrap().slot;
let sync_distance = self.chain.slot().unwrap() - head_slot;

let expected = SyncingData {
is_syncing: false,
head_slot,
sync_distance,
};

assert_eq!(result, expected);

self
}

pub async fn test_get_debug_beacon_states(self) -> Self {
for state_id in self.interesting_state_ids() {
let result = self
Expand Down Expand Up @@ -1554,6 +1579,11 @@ async fn debug_get() {
.await;
}

#[tokio::test(core_threads = 2)]
async fn node_get() {
ApiTester::new().test_get_node_syncing().await;
}

#[tokio::test(core_threads = 2)]
async fn get_validator_duties_attester() {
ApiTester::new().test_get_validator_duties_attester().await;
Expand Down
12 changes: 12 additions & 0 deletions common/eth2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,18 @@ impl BeaconNodeClient {
self.get(path).await
}

/// `GET node/syncing`
pub async fn get_node_syncing(&self) -> Result<GenericResponse<SyncingData>, Error> {
let mut path = self.server.clone();

path.path_segments_mut()
.expect("path is base")
.push("node")
.push("syncing");

self.get(path).await
}

/// `GET debug/beacon/states/{state_id}`
pub async fn get_debug_beacon_states<T: EthSpec>(
&self,
Expand Down
7 changes: 7 additions & 0 deletions common/eth2/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,13 @@ pub struct ChainHeadData {
pub root: Hash256,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SyncingData {
pub is_syncing: bool,
pub head_slot: Slot,
pub sync_distance: Slot,
}

#[derive(Clone, PartialEq, Debug, Deserialize)]
#[serde(try_from = "String", bound = "T: FromStr")]
pub struct QueryVec<T: FromStr>(pub Vec<T>);
Expand Down

0 comments on commit e93f95c

Please sign in to comment.