mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-03 00:31:50 +00:00
Proposer duties backwards compat (#8335)
The beacon API spec wasn't updated to use the Fulu definition of `dependent_root` for the proposer duties endpoint. No other client updated their logic, so to retain backwards compatibility the decision has been made to continue using the block root at the end of epoch `N - 1`, and introduce a new v2 endpoint down the track to use the correct dependent root. Eth R&D discussion: https://discord.com/channels/595666850260713488/598292067260825641/1433036715848765562 Change the behaviour of the v1 endpoint back to using the last slot of `N - 1` rather than the last slot of `N - 2`. This introduces the possibility of dependent root false positives (the root can change without changing the shuffling), but causes the least compatibility issues with other clients. Co-Authored-By: Michael Sproul <michael@sigmaprime.io>
This commit is contained in:
@@ -166,10 +166,17 @@ impl BeaconProposerCache {
|
||||
}
|
||||
|
||||
/// Compute the proposer duties using the head state without cache.
|
||||
///
|
||||
/// Return:
|
||||
/// - Proposer indices.
|
||||
/// - True dependent root.
|
||||
/// - Legacy dependent root (last block of epoch `N - 1`).
|
||||
/// - Head execution status.
|
||||
/// - Fork at `request_epoch`.
|
||||
pub fn compute_proposer_duties_from_head<T: BeaconChainTypes>(
|
||||
request_epoch: Epoch,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<(Vec<usize>, Hash256, ExecutionStatus, Fork), BeaconChainError> {
|
||||
) -> Result<(Vec<usize>, Hash256, Hash256, ExecutionStatus, Fork), BeaconChainError> {
|
||||
// Atomically collect information about the head whilst holding the canonical head `Arc` as
|
||||
// short as possible.
|
||||
let (mut state, head_state_root, head_block_root) = {
|
||||
@@ -203,11 +210,23 @@ pub fn compute_proposer_duties_from_head<T: BeaconChainTypes>(
|
||||
.proposer_shuffling_decision_root_at_epoch(request_epoch, head_block_root, &chain.spec)
|
||||
.map_err(BeaconChainError::from)?;
|
||||
|
||||
// This is only required because the V1 proposer duties endpoint spec wasn't updated for Fulu. We
|
||||
// can delete this once the V1 endpoint is deprecated at the Glamsterdam fork.
|
||||
let legacy_dependent_root = state
|
||||
.legacy_proposer_shuffling_decision_root_at_epoch(request_epoch, head_block_root)
|
||||
.map_err(BeaconChainError::from)?;
|
||||
|
||||
// Use fork_at_epoch rather than the state's fork, because post-Fulu we may not have advanced
|
||||
// the state completely into the new epoch.
|
||||
let fork = chain.spec.fork_at_epoch(request_epoch);
|
||||
|
||||
Ok((indices, dependent_root, execution_status, fork))
|
||||
Ok((
|
||||
indices,
|
||||
dependent_root,
|
||||
legacy_dependent_root,
|
||||
execution_status,
|
||||
fork,
|
||||
))
|
||||
}
|
||||
|
||||
/// If required, advance `state` to the epoch required to determine proposer indices in `target_epoch`.
|
||||
|
||||
@@ -1561,7 +1561,7 @@ async fn proposer_duties_from_head_fulu() {
|
||||
|
||||
// Compute the proposer duties at the next epoch from the head
|
||||
let next_epoch = head_state.next_epoch().unwrap();
|
||||
let (_indices, dependent_root, _, fork) =
|
||||
let (_indices, dependent_root, legacy_dependent_root, _, fork) =
|
||||
compute_proposer_duties_from_head(next_epoch, &harness.chain).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -1570,6 +1570,8 @@ async fn proposer_duties_from_head_fulu() {
|
||||
.proposer_shuffling_decision_root_at_epoch(next_epoch, head_block_root.into(), spec)
|
||||
.unwrap()
|
||||
);
|
||||
assert_ne!(dependent_root, legacy_dependent_root);
|
||||
assert_eq!(legacy_dependent_root, Hash256::from(head_block_root));
|
||||
assert_eq!(fork, head_state.fork());
|
||||
}
|
||||
|
||||
@@ -1617,7 +1619,7 @@ async fn proposer_lookahead_gloas_fork_epoch() {
|
||||
assert_eq!(head_state.current_epoch(), gloas_fork_epoch - 1);
|
||||
|
||||
// Compute the proposer duties at the fork epoch from the head.
|
||||
let (indices, dependent_root, _, fork) =
|
||||
let (indices, dependent_root, legacy_dependent_root, _, fork) =
|
||||
compute_proposer_duties_from_head(gloas_fork_epoch, &harness.chain).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -1630,6 +1632,7 @@ async fn proposer_lookahead_gloas_fork_epoch() {
|
||||
)
|
||||
.unwrap()
|
||||
);
|
||||
assert_ne!(dependent_root, legacy_dependent_root);
|
||||
assert_ne!(fork, head_state.fork());
|
||||
assert_eq!(fork, spec.fork_at_epoch(gloas_fork_epoch));
|
||||
|
||||
@@ -1639,7 +1642,7 @@ async fn proposer_lookahead_gloas_fork_epoch() {
|
||||
.add_attested_blocks_at_slots(head_state, head_state_root, &gloas_slots, &all_validators)
|
||||
.await;
|
||||
|
||||
let (no_lookahead_indices, no_lookahead_dependent_root, _, no_lookahead_fork) =
|
||||
let (no_lookahead_indices, no_lookahead_dependent_root, _, _, no_lookahead_fork) =
|
||||
compute_proposer_duties_from_head(gloas_fork_epoch, &harness.chain).unwrap();
|
||||
|
||||
assert_eq!(no_lookahead_indices, indices);
|
||||
|
||||
Reference in New Issue
Block a user