From a6387c1bc1709270bae40716d0cfc8c4a6f6a2a4 Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Wed, 9 Apr 2025 22:59:19 +0100 Subject: [PATCH 1/3] fix switching to main chain after a reorg --- .../src/blockchain/manager/handler.rs | 6 +- .../cuprated/src/blockchain/manager/tests.rs | 119 +++++++++++++++++- 2 files changed, 123 insertions(+), 2 deletions(-) diff --git a/binaries/cuprated/src/blockchain/manager/handler.rs b/binaries/cuprated/src/blockchain/manager/handler.rs index 5dab932db..190261a53 100644 --- a/binaries/cuprated/src/blockchain/manager/handler.rs +++ b/binaries/cuprated/src/blockchain/manager/handler.rs @@ -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). let mut blocks = batch.blocks.into_iter(); while let Some((block, txs)) = blocks.next() { @@ -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; } diff --git a/binaries/cuprated/src/blockchain/manager/tests.rs b/binaries/cuprated/src/blockchain/manager/tests.rs index 55acb5c3d..fd8754b70 100644 --- a/binaries/cuprated/src/blockchain/manager/tests.rs +++ b/binaries/cuprated/src/blockchain/manager/tests.rs @@ -10,8 +10,9 @@ 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::block_downloader::BlockBatch; use cuprate_p2p::BroadcastSvc; - +use cuprate_p2p_core::handles::HandleBuilder; use crate::blockchain::{ check_add_genesis, manager::BlockchainManager, manager::BlockchainManagerCommand, ConsensusBlockchainReadHandle, @@ -202,3 +203,119 @@ 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 + ); +} + From 1a07db68b777d3da5e7d27e89ecaa6478a6b90fb Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Wed, 9 Apr 2025 23:08:53 +0100 Subject: [PATCH 2/3] fmt --- binaries/cuprated/src/blockchain/manager/tests.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/binaries/cuprated/src/blockchain/manager/tests.rs b/binaries/cuprated/src/blockchain/manager/tests.rs index fd8754b70..c63f8872a 100644 --- a/binaries/cuprated/src/blockchain/manager/tests.rs +++ b/binaries/cuprated/src/blockchain/manager/tests.rs @@ -7,16 +7,16 @@ use monero_serai::{ use tokio::sync::{oneshot, watch}; use tower::BoxError; +use crate::blockchain::{ + check_add_genesis, manager::BlockchainManager, manager::BlockchainManagerCommand, + ConsensusBlockchainReadHandle, +}; 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::block_downloader::BlockBatch; use cuprate_p2p::BroadcastSvc; use cuprate_p2p_core::handles::HandleBuilder; -use crate::blockchain::{ - check_add_genesis, manager::BlockchainManager, manager::BlockchainManagerCommand, - ConsensusBlockchainReadHandle, -}; async fn mock_manager(data_dir: PathBuf) -> BlockchainManager { let blockchain_config = cuprate_blockchain::config::ConfigBuilder::new() @@ -208,7 +208,7 @@ async fn simple_reorg() { #[tokio::test] async fn simple_reorg_block_batch() { cuprate_fast_sync::set_fast_sync_hashes(&[]); - + let handle = HandleBuilder::new().build(); // create 2 managers @@ -318,4 +318,3 @@ async fn simple_reorg_block_batch() { 4 ); } - From 4327c606f9338125d7e1b0730056d58f57234c5b Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Wed, 9 Apr 2025 23:11:19 +0100 Subject: [PATCH 3/3] sort imports --- binaries/cuprated/src/blockchain/manager/tests.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/binaries/cuprated/src/blockchain/manager/tests.rs b/binaries/cuprated/src/blockchain/manager/tests.rs index c63f8872a..c1e944cd5 100644 --- a/binaries/cuprated/src/blockchain/manager/tests.rs +++ b/binaries/cuprated/src/blockchain/manager/tests.rs @@ -7,17 +7,17 @@ use monero_serai::{ use tokio::sync::{oneshot, watch}; use tower::BoxError; -use crate::blockchain::{ - check_add_genesis, manager::BlockchainManager, manager::BlockchainManagerCommand, - ConsensusBlockchainReadHandle, -}; 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::block_downloader::BlockBatch; -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, + ConsensusBlockchainReadHandle, +}; + async fn mock_manager(data_dir: PathBuf) -> BlockchainManager { let blockchain_config = cuprate_blockchain::config::ConfigBuilder::new() .data_directory(data_dir.clone())