Fleshed out some API endpoints.
- Added the /beacon/validator/block endpoint for GET (untested) - Added the /beacon/fork endpoint for GET - Cleaned up a bunch of unused imports & variables - Removed '/network/block_discovery' endpoint
This commit is contained in:
parent
0bd5ce65f4
commit
faef347d18
@ -983,20 +983,34 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
Ok(BlockProcessingOutcome::Processed { block_root })
|
Ok(BlockProcessingOutcome::Processed { block_root })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produce a new block at the present slot.
|
/// Produce a new block at the specified slot.
|
||||||
///
|
///
|
||||||
/// The produced block will not be inherently valid, it must be signed by a block producer.
|
/// The produced block will not be inherently valid, it must be signed by a block producer.
|
||||||
/// Block signing is out of the scope of this function and should be done by a separate program.
|
/// Block signing is out of the scope of this function and should be done by a separate program.
|
||||||
pub fn produce_block(
|
pub fn produce_block(
|
||||||
&self,
|
&self,
|
||||||
randao_reveal: Signature,
|
randao_reveal: Signature,
|
||||||
|
slot: Slot,
|
||||||
) -> Result<(BeaconBlock<T::EthSpec>, BeaconState<T::EthSpec>), BlockProductionError> {
|
) -> Result<(BeaconBlock<T::EthSpec>, BeaconState<T::EthSpec>), BlockProductionError> {
|
||||||
let state = self.state.read().clone();
|
let state = self.state.read().clone();
|
||||||
|
|
||||||
|
self.produce_block_on_state(state, slot, randao_reveal)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Produce a new block at the current slot
|
||||||
|
///
|
||||||
|
/// Calls `produce_block`, with the slot parameter set as the current.
|
||||||
|
///
|
||||||
|
/// ** This function is probably obsolete (was for previous RPC), and can probably be removed **
|
||||||
|
pub fn produce_current_block(
|
||||||
|
&self,
|
||||||
|
randao_reveal: Signature,
|
||||||
|
) -> Result<(BeaconBlock<T::EthSpec>, BeaconState<T::EthSpec>), BlockProductionError> {
|
||||||
let slot = self
|
let slot = self
|
||||||
.read_slot_clock()
|
.read_slot_clock()
|
||||||
.ok_or_else(|| BlockProductionError::UnableToReadSlot)?;
|
.ok_or_else(|| BlockProductionError::UnableToReadSlot)?;
|
||||||
|
|
||||||
self.produce_block_on_state(state, slot, randao_reveal)
|
self.produce_block(randao_reveal, slot)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produce a block for some `slot` upon the given `state`.
|
/// Produce a block for some `slot` upon the given `state`.
|
||||||
|
@ -130,6 +130,22 @@ pub fn get_block_root<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiR
|
|||||||
Ok(success_response(Body::from(json)))
|
Ok(success_response(Body::from(json)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// HTTP handler to return the `Fork` of the current head.
|
||||||
|
pub fn get_fork<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 chain_head = beacon_chain.head();
|
||||||
|
|
||||||
|
let json: String = serde_json::to_string(&chain_head.beacon_state.fork).map_err(|e| {
|
||||||
|
ApiError::ServerError(format!("Unable to serialize BeaconState::Fork: {:?}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(success_response(Body::from(json)))
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
#[serde(bound = "T: EthSpec")]
|
#[serde(bound = "T: EthSpec")]
|
||||||
pub struct StateResponse<T: EthSpec> {
|
pub struct StateResponse<T: EthSpec> {
|
||||||
|
@ -2,9 +2,7 @@ use crate::{ApiError, ApiResult};
|
|||||||
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
||||||
use bls::PublicKey;
|
use bls::PublicKey;
|
||||||
use hex;
|
use hex;
|
||||||
use hyper::{Body, Request, StatusCode};
|
use hyper::{Body, Request};
|
||||||
use serde::de::value::StringDeserializer;
|
|
||||||
use serde_json::Deserializer;
|
|
||||||
use store::{iter::AncestorIter, Store};
|
use store::{iter::AncestorIter, Store};
|
||||||
use types::{BeaconState, EthSpec, Hash256, RelativeEpoch, Slot};
|
use types::{BeaconState, EthSpec, Hash256, RelativeEpoch, Slot};
|
||||||
|
|
||||||
|
@ -139,16 +139,13 @@ pub fn start_server<T: BeaconChainTypes>(
|
|||||||
(&Method::GET, "/network/listen_addresses") => {
|
(&Method::GET, "/network/listen_addresses") => {
|
||||||
network::get_listen_addresses::<T>(req)
|
network::get_listen_addresses::<T>(req)
|
||||||
}
|
}
|
||||||
(&Method::GET, "/network/block_discovery") => {
|
|
||||||
helpers::implementation_pending_response(req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Methods for Beacon Node
|
// Methods for Beacon Node
|
||||||
(&Method::GET, "/beacon/head") => beacon::get_head::<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/blocks") => helpers::implementation_pending_response(req),
|
(&Method::GET, "/beacon/blocks") => helpers::implementation_pending_response(req),
|
||||||
(&Method::GET, "/beacon/fork") => helpers::implementation_pending_response(req),
|
(&Method::GET, "/beacon/fork") => beacon::get_fork::<T>(req),
|
||||||
(&Method::GET, "/beacon/attestations") => {
|
(&Method::GET, "/beacon/attestations") => {
|
||||||
helpers::implementation_pending_response(req)
|
helpers::implementation_pending_response(req)
|
||||||
}
|
}
|
||||||
@ -171,7 +168,7 @@ pub fn start_server<T: BeaconChainTypes>(
|
|||||||
validator::get_validator_duties::<T>(req)
|
validator::get_validator_duties::<T>(req)
|
||||||
}
|
}
|
||||||
(&Method::GET, "/beacon/validator/block") => {
|
(&Method::GET, "/beacon/validator/block") => {
|
||||||
helpers::implementation_pending_response(req)
|
validator::get_new_beacon_block::<T>(req)
|
||||||
}
|
}
|
||||||
(&Method::POST, "/beacon/validator/block") => {
|
(&Method::POST, "/beacon/validator/block") => {
|
||||||
helpers::implementation_pending_response(req)
|
helpers::implementation_pending_response(req)
|
||||||
|
@ -64,7 +64,7 @@ impl<'a> UrlQuery<'a> {
|
|||||||
/// Returns a vector of all values present where `key` is in `keys
|
/// Returns a vector of all values present where `key` is in `keys
|
||||||
///
|
///
|
||||||
/// If no match is found, an `InvalidQueryParams` error is returned.
|
/// If no match is found, an `InvalidQueryParams` error is returned.
|
||||||
pub fn all_of(mut self, key: &str) -> Result<Vec<String>, ApiError> {
|
pub fn all_of(self, key: &str) -> Result<Vec<String>, ApiError> {
|
||||||
let queries: Vec<_> = self
|
let queries: Vec<_> = self
|
||||||
.0
|
.0
|
||||||
.filter_map(|(k, v)| {
|
.filter_map(|(k, v)| {
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
use super::{success_response, ApiResult};
|
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 bls::PublicKey;
|
use bls::{PublicKey, Signature};
|
||||||
use hyper::{Body, Request};
|
use hyper::{Body, Request};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use store::Store;
|
|
||||||
use types::beacon_state::EthSpec;
|
use types::beacon_state::EthSpec;
|
||||||
use types::{BeaconBlock, BeaconState, Epoch, RelativeEpoch, Shard, Slot};
|
use types::{Epoch, RelativeEpoch, Shard, Slot};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct ValidatorDuty {
|
pub struct ValidatorDuty {
|
||||||
@ -39,16 +38,14 @@ pub fn get_validator_duties<T: BeaconChainTypes + 'static>(req: Request<Body>) -
|
|||||||
.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()))?;
|
||||||
|
//TODO Surely this state_cache thing is not necessary?
|
||||||
let _ = beacon_chain
|
let _ = beacon_chain
|
||||||
.ensure_state_caches_are_built()
|
.ensure_state_caches_are_built()
|
||||||
.map_err(|e| ApiError::ServerError(format!("Unable to build state caches: {:?}", e)))?;
|
.map_err(|e| ApiError::ServerError(format!("Unable to build state caches: {:?}", e)))?;
|
||||||
let head_state = beacon_chain
|
let head_state = &beacon_chain.head().beacon_state;
|
||||||
.speculative_state()
|
|
||||||
.expect("This is legacy code and should be removed.");
|
|
||||||
|
|
||||||
// Parse and check query parameters
|
// Parse and check query parameters
|
||||||
let query = UrlQuery::from_request(&req)?;
|
let query = UrlQuery::from_request(&req)?;
|
||||||
|
|
||||||
let current_epoch = head_state.current_epoch();
|
let current_epoch = head_state.current_epoch();
|
||||||
let epoch = match query.first_of(&["epoch"]) {
|
let epoch = match query.first_of(&["epoch"]) {
|
||||||
Ok((_, v)) => Epoch::new(v.parse::<u64>().map_err(|e| {
|
Ok((_, v)) => Epoch::new(v.parse::<u64>().map_err(|e| {
|
||||||
@ -66,7 +63,7 @@ pub fn get_validator_duties<T: BeaconChainTypes + 'static>(req: Request<Body>) -
|
|||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
//TODO: Handle an array of validators, currently only takes one
|
//TODO: Handle an array of validators, currently only takes one
|
||||||
let mut validators: Vec<PublicKey> = match query.all_of("validator_pubkeys") {
|
let validators: Vec<PublicKey> = match query.all_of("validator_pubkeys") {
|
||||||
Ok(v) => v
|
Ok(v) => v
|
||||||
.iter()
|
.iter()
|
||||||
.map(|pk| parse_pubkey(pk))
|
.map(|pk| parse_pubkey(pk))
|
||||||
@ -147,3 +144,60 @@ pub fn get_validator_duties<T: BeaconChainTypes + 'static>(req: Request<Body>) -
|
|||||||
);
|
);
|
||||||
Ok(success_response(body))
|
Ok(success_response(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// HTTP Handler to produce a new BeaconBlock from the current state, ready to be signed by a validator.
|
||||||
|
pub fn get_new_beacon_block<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
|
||||||
|
// Get beacon state
|
||||||
|
let beacon_chain = req
|
||||||
|
.extensions()
|
||||||
|
.get::<Arc<BeaconChain<T>>>()
|
||||||
|
.ok_or_else(|| ApiError::ServerError("Beacon chain extension missing".to_string()))?;
|
||||||
|
//TODO Surely this state_cache thing is not necessary?
|
||||||
|
let _ = beacon_chain
|
||||||
|
.ensure_state_caches_are_built()
|
||||||
|
.map_err(|e| ApiError::ServerError(format!("Unable to build state caches: {:?}", e)))?;
|
||||||
|
|
||||||
|
let query = UrlQuery::from_request(&req)?;
|
||||||
|
let slot = match query.first_of(&["slot"]) {
|
||||||
|
Ok((_, v)) => Slot::new(v.parse::<u64>().map_err(|e| {
|
||||||
|
ApiError::InvalidQueryParams(format!("Invalid slot parameter, must be a u64. {:?}", e))
|
||||||
|
})?),
|
||||||
|
Err(e) => {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let randao_reveal = match query.first_of(&["randao_reveal"]) {
|
||||||
|
Ok((_, v)) => Signature::from_bytes(
|
||||||
|
hex::decode(&v)
|
||||||
|
.map_err(|e| {
|
||||||
|
ApiError::InvalidQueryParams(format!(
|
||||||
|
"Invalid hex string for randao_reveal: {:?}",
|
||||||
|
e
|
||||||
|
))
|
||||||
|
})?
|
||||||
|
.as_slice(),
|
||||||
|
)
|
||||||
|
.map_err(|e| {
|
||||||
|
ApiError::InvalidQueryParams(format!("randao_reveal is not a valid signature: {:?}", e))
|
||||||
|
})?,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let new_block = match beacon_chain.produce_block(randao_reveal, slot) {
|
||||||
|
Ok((block, _state)) => block,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(ApiError::ServerError(format!(
|
||||||
|
"Beacon node is not able to produce a block: {:?}",
|
||||||
|
e
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let body = Body::from(
|
||||||
|
serde_json::to_string(&new_block)
|
||||||
|
.expect("We should always be able to serialize a new block that we created."),
|
||||||
|
);
|
||||||
|
Ok(success_response(body))
|
||||||
|
}
|
||||||
|
@ -51,7 +51,7 @@ impl<T: BeaconChainTypes> BeaconBlockService for BeaconBlockServiceInstance<T> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let produced_block = match self.chain.produce_block(randao_reveal) {
|
let produced_block = match self.chain.produce_current_block(randao_reveal) {
|
||||||
Ok((block, _state)) => block,
|
Ok((block, _state)) => block,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// could not produce a block
|
// could not produce a block
|
||||||
|
Loading…
Reference in New Issue
Block a user