diff --git a/src/bitcoin/poller/mod.rs b/src/bitcoin/poller/mod.rs index e760f211b..8e9874e16 100644 --- a/src/bitcoin/poller/mod.rs +++ b/src/bitcoin/poller/mod.rs @@ -12,6 +12,9 @@ use miniscript::bitcoin::secp256k1; #[derive(Debug, Clone)] pub enum PollerMessage { Shutdown, + /// Ask the Bitcoin poller to poll immediately, get notified through the passed channel once + /// it's done. + PollNow(mpsc::SyncSender<()>), } /// The Bitcoin poller handler. @@ -84,6 +87,16 @@ impl Poller { log::info!("Bitcoin poller was told to shut down."); return; } + Ok(PollerMessage::PollNow(sender)) => { + // We've been asked to poll, don't wait any further and signal completion to + // the caller. + last_poll = Some(time::Instant::now()); + looper::poll(&self.bit, &self.db, &self.secp, &self.descs); + if let Err(e) = sender.send(()) { + log::error!("Error sending immediate poll completion signal: {}.", e); + } + continue; + } Err(mpsc::RecvTimeoutError::Timeout) => { // It's been long enough since the last poll. } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 25af70407..a77fb8d25 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -8,6 +8,7 @@ use crate::{ bitcoin::BitcoinInterface, database::{Coin, DatabaseConnection, DatabaseInterface}, descriptors, + poller::PollerMessage, spend::{ create_spend, AddrInfo, AncestorInfo, CandidateCoin, CreateSpendRes, SpendCreationError, SpendOutputAddress, SpendTxFees, TxGetter, @@ -24,7 +25,8 @@ use utils::{ use std::{ collections::{hash_map, HashMap, HashSet}, - fmt, sync, + fmt, + sync::{self, mpsc}, }; use miniscript::{ @@ -688,7 +690,18 @@ impl DaemonControl { let final_tx = spend_psbt.extract_tx_unchecked_fee_rate(); self.bitcoin .broadcast_tx(&final_tx) - .map_err(CommandError::TxBroadcast) + .map_err(CommandError::TxBroadcast)?; + + // Finally, update our state with the changes from this transaction. + let (tx, rx) = mpsc::sync_channel(0); + if let Err(e) = self.poller_sender.send(PollerMessage::PollNow(tx)) { + log::error!("Error requesting update from poller: {}", e); + } + if let Err(e) = rx.recv() { + log::error!("Error receiving completion signal from poller: {}", e); + } + + Ok(()) } /// Create PSBT to replace the given transaction using RBF. diff --git a/src/lib.rs b/src/lib.rs index d3a5222b1..0381f9f97 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -257,6 +257,7 @@ fn setup_bitcoind( pub struct DaemonControl { config: Config, bitcoin: sync::Arc>, + poller_sender: mpsc::SyncSender, // FIXME: Should we require Sync on DatabaseInterface rather than using a Mutex? db: sync::Arc>, secp: secp256k1::Secp256k1, @@ -266,12 +267,14 @@ impl DaemonControl { pub(crate) fn new( config: Config, bitcoin: sync::Arc>, + poller_sender: mpsc::SyncSender, db: sync::Arc>, secp: secp256k1::Secp256k1, ) -> DaemonControl { DaemonControl { config, bitcoin, + poller_sender, db, secp, } @@ -387,7 +390,7 @@ impl DaemonHandle { // Create the API the external world will use to talk to us, either directly through the Rust // structure or through the JSONRPC server we may setup below. - let control = DaemonControl::new(config, bit, db, secp); + let control = DaemonControl::new(config, bit, poller_sender.clone(), db, secp); Ok(if with_rpc_server { let rpcserver_shutdown = sync::Arc::from(sync::atomic::AtomicBool::from(false));