From 1e3df6b0e4d97135cefe71023a2195de0dceffdb Mon Sep 17 00:00:00 2001 From: Daniela Brozzoni Date: Thu, 28 Jul 2022 10:56:29 +0200 Subject: [PATCH] rpc: manually add the immature utxos to the db Before this commit, the rpc backend wouldn't notice the immature utxos (listunspent doesn't return them), making the rpc balance different from the other backend's balance. --- src/blockchain/rpc.rs | 39 ++++++++++++++++++++++++++++--- src/testutils/blockchain_tests.rs | 8 ------- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/blockchain/rpc.rs b/src/blockchain/rpc.rs index 1d0d884c0..9925468a0 100644 --- a/src/blockchain/rpc.rs +++ b/src/blockchain/rpc.rs @@ -39,8 +39,9 @@ use crate::database::{BatchDatabase, DatabaseUtils}; use crate::descriptor::get_checksum; use crate::{BlockTime, Error, FeeRate, KeychainKind, LocalUtxo, TransactionDetails}; use bitcoincore_rpc::json::{ - GetAddressInfoResultLabel, ImportMultiOptions, ImportMultiRequest, - ImportMultiRequestScriptPubkey, ImportMultiRescanSince, + GetAddressInfoResultLabel, GetTransactionResultDetailCategory, ImportMultiOptions, + ImportMultiRequest, ImportMultiRequestScriptPubkey, ImportMultiRescanSince, + ListUnspentResultEntry, }; use bitcoincore_rpc::jsonrpc::serde_json::{json, Value}; use bitcoincore_rpc::Auth as RpcAuth; @@ -276,7 +277,7 @@ impl WalletSync for RpcBlockchain { let known_utxos: HashSet<_> = db.iter_utxos()?.into_iter().collect(); //TODO list_since_blocks would be more efficient - let current_utxo = self + let mut current_utxo = self .client .list_unspent(Some(0), None, None, Some(true), None)?; debug!("current_utxo len {}", current_utxo.len()); @@ -294,6 +295,38 @@ impl WalletSync for RpcBlockchain { }) { let txid = tx_result.info.txid; list_txs_ids.insert(txid); + if tx_result.detail.category == GetTransactionResultDetailCategory::Immature { + // Immature UTXOs don't appear in rpc's listunspent, so we + // have to manually add them to the current_utxos list + // FIXME: This will produce a wrong result if the immature utxo is spent, + // which *should* be impossible. + let utxo = ListUnspentResultEntry { + txid: tx_result.info.txid, + vout: tx_result.detail.vout, + amount: tx_result + .detail + .amount + .to_unsigned() + .expect("immature txs amount can't be negative"), + script_pub_key: tx_result + .detail + .address + .as_ref() + .expect("Should always be here") + .script_pubkey(), + // We don't care about those other fields, we set them to their default + address: None, + confirmations: 0, + descriptor: None, + label: None, + redeem_script: None, + witness_script: None, + safe: true, + solvable: true, + spendable: true, + }; + current_utxo.push(utxo); + } if let Some(mut known_tx) = known_txs.get_mut(&txid) { let confirmation_time = BlockTime::new(tx_result.info.blockheight, tx_result.info.blocktime); diff --git a/src/testutils/blockchain_tests.rs b/src/testutils/blockchain_tests.rs index 89e091335..d1aefebeb 100644 --- a/src/testutils/blockchain_tests.rs +++ b/src/testutils/blockchain_tests.rs @@ -1063,14 +1063,6 @@ macro_rules! bdk_blockchain_tests { test_client.generate(1, Some(wallet_addr)); - #[cfg(feature = "rpc")] - { - // rpc consider coinbase only when mature (100 blocks) - let node_addr = test_client.get_node_address(None); - test_client.generate(100, Some(node_addr)); - } - - wallet.sync(&blockchain, SyncOptions::default()).unwrap(); assert!(wallet.get_balance().unwrap() > 0, "incorrect balance after receiving coinbase"); }