Merge remote-tracking branch 'origin/unstable' into tree-states

This commit is contained in:
Michael Sproul
2023-02-08 11:17:43 +11:00
39 changed files with 1463 additions and 77 deletions

View File

@@ -15,7 +15,9 @@ mod database;
mod metrics;
mod proposer_duties;
mod publish_blocks;
mod standard_block_rewards;
mod state_id;
mod sync_committee_rewards;
mod sync_committees;
mod ui;
mod validator_inclusion;
@@ -1719,6 +1721,114 @@ pub fn serve<T: BeaconChainTypes>(
},
);
let beacon_rewards_path = eth_v1
.and(warp::path("beacon"))
.and(warp::path("rewards"))
.and(chain_filter.clone());
// GET beacon/rewards/blocks/{block_id}
let get_beacon_rewards_blocks = beacon_rewards_path
.clone()
.and(warp::path("blocks"))
.and(block_id_or_err)
.and(warp::path::end())
.and_then(|chain: Arc<BeaconChain<T>>, block_id: BlockId| {
blocking_json_task(move || {
let (rewards, execution_optimistic) =
standard_block_rewards::compute_beacon_block_rewards(chain, block_id)?;
Ok(rewards)
.map(api_types::GenericResponse::from)
.map(|resp| resp.add_execution_optimistic(execution_optimistic))
})
});
/*
* beacon/rewards
*/
let beacon_rewards_path = eth_v1
.and(warp::path("beacon"))
.and(warp::path("rewards"))
.and(chain_filter.clone());
// POST beacon/rewards/attestations/{epoch}
let post_beacon_rewards_attestations = beacon_rewards_path
.clone()
.and(warp::path("attestations"))
.and(warp::path::param::<Epoch>())
.and(warp::path::end())
.and(warp::body::json())
.and(log_filter.clone())
.and_then(
|chain: Arc<BeaconChain<T>>,
epoch: Epoch,
validators: Vec<ValidatorId>,
log: Logger| {
blocking_json_task(move || {
let attestation_rewards = chain
.compute_attestation_rewards(epoch, validators, log)
.map_err(|e| match e {
BeaconChainError::MissingBeaconState(root) => {
warp_utils::reject::custom_not_found(format!(
"missing state {root:?}",
))
}
BeaconChainError::NoStateForSlot(slot) => {
warp_utils::reject::custom_not_found(format!(
"missing state at slot {slot}"
))
}
BeaconChainError::BeaconStateError(
BeaconStateError::UnknownValidator(validator_index),
) => warp_utils::reject::custom_bad_request(format!(
"validator is unknown: {validator_index}"
)),
BeaconChainError::ValidatorPubkeyUnknown(pubkey) => {
warp_utils::reject::custom_bad_request(format!(
"validator pubkey is unknown: {pubkey:?}"
))
}
e => warp_utils::reject::custom_server_error(format!(
"unexpected error: {:?}",
e
)),
})?;
let execution_optimistic =
chain.is_optimistic_or_invalid_head().unwrap_or_default();
Ok(attestation_rewards)
.map(api_types::GenericResponse::from)
.map(|resp| resp.add_execution_optimistic(execution_optimistic))
})
},
);
// POST beacon/rewards/sync_committee/{block_id}
let post_beacon_rewards_sync_committee = beacon_rewards_path
.clone()
.and(warp::path("sync_committee"))
.and(block_id_or_err)
.and(warp::path::end())
.and(warp::body::json())
.and(log_filter.clone())
.and_then(
|chain: Arc<BeaconChain<T>>,
block_id: BlockId,
validators: Vec<ValidatorId>,
log: Logger| {
blocking_json_task(move || {
let (rewards, execution_optimistic) =
sync_committee_rewards::compute_sync_committee_rewards(
chain, block_id, validators, log,
)?;
Ok(rewards)
.map(api_types::GenericResponse::from)
.map(|resp| resp.add_execution_optimistic(execution_optimistic))
})
},
);
/*
* config
*/
@@ -3365,6 +3475,7 @@ pub fn serve<T: BeaconChainTypes>(
.or(get_beacon_pool_proposer_slashings.boxed())
.or(get_beacon_pool_voluntary_exits.boxed())
.or(get_beacon_deposit_snapshot.boxed())
.or(get_beacon_rewards_blocks.boxed())
.or(get_config_fork_schedule.boxed())
.or(get_config_spec.boxed())
.or(get_config_deposit_contract.boxed())
@@ -3416,6 +3527,8 @@ pub fn serve<T: BeaconChainTypes>(
.or(post_beacon_pool_proposer_slashings.boxed())
.or(post_beacon_pool_voluntary_exits.boxed())
.or(post_beacon_pool_sync_committees.boxed())
.or(post_beacon_rewards_attestations.boxed())
.or(post_beacon_rewards_sync_committee.boxed())
.or(post_validator_duties_attester.boxed())
.or(post_validator_duties_sync.boxed())
.or(post_validator_aggregate_and_proofs.boxed())

View File

@@ -0,0 +1,27 @@
use crate::sync_committee_rewards::get_state_before_applying_block;
use crate::BlockId;
use crate::ExecutionOptimistic;
use beacon_chain::{BeaconChain, BeaconChainTypes};
use eth2::lighthouse::StandardBlockReward;
use std::sync::Arc;
use warp_utils::reject::beacon_chain_error;
//// The difference between block_rewards and beacon_block_rewards is the later returns block
//// reward format that satisfies beacon-api specs
pub fn compute_beacon_block_rewards<T: BeaconChainTypes>(
chain: Arc<BeaconChain<T>>,
block_id: BlockId,
) -> Result<(StandardBlockReward, ExecutionOptimistic), warp::Rejection> {
let (block, execution_optimistic) = block_id.blinded_block(&chain)?;
let block_ref = block.message();
let block_root = block.canonical_root();
let mut state = get_state_before_applying_block(chain.clone(), &block)?;
let rewards = chain
.compute_beacon_block_reward(block_ref, block_root, &mut state)
.map_err(beacon_chain_error)?;
Ok((rewards, execution_optimistic))
}

View File

@@ -0,0 +1,77 @@
use crate::{BlockId, ExecutionOptimistic};
use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes};
use eth2::lighthouse::SyncCommitteeReward;
use eth2::types::ValidatorId;
use slog::{debug, Logger};
use state_processing::BlockReplayer;
use std::sync::Arc;
use types::{BeaconState, SignedBlindedBeaconBlock};
use warp_utils::reject::{beacon_chain_error, custom_not_found};
pub fn compute_sync_committee_rewards<T: BeaconChainTypes>(
chain: Arc<BeaconChain<T>>,
block_id: BlockId,
validators: Vec<ValidatorId>,
log: Logger,
) -> Result<(Option<Vec<SyncCommitteeReward>>, ExecutionOptimistic), warp::Rejection> {
let (block, execution_optimistic) = block_id.blinded_block(&chain)?;
let mut state = get_state_before_applying_block(chain.clone(), &block)?;
let reward_payload = chain
.compute_sync_committee_rewards(block.message(), &mut state)
.map_err(beacon_chain_error)?;
let data = if reward_payload.is_empty() {
debug!(log, "compute_sync_committee_rewards returned empty");
None
} else if validators.is_empty() {
Some(reward_payload)
} else {
Some(
reward_payload
.into_iter()
.filter(|reward| {
validators.iter().any(|validator| match validator {
ValidatorId::Index(i) => reward.validator_index == *i,
ValidatorId::PublicKey(pubkey) => match state.get_validator_index(pubkey) {
Ok(Some(i)) => reward.validator_index == i as u64,
_ => false,
},
})
})
.collect::<Vec<SyncCommitteeReward>>(),
)
};
Ok((data, execution_optimistic))
}
pub fn get_state_before_applying_block<T: BeaconChainTypes>(
chain: Arc<BeaconChain<T>>,
block: &SignedBlindedBeaconBlock<T::EthSpec>,
) -> Result<BeaconState<T::EthSpec>, warp::reject::Rejection> {
let parent_block: SignedBlindedBeaconBlock<T::EthSpec> = chain
.get_blinded_block(&block.parent_root())
.and_then(|maybe_block| {
maybe_block.ok_or_else(|| BeaconChainError::MissingBeaconBlock(block.parent_root()))
})
.map_err(|e| custom_not_found(format!("Parent block is not available! {:?}", e)))?;
let parent_state = chain
.get_state(&parent_block.state_root(), Some(parent_block.slot()))
.and_then(|maybe_state| {
maybe_state
.ok_or_else(|| BeaconChainError::MissingBeaconState(parent_block.state_root()))
})
.map_err(|e| custom_not_found(format!("Parent state is not available! {:?}", e)))?;
let 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)?;
Ok(replayer.into_state())
}