Skip to content

Commit 53c0151

Browse files
paulhaunerWoodpile37
authored andcommitted
Fork choice modifications and cleanup (sigp#3962)
NA - Implements ethereum/consensus-specs#3290 - Bumps `ef-tests` to [v1.3.0-rc.4](https://github.com/ethereum/consensus-spec-tests/releases/tag/v1.3.0-rc.4). The `CountRealizedFull` concept has been removed and the `--count-unrealized-full` and `--count-unrealized` BN flags now do nothing but log a `WARN` when used. This PR removes the `best_justified_checkpoint` from fork choice. This field is persisted on-disk and the correct way to go about this would be to make a DB migration to remove the field. However, in this PR I've simply stubbed out the value with a junk value. I've taken this approach because if we're going to do a DB migration I'd love to remove the `Option`s around the justified and finalized checkpoints on `ProtoNode` whilst we're at it. Those options were added in sigp#2822 which was included in Lighthouse v2.1.0. The options were only put there to handle the migration and they've been set to `Some` ever since v2.1.0. There's no reason to keep them as options anymore. I started adding the DB migration to this branch but I started to feel like I was bloating this rather critical PR with nice-to-haves. I've kept the partially-complete migration [over in my repo](https://github.com/paulhauner/lighthouse/tree/fc-pr-18-migration) so we can pick it up after this PR is merged.
1 parent b4884aa commit 53c0151

27 files changed

+215
-411
lines changed

beacon_node/beacon_chain/src/beacon_chain.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ use itertools::process_results;
7373
use itertools::Itertools;
7474
use operation_pool::{AttestationRef, OperationPool, PersistedOperationPool};
7575
use parking_lot::{Mutex, RwLock};
76-
use proto_array::{CountUnrealizedFull, DoNotReOrg, ProposerHeadError};
76+
use proto_array::{DoNotReOrg, ProposerHeadError};
7777
use safe_arith::SafeArith;
7878
use slasher::Slasher;
7979
use slog::{crit, debug, error, info, trace, warn, Logger};
@@ -472,7 +472,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
472472
pub fn load_fork_choice(
473473
store: BeaconStore<T>,
474474
reset_payload_statuses: ResetPayloadStatuses,
475-
count_unrealized_full: CountUnrealizedFull,
476475
spec: &ChainSpec,
477476
log: &Logger,
478477
) -> Result<Option<BeaconForkChoice<T>>, Error> {
@@ -489,7 +488,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
489488
persisted_fork_choice.fork_choice,
490489
reset_payload_statuses,
491490
fc_store,
492-
count_unrealized_full,
493491
spec,
494492
log,
495493
)?))
@@ -1893,7 +1891,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
18931891
self.slot()?,
18941892
verified.indexed_attestation(),
18951893
AttestationFromBlock::False,
1896-
&self.spec,
18971894
)
18981895
.map_err(Into::into)
18991896
}
@@ -2862,7 +2859,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
28622859
&state,
28632860
payload_verification_status,
28642861
&self.spec,
2865-
count_unrealized.and(self.config.count_unrealized.into()),
2862+
count_unrealized,
28662863
)
28672864
.map_err(|e| BlockError::BeaconChainError(e.into()))?;
28682865
}
@@ -3070,7 +3067,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
30703067
ResetPayloadStatuses::always_reset_conditionally(
30713068
self.config.always_reset_payload_statuses,
30723069
),
3073-
self.config.count_unrealized_full,
30743070
&self.store,
30753071
&self.spec,
30763072
&self.log,

beacon_node/beacon_chain/src/beacon_fork_choice_store.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ use types::{
2020
Hash256, Slot,
2121
};
2222

23+
/// Ensure this justified checkpoint has an epoch of 0 so that it is never
24+
/// greater than the justified checkpoint and enshrined as the actual justified
25+
/// checkpoint.
26+
const JUNK_BEST_JUSTIFIED_CHECKPOINT: Checkpoint = Checkpoint {
27+
epoch: Epoch::new(0),
28+
root: Hash256::repeat_byte(0),
29+
};
30+
2331
#[derive(Debug)]
2432
pub enum Error {
2533
UnableToReadSlot,
@@ -144,7 +152,6 @@ pub struct BeaconForkChoiceStore<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<
144152
finalized_checkpoint: Checkpoint,
145153
justified_checkpoint: Checkpoint,
146154
justified_balances: JustifiedBalances,
147-
best_justified_checkpoint: Checkpoint,
148155
unrealized_justified_checkpoint: Checkpoint,
149156
unrealized_finalized_checkpoint: Checkpoint,
150157
proposer_boost_root: Hash256,
@@ -194,7 +201,6 @@ where
194201
justified_checkpoint,
195202
justified_balances,
196203
finalized_checkpoint,
197-
best_justified_checkpoint: justified_checkpoint,
198204
unrealized_justified_checkpoint: justified_checkpoint,
199205
unrealized_finalized_checkpoint: finalized_checkpoint,
200206
proposer_boost_root: Hash256::zero(),
@@ -212,7 +218,7 @@ where
212218
finalized_checkpoint: self.finalized_checkpoint,
213219
justified_checkpoint: self.justified_checkpoint,
214220
justified_balances: self.justified_balances.effective_balances.clone(),
215-
best_justified_checkpoint: self.best_justified_checkpoint,
221+
best_justified_checkpoint: JUNK_BEST_JUSTIFIED_CHECKPOINT,
216222
unrealized_justified_checkpoint: self.unrealized_justified_checkpoint,
217223
unrealized_finalized_checkpoint: self.unrealized_finalized_checkpoint,
218224
proposer_boost_root: self.proposer_boost_root,
@@ -234,7 +240,6 @@ where
234240
finalized_checkpoint: persisted.finalized_checkpoint,
235241
justified_checkpoint: persisted.justified_checkpoint,
236242
justified_balances,
237-
best_justified_checkpoint: persisted.best_justified_checkpoint,
238243
unrealized_justified_checkpoint: persisted.unrealized_justified_checkpoint,
239244
unrealized_finalized_checkpoint: persisted.unrealized_finalized_checkpoint,
240245
proposer_boost_root: persisted.proposer_boost_root,
@@ -277,10 +282,6 @@ where
277282
&self.justified_balances
278283
}
279284

280-
fn best_justified_checkpoint(&self) -> &Checkpoint {
281-
&self.best_justified_checkpoint
282-
}
283-
284285
fn finalized_checkpoint(&self) -> &Checkpoint {
285286
&self.finalized_checkpoint
286287
}
@@ -333,10 +334,6 @@ where
333334
Ok(())
334335
}
335336

336-
fn set_best_justified_checkpoint(&mut self, checkpoint: Checkpoint) {
337-
self.best_justified_checkpoint = checkpoint
338-
}
339-
340337
fn set_unrealized_justified_checkpoint(&mut self, checkpoint: Checkpoint) {
341338
self.unrealized_justified_checkpoint = checkpoint;
342339
}

beacon_node/beacon_chain/src/builder.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::{
1919
};
2020
use eth1::Config as Eth1Config;
2121
use execution_layer::ExecutionLayer;
22-
use fork_choice::{ForkChoice, ResetPayloadStatuses};
22+
use fork_choice::{CountUnrealized, ForkChoice, ResetPayloadStatuses};
2323
use futures::channel::mpsc::Sender;
2424
use kzg::{Kzg, TrustedSetup};
2525
use operation_pool::{OperationPool, PersistedOperationPool};
@@ -269,7 +269,6 @@ where
269269
ResetPayloadStatuses::always_reset_conditionally(
270270
self.chain_config.always_reset_payload_statuses,
271271
),
272-
self.chain_config.count_unrealized_full,
273272
&self.spec,
274273
log,
275274
)
@@ -388,7 +387,6 @@ where
388387
&genesis.beacon_block,
389388
&genesis.beacon_state,
390389
current_slot,
391-
self.chain_config.count_unrealized_full,
392390
&self.spec,
393391
)
394392
.map_err(|e| format!("Unable to initialize ForkChoice: {:?}", e))?;
@@ -507,7 +505,6 @@ where
507505
&snapshot.beacon_block,
508506
&snapshot.beacon_state,
509507
current_slot,
510-
self.chain_config.count_unrealized_full,
511508
&self.spec,
512509
)
513510
.map_err(|e| format!("Unable to initialize ForkChoice: {:?}", e))?;
@@ -698,8 +695,7 @@ where
698695
store.clone(),
699696
Some(current_slot),
700697
&self.spec,
701-
self.chain_config.count_unrealized.into(),
702-
self.chain_config.count_unrealized_full,
698+
CountUnrealized::True,
703699
)?;
704700
}
705701

beacon_node/beacon_chain/src/canonical_head.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ use crate::{
4545
};
4646
use eth2::types::{EventKind, SseChainReorg, SseFinalizedCheckpoint, SseHead, SseLateHead};
4747
use fork_choice::{
48-
CountUnrealizedFull, ExecutionStatus, ForkChoiceView, ForkchoiceUpdateParameters, ProtoBlock,
49-
ResetPayloadStatuses,
48+
ExecutionStatus, ForkChoiceView, ForkchoiceUpdateParameters, ProtoBlock, ResetPayloadStatuses,
5049
};
5150
use itertools::process_results;
5251
use parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
@@ -285,19 +284,13 @@ impl<T: BeaconChainTypes> CanonicalHead<T> {
285284
// defensive programming.
286285
mut fork_choice_write_lock: RwLockWriteGuard<BeaconForkChoice<T>>,
287286
reset_payload_statuses: ResetPayloadStatuses,
288-
count_unrealized_full: CountUnrealizedFull,
289287
store: &BeaconStore<T>,
290288
spec: &ChainSpec,
291289
log: &Logger,
292290
) -> Result<(), Error> {
293-
let fork_choice = <BeaconChain<T>>::load_fork_choice(
294-
store.clone(),
295-
reset_payload_statuses,
296-
count_unrealized_full,
297-
spec,
298-
log,
299-
)?
300-
.ok_or(Error::MissingPersistedForkChoice)?;
291+
let fork_choice =
292+
<BeaconChain<T>>::load_fork_choice(store.clone(), reset_payload_statuses, spec, log)?
293+
.ok_or(Error::MissingPersistedForkChoice)?;
301294
let fork_choice_view = fork_choice.cached_fork_choice_view();
302295
let beacon_block_root = fork_choice_view.head_block_root;
303296
let beacon_block = store

beacon_node/beacon_chain/src/chain_config.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pub use proto_array::{CountUnrealizedFull, ReOrgThreshold};
1+
pub use proto_array::ReOrgThreshold;
22
use serde_derive::{Deserialize, Serialize};
33
use std::time::Duration;
44
use types::{Checkpoint, Epoch};
@@ -48,16 +48,11 @@ pub struct ChainConfig {
4848
pub builder_fallback_epochs_since_finalization: usize,
4949
/// Whether any chain health checks should be considered when deciding whether to use the builder API.
5050
pub builder_fallback_disable_checks: bool,
51-
/// When set to `true`, weigh the "unrealized" FFG progression when choosing a head in fork
52-
/// choice.
53-
pub count_unrealized: bool,
5451
/// When set to `true`, forget any valid/invalid/optimistic statuses in fork choice during start
5552
/// up.
5653
pub always_reset_payload_statuses: bool,
5754
/// Whether to apply paranoid checks to blocks proposed by this beacon node.
5855
pub paranoid_block_proposal: bool,
59-
/// Whether to strictly count unrealized justified votes.
60-
pub count_unrealized_full: CountUnrealizedFull,
6156
/// Optionally set timeout for calls to checkpoint sync endpoint.
6257
pub checkpoint_sync_url_timeout: u64,
6358
/// The offset before the start of a proposal slot at which payload attributes should be sent.
@@ -91,10 +86,8 @@ impl Default for ChainConfig {
9186
builder_fallback_skips_per_epoch: 8,
9287
builder_fallback_epochs_since_finalization: 3,
9388
builder_fallback_disable_checks: false,
94-
count_unrealized: true,
9589
always_reset_payload_statuses: false,
9690
paranoid_block_proposal: false,
97-
count_unrealized_full: CountUnrealizedFull::default(),
9891
checkpoint_sync_url_timeout: 60,
9992
prepare_payload_lookahead: Duration::from_secs(4),
10093
optimistic_finalized_sync: true,

beacon_node/beacon_chain/src/fork_revert.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::{BeaconForkChoiceStore, BeaconSnapshot};
22
use fork_choice::{CountUnrealized, ForkChoice, PayloadVerificationStatus};
33
use itertools::process_results;
4-
use proto_array::CountUnrealizedFull;
54
use slog::{info, warn, Logger};
65
use state_processing::state_advance::complete_state_advance;
76
use state_processing::{
@@ -102,7 +101,6 @@ pub fn reset_fork_choice_to_finalization<E: EthSpec, Hot: ItemStore<E>, Cold: It
102101
current_slot: Option<Slot>,
103102
spec: &ChainSpec,
104103
count_unrealized_config: CountUnrealized,
105-
count_unrealized_full_config: CountUnrealizedFull,
106104
) -> Result<ForkChoice<BeaconForkChoiceStore<E, Hot, Cold>, E>, String> {
107105
// Fetch finalized block.
108106
let finalized_checkpoint = head_state.finalized_checkpoint();
@@ -156,7 +154,6 @@ pub fn reset_fork_choice_to_finalization<E: EthSpec, Hot: ItemStore<E>, Cold: It
156154
&finalized_snapshot.beacon_block,
157155
&finalized_snapshot.beacon_state,
158156
current_slot,
159-
count_unrealized_full_config,
160157
spec,
161158
)
162159
.map_err(|e| format!("Unable to reset fork choice for revert: {:?}", e))?;

beacon_node/beacon_chain/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub use self::beacon_chain::{
5858
INVALID_JUSTIFIED_PAYLOAD_SHUTDOWN_REASON, MAXIMUM_GOSSIP_CLOCK_DISPARITY,
5959
};
6060
pub use self::beacon_snapshot::BeaconSnapshot;
61-
pub use self::chain_config::{ChainConfig, CountUnrealizedFull};
61+
pub use self::chain_config::ChainConfig;
6262
pub use self::errors::{BeaconChainError, BlockProductionError};
6363
pub use self::historical_blocks::HistoricalBlockError;
6464
pub use attestation_verification::Error as AttestationError;

beacon_node/beacon_chain/src/schema_change.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ mod migration_schema_v12;
33
mod migration_schema_v13;
44
mod migration_schema_v14;
55
mod migration_schema_v15;
6+
mod migration_schema_v16;
67

78
use crate::beacon_chain::{BeaconChainTypes, ETH1_CACHE_DB_KEY};
89
use crate::eth1_chain::SszEth1;
@@ -132,6 +133,14 @@ pub fn migrate_schema<T: BeaconChainTypes>(
132133
let ops = migration_schema_v15::downgrade_from_v15::<T>(db.clone(), log)?;
133134
db.store_schema_version_atomically(to, ops)
134135
}
136+
(SchemaVersion(15), SchemaVersion(16)) => {
137+
let ops = migration_schema_v16::upgrade_to_v16::<T>(db.clone(), log)?;
138+
db.store_schema_version_atomically(to, ops)
139+
}
140+
(SchemaVersion(16), SchemaVersion(15)) => {
141+
let ops = migration_schema_v16::downgrade_from_v16::<T>(db.clone(), log)?;
142+
db.store_schema_version_atomically(to, ops)
143+
}
135144
// Anything else is an error.
136145
(_, _) => Err(HotColdDBError::UnsupportedSchemaVersion {
137146
target_version: to,
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use crate::beacon_chain::{BeaconChainTypes, FORK_CHOICE_DB_KEY};
2+
use crate::persisted_fork_choice::PersistedForkChoiceV11;
3+
use slog::{debug, Logger};
4+
use std::sync::Arc;
5+
use store::{Error, HotColdDB, KeyValueStoreOp, StoreItem};
6+
7+
pub fn upgrade_to_v16<T: BeaconChainTypes>(
8+
db: Arc<HotColdDB<T::EthSpec, T::HotStore, T::ColdStore>>,
9+
log: Logger,
10+
) -> Result<Vec<KeyValueStoreOp>, Error> {
11+
drop_balances_cache::<T>(db, log)
12+
}
13+
14+
pub fn downgrade_from_v16<T: BeaconChainTypes>(
15+
db: Arc<HotColdDB<T::EthSpec, T::HotStore, T::ColdStore>>,
16+
log: Logger,
17+
) -> Result<Vec<KeyValueStoreOp>, Error> {
18+
drop_balances_cache::<T>(db, log)
19+
}
20+
21+
/// Drop the balances cache from the fork choice store.
22+
///
23+
/// There aren't any type-level changes in this schema migration, however the
24+
/// way that we compute the `JustifiedBalances` has changed due to:
25+
/// https://github.com/sigp/lighthouse/pull/3962
26+
pub fn drop_balances_cache<T: BeaconChainTypes>(
27+
db: Arc<HotColdDB<T::EthSpec, T::HotStore, T::ColdStore>>,
28+
log: Logger,
29+
) -> Result<Vec<KeyValueStoreOp>, Error> {
30+
let mut persisted_fork_choice = db
31+
.get_item::<PersistedForkChoiceV11>(&FORK_CHOICE_DB_KEY)?
32+
.ok_or_else(|| Error::SchemaMigrationError("fork choice missing from database".into()))?;
33+
34+
debug!(
35+
log,
36+
"Dropping fork choice balances cache";
37+
"item_count" => persisted_fork_choice.fork_choice_store.balances_cache.items.len()
38+
);
39+
40+
// Drop all items in the balances cache.
41+
persisted_fork_choice.fork_choice_store.balances_cache = <_>::default();
42+
43+
let kv_op = persisted_fork_choice.as_kv_store_op(FORK_CHOICE_DB_KEY);
44+
45+
Ok(vec![kv_op])
46+
}

beacon_node/beacon_chain/tests/tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ async fn unaggregated_attestations_added_to_fork_choice_some_none() {
500500
// Move forward a slot so all queued attestations can be processed.
501501
harness.advance_slot();
502502
fork_choice
503-
.update_time(harness.chain.slot().unwrap(), &harness.chain.spec)
503+
.update_time(harness.chain.slot().unwrap())
504504
.unwrap();
505505

506506
let validator_slots: Vec<(usize, Slot)> = (0..VALIDATOR_COUNT)
@@ -614,7 +614,7 @@ async fn unaggregated_attestations_added_to_fork_choice_all_updated() {
614614
// Move forward a slot so all queued attestations can be processed.
615615
harness.advance_slot();
616616
fork_choice
617-
.update_time(harness.chain.slot().unwrap(), &harness.chain.spec)
617+
.update_time(harness.chain.slot().unwrap())
618618
.unwrap();
619619

620620
let validators: Vec<usize> = (0..VALIDATOR_COUNT).collect();

0 commit comments

Comments
 (0)