mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-19 04:42:34 +00:00
Extend block reward APIs (#3290)
## Proposed Changes Add a new HTTP endpoint `POST /lighthouse/analysis/block_rewards` which takes a vec of `BeaconBlock`s as input and outputs the `BlockReward`s for them. Augment the `BlockReward` struct with the attestation data for attestations in the block, which simplifies access to this information from blockprint. Using attestation data I've been able to make blockprint up to 95% accurate across Prysm/Lighthouse/Teku/Nimbus. I hope to go even higher using a bunch of synthetic blocks produced for Prysm/Nimbus/Lodestar, which are underrepresented in the current training data.
This commit is contained in:
@@ -1,10 +1,17 @@
|
||||
use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes, WhenSlotSkipped};
|
||||
use eth2::lighthouse::{BlockReward, BlockRewardsQuery};
|
||||
use slog::{warn, Logger};
|
||||
use lru::LruCache;
|
||||
use slog::{debug, warn, Logger};
|
||||
use state_processing::BlockReplayer;
|
||||
use std::sync::Arc;
|
||||
use warp_utils::reject::{beacon_chain_error, beacon_state_error, custom_bad_request};
|
||||
use types::BeaconBlock;
|
||||
use warp_utils::reject::{
|
||||
beacon_chain_error, beacon_state_error, custom_bad_request, custom_server_error,
|
||||
};
|
||||
|
||||
const STATE_CACHE_SIZE: usize = 2;
|
||||
|
||||
/// Fetch block rewards for blocks from the canonical chain.
|
||||
pub fn get_block_rewards<T: BeaconChainTypes>(
|
||||
query: BlockRewardsQuery,
|
||||
chain: Arc<BeaconChain<T>>,
|
||||
@@ -50,8 +57,12 @@ pub fn get_block_rewards<T: BeaconChainTypes>(
|
||||
let block_replayer = BlockReplayer::new(state, &chain.spec)
|
||||
.pre_block_hook(Box::new(|state, block| {
|
||||
// Compute block reward.
|
||||
let block_reward =
|
||||
chain.compute_block_reward(block.message(), block.canonical_root(), state)?;
|
||||
let block_reward = chain.compute_block_reward(
|
||||
block.message(),
|
||||
block.canonical_root(),
|
||||
state,
|
||||
query.include_attestations,
|
||||
)?;
|
||||
block_rewards.push(block_reward);
|
||||
Ok(())
|
||||
}))
|
||||
@@ -78,3 +89,84 @@ pub fn get_block_rewards<T: BeaconChainTypes>(
|
||||
|
||||
Ok(block_rewards)
|
||||
}
|
||||
|
||||
/// Compute block rewards for blocks passed in as input.
|
||||
pub fn compute_block_rewards<T: BeaconChainTypes>(
|
||||
blocks: Vec<BeaconBlock<T::EthSpec>>,
|
||||
chain: Arc<BeaconChain<T>>,
|
||||
log: Logger,
|
||||
) -> Result<Vec<BlockReward>, warp::Rejection> {
|
||||
let mut block_rewards = Vec::with_capacity(blocks.len());
|
||||
let mut state_cache = LruCache::new(STATE_CACHE_SIZE);
|
||||
|
||||
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!(
|
||||
log,
|
||||
"Re-using cached state for block rewards";
|
||||
"parent_root" => ?parent_root,
|
||||
"slot" => block.slot(),
|
||||
);
|
||||
state
|
||||
} else {
|
||||
debug!(
|
||||
log,
|
||||
"Fetching state for block rewards";
|
||||
"parent_root" => ?parent_root,
|
||||
"slot" => block.slot()
|
||||
);
|
||||
let parent_block = chain
|
||||
.get_blinded_block(&parent_root)
|
||||
.map_err(beacon_chain_error)?
|
||||
.ok_or_else(|| {
|
||||
custom_bad_request(format!(
|
||||
"parent block not known or not canonical: {:?}",
|
||||
parent_root
|
||||
))
|
||||
})?;
|
||||
|
||||
let parent_state = chain
|
||||
.get_state(&parent_block.state_root(), Some(parent_block.slot()))
|
||||
.map_err(beacon_chain_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(beacon_chain_error)?;
|
||||
|
||||
if block_replayer.state_root_miss() {
|
||||
warn!(
|
||||
log,
|
||||
"Block reward state root miss";
|
||||
"parent_slot" => parent_block.slot(),
|
||||
"slot" => block.slot(),
|
||||
);
|
||||
}
|
||||
|
||||
state_cache
|
||||
.get_or_insert((parent_root, block.slot()), || block_replayer.into_state())
|
||||
.ok_or_else(|| {
|
||||
custom_server_error("LRU cache insert should always succeed".into())
|
||||
})?
|
||||
};
|
||||
|
||||
// Compute block reward.
|
||||
let block_reward = chain
|
||||
.compute_block_reward(block.to_ref(), block.canonical_root(), state, true)
|
||||
.map_err(beacon_chain_error)?;
|
||||
block_rewards.push(block_reward);
|
||||
}
|
||||
|
||||
Ok(block_rewards)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user