Skip to content

Commit

Permalink
[consensus] remove non smart ancestor selection logic (MystenLabs#21238)
Browse files Browse the repository at this point in the history
## Description 

Smart ancestor selection logic is live on mainnet as of v1.42

---

## Release notes

Check each box that your changes affect. If none of the boxes relate to
your changes, release notes aren't required.

For each box you select, include information after the relevant heading
that describes the impact of your changes that a user might notice and
any actions they must take to implement updates.

- [ ] Protocol: 
- [ ] Nodes (Validators and Full nodes): 
- [ ] gRPC:
- [ ] JSON-RPC: 
- [ ] GraphQL: 
- [ ] CLI: 
- [ ] Rust SDK:
  • Loading branch information
arun-koshy authored Feb 14, 2025
1 parent c550e71 commit 8002b4c
Showing 1 changed file with 21 additions and 91 deletions.
112 changes: 21 additions & 91 deletions consensus/core/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,44 +440,29 @@ impl Core {
}

// Determine the ancestors to be included in proposal.
// Smart ancestor selection requires distributed scoring to be enabled.
let (ancestors, excluded_ancestors) = if self
.context
.protocol_config
.consensus_distributed_vote_scoring_strategy()
&& self
.context
.protocol_config
.consensus_smart_ancestor_selection()
{
let (ancestors, excluded_and_equivocating_ancestors) =
self.smart_ancestors_to_propose(clock_round, !force);

// If we did not find enough good ancestors to propose, continue to wait before proposing.
if ancestors.is_empty() {
assert!(
!force,
"Ancestors should have been returned if force is true!"
);
return None;
}
let (ancestors, excluded_and_equivocating_ancestors) =
self.smart_ancestors_to_propose(clock_round, !force);

let excluded_ancestors_limit = self.context.committee.size() * 2;
if excluded_and_equivocating_ancestors.len() > excluded_ancestors_limit {
debug!(
"Dropping {} excluded ancestor(s) during proposal due to size limit",
excluded_and_equivocating_ancestors.len() - excluded_ancestors_limit,
);
}
let excluded_ancestors = excluded_and_equivocating_ancestors
.into_iter()
.take(excluded_ancestors_limit)
.collect();
// If we did not find enough good ancestors to propose, continue to wait before proposing.
if ancestors.is_empty() {
assert!(
!force,
"Ancestors should have been returned if force is true!"
);
return None;
}

(ancestors, excluded_ancestors)
} else {
(self.ancestors_to_propose(clock_round), vec![])
};
let excluded_ancestors_limit = self.context.committee.size() * 2;
if excluded_and_equivocating_ancestors.len() > excluded_ancestors_limit {
debug!(
"Dropping {} excluded ancestor(s) during proposal due to size limit",
excluded_and_equivocating_ancestors.len() - excluded_ancestors_limit,
);
}
let excluded_ancestors = excluded_and_equivocating_ancestors
.into_iter()
.take(excluded_ancestors_limit)
.collect();

// Update the last included ancestor block refs
for ancestor in &ancestors {
Expand Down Expand Up @@ -852,61 +837,6 @@ impl Core {
true
}

/// Retrieves the next ancestors to propose to form a block at `clock_round` round.
fn ancestors_to_propose(&mut self, clock_round: Round) -> Vec<VerifiedBlock> {
// Now take the ancestors before the clock_round (excluded) for each authority.
let (ancestors, gc_enabled, gc_round) = {
let dag_state = self.dag_state.read();
(
dag_state.get_last_cached_block_per_authority(clock_round),
dag_state.gc_enabled(),
dag_state.gc_round(),
)
};

assert_eq!(
ancestors.len(),
self.context.committee.size(),
"Fatal error, number of returned ancestors don't match committee size."
);

// Propose only ancestors of higher rounds than what has already been proposed.
// And always include own last proposed block first among ancestors.
let (last_proposed_block, _) = ancestors[self.context.own_index].clone();
assert_eq!(last_proposed_block.author(), self.context.own_index);
let ancestors = iter::once(last_proposed_block)
.chain(
ancestors
.into_iter()
.filter(|(block, _)| block.author() != self.context.own_index)
.filter(|(block, _)| {
if gc_enabled && gc_round > GENESIS_ROUND {
return block.round() > gc_round;
}
true
})
.flat_map(|(block, _)| {
if let Some(last_block_ref) = self.last_included_ancestors[block.author()] {
return (last_block_ref.round < block.round()).then_some(block);
}
Some(block)
}),
)
.collect::<Vec<_>>();

// TODO: this is for temporary sanity check - we might want to remove later on
let mut quorum = StakeAggregator::<QuorumThreshold>::new();
for ancestor in ancestors
.iter()
.filter(|block| block.round() == clock_round - 1)
{
quorum.add(ancestor.author(), &self.context.committee);
}
assert!(quorum.reached_threshold(&self.context.committee), "Fatal error, quorum not reached for parent round when proposing for round {}. Possible mismatch between DagState and Core.", clock_round);

ancestors
}

/// Retrieves the next ancestors to propose to form a block at `clock_round` round.
/// If smart selection is enabled then this will try to select the best ancestors
/// based on the propagation scores of the authorities.
Expand Down

0 comments on commit 8002b4c

Please sign in to comment.