Skip to content

Commit

Permalink
Add epoch to authenticated checkpoints (MystenLabs#2670)
Browse files Browse the repository at this point in the history
  • Loading branch information
lxfind authored Jun 23, 2022
1 parent 3310364 commit bb429df
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 76 deletions.
4 changes: 3 additions & 1 deletion crates/sui-core/src/authority.rs
Original file line number Diff line number Diff line change
Expand Up @@ -971,7 +971,7 @@ impl AuthorityState {
.lock();
match &request.request_type {
CheckpointRequestType::LatestCheckpointProposal => {
checkpoint_store.handle_latest_proposal(request)
checkpoint_store.handle_latest_proposal(self.committee.load().epoch, request)
}
CheckpointRequestType::PastCheckpoint(seq) => {
checkpoint_store.handle_past_checkpoint(request.detail, *seq)
Expand All @@ -984,6 +984,8 @@ impl AuthorityState {
}
}

// TODO: This function takes both committee and genesis as parameter.
// Technically genesis already contains committee information. Could consider merging them.
pub async fn new(
committee: Committee,
name: AuthorityName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,10 @@ pub async fn checkpoint_process<A>(

let _start_checkpoint_making = weight > committee.quorum_threshold();

let proposal = state_checkpoints.lock().new_proposal().clone();
let proposal = state_checkpoints
.lock()
.new_proposal(committee.epoch)
.clone();
if let Ok(my_proposal) = proposal {
diff_proposals(
active_authority,
Expand Down
10 changes: 8 additions & 2 deletions crates/sui-core/src/authority_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,8 +341,14 @@ impl LocalAuthorityClient {
let store = Arc::new(AuthorityStore::open(&store_path, None));
let mut checkpoints_path = path.clone();
checkpoints_path.push("checkpoints");
let checkpoints = CheckpointStore::open(&checkpoints_path, None, address, secret.clone())
.expect("Should not fail to open local checkpoint DB");
let checkpoints = CheckpointStore::open(
&checkpoints_path,
None,
committee.epoch,
address,
secret.clone(),
)
.expect("Should not fail to open local checkpoint DB");

let state = AuthorityState::new(
committee.clone(),
Expand Down
39 changes: 27 additions & 12 deletions crates/sui-core/src/checkpoints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use typed_store::{
};

use arc_swap::ArcSwapOption;
use sui_types::committee::EpochId;

use crate::{
authority::StableSyncAuthoritySigner,
Expand Down Expand Up @@ -164,7 +165,7 @@ impl CheckpointStore {
// Manage persistent local variables

/// Loads the locals from the store -- do this at init
fn load_locals(&mut self) -> Result<CheckpointLocals, SuiError> {
fn load_locals(&mut self, epoch: EpochId) -> Result<CheckpointLocals, SuiError> {
// Loads locals from disk, or inserts initial locals
let mut locals = match self.locals.get(&LOCALS)? {
Some(locals) => locals,
Expand All @@ -186,6 +187,7 @@ impl CheckpointStore {
let transactions = CheckpointContents::new(transactions);
let previous_digest = self.get_prev_checkpoint_digest(checkpoint_sequence)?;
let proposal = SignedCheckpointProposal(SignedCheckpoint::new(
epoch,
checkpoint_sequence,
self.name,
&*self.secret,
Expand Down Expand Up @@ -234,6 +236,7 @@ impl CheckpointStore {
pub fn open<P: AsRef<Path>>(
path: P,
db_options: Option<Options>,
current_epoch: EpochId,
name: AuthorityName,
secret: StableSyncAuthoritySigner,
) -> Result<CheckpointStore, SuiError> {
Expand Down Expand Up @@ -296,7 +299,7 @@ impl CheckpointStore {
};

// Initialize the locals
checkpoint_db.load_locals()?;
checkpoint_db.load_locals(current_epoch)?;

Ok(checkpoint_db)
}
Expand All @@ -305,12 +308,13 @@ impl CheckpointStore {

pub fn handle_latest_proposal(
&mut self,
epoch: EpochId,
request: &CheckpointRequest,
) -> Result<CheckpointResponse, SuiError> {
// Set a proposal if there is not one, and one could be set
// TODO: check some minimum time passed since the last one
// and only set after that time.
let _ = self.new_proposal();
let _ = self.new_proposal(epoch);

// Try to load any latest proposal
let locals = self.get_locals();
Expand Down Expand Up @@ -395,6 +399,7 @@ impl CheckpointStore {
/// registered as processed or unprocessed.
pub fn handle_internal_set_checkpoint(
&mut self,
epoch: EpochId,
checkpoint: CheckpointSummary,
contents: &CheckpointContents,
) -> Result<(), SuiError> {
Expand Down Expand Up @@ -449,7 +454,7 @@ impl CheckpointStore {
self.update_new_checkpoint_inner(checkpoint_sequence_number, &transactions, batch)?;

// Try to set a fresh proposal, and ignore errors if this fails.
let _ = self.new_proposal();
let _ = self.new_proposal(epoch);

Ok(())
}
Expand Down Expand Up @@ -687,9 +692,13 @@ impl CheckpointStore {
let previous_digest = self
.get_prev_checkpoint_digest(next_sequence_number)
.map_err(FragmentInternalError::Error)?;
let summary =
CheckpointSummary::new(next_sequence_number, &contents, previous_digest);
self.handle_internal_set_checkpoint(summary, &contents)
let summary = CheckpointSummary::new(
committee.epoch,
next_sequence_number,
&contents,
previous_digest,
);
self.handle_internal_set_checkpoint(committee.epoch, summary, &contents)
.map_err(FragmentInternalError::Error)?;
return Ok(true);
}
Expand Down Expand Up @@ -741,11 +750,12 @@ impl CheckpointStore {
.get_prev_checkpoint_digest(next_sequence_number)
.map_err(FragmentInternalError::Error)?;
let summary = CheckpointSummary::new(
committee.epoch,
next_sequence_number,
&contents,
previous_digest,
);
self.handle_internal_set_checkpoint(summary, &contents)
self.handle_internal_set_checkpoint(committee.epoch, summary, &contents)
.map_err(FragmentInternalError::Error)?;
return Ok(true);
}
Expand Down Expand Up @@ -807,7 +817,11 @@ impl CheckpointStore {
if let &Some(contents) = &contents {
// Check and process contents
checkpoint.verify_with_transactions(committee, contents)?;
self.handle_internal_set_checkpoint(checkpoint.checkpoint.clone(), contents)?;
self.handle_internal_set_checkpoint(
committee.epoch,
checkpoint.checkpoint.clone(),
contents,
)?;
// Then insert it
self.checkpoints.insert(
checkpoint.checkpoint.sequence_number(),
Expand Down Expand Up @@ -875,7 +889,7 @@ impl CheckpointStore {
/// Creates a new proposal, but only if the previous checkpoint certificate
/// is known and stored. This ensures that any validator in checkpoint round
/// X can serve certificates for all rounds < X.
pub fn new_proposal(&mut self) -> Result<CheckpointProposal, SuiError> {
pub fn new_proposal(&mut self, epoch: EpochId) -> Result<CheckpointProposal, SuiError> {
let sequence_number = self.next_checkpoint();

// Only move to propose when we have the full checkpoint certificate
Expand All @@ -889,7 +903,7 @@ impl CheckpointStore {
}
}

self.set_proposal()
self.set_proposal(epoch)
}

/// Get the latest stored checkpoint if there is one
Expand All @@ -907,7 +921,7 @@ impl CheckpointStore {
// Helper write functions

/// Set the next checkpoint proposal.
pub fn set_proposal(&mut self) -> Result<CheckpointProposal, SuiError> {
pub fn set_proposal(&mut self, epoch: EpochId) -> Result<CheckpointProposal, SuiError> {
// Check that:
// - there is no current proposal.
// - there are no unprocessed transactions.
Expand Down Expand Up @@ -939,6 +953,7 @@ impl CheckpointStore {

let transactions = CheckpointContents::new(self.extra_transactions.keys());
let proposal = SignedCheckpointProposal(SignedCheckpoint::new(
epoch,
checkpoint_sequence,
self.name,
&*self.secret,
Expand Down
Loading

0 comments on commit bb429df

Please sign in to comment.