diff --git a/crates/sui-core/src/authority.rs b/crates/sui-core/src/authority.rs index f3a2fc0f6f845..7bafbedd8d4fd 100644 --- a/crates/sui-core/src/authority.rs +++ b/crates/sui-core/src/authority.rs @@ -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) @@ -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, diff --git a/crates/sui-core/src/authority_active/checkpoint_driver/mod.rs b/crates/sui-core/src/authority_active/checkpoint_driver/mod.rs index 6e79b1059d724..224dc796f58e1 100644 --- a/crates/sui-core/src/authority_active/checkpoint_driver/mod.rs +++ b/crates/sui-core/src/authority_active/checkpoint_driver/mod.rs @@ -202,7 +202,10 @@ pub async fn checkpoint_process( 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, diff --git a/crates/sui-core/src/authority_client.rs b/crates/sui-core/src/authority_client.rs index 958a20de1974c..b58040439a027 100644 --- a/crates/sui-core/src/authority_client.rs +++ b/crates/sui-core/src/authority_client.rs @@ -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(), diff --git a/crates/sui-core/src/checkpoints/mod.rs b/crates/sui-core/src/checkpoints/mod.rs index 21b6bce5fcbbd..a38c4a4d4b310 100644 --- a/crates/sui-core/src/checkpoints/mod.rs +++ b/crates/sui-core/src/checkpoints/mod.rs @@ -33,6 +33,7 @@ use typed_store::{ }; use arc_swap::ArcSwapOption; +use sui_types::committee::EpochId; use crate::{ authority::StableSyncAuthoritySigner, @@ -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 { + fn load_locals(&mut self, epoch: EpochId) -> Result { // Loads locals from disk, or inserts initial locals let mut locals = match self.locals.get(&LOCALS)? { Some(locals) => locals, @@ -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, @@ -234,6 +236,7 @@ impl CheckpointStore { pub fn open>( path: P, db_options: Option, + current_epoch: EpochId, name: AuthorityName, secret: StableSyncAuthoritySigner, ) -> Result { @@ -296,7 +299,7 @@ impl CheckpointStore { }; // Initialize the locals - checkpoint_db.load_locals()?; + checkpoint_db.load_locals(current_epoch)?; Ok(checkpoint_db) } @@ -305,12 +308,13 @@ impl CheckpointStore { pub fn handle_latest_proposal( &mut self, + epoch: EpochId, request: &CheckpointRequest, ) -> Result { // 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(); @@ -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> { @@ -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(()) } @@ -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); } @@ -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); } @@ -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(), @@ -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 { + pub fn new_proposal(&mut self, epoch: EpochId) -> Result { let sequence_number = self.next_checkpoint(); // Only move to propose when we have the full checkpoint certificate @@ -889,7 +903,7 @@ impl CheckpointStore { } } - self.set_proposal() + self.set_proposal(epoch) } /// Get the latest stored checkpoint if there is one @@ -907,7 +921,7 @@ impl CheckpointStore { // Helper write functions /// Set the next checkpoint proposal. - pub fn set_proposal(&mut self) -> Result { + pub fn set_proposal(&mut self, epoch: EpochId) -> Result { // Check that: // - there is no current proposal. // - there are no unprocessed transactions. @@ -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, diff --git a/crates/sui-core/src/checkpoints/tests/checkpoint_tests.rs b/crates/sui-core/src/checkpoints/tests/checkpoint_tests.rs index e41ff00066bfc..609657520d5fe 100644 --- a/crates/sui-core/src/checkpoints/tests/checkpoint_tests.rs +++ b/crates/sui-core/src/checkpoints/tests/checkpoint_tests.rs @@ -48,6 +48,7 @@ fn random_ckpoint_store_num( let cps = CheckpointStore::open( path.clone(), None, + committee.epoch, *k.public_key_bytes(), Arc::pin(k.copy()), ) @@ -61,7 +62,7 @@ fn random_ckpoint_store_num( #[test] fn crash_recovery() { let mut rng = StdRng::from_seed(RNG_SEED); - let (keys, _committee) = make_committee_key(&mut rng); + let (keys, committee) = make_committee_key(&mut rng); let k = keys[0].copy(); // Setup @@ -76,6 +77,7 @@ fn crash_recovery() { let mut cps = CheckpointStore::open( path.clone(), None, + committee.epoch, *k.public_key_bytes(), Arc::pin(k.copy()), ) @@ -107,7 +109,7 @@ fn crash_recovery() { let locals = cps.get_locals(); assert_eq!(locals.next_transaction_sequence, 4); - let proposal = cps.set_proposal().unwrap(); + let proposal = cps.set_proposal(committee.epoch).unwrap(); assert_eq!(*proposal.sequence_number(), 0); cps.handle_internal_batch(7, &[(4, t4), (5, t5), (6, t6)]) @@ -116,8 +118,14 @@ fn crash_recovery() { // Delete and re-open DB drop(cps); - let mut cps_new = - CheckpointStore::open(path, None, *k.public_key_bytes(), Arc::pin(k.copy())).unwrap(); + let mut cps_new = CheckpointStore::open( + path, + None, + committee.epoch, + *k.public_key_bytes(), + Arc::pin(k.copy()), + ) + .unwrap(); // TEST 3 -- the current proposal is correctly recreated. @@ -184,7 +192,7 @@ fn make_checkpoint_db() { #[test] fn make_proposals() { - let (_committee, _keys, mut stores) = random_ckpoint_store(); + let (committee, _keys, mut stores) = random_ckpoint_store(); let (_, mut cps1) = stores.pop().unwrap(); let (_, mut cps2) = stores.pop().unwrap(); let (_, mut cps3) = stores.pop().unwrap(); @@ -209,9 +217,9 @@ fn make_proposals() { cps4.update_processed_transactions(&[(1, t4), (2, t5)]) .unwrap(); - let p1 = cps1.set_proposal().unwrap(); - let p2 = cps2.set_proposal().unwrap(); - let p3 = cps3.set_proposal().unwrap(); + let p1 = cps1.set_proposal(committee.epoch).unwrap(); + let p2 = cps2.set_proposal(committee.epoch).unwrap(); + let p3 = cps3.set_proposal(committee.epoch).unwrap(); let ckp_items: Vec<_> = p1 .transactions() @@ -238,7 +246,7 @@ fn make_proposals() { #[test] fn make_diffs() { - let (_committee, _keys, mut stores) = random_ckpoint_store(); + let (committee, _keys, mut stores) = random_ckpoint_store(); let (_, mut cps1) = stores.pop().unwrap(); let (_, mut cps2) = stores.pop().unwrap(); let (_, mut cps3) = stores.pop().unwrap(); @@ -263,10 +271,10 @@ fn make_diffs() { cps4.update_processed_transactions(&[(1, t4), (2, t5)]) .unwrap(); - let p1 = cps1.set_proposal().unwrap(); - let p2 = cps2.set_proposal().unwrap(); - let p3 = cps3.set_proposal().unwrap(); - let p4 = cps4.set_proposal().unwrap(); + let p1 = cps1.set_proposal(committee.epoch).unwrap(); + let p2 = cps2.set_proposal(committee.epoch).unwrap(); + let p3 = cps3.set_proposal(committee.epoch).unwrap(); + let p4 = cps4.set_proposal(committee.epoch).unwrap(); let diff12 = p1.fragment_with(&p2); let diff23 = p2.fragment_with(&p3); @@ -292,7 +300,7 @@ fn make_diffs() { #[test] fn latest_proposal() { - let (_committee, _keys, mut stores) = random_ckpoint_store(); + let (committee, _keys, mut stores) = random_ckpoint_store(); let (_, mut cps1) = stores.pop().unwrap(); let (_, mut cps2) = stores.pop().unwrap(); let (_, mut cps3) = stores.pop().unwrap(); @@ -322,7 +330,9 @@ fn latest_proposal() { // No checkpoint no proposal let request = CheckpointRequest::latest(false); - let response = cps1.handle_latest_proposal(&request).expect("no errors"); + let response = cps1 + .handle_latest_proposal(committee.epoch, &request) + .expect("no errors"); assert!(response.detail.is_none()); assert!(matches!( response.info, @@ -335,9 +345,9 @@ fn latest_proposal() { // --- - let p1 = cps1.set_proposal().unwrap(); - let p2 = cps2.set_proposal().unwrap(); - let p3 = cps3.set_proposal().unwrap(); + let p1 = cps1.set_proposal(committee.epoch).unwrap(); + let p2 = cps2.set_proposal(committee.epoch).unwrap(); + let p3 = cps3.set_proposal(committee.epoch).unwrap(); // --- TEST 1 --- @@ -345,7 +355,9 @@ fn latest_proposal() { // Check the latest checkpoint with no detail let request = CheckpointRequest::latest(false); - let response = cps1.handle_latest_proposal(&request).expect("no errors"); + let response = cps1 + .handle_latest_proposal(committee.epoch, &request) + .expect("no errors"); assert!(response.detail.is_none()); assert!(matches!( response.info, @@ -364,7 +376,9 @@ fn latest_proposal() { // Check the latest checkpoint with detail let request = CheckpointRequest::latest(true); - let response = cps1.handle_latest_proposal(&request).expect("no errors"); + let response = cps1 + .handle_latest_proposal(committee.epoch, &request) + .expect("no errors"); assert!(response.detail.is_some()); assert!(matches!( response.info, @@ -392,15 +406,15 @@ fn latest_proposal() { .collect(); let transactions = CheckpointContents::new(ckp_items.clone().into_iter()); - let summary = CheckpointSummary::new(0, &transactions, None); + let summary = CheckpointSummary::new(committee.epoch, 0, &transactions, None); - cps1.handle_internal_set_checkpoint(summary.clone(), &transactions) + cps1.handle_internal_set_checkpoint(committee.epoch, summary.clone(), &transactions) .unwrap(); - cps2.handle_internal_set_checkpoint(summary.clone(), &transactions) + cps2.handle_internal_set_checkpoint(committee.epoch, summary.clone(), &transactions) .unwrap(); - cps3.handle_internal_set_checkpoint(summary.clone(), &transactions) + cps3.handle_internal_set_checkpoint(committee.epoch, summary.clone(), &transactions) .unwrap(); - cps4.handle_internal_set_checkpoint(summary, &transactions) + cps4.handle_internal_set_checkpoint(committee.epoch, summary, &transactions) .unwrap(); // --- TEST3 --- @@ -408,10 +422,12 @@ fn latest_proposal() { // No valid checkpoint proposal condition... assert!(cps1.get_locals().current_proposal.is_none()); // ... because a valid checkpoint cannot be generated. - assert!(cps1.set_proposal().is_err()); + assert!(cps1.set_proposal(committee.epoch).is_err()); let request = CheckpointRequest::latest(false); - let response = cps1.handle_latest_proposal(&request).expect("no errors"); + let response = cps1 + .handle_latest_proposal(committee.epoch, &request) + .expect("no errors"); assert!(response.detail.is_none()); assert!(matches!( response.info, @@ -426,7 +442,9 @@ fn latest_proposal() { // When details are needed, then return unexecuted transactions if there is no proposal let request = CheckpointRequest::latest(true); - let response = cps1.handle_latest_proposal(&request).expect("no errors"); + let response = cps1 + .handle_latest_proposal(committee.epoch, &request) + .expect("no errors"); assert!(response.detail.is_some()); use typed_store::traits::Map; let txs = response.detail.unwrap(); @@ -452,13 +470,15 @@ fn latest_proposal() { .collect(); cps1.update_processed_transactions(&batch[..]).unwrap(); - let _p1 = cps1.set_proposal().unwrap(); + let _p1 = cps1.set_proposal(committee.epoch).unwrap(); // --- TEST 5 --- // Get the full proposal with previous proposal let request = CheckpointRequest::latest(true); - let response = cps1.handle_latest_proposal(&request).expect("no errors"); + let response = cps1 + .handle_latest_proposal(committee.epoch, &request) + .expect("no errors"); assert!(matches!( response.info, AuthorityCheckpointInfo::Proposal { .. } @@ -500,9 +520,9 @@ fn set_get_checkpoint() { cps4.update_processed_transactions(&[(1, t4), (2, t5)]) .unwrap(); - let p1 = cps1.set_proposal().unwrap(); - let p2 = cps2.set_proposal().unwrap(); - let p3 = cps3.set_proposal().unwrap(); + let p1 = cps1.set_proposal(committee.epoch).unwrap(); + let p2 = cps2.set_proposal(committee.epoch).unwrap(); + let p3 = cps3.set_proposal(committee.epoch).unwrap(); // --- TEST 0 --- @@ -531,13 +551,13 @@ fn set_get_checkpoint() { .cloned(); let transactions = CheckpointContents::new(ckp_items); - let summary = CheckpointSummary::new(0, &transactions, None); + let summary = CheckpointSummary::new(committee.epoch, 0, &transactions, None); - cps1.handle_internal_set_checkpoint(summary.clone(), &transactions) + cps1.handle_internal_set_checkpoint(committee.epoch, summary.clone(), &transactions) .unwrap(); - cps2.handle_internal_set_checkpoint(summary.clone(), &transactions) + cps2.handle_internal_set_checkpoint(committee.epoch, summary.clone(), &transactions) .unwrap(); - cps3.handle_internal_set_checkpoint(summary, &transactions) + cps3.handle_internal_set_checkpoint(committee.epoch, summary, &transactions) .unwrap(); // cps4.handle_internal_set_checkpoint(summary, &transactions) // .unwrap(); @@ -615,7 +635,7 @@ fn set_get_checkpoint() { #[test] fn checkpoint_integration() { let mut rng = StdRng::from_seed(RNG_SEED); - let (keys, _committee) = make_committee_key(&mut rng); + let (keys, committee) = make_committee_key(&mut rng); let k = keys[0].copy(); // Setup @@ -627,8 +647,14 @@ fn checkpoint_integration() { // Create an authority // Make a checkpoint store: - let mut cps = - CheckpointStore::open(path, None, *k.public_key_bytes(), Arc::pin(k.copy())).unwrap(); + let mut cps = CheckpointStore::open( + path, + None, + committee.epoch, + *k.public_key_bytes(), + Arc::pin(k.copy()), + ) + .unwrap(); let mut next_tx_num: TxSequenceNumber = 0; let mut unprocessed = Vec::new(); @@ -653,7 +679,7 @@ fn checkpoint_integration() { .unwrap(); // Step 1. Make a proposal - let _proposal = cps.set_proposal().unwrap(); + let _proposal = cps.set_proposal(committee.epoch).unwrap(); // Step 2. Continue to process transactions while a proposal is out. let some_fresh_transactions: Vec<_> = (0..7) @@ -677,17 +703,18 @@ fn checkpoint_integration() { let transactions = CheckpointContents::new(unprocessed.clone().into_iter()); let next_checkpoint = cps.get_locals().next_checkpoint; let summary = CheckpointSummary::new( + committee.epoch, next_checkpoint, &transactions, cps.get_prev_checkpoint_digest(next_checkpoint) .expect("previous checkpoint should exist"), ); - cps.handle_internal_set_checkpoint(summary.clone(), &transactions) + cps.handle_internal_set_checkpoint(committee.epoch, summary.clone(), &transactions) .unwrap(); // Cannot make a checkpoint proposal before adding the unprocessed transactions - assert!(cps.set_proposal().is_err()); + assert!(cps.set_proposal(committee.epoch).is_err()); // Loop invariant to ensure termination or error assert_eq!(cps.get_locals().next_checkpoint, old_checkpoint + 1); } @@ -720,6 +747,7 @@ async fn test_batch_to_checkpointing() { CheckpointStore::open( &checkpoints_path, None, + committee.epoch, *secret.public_key_bytes(), secret.clone(), ) @@ -889,6 +917,7 @@ async fn test_batch_to_checkpointing_init_crash() { CheckpointStore::open( &checkpoints_path, None, + committee.epoch, *secret.public_key_bytes(), secret.clone(), ) @@ -957,9 +986,9 @@ fn set_fragment_external() { cps4.update_processed_transactions(&[(1, t4), (2, t5)]) .unwrap(); - let p1 = cps1.set_proposal().unwrap(); - let p2 = cps2.set_proposal().unwrap(); - let _p3 = cps3.set_proposal().unwrap(); + let p1 = cps1.set_proposal(committee.epoch).unwrap(); + let p2 = cps2.set_proposal(committee.epoch).unwrap(); + let _p3 = cps3.set_proposal(committee.epoch).unwrap(); let fragment12 = p1.fragment_with(&p2); // let fragment13 = p1.diff_with(&p3); @@ -1005,10 +1034,10 @@ fn set_fragment_reconstruct() { cps4.update_processed_transactions(&[(1, t4), (2, t5)]) .unwrap(); - let p1 = cps1.set_proposal().unwrap(); - let p2 = cps2.set_proposal().unwrap(); - let p3 = cps3.set_proposal().unwrap(); - let p4 = cps4.set_proposal().unwrap(); + let p1 = cps1.set_proposal(committee.epoch).unwrap(); + let p2 = cps2.set_proposal(committee.epoch).unwrap(); + let p3 = cps3.set_proposal(committee.epoch).unwrap(); + let p4 = cps4.set_proposal(committee.epoch).unwrap(); let fragment12 = p1.fragment_with(&p2); let fragment34 = p3.fragment_with(&p4); @@ -1044,7 +1073,7 @@ fn set_fragment_reconstruct_two_components() { let mut proposals: Vec<_> = test_objects .iter_mut() - .map(|(_, cps)| cps.set_proposal().unwrap()) + .map(|(_, cps)| cps.set_proposal(committee.epoch).unwrap()) .collect(); // Get out the last two @@ -1096,7 +1125,7 @@ fn set_fragment_reconstruct_two_mutual() { let mut proposals: Vec<_> = test_objects .iter_mut() - .map(|(_, cps)| cps.set_proposal().unwrap()) + .map(|(_, cps)| cps.set_proposal(committee.epoch).unwrap()) .collect(); // Get out the last two @@ -1157,7 +1186,7 @@ fn test_fragment_full_flow() { let mut proposals: Vec<_> = test_objects .iter_mut() - .map(|(_, cps)| cps.set_proposal().unwrap()) + .map(|(_, cps)| cps.set_proposal(committee.epoch).unwrap()) .collect(); // Get out the last two @@ -1394,6 +1423,7 @@ pub async fn checkpoint_tests_setup(num_objects: usize, batch_interval: Duration let mut checkpoint = CheckpointStore::open( &checkpoints_path, None, + committee.epoch, *secret.public_key_bytes(), secret.clone(), ) diff --git a/crates/sui-node/src/lib.rs b/crates/sui-node/src/lib.rs index f0163ceea9175..7b8518ee5f6e3 100644 --- a/crates/sui-node/src/lib.rs +++ b/crates/sui-node/src/lib.rs @@ -57,11 +57,13 @@ impl SuiNode { let genesis = config.genesis()?; let secret = Arc::pin(config.key_pair().copy()); + let committee = genesis.committee(); let store = Arc::new(AuthorityStore::open(config.db_path().join("store"), None)); let checkpoint_store = if config.consensus_config().is_some() { Some(Arc::new(Mutex::new(CheckpointStore::open( config.db_path().join("checkpoints"), None, + committee.epoch, config.public_key(), secret.clone(), )?))) @@ -82,7 +84,7 @@ impl SuiNode { let state = Arc::new( AuthorityState::new( - genesis.committee(), + committee, config.public_key(), secret, store, diff --git a/crates/sui-types/src/messages_checkpoint.rs b/crates/sui-types/src/messages_checkpoint.rs index 9757867f3be0a..c3b01f30007ef 100644 --- a/crates/sui-types/src/messages_checkpoint.rs +++ b/crates/sui-types/src/messages_checkpoint.rs @@ -4,6 +4,7 @@ use std::collections::{BTreeMap, BTreeSet, HashSet}; use crate::base_types::ExecutionDigests; +use crate::committee::EpochId; use crate::crypto::Signable; use crate::messages::CertifiedTransaction; use crate::waypoint::{Waypoint, WaypointDiff}; @@ -181,6 +182,7 @@ pub type CheckpointDigest = [u8; 32]; #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct CheckpointSummary { + pub epoch: EpochId, pub sequence_number: CheckpointSequenceNumber, pub waypoint: Box, // Bigger structure, can live on heap. pub content_digest: CheckpointDigest, @@ -190,6 +192,7 @@ pub struct CheckpointSummary { impl CheckpointSummary { pub fn new( + epoch: EpochId, sequence_number: CheckpointSequenceNumber, transactions: &CheckpointContents, previous_digest: Option, @@ -202,6 +205,7 @@ impl CheckpointSummary { let content_digest = transactions.digest(); Self { + epoch, sequence_number, waypoint, content_digest, @@ -231,13 +235,15 @@ pub struct SignedCheckpoint { impl SignedCheckpoint { /// Create a new signed checkpoint proposal for this authority pub fn new( + epoch: EpochId, sequence_number: CheckpointSequenceNumber, authority: AuthorityName, signer: &dyn signature::Signer, transactions: &CheckpointContents, previous_digest: Option, ) -> SignedCheckpoint { - let checkpoint = CheckpointSummary::new(sequence_number, transactions, previous_digest); + let checkpoint = + CheckpointSummary::new(epoch, sequence_number, transactions, previous_digest); SignedCheckpoint::new_from_summary(checkpoint, authority, signer) } @@ -265,6 +271,7 @@ impl SignedCheckpoint { pub fn verify_with_transactions(&self, contents: &CheckpointContents) -> Result<(), SuiError> { self.verify()?; let recomputed = CheckpointSummary::new( + self.checkpoint.epoch, *self.checkpoint.sequence_number(), contents, self.checkpoint.previous_digest, @@ -478,13 +485,14 @@ mod tests { #[test] fn test_signed_proposal() { let mut rng = StdRng::from_seed(RNG_SEED); - let (authority_key, _committee) = make_committee_key(&mut rng); + let (authority_key, committee) = make_committee_key(&mut rng); let name = authority_key[0].public_key_bytes(); let set = [ExecutionDigests::random()]; let set = CheckpointContents::new(set.iter().cloned()); - let mut proposal = SignedCheckpoint::new(1, *name, &authority_key[0], &set, None); + let mut proposal = + SignedCheckpoint::new(committee.epoch, 1, *name, &authority_key[0], &set, None); // Signature is correct on proposal, and with same transactions assert!(proposal.verify().is_ok()); @@ -514,7 +522,7 @@ mod tests { .map(|k| { let name = k.public_key_bytes(); - SignedCheckpoint::new(1, *name, k, &set, None) + SignedCheckpoint::new(committee.epoch, 1, *name, k, &set, None) }) .collect(); @@ -534,7 +542,7 @@ mod tests { let set: BTreeSet<_> = [ExecutionDigests::random()].into_iter().collect(); let set = CheckpointContents::new(set.iter().cloned()); - SignedCheckpoint::new(1, *name, k, &set, None) + SignedCheckpoint::new(committee.epoch, 1, *name, k, &set, None) }) .collect(); diff --git a/crates/sui/tests/checkpoints_tests.rs b/crates/sui/tests/checkpoints_tests.rs index fcd8b37db6f3f..e9b83e754cd67 100644 --- a/crates/sui/tests/checkpoints_tests.rs +++ b/crates/sui/tests/checkpoints_tests.rs @@ -70,7 +70,10 @@ async fn sequence_fragments() { .lock() .handle_internal_batch(next_sequence_number, &transactions) .unwrap(); - let proposal = checkpoints_store.lock().set_proposal().unwrap(); + let proposal = checkpoints_store + .lock() + .set_proposal(committee.epoch) + .unwrap(); proposal }) .collect();