From 035307ef54ebc330b1760bbdd17bdab3b167cfeb Mon Sep 17 00:00:00 2001 From: LLFourn Date: Thu, 24 Feb 2022 20:32:47 +1100 Subject: [PATCH] [rpc] Filter out unrelated transactions For some reason while doing the "remove blockchain from wallet PR" I changed the tests around in what I thought was a benign way. But it meant (apparently) that both parties "test_sync_double_receive" were using the same "blockchain". This meant that when the blockchain was RPC they both imported their addresses to it and got each other's results when syncing. This bugged out the sync and this commit fixes that. --- src/blockchain/rpc.rs | 32 ++++++++++++++++--------------- src/testutils/blockchain_tests.rs | 20 +++++++++---------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/blockchain/rpc.rs b/src/blockchain/rpc.rs index a474a0e2..e4a79846 100644 --- a/src/blockchain/rpc.rs +++ b/src/blockchain/rpc.rs @@ -318,22 +318,24 @@ impl WalletSync for RpcBlockchain { } } - let current_utxos: HashSet<_> = current_utxo + // Filter out trasactions that are for script pubkeys that aren't in this wallet. + let current_utxos = current_utxo .into_iter() - .map(|u| { - Ok(LocalUtxo { - outpoint: OutPoint::new(u.txid, u.vout), - keychain: db - .get_path_from_script_pubkey(&u.script_pub_key)? - .ok_or(Error::TransactionNotFound)? - .0, - txout: TxOut { - value: u.amount.as_sat(), - script_pubkey: u.script_pub_key, - }, - }) - }) - .collect::>()?; + .filter_map( + |u| match db.get_path_from_script_pubkey(&u.script_pub_key) { + Err(e) => Some(Err(e)), + Ok(None) => None, + Ok(Some(path)) => Some(Ok(LocalUtxo { + outpoint: OutPoint::new(u.txid, u.vout), + keychain: path.0, + txout: TxOut { + value: u.amount.as_sat(), + script_pubkey: u.script_pub_key, + }, + })), + }, + ) + .collect::, Error>>()?; let spent: HashSet<_> = known_utxos.difference(¤t_utxos).collect(); for s in spent { diff --git a/src/testutils/blockchain_tests.rs b/src/testutils/blockchain_tests.rs index eefdd75b..b54da105 100644 --- a/src/testutils/blockchain_tests.rs +++ b/src/testutils/blockchain_tests.rs @@ -621,7 +621,7 @@ macro_rules! bdk_blockchain_tests { #[test] fn test_sync_double_receive() { let (wallet, blockchain, descriptors, mut test_client) = init_single_sig(); - let receiver_wallet = get_wallet_from_descriptors(&("wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)".to_string(), None)); + let receiver_wallet = get_wallet_from_descriptors(&("wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)".to_string(), None)); // need to sync so rpc can start watching receiver_wallet.sync(&blockchain, SyncOptions::default()).unwrap(); @@ -629,15 +629,15 @@ macro_rules! bdk_blockchain_tests { @tx ( (@external descriptors, 0) => 50_000, (@external descriptors, 1) => 25_000 ) (@confirmations 1) }); - wallet.sync(&blockchain, SyncOptions::default()).unwrap(); + wallet.sync(&blockchain, SyncOptions::default()).expect("sync"); assert_eq!(wallet.get_balance().unwrap(), 75_000, "incorrect balance"); let target_addr = receiver_wallet.get_address($crate::wallet::AddressIndex::New).unwrap().address; let tx1 = { let mut builder = wallet.build_tx(); builder.add_recipient(target_addr.script_pubkey(), 49_000).enable_rbf(); - let (mut psbt, _details) = builder.finish().unwrap(); - let finalized = wallet.sign(&mut psbt, Default::default()).unwrap(); + let (mut psbt, _details) = builder.finish().expect("building first tx"); + let finalized = wallet.sign(&mut psbt, Default::default()).expect("signing first tx"); assert!(finalized, "Cannot finalize transaction"); psbt.extract_tx() }; @@ -645,17 +645,17 @@ macro_rules! bdk_blockchain_tests { let tx2 = { let mut builder = wallet.build_tx(); builder.add_recipient(target_addr.script_pubkey(), 49_000).enable_rbf().fee_rate(FeeRate::from_sat_per_vb(5.0)); - let (mut psbt, _details) = builder.finish().unwrap(); - let finalized = wallet.sign(&mut psbt, Default::default()).unwrap(); + let (mut psbt, _details) = builder.finish().expect("building replacement tx"); + let finalized = wallet.sign(&mut psbt, Default::default()).expect("signing replacement tx"); assert!(finalized, "Cannot finalize transaction"); psbt.extract_tx() }; - blockchain.broadcast(&tx1).unwrap(); - blockchain.broadcast(&tx2).unwrap(); + blockchain.broadcast(&tx1).expect("broadcasting first"); + blockchain.broadcast(&tx2).expect("broadcasting replacement"); - receiver_wallet.sync(&blockchain, SyncOptions::default()).unwrap(); - assert_eq!(receiver_wallet.get_balance().unwrap(), 49_000, "should have received coins once and only once"); + receiver_wallet.sync(&blockchain, SyncOptions::default()).expect("syncing receiver"); + assert_eq!(receiver_wallet.get_balance().expect("balance"), 49_000, "should have received coins once and only once"); } #[test]