diff --git a/Cargo.lock b/Cargo.lock --- a/Cargo.lock +++ b/Cargo.lock @@ -323,6 +323,7 @@ "axum", "bitcoinsuite-core", "bitcoinsuite-slp", + "chronik-bridge", "chronik-db", "chronik-indexer", "chronik-proto", diff --git a/chronik/chronik-bridge/src/ffi.rs b/chronik/chronik-bridge/src/ffi.rs --- a/chronik/chronik-bridge/src/ffi.rs +++ b/chronik/chronik-bridge/src/ffi.rs @@ -283,6 +283,10 @@ /// Default maximum fee rate when broadcasting txs. fn default_max_raw_tx_fee_rate_per_kb() -> i64; + /// Calls `SyncWithValidationInterfaceQueue` from validationinterface.h + /// to make sure wallet/indexes are synced. + fn sync_with_validation_interface_queue(); + /// Calls `InitError` from `node/ui_interface.h` to report an error to /// the user and then gracefully shut down the node. fn init_error(msg: &str) -> bool; diff --git a/chronik/chronik-cpp/chronik_bridge.h b/chronik/chronik-cpp/chronik_bridge.h --- a/chronik/chronik-cpp/chronik_bridge.h +++ b/chronik/chronik-cpp/chronik_bridge.h @@ -95,6 +95,8 @@ int64_t default_max_raw_tx_fee_rate_per_kb(); +void sync_with_validation_interface_queue(); + bool init_error(const rust::Str msg); void abort_node(const rust::Str msg, const rust::Str user_msg); diff --git a/chronik/chronik-cpp/chronik_bridge.cpp b/chronik/chronik-cpp/chronik_bridge.cpp --- a/chronik/chronik-cpp/chronik_bridge.cpp +++ b/chronik/chronik-cpp/chronik_bridge.cpp @@ -22,6 +22,7 @@ #include #include #include +#include chronik_bridge::OutPoint BridgeOutPoint(const COutPoint &outpoint) { return { @@ -361,6 +362,10 @@ return node::DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK() / SATOSHI; } +void sync_with_validation_interface_queue() { + SyncWithValidationInterfaceQueue(); +} + bool init_error(const rust::Str msg) { return InitError(Untranslated(std::string(msg))); } diff --git a/chronik/chronik-http/Cargo.toml b/chronik/chronik-http/Cargo.toml --- a/chronik/chronik-http/Cargo.toml +++ b/chronik/chronik-http/Cargo.toml @@ -14,6 +14,7 @@ bitcoinsuite-core = { path = "../bitcoinsuite-core" } bitcoinsuite-slp = { path = "../bitcoinsuite-slp" } +chronik-bridge = { path = "../chronik-bridge" } chronik-db = { path = "../chronik-db" } chronik-indexer = { path = "../chronik-indexer" } chronik-proto = { path = "../chronik-proto" } diff --git a/chronik/chronik-http/src/server.rs b/chronik/chronik-http/src/server.rs --- a/chronik/chronik-http/src/server.rs +++ b/chronik/chronik-http/src/server.rs @@ -16,6 +16,7 @@ Extension, Router, }; use bitcoinsuite_core::tx::TxId; +use chronik_bridge::ffi; use chronik_indexer::{ indexer::{ChronikIndexer, Node}, pause::PauseNotify, @@ -287,9 +288,15 @@ Protobuf(request): Protobuf, ) -> Result, ReportError> { let indexer = indexer.read().await; - let txids = indexer + let txids_result = indexer .broadcast(node.as_ref()) - .broadcast_txs(&[request.raw_tx.into()], request.skip_token_checks)?; + .broadcast_txs(&[request.raw_tx.into()], request.skip_token_checks); + // Drop indexer before syncing otherwise we get a deadlock + drop(indexer); + // Block for indexer being synced before returning so the user can query + // the broadcast txs right away + ffi::sync_with_validation_interface_queue(); + let txids = txids_result?; Ok(Protobuf(proto::BroadcastTxResponse { txid: txids[0].to_vec(), })) @@ -301,14 +308,20 @@ Protobuf(request): Protobuf, ) -> Result, ReportError> { let indexer = indexer.read().await; - let txids = indexer.broadcast(node.as_ref()).broadcast_txs( + let txids_result = indexer.broadcast(node.as_ref()).broadcast_txs( &request .raw_txs .into_iter() .map(Into::into) .collect::>(), request.skip_token_checks, - )?; + ); + // Drop indexer before syncing otherwise we get a deadlock + drop(indexer); + // Block for indexer being synced before returning so the user can query + // the broadcast txs right away + ffi::sync_with_validation_interface_queue(); + let txids = txids_result?; Ok(Protobuf(proto::BroadcastTxsResponse { txids: txids.into_iter().map(|txid| txid.to_vec()).collect(), }))