Skip to content

Commit df0cbe3

Browse files
authored
Merge of #8335
2 parents 25832e5 + 258c13b commit df0cbe3

File tree

6 files changed

+64
-16
lines changed

6 files changed

+64
-16
lines changed

beacon_node/beacon_chain/src/beacon_proposer_cache.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,17 @@ impl BeaconProposerCache {
166166
}
167167

168168
/// Compute the proposer duties using the head state without cache.
169+
///
170+
/// Return:
171+
/// - Proposer indices.
172+
/// - True dependent root.
173+
/// - Legacy dependent root (last block of epoch `N - 1`).
174+
/// - Head execution status.
175+
/// - Fork at `request_epoch`.
169176
pub fn compute_proposer_duties_from_head<T: BeaconChainTypes>(
170177
request_epoch: Epoch,
171178
chain: &BeaconChain<T>,
172-
) -> Result<(Vec<usize>, Hash256, ExecutionStatus, Fork), BeaconChainError> {
179+
) -> Result<(Vec<usize>, Hash256, Hash256, ExecutionStatus, Fork), BeaconChainError> {
173180
// Atomically collect information about the head whilst holding the canonical head `Arc` as
174181
// short as possible.
175182
let (mut state, head_state_root, head_block_root) = {
@@ -203,11 +210,23 @@ pub fn compute_proposer_duties_from_head<T: BeaconChainTypes>(
203210
.proposer_shuffling_decision_root_at_epoch(request_epoch, head_block_root, &chain.spec)
204211
.map_err(BeaconChainError::from)?;
205212

213+
// This is only required because the V1 proposer duties endpoint spec wasn't updated for Fulu. We
214+
// can delete this once the V1 endpoint is deprecated at the Glamsterdam fork.
215+
let legacy_dependent_root = state
216+
.legacy_proposer_shuffling_decision_root_at_epoch(request_epoch, head_block_root)
217+
.map_err(BeaconChainError::from)?;
218+
206219
// Use fork_at_epoch rather than the state's fork, because post-Fulu we may not have advanced
207220
// the state completely into the new epoch.
208221
let fork = chain.spec.fork_at_epoch(request_epoch);
209222

210-
Ok((indices, dependent_root, execution_status, fork))
223+
Ok((
224+
indices,
225+
dependent_root,
226+
legacy_dependent_root,
227+
execution_status,
228+
fork,
229+
))
211230
}
212231

213232
/// If required, advance `state` to the epoch required to determine proposer indices in `target_epoch`.

beacon_node/beacon_chain/tests/store_tests.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,7 +1561,7 @@ async fn proposer_duties_from_head_fulu() {
15611561

15621562
// Compute the proposer duties at the next epoch from the head
15631563
let next_epoch = head_state.next_epoch().unwrap();
1564-
let (_indices, dependent_root, _, fork) =
1564+
let (_indices, dependent_root, legacy_dependent_root, _, fork) =
15651565
compute_proposer_duties_from_head(next_epoch, &harness.chain).unwrap();
15661566

15671567
assert_eq!(
@@ -1570,6 +1570,8 @@ async fn proposer_duties_from_head_fulu() {
15701570
.proposer_shuffling_decision_root_at_epoch(next_epoch, head_block_root.into(), spec)
15711571
.unwrap()
15721572
);
1573+
assert_ne!(dependent_root, legacy_dependent_root);
1574+
assert_eq!(legacy_dependent_root, Hash256::from(head_block_root));
15731575
assert_eq!(fork, head_state.fork());
15741576
}
15751577

@@ -1617,7 +1619,7 @@ async fn proposer_lookahead_gloas_fork_epoch() {
16171619
assert_eq!(head_state.current_epoch(), gloas_fork_epoch - 1);
16181620

16191621
// Compute the proposer duties at the fork epoch from the head.
1620-
let (indices, dependent_root, _, fork) =
1622+
let (indices, dependent_root, legacy_dependent_root, _, fork) =
16211623
compute_proposer_duties_from_head(gloas_fork_epoch, &harness.chain).unwrap();
16221624

16231625
assert_eq!(
@@ -1630,6 +1632,7 @@ async fn proposer_lookahead_gloas_fork_epoch() {
16301632
)
16311633
.unwrap()
16321634
);
1635+
assert_ne!(dependent_root, legacy_dependent_root);
16331636
assert_ne!(fork, head_state.fork());
16341637
assert_eq!(fork, spec.fork_at_epoch(gloas_fork_epoch));
16351638

@@ -1639,7 +1642,7 @@ async fn proposer_lookahead_gloas_fork_epoch() {
16391642
.add_attested_blocks_at_slots(head_state, head_state_root, &gloas_slots, &all_validators)
16401643
.await;
16411644

1642-
let (no_lookahead_indices, no_lookahead_dependent_root, _, no_lookahead_fork) =
1645+
let (no_lookahead_indices, no_lookahead_dependent_root, _, _, no_lookahead_fork) =
16431646
compute_proposer_duties_from_head(gloas_fork_epoch, &harness.chain).unwrap();
16441647

16451648
assert_eq!(no_lookahead_indices, indices);

beacon_node/http_api/src/proposer_duties.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,13 @@ pub fn proposer_duties<T: BeaconChainTypes>(
6060
.safe_add(1)
6161
.map_err(warp_utils::reject::arith_error)?
6262
{
63-
let (proposers, dependent_root, execution_status, _fork) =
63+
let (proposers, _dependent_root, legacy_dependent_root, execution_status, _fork) =
6464
compute_proposer_duties_from_head(request_epoch, chain)
6565
.map_err(warp_utils::reject::unhandled_error)?;
6666
convert_to_api_response(
6767
chain,
6868
request_epoch,
69-
dependent_root,
69+
legacy_dependent_root,
7070
execution_status.is_optimistic_or_invalid(),
7171
proposers,
7272
)
@@ -116,6 +116,11 @@ fn try_proposer_duties_from_cache<T: BeaconChainTypes>(
116116
.beacon_state
117117
.proposer_shuffling_decision_root_at_epoch(request_epoch, head_block_root, &chain.spec)
118118
.map_err(warp_utils::reject::beacon_state_error)?;
119+
let legacy_dependent_root = head
120+
.snapshot
121+
.beacon_state
122+
.legacy_proposer_shuffling_decision_root_at_epoch(request_epoch, head_block_root)
123+
.map_err(warp_utils::reject::beacon_state_error)?;
119124
let execution_optimistic = chain
120125
.is_optimistic_or_invalid_head_block(head_block)
121126
.map_err(warp_utils::reject::unhandled_error)?;
@@ -129,7 +134,7 @@ fn try_proposer_duties_from_cache<T: BeaconChainTypes>(
129134
convert_to_api_response(
130135
chain,
131136
request_epoch,
132-
head_decision_root,
137+
legacy_dependent_root,
133138
execution_optimistic,
134139
indices.to_vec(),
135140
)
@@ -151,7 +156,7 @@ fn compute_and_cache_proposer_duties<T: BeaconChainTypes>(
151156
current_epoch: Epoch,
152157
chain: &BeaconChain<T>,
153158
) -> Result<ApiDuties, warp::reject::Rejection> {
154-
let (indices, dependent_root, execution_status, fork) =
159+
let (indices, dependent_root, legacy_dependent_root, execution_status, fork) =
155160
compute_proposer_duties_from_head(current_epoch, chain)
156161
.map_err(warp_utils::reject::unhandled_error)?;
157162

@@ -166,7 +171,7 @@ fn compute_and_cache_proposer_duties<T: BeaconChainTypes>(
166171
convert_to_api_response(
167172
chain,
168173
current_epoch,
169-
dependent_root,
174+
legacy_dependent_root,
170175
execution_status.is_optimistic_or_invalid(),
171176
indices,
172177
)
@@ -229,12 +234,18 @@ fn compute_historic_proposer_duties<T: BeaconChainTypes>(
229234

230235
// We can supply the genesis block root as the block root since we know that the only block that
231236
// decides its own root is the genesis block.
232-
let dependent_root = state
233-
.proposer_shuffling_decision_root(chain.genesis_block_root, &chain.spec)
237+
let legacy_dependent_root = state
238+
.legacy_proposer_shuffling_decision_root_at_epoch(epoch, chain.genesis_block_root)
234239
.map_err(BeaconChainError::from)
235240
.map_err(warp_utils::reject::unhandled_error)?;
236241

237-
convert_to_api_response(chain, epoch, dependent_root, execution_optimistic, indices)
242+
convert_to_api_response(
243+
chain,
244+
epoch,
245+
legacy_dependent_root,
246+
execution_optimistic,
247+
indices,
248+
)
238249
}
239250

240251
/// Converts the internal representation of proposer duties into one that is compatible with the

beacon_node/http_api/tests/interactive_tests.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,10 +1017,9 @@ async fn proposer_duties_with_gossip_tolerance() {
10171017
assert_eq!(
10181018
proposer_duties_tolerant_current_epoch.dependent_root,
10191019
head_state
1020-
.proposer_shuffling_decision_root_at_epoch(
1020+
.legacy_proposer_shuffling_decision_root_at_epoch(
10211021
tolerant_current_epoch,
10221022
head_block_root,
1023-
spec
10241023
)
10251024
.unwrap()
10261025
);

consensus/types/src/beacon_state.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,22 @@ impl<E: EthSpec> BeaconState<E> {
911911
}
912912
}
913913

914+
/// Returns the block root at the last slot of `epoch - 1`.
915+
///
916+
/// This can be deleted after Glamsterdam and the removal of the v1 proposer duties endpoint.
917+
pub fn legacy_proposer_shuffling_decision_root_at_epoch(
918+
&self,
919+
epoch: Epoch,
920+
head_block_root: Hash256,
921+
) -> Result<Hash256, Error> {
922+
let decision_slot = epoch.saturating_sub(1u64).end_slot(E::slots_per_epoch());
923+
if self.slot() <= decision_slot {
924+
Ok(head_block_root)
925+
} else {
926+
self.get_block_root(decision_slot).copied()
927+
}
928+
}
929+
914930
/// Returns the block root which decided the proposer shuffling for the current epoch. This root
915931
/// can be used to key this proposer shuffling.
916932
///

testing/ef_tests/src/cases/fork_choice.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -920,7 +920,7 @@ impl<E: EthSpec> Tester<E> {
920920
let cached_head = self.harness.chain.canonical_head.cached_head();
921921
let next_slot = cached_head.snapshot.beacon_block.slot() + 1;
922922
let next_slot_epoch = next_slot.epoch(E::slots_per_epoch());
923-
let (proposer_indices, decision_root, _, fork) =
923+
let (proposer_indices, decision_root, _, _, fork) =
924924
compute_proposer_duties_from_head(next_slot_epoch, &self.harness.chain).unwrap();
925925
let proposer_index = proposer_indices[next_slot.as_usize() % E::slots_per_epoch() as usize];
926926

0 commit comments

Comments
 (0)