diff --git a/consensus/src/consensus_observer/payload_store.rs b/consensus/src/consensus_observer/payload_store.rs index cd99c440b5f6e..42d743dddff79 100644 --- a/consensus/src/consensus_observer/payload_store.rs +++ b/consensus/src/consensus_observer/payload_store.rs @@ -202,7 +202,7 @@ impl BlockPayloadStore { // Process the unverified block payloads for the current epoch let mut gap_in_verified_blocks = false; - for ((epoch, round), block_payload_status) in + 'block_loop: for ((epoch, round), block_payload_status) in self.unverified_block_transaction_payloads.lock().iter() { if let BlockPayloadStatus::Available(block_payload) = block_payload_status { @@ -224,15 +224,15 @@ impl BlockPayloadStore { // Break early and cause all remaining blocks to be dropped gap_in_verified_blocks = true; - break; - } else { - // Insert the block payload into the verified block payloads - self.verified_block_transaction_payloads.lock().insert( - (*epoch, *round), - BlockPayloadStatus::Available(block_payload.clone()), - ); + break 'block_loop; } } + + // Insert the block payload into the verified block payloads + self.verified_block_transaction_payloads.lock().insert( + (*epoch, *round), + BlockPayloadStatus::Available(block_payload.clone()), + ); } else { // The payload is missing warn!( @@ -244,7 +244,7 @@ impl BlockPayloadStore { // Break early and cause all remaining blocks to be dropped gap_in_verified_blocks = true; - break; + break 'block_loop; } } @@ -277,10 +277,18 @@ mod test { block::Block, block_data::{BlockData, BlockType}, common::ProofWithData, + proof_of_store::{BatchId, BatchInfo, ProofOfStore}, quorum_cert::QuorumCert, }; use aptos_crypto::HashValue; - use aptos_types::{block_info::Round, transaction::Version}; + use aptos_types::{ + aggregate_signature::AggregateSignature, + block_info::Round, + transaction::Version, + validator_signer::ValidatorSigner, + validator_verifier::{ValidatorConsensusInfo, ValidatorVerifier}, + PeerId, + }; #[test] fn test_all_payloads_exist() { @@ -288,9 +296,26 @@ mod test { let consensus_observer_config = ConsensusObserverConfig::default(); let block_payload_store = BlockPayloadStore::new(consensus_observer_config); - // Add some blocks to the payload store + // Add some unverified blocks to the payload store let num_blocks_in_store = 100; - let pipelined_blocks = create_and_add_blocks_to_store( + let unverified_blocks = create_and_add_blocks_to_store( + block_payload_store.clone(), + num_blocks_in_store, + 0, + false, + ); + + // Verify the payloads don't exist in the block payload store + assert!(!block_payload_store.all_payloads_exist(&unverified_blocks)); + assert_eq!(get_num_verified_payloads(&block_payload_store), 0); + assert_eq!( + get_num_unverified_payloads(&block_payload_store), + num_blocks_in_store + ); + + // Add some verified blocks to the payload store + let num_blocks_in_store = 100; + let verified_blocks = create_and_add_blocks_to_store( block_payload_store.clone(), num_blocks_in_store, 0, @@ -298,27 +323,27 @@ mod test { ); // Check that all the payloads exist in the block payload store - assert!(block_payload_store.all_payloads_exist(&pipelined_blocks)); + assert!(block_payload_store.all_payloads_exist(&verified_blocks)); // Check that a subset of the payloads exist in the block payload store - let subset_pipelined_blocks = &pipelined_blocks[0..50]; - assert!(block_payload_store.all_payloads_exist(subset_pipelined_blocks)); + let subset_verified_blocks = &verified_blocks[0..50]; + assert!(block_payload_store.all_payloads_exist(subset_verified_blocks)); // Remove some of the payloads from the block payload store - block_payload_store.remove_committed_blocks(subset_pipelined_blocks); + block_payload_store.remove_committed_blocks(subset_verified_blocks); // Check that the payloads no longer exist in the block payload store - assert!(!block_payload_store.all_payloads_exist(subset_pipelined_blocks)); + assert!(!block_payload_store.all_payloads_exist(subset_verified_blocks)); // Check that the remaining payloads still exist in the block payload store - let subset_pipelined_blocks = &pipelined_blocks[50..100]; - assert!(block_payload_store.all_payloads_exist(subset_pipelined_blocks)); + let subset_verified_blocks = &verified_blocks[50..100]; + assert!(block_payload_store.all_payloads_exist(subset_verified_blocks)); // Remove the remaining payloads from the block payload store - block_payload_store.remove_committed_blocks(subset_pipelined_blocks); + block_payload_store.remove_committed_blocks(subset_verified_blocks); // Check that the payloads no longer exist in the block payload store - assert!(!block_payload_store.all_payloads_exist(subset_pipelined_blocks)); + assert!(!block_payload_store.all_payloads_exist(subset_verified_blocks)); } #[test] @@ -327,9 +352,9 @@ mod test { let consensus_observer_config = ConsensusObserverConfig::default(); let block_payload_store = BlockPayloadStore::new(consensus_observer_config); - // Add several blocks to the payload store + // Add several verified blocks to the payload store let num_blocks_in_store = 10; - let pipelined_blocks = create_and_add_blocks_to_store( + let verified_blocks = create_and_add_blocks_to_store( block_payload_store.clone(), num_blocks_in_store, 0, @@ -337,16 +362,16 @@ mod test { ); // Check that the payloads exists in the block payload store - assert!(block_payload_store.all_payloads_exist(&pipelined_blocks)); + assert!(block_payload_store.all_payloads_exist(&verified_blocks)); // Mark the payload of the first block as requested - mark_payload_as_requested(block_payload_store.clone(), &pipelined_blocks[0]); + mark_payload_as_requested(block_payload_store.clone(), &verified_blocks[0]); // Check that the payload no longer exists in the block payload store - assert!(!block_payload_store.all_payloads_exist(&pipelined_blocks)); + assert!(!block_payload_store.all_payloads_exist(&verified_blocks)); // Check that the remaining payloads still exist in the block payload store - assert!(block_payload_store.all_payloads_exist(&pipelined_blocks[1..10])); + assert!(block_payload_store.all_payloads_exist(&verified_blocks[1..10])); } #[test] @@ -355,9 +380,12 @@ mod test { let consensus_observer_config = ConsensusObserverConfig::default(); let block_payload_store = BlockPayloadStore::new(consensus_observer_config); - // Add some blocks to the payload store - let num_blocks_in_store = 10; - let pipelined_blocks = create_and_add_blocks_to_store( + // Add some unverified blocks to the payload store + let num_blocks_in_store = 100; + create_and_add_blocks_to_store(block_payload_store.clone(), num_blocks_in_store, 0, false); + + // Add some verified blocks to the payload store + let verified_blocks = create_and_add_blocks_to_store( block_payload_store.clone(), num_blocks_in_store, 0, @@ -365,22 +393,20 @@ mod test { ); // Check that the payloads exist in the block payload store - assert!(block_payload_store.all_payloads_exist(&pipelined_blocks)); + assert!(block_payload_store.all_payloads_exist(&verified_blocks)); // Verify the number of blocks in the block payload store + check_num_unverified_payloads(&block_payload_store, num_blocks_in_store); check_num_verified_payloads(&block_payload_store, num_blocks_in_store); // Clear all the payloads from the block payload store block_payload_store.clear_all_payloads(); // Check that the payloads no longer exist in the block payload store - assert!(!block_payload_store.all_payloads_exist(&pipelined_blocks)); + assert!(!block_payload_store.all_payloads_exist(&verified_blocks)); // Check that the block payload store is empty - let block_transaction_payloads = block_payload_store.get_verified_block_payloads(); - assert!(block_transaction_payloads.lock().is_empty()); - - // Verify the number of blocks in the block payload store + check_num_unverified_payloads(&block_payload_store, 0); check_num_verified_payloads(&block_payload_store, 0); } @@ -390,9 +416,9 @@ mod test { let consensus_observer_config = ConsensusObserverConfig::default(); let mut block_payload_store = BlockPayloadStore::new(consensus_observer_config); - // Add some blocks to the payload store + // Add some verified blocks to the payload store let num_blocks_in_store = 10; - let pipelined_blocks = create_and_add_blocks_to_store( + let verified_blocks = create_and_add_blocks_to_store( block_payload_store.clone(), num_blocks_in_store, 0, @@ -400,32 +426,34 @@ mod test { ); // Check that the block payload store contains the new block payloads - assert!(block_payload_store.all_payloads_exist(&pipelined_blocks)); + assert!(block_payload_store.all_payloads_exist(&verified_blocks)); // Verify the number of blocks in the block payload store + check_num_unverified_payloads(&block_payload_store, 0); check_num_verified_payloads(&block_payload_store, num_blocks_in_store); // Mark the payload of the first block as requested let payload_receiver = - mark_payload_as_requested(block_payload_store.clone(), &pipelined_blocks[0]); + mark_payload_as_requested(block_payload_store.clone(), &verified_blocks[0]); // Check that the payload no longer exists in the block payload store - assert!(!block_payload_store.all_payloads_exist(&pipelined_blocks)); + assert!(!block_payload_store.all_payloads_exist(&verified_blocks)); // Verify the number of blocks in the block payload store + check_num_unverified_payloads(&block_payload_store, 0); check_num_verified_payloads(&block_payload_store, num_blocks_in_store); // Insert the same block payload into the block payload store let transaction_payload = BlockTransactionPayload::new(vec![], Some(0), ProofWithData::empty(), vec![]); block_payload_store.insert_block_payload( - pipelined_blocks[0].block_info(), + verified_blocks[0].block_info(), transaction_payload, true, ); // Check that the block payload store now contains the requested block payload - assert!(block_payload_store.all_payloads_exist(&pipelined_blocks)); + assert!(block_payload_store.all_payloads_exist(&verified_blocks)); // Check that the payload receiver receives the requested block payload message let block_transaction_payload = payload_receiver.blocking_recv().unwrap(); @@ -434,7 +462,7 @@ mod test { } #[test] - fn test_insert_block_payload_limit() { + fn test_insert_block_payload_limit_verified() { // Create a new config observer config let max_num_pending_blocks = 10; let consensus_observer_config = ConsensusObserverConfig { @@ -445,12 +473,13 @@ mod test { // Create a new block payload store let block_payload_store = BlockPayloadStore::new(consensus_observer_config); - // Add the maximum number of blocks to the payload store + // Add the maximum number of verified blocks to the payload store let num_blocks_in_store = max_num_pending_blocks as usize; create_and_add_blocks_to_store(block_payload_store.clone(), num_blocks_in_store, 0, true); // Verify the number of blocks in the block payload store check_num_verified_payloads(&block_payload_store, num_blocks_in_store); + check_num_unverified_payloads(&block_payload_store, 0); // Add more blocks to the payload store let num_blocks_to_add = 5; @@ -458,6 +487,7 @@ mod test { // Verify the number of blocks in the block payload store check_num_verified_payloads(&block_payload_store, max_num_pending_blocks as usize); + check_num_unverified_payloads(&block_payload_store, 0); // Add a large number of blocks to the payload store let num_blocks_to_add = 100; @@ -465,18 +495,56 @@ mod test { // Verify the number of blocks in the block payload store check_num_verified_payloads(&block_payload_store, max_num_pending_blocks as usize); + check_num_unverified_payloads(&block_payload_store, 0); } #[test] - fn test_remove_blocks_for_epoch_round() { + fn test_insert_block_payload_limit_unverified() { + // Create a new config observer config + let max_num_pending_blocks = 10; + let consensus_observer_config = ConsensusObserverConfig { + max_num_pending_blocks, + ..ConsensusObserverConfig::default() + }; + + // Create a new block payload store + let block_payload_store = BlockPayloadStore::new(consensus_observer_config); + + // Add the maximum number of unverified blocks to the payload store + let num_blocks_in_store = max_num_pending_blocks as usize; + create_and_add_blocks_to_store(block_payload_store.clone(), num_blocks_in_store, 0, false); + + // Verify the number of blocks in the block payload store + check_num_unverified_payloads(&block_payload_store, num_blocks_in_store); + check_num_verified_payloads(&block_payload_store, 0); + + // Add more blocks to the payload store + let num_blocks_to_add = 5; + create_and_add_blocks_to_store(block_payload_store.clone(), num_blocks_to_add, 0, false); + + // Verify the number of blocks in the block payload store + check_num_unverified_payloads(&block_payload_store, max_num_pending_blocks as usize); + check_num_verified_payloads(&block_payload_store, 0); + + // Add a large number of blocks to the payload store + let num_blocks_to_add = 100; + create_and_add_blocks_to_store(block_payload_store.clone(), num_blocks_to_add, 0, false); + + // Verify the number of blocks in the block payload store + check_num_unverified_payloads(&block_payload_store, max_num_pending_blocks as usize); + check_num_verified_payloads(&block_payload_store, 0); + } + + #[test] + fn test_remove_blocks_for_epoch_round_verified() { // Create a new block payload store let consensus_observer_config = ConsensusObserverConfig::default(); let block_payload_store = BlockPayloadStore::new(consensus_observer_config); - // Add some blocks to the payload store for the current epoch + // Add some verified blocks to the payload store for the current epoch let current_epoch = 0; let num_blocks_in_store = 100; - let pipelined_blocks = create_and_add_blocks_to_store( + let verified_blocks = create_and_add_blocks_to_store( block_payload_store.clone(), num_blocks_in_store, current_epoch, @@ -488,10 +556,10 @@ mod test { // Check that the block payload store no longer contains the removed blocks let block_transaction_payloads = block_payload_store.get_verified_block_payloads(); - for pipelined_block in pipelined_blocks.iter().take(50) { + for verified_block in verified_blocks.iter().take(50) { assert!(!block_transaction_payloads .lock() - .contains_key(&(pipelined_block.epoch(), pipelined_block.round()))); + .contains_key(&(verified_block.epoch(), verified_block.round()))); } // Verify the number of blocks in the block payload store @@ -508,8 +576,8 @@ mod test { // Verify the number of blocks in the block payload store check_num_verified_payloads(&block_payload_store, 0); - // Add some blocks to the payload store for the next epoch - let next_epoch = 1; + // Add some verified blocks to the payload store for the next epoch + let next_epoch = current_epoch + 1; create_and_add_blocks_to_store( block_payload_store.clone(), num_blocks_in_store, @@ -518,7 +586,7 @@ mod test { ); // Remove all the blocks for the future epoch and round - let future_epoch = 2; + let future_epoch = next_epoch + 1; block_payload_store.remove_blocks_for_epoch_round(future_epoch, 0); // Verify the store is now empty @@ -526,7 +594,69 @@ mod test { } #[test] - fn test_remove_committed_blocks() { + fn test_remove_blocks_for_epoch_round_unverified() { + // Create a new block payload store + let consensus_observer_config = ConsensusObserverConfig::default(); + let block_payload_store = BlockPayloadStore::new(consensus_observer_config); + + // Add some unverified blocks to the payload store for the current epoch + let current_epoch = 10; + let num_blocks_in_store = 100; + let unverified_blocks = create_and_add_blocks_to_store( + block_payload_store.clone(), + num_blocks_in_store, + current_epoch, + false, + ); + + // Remove all the blocks for the given epoch and round + block_payload_store.remove_blocks_for_epoch_round(current_epoch, 49); + + // Check that the block payload store no longer contains the removed blocks + let block_transaction_payloads = block_payload_store + .unverified_block_transaction_payloads + .clone(); + for unverified_block in unverified_blocks.iter().take(50) { + assert!(!block_transaction_payloads + .lock() + .contains_key(&(unverified_block.epoch(), unverified_block.round()))); + } + + // Verify the number of blocks in the block payload store + check_num_unverified_payloads(&block_payload_store, num_blocks_in_store - 50); + + // Remove all the blocks for the given epoch and round + block_payload_store + .remove_blocks_for_epoch_round(current_epoch, num_blocks_in_store as Round); + + // Check that the block payload store no longer contains any blocks + let block_transaction_payloads = block_payload_store + .unverified_block_transaction_payloads + .clone(); + assert!(block_transaction_payloads.lock().is_empty()); + + // Verify the number of blocks in the block payload store + check_num_unverified_payloads(&block_payload_store, 0); + + // Add some unverified blocks to the payload store for the next epoch + let next_epoch = current_epoch + 1; + create_and_add_blocks_to_store( + block_payload_store.clone(), + num_blocks_in_store, + next_epoch, + false, + ); + + // Remove all the blocks for the future epoch and round + let future_epoch = next_epoch + 10; + block_payload_store.remove_blocks_for_epoch_round(future_epoch, 0); + + // Verify the store is now empty + check_num_unverified_payloads(&block_payload_store, 0); + } + + #[test] + fn test_remove_committed_blocks_verified() { // Create a new block payload store let consensus_observer_config = ConsensusObserverConfig::default(); let block_payload_store = BlockPayloadStore::new(consensus_observer_config); @@ -534,7 +664,7 @@ mod test { // Add some blocks to the payload store for the current epoch let current_epoch = 0; let num_blocks_in_store = 100; - let pipelined_blocks = create_and_add_blocks_to_store( + let verified_blocks = create_and_add_blocks_to_store( block_payload_store.clone(), num_blocks_in_store, current_epoch, @@ -542,11 +672,11 @@ mod test { ); // Remove the first block from the block payload store - block_payload_store.remove_committed_blocks(&pipelined_blocks[0..1]); + block_payload_store.remove_committed_blocks(&verified_blocks[0..1]); // Check that the block payload store no longer contains the removed block let block_transaction_payloads = block_payload_store.get_verified_block_payloads(); - let removed_block = &pipelined_blocks[0]; + let removed_block = &verified_blocks[0]; assert!(!block_transaction_payloads .lock() .contains_key(&(removed_block.epoch(), removed_block.round()))); @@ -555,21 +685,21 @@ mod test { check_num_verified_payloads(&block_payload_store, num_blocks_in_store - 1); // Remove the last 5 blocks from the block payload store - block_payload_store.remove_committed_blocks(&pipelined_blocks[5..10]); + block_payload_store.remove_committed_blocks(&verified_blocks[5..10]); // Check that the block payload store no longer contains the removed blocks let block_transaction_payloads = block_payload_store.get_verified_block_payloads(); - for pipelined_block in pipelined_blocks.iter().take(10).skip(5) { + for verified_block in verified_blocks.iter().take(10).skip(5) { assert!(!block_transaction_payloads .lock() - .contains_key(&(pipelined_block.epoch(), pipelined_block.round()))); + .contains_key(&(verified_block.epoch(), verified_block.round()))); } // Verify the number of blocks in the block payload store check_num_verified_payloads(&block_payload_store, num_blocks_in_store - 10); // Remove all the blocks from the block payload store (including some that don't exist) - block_payload_store.remove_committed_blocks(&pipelined_blocks[0..num_blocks_in_store]); + block_payload_store.remove_committed_blocks(&verified_blocks[0..num_blocks_in_store]); // Check that the block payload store no longer contains any blocks let block_transaction_payloads = block_payload_store.get_verified_block_payloads(); @@ -580,7 +710,7 @@ mod test { // Add some blocks to the payload store for the next epoch let next_epoch = 1; - let pipelined_blocks = create_and_add_blocks_to_store( + let verified_blocks = create_and_add_blocks_to_store( block_payload_store.clone(), num_blocks_in_store, next_epoch, @@ -588,12 +718,215 @@ mod test { ); // Remove the last committed block from the future epoch - block_payload_store.remove_committed_blocks(&pipelined_blocks[99..100]); + block_payload_store.remove_committed_blocks(&verified_blocks[99..100]); // Check that the block payload store is now empty check_num_verified_payloads(&block_payload_store, 0); } + #[test] + fn test_remove_committed_blocks_unverified() { + // Create a new block payload store + let consensus_observer_config = ConsensusObserverConfig::default(); + let block_payload_store = BlockPayloadStore::new(consensus_observer_config); + + // Add some blocks to the payload store for the current epoch + let current_epoch = 10; + let num_blocks_in_store = 100; + let unverified_blocks = create_and_add_blocks_to_store( + block_payload_store.clone(), + num_blocks_in_store, + current_epoch, + false, + ); + + // Remove the first block from the block payload store + block_payload_store.remove_committed_blocks(&unverified_blocks[0..1]); + + // Check that the block payload store no longer contains the removed block + let block_transaction_payloads = block_payload_store + .unverified_block_transaction_payloads + .clone(); + let removed_block = &unverified_blocks[0]; + assert!(!block_transaction_payloads + .lock() + .contains_key(&(removed_block.epoch(), removed_block.round()))); + + // Verify the number of blocks in the block payload store + check_num_unverified_payloads(&block_payload_store, num_blocks_in_store - 1); + + // Remove the last 5 blocks from the block payload store + block_payload_store.remove_committed_blocks(&unverified_blocks[5..10]); + + // Check that the block payload store no longer contains the removed blocks + let block_transaction_payloads = block_payload_store + .unverified_block_transaction_payloads + .clone(); + for verified_block in unverified_blocks.iter().take(10).skip(5) { + assert!(!block_transaction_payloads + .lock() + .contains_key(&(verified_block.epoch(), verified_block.round()))); + } + + // Verify the number of blocks in the block payload store + check_num_unverified_payloads(&block_payload_store, num_blocks_in_store - 10); + + // Remove all the blocks from the block payload store (including some that don't exist) + block_payload_store.remove_committed_blocks(&unverified_blocks[0..num_blocks_in_store]); + + // Check that the block payload store no longer contains any blocks + let block_transaction_payloads = block_payload_store + .unverified_block_transaction_payloads + .clone(); + assert!(block_transaction_payloads.lock().is_empty()); + + // Verify the number of blocks in the block payload store + check_num_unverified_payloads(&block_payload_store, 0); + + // Add some blocks to the payload store for the next epoch + let next_epoch = 11; + let unverified_blocks = create_and_add_blocks_to_store( + block_payload_store.clone(), + num_blocks_in_store, + next_epoch, + false, + ); + + // Remove the last committed block from the future epoch + block_payload_store.remove_committed_blocks(&unverified_blocks[99..100]); + + // Check that the block payload store is now empty + check_num_unverified_payloads(&block_payload_store, 0); + } + + #[test] + fn test_verify_payload_signatures() { + // Create a new block payload store + let consensus_observer_config = ConsensusObserverConfig::default(); + let block_payload_store = BlockPayloadStore::new(consensus_observer_config); + + // Add some verified blocks for the current epoch + let current_epoch = 0; + let num_verified_blocks = 10; + create_and_add_blocks_to_store( + block_payload_store.clone(), + num_verified_blocks, + current_epoch, + true, + ); + + // Add some unverified blocks for the next epoch + let next_epoch = current_epoch + 1; + let num_unverified_blocks = 20; + let unverified_blocks = create_and_add_blocks_to_store( + block_payload_store.clone(), + num_unverified_blocks, + next_epoch, + false, + ); + + // Add some unverified blocks for a future epoch + let future_epoch = current_epoch + 30; + let num_future_blocks = 30; + let future_unverified_blocks = create_and_add_blocks_to_store( + block_payload_store.clone(), + num_future_blocks, + future_epoch, + false, + ); + + // Create an epoch state for the next epoch (with an empty verifier) + let epoch_state = EpochState::new(next_epoch, ValidatorVerifier::new(vec![])); + + // Verify the block payload signatures + block_payload_store.verify_payload_signatures(&epoch_state); + + // Verify the unverified payloads were moved to the verified store + assert!(block_payload_store.all_payloads_exist(&unverified_blocks)); + assert_eq!( + get_num_verified_payloads(&block_payload_store), + num_verified_blocks + num_unverified_blocks + ); + assert_eq!( + get_num_unverified_payloads(&block_payload_store), + num_future_blocks + ); + + // Clear the verified blocks and check the verified blocks are empty + block_payload_store.remove_committed_blocks(&unverified_blocks); + assert_eq!(get_num_verified_payloads(&block_payload_store), 0); + + // Create an epoch state for the future epoch (with an empty verifier) + let epoch_state = EpochState::new(future_epoch, ValidatorVerifier::new(vec![])); + + // Verify the block payload signatures for a future epoch + block_payload_store.verify_payload_signatures(&epoch_state); + + // Verify the future unverified payloads were moved to the verified store + assert!(block_payload_store.all_payloads_exist(&future_unverified_blocks)); + assert_eq!( + get_num_verified_payloads(&block_payload_store), + num_future_blocks + ); + assert_eq!(get_num_unverified_payloads(&block_payload_store), 0); + } + + #[test] + fn test_verify_payload_signatures_failure() { + // Create a new block payload store + let consensus_observer_config = ConsensusObserverConfig::default(); + let block_payload_store = BlockPayloadStore::new(consensus_observer_config); + + // Add some verified blocks for the current epoch + let current_epoch = 10; + let num_verified_blocks = 6; + create_and_add_blocks_to_store( + block_payload_store.clone(), + num_verified_blocks, + current_epoch, + true, + ); + + // Add some unverified blocks for the next epoch + let next_epoch = current_epoch + 1; + let num_unverified_blocks = 15; + let unverified_blocks = create_and_add_blocks_to_store( + block_payload_store.clone(), + num_unverified_blocks, + next_epoch, + false, + ); + + // Add some unverified blocks for a future epoch + let future_epoch = next_epoch + 1; + let num_future_blocks = 10; + create_and_add_blocks_to_store( + block_payload_store.clone(), + num_future_blocks, + future_epoch, + false, + ); + + // Create an epoch state for the next epoch (with a non-empty verifier) + let validator_signer = ValidatorSigner::random(None); + let validator_consensus_info = ValidatorConsensusInfo::new( + validator_signer.author(), + validator_signer.public_key(), + 100, + ); + let validator_verified = ValidatorVerifier::new(vec![validator_consensus_info]); + let epoch_state = EpochState::new(next_epoch, validator_verified); + + // Verify the block payload signatures + block_payload_store.verify_payload_signatures(&epoch_state); + + // Verify the unverified payloads were not moved to the verified store + assert!(!block_payload_store.all_payloads_exist(&unverified_blocks)); + + // Ensure the unverified payloads were all removed + assert_eq!(get_num_unverified_payloads(&block_payload_store), 0); + } + /// Creates and adds the given number of blocks to the block payload store fn create_and_add_blocks_to_store( mut block_payload_store: BlockPayloadStore, @@ -614,10 +947,32 @@ mod test { None, ); + // Create the block transaction payload with proofs of store + let mut proofs_of_store = vec![]; + for _ in 0..10 { + let batch_info = BatchInfo::new( + PeerId::random(), + BatchId::new(0), + epoch, + 0, + HashValue::random(), + 0, + 0, + 0, + ); + proofs_of_store.push(ProofOfStore::new(batch_info, AggregateSignature::empty())); + } + let block_transaction_payload = BlockTransactionPayload::new( + vec![], + None, + ProofWithData::new(proofs_of_store), + vec![], + ); + // Insert the block payload into the store block_payload_store.insert_block_payload( block_info.clone(), - BlockTransactionPayload::empty(), + block_transaction_payload, verified_payload_signatures, ); @@ -639,6 +994,40 @@ mod test { pipelined_blocks } + /// Checks the number of unverified payloads in the block payload store + fn check_num_unverified_payloads( + block_payload_store: &BlockPayloadStore, + expected_num_payloads: usize, + ) { + let num_payloads = get_num_unverified_payloads(block_payload_store); + assert_eq!(num_payloads, expected_num_payloads); + } + + /// Checks the number of verified payloads in the block payload store + fn check_num_verified_payloads( + block_payload_store: &BlockPayloadStore, + expected_num_payloads: usize, + ) { + let num_payloads = get_num_verified_payloads(block_payload_store); + assert_eq!(num_payloads, expected_num_payloads); + } + + /// Returns the number of unverified payloads in the block payload store + fn get_num_unverified_payloads(block_payload_store: &BlockPayloadStore) -> usize { + block_payload_store + .unverified_block_transaction_payloads + .lock() + .len() + } + + /// Returns the number of verified payloads in the block payload store + fn get_num_verified_payloads(block_payload_store: &BlockPayloadStore) -> usize { + block_payload_store + .verified_block_transaction_payloads + .lock() + .len() + } + /// Marks the payload of the given block as requested and returns the receiver fn mark_payload_as_requested( block_payload_store: BlockPayloadStore, @@ -658,16 +1047,4 @@ mod test { // Return the payload receiver payload_receiver } - - /// Checks the number of verified payloads in the block payload store - fn check_num_verified_payloads( - block_payload_store: &BlockPayloadStore, - expected_num_entries: usize, - ) { - let num_payloads = block_payload_store - .verified_block_transaction_payloads - .lock() - .len(); - assert_eq!(num_payloads, expected_num_entries); - } }