mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-29 20:27:14 +00:00
Remove /lighthouse/analysis/block_rewards APIs (#8935)
Mark pointed out that these APIs will require updates for Gloas, so I figured we may as well get rid of them. As far as I know, blockprint was the only use case and it is now defunct. The consensus block value is included in getBlock API responses, so there's no reason for VCs to use the `POST` API, and there is now a standard API for the rewards of canonical blocks. The SSE event was non-standard, and likely only used by blockprint as well. Co-Authored-By: Michael Sproul <michael@sigmaprime.io>
This commit is contained in:
@@ -1,140 +0,0 @@
|
||||
use crate::{BeaconChain, BeaconChainError, BeaconChainTypes};
|
||||
use eth2::lighthouse::{AttestationRewards, BlockReward, BlockRewardMeta};
|
||||
use operation_pool::{
|
||||
AttMaxCover, MaxCover, PROPOSER_REWARD_DENOMINATOR, RewardCache, SplitAttestation,
|
||||
};
|
||||
use state_processing::{
|
||||
common::get_attesting_indices_from_state,
|
||||
per_block_processing::altair::sync_committee::compute_sync_aggregate_rewards,
|
||||
};
|
||||
use types::{AbstractExecPayload, BeaconBlockRef, BeaconState, EthSpec, Hash256};
|
||||
|
||||
impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
pub fn compute_block_reward<Payload: AbstractExecPayload<T::EthSpec>>(
|
||||
&self,
|
||||
block: BeaconBlockRef<'_, T::EthSpec, Payload>,
|
||||
block_root: Hash256,
|
||||
state: &BeaconState<T::EthSpec>,
|
||||
reward_cache: &mut RewardCache,
|
||||
include_attestations: bool,
|
||||
) -> Result<BlockReward, BeaconChainError> {
|
||||
if block.slot() != state.slot() {
|
||||
return Err(BeaconChainError::BlockRewardSlotError);
|
||||
}
|
||||
|
||||
reward_cache.update(state)?;
|
||||
|
||||
let total_active_balance = state.get_total_active_balance()?;
|
||||
|
||||
let split_attestations = block
|
||||
.body()
|
||||
.attestations()
|
||||
.map(|att| {
|
||||
let attesting_indices = get_attesting_indices_from_state(state, att)?;
|
||||
Ok(SplitAttestation::new(
|
||||
att.clone_as_attestation(),
|
||||
attesting_indices,
|
||||
))
|
||||
})
|
||||
.collect::<Result<Vec<_>, BeaconChainError>>()?;
|
||||
|
||||
let mut per_attestation_rewards = split_attestations
|
||||
.iter()
|
||||
.map(|att| {
|
||||
AttMaxCover::new(
|
||||
att.as_ref(),
|
||||
state,
|
||||
reward_cache,
|
||||
total_active_balance,
|
||||
&self.spec,
|
||||
)
|
||||
.ok_or(BeaconChainError::BlockRewardAttestationError)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// Update the attestation rewards for each previous attestation included.
|
||||
// This is O(n^2) in the number of attestations n.
|
||||
for i in 0..per_attestation_rewards.len() {
|
||||
let (updated, to_update) = per_attestation_rewards.split_at_mut(i + 1);
|
||||
let latest_att = &updated[i];
|
||||
|
||||
for att in to_update {
|
||||
att.update_covering_set(latest_att.intermediate(), latest_att.covering_set());
|
||||
}
|
||||
}
|
||||
|
||||
let mut prev_epoch_total = 0;
|
||||
let mut curr_epoch_total = 0;
|
||||
|
||||
for cover in &per_attestation_rewards {
|
||||
if cover.att.data.slot.epoch(T::EthSpec::slots_per_epoch()) == state.current_epoch() {
|
||||
curr_epoch_total += cover.score() as u64;
|
||||
} else {
|
||||
prev_epoch_total += cover.score() as u64;
|
||||
}
|
||||
}
|
||||
|
||||
let attestation_total = prev_epoch_total + curr_epoch_total;
|
||||
|
||||
// Drop the covers.
|
||||
let per_attestation_rewards = per_attestation_rewards
|
||||
.into_iter()
|
||||
.map(|cover| {
|
||||
// Divide each reward numerator by the denominator. This can lead to the total being
|
||||
// less than the sum of the individual rewards due to the fact that integer division
|
||||
// does not distribute over addition.
|
||||
let mut rewards = cover.fresh_validators_rewards;
|
||||
rewards
|
||||
.values_mut()
|
||||
.for_each(|reward| *reward /= PROPOSER_REWARD_DENOMINATOR);
|
||||
rewards
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Add the attestation data if desired.
|
||||
let attestations = if include_attestations {
|
||||
block
|
||||
.body()
|
||||
.attestations()
|
||||
.map(|a| a.data().clone())
|
||||
.collect()
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let attestation_rewards = AttestationRewards {
|
||||
total: attestation_total,
|
||||
prev_epoch_total,
|
||||
curr_epoch_total,
|
||||
per_attestation_rewards,
|
||||
attestations,
|
||||
};
|
||||
|
||||
// Sync committee rewards.
|
||||
let sync_committee_rewards = if let Ok(sync_aggregate) = block.body().sync_aggregate() {
|
||||
let (_, proposer_reward_per_bit) = compute_sync_aggregate_rewards(state, &self.spec)
|
||||
.map_err(|_| BeaconChainError::BlockRewardSyncError)?;
|
||||
sync_aggregate.sync_committee_bits.num_set_bits() as u64 * proposer_reward_per_bit
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
// Total, metadata
|
||||
let total = attestation_total + sync_committee_rewards;
|
||||
|
||||
let meta = BlockRewardMeta {
|
||||
slot: block.slot(),
|
||||
parent_slot: state.latest_block_header().slot,
|
||||
proposer_index: block.proposer_index(),
|
||||
graffiti: block.body().graffiti().as_utf8_lossy(),
|
||||
};
|
||||
|
||||
Ok(BlockReward {
|
||||
total,
|
||||
block_root,
|
||||
meta,
|
||||
attestation_rewards,
|
||||
sync_committee_rewards,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1571,24 +1571,6 @@ impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
|
||||
|
||||
metrics::stop_timer(committee_timer);
|
||||
|
||||
/*
|
||||
* If we have block reward listeners, compute the block reward and push it to the
|
||||
* event handler.
|
||||
*/
|
||||
if let Some(ref event_handler) = chain.event_handler
|
||||
&& event_handler.has_block_reward_subscribers()
|
||||
{
|
||||
let mut reward_cache = Default::default();
|
||||
let block_reward = chain.compute_block_reward(
|
||||
block.message(),
|
||||
block_root,
|
||||
&state,
|
||||
&mut reward_cache,
|
||||
true,
|
||||
)?;
|
||||
event_handler.register(EventKind::BlockReward(block_reward));
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform `per_block_processing` on the block and state, returning early if the block is
|
||||
* invalid.
|
||||
|
||||
@@ -21,7 +21,6 @@ pub struct ServerSentEventHandler<E: EthSpec> {
|
||||
late_head: Sender<EventKind<E>>,
|
||||
light_client_finality_update_tx: Sender<EventKind<E>>,
|
||||
light_client_optimistic_update_tx: Sender<EventKind<E>>,
|
||||
block_reward_tx: Sender<EventKind<E>>,
|
||||
proposer_slashing_tx: Sender<EventKind<E>>,
|
||||
attester_slashing_tx: Sender<EventKind<E>>,
|
||||
bls_to_execution_change_tx: Sender<EventKind<E>>,
|
||||
@@ -48,7 +47,6 @@ impl<E: EthSpec> ServerSentEventHandler<E> {
|
||||
let (late_head, _) = broadcast::channel(capacity);
|
||||
let (light_client_finality_update_tx, _) = broadcast::channel(capacity);
|
||||
let (light_client_optimistic_update_tx, _) = broadcast::channel(capacity);
|
||||
let (block_reward_tx, _) = broadcast::channel(capacity);
|
||||
let (proposer_slashing_tx, _) = broadcast::channel(capacity);
|
||||
let (attester_slashing_tx, _) = broadcast::channel(capacity);
|
||||
let (bls_to_execution_change_tx, _) = broadcast::channel(capacity);
|
||||
@@ -69,7 +67,6 @@ impl<E: EthSpec> ServerSentEventHandler<E> {
|
||||
late_head,
|
||||
light_client_finality_update_tx,
|
||||
light_client_optimistic_update_tx,
|
||||
block_reward_tx,
|
||||
proposer_slashing_tx,
|
||||
attester_slashing_tx,
|
||||
bls_to_execution_change_tx,
|
||||
@@ -142,10 +139,6 @@ impl<E: EthSpec> ServerSentEventHandler<E> {
|
||||
.light_client_optimistic_update_tx
|
||||
.send(kind)
|
||||
.map(|count| log_count("light client optimistic update", count)),
|
||||
EventKind::BlockReward(_) => self
|
||||
.block_reward_tx
|
||||
.send(kind)
|
||||
.map(|count| log_count("block reward", count)),
|
||||
EventKind::ProposerSlashing(_) => self
|
||||
.proposer_slashing_tx
|
||||
.send(kind)
|
||||
@@ -224,10 +217,6 @@ impl<E: EthSpec> ServerSentEventHandler<E> {
|
||||
self.light_client_optimistic_update_tx.subscribe()
|
||||
}
|
||||
|
||||
pub fn subscribe_block_reward(&self) -> Receiver<EventKind<E>> {
|
||||
self.block_reward_tx.subscribe()
|
||||
}
|
||||
|
||||
pub fn subscribe_attester_slashing(&self) -> Receiver<EventKind<E>> {
|
||||
self.attester_slashing_tx.subscribe()
|
||||
}
|
||||
@@ -292,10 +281,6 @@ impl<E: EthSpec> ServerSentEventHandler<E> {
|
||||
self.late_head.receiver_count() > 0
|
||||
}
|
||||
|
||||
pub fn has_block_reward_subscribers(&self) -> bool {
|
||||
self.block_reward_tx.receiver_count() > 0
|
||||
}
|
||||
|
||||
pub fn has_proposer_slashing_subscribers(&self) -> bool {
|
||||
self.proposer_slashing_tx.receiver_count() > 0
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ mod beacon_snapshot;
|
||||
pub mod bellatrix_readiness;
|
||||
pub mod blob_verification;
|
||||
mod block_production;
|
||||
pub mod block_reward;
|
||||
mod block_times_cache;
|
||||
mod block_verification;
|
||||
pub mod block_verification_types;
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes, WhenSlotSkipped};
|
||||
use eth2::lighthouse::{BlockReward, BlockRewardsQuery};
|
||||
use lru::LruCache;
|
||||
use state_processing::BlockReplayer;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::sync::Arc;
|
||||
use tracing::{debug, warn};
|
||||
use types::block::BlindedBeaconBlock;
|
||||
use types::new_non_zero_usize;
|
||||
use warp_utils::reject::{beacon_state_error, custom_bad_request, unhandled_error};
|
||||
|
||||
const STATE_CACHE_SIZE: NonZeroUsize = new_non_zero_usize(2);
|
||||
|
||||
/// Fetch block rewards for blocks from the canonical chain.
|
||||
pub fn get_block_rewards<T: BeaconChainTypes>(
|
||||
query: BlockRewardsQuery,
|
||||
chain: Arc<BeaconChain<T>>,
|
||||
) -> Result<Vec<BlockReward>, warp::Rejection> {
|
||||
let start_slot = query.start_slot;
|
||||
let end_slot = query.end_slot;
|
||||
let prior_slot = start_slot - 1;
|
||||
|
||||
if start_slot > end_slot || start_slot == 0 {
|
||||
return Err(custom_bad_request(format!(
|
||||
"invalid start and end: {}, {}",
|
||||
start_slot, end_slot
|
||||
)));
|
||||
}
|
||||
|
||||
let end_block_root = chain
|
||||
.block_root_at_slot(end_slot, WhenSlotSkipped::Prev)
|
||||
.map_err(unhandled_error)?
|
||||
.ok_or_else(|| custom_bad_request(format!("block at end slot {} unknown", end_slot)))?;
|
||||
|
||||
let blocks = chain
|
||||
.store
|
||||
.load_blocks_to_replay(start_slot, end_slot, end_block_root)
|
||||
.map_err(|e| unhandled_error(BeaconChainError::from(e)))?;
|
||||
|
||||
let state_root = chain
|
||||
.state_root_at_slot(prior_slot)
|
||||
.map_err(unhandled_error)?
|
||||
.ok_or_else(|| custom_bad_request(format!("prior state at slot {} unknown", prior_slot)))?;
|
||||
|
||||
// This branch is reached from the HTTP API. We assume the user wants
|
||||
// to cache states so that future calls are faster.
|
||||
let mut state = chain
|
||||
.get_state(&state_root, Some(prior_slot), true)
|
||||
.and_then(|maybe_state| maybe_state.ok_or(BeaconChainError::MissingBeaconState(state_root)))
|
||||
.map_err(unhandled_error)?;
|
||||
|
||||
state
|
||||
.build_caches(&chain.spec)
|
||||
.map_err(beacon_state_error)?;
|
||||
|
||||
let mut reward_cache = Default::default();
|
||||
let mut block_rewards = Vec::with_capacity(blocks.len());
|
||||
|
||||
let block_replayer = BlockReplayer::new(state, &chain.spec)
|
||||
.pre_block_hook(Box::new(|state, block| {
|
||||
state.build_all_committee_caches(&chain.spec)?;
|
||||
|
||||
// Compute block reward.
|
||||
let block_reward = chain.compute_block_reward(
|
||||
block.message(),
|
||||
block.canonical_root(),
|
||||
state,
|
||||
&mut reward_cache,
|
||||
query.include_attestations,
|
||||
)?;
|
||||
block_rewards.push(block_reward);
|
||||
Ok(())
|
||||
}))
|
||||
.state_root_iter(
|
||||
chain
|
||||
.forwards_iter_state_roots_until(prior_slot, end_slot)
|
||||
.map_err(unhandled_error)?,
|
||||
)
|
||||
.no_signature_verification()
|
||||
.minimal_block_root_verification()
|
||||
.apply_blocks(blocks, None)
|
||||
.map_err(unhandled_error)?;
|
||||
|
||||
if block_replayer.state_root_miss() {
|
||||
warn!(%start_slot, %end_slot, "Block reward state root miss");
|
||||
}
|
||||
|
||||
drop(block_replayer);
|
||||
|
||||
Ok(block_rewards)
|
||||
}
|
||||
|
||||
/// Compute block rewards for blocks passed in as input.
|
||||
pub fn compute_block_rewards<T: BeaconChainTypes>(
|
||||
blocks: Vec<BlindedBeaconBlock<T::EthSpec>>,
|
||||
chain: Arc<BeaconChain<T>>,
|
||||
) -> Result<Vec<BlockReward>, warp::Rejection> {
|
||||
let mut block_rewards = Vec::with_capacity(blocks.len());
|
||||
let mut state_cache = LruCache::new(STATE_CACHE_SIZE);
|
||||
let mut reward_cache = Default::default();
|
||||
|
||||
for block in blocks {
|
||||
let parent_root = block.parent_root();
|
||||
|
||||
// Check LRU cache for a constructed state from a previous iteration.
|
||||
let state = if let Some(state) = state_cache.get(&(parent_root, block.slot())) {
|
||||
debug!(
|
||||
?parent_root,
|
||||
slot = %block.slot(),
|
||||
"Re-using cached state for block rewards"
|
||||
);
|
||||
state
|
||||
} else {
|
||||
debug!(
|
||||
?parent_root,
|
||||
slot = %block.slot(),
|
||||
"Fetching state for block rewards"
|
||||
);
|
||||
let parent_block = chain
|
||||
.get_blinded_block(&parent_root)
|
||||
.map_err(unhandled_error)?
|
||||
.ok_or_else(|| {
|
||||
custom_bad_request(format!(
|
||||
"parent block not known or not canonical: {:?}",
|
||||
parent_root
|
||||
))
|
||||
})?;
|
||||
|
||||
// This branch is reached from the HTTP API. We assume the user wants
|
||||
// to cache states so that future calls are faster.
|
||||
let parent_state = chain
|
||||
.get_state(&parent_block.state_root(), Some(parent_block.slot()), true)
|
||||
.map_err(unhandled_error)?
|
||||
.ok_or_else(|| {
|
||||
custom_bad_request(format!(
|
||||
"no state known for parent block: {:?}",
|
||||
parent_root
|
||||
))
|
||||
})?;
|
||||
|
||||
let block_replayer = BlockReplayer::new(parent_state, &chain.spec)
|
||||
.no_signature_verification()
|
||||
.state_root_iter([Ok((parent_block.state_root(), parent_block.slot()))].into_iter())
|
||||
.minimal_block_root_verification()
|
||||
.apply_blocks(vec![], Some(block.slot()))
|
||||
.map_err(unhandled_error::<BeaconChainError>)?;
|
||||
|
||||
if block_replayer.state_root_miss() {
|
||||
warn!(
|
||||
parent_slot = %parent_block.slot(),
|
||||
slot = %block.slot(),
|
||||
"Block reward state root miss"
|
||||
);
|
||||
}
|
||||
|
||||
let mut state = block_replayer.into_state();
|
||||
state
|
||||
.build_all_committee_caches(&chain.spec)
|
||||
.map_err(beacon_state_error)?;
|
||||
|
||||
state_cache.get_or_insert((parent_root, block.slot()), || state)
|
||||
};
|
||||
|
||||
// Compute block reward.
|
||||
let block_reward = chain
|
||||
.compute_block_reward(
|
||||
block.to_ref(),
|
||||
block.canonical_root(),
|
||||
state,
|
||||
&mut reward_cache,
|
||||
true,
|
||||
)
|
||||
.map_err(unhandled_error)?;
|
||||
block_rewards.push(block_reward);
|
||||
}
|
||||
|
||||
Ok(block_rewards)
|
||||
}
|
||||
@@ -12,7 +12,6 @@ mod attester_duties;
|
||||
mod beacon;
|
||||
mod block_id;
|
||||
mod block_packing_efficiency;
|
||||
mod block_rewards;
|
||||
mod build_block_contents;
|
||||
mod builder_states;
|
||||
mod custody;
|
||||
@@ -3066,34 +3065,6 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
},
|
||||
);
|
||||
|
||||
// GET lighthouse/analysis/block_rewards
|
||||
let get_lighthouse_block_rewards = warp::path("lighthouse")
|
||||
.and(warp::path("analysis"))
|
||||
.and(warp::path("block_rewards"))
|
||||
.and(warp::query::<eth2::lighthouse::BlockRewardsQuery>())
|
||||
.and(warp::path::end())
|
||||
.and(task_spawner_filter.clone())
|
||||
.and(chain_filter.clone())
|
||||
.then(|query, task_spawner: TaskSpawner<T::EthSpec>, chain| {
|
||||
task_spawner.blocking_json_task(Priority::P1, move || {
|
||||
block_rewards::get_block_rewards(query, chain)
|
||||
})
|
||||
});
|
||||
|
||||
// POST lighthouse/analysis/block_rewards
|
||||
let post_lighthouse_block_rewards = warp::path("lighthouse")
|
||||
.and(warp::path("analysis"))
|
||||
.and(warp::path("block_rewards"))
|
||||
.and(warp_utils::json::json())
|
||||
.and(warp::path::end())
|
||||
.and(task_spawner_filter.clone())
|
||||
.and(chain_filter.clone())
|
||||
.then(|blocks, task_spawner: TaskSpawner<T::EthSpec>, chain| {
|
||||
task_spawner.blocking_json_task(Priority::P1, move || {
|
||||
block_rewards::compute_block_rewards(blocks, chain)
|
||||
})
|
||||
});
|
||||
|
||||
// GET lighthouse/analysis/attestation_performance/{index}
|
||||
let get_lighthouse_attestation_performance = warp::path("lighthouse")
|
||||
.and(warp::path("analysis"))
|
||||
@@ -3184,9 +3155,6 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
api_types::EventTopic::LightClientOptimisticUpdate => {
|
||||
event_handler.subscribe_light_client_optimistic_update()
|
||||
}
|
||||
api_types::EventTopic::BlockReward => {
|
||||
event_handler.subscribe_block_reward()
|
||||
}
|
||||
api_types::EventTopic::AttesterSlashing => {
|
||||
event_handler.subscribe_attester_slashing()
|
||||
}
|
||||
@@ -3363,7 +3331,6 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
.uor(get_lighthouse_staking)
|
||||
.uor(get_lighthouse_database_info)
|
||||
.uor(get_lighthouse_custody_info)
|
||||
.uor(get_lighthouse_block_rewards)
|
||||
.uor(get_lighthouse_attestation_performance)
|
||||
.uor(get_beacon_light_client_optimistic_update)
|
||||
.uor(get_beacon_light_client_finality_update)
|
||||
@@ -3414,7 +3381,6 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
.uor(post_validator_liveness_epoch)
|
||||
.uor(post_lighthouse_liveness)
|
||||
.uor(post_lighthouse_database_reconstruct)
|
||||
.uor(post_lighthouse_block_rewards)
|
||||
.uor(post_lighthouse_ui_validator_metrics)
|
||||
.uor(post_lighthouse_ui_validator_info)
|
||||
.uor(post_lighthouse_finalize)
|
||||
|
||||
Reference in New Issue
Block a user