Start heavy refactor of validator client

- Block production is working
This commit is contained in:
Paul Hauner
2019-11-22 01:22:05 +11:00
parent 06002f3f6a
commit 114067bb50
20 changed files with 1165 additions and 150 deletions

View File

@@ -249,3 +249,11 @@ pub fn get_genesis_state<T: BeaconChainTypes + 'static>(
ResponseBuilder::new(&req)?.body(&state)
}
/// Read the genesis time from the current beacon chain state.
pub fn get_genesis_time<T: BeaconChainTypes + 'static>(
req: Request<Body>,
beacon_chain: Arc<BeaconChain<T>>,
) -> ApiResult {
ResponseBuilder::new(&req)?.body(&beacon_chain.head().beacon_state.genesis_time)
}

View File

@@ -9,11 +9,3 @@ use version;
pub fn get_version(req: Request<Body>) -> ApiResult {
ResponseBuilder::new(&req)?.body_no_ssz(&version::version())
}
/// Read the genesis time from the current beacon chain state.
pub fn get_genesis_time<T: BeaconChainTypes + 'static>(
req: Request<Body>,
beacon_chain: Arc<BeaconChain<T>>,
) -> ApiResult {
ResponseBuilder::new(&req)?.body(&beacon_chain.head().beacon_state.genesis_time)
}

View File

@@ -38,9 +38,6 @@ pub fn route<T: BeaconChainTypes>(
match (req.method(), path.as_ref()) {
// Methods for Client
(&Method::GET, "/node/version") => into_boxfut(node::get_version(req)),
(&Method::GET, "/node/genesis_time") => {
into_boxfut(node::get_genesis_time::<T>(req, beacon_chain))
}
(&Method::GET, "/node/syncing") => {
into_boxfut(helpers::implementation_pending_response(req))
}
@@ -83,6 +80,9 @@ pub fn route<T: BeaconChainTypes>(
(&Method::GET, "/beacon/attestations/pending") => {
into_boxfut(helpers::implementation_pending_response(req))
}
(&Method::GET, "/beacon/genesis_time") => {
into_boxfut(beacon::get_genesis_time::<T>(req, beacon_chain))
}
(&Method::GET, "/beacon/validators") => {
into_boxfut(beacon::get_validators::<T>(req, beacon_chain))

View File

@@ -17,7 +17,7 @@ use std::sync::Arc;
use types::beacon_state::EthSpec;
use types::{Attestation, BeaconBlock, CommitteeIndex, RelativeEpoch, Slot};
#[derive(Debug, Serialize, Deserialize, Clone)]
#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)]
pub struct ValidatorDuty {
/// The validator's BLS public key, uniquely identifying them. _48-bytes, hex encoded with 0x prefix, case insensitive._
pub validator_pubkey: PublicKey,
@@ -45,19 +45,23 @@ pub fn get_validator_duties<T: BeaconChainTypes + 'static>(
let epoch = query.epoch()?;
let mut head_state = beacon_chain.head().beacon_state;
let mut state = beacon_chain
.state_at_slot(epoch.start_slot(T::EthSpec::slots_per_epoch()))
.map_err(|e| {
ApiError::ServerError(format!("Unable to load state for epoch {}: {:?}", epoch, e))
})?;
let current_epoch = head_state.current_epoch();
let current_epoch = state.current_epoch();
let relative_epoch = RelativeEpoch::from_epoch(current_epoch, epoch).map_err(|_| {
ApiError::BadRequest(format!(
"Epoch must be within one epoch of the current epoch",
))
})?;
head_state
state
.build_committee_cache(relative_epoch, &beacon_chain.spec)
.map_err(|e| ApiError::ServerError(format!("Unable to build committee cache: {:?}", e)))?;
head_state
state
.update_pubkey_cache()
.map_err(|e| ApiError::ServerError(format!("Unable to build pubkey cache: {:?}", e)))?;
@@ -67,7 +71,7 @@ pub fn get_validator_duties<T: BeaconChainTypes + 'static>(
let validator_proposers: Vec<(usize, Slot)> = epoch
.slot_iter(T::EthSpec::slots_per_epoch())
.map(|slot| {
head_state
state
.get_beacon_proposer_index(slot, &beacon_chain.spec)
.map(|i| (i, slot))
.map_err(|e| {
@@ -84,13 +88,12 @@ pub fn get_validator_duties<T: BeaconChainTypes + 'static>(
.iter()
.map(|validator_pubkey_str| {
parse_pubkey(validator_pubkey_str).and_then(|validator_pubkey| {
if let Some(validator_index) = head_state
.get_validator_index(&validator_pubkey)
.map_err(|e| {
if let Some(validator_index) =
state.get_validator_index(&validator_pubkey).map_err(|e| {
ApiError::ServerError(format!("Unable to read pubkey cache: {:?}", e))
})?
{
let duties = head_state
let duties = state
.get_attestation_duties(validator_index, relative_epoch)
.map_err(|e| {
ApiError::ServerError(format!(

View File

@@ -3,7 +3,7 @@
use beacon_chain::{BeaconChain, BeaconChainTypes};
use node_test_rig::{
environment::{Environment, EnvironmentBuilder},
LocalBeaconNode,
testing_client_config, ClientGenesis, LocalBeaconNode,
};
use remote_beacon_node::PublishStatus;
use std::sync::Arc;
@@ -66,7 +66,7 @@ fn validator_produce_attestation() {
let spec = &E::default_spec();
let node = LocalBeaconNode::production(env.core_context());
let node = LocalBeaconNode::production(env.core_context(), testing_client_config());
let remote_node = node.remote_node().expect("should produce remote node");
let beacon_chain = node
@@ -75,36 +75,6 @@ fn validator_produce_attestation() {
.expect("client should have beacon chain");
let state = beacon_chain.head().beacon_state.clone();
/*
// Publish a block so that we're not attesting to the genesis block.
{
let slot = Slot::new(1);
let randao_reveal = get_randao_reveal(beacon_chain.clone(), slot, spec);
let mut block = env
.runtime()
.block_on(
remote_node
.http
.validator()
.produce_block(slot, randao_reveal.clone()),
)
.expect("should fetch block from http api");
sign_block(beacon_chain.clone(), &mut block, spec);
let publish_status = env
.runtime()
.block_on(remote_node.http.validator().publish_block(block.clone()))
.expect("should publish block");
assert_eq!(
publish_status,
PublishStatus::Valid,
"should have published block"
);
}
*/
let validator_index = 0;
let duties = state
.get_attestation_duties(validator_index, RelativeEpoch::Current)
@@ -195,7 +165,7 @@ fn validator_duties() {
let spec = &E::default_spec();
let node = LocalBeaconNode::production(env.core_context());
let node = LocalBeaconNode::production(env.core_context(), testing_client_config());
let remote_node = node.remote_node().expect("should produce remote node");
let beacon_chain = node
@@ -282,7 +252,13 @@ fn validator_block_post() {
let spec = &E::default_spec();
let node = LocalBeaconNode::production(env.core_context());
let mut config = testing_client_config();
config.genesis = ClientGenesis::Interop {
validator_count: 8,
genesis_time: 13_371_337,
};
let node = LocalBeaconNode::production(env.core_context(), config);
let remote_node = node.remote_node().expect("should produce remote node");
let beacon_chain = node
@@ -343,7 +319,7 @@ fn validator_block_get() {
let spec = &E::default_spec();
let node = LocalBeaconNode::production(env.core_context());
let node = LocalBeaconNode::production(env.core_context(), testing_client_config());
let remote_node = node.remote_node().expect("should produce remote node");
let beacon_chain = node
@@ -381,7 +357,7 @@ fn validator_block_get() {
fn beacon_state() {
let mut env = build_env();
let node = LocalBeaconNode::production(env.core_context());
let node = LocalBeaconNode::production(env.core_context(), testing_client_config());
let remote_node = node.remote_node().expect("should produce remote node");
let (state_by_slot, root) = env
@@ -425,7 +401,7 @@ fn beacon_state() {
fn beacon_block() {
let mut env = build_env();
let node = LocalBeaconNode::production(env.core_context());
let node = LocalBeaconNode::production(env.core_context(), testing_client_config());
let remote_node = node.remote_node().expect("should produce remote node");
let (block_by_slot, root) = env
@@ -464,3 +440,75 @@ fn beacon_block() {
"genesis block by root from api should match that from the DB"
);
}
#[test]
fn genesis_time() {
let mut env = build_env();
let node = LocalBeaconNode::production(env.core_context(), testing_client_config());
let remote_node = node.remote_node().expect("should produce remote node");
let genesis_time = env
.runtime()
.block_on(remote_node.http.beacon().get_genesis_time())
.expect("should fetch genesis time from http api");
assert_eq!(
node.client
.beacon_chain()
.expect("should have beacon chain")
.head()
.beacon_state
.genesis_time,
genesis_time,
"should match genesis time from head state"
);
}
#[test]
fn fork() {
let mut env = build_env();
let node = LocalBeaconNode::production(env.core_context(), testing_client_config());
let remote_node = node.remote_node().expect("should produce remote node");
let fork = env
.runtime()
.block_on(remote_node.http.beacon().get_fork())
.expect("should fetch from http api");
assert_eq!(
node.client
.beacon_chain()
.expect("should have beacon chain")
.head()
.beacon_state
.fork,
fork,
"should match head state"
);
}
#[test]
fn eth2_config() {
let mut env = build_env();
let node = LocalBeaconNode::production(env.core_context(), testing_client_config());
let remote_node = node.remote_node().expect("should produce remote node");
let eth2_config = env
.runtime()
.block_on(remote_node.http.spec().get_eth2_config())
.expect("should fetch eth2 config from http api");
// TODO: check the entire eth2_config, not just the spec.
assert_eq!(
node.client
.beacon_chain()
.expect("should have beacon chain")
.spec,
eth2_config.spec,
"should match genesis time from head state"
);
}