diff --git a/beacon_node/rest_api/src/helpers.rs b/beacon_node/rest_api/src/helpers.rs index 2477884c4..98293e75c 100644 --- a/beacon_node/rest_api/src/helpers.rs +++ b/beacon_node/rest_api/src/helpers.rs @@ -5,6 +5,7 @@ use hex; use hyper::{Body, Request}; use store::{iter::AncestorIter, Store}; use types::{BeaconState, EthSpec, Hash256, RelativeEpoch, Slot}; +use std::sync::Arc; /// Parse a slot from a `0x` preixed string. /// @@ -169,6 +170,18 @@ pub fn implementation_pending_response(_req: Request) -> ApiResult { )) } +pub fn get_beacon_chain_from_request(req: &Request) -> Result>, ApiError> { + // Get beacon state + let beacon_chain = req + .extensions() + .get::>>() + .ok_or_else(|| ApiError::ServerError("Request is missing the beacon chain extension".into()))?; + let _ = beacon_chain + .ensure_state_caches_are_built() + .map_err(|e| ApiError::ServerError(format!("Unable to build state caches: {:?}", e)))?; + Ok(beacon_chain.clone()) +} + #[cfg(test)] mod test { use super::*; diff --git a/beacon_node/rest_api/src/lib.rs b/beacon_node/rest_api/src/lib.rs index 2c7b90e3f..2c9c4011a 100644 --- a/beacon_node/rest_api/src/lib.rs +++ b/beacon_node/rest_api/src/lib.rs @@ -172,9 +172,9 @@ pub fn start_server( (&Method::POST, "/beacon/validator/block") => { helpers::implementation_pending_response(req) } - (&Method::GET, "/beacon/validator/attestation") => { + /*(&Method::GET, "/beacon/validator/attestation") => { validator::get_new_attestation::(req) - } + }*/ (&Method::POST, "/beacon/validator/attestation") => { helpers::implementation_pending_response(req) } diff --git a/beacon_node/rest_api/src/validator.rs b/beacon_node/rest_api/src/validator.rs index 1c72874f2..f60acbad8 100644 --- a/beacon_node/rest_api/src/validator.rs +++ b/beacon_node/rest_api/src/validator.rs @@ -5,6 +5,7 @@ use bls::{AggregateSignature, PublicKey, Signature}; use hyper::{Body, Request}; use serde::{Deserialize, Serialize}; use std::sync::Arc; +use std::borrow::Borrow; use types::beacon_state::EthSpec; use types::{Attestation, BitList, Epoch, RelativeEpoch, Shard, Slot}; @@ -33,15 +34,7 @@ impl ValidatorDuty { /// HTTP Handler to retrieve a the duties for a set of validators during a particular epoch pub fn get_validator_duties(req: Request) -> ApiResult { - // Get beacon state - let beacon_chain = req - .extensions() - .get::>>() - .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 beacon_chain = get_beacon_chain_from_request::(&req)?; let head_state = &beacon_chain.head().beacon_state; // Parse and check query parameters @@ -146,15 +139,8 @@ pub fn get_validator_duties(req: Request) - /// HTTP Handler to produce a new BeaconBlock from the current state, ready to be signed by a validator. pub fn get_new_beacon_block(req: Request) -> ApiResult { - // Get beacon state - let beacon_chain = req - .extensions() - .get::>>() - .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 beacon_chain = get_beacon_chain_from_request::(&req)?; + let head_state = &beacon_chain.head().beacon_state; let query = UrlQuery::from_request(&req)?; let slot = match query.first_of(&["slot"]) { @@ -201,17 +187,60 @@ pub fn get_new_beacon_block(req: Request) - Ok(success_response(body)) } +/// HTTP Handler to accept a validator-signed BeaconBlock, and publish it to the network. +pub fn publish_beacon_block(req: Request) -> ApiResult { + let beacon_chain = get_beacon_chain_from_request::(&req)?; + let head_state = &beacon_chain.head().beacon_state; + + let query = UrlQuery::from_request(&req)?; + let slot = match query.first_of(&["slot"]) { + Ok((_, v)) => Slot::new(v.parse::().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 produced."), + ); + Ok(success_response(body)) +} + +/* /// HTTP Handler to produce a new Attestation from the current state, ready to be signed by a validator. pub fn get_new_attestation(req: Request) -> ApiResult { - // Get beacon state - let beacon_chain = req - .extensions() - .get::>>() - .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 beacon_chain = get_beacon_chain_from_request(req)?; let head_state = &beacon_chain.head().beacon_state; let query = UrlQuery::from_request(&req)?; @@ -340,3 +369,4 @@ pub fn get_new_attestation(req: Request) -> ); Ok(success_response(body)) } +*/