mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-30 12:47:05 +00:00
add HTTP API to retrieve validator IL duties
This commit is contained in:
97
beacon_node/http_api/src/inclusion_list_duties.rs
Normal file
97
beacon_node/http_api/src/inclusion_list_duties.rs
Normal file
@@ -0,0 +1,97 @@
|
||||
use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes};
|
||||
use eth2::types::{self as api_types};
|
||||
use slot_clock::SlotClock;
|
||||
use types::{Epoch, EthSpec, Hash256, InclusionListDuty};
|
||||
|
||||
/// The struct that is returned to the requesting HTTP client.
|
||||
type ApiDuties = api_types::DutiesResponse<Vec<api_types::InclusionListDutyData>>;
|
||||
|
||||
/// Handles a request from the HTTP API for inclusion list duties.
|
||||
pub fn inclusion_list_duties<T: BeaconChainTypes>(
|
||||
request_epoch: Epoch,
|
||||
request_indices: &[u64],
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<ApiDuties, warp::reject::Rejection> {
|
||||
let current_epoch = chain
|
||||
.epoch()
|
||||
.map_err(warp_utils::reject::beacon_chain_error)?;
|
||||
|
||||
// Determine what the current epoch would be if we fast-forward our system clock by
|
||||
// `MAXIMUM_GOSSIP_CLOCK_DISPARITY`.
|
||||
//
|
||||
// Most of the time, `tolerant_current_epoch` will be equal to `current_epoch`. However, during
|
||||
// the first `MAXIMUM_GOSSIP_CLOCK_DISPARITY` duration of the epoch `tolerant_current_epoch`
|
||||
// will equal `current_epoch + 1`
|
||||
let tolerant_current_epoch = chain
|
||||
.slot_clock
|
||||
.now_with_future_tolerance(chain.spec.maximum_gossip_clock_disparity())
|
||||
.ok_or_else(|| warp_utils::reject::custom_server_error("unable to read slot clock".into()))?
|
||||
.epoch(T::EthSpec::slots_per_epoch());
|
||||
|
||||
if request_epoch == current_epoch
|
||||
|| request_epoch == current_epoch + 1
|
||||
|| request_epoch == tolerant_current_epoch + 1
|
||||
{
|
||||
let head_block_root = chain.canonical_head.cached_head().head_block_root();
|
||||
let (duties, dependent_root) = chain
|
||||
.validator_inclusion_list_duties(request_indices, request_epoch, head_block_root)
|
||||
.map_err(warp_utils::reject::beacon_chain_error)?;
|
||||
convert_to_api_response(duties, request_indices, dependent_root, chain)
|
||||
} else if request_epoch > current_epoch + 1 {
|
||||
Err(warp_utils::reject::custom_bad_request(format!(
|
||||
"request epoch {} is more than one epoch past the current epoch {}",
|
||||
request_epoch, current_epoch
|
||||
)))
|
||||
} else {
|
||||
// request_epoch < current_epoch
|
||||
//
|
||||
// TODO: support historical inclusion list duties requests
|
||||
Err(warp_utils::reject::custom_bad_request(format!(
|
||||
"request epoch {} is earlier than the current epoch {}",
|
||||
request_epoch, current_epoch
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert the internal representation of attester duties into the format returned to the HTTP
|
||||
/// client.
|
||||
fn convert_to_api_response<T: BeaconChainTypes>(
|
||||
duties: Vec<Option<InclusionListDuty>>,
|
||||
indices: &[u64],
|
||||
dependent_root: Hash256,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<ApiDuties, warp::reject::Rejection> {
|
||||
// Protect against an inconsistent slot clock.
|
||||
if duties.len() != indices.len() {
|
||||
return Err(warp_utils::reject::custom_server_error(format!(
|
||||
"duties length {} does not match indices length {}",
|
||||
duties.len(),
|
||||
indices.len()
|
||||
)));
|
||||
}
|
||||
|
||||
let usize_indices = indices.iter().map(|i| *i as usize).collect::<Vec<_>>();
|
||||
let index_to_pubkey_map = chain
|
||||
.validator_pubkey_bytes_many(&usize_indices)
|
||||
.map_err(warp_utils::reject::beacon_chain_error)?;
|
||||
|
||||
let data = duties
|
||||
.into_iter()
|
||||
.zip(indices)
|
||||
.filter_map(|(duty_opt, &validator_index)| {
|
||||
let duty = duty_opt?;
|
||||
Some(api_types::InclusionListDutyData {
|
||||
validator_index,
|
||||
pubkey: *index_to_pubkey_map.get(&(validator_index as usize))?,
|
||||
slot: duty.slot,
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// TODO: account for optimistic execution
|
||||
Ok(api_types::DutiesResponse {
|
||||
dependent_root,
|
||||
execution_optimistic: None,
|
||||
data,
|
||||
})
|
||||
}
|
||||
@@ -13,6 +13,7 @@ mod block_rewards;
|
||||
mod build_block_contents;
|
||||
mod builder_states;
|
||||
mod database;
|
||||
mod inclusion_list_duties;
|
||||
mod light_client;
|
||||
mod metrics;
|
||||
mod produce_block;
|
||||
@@ -257,6 +258,7 @@ pub fn prometheus_metrics() -> warp::filters::log::Log<impl Fn(warp::filters::lo
|
||||
.or_else(|| starts_with("v1/validator/duties/attester"))
|
||||
.or_else(|| starts_with("v1/validator/duties/proposer"))
|
||||
.or_else(|| starts_with("v1/validator/duties/sync"))
|
||||
.or_else(|| starts_with("v1/validator/duties/inclusion_list"))
|
||||
.or_else(|| starts_with("v1/validator/attestation_data"))
|
||||
.or_else(|| starts_with("v1/validator/aggregate_attestation"))
|
||||
.or_else(|| starts_with("v2/validator/aggregate_attestation"))
|
||||
@@ -3432,6 +3434,34 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
},
|
||||
);
|
||||
|
||||
// POST validator/duties/inclusion_list/{epoch}
|
||||
let post_validator_duties_inclusion_list = eth_v1
|
||||
.and(warp::path("validator"))
|
||||
.and(warp::path("duties"))
|
||||
.and(warp::path("inclusion_list"))
|
||||
.and(warp::path::param::<Epoch>().or_else(|_| async {
|
||||
Err(warp_utils::reject::custom_bad_request(
|
||||
"Invalid epoch".to_string(),
|
||||
))
|
||||
}))
|
||||
.and(warp::path::end())
|
||||
.and(not_while_syncing_filter.clone())
|
||||
.and(warp_utils::json::json())
|
||||
.and(task_spawner_filter.clone())
|
||||
.and(chain_filter.clone())
|
||||
.then(
|
||||
|epoch: Epoch,
|
||||
not_synced_filter: Result<(), Rejection>,
|
||||
indices: api_types::ValidatorIndexData,
|
||||
task_spawner: TaskSpawner<T::EthSpec>,
|
||||
chain: Arc<BeaconChain<T>>| {
|
||||
task_spawner.blocking_json_task(Priority::P0, move || {
|
||||
not_synced_filter?;
|
||||
inclusion_list_duties::inclusion_list_duties(epoch, &indices.0, &chain)
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
// GET validator/sync_committee_contribution
|
||||
let get_validator_sync_committee_contribution = eth_v1
|
||||
.and(warp::path("validator"))
|
||||
@@ -4743,6 +4773,7 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
.uor(post_beacon_rewards_sync_committee)
|
||||
.uor(post_validator_duties_attester)
|
||||
.uor(post_validator_duties_sync)
|
||||
.uor(post_validator_duties_inclusion_list)
|
||||
.uor(post_validator_aggregate_and_proofs)
|
||||
.uor(post_validator_contribution_and_proofs)
|
||||
.uor(post_validator_beacon_committee_subscriptions)
|
||||
|
||||
Reference in New Issue
Block a user