diff --git a/bindings/ldk_node.udl b/bindings/ldk_node.udl index c881dbe09..4c7311a53 100644 --- a/bindings/ldk_node.udl +++ b/bindings/ldk_node.udl @@ -119,6 +119,7 @@ interface Builder { void set_node_alias(string node_alias); [Throws=BuildError] void set_async_payments_role(AsyncPaymentsRole? role); + void set_wallet_recovery_mode(); [Throws=BuildError] Node build(NodeEntropy node_entropy); [Throws=BuildError] diff --git a/src/builder.rs b/src/builder.rs index 0e8e8c166..a7328f1b0 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -241,6 +241,7 @@ pub struct NodeBuilder { async_payments_role: Option, runtime_handle: Option, pathfinding_scores_sync_config: Option, + recovery_mode: bool, } impl NodeBuilder { @@ -258,6 +259,7 @@ impl NodeBuilder { let log_writer_config = None; let runtime_handle = None; let pathfinding_scores_sync_config = None; + let recovery_mode = false; Self { config, chain_data_source_config, @@ -267,6 +269,7 @@ impl NodeBuilder { runtime_handle, async_payments_role: None, pathfinding_scores_sync_config, + recovery_mode, } } @@ -541,6 +544,16 @@ impl NodeBuilder { Ok(self) } + /// Configures the [`Node`] to resync chain data from genesis on first startup, recovering any + /// historical wallet funds. + /// + /// This should only be set on first startup when importing an older wallet from a previously + /// used [`NodeEntropy`]. + pub fn set_wallet_recovery_mode(&mut self) -> &mut Self { + self.recovery_mode = true; + self + } + /// Builds a [`Node`] instance with a [`SqliteStore`] backend and according to the options /// previously configured. pub fn build(&self, node_entropy: NodeEntropy) -> Result { @@ -676,6 +689,7 @@ impl NodeBuilder { self.liquidity_source_config.as_ref(), self.pathfinding_scores_sync_config.as_ref(), self.async_payments_role, + self.recovery_mode, seed_bytes, runtime, logger, @@ -916,6 +930,15 @@ impl ArcedNodeBuilder { self.inner.write().unwrap().set_async_payments_role(role).map(|_| ()) } + /// Configures the [`Node`] to resync chain data from genesis on first startup, recovering any + /// historical wallet funds. + /// + /// This should only be set on first startup when importing an older wallet from a previously + /// used [`NodeEntropy`]. + pub fn set_wallet_recovery_mode(&self) { + self.inner.write().unwrap().set_wallet_recovery_mode(); + } + /// Builds a [`Node`] instance with a [`SqliteStore`] backend and according to the options /// previously configured. pub fn build(&self, node_entropy: Arc) -> Result, BuildError> { @@ -1030,8 +1053,8 @@ fn build_with_store_internal( gossip_source_config: Option<&GossipSourceConfig>, liquidity_source_config: Option<&LiquiditySourceConfig>, pathfinding_scores_sync_config: Option<&PathfindingScoresSyncConfig>, - async_payments_role: Option, seed_bytes: [u8; 64], runtime: Arc, - logger: Arc, kv_store: Arc, + async_payments_role: Option, recovery_mode: bool, seed_bytes: [u8; 64], + runtime: Arc, logger: Arc, kv_store: Arc, ) -> Result { optionally_install_rustls_cryptoprovider(); @@ -1225,19 +1248,23 @@ fn build_with_store_internal( BuildError::WalletSetupFailed })?; - if let Some(best_block) = chain_tip_opt { - // Insert the first checkpoint if we have it, to avoid resyncing from genesis. - // TODO: Use a proper wallet birthday once BDK supports it. - let mut latest_checkpoint = wallet.latest_checkpoint(); - let block_id = - bdk_chain::BlockId { height: best_block.height, hash: best_block.block_hash }; - latest_checkpoint = latest_checkpoint.insert(block_id); - let update = - bdk_wallet::Update { chain: Some(latest_checkpoint), ..Default::default() }; - wallet.apply_update(update).map_err(|e| { - log_error!(logger, "Failed to apply checkpoint during wallet setup: {}", e); - BuildError::WalletSetupFailed - })?; + if !recovery_mode { + if let Some(best_block) = chain_tip_opt { + // Insert the first checkpoint if we have it, to avoid resyncing from genesis. + // TODO: Use a proper wallet birthday once BDK supports it. + let mut latest_checkpoint = wallet.latest_checkpoint(); + let block_id = bdk_chain::BlockId { + height: best_block.height, + hash: best_block.block_hash, + }; + latest_checkpoint = latest_checkpoint.insert(block_id); + let update = + bdk_wallet::Update { chain: Some(latest_checkpoint), ..Default::default() }; + wallet.apply_update(update).map_err(|e| { + log_error!(logger, "Failed to apply checkpoint during wallet setup: {}", e); + BuildError::WalletSetupFailed + })?; + } } wallet }, diff --git a/src/wallet/mod.rs b/src/wallet/mod.rs index 5fd7b3d8e..7d1e41c45 100644 --- a/src/wallet/mod.rs +++ b/src/wallet/mod.rs @@ -139,6 +139,10 @@ impl Wallet { pub(crate) fn apply_mempool_txs( &self, unconfirmed_txs: Vec<(Transaction, u64)>, evicted_txids: Vec<(Txid, u64)>, ) -> Result<(), Error> { + if unconfirmed_txs.is_empty() { + return Ok(()); + } + let mut locked_wallet = self.inner.lock().unwrap(); locked_wallet.apply_unconfirmed_txs(unconfirmed_txs); locked_wallet.apply_evicted_txs(evicted_txids); @@ -149,6 +153,11 @@ impl Wallet { Error::PersistenceFailed })?; + self.update_payment_store(&mut *locked_wallet).map_err(|e| { + log_error!(self.logger, "Failed to update payment store: {}", e); + Error::PersistenceFailed + })?; + Ok(()) } diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 96f58297c..f2127d526 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -206,6 +206,31 @@ pub(crate) fn setup_bitcoind_and_electrsd() -> (BitcoinD, ElectrsD) { (bitcoind, electrsd) } +pub(crate) fn random_chain_source<'a>( + bitcoind: &'a BitcoinD, electrsd: &'a ElectrsD, +) -> TestChainSource<'a> { + let r = rand::random_range(0..3); + match r { + 0 => { + println!("Randomly setting up Esplora chain syncing..."); + TestChainSource::Esplora(electrsd) + }, + 1 => { + println!("Randomly setting up Electrum chain syncing..."); + TestChainSource::Electrum(electrsd) + }, + 2 => { + println!("Randomly setting up Bitcoind RPC chain syncing..."); + TestChainSource::BitcoindRpcSync(bitcoind) + }, + 3 => { + println!("Randomly setting up Bitcoind REST chain syncing..."); + TestChainSource::BitcoindRestSync(bitcoind) + }, + _ => unreachable!(), + } +} + pub(crate) fn random_storage_path() -> PathBuf { let mut temp_path = std::env::temp_dir(); let mut rng = rng(); @@ -292,6 +317,8 @@ pub(crate) struct TestConfig { pub log_writer: TestLogWriter, pub store_type: TestStoreType, pub node_entropy: NodeEntropy, + pub async_payments_role: Option, + pub recovery_mode: bool, } impl Default for TestConfig { @@ -302,7 +329,16 @@ impl Default for TestConfig { let mnemonic = generate_entropy_mnemonic(None); let node_entropy = NodeEntropy::from_bip39_mnemonic(mnemonic, None); - TestConfig { node_config, log_writer, store_type, node_entropy } + let async_payments_role = None; + let recovery_mode = false; + TestConfig { + node_config, + log_writer, + store_type, + node_entropy, + async_payments_role, + recovery_mode, + } } } @@ -359,13 +395,6 @@ pub(crate) fn setup_two_nodes_with_store( } pub(crate) fn setup_node(chain_source: &TestChainSource, config: TestConfig) -> TestNode { - setup_node_for_async_payments(chain_source, config, None) -} - -pub(crate) fn setup_node_for_async_payments( - chain_source: &TestChainSource, config: TestConfig, - async_payments_role: Option, -) -> TestNode { setup_builder!(builder, config.node_config); match chain_source { TestChainSource::Esplora(electrsd) => { @@ -417,7 +446,11 @@ pub(crate) fn setup_node_for_async_payments( }, } - builder.set_async_payments_role(async_payments_role).unwrap(); + builder.set_async_payments_role(config.async_payments_role).unwrap(); + + if config.recovery_mode { + builder.set_wallet_recovery_mode(); + } let node = match config.store_type { TestStoreType::TestSyncStore => { @@ -427,6 +460,10 @@ pub(crate) fn setup_node_for_async_payments( TestStoreType::Sqlite => builder.build(config.node_entropy.into()).unwrap(), }; + if config.recovery_mode { + builder.set_wallet_recovery_mode(); + } + node.start().unwrap(); assert!(node.status().is_running); assert!(node.status().latest_fee_rate_cache_update_timestamp.is_some()); diff --git a/tests/integration_tests_rust.rs b/tests/integration_tests_rust.rs index 4e94dd044..bb1e11fdb 100644 --- a/tests/integration_tests_rust.rs +++ b/tests/integration_tests_rust.rs @@ -21,10 +21,9 @@ use common::{ expect_channel_pending_event, expect_channel_ready_event, expect_event, expect_payment_claimable_event, expect_payment_received_event, expect_payment_successful_event, expect_splice_pending_event, generate_blocks_and_wait, open_channel, open_channel_push_amt, - premine_and_distribute_funds, premine_blocks, prepare_rbf, random_config, + premine_and_distribute_funds, premine_blocks, prepare_rbf, random_chain_source, random_config, random_listening_addresses, setup_bitcoind_and_electrsd, setup_builder, setup_node, - setup_node_for_async_payments, setup_two_nodes, wait_for_tx, TestChainSource, TestStoreType, - TestSyncStore, + setup_two_nodes, wait_for_tx, TestChainSource, TestStoreType, TestSyncStore, }; use ldk_node::config::{AsyncPaymentsRole, EsploraSyncConfig}; use ldk_node::entropy::NodeEntropy; @@ -44,34 +43,7 @@ use log::LevelFilter; #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn channel_full_cycle() { let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); - let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false); - do_channel_full_cycle(node_a, node_b, &bitcoind.client, &electrsd.client, false, true, false) - .await; -} - -#[tokio::test(flavor = "multi_thread", worker_threads = 1)] -async fn channel_full_cycle_electrum() { - let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Electrum(&electrsd); - let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false); - do_channel_full_cycle(node_a, node_b, &bitcoind.client, &electrsd.client, false, true, false) - .await; -} - -#[tokio::test(flavor = "multi_thread", worker_threads = 1)] -async fn channel_full_cycle_bitcoind_rpc_sync() { - let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::BitcoindRpcSync(&bitcoind); - let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false); - do_channel_full_cycle(node_a, node_b, &bitcoind.client, &electrsd.client, false, true, false) - .await; -} - -#[tokio::test(flavor = "multi_thread", worker_threads = 1)] -async fn channel_full_cycle_bitcoind_rest_sync() { - let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::BitcoindRestSync(&bitcoind); + let chain_source = random_chain_source(&bitcoind, &electrsd); let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false); do_channel_full_cycle(node_a, node_b, &bitcoind.client, &electrsd.client, false, true, false) .await; @@ -80,7 +52,7 @@ async fn channel_full_cycle_bitcoind_rest_sync() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn channel_full_cycle_force_close() { let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let chain_source = random_chain_source(&bitcoind, &electrsd); let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false); do_channel_full_cycle(node_a, node_b, &bitcoind.client, &electrsd.client, false, true, true) .await; @@ -89,7 +61,7 @@ async fn channel_full_cycle_force_close() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn channel_full_cycle_force_close_trusted_no_reserve() { let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let chain_source = random_chain_source(&bitcoind, &electrsd); let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, true); do_channel_full_cycle(node_a, node_b, &bitcoind.client, &electrsd.client, false, true, true) .await; @@ -98,7 +70,7 @@ async fn channel_full_cycle_force_close_trusted_no_reserve() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn channel_full_cycle_0conf() { let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let chain_source = random_chain_source(&bitcoind, &electrsd); let (node_a, node_b) = setup_two_nodes(&chain_source, true, true, false); do_channel_full_cycle(node_a, node_b, &bitcoind.client, &electrsd.client, true, true, false) .await; @@ -107,7 +79,7 @@ async fn channel_full_cycle_0conf() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn channel_full_cycle_legacy_staticremotekey() { let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let chain_source = random_chain_source(&bitcoind, &electrsd); let (node_a, node_b) = setup_two_nodes(&chain_source, false, false, false); do_channel_full_cycle(node_a, node_b, &bitcoind.client, &electrsd.client, false, false, false) .await; @@ -116,7 +88,7 @@ async fn channel_full_cycle_legacy_staticremotekey() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn channel_open_fails_when_funds_insufficient() { let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let chain_source = random_chain_source(&bitcoind, &electrsd); let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false); let addr_a = node_a.onchain_payment().new_address().unwrap(); @@ -321,7 +293,7 @@ async fn start_stop_reinit() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn onchain_send_receive() { let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let chain_source = random_chain_source(&bitcoind, &electrsd); let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false); let addr_a = node_a.onchain_payment().new_address().unwrap(); @@ -522,7 +494,7 @@ async fn onchain_send_receive() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn onchain_send_all_retains_reserve() { let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let chain_source = random_chain_source(&bitcoind, &electrsd); let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false); // Setup nodes @@ -607,7 +579,7 @@ async fn onchain_send_all_retains_reserve() { async fn onchain_wallet_recovery() { let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let chain_source = random_chain_source(&bitcoind, &electrsd); let original_config = random_config(true); let original_node_entropy = original_config.node_entropy; @@ -652,6 +624,7 @@ async fn onchain_wallet_recovery() { // Now we start from scratch, only the seed remains the same. let mut recovered_config = random_config(true); recovered_config.node_entropy = original_node_entropy; + recovered_config.recovery_mode = true; let recovered_node = setup_node(&chain_source, recovered_config); recovered_node.sync_wallets().unwrap(); @@ -822,9 +795,9 @@ async fn run_rbf_test(is_insert_block: bool) { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn sign_verify_msg() { - let (_bitcoind, electrsd) = setup_bitcoind_and_electrsd(); + let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); let config = random_config(true); - let chain_source = TestChainSource::Esplora(&electrsd); + let chain_source = random_chain_source(&bitcoind, &electrsd); let node = setup_node(&chain_source, config); // Tests arbitrary message signing and later verification @@ -836,8 +809,8 @@ async fn sign_verify_msg() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn connection_multi_listen() { - let (_bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); + let chain_source = random_chain_source(&bitcoind, &electrsd); let (node_a, node_b) = setup_two_nodes(&chain_source, false, false, false); let node_id_b = node_b.node_id(); @@ -856,8 +829,8 @@ async fn connection_restart_behavior() { } async fn do_connection_restart_behavior(persist: bool) { - let (_bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); + let chain_source = random_chain_source(&bitcoind, &electrsd); let (node_a, node_b) = setup_two_nodes(&chain_source, false, false, false); let node_id_a = node_a.node_id(); @@ -903,8 +876,8 @@ async fn do_connection_restart_behavior(persist: bool) { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn concurrent_connections_succeed() { - let (_bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); + let chain_source = random_chain_source(&bitcoind, &electrsd); let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false); let node_a = Arc::new(node_a); @@ -1079,7 +1052,7 @@ async fn splice_channel() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn simple_bolt12_send_receive() { let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let chain_source = random_chain_source(&bitcoind, &electrsd); let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false); let address_a = node_a.onchain_payment().new_address().unwrap(); @@ -1308,37 +1281,28 @@ async fn simple_bolt12_send_receive() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn async_payment() { let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let chain_source = random_chain_source(&bitcoind, &electrsd); let mut config_sender = random_config(true); config_sender.node_config.listening_addresses = None; config_sender.node_config.node_alias = None; config_sender.log_writer = TestLogWriter::Custom(Arc::new(MultiNodeLogger::new("sender ".to_string()))); - let node_sender = setup_node_for_async_payments( - &chain_source, - config_sender, - Some(AsyncPaymentsRole::Client), - ); + config_sender.async_payments_role = Some(AsyncPaymentsRole::Client); + let node_sender = setup_node(&chain_source, config_sender); let mut config_sender_lsp = random_config(true); config_sender_lsp.log_writer = TestLogWriter::Custom(Arc::new(MultiNodeLogger::new("sender_lsp ".to_string()))); - let node_sender_lsp = setup_node_for_async_payments( - &chain_source, - config_sender_lsp, - Some(AsyncPaymentsRole::Server), - ); + config_sender_lsp.async_payments_role = Some(AsyncPaymentsRole::Server); + let node_sender_lsp = setup_node(&chain_source, config_sender_lsp); let mut config_receiver_lsp = random_config(true); config_receiver_lsp.log_writer = TestLogWriter::Custom(Arc::new(MultiNodeLogger::new("receiver_lsp".to_string()))); + config_receiver_lsp.async_payments_role = Some(AsyncPaymentsRole::Server); - let node_receiver_lsp = setup_node_for_async_payments( - &chain_source, - config_receiver_lsp, - Some(AsyncPaymentsRole::Server), - ); + let node_receiver_lsp = setup_node(&chain_source, config_receiver_lsp); let mut config_receiver = random_config(true); config_receiver.node_config.listening_addresses = None; @@ -1443,7 +1407,7 @@ async fn async_payment() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn test_node_announcement_propagation() { let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let chain_source = random_chain_source(&bitcoind, &electrsd); // Node A will use both listening and announcement addresses let mut config_a = random_config(true); @@ -1535,7 +1499,7 @@ async fn test_node_announcement_propagation() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn generate_bip21_uri() { let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let chain_source = random_chain_source(&bitcoind, &electrsd); let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false); @@ -1590,7 +1554,7 @@ async fn generate_bip21_uri() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn unified_send_receive_bip21_uri() { let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let chain_source = random_chain_source(&bitcoind, &electrsd); let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false); @@ -1928,8 +1892,8 @@ async fn do_lsps2_client_service_integration(client_trusts_lsp: bool) { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn facade_logging() { - let (_bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); + let chain_source = random_chain_source(&bitcoind, &electrsd); let logger = init_log_logger(LevelFilter::Trace); let mut config = random_config(false); @@ -1947,7 +1911,7 @@ async fn facade_logging() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn spontaneous_send_with_custom_preimage() { let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let chain_source = random_chain_source(&bitcoind, &electrsd); let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false); let address_a = node_a.onchain_payment().new_address().unwrap(); @@ -2013,8 +1977,8 @@ async fn spontaneous_send_with_custom_preimage() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn drop_in_async_context() { - let (_bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); + let chain_source = random_chain_source(&bitcoind, &electrsd); let config = random_config(true); let node = setup_node(&chain_source, config); node.stop().unwrap(); @@ -2323,7 +2287,7 @@ async fn lsps2_lsp_trusts_client_but_client_does_not_claim() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn payment_persistence_after_restart() { let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); - let chain_source = TestChainSource::Esplora(&electrsd); + let chain_source = random_chain_source(&bitcoind, &electrsd); // Setup nodes manually so we can restart node_a with the same config println!("== Node A ==");