[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.
This commit is contained in:
LLFourn 2022-02-24 20:32:47 +11:00
parent c0e75fc1a8
commit 035307ef54
No known key found for this signature in database
GPG Key ID: A27093B54DA11F65
2 changed files with 27 additions and 25 deletions

View File

@ -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() .into_iter()
.map(|u| { .filter_map(
Ok(LocalUtxo { |u| match db.get_path_from_script_pubkey(&u.script_pub_key) {
outpoint: OutPoint::new(u.txid, u.vout), Err(e) => Some(Err(e)),
keychain: db Ok(None) => None,
.get_path_from_script_pubkey(&u.script_pub_key)? Ok(Some(path)) => Some(Ok(LocalUtxo {
.ok_or(Error::TransactionNotFound)? outpoint: OutPoint::new(u.txid, u.vout),
.0, keychain: path.0,
txout: TxOut { txout: TxOut {
value: u.amount.as_sat(), value: u.amount.as_sat(),
script_pubkey: u.script_pub_key, script_pubkey: u.script_pub_key,
}, },
}) })),
}) },
.collect::<Result<_, Error>>()?; )
.collect::<Result<HashSet<_>, Error>>()?;
let spent: HashSet<_> = known_utxos.difference(&current_utxos).collect(); let spent: HashSet<_> = known_utxos.difference(&current_utxos).collect();
for s in spent { for s in spent {

View File

@ -621,7 +621,7 @@ macro_rules! bdk_blockchain_tests {
#[test] #[test]
fn test_sync_double_receive() { fn test_sync_double_receive() {
let (wallet, blockchain, descriptors, mut test_client) = init_single_sig(); 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 // need to sync so rpc can start watching
receiver_wallet.sync(&blockchain, SyncOptions::default()).unwrap(); 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) @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"); assert_eq!(wallet.get_balance().unwrap(), 75_000, "incorrect balance");
let target_addr = receiver_wallet.get_address($crate::wallet::AddressIndex::New).unwrap().address; let target_addr = receiver_wallet.get_address($crate::wallet::AddressIndex::New).unwrap().address;
let tx1 = { let tx1 = {
let mut builder = wallet.build_tx(); let mut builder = wallet.build_tx();
builder.add_recipient(target_addr.script_pubkey(), 49_000).enable_rbf(); builder.add_recipient(target_addr.script_pubkey(), 49_000).enable_rbf();
let (mut psbt, _details) = builder.finish().unwrap(); let (mut psbt, _details) = builder.finish().expect("building first tx");
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap(); let finalized = wallet.sign(&mut psbt, Default::default()).expect("signing first tx");
assert!(finalized, "Cannot finalize transaction"); assert!(finalized, "Cannot finalize transaction");
psbt.extract_tx() psbt.extract_tx()
}; };
@ -645,17 +645,17 @@ macro_rules! bdk_blockchain_tests {
let tx2 = { let tx2 = {
let mut builder = wallet.build_tx(); 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)); 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 (mut psbt, _details) = builder.finish().expect("building replacement tx");
let finalized = wallet.sign(&mut psbt, Default::default()).unwrap(); let finalized = wallet.sign(&mut psbt, Default::default()).expect("signing replacement tx");
assert!(finalized, "Cannot finalize transaction"); assert!(finalized, "Cannot finalize transaction");
psbt.extract_tx() psbt.extract_tx()
}; };
blockchain.broadcast(&tx1).unwrap(); blockchain.broadcast(&tx1).expect("broadcasting first");
blockchain.broadcast(&tx2).unwrap(); blockchain.broadcast(&tx2).expect("broadcasting replacement");
receiver_wallet.sync(&blockchain, SyncOptions::default()).unwrap(); receiver_wallet.sync(&blockchain, SyncOptions::default()).expect("syncing receiver");
assert_eq!(receiver_wallet.get_balance().unwrap(), 49_000, "should have received coins once and only once"); assert_eq!(receiver_wallet.get_balance().expect("balance"), 49_000, "should have received coins once and only once");
} }
#[test] #[test]