From a433ff8e6e9430ba9991445e8da892422b5f1f2c Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Fri, 15 Nov 2019 17:13:22 +1100 Subject: [PATCH] Add more tests --- beacon_node/rest_api/tests/test.rs | 52 ++++++++++++++++++--- eth2/utils/remote_beacon_node/src/lib.rs | 57 ++++++++++++++++++------ 2 files changed, 91 insertions(+), 18 deletions(-) diff --git a/beacon_node/rest_api/tests/test.rs b/beacon_node/rest_api/tests/test.rs index 3ab04729a2..c833827543 100644 --- a/beacon_node/rest_api/tests/test.rs +++ b/beacon_node/rest_api/tests/test.rs @@ -1,6 +1,7 @@ #![cfg(test)] use beacon_chain::{BeaconChain, BeaconChainTypes}; +use futures::Future; use node_test_rig::{ environment::{Environment, EnvironmentBuilder}, LocalBeaconNode, @@ -42,6 +43,47 @@ fn get_randao_reveal( Signature::new(&message, domain, &keypair.sk) } +/* +#[test] +fn validator_block_post() { + let mut env = build_env(); + + let spec = &E::default_spec(); + + let node = LocalBeaconNode::production(env.core_context()); + let remote_node = node.remote_node().expect("should produce remote node"); + + let beacon_chain = node + .client + .beacon_chain() + .expect("client should have beacon chain"); + + let slot = Slot::new(1); + let randao_reveal = get_randao_reveal(beacon_chain.clone(), slot, spec); + + let block = env + .runtime() + .block_on( + remote_node + .http + .validator() + .produce_block(slot, randao_reveal.clone()), + ) + .expect("should fetch block from http api"); + + assert!(env + .runtime() + .block_on( + remote_node + .http + .validator() + .publish_block(block) + .and_then(|_| Ok(())) + ) + .is_ok()); +} +*/ + #[test] fn validator_block_get() { let mut env = build_env(); @@ -65,7 +107,7 @@ fn validator_block_get() { remote_node .http .validator() - .block(slot, randao_reveal.clone()), + .produce_block(slot, randao_reveal.clone()), ) .expect("should fetch block from http api"); @@ -91,12 +133,12 @@ fn beacon_state() { let (state_by_slot, root) = env .runtime() - .block_on(remote_node.http.beacon().state_by_slot(Slot::new(0))) + .block_on(remote_node.http.beacon().get_state_by_slot(Slot::new(0))) .expect("should fetch state from http api"); let (state_by_root, root_2) = env .runtime() - .block_on(remote_node.http.beacon().state_by_root(root)) + .block_on(remote_node.http.beacon().get_state_by_root(root)) .expect("should fetch state from http api"); let mut db_state = node @@ -135,12 +177,12 @@ fn beacon_block() { let (block_by_slot, root) = env .runtime() - .block_on(remote_node.http.beacon().block_by_slot(Slot::new(0))) + .block_on(remote_node.http.beacon().get_block_by_slot(Slot::new(0))) .expect("should fetch block from http api"); let (block_by_root, root_2) = env .runtime() - .block_on(remote_node.http.beacon().block_by_root(root)) + .block_on(remote_node.http.beacon().get_block_by_root(root)) .expect("should fetch block from http api"); let db_block = node diff --git a/eth2/utils/remote_beacon_node/src/lib.rs b/eth2/utils/remote_beacon_node/src/lib.rs index 1ef0c9cc38..cc21899cf3 100644 --- a/eth2/utils/remote_beacon_node/src/lib.rs +++ b/eth2/utils/remote_beacon_node/src/lib.rs @@ -4,15 +4,18 @@ //! Presently, this is only used for testing but it _could_ become a user-facing library. use futures::{Future, IntoFuture}; -use reqwest::r#async::{Client, RequestBuilder}; +use reqwest::r#async::{Client, ClientBuilder, RequestBuilder}; use serde::Deserialize; use ssz::Encode; use std::marker::PhantomData; use std::net::SocketAddr; +use std::time::Duration; use types::{BeaconBlock, BeaconState, EthSpec, Signature}; use types::{Hash256, Slot}; use url::Url; +pub const REQUEST_TIMEOUT_SECONDS: u64 = 5; + /// Connects to a remote Lighthouse (or compatible) node via HTTP. pub struct RemoteBeaconNode { pub http: HttpClient, @@ -37,15 +40,22 @@ pub enum Error { pub struct HttpClient { client: Client, url: Url, + timeout: Duration, _phantom: PhantomData, } impl HttpClient { /// Creates a new instance (without connecting to the node). + /// + /// The `timeout` is set to 15 seconds. pub fn new(server_url: String) -> Result { Ok(Self { - client: Client::new(), + client: ClientBuilder::new() + .timeout(Duration::from_secs(REQUEST_TIMEOUT_SECONDS)) + .build() + .expect("should build from static configuration"), url: Url::parse(&server_url)?, + timeout: Duration::from_secs(15), _phantom: PhantomData, }) } @@ -67,6 +77,12 @@ impl HttpClient { self.url(path) .map(|url| Client::new().get(&url.to_string())) } + + pub fn post(&self, path: &str) -> Result { + // TODO: add timeout + self.url(path) + .map(|url| Client::new().post(&url.to_string())) + } } /// Provides the functions on the `/beacon` endpoint of the node. @@ -81,8 +97,23 @@ impl Validator { .map_err(Into::into) } + /// Posts a block to the beacon node, expecting it to verify it and publish it to the network. + pub fn publish_block(&self, block: BeaconBlock) -> impl Future { + let client = self.0.clone(); + self.url("block") + .into_future() + .and_then(move |url| client.post(&url.to_string())) + .and_then(move |builder| { + builder + .json(&block) + .send() + .map_err(|e| Error::ReqwestError(e)) + }) + .map(|_response| ()) + } + /// Requests a new (unsigned) block from the beacon node. - pub fn block( + pub fn produce_block( &self, slot: Slot, randao_reveal: Signature, @@ -116,23 +147,23 @@ impl Beacon { } /// Returns the block and block root at the given slot. - pub fn block_by_slot( + pub fn get_block_by_slot( &self, slot: Slot, ) -> impl Future, Hash256), Error = Error> { - self.block("slot", format!("{}", slot.as_u64())) + self.get_block("slot", format!("{}", slot.as_u64())) } /// Returns the block and block root at the given root. - pub fn block_by_root( + pub fn get_block_by_root( &self, root: Hash256, ) -> impl Future, Hash256), Error = Error> { - self.block("root", root_as_string(root)) + self.get_block("root", root_as_string(root)) } /// Returns the block and block root at the given slot. - fn block( + fn get_block( &self, query_key: &'static str, query_param: String, @@ -151,23 +182,23 @@ impl Beacon { } /// Returns the state and state root at the given slot. - pub fn state_by_slot( + pub fn get_state_by_slot( &self, slot: Slot, ) -> impl Future, Hash256), Error = Error> { - self.state("slot", format!("{}", slot.as_u64())) + self.get_state("slot", format!("{}", slot.as_u64())) } /// Returns the state and state root at the given root. - pub fn state_by_root( + pub fn get_state_by_root( &self, root: Hash256, ) -> impl Future, Hash256), Error = Error> { - self.state("root", root_as_string(root)) + self.get_state("root", root_as_string(root)) } /// Returns the state and state root at the given slot. - fn state( + fn get_state( &self, query_key: &'static str, query_param: String,