Skip to content

Commit ee69e14

Browse files
authored
Add is_parent_strong proposer re-org check (#5417)
* initial fork choice additions * add helper fns * add is_parent_strong * Merge branch 'unstable' of https://github.com/sigp/lighthouse into add_is_parent_strong_check * disabling proposer reorg should set parent_threshold to u64 max * add new flag, is_parent_strong check in override fcu params * cherry-pick changes * Merge branch 'unstable' of https://github.com/sigp/lighthouse into add_is_parent_strong_check * cleanup * fmt * Minor review tweaks
1 parent 053525e commit ee69e14

File tree

16 files changed

+181
-53
lines changed

16 files changed

+181
-53
lines changed

beacon_node/beacon_chain/src/beacon_chain.rs

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4262,7 +4262,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
42624262
head_slot: Slot,
42634263
canonical_head: Hash256,
42644264
) -> Option<BlockProductionPreState<T::EthSpec>> {
4265-
let re_org_threshold = self.config.re_org_threshold?;
4265+
let re_org_head_threshold = self.config.re_org_head_threshold?;
4266+
let re_org_parent_threshold = self.config.re_org_parent_threshold?;
42664267

42674268
if self.spec.proposer_score_boost.is_none() {
42684269
warn!(
@@ -4319,7 +4320,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
43194320
.get_proposer_head(
43204321
slot,
43214322
canonical_head,
4322-
re_org_threshold,
4323+
re_org_head_threshold,
4324+
re_org_parent_threshold,
43234325
&self.config.re_org_disallowed_offsets,
43244326
self.config.re_org_max_epochs_since_finalization,
43254327
)
@@ -4373,7 +4375,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
43734375
"weak_head" => ?canonical_head,
43744376
"parent" => ?re_org_parent_block,
43754377
"head_weight" => proposer_head.head_node.weight,
4376-
"threshold_weight" => proposer_head.re_org_weight_threshold
4378+
"threshold_weight" => proposer_head.re_org_head_weight_threshold
43774379
);
43784380

43794381
Some(pre_state)
@@ -4593,9 +4595,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
45934595
let _timer = metrics::start_timer(&metrics::FORK_CHOICE_OVERRIDE_FCU_TIMES);
45944596

45954597
// Never override if proposer re-orgs are disabled.
4596-
let re_org_threshold = self
4598+
let re_org_head_threshold = self
45974599
.config
4598-
.re_org_threshold
4600+
.re_org_head_threshold
4601+
.ok_or(DoNotReOrg::ReOrgsDisabled)?;
4602+
4603+
let re_org_parent_threshold = self
4604+
.config
4605+
.re_org_parent_threshold
45994606
.ok_or(DoNotReOrg::ReOrgsDisabled)?;
46004607

46014608
let head_block_root = canonical_forkchoice_params.head_root;
@@ -4606,7 +4613,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
46064613
.fork_choice_read_lock()
46074614
.get_preliminary_proposer_head(
46084615
head_block_root,
4609-
re_org_threshold,
4616+
re_org_head_threshold,
4617+
re_org_parent_threshold,
46104618
&self.config.re_org_disallowed_offsets,
46114619
self.config.re_org_max_epochs_since_finalization,
46124620
)
@@ -4674,16 +4682,27 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
46744682
}
46754683

46764684
// If the current slot is already equal to the proposal slot (or we are in the tail end of
4677-
// the prior slot), then check the actual weight of the head against the re-org threshold.
4678-
let head_weak = if fork_choice_slot == re_org_block_slot {
4679-
info.head_node.weight < info.re_org_weight_threshold
4685+
// the prior slot), then check the actual weight of the head against the head re-org threshold
4686+
// and the actual weight of the parent against the parent re-org threshold.
4687+
let (head_weak, parent_strong) = if fork_choice_slot == re_org_block_slot {
4688+
(
4689+
info.head_node.weight < info.re_org_head_weight_threshold,
4690+
info.parent_node.weight > info.re_org_parent_weight_threshold,
4691+
)
46804692
} else {
4681-
true
4693+
(true, true)
46824694
};
46834695
if !head_weak {
46844696
return Err(DoNotReOrg::HeadNotWeak {
46854697
head_weight: info.head_node.weight,
4686-
re_org_weight_threshold: info.re_org_weight_threshold,
4698+
re_org_head_weight_threshold: info.re_org_head_weight_threshold,
4699+
}
4700+
.into());
4701+
}
4702+
if !parent_strong {
4703+
return Err(DoNotReOrg::ParentNotStrong {
4704+
parent_weight: info.parent_node.weight,
4705+
re_org_parent_weight_threshold: info.re_org_parent_weight_threshold,
46874706
}
46884707
.into());
46894708
}

beacon_node/beacon_chain/src/builder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,8 @@ where
172172
}
173173

174174
/// Sets the proposer re-org threshold.
175-
pub fn proposer_re_org_threshold(mut self, threshold: Option<ReOrgThreshold>) -> Self {
176-
self.chain_config.re_org_threshold = threshold;
175+
pub fn proposer_re_org_head_threshold(mut self, threshold: Option<ReOrgThreshold>) -> Self {
176+
self.chain_config.re_org_head_threshold = threshold;
177177
self
178178
}
179179

beacon_node/beacon_chain/src/chain_config.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use serde::{Deserialize, Serialize};
33
use std::time::Duration;
44
use types::{Checkpoint, Epoch};
55

6-
pub const DEFAULT_RE_ORG_THRESHOLD: ReOrgThreshold = ReOrgThreshold(20);
6+
pub const DEFAULT_RE_ORG_HEAD_THRESHOLD: ReOrgThreshold = ReOrgThreshold(20);
7+
pub const DEFAULT_RE_ORG_PARENT_THRESHOLD: ReOrgThreshold = ReOrgThreshold(160);
78
pub const DEFAULT_RE_ORG_MAX_EPOCHS_SINCE_FINALIZATION: Epoch = Epoch::new(2);
89
/// Default to 1/12th of the slot, which is 1 second on mainnet.
910
pub const DEFAULT_RE_ORG_CUTOFF_DENOMINATOR: u32 = 12;
@@ -31,8 +32,10 @@ pub struct ChainConfig {
3132
pub enable_lock_timeouts: bool,
3233
/// The max size of a message that can be sent over the network.
3334
pub max_network_size: usize,
34-
/// Maximum percentage of committee weight at which to attempt re-orging the canonical head.
35-
pub re_org_threshold: Option<ReOrgThreshold>,
35+
/// Maximum percentage of the head committee weight at which to attempt re-orging the canonical head.
36+
pub re_org_head_threshold: Option<ReOrgThreshold>,
37+
/// Minimum percentage of the parent committee weight at which to attempt re-orging the canonical head.
38+
pub re_org_parent_threshold: Option<ReOrgThreshold>,
3639
/// Maximum number of epochs since finalization for attempting a proposer re-org.
3740
pub re_org_max_epochs_since_finalization: Epoch,
3841
/// Maximum delay after the start of the slot at which to propose a reorging block.
@@ -95,7 +98,8 @@ impl Default for ChainConfig {
9598
reconstruct_historic_states: false,
9699
enable_lock_timeouts: true,
97100
max_network_size: 10 * 1_048_576, // 10M
98-
re_org_threshold: Some(DEFAULT_RE_ORG_THRESHOLD),
101+
re_org_head_threshold: Some(DEFAULT_RE_ORG_HEAD_THRESHOLD),
102+
re_org_parent_threshold: Some(DEFAULT_RE_ORG_PARENT_THRESHOLD),
99103
re_org_max_epochs_since_finalization: DEFAULT_RE_ORG_MAX_EPOCHS_SINCE_FINALIZATION,
100104
re_org_cutoff_millis: None,
101105
re_org_disallowed_offsets: DisallowedReOrgOffsets::default(),

beacon_node/http_api/tests/interactive_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ pub async fn proposer_boost_re_org_test(
419419
None,
420420
Some(Box::new(move |builder| {
421421
builder
422-
.proposer_re_org_threshold(Some(ReOrgThreshold(re_org_threshold)))
422+
.proposer_re_org_head_threshold(Some(ReOrgThreshold(re_org_threshold)))
423423
.proposer_re_org_max_epochs_since_finalization(Epoch::new(
424424
max_epochs_since_finalization,
425425
))

beacon_node/src/cli.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1040,10 +1040,18 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
10401040
Arg::with_name("proposer-reorg-threshold")
10411041
.long("proposer-reorg-threshold")
10421042
.value_name("PERCENT")
1043-
.help("Percentage of vote weight below which to attempt a proposer reorg. \
1043+
.help("Percentage of head vote weight below which to attempt a proposer reorg. \
10441044
Default: 20%")
10451045
.conflicts_with("disable-proposer-reorgs")
10461046
)
1047+
.arg(
1048+
Arg::with_name("proposer-reorg-parent-threshold")
1049+
.long("proposer-reorg-parent-threshold")
1050+
.value_name("PERCENT")
1051+
.help("Percentage of parent vote weight above which to attempt a proposer reorg. \
1052+
Default: 160%")
1053+
.conflicts_with("disable-proposer-reorgs")
1054+
)
10471055
.arg(
10481056
Arg::with_name("proposer-reorg-epochs-since-finalization")
10491057
.long("proposer-reorg-epochs-since-finalization")

beacon_node/src/config.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use beacon_chain::chain_config::{
22
DisallowedReOrgOffsets, ReOrgThreshold, DEFAULT_PREPARE_PAYLOAD_LOOKAHEAD_FACTOR,
3-
DEFAULT_RE_ORG_MAX_EPOCHS_SINCE_FINALIZATION, DEFAULT_RE_ORG_THRESHOLD,
3+
DEFAULT_RE_ORG_HEAD_THRESHOLD, DEFAULT_RE_ORG_MAX_EPOCHS_SINCE_FINALIZATION,
4+
DEFAULT_RE_ORG_PARENT_THRESHOLD,
45
};
56
use beacon_chain::TrustedSetup;
67
use clap::ArgMatches;
@@ -749,19 +750,26 @@ pub fn get_config<E: EthSpec>(
749750
}
750751

751752
if cli_args.is_present("disable-proposer-reorgs") {
752-
client_config.chain.re_org_threshold = None;
753+
client_config.chain.re_org_head_threshold = None;
754+
client_config.chain.re_org_parent_threshold = None;
753755
} else {
754-
client_config.chain.re_org_threshold = Some(
756+
client_config.chain.re_org_head_threshold = Some(
755757
clap_utils::parse_optional(cli_args, "proposer-reorg-threshold")?
756758
.map(ReOrgThreshold)
757-
.unwrap_or(DEFAULT_RE_ORG_THRESHOLD),
759+
.unwrap_or(DEFAULT_RE_ORG_HEAD_THRESHOLD),
758760
);
759761
client_config.chain.re_org_max_epochs_since_finalization =
760762
clap_utils::parse_optional(cli_args, "proposer-reorg-epochs-since-finalization")?
761763
.unwrap_or(DEFAULT_RE_ORG_MAX_EPOCHS_SINCE_FINALIZATION);
762764
client_config.chain.re_org_cutoff_millis =
763765
clap_utils::parse_optional(cli_args, "proposer-reorg-cutoff")?;
764766

767+
client_config.chain.re_org_parent_threshold = Some(
768+
clap_utils::parse_optional(cli_args, "proposer-reorg-parent-threshold")?
769+
.map(ReOrgThreshold)
770+
.unwrap_or(DEFAULT_RE_ORG_PARENT_THRESHOLD),
771+
);
772+
765773
if let Some(disallowed_offsets_str) =
766774
clap_utils::parse_optional::<String>(cli_args, "proposer-reorg-disallowed-offsets")?
767775
{

book/src/help_bn.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,11 @@ OPTIONS:
383383
--proposer-reorg-epochs-since-finalization <EPOCHS>
384384
Maximum number of epochs since finalization at which proposer reorgs are allowed. Default: 2
385385
386+
--proposer-reorg-parent-threshold <PERCENT>
387+
Percentage of parent vote weight above which to attempt a proposer reorg. Default: 160%
388+
386389
--proposer-reorg-threshold <PERCENT>
387-
Percentage of vote weight below which to attempt a proposer reorg. Default: 20%
390+
Percentage of head vote weight below which to attempt a proposer reorg. Default: 20%
388391
389392
--prune-blobs <BOOLEAN>
390393
Prune blobs from Lighthouse's database when they are older than the data data availability boundary relative

common/eth2_network_config/built_in_network_configs/gnosis/config.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ CHURN_LIMIT_QUOTIENT: 4096
8181
# ---------------------------------------------------------------
8282
# 40%
8383
PROPOSER_SCORE_BOOST: 40
84+
# 20%
85+
REORG_HEAD_WEIGHT_THRESHOLD: 20
86+
# 160%
87+
REORG_PARENT_WEIGHT_THRESHOLD: 160
88+
# `2` epochs
89+
REORG_MAX_EPOCHS_SINCE_FINALIZATION: 2
8490

8591
# Deposit contract
8692
# ---------------------------------------------------------------

common/eth2_network_config/built_in_network_configs/holesky/config.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: 8
7171
# ---------------------------------------------------------------
7272
# 40%
7373
PROPOSER_SCORE_BOOST: 40
74+
# 20%
75+
REORG_HEAD_WEIGHT_THRESHOLD: 20
76+
# 160%
77+
REORG_PARENT_WEIGHT_THRESHOLD: 160
78+
# `2` epochs
79+
REORG_MAX_EPOCHS_SINCE_FINALIZATION: 2
7480

7581
# Deposit contract
7682
# ---------------------------------------------------------------

common/eth2_network_config/built_in_network_configs/prater/config.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: 8
7878
# ---------------------------------------------------------------
7979
# 40%
8080
PROPOSER_SCORE_BOOST: 40
81+
# 20%
82+
REORG_HEAD_WEIGHT_THRESHOLD: 20
83+
# 160%
84+
REORG_PARENT_WEIGHT_THRESHOLD: 160
85+
# `2` epochs
86+
REORG_MAX_EPOCHS_SINCE_FINALIZATION: 2
8187

8288
# Deposit contract
8389
# ---------------------------------------------------------------

0 commit comments

Comments
 (0)