Skip to content

Commit 3359f1e

Browse files
committed
test: try stopping bitcoind within Rust, rather than spawning the CLI
1 parent f8907be commit 3359f1e

File tree

4 files changed

+64
-20
lines changed

4 files changed

+64
-20
lines changed

.github/workflows/bitcoin-tests.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ jobs:
7474
- tests::neon_integrations::min_txs
7575
- tests::neon_integrations::vote_for_aggregate_key_burn_op_test
7676
- tests::neon_integrations::mock_miner_replay
77+
- tests::neon_integrations::bitcoin_reorg_flap
78+
- tests::neon_integrations::bitcoin_reorg_flap_with_follower
79+
- tests::neon_integrations::start_stop_bitcoind
7780
- tests::epoch_25::microblocks_disabled
7881
- tests::should_succeed_handling_malformed_and_valid_txs
7982
- tests::nakamoto_integrations::simple_neon_integration
@@ -121,9 +124,6 @@ jobs:
121124
- tests::nakamoto_integrations::follower_bootup_across_multiple_cycles
122125
- tests::nakamoto_integrations::utxo_check_on_startup_panic
123126
- tests::nakamoto_integrations::utxo_check_on_startup_recover
124-
# Do not run this one until we figure out why it fails in CI
125-
# - tests::neon_integrations::bitcoin_reorg_flap
126-
# - tests::neon_integrations::bitcoin_reorg_flap_with_follower
127127
# TODO: enable these once v1 signer is supported by a new nakamoto epoch
128128
# - tests::signer::v1::dkg
129129
# - tests::signer::v1::sign_request_rejected

testnet/stacks-node/src/burnchains/bitcoin_regtest_controller.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2815,7 +2815,7 @@ impl BitcoinRPCRequest {
28152815
Ok(())
28162816
}
28172817

2818-
fn send(config: &Config, payload: BitcoinRPCRequest) -> RPCResult<serde_json::Value> {
2818+
pub fn send(config: &Config, payload: BitcoinRPCRequest) -> RPCResult<serde_json::Value> {
28192819
let request = BitcoinRPCRequest::build_rpc_request(&config, &payload);
28202820
let timeout = Duration::from_secs(u64::from(config.burnchain.timeout));
28212821

testnet/stacks-node/src/tests/bitcoin_regtest.rs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use stacks::core::StacksEpochId;
1111
use stacks_common::util::hash::hex_bytes;
1212

1313
use super::PUBLISH_CONTRACT;
14+
use crate::burnchains::bitcoin_regtest_controller::BitcoinRPCRequest;
1415
use crate::config::InitialBalance;
1516
use crate::helium::RunLoop;
1617
use crate::tests::to_addr;
@@ -19,12 +20,14 @@ use crate::Config;
1920
#[derive(Debug)]
2021
pub enum BitcoinCoreError {
2122
SpawnFailed(String),
23+
StopFailed(String),
2224
}
2325

2426
impl std::fmt::Display for BitcoinCoreError {
2527
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2628
match self {
2729
Self::SpawnFailed(msg) => write!(f, "bitcoind spawn failed: {msg}"),
30+
Self::StopFailed(msg) => write!(f, "bitcoind stop failed: {msg}"),
2831
}
2932
}
3033
}
@@ -109,25 +112,25 @@ impl BitcoinCoreController {
109112

110113
pub fn stop_bitcoind(&mut self) -> Result<(), BitcoinCoreError> {
111114
if let Some(_) = self.bitcoind_process.take() {
112-
let mut command = Command::new("bitcoin-cli");
113-
command.stdout(Stdio::piped()).arg("-rpcconnect=127.0.0.1");
114-
115-
self.add_rpc_cli_args(&mut command);
116-
117-
command.arg("stop");
118-
119-
let mut process = match command.spawn() {
120-
Ok(child) => child,
121-
Err(e) => return Err(BitcoinCoreError::SpawnFailed(format!("{e:?}"))),
115+
let payload = BitcoinRPCRequest {
116+
method: "stop".to_string(),
117+
params: vec![],
118+
id: "stacks".to_string(),
119+
jsonrpc: "2.0".to_string(),
122120
};
123121

124-
let mut out_reader = BufReader::new(process.stdout.take().unwrap());
125-
let mut line = String::new();
126-
while let Ok(bytes_read) = out_reader.read_line(&mut line) {
127-
if bytes_read == 0 {
128-
break;
122+
let res = BitcoinRPCRequest::send(&self.config, payload)
123+
.map_err(|e| BitcoinCoreError::StopFailed(format!("{e:?}")))?;
124+
125+
if let Some(err) = res.get("error") {
126+
if !err.is_null() {
127+
return Err(BitcoinCoreError::StopFailed(format!("{err}")));
129128
}
130-
eprintln!("{line}");
129+
} else {
130+
return Err(BitcoinCoreError::StopFailed(format!(
131+
"Invalid response: {:?}",
132+
res
133+
)));
131134
}
132135
}
133136
Ok(())

testnet/stacks-node/src/tests/neon_integrations.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12794,3 +12794,44 @@ fn mock_miner_replay() {
1279412794
miner_channel.stop_chains_coordinator();
1279512795
follower_channel.stop_chains_coordinator();
1279612796
}
12797+
12798+
#[test]
12799+
#[ignore]
12800+
/// Test out stopping bitcoind and restarting it
12801+
fn start_stop_bitcoind() {
12802+
if env::var("BITCOIND_TEST") != Ok("1".into()) {
12803+
return;
12804+
}
12805+
12806+
let (mut conf, _miner_account) = neon_integration_test_conf();
12807+
let prom_bind = format!("{}:{}", "127.0.0.1", 6000);
12808+
conf.node.prometheus_bind = Some(prom_bind.clone());
12809+
12810+
conf.burnchain.max_rbf = 1000000;
12811+
12812+
let mut btcd_controller = BitcoinCoreController::new(conf.clone());
12813+
btcd_controller
12814+
.start_bitcoind()
12815+
.map_err(|_e| ())
12816+
.expect("Failed starting bitcoind");
12817+
12818+
let mut btc_regtest_controller = BitcoinRegtestController::new(conf.clone(), None);
12819+
12820+
btc_regtest_controller.bootstrap_chain(201);
12821+
12822+
eprintln!("Chain bootstrapped...");
12823+
12824+
btcd_controller
12825+
.stop_bitcoind()
12826+
.expect("Failed to stop bitcoind");
12827+
12828+
thread::sleep(Duration::from_secs(5));
12829+
12830+
btcd_controller
12831+
.start_bitcoind()
12832+
.expect("Failed to start bitcoind");
12833+
12834+
btcd_controller
12835+
.stop_bitcoind()
12836+
.expect("Failed to stop bitcoind");
12837+
}

0 commit comments

Comments
 (0)