Add more tests

This commit is contained in:
Paul Hauner
2019-11-15 17:13:22 +11:00
parent 7406ef8e8a
commit a433ff8e6e
2 changed files with 91 additions and 18 deletions

View File

@@ -1,6 +1,7 @@
#![cfg(test)] #![cfg(test)]
use beacon_chain::{BeaconChain, BeaconChainTypes}; use beacon_chain::{BeaconChain, BeaconChainTypes};
use futures::Future;
use node_test_rig::{ use node_test_rig::{
environment::{Environment, EnvironmentBuilder}, environment::{Environment, EnvironmentBuilder},
LocalBeaconNode, LocalBeaconNode,
@@ -42,6 +43,47 @@ fn get_randao_reveal<T: BeaconChainTypes>(
Signature::new(&message, domain, &keypair.sk) 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] #[test]
fn validator_block_get() { fn validator_block_get() {
let mut env = build_env(); let mut env = build_env();
@@ -65,7 +107,7 @@ fn validator_block_get() {
remote_node remote_node
.http .http
.validator() .validator()
.block(slot, randao_reveal.clone()), .produce_block(slot, randao_reveal.clone()),
) )
.expect("should fetch block from http api"); .expect("should fetch block from http api");
@@ -91,12 +133,12 @@ fn beacon_state() {
let (state_by_slot, root) = env let (state_by_slot, root) = env
.runtime() .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"); .expect("should fetch state from http api");
let (state_by_root, root_2) = env let (state_by_root, root_2) = env
.runtime() .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"); .expect("should fetch state from http api");
let mut db_state = node let mut db_state = node
@@ -135,12 +177,12 @@ fn beacon_block() {
let (block_by_slot, root) = env let (block_by_slot, root) = env
.runtime() .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"); .expect("should fetch block from http api");
let (block_by_root, root_2) = env let (block_by_root, root_2) = env
.runtime() .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"); .expect("should fetch block from http api");
let db_block = node let db_block = node

View File

@@ -4,15 +4,18 @@
//! Presently, this is only used for testing but it _could_ become a user-facing library. //! Presently, this is only used for testing but it _could_ become a user-facing library.
use futures::{Future, IntoFuture}; use futures::{Future, IntoFuture};
use reqwest::r#async::{Client, RequestBuilder}; use reqwest::r#async::{Client, ClientBuilder, RequestBuilder};
use serde::Deserialize; use serde::Deserialize;
use ssz::Encode; use ssz::Encode;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::time::Duration;
use types::{BeaconBlock, BeaconState, EthSpec, Signature}; use types::{BeaconBlock, BeaconState, EthSpec, Signature};
use types::{Hash256, Slot}; use types::{Hash256, Slot};
use url::Url; use url::Url;
pub const REQUEST_TIMEOUT_SECONDS: u64 = 5;
/// Connects to a remote Lighthouse (or compatible) node via HTTP. /// Connects to a remote Lighthouse (or compatible) node via HTTP.
pub struct RemoteBeaconNode<E: EthSpec> { pub struct RemoteBeaconNode<E: EthSpec> {
pub http: HttpClient<E>, pub http: HttpClient<E>,
@@ -37,15 +40,22 @@ pub enum Error {
pub struct HttpClient<E> { pub struct HttpClient<E> {
client: Client, client: Client,
url: Url, url: Url,
timeout: Duration,
_phantom: PhantomData<E>, _phantom: PhantomData<E>,
} }
impl<E: EthSpec> HttpClient<E> { impl<E: EthSpec> HttpClient<E> {
/// Creates a new instance (without connecting to the node). /// Creates a new instance (without connecting to the node).
///
/// The `timeout` is set to 15 seconds.
pub fn new(server_url: String) -> Result<Self, Error> { pub fn new(server_url: String) -> Result<Self, Error> {
Ok(Self { 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)?, url: Url::parse(&server_url)?,
timeout: Duration::from_secs(15),
_phantom: PhantomData, _phantom: PhantomData,
}) })
} }
@@ -67,6 +77,12 @@ impl<E: EthSpec> HttpClient<E> {
self.url(path) self.url(path)
.map(|url| Client::new().get(&url.to_string())) .map(|url| Client::new().get(&url.to_string()))
} }
pub fn post(&self, path: &str) -> Result<RequestBuilder, Error> {
// TODO: add timeout
self.url(path)
.map(|url| Client::new().post(&url.to_string()))
}
} }
/// Provides the functions on the `/beacon` endpoint of the node. /// Provides the functions on the `/beacon` endpoint of the node.
@@ -81,8 +97,23 @@ impl<E: EthSpec> Validator<E> {
.map_err(Into::into) .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<E>) -> impl Future<Item = (), Error = Error> {
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. /// Requests a new (unsigned) block from the beacon node.
pub fn block( pub fn produce_block(
&self, &self,
slot: Slot, slot: Slot,
randao_reveal: Signature, randao_reveal: Signature,
@@ -116,23 +147,23 @@ impl<E: EthSpec> Beacon<E> {
} }
/// Returns the block and block root at the given slot. /// Returns the block and block root at the given slot.
pub fn block_by_slot( pub fn get_block_by_slot(
&self, &self,
slot: Slot, slot: Slot,
) -> impl Future<Item = (BeaconBlock<E>, Hash256), Error = Error> { ) -> impl Future<Item = (BeaconBlock<E>, 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. /// Returns the block and block root at the given root.
pub fn block_by_root( pub fn get_block_by_root(
&self, &self,
root: Hash256, root: Hash256,
) -> impl Future<Item = (BeaconBlock<E>, Hash256), Error = Error> { ) -> impl Future<Item = (BeaconBlock<E>, 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. /// Returns the block and block root at the given slot.
fn block( fn get_block(
&self, &self,
query_key: &'static str, query_key: &'static str,
query_param: String, query_param: String,
@@ -151,23 +182,23 @@ impl<E: EthSpec> Beacon<E> {
} }
/// Returns the state and state root at the given slot. /// Returns the state and state root at the given slot.
pub fn state_by_slot( pub fn get_state_by_slot(
&self, &self,
slot: Slot, slot: Slot,
) -> impl Future<Item = (BeaconState<E>, Hash256), Error = Error> { ) -> impl Future<Item = (BeaconState<E>, 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. /// Returns the state and state root at the given root.
pub fn state_by_root( pub fn get_state_by_root(
&self, &self,
root: Hash256, root: Hash256,
) -> impl Future<Item = (BeaconState<E>, Hash256), Error = Error> { ) -> impl Future<Item = (BeaconState<E>, 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. /// Returns the state and state root at the given slot.
fn state( fn get_state(
&self, &self,
query_key: &'static str, query_key: &'static str,
query_param: String, query_param: String,