From 112294f1436540d6b5ebfce5908bc3ccbaa43527 Mon Sep 17 00:00:00 2001 From: Arya Date: Thu, 13 Jun 2024 23:05:43 -0400 Subject: [PATCH] checks for chain tip changes in test --- zebra-rpc/src/sync.rs | 11 +++--- zebrad/tests/acceptance.rs | 61 ++++++++++++++++++++++++++++------ zebrad/tests/common/regtest.rs | 4 +-- 3 files changed, 60 insertions(+), 16 deletions(-) diff --git a/zebra-rpc/src/sync.rs b/zebra-rpc/src/sync.rs index 0d670d2bbed..93045b183a0 100644 --- a/zebra-rpc/src/sync.rs +++ b/zebra-rpc/src/sync.rs @@ -193,11 +193,13 @@ impl TrustedChainSync { } /// Tries to catch up to the primary db instance for an up-to-date view of finalized blocks. + // TODO: Use getblock RPC if it fails to catch up to primary? async fn try_catch_up_with_primary(&self) { let db = self.db.clone(); tokio::task::spawn_blocking(move || { - let catch_up_result = db.try_catch_up_with_primary(); - tracing::debug!(?catch_up_result, "trying to catch up to primary"); + if let Err(catch_up_error) = db.try_catch_up_with_primary() { + tracing::warn!(?catch_up_error, "failed to catch up to primary"); + } }) .wait_for_panics() .await @@ -211,8 +213,9 @@ impl TrustedChainSync { self.non_finalized_state.chain_count() == 0 && { let db = self.db.clone(); tokio::task::spawn_blocking(move || { - let catch_up_result = db.try_catch_up_with_primary(); - tracing::debug!(?catch_up_result, "trying to catch up to primary"); + if let Err(catch_up_error) = db.try_catch_up_with_primary() { + tracing::warn!(?catch_up_error, "failed to catch up to primary"); + } db.contains_hash(target_tip_hash) }) .wait_for_panics() diff --git a/zebrad/tests/acceptance.rs b/zebrad/tests/acceptance.rs index fff60003e50..672b7cd9470 100644 --- a/zebrad/tests/acceptance.rs +++ b/zebrad/tests/acceptance.rs @@ -3171,14 +3171,13 @@ async fn regtest_submit_blocks() -> Result<()> { Ok(()) } -// TODO: -// - Test that the `ChainTipChange` updated by the RPC syncer is updated when the finalized tip changes (outside Regtest) #[cfg(feature = "rpc-syncer")] #[tokio::test(flavor = "multi_thread")] async fn trusted_chain_sync_handles_forks_correctly() -> Result<()> { use std::sync::Arc; use common::regtest::MiningRpcMethods; + use eyre::Error; use tokio::time::timeout; use zebra_chain::{ chain_tip::ChainTip, parameters::NetworkUpgrade, @@ -3193,9 +3192,9 @@ async fn trusted_chain_sync_handles_forks_correctly() -> Result<()> { let network = config.network.network.clone(); let rpc_address = config.rpc.listen_addr.unwrap(); - let testdir = testdir()?.with_config(&mut config)?; + let test_dir = testdir()?.with_config(&mut config)?; - let mut child = testdir.spawn_child(args!["start"])?; + let mut child = test_dir.spawn_child(args!["start"])?; tracing::info!("waiting for Zebra state cache to be opened"); @@ -3244,10 +3243,11 @@ async fn trusted_chain_sync_handles_forks_correctly() -> Result<()> { ); } + tracing::info!("checking that read state has the new non-finalized best chain blocks"); for expected_block in blocks.clone() { let height = expected_block.coinbase_height().unwrap(); let zebra_block = rpc_client - .get_block(height.0) + .get_block(height.0 as i32) .await .map_err(|err| eyre!(err))? .expect("Zebra test child should have the expected block"); @@ -3361,10 +3361,11 @@ async fn trusted_chain_sync_handles_forks_correctly() -> Result<()> { "tip action hashes and heights should match" ); + tracing::info!("checking that read state has the new non-finalized best chain blocks"); for expected_block in blocks { let height = expected_block.coinbase_height().unwrap(); let zebra_block = rpc_client - .get_block(height.0) + .get_block(height.0 as i32) .await .map_err(|err| eyre!(err))? .expect("Zebra test child should have the expected block"); @@ -3391,6 +3392,8 @@ async fn trusted_chain_sync_handles_forks_correctly() -> Result<()> { ); } + tracing::info!("restarting Zebra on Mainnet"); + child.kill(false)?; let output = child.wait_with_output()?; @@ -3399,10 +3402,48 @@ async fn trusted_chain_sync_handles_forks_correctly() -> Result<()> { output.assert_failure()?; - // TODO: - // - Start another Zebra testchild on Testnet or Mainnet - // - Wait for it to start syncing blocks from the network - // - Check that `LatestChainTip` is being updated with the newly synced finalized blocks + let mut config = random_known_rpc_port_config(false, &Network::Mainnet)?; + config.state.ephemeral = false; + let rpc_address = config.rpc.listen_addr.unwrap(); + + let test_dir = testdir()?.with_config(&mut config)?; + + let mut child = test_dir.spawn_child(args!["start"])?; + + tracing::info!("waiting for Zebra state cache to be opened"); + + child.expect_stdout_line_matches(format!( + "Opened Zebra state cache at {}", + config.state.cache_dir.to_str().unwrap() + ))?; + + tracing::info!("starting read state with syncer"); + // Spawn a read state with the RPC syncer to check that it has the same best chain as Zebra + let (_read_state, _latest_chain_tip, mut chain_tip_change, _sync_task) = + zebra_rpc::sync::init_read_state_with_syncer( + config.state, + &config.network.network, + rpc_address, + ) + .await? + .map_err(|err| eyre!(err))?; + + tracing::info!("waiting for finalized chain tip changes"); + + timeout( + Duration::from_secs(100), + tokio::spawn(async move { + for _ in 0..2 { + chain_tip_change + .wait_for_tip_change() + .await + .map_err(|err| eyre!(err))?; + } + + Ok::<(), Error>(()) + }), + ) + .await???; Ok(()) } diff --git a/zebrad/tests/common/regtest.rs b/zebrad/tests/common/regtest.rs index 1b36cba80e5..5140314b04b 100644 --- a/zebrad/tests/common/regtest.rs +++ b/zebrad/tests/common/regtest.rs @@ -96,7 +96,7 @@ pub trait MiningRpcMethods { async fn block_from_template(&self, nu5_activation_height: Height) -> Result<(Block, Height)>; async fn submit_block(&self, block: Block) -> Result<()>; async fn submit_block_from_template(&self) -> Result<(Block, Height)>; - async fn get_block(&self, height: u32) -> Result>, BoxError>; + async fn get_block(&self, height: i32) -> Result>, BoxError>; } impl MiningRpcMethods for RpcRequestClient { @@ -146,7 +146,7 @@ impl MiningRpcMethods for RpcRequestClient { Ok((block, height)) } - async fn get_block(&self, height: u32) -> Result>, BoxError> { + async fn get_block(&self, height: i32) -> Result>, BoxError> { match self .json_result_from_call("getblock", format!(r#"["{}", 0]"#, height)) .await