diff --git a/zebra-rpc/src/sync.rs b/zebra-rpc/src/sync.rs index 480755e98f8..96b31d49c00 100644 --- a/zebra-rpc/src/sync.rs +++ b/zebra-rpc/src/sync.rs @@ -334,7 +334,6 @@ impl SyncerRpcMethods for RpcRequestClient { } Err(err) => Err(err), } - // TODO: Check for the MISSING_BLOCK_ERROR_CODE and return a `Result>`? } } diff --git a/zebrad/Cargo.toml b/zebrad/Cargo.toml index a86d2afe8a2..04a21dfcfc9 100644 --- a/zebrad/Cargo.toml +++ b/zebrad/Cargo.toml @@ -100,6 +100,8 @@ progress-bar = [ prometheus = ["metrics-exporter-prometheus"] +rpc-syncer = ["zebra-rpc/syncer"] + # Production features that modify dependency behaviour # Enable additional error debugging in release builds diff --git a/zebrad/tests/acceptance.rs b/zebrad/tests/acceptance.rs index 2c8c692d4b9..6994b3bf05d 100644 --- a/zebrad/tests/acceptance.rs +++ b/zebrad/tests/acceptance.rs @@ -3170,3 +3170,43 @@ async fn regtest_submit_blocks() -> Result<()> { common::regtest::submit_blocks_test().await?; Ok(()) } + +// TODO: +// - Test that chain forks are handled correctly and that `ChainTipChange` sees a `Reset` +// - Test that `ChainTipChange` is updated when the non-finalized best chain grows +// - Test that the `ChainTipChange` updated by the RPC syncer is updated when the finalized tip changes +#[cfg(feature = "rpc-syncer")] +#[tokio::test] +async fn trusted_chain_sync_handles_forks_correctly() -> Result<()> { + let _init_guard = zebra_test::init(); + let mut config = random_known_rpc_port_config(false, &Mainnet)?; + config.state.ephemeral = false; + config.network.network = Network::new_regtest(None); + + let testdir = testdir()?.with_config(&mut config)?; + let mut child = testdir.spawn_child(args!["start"])?; + + std::thread::sleep(LAUNCH_DELAY); + + // 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, _chain_tip_change, _sync_task) = + zebra_rpc::sync::init_read_state_with_syncer( + config.state, + &config.network.network, + config.rpc.listen_addr.unwrap(), + ) + .await? + .map_err(|err| eyre!(err))?; + + // Submit some blocks on the best chain + + child.kill(false)?; + let output = child.wait_with_output()?; + + // Make sure the command was killed + output.assert_was_killed()?; + + output.assert_failure()?; + + Ok(()) +}