diff --git a/beacon_node/rest_api/src/consensus.rs b/beacon_node/rest_api/src/consensus.rs index 5d3749fc0..c22fb2f88 100644 --- a/beacon_node/rest_api/src/consensus.rs +++ b/beacon_node/rest_api/src/consensus.rs @@ -156,12 +156,16 @@ pub fn post_individual_votes( // This is the last slot of the given epoch (one prior to the first slot of the next epoch). let target_slot = (epoch + 1).start_slot(T::EthSpec::slots_per_epoch()) - 1; - let (_root, state) = state_at_slot(&beacon_chain, target_slot)?; + let (_root, mut state) = state_at_slot(&beacon_chain, target_slot)?; let spec = &beacon_chain.spec; let mut validator_statuses = ValidatorStatuses::new(&state, spec)?; validator_statuses.process_attestations(&state, spec)?; + state.update_pubkey_cache().map_err(|e| { + ApiError::ServerError(format!("Unable to build pubkey cache: {:?}", e)) + })?; + body.pubkeys .into_iter() .map(|pubkey| { diff --git a/beacon_node/rest_api/src/lib.rs b/beacon_node/rest_api/src/lib.rs index f4f13babc..6f219529d 100644 --- a/beacon_node/rest_api/src/lib.rs +++ b/beacon_node/rest_api/src/lib.rs @@ -45,6 +45,7 @@ pub use beacon::{ ValidatorRequest, ValidatorResponse, }; pub use config::Config; +pub use consensus::{IndividualVote, IndividualVotesRequest, IndividualVotesResponse}; pub use validator::{ValidatorDutiesRequest, ValidatorDuty}; pub type BoxFut = Box, Error = ApiError> + Send>; diff --git a/eth2/utils/remote_beacon_node/src/lib.rs b/eth2/utils/remote_beacon_node/src/lib.rs index 64791e8ad..e7b235256 100644 --- a/eth2/utils/remote_beacon_node/src/lib.rs +++ b/eth2/utils/remote_beacon_node/src/lib.rs @@ -15,15 +15,16 @@ use std::marker::PhantomData; use std::time::Duration; use types::{ Attestation, AttesterSlashing, BeaconBlock, BeaconState, CommitteeIndex, Epoch, EthSpec, Fork, - Hash256, ProposerSlashing, PublicKey, Signature, SignedBeaconBlock, Slot, + Hash256, ProposerSlashing, PublicKey, PublicKeyBytes, Signature, SignedBeaconBlock, Slot, }; use url::Url; pub use operation_pool::PersistedOperationPool; pub use proto_array_fork_choice::core::ProtoArray; pub use rest_api::{ - CanonicalHeadResponse, Committee, HeadBeaconBlock, ValidatorDutiesRequest, ValidatorDuty, - ValidatorRequest, ValidatorResponse, + CanonicalHeadResponse, Committee, HeadBeaconBlock, IndividualVotesRequest, + IndividualVotesResponse, ValidatorDutiesRequest, ValidatorDuty, ValidatorRequest, + ValidatorResponse, }; // Setting a long timeout for debug ensures that crypto-heavy operations can still succeed. @@ -107,6 +108,10 @@ impl HttpClient { Advanced(self.clone()) } + pub fn consensus(&self) -> Consensus { + Consensus(self.clone()) + } + fn url(&self, path: &str) -> Result { self.url.join(path).map_err(|e| e.into()) } @@ -605,6 +610,47 @@ impl Advanced { } } +/// Provides the functions on the `/consensus` endpoint of the node. +#[derive(Clone)] +pub struct Consensus(HttpClient); + +impl Consensus { + fn url(&self, path: &str) -> Result { + self.0 + .url("consensus/") + .and_then(move |url| url.join(path).map_err(Error::from)) + .map_err(Into::into) + } + + /// Gets a `IndividualVote` for each of the given `pubkeys`. + pub fn get_individual_votes( + &self, + epoch: Epoch, + pubkeys: Vec, + ) -> impl Future { + let client = self.0.clone(); + let req_body = IndividualVotesRequest { epoch, pubkeys }; + + self.url("individual_votes") + .into_future() + .and_then(move |url| client.json_post::<_>(url, req_body)) + .and_then(|response| error_for_status(response).map_err(Error::from)) + .and_then(|mut success| success.json().map_err(Error::from)) + } + + /// Gets a `VoteCount` for the given `epoch`. + pub fn get_vote_count( + &self, + epoch: Epoch, + ) -> impl Future { + let client = self.0.clone(); + let query_params = vec![("epoch".into(), format!("{}", epoch.as_u64()))]; + self.url("vote_count") + .into_future() + .and_then(move |url| client.json_get(url, query_params)) + } +} + #[derive(Deserialize)] #[serde(bound = "T: EthSpec")] pub struct BlockResponse {