mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-11 18:04:18 +00:00
Start work on attestation endpoint
This commit is contained in:
@@ -28,6 +28,7 @@ sloggers = "0.3.4"
|
||||
slot_clock = { path = "../../eth2/utils/slot_clock" }
|
||||
eth2_hashing = "0.1.0"
|
||||
eth2_ssz = "0.1.2"
|
||||
eth2_ssz_types = { path = "../../eth2/utils/ssz_types" }
|
||||
eth2_ssz_derive = "0.1.0"
|
||||
state_processing = { path = "../../eth2/state_processing" }
|
||||
tree_hash = "0.1.0"
|
||||
|
||||
@@ -444,6 +444,42 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Produce an `Attestation` that is valid for the given `slot` `shard`.
|
||||
///
|
||||
/// Always attests to the canonical chain.
|
||||
pub fn produce_attestation(
|
||||
&self,
|
||||
shard: u64,
|
||||
slot: Slot,
|
||||
) -> Result<Attestation<T::EthSpec>, Error> {
|
||||
let state = self.state_at_slot(slot)?;
|
||||
let head = self.head();
|
||||
|
||||
let data = self.produce_attestation_data_for_block(
|
||||
shard,
|
||||
head.beacon_block_root,
|
||||
head.beacon_block.slot,
|
||||
&state,
|
||||
)?;
|
||||
|
||||
let relative_epoch =
|
||||
RelativeEpoch::from_slot(state.slot, slot, T::EthSpec::slots_per_epoch())?;
|
||||
|
||||
let committee_len = state
|
||||
.get_crosslink_committee_for_shard(shard, relative_epoch)?
|
||||
.committee
|
||||
.len();
|
||||
|
||||
let empty_bitfield = BitList::with_capacity(committee_len)?;
|
||||
|
||||
Ok(Attestation {
|
||||
aggregation_bits: empty_bitfield.clone(),
|
||||
data,
|
||||
custody_bits: empty_bitfield,
|
||||
signature: AggregateSignature::new(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Produce an `AttestationData` that is valid for the given `slot` `shard`.
|
||||
///
|
||||
/// Always attests to the canonical chain.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::eth1_chain::Error as Eth1ChainError;
|
||||
use crate::fork_choice::Error as ForkChoiceError;
|
||||
use ssz_types::Error as SszTypesError;
|
||||
use state_processing::per_block_processing::errors::AttestationValidationError;
|
||||
use state_processing::BlockProcessingError;
|
||||
use state_processing::SlotProcessingError;
|
||||
@@ -41,10 +42,14 @@ pub enum BeaconChainError {
|
||||
AttestationValidationError(AttestationValidationError),
|
||||
/// Returned when an internal check fails, indicating corrupt data.
|
||||
InvariantViolated(String),
|
||||
RelativeEpochError(RelativeEpochError),
|
||||
SszTypesError(SszTypesError),
|
||||
}
|
||||
|
||||
easy_from_to!(SlotProcessingError, BeaconChainError);
|
||||
easy_from_to!(AttestationValidationError, BeaconChainError);
|
||||
easy_from_to!(RelativeEpochError, BeaconChainError);
|
||||
easy_from_to!(SszTypesError, BeaconChainError);
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum BlockProductionError {
|
||||
|
||||
@@ -38,6 +38,15 @@ pub fn parse_epoch(string: &str) -> Result<Epoch, ApiError> {
|
||||
.map_err(|e| ApiError::BadRequest(format!("Unable to parse epoch: {:?}", e)))
|
||||
}
|
||||
|
||||
/// Parse an shard.
|
||||
///
|
||||
/// E.g., `"18"`
|
||||
pub fn parse_shard(string: &str) -> Result<u64, ApiError> {
|
||||
string
|
||||
.parse::<u64>()
|
||||
.map_err(|e| ApiError::BadRequest(format!("Unable to parse shard: {:?}", e)))
|
||||
}
|
||||
|
||||
/// Checks the provided request to ensure that the `content-type` header.
|
||||
///
|
||||
/// The content-type header should either be omitted, in which case JSON is assumed, or it should
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::helpers::{
|
||||
check_content_type_for_json, parse_epoch, parse_pubkey, parse_signature,
|
||||
publish_attestation_to_network, publish_beacon_block_to_network,
|
||||
check_content_type_for_json, parse_epoch, parse_pubkey, parse_shard, parse_signature,
|
||||
parse_slot, publish_attestation_to_network, publish_beacon_block_to_network,
|
||||
};
|
||||
use crate::response_builder::ResponseBuilder;
|
||||
use crate::{ApiError, ApiResult, BoxFut, NetworkChannel, UrlQuery};
|
||||
@@ -82,44 +82,43 @@ pub fn get_validator_duties<T: BeaconChainTypes + 'static>(
|
||||
let duties = query
|
||||
.all_of("validator_pubkeys")?
|
||||
.iter()
|
||||
.map(|string| parse_pubkey(string))
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.into_iter()
|
||||
.map(|validator_pubkey| {
|
||||
if let Some(validator_index) = head_state
|
||||
.get_validator_index(&validator_pubkey)
|
||||
.map_err(|e| {
|
||||
ApiError::ServerError(format!("Unable to read pubkey cache: {:?}", e))
|
||||
})?
|
||||
{
|
||||
let duties = head_state
|
||||
.get_attestation_duties(validator_index, relative_epoch)
|
||||
.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| {
|
||||
ApiError::ServerError(format!(
|
||||
"Unable to obtain attestation duties: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
ApiError::ServerError(format!("Unable to read pubkey cache: {:?}", e))
|
||||
})?
|
||||
{
|
||||
let duties = head_state
|
||||
.get_attestation_duties(validator_index, relative_epoch)
|
||||
.map_err(|e| {
|
||||
ApiError::ServerError(format!(
|
||||
"Unable to obtain attestation duties: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
|
||||
let block_proposal_slot = validator_proposers
|
||||
.iter()
|
||||
.find(|(i, _slot)| validator_index == *i)
|
||||
.map(|(_i, slot)| *slot);
|
||||
let block_proposal_slot = validator_proposers
|
||||
.iter()
|
||||
.find(|(i, _slot)| validator_index == *i)
|
||||
.map(|(_i, slot)| *slot);
|
||||
|
||||
Ok(ValidatorDuty {
|
||||
validator_pubkey,
|
||||
attestation_slot: duties.map(|d| d.slot),
|
||||
attestation_shard: duties.map(|d| d.shard),
|
||||
block_proposal_slot,
|
||||
})
|
||||
} else {
|
||||
Ok(ValidatorDuty {
|
||||
validator_pubkey,
|
||||
attestation_slot: None,
|
||||
attestation_shard: None,
|
||||
block_proposal_slot: None,
|
||||
})
|
||||
}
|
||||
Ok(ValidatorDuty {
|
||||
validator_pubkey,
|
||||
attestation_slot: duties.map(|d| d.slot),
|
||||
attestation_shard: duties.map(|d| d.shard),
|
||||
block_proposal_slot,
|
||||
})
|
||||
} else {
|
||||
Ok(ValidatorDuty {
|
||||
validator_pubkey,
|
||||
attestation_slot: None,
|
||||
attestation_shard: None,
|
||||
block_proposal_slot: None,
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>, ApiError>>()?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user