Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion binaries/cuprated/src/blockchain/manager/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,6 @@ impl super::BlockchainManager {
/// This function will panic if any internal service returns an unexpected error that we cannot
/// recover from.
async fn handle_incoming_block_batch_alt_chain(&mut self, mut batch: BlockBatch) {
// TODO: this needs testing (this whole section does but alt-blocks specifically).
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is sufficiently tested now :)

let mut blocks = batch.blocks.into_iter();

while let Some((block, txs)) = blocks.next() {
Expand Down Expand Up @@ -271,6 +270,11 @@ impl super::BlockchainManager {
Ok(AddAltBlock::Reorged) => {
// Collect the remaining blocks and add them to the main chain instead.
batch.blocks = blocks.collect();

if batch.blocks.is_empty() {
return;
}

self.handle_incoming_block_batch_main_chain(batch).await;
return;
}
Expand Down
118 changes: 117 additions & 1 deletion binaries/cuprated/src/blockchain/manager/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ use tower::BoxError;
use cuprate_consensus_context::{BlockchainContext, ContextConfig};
use cuprate_consensus_rules::{hard_forks::HFInfo, miner_tx::calculate_block_reward, HFsInfo};
use cuprate_helper::network::Network;
use cuprate_p2p::BroadcastSvc;
use cuprate_p2p::{block_downloader::BlockBatch, BroadcastSvc};
use cuprate_p2p_core::handles::HandleBuilder;

use crate::blockchain::{
check_add_genesis, manager::BlockchainManager, manager::BlockchainManagerCommand,
Expand Down Expand Up @@ -202,3 +203,118 @@ async fn simple_reorg() {
4
);
}

/// Same as [`simple_reorg`] but uses block batches instead.
#[tokio::test]
async fn simple_reorg_block_batch() {
cuprate_fast_sync::set_fast_sync_hashes(&[]);

let handle = HandleBuilder::new().build();

// create 2 managers
let data_dir_1 = tempfile::tempdir().unwrap();
let mut manager_1 = mock_manager(data_dir_1.path().to_path_buf()).await;

let data_dir_2 = tempfile::tempdir().unwrap();
let mut manager_2 = mock_manager(data_dir_2.path().to_path_buf()).await;

// give both managers the same first non-genesis block
let block_1 = generate_block(manager_1.blockchain_context_service.blockchain_context());

manager_1
.handle_incoming_block_batch(BlockBatch {
blocks: vec![(block_1.clone(), vec![])],
size: 0,
peer_handle: handle.1.clone(),
})
.await;

manager_2
.handle_incoming_block_batch(BlockBatch {
blocks: vec![(block_1, vec![])],
size: 0,
peer_handle: handle.1.clone(),
})
.await;

assert_eq!(
manager_1.blockchain_context_service.blockchain_context(),
manager_2.blockchain_context_service.blockchain_context()
);

// give managers different 2nd block
let block_2a = generate_block(manager_1.blockchain_context_service.blockchain_context());
let block_2b = generate_block(manager_2.blockchain_context_service.blockchain_context());

manager_1
.handle_incoming_block_batch(BlockBatch {
blocks: vec![(block_2a, vec![])],
size: 0,
peer_handle: handle.1.clone(),
})
.await;

manager_2
.handle_incoming_block_batch(BlockBatch {
blocks: vec![(block_2b.clone(), vec![])],
size: 0,
peer_handle: handle.1.clone(),
})
.await;

let manager_1_context = manager_1
.blockchain_context_service
.blockchain_context()
.clone();
assert_ne!(
&manager_1_context,
manager_2.blockchain_context_service.blockchain_context()
);

// give manager 1 missing block

manager_1
.handle_incoming_block_batch(BlockBatch {
blocks: vec![(block_2b, vec![])],
size: 0,
peer_handle: handle.1.clone(),
})
.await;
// make sure this didn't change the context
assert_eq!(
&manager_1_context,
manager_1.blockchain_context_service.blockchain_context()
);

// give both managers new block (built of manager 2's chain)
let block_3 = generate_block(manager_2.blockchain_context_service.blockchain_context());

manager_1
.handle_incoming_block_batch(BlockBatch {
blocks: vec![(block_3.clone(), vec![])],
size: 0,
peer_handle: handle.1.clone(),
})
.await;

manager_2
.handle_incoming_block_batch(BlockBatch {
blocks: vec![(block_3, vec![])],
size: 0,
peer_handle: handle.1.clone(),
})
.await;

// make sure manager 1 reorged.
assert_eq!(
manager_1.blockchain_context_service.blockchain_context(),
manager_2.blockchain_context_service.blockchain_context()
);
assert_eq!(
manager_1
.blockchain_context_service
.blockchain_context()
.chain_height,
4
);
}