Skip to content

Commit 9b4c1b5

Browse files
Fix RPC Txid handling and mempool eviction
- Replace `bitcoin::consensus::encode::deserialize_hex()` with `hex_str.parse::<Txid>()` when parsing Txids from RPC, and `serialize_hex()` with `txid.to_string()` when sending to RPC, ensuring proper handling of Bitcoin Core's reversed-byte hexadecimal format. - Fix mempool eviction logic: transactions that are no longer in the mempool are now correctly removed from wallet consideration, preventing stale pending transactions from inflating unconfirmed balances.
1 parent 86cc3d2 commit 9b4c1b5

File tree

1 file changed

+18
-14
lines changed

1 file changed

+18
-14
lines changed

src/chain/bitcoind.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -370,8 +370,11 @@ impl BitcoindChainSource {
370370
let cur_height = channel_manager.current_best_block().height;
371371

372372
let now = SystemTime::now();
373-
let unconfirmed_txids = self.onchain_wallet.get_unconfirmed_txids();
374-
match self.api_client.get_updated_mempool_transactions(cur_height, unconfirmed_txids).await
373+
let bdk_unconfirmed_txids = self.onchain_wallet.get_unconfirmed_txids();
374+
match self
375+
.api_client
376+
.get_updated_mempool_transactions(cur_height, bdk_unconfirmed_txids)
377+
.await
375378
{
376379
Ok((unconfirmed_txs, evicted_txids)) => {
377380
log_trace!(
@@ -754,7 +757,7 @@ impl BitcoindClient {
754757
async fn get_raw_transaction_rpc(
755758
rpc_client: Arc<RpcClient>, txid: &Txid,
756759
) -> std::io::Result<Option<Transaction>> {
757-
let txid_hex = bitcoin::consensus::encode::serialize_hex(txid);
760+
let txid_hex = txid.to_string();
758761
let txid_json = serde_json::json!(txid_hex);
759762
match rpc_client
760763
.call_method::<GetRawTransactionResponse>("getrawtransaction", &[txid_json])
@@ -792,7 +795,7 @@ impl BitcoindClient {
792795
async fn get_raw_transaction_rest(
793796
rest_client: Arc<RestClient>, txid: &Txid,
794797
) -> std::io::Result<Option<Transaction>> {
795-
let txid_hex = bitcoin::consensus::encode::serialize_hex(txid);
798+
let txid_hex = txid.to_string();
796799
let tx_path = format!("tx/{}.json", txid_hex);
797800
match rest_client
798801
.request_resource::<JsonResponse, GetRawTransactionResponse>(&tx_path)
@@ -889,7 +892,7 @@ impl BitcoindClient {
889892
async fn get_mempool_entry_inner(
890893
client: Arc<RpcClient>, txid: Txid,
891894
) -> std::io::Result<Option<MempoolEntry>> {
892-
let txid_hex = bitcoin::consensus::encode::serialize_hex(&txid);
895+
let txid_hex = txid.to_string();
893896
let txid_json = serde_json::json!(txid_hex);
894897

895898
match client.call_method::<GetMempoolEntryResponse>("getmempoolentry", &[txid_json]).await {
@@ -964,11 +967,12 @@ impl BitcoindClient {
964967
/// - mempool transactions, alongside their first-seen unix timestamps.
965968
/// - transactions that have been evicted from the mempool, alongside the last time they were seen absent.
966969
pub(crate) async fn get_updated_mempool_transactions(
967-
&self, best_processed_height: u32, unconfirmed_txids: Vec<Txid>,
970+
&self, best_processed_height: u32, bdk_unconfirmed_txids: Vec<Txid>,
968971
) -> std::io::Result<(Vec<(Transaction, u64)>, Vec<(Txid, u64)>)> {
969972
let mempool_txs =
970973
self.get_mempool_transactions_and_timestamp_at_height(best_processed_height).await?;
971-
let evicted_txids = self.get_evicted_mempool_txids_and_timestamp(unconfirmed_txids).await?;
974+
let evicted_txids =
975+
self.get_evicted_mempool_txids_and_timestamp(bdk_unconfirmed_txids).await?;
972976
Ok((mempool_txs, evicted_txids))
973977
}
974978

@@ -1078,22 +1082,22 @@ impl BitcoindClient {
10781082
// To this end, we first update our local mempool_entries_cache and then return all unconfirmed
10791083
// wallet `Txid`s that don't appear in the mempool still.
10801084
async fn get_evicted_mempool_txids_and_timestamp(
1081-
&self, unconfirmed_txids: Vec<Txid>,
1085+
&self, bdk_unconfirmed_txids: Vec<Txid>,
10821086
) -> std::io::Result<Vec<(Txid, u64)>> {
10831087
match self {
10841088
BitcoindClient::Rpc { latest_mempool_timestamp, mempool_entries_cache, .. } => {
10851089
Self::get_evicted_mempool_txids_and_timestamp_inner(
10861090
latest_mempool_timestamp,
10871091
mempool_entries_cache,
1088-
unconfirmed_txids,
1092+
bdk_unconfirmed_txids,
10891093
)
10901094
.await
10911095
},
10921096
BitcoindClient::Rest { latest_mempool_timestamp, mempool_entries_cache, .. } => {
10931097
Self::get_evicted_mempool_txids_and_timestamp_inner(
10941098
latest_mempool_timestamp,
10951099
mempool_entries_cache,
1096-
unconfirmed_txids,
1100+
bdk_unconfirmed_txids,
10971101
)
10981102
.await
10991103
},
@@ -1103,13 +1107,13 @@ impl BitcoindClient {
11031107
async fn get_evicted_mempool_txids_and_timestamp_inner(
11041108
latest_mempool_timestamp: &AtomicU64,
11051109
mempool_entries_cache: &tokio::sync::Mutex<HashMap<Txid, MempoolEntry>>,
1106-
unconfirmed_txids: Vec<Txid>,
1110+
bdk_unconfirmed_txids: Vec<Txid>,
11071111
) -> std::io::Result<Vec<(Txid, u64)>> {
11081112
let latest_mempool_timestamp = latest_mempool_timestamp.load(Ordering::Relaxed);
11091113
let mempool_entries_cache = mempool_entries_cache.lock().await;
1110-
let evicted_txids = unconfirmed_txids
1114+
let evicted_txids = bdk_unconfirmed_txids
11111115
.into_iter()
1112-
.filter(|txid| mempool_entries_cache.contains_key(txid))
1116+
.filter(|txid| !mempool_entries_cache.contains_key(txid))
11131117
.map(|txid| (txid, latest_mempool_timestamp))
11141118
.collect();
11151119
Ok(evicted_txids)
@@ -1236,7 +1240,7 @@ impl TryInto<GetRawMempoolResponse> for JsonResponse {
12361240

12371241
for hex in res {
12381242
let txid = if let Some(hex_str) = hex.as_str() {
1239-
match bitcoin::consensus::encode::deserialize_hex(hex_str) {
1243+
match hex_str.parse::<Txid>() {
12401244
Ok(txid) => txid,
12411245
Err(_) => {
12421246
return Err(std::io::Error::new(

0 commit comments

Comments
 (0)