Skip to content

Commit ab0f7f2

Browse files
committed
All previous changes squashed
Don't return an error from fork choice Fix more tests Add test Fix beacon processor test Improve test Fix block import Rebuild from finalized state if `get_head` fails Rebuild from finalized state if `get_head` fails Revert changes to `ForkChoice` Add failing test Revert "Rebuild from finalized state if `get_head` fails" This reverts commit 17cf507. Add `set_all_blocks_to_optimistic` Remove code fragment Fix tests
1 parent 947ad9f commit ab0f7f2

File tree

15 files changed

+362
-165
lines changed

15 files changed

+362
-165
lines changed

beacon_node/beacon_chain/src/beacon_chain.rs

Lines changed: 29 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2791,32 +2791,38 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
27912791
if !payload_verification_status.is_optimistic()
27922792
&& block.slot() + EARLY_ATTESTER_CACHE_HISTORIC_SLOTS >= current_slot
27932793
{
2794-
let new_head_root = fork_choice
2795-
.get_head(current_slot, &self.spec)
2796-
.map_err(BeaconChainError::from)?;
2797-
2798-
if new_head_root == block_root {
2799-
if let Some(proto_block) = fork_choice.get_block(&block_root) {
2800-
if let Err(e) = self.early_attester_cache.add_head_block(
2801-
block_root,
2802-
signed_block.clone(),
2803-
proto_block,
2804-
&state,
2805-
&self.spec,
2806-
) {
2794+
match fork_choice.get_head(current_slot, &self.spec) {
2795+
// This block became the head, add it to the early attester cache.
2796+
Ok(new_head_root) if new_head_root == block_root => {
2797+
if let Some(proto_block) = fork_choice.get_block(&block_root) {
2798+
if let Err(e) = self.early_attester_cache.add_head_block(
2799+
block_root,
2800+
signed_block.clone(),
2801+
proto_block,
2802+
&state,
2803+
&self.spec,
2804+
) {
2805+
warn!(
2806+
self.log,
2807+
"Early attester cache insert failed";
2808+
"error" => ?e
2809+
);
2810+
}
2811+
} else {
28072812
warn!(
28082813
self.log,
2809-
"Early attester cache insert failed";
2810-
"error" => ?e
2814+
"Early attester block missing";
2815+
"block_root" => ?block_root
28112816
);
28122817
}
2813-
} else {
2814-
warn!(
2815-
self.log,
2816-
"Early attester block missing";
2817-
"block_root" => ?block_root
2818-
);
28192818
}
2819+
// This block did not become the head, nothing to do.
2820+
Ok(_) => (),
2821+
Err(e) => error!(
2822+
self.log,
2823+
"Failed to compute head during block import";
2824+
"error" => ?e
2825+
),
28202826
}
28212827
}
28222828

@@ -3594,16 +3600,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
35943600

35953601
// Run fork choice since it's possible that the payload invalidation might result in a new
35963602
// head.
3597-
//
3598-
// Don't return early though, since invalidating the justified checkpoint might cause an
3599-
// error here.
3600-
if let Err(e) = self.recompute_head_at_current_slot().await {
3601-
crit!(
3602-
self.log,
3603-
"Failed to run fork choice routine";
3604-
"error" => ?e,
3605-
);
3606-
}
3603+
self.recompute_head_at_current_slot().await;
36073604

36083605
// Obtain the justified root from fork choice.
36093606
//
@@ -4248,14 +4245,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
42484245
}
42494246

42504247
// Run fork choice and signal to any waiting task that it has completed.
4251-
if let Err(e) = self.recompute_head_at_current_slot().await {
4252-
error!(
4253-
self.log,
4254-
"Fork choice error at slot start";
4255-
"error" => ?e,
4256-
"slot" => slot,
4257-
);
4258-
}
4248+
self.recompute_head_at_current_slot().await;
42594249

42604250
// Send the notification regardless of fork choice success, this is a "best effort"
42614251
// notification and we don't want block production to hit the timeout in case of error.

beacon_node/beacon_chain/src/canonical_head.rs

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -434,9 +434,15 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
434434
/// Execute the fork choice algorithm and enthrone the result as the canonical head.
435435
///
436436
/// This method replaces the old `BeaconChain::fork_choice` method.
437-
pub async fn recompute_head_at_current_slot(self: &Arc<Self>) -> Result<(), Error> {
438-
let current_slot = self.slot()?;
439-
self.recompute_head_at_slot(current_slot).await
437+
pub async fn recompute_head_at_current_slot(self: &Arc<Self>) {
438+
match self.slot() {
439+
Ok(current_slot) => self.recompute_head_at_slot(current_slot).await,
440+
Err(e) => error!(
441+
self.log,
442+
"No slot when recomputing head";
443+
"error" => ?e
444+
),
445+
}
440446
}
441447

442448
/// Execute the fork choice algorithm and enthrone the result as the canonical head.
@@ -445,7 +451,13 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
445451
/// different slot to the wall-clock can be useful for pushing fork choice into the next slot
446452
/// *just* before the start of the slot. This ensures that block production can use the correct
447453
/// head value without being delayed.
448-
pub async fn recompute_head_at_slot(self: &Arc<Self>, current_slot: Slot) -> Result<(), Error> {
454+
///
455+
/// This function purposefully does *not* return a `Result`. It's possible for fork choice to
456+
/// fail to update if there is only one viable head and it has an invalid execution payload. In
457+
/// such a case it's critical that the `BeaconChain` keeps importing blocks so that the
458+
/// situation can be rectified. We avoid returning an error here so that calling functions
459+
/// can't abort block import because an error is returned here.
460+
pub async fn recompute_head_at_slot(self: &Arc<Self>, current_slot: Slot) {
449461
metrics::inc_counter(&metrics::FORK_CHOICE_REQUESTS);
450462
let _timer = metrics::start_timer(&metrics::FORK_CHOICE_TIMES);
451463

@@ -455,23 +467,22 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
455467
move || chain.recompute_head_at_slot_internal(current_slot),
456468
"recompute_head_internal",
457469
)
458-
.await?
470+
.await
459471
{
460472
// Fork choice returned successfully and did not need to update the EL.
461-
Ok(None) => Ok(()),
473+
Ok(Ok(None)) => (),
462474
// Fork choice returned successfully and needed to update the EL. It has returned a
463475
// join-handle from when it spawned some async tasks. We should await those tasks.
464-
Ok(Some(join_handle)) => match join_handle.await {
476+
Ok(Ok(Some(join_handle))) => match join_handle.await {
465477
// The async task completed successfully.
466-
Ok(Some(())) => Ok(()),
478+
Ok(Some(())) => (),
467479
// The async task did not complete successfully since the runtime is shutting down.
468480
Ok(None) => {
469481
debug!(
470482
self.log,
471483
"Did not update EL fork choice";
472484
"info" => "shutting down"
473485
);
474-
Err(Error::RuntimeShutdown)
475486
}
476487
// The async task did not complete successfully, tokio returned an error.
477488
Err(e) => {
@@ -480,13 +491,24 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
480491
"Did not update EL fork choice";
481492
"error" => ?e
482493
);
483-
Err(Error::TokioJoin(e))
484494
}
485495
},
486496
// There was an error recomputing the head.
487-
Err(e) => {
497+
Ok(Err(e)) => {
488498
metrics::inc_counter(&metrics::FORK_CHOICE_ERRORS);
489-
Err(e)
499+
error!(
500+
self.log,
501+
"Error whist recomputing head";
502+
"error" => ?e
503+
);
504+
}
505+
// There was an error spawning the task.
506+
Err(e) => {
507+
error!(
508+
self.log,
509+
"Failed to spawn recompute head task";
510+
"error" => ?e
511+
);
490512
}
491513
}
492514
}

beacon_node/beacon_chain/src/state_advance_timer.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,7 @@ async fn state_advance_timer<T: BeaconChainTypes>(
220220
return;
221221
}
222222

223-
if let Err(e) = beacon_chain.recompute_head_at_slot(next_slot).await {
224-
warn!(
225-
log,
226-
"Error updating fork choice for next slot";
227-
"error" => ?e,
228-
"slot" => next_slot,
229-
);
230-
}
223+
beacon_chain.recompute_head_at_slot(next_slot).await;
231224

232225
// Use a blocking task to avoid blocking the core executor whilst waiting for locks
233226
// in `ForkChoiceSignalTx`.

beacon_node/beacon_chain/src/test_utils.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,20 @@ impl<E: EthSpec> Builder<EphemeralHarnessType<E>> {
211211
self.store = Some(store);
212212
self.store_mutator(Box::new(mutator))
213213
}
214+
215+
/// Disk store, resume.
216+
pub fn resumed_ephemeral_store(
217+
mut self,
218+
store: Arc<HotColdDB<E, MemoryStore<E>, MemoryStore<E>>>,
219+
) -> Self {
220+
let mutator = move |builder: BeaconChainBuilder<_>| {
221+
builder
222+
.resume_from_db()
223+
.expect("should resume from database")
224+
};
225+
self.store = Some(store);
226+
self.store_mutator(Box::new(mutator))
227+
}
214228
}
215229

216230
impl<E: EthSpec> Builder<DiskHarnessType<E>> {
@@ -1376,7 +1390,7 @@ where
13761390
.process_block(Arc::new(block), CountUnrealized::True)
13771391
.await?
13781392
.into();
1379-
self.chain.recompute_head_at_current_slot().await?;
1393+
self.chain.recompute_head_at_current_slot().await;
13801394
Ok(block_hash)
13811395
}
13821396

@@ -1389,7 +1403,7 @@ where
13891403
.process_block(Arc::new(block), CountUnrealized::True)
13901404
.await?
13911405
.into();
1392-
self.chain.recompute_head_at_current_slot().await?;
1406+
self.chain.recompute_head_at_current_slot().await;
13931407
Ok(block_hash)
13941408
}
13951409

beacon_node/beacon_chain/tests/block_verification.rs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,7 @@ async fn chain_segment_full_segment() {
160160
.into_block_error()
161161
.expect("should import chain segment");
162162

163-
harness
164-
.chain
165-
.recompute_head_at_current_slot()
166-
.await
167-
.expect("should run fork choice");
163+
harness.chain.recompute_head_at_current_slot().await;
168164

169165
assert_eq!(
170166
harness.head_block_root(),
@@ -194,11 +190,7 @@ async fn chain_segment_varying_chunk_size() {
194190
.unwrap_or_else(|_| panic!("should import chain segment of len {}", chunk_size));
195191
}
196192

197-
harness
198-
.chain
199-
.recompute_head_at_current_slot()
200-
.await
201-
.expect("should run fork choice");
193+
harness.chain.recompute_head_at_current_slot().await;
202194

203195
assert_eq!(
204196
harness.head_block_root(),
@@ -729,11 +721,7 @@ async fn block_gossip_verification() {
729721
}
730722

731723
// Recompute the head to ensure we cache the latest view of fork choice.
732-
harness
733-
.chain
734-
.recompute_head_at_current_slot()
735-
.await
736-
.unwrap();
724+
harness.chain.recompute_head_at_current_slot().await;
737725

738726
/*
739727
* This test ensures that:

0 commit comments

Comments
 (0)