Skip to content

Commit

Permalink
3966 add_epoch_root and sync_l1 on Membership
Browse files Browse the repository at this point in the history
  • Loading branch information
pls148 committed Dec 20, 2024
1 parent 3d705c6 commit 426d478
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
56 changes: 56 additions & 0 deletions crates/task-impls/src/quorum_vote/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,55 @@ async fn handle_quorum_proposal_validated_drb_calculation_seed<
Ok(())
}

/// Handles calling add_epoch_root and sync_l1 on Membership if necessary.
async fn handle_quorum_proposal_validated_add_epoch_root<
TYPES: NodeType,
I: NodeImplementation<TYPES>,
V: Versions,
>(
proposal: &QuorumProposal2<TYPES>,
task_state: &mut QuorumVoteTaskState<TYPES, I, V>,
leaf_views: &[LeafInfo<TYPES>],
) {
let decided_block_number = leaf_views
.last()
.unwrap()
.leaf
.block_header()
.block_number();

// Skip if this is not the expected block.
if task_state.epoch_height != 0 && (decided_block_number + 3) % task_state.epoch_height == 0 {
let next_epoch_number = TYPES::Epoch::new(
epoch_from_block_number(decided_block_number, task_state.epoch_height) + 1,
);

let write_callback = {
let membership_reader = task_state.membership.read().await;
membership_reader
.add_epoch_root(next_epoch_number, proposal.block_header.clone())
.await
};

if let Some(write_callback) = write_callback {
let mut membership_writer = task_state.membership.write().await;
write_callback(&mut *membership_writer);
}

if TYPES::Membership::uses_sync_l1() {
let write_callback = {
let membership_reader = task_state.membership.read().await;
membership_reader.sync_l1().await
};

if let Some(write_callback) = write_callback {
let mut membership_writer = task_state.membership.write().await;
write_callback(&mut *membership_writer);
}
}
}
}

/// Handles the `QuorumProposalValidated` event.
#[instrument(skip_all, fields(id = task_state.id, view = *proposal.view_number))]
pub(crate) async fn handle_quorum_proposal_validated<
Expand Down Expand Up @@ -235,6 +284,13 @@ pub(crate) async fn handle_quorum_proposal_validated<
// We don't need to hold this while we broadcast
drop(consensus_writer);

// Notify the membership of the new change

if version >= V::Epochs::VERSION {
handle_quorum_proposal_validated_add_epoch_root(proposal, task_state, &leaf_views)
.await;
}

// Send an update to everyone saying that we've reached a decide
broadcast_event(
Event {
Expand Down
30 changes: 30 additions & 0 deletions crates/types/src/traits/election.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
//! The election trait, used to decide which node is the leader and determine if a vote is valid.
use std::{collections::BTreeSet, fmt::Debug, num::NonZeroU64};

use async_trait::async_trait;
use utils::anytrace::Result;

use super::node_implementation::NodeType;
use crate::{traits::signature_key::SignatureKey, PeerConfig};

#[async_trait]
/// A protocol for determining membership in and participating in a committee.
pub trait Membership<TYPES: NodeType>: Debug + Send + Sync {
/// The error type returned by methods like `lookup_leader`.
Expand Down Expand Up @@ -125,4 +127,32 @@ pub trait Membership<TYPES: NodeType>: Debug + Send + Sync {

/// Returns the threshold required to upgrade the network protocol
fn upgrade_threshold(&self, epoch: TYPES::Epoch) -> NonZeroU64;

#[allow(clippy::type_complexity)]
/// Handles notifications that a new epoch root has been created
/// Is called under a read lock to the Membership. Return a callback
/// with Some to have that callback invoked under a write lock.
async fn add_epoch_root(
&self,
_epoch: TYPES::Epoch,
_block_header: TYPES::BlockHeader,
) -> Option<Box<dyn FnOnce(&mut Self) + Send>> {
None
}

#[must_use]
/// Used to determine if sync_l1 should be called after add_epoch_root.
/// Returning false avoids a redundant read lock for cases where sync_l1
/// is a no-op.
fn uses_sync_l1() -> bool {
false
}

#[allow(clippy::type_complexity)]
/// Called after add_epoch_root runs and any callback has been invoked.
/// Causes a read lock to be reacquired for this functionality. If it is
/// not needed, then have uses_sync_l1 return false.
async fn sync_l1(&self) -> Option<Box<dyn FnOnce(&mut Self) + Send>> {
None
}
}

0 comments on commit 426d478

Please sign in to comment.