Skip to content

Commit

Permalink
Progress with implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
paulhauner committed Sep 5, 2020
1 parent 49ac075 commit 0922a39
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 338 deletions.
323 changes: 4 additions & 319 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ members = [
"common/eth2_testnet_config",
"common/eth2_wallet_manager",
"common/hashset_delay",
"common/http_api_common",
"common/lighthouse_metrics",
"common/lighthouse_version",
"common/logging",
Expand Down
14 changes: 14 additions & 0 deletions beacon_node/beacon_chain/src/beacon_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,20 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
f(&head_lock)
}

/// Returns the beacon block at the head of the canonical chain.
///
/// See `Self::head` for more information.
pub fn head_beacon_block(&self) -> Result<SignedBeaconBlock<T::EthSpec>, Error> {
self.with_head(|s| s.beacon_block.clone())
}

/// Returns the beacon state at the head of the canonical chain.
///
/// See `Self::head` for more information.
pub fn head_beacon_state(&self) -> Result<BeaconState<T::EthSpec>, Error> {
self.with_head(|s| s.beacon_state.clone())
}

/// Returns info representing the head block and state.
///
/// A summarized version of `Self::head` that involves less cloning.
Expand Down
1 change: 1 addition & 0 deletions beacon_node/http_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ parking_lot = "0.11.0"
types = { path = "../../consensus/types" }
hex = "0.4.2"
beacon_chain = { path = "../beacon_chain" }
http_api_common = { path = "../../common/http_api_common" }
21 changes: 20 additions & 1 deletion beacon_node/http_api/src/block_id.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use beacon_chain::{BeaconChain, BeaconChainTypes};
use std::str::FromStr;
use types::{Hash256, Slot};
use types::{Hash256, SignedBeaconBlock, Slot};

#[derive(Debug)]
pub enum BlockId {
Expand Down Expand Up @@ -38,6 +38,25 @@ impl BlockId {
BlockId::Root(root) => Ok(*root),
}
}

pub fn block<T: BeaconChainTypes>(
&self,
chain: &BeaconChain<T>,
) -> Result<SignedBeaconBlock<T::EthSpec>, warp::Rejection> {
let block_root = match self {
BlockId::Head => {
return chain
.head_beacon_block()
.map_err(crate::reject::beacon_chain_error)
}
other => other.root(chain),
}?;

chain
.get_block(&block_root)
.map_err(crate::reject::beacon_chain_error)
.and_then(|root_opt| root_opt.ok_or_else(|| warp::reject::not_found()))
}
}

impl FromStr for BlockId {
Expand Down
60 changes: 54 additions & 6 deletions beacon_node/http_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ mod state_id;

use beacon_chain::{BeaconChain, BeaconChainTypes};
use block_id::BlockId;
use http_api_common as api;
use serde::Serialize;
use state_id::StateId;
use std::sync::Arc;
use warp::Filter;
Expand Down Expand Up @@ -40,16 +42,39 @@ pub async fn serve<T: BeaconChainTypes>(ctx: Arc<Context<T>>) {
.clone()
.and(warp::path("root"))
.and(warp::path::end())
.and_then(|state_id: StateId, chain: Arc<BeaconChain<T>>| async move {
state_id.root(&chain).map(|resp| warp::reply::json(&resp))
.and_then(|state_id: StateId, chain: Arc<BeaconChain<T>>| {
blocking_json_task(move || {
state_id
.root(&chain)
.map(api::RootData::from)
.map(api::GenericResponse::from)
})
});

let beacon_state_fork = beacon_states_path
.clone()
.and(warp::path("fork"))
.and(warp::path::end())
.and_then(|state_id: StateId, chain: Arc<BeaconChain<T>>| async move {
state_id.root(&chain).map(|resp| warp::reply::json(&resp))
.and_then(|state_id: StateId, chain: Arc<BeaconChain<T>>| {
blocking_json_task(move || state_id.fork(&chain).map(api::GenericResponse::from))
});

let beacon_state_finality_checkpoints = beacon_states_path
.clone()
.and(warp::path("finality_checkpoints"))
.and(warp::path::end())
.and_then(|state_id: StateId, chain: Arc<BeaconChain<T>>| {
blocking_json_task(move || {
state_id
.map_state(&chain, |state| {
Ok(api::FinalityCheckpointsData {
previous_justified: state.previous_justified_checkpoint,
current_justified: state.current_justified_checkpoint,
finalized: state.finalized_checkpoint,
})
})
.map(api::GenericResponse::from)
})
});

/*
Expand All @@ -66,13 +91,36 @@ pub async fn serve<T: BeaconChainTypes>(ctx: Arc<Context<T>>) {
.clone()
.and(warp::path("root"))
.and(warp::path::end())
.and_then(|block_id: BlockId, chain: Arc<BeaconChain<T>>| async move {
block_id.root(&chain).map(|resp| warp::reply::json(&resp))
.and_then(|block_id: BlockId, chain: Arc<BeaconChain<T>>| {
blocking_json_task(move || {
block_id
.root(&chain)
.map(api::RootData::from)
.map(api::GenericResponse::from)
})
});

let routes = beacon_state_root
.or(beacon_state_fork)
.or(beacon_state_finality_checkpoints)
.or(beacon_block_root);

warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
}

async fn blocking_task<F, T>(func: F) -> T
where
F: Fn() -> T,
{
tokio::task::block_in_place(func)
}

async fn blocking_json_task<F, T>(func: F) -> Result<warp::reply::Json, warp::Rejection>
where
F: Fn() -> Result<T, warp::Rejection>,
T: Serialize,
{
blocking_task(func)
.await
.map(|resp| warp::reply::json(&resp))
}
76 changes: 64 additions & 12 deletions beacon_node/http_api/src/state_id.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::BlockId;
use beacon_chain::{BeaconChain, BeaconChainTypes};
use std::str::FromStr;
use types::{Hash256, Slot};
use types::{BeaconState, Fork, Hash256, Slot};

#[derive(Debug)]
pub enum StateId {
Expand All @@ -17,17 +18,68 @@ impl StateId {
&self,
chain: &BeaconChain<T>,
) -> Result<Hash256, warp::Rejection> {
match self {
StateId::Head => chain
.head_info()
.map(|head| head.state_root)
.map_err(crate::reject::beacon_chain_error),
StateId::Genesis => Ok(chain.genesis_state_root),
StateId::Finalized => todo!(),
StateId::Justified => todo!(),
StateId::Slot(_) => todo!(),
StateId::Root(root) => Ok(*root),
}
let block = match self {
StateId::Head => {
return chain
.head_info()
.map(|head| head.state_root)
.map_err(crate::reject::beacon_chain_error)
}
StateId::Genesis => return Ok(chain.genesis_state_root),
StateId::Finalized => BlockId::Finalized.block(chain),
StateId::Justified => BlockId::Justified.block(chain),
StateId::Slot(slot) => BlockId::Slot(*slot).block(chain),
StateId::Root(root) => return Ok(*root),
}?;

Ok(block.state_root())
}

pub fn fork<T: BeaconChainTypes>(
&self,
chain: &BeaconChain<T>,
) -> Result<Fork, warp::Rejection> {
self.map_state(chain, |state| Ok(state.fork.clone()))
}

pub fn state<T: BeaconChainTypes>(
&self,
chain: &BeaconChain<T>,
) -> Result<BeaconState<T::EthSpec>, warp::Rejection> {
let (state_root, slot_opt) = match self {
StateId::Head => {
return chain
.head_beacon_state()
.map_err(crate::reject::beacon_chain_error)
}
StateId::Slot(slot) => (self.root(chain)?, Some(*slot)),
other => (other.root(chain)?, None),
};

chain
.get_state(&state_root, slot_opt)
.map_err(crate::reject::beacon_chain_error)
.and_then(|opt| opt.ok_or_else(|| warp::reject::not_found()))
}

pub fn map_state<T: BeaconChainTypes, F, U>(
&self,
chain: &BeaconChain<T>,
func: F,
) -> Result<U, warp::Rejection>
where
F: Fn(&BeaconState<T::EthSpec>) -> Result<U, warp::Rejection>,
{
let state = match self {
StateId::Head => {
return chain
.map_head(|snapshot| func(&snapshot.beacon_state))
.map_err(crate::reject::beacon_chain_error)?
}
other => other.state(chain)?,
};

func(&state)
}
}

Expand Down
12 changes: 12 additions & 0 deletions common/http_api_common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "http_api_common"
version = "0.1.0"
authors = ["Paul Hauner <[email protected]>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
serde = { version = "1.0.110", features = ["derive"] }
types = { path = "../../consensus/types" }
hex = "0.4.2"
31 changes: 31 additions & 0 deletions common/http_api_common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use serde::{Deserialize, Serialize};
use types::{Checkpoint, Hash256};

#[derive(Serialize)]
pub struct GenericResponse<T: Serialize> {
pub data: T,
}

impl<T: Serialize> From<T> for GenericResponse<T> {
fn from(data: T) -> Self {
Self { data }
}
}

#[derive(Serialize, Deserialize)]
pub struct RootData {
pub root: Hash256,
}

impl From<Hash256> for RootData {
fn from(root: Hash256) -> Self {
Self { root }
}
}

#[derive(Serialize, Deserialize)]
pub struct FinalityCheckpointsData {
pub previous_justified: Checkpoint,
pub current_justified: Checkpoint,
pub finalized: Checkpoint,
}

0 comments on commit 0922a39

Please sign in to comment.