Skip to content

Commit e9a3034

Browse files
committed
test(wallet): add tests for apply_block_events
Also did minor cleanup of apply_update_events tests.
1 parent 3f0664e commit e9a3034

File tree

1 file changed

+180
-9
lines changed

1 file changed

+180
-9
lines changed

wallet/tests/wallet_event.rs

Lines changed: 180 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ use bdk_chain::{BlockId, CheckPoint, ConfirmationBlockTime};
33
use bdk_wallet::event::WalletEvent;
44
use bdk_wallet::test_utils::{get_test_wpkh_and_change_desc, new_wallet_and_funding_update};
55
use bdk_wallet::{SignOptions, Update};
6+
use bitcoin::block::Header;
67
use bitcoin::hashes::Hash;
7-
use bitcoin::{Address, Amount, BlockHash, FeeRate};
8+
use bitcoin::{Address, Amount, Block, BlockHash, FeeRate, Transaction, TxMerkleNode};
89
use core::str::FromStr;
910
use std::sync::Arc;
1011

12+
/// apply_update_events tests.
1113
#[test]
1214
fn test_new_confirmed_tx_event() {
1315
let (desc, change_desc) = get_test_wpkh_and_change_desc();
@@ -28,9 +30,8 @@ fn test_new_confirmed_tx_event() {
2830
);
2931
assert!(matches!(&events[1], WalletEvent::TxConfirmed {tx, ..} if tx.output.len() == 1));
3032
assert!(
31-
matches!(events[2], WalletEvent::TxConfirmed {block_time, ..} if block_time.block_id.height == 2000)
33+
matches!(&events[2], WalletEvent::TxConfirmed {tx, block_time, ..} if block_time.block_id.height == 2000 && tx.output.len() == 2)
3234
);
33-
assert!(matches!(&events[2], WalletEvent::TxConfirmed {tx, ..} if tx.output.len() == 2));
3435
}
3536

3637
#[test]
@@ -88,7 +89,6 @@ fn test_tx_replaced_event() {
8889
update.tx_update.seen_ats = [(orig_txid, 210)].into();
8990
let events = wallet.apply_update_events(update).unwrap();
9091
assert_eq!(events.len(), 1);
91-
assert!(matches!(events[0], WalletEvent::TxUnconfirmed { .. }));
9292
assert!(
9393
matches!(&events[0], WalletEvent::TxUnconfirmed {tx, ..} if tx.compute_txid() == orig_txid)
9494
);
@@ -110,9 +110,8 @@ fn test_tx_replaced_event() {
110110
let events = wallet.apply_update_events(update).unwrap();
111111
assert_eq!(events.len(), 2);
112112
assert!(matches!(events[0], WalletEvent::TxUnconfirmed { txid, .. } if txid == rbf_txid));
113-
assert!(matches!(events[1], WalletEvent::TxReplaced { txid, ..} if txid == orig_txid));
114113
assert!(
115-
matches!(&events[1], WalletEvent::TxReplaced {conflicts, ..} if conflicts.len() == 1 &&
114+
matches!(&events[1], WalletEvent::TxReplaced {txid, conflicts, ..} if *txid == orig_txid && conflicts.len() == 1 &&
116115
conflicts.contains(&(0, rbf_txid)))
117116
);
118117
}
@@ -143,7 +142,6 @@ fn test_tx_confirmed_event() {
143142
update.tx_update.seen_ats = [(new_txid, 210)].into();
144143
let events = wallet.apply_update_events(update).unwrap();
145144
assert_eq!(events.len(), 1);
146-
assert!(matches!(events[0], WalletEvent::TxUnconfirmed { .. }));
147145
assert!(
148146
matches!(&events[0], WalletEvent::TxUnconfirmed {tx, ..} if tx.compute_txid() == new_txid)
149147
);
@@ -201,7 +199,6 @@ fn test_tx_confirmed_new_block_event() {
201199
update.tx_update.seen_ats = [(new_txid, 210)].into();
202200
let events = wallet.apply_update_events(update).unwrap();
203201
assert_eq!(events.len(), 1);
204-
assert!(matches!(events[0], WalletEvent::TxUnconfirmed { .. }));
205202
assert!(
206203
matches!(&events[0], WalletEvent::TxUnconfirmed {tx, ..} if tx.compute_txid() == new_txid)
207204
);
@@ -286,7 +283,6 @@ fn test_tx_dropped_event() {
286283
update.tx_update.seen_ats = [(new_txid, 210)].into();
287284
let events = wallet.apply_update_events(update).unwrap();
288285
assert_eq!(events.len(), 1);
289-
assert!(matches!(events[0], WalletEvent::TxUnconfirmed { .. }));
290286
assert!(
291287
matches!(&events[0], WalletEvent::TxUnconfirmed {tx, ..} if tx.compute_txid() == new_txid)
292288
);
@@ -299,3 +295,178 @@ fn test_tx_dropped_event() {
299295
assert_eq!(events.len(), 1);
300296
assert!(matches!(events[0], WalletEvent::TxDropped { txid, .. } if txid == new_txid));
301297
}
298+
299+
// apply_block_events tests.
300+
301+
fn test_block(prev_blockhash: BlockHash, time: u32, txdata: Vec<Transaction>) -> Block {
302+
Block {
303+
header: Header {
304+
version: Default::default(),
305+
prev_blockhash,
306+
merkle_root: TxMerkleNode::all_zeros(),
307+
time,
308+
bits: Default::default(),
309+
nonce: time,
310+
},
311+
txdata,
312+
}
313+
}
314+
315+
#[test]
316+
fn test_apply_block_new_confirmed_tx_event() {
317+
let (desc, change_desc) = get_test_wpkh_and_change_desc();
318+
let (mut wallet, _, update) = new_wallet_and_funding_update(desc, Some(change_desc));
319+
320+
let genesis = BlockId {
321+
height: 0,
322+
hash: wallet.local_chain().genesis_hash(),
323+
};
324+
// apply empty block
325+
let block1 = test_block(genesis.hash, 1000, vec![]);
326+
let events = wallet.apply_block_events(&block1, 1).unwrap();
327+
assert_eq!(events.len(), 1);
328+
329+
// apply funding block
330+
let block2 = test_block(
331+
block1.block_hash(),
332+
2000,
333+
update.tx_update.txs[..1]
334+
.iter()
335+
.map(|tx| (**tx).clone())
336+
.collect(),
337+
);
338+
let events = wallet.apply_block_events(&block2, 2).unwrap();
339+
assert_eq!(events.len(), 2);
340+
let new_tip2 = wallet.local_chain().tip().block_id();
341+
assert!(
342+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip == (1, block1.block_hash()).into() && new_tip == new_tip2)
343+
);
344+
assert!(
345+
matches!(&events[1], WalletEvent::TxConfirmed { tx, block_time, ..} if block_time.block_id.height == 2 && tx.output.len() == 1)
346+
);
347+
348+
// apply empty block
349+
let block3 = test_block(block2.block_hash(), 3000, vec![]);
350+
let events = wallet.apply_block_events(&block3, 3).unwrap();
351+
assert_eq!(events.len(), 1);
352+
353+
// apply spending block
354+
let block4 = test_block(
355+
block3.block_hash(),
356+
4000,
357+
update.tx_update.txs[1..]
358+
.iter()
359+
.map(|tx| (**tx).clone())
360+
.collect(),
361+
);
362+
let events = wallet.apply_block_events(&block4, 4).unwrap();
363+
let new_tip3 = wallet.local_chain().tip().block_id();
364+
assert_eq!(events.len(), 2);
365+
assert!(
366+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip == (3, block3.block_hash()).into() && new_tip == new_tip3)
367+
);
368+
assert!(
369+
matches!(&events[1], WalletEvent::TxConfirmed {tx, block_time, ..} if block_time.block_id.height == 4 && tx.output.len() == 2)
370+
);
371+
}
372+
373+
#[test]
374+
fn test_apply_block_tx_unconfirmed_event() {
375+
let (desc, change_desc) = get_test_wpkh_and_change_desc();
376+
let (mut wallet, _, update) = new_wallet_and_funding_update(desc, Some(change_desc));
377+
// apply funding block
378+
let genesis = BlockId {
379+
height: 0,
380+
hash: wallet.local_chain().genesis_hash(),
381+
};
382+
let block1 = test_block(
383+
genesis.hash,
384+
1000,
385+
update.tx_update.txs[..1]
386+
.iter()
387+
.map(|tx| (**tx).clone())
388+
.collect(),
389+
);
390+
let events = wallet.apply_block_events(&block1, 1).unwrap();
391+
assert_eq!(events.len(), 2);
392+
393+
// apply spending block
394+
let block2 = test_block(
395+
block1.block_hash(),
396+
2000,
397+
update.tx_update.txs[1..]
398+
.iter()
399+
.map(|tx| (**tx).clone())
400+
.collect(),
401+
);
402+
let events = wallet.apply_block_events(&block2, 2).unwrap();
403+
assert_eq!(events.len(), 2);
404+
let new_tip2 = wallet.local_chain().tip().block_id();
405+
assert!(
406+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip == (1, block1.block_hash()).into() && new_tip == new_tip2)
407+
);
408+
assert!(
409+
matches!(&events[1], WalletEvent::TxConfirmed {block_time, tx, ..} if block_time.block_id.height == 2 && tx.output.len() == 2)
410+
);
411+
412+
// apply reorg of spending block without previously confirmed tx
413+
let reorg_block2 = test_block(block1.block_hash(), 2100, vec![]);
414+
let events = wallet.apply_block_events(&reorg_block2, 2).unwrap();
415+
assert_eq!(events.len(), 2);
416+
assert!(
417+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip ==
418+
(2, block2.block_hash()).into() && new_tip == (2, reorg_block2.block_hash()).into())
419+
);
420+
assert!(
421+
matches!(&events[1], WalletEvent::TxUnconfirmed {tx, old_block_time, ..} if
422+
tx.output.len() == 2 && old_block_time.is_some())
423+
);
424+
}
425+
426+
#[test]
427+
fn test_apply_block_tx_confirmed_new_block_event() {
428+
let (desc, change_desc) = get_test_wpkh_and_change_desc();
429+
let (mut wallet, _, update) = new_wallet_and_funding_update(desc, Some(change_desc));
430+
// apply funding block
431+
let genesis = BlockId {
432+
height: 0,
433+
hash: wallet.local_chain().genesis_hash(),
434+
};
435+
let block1 = test_block(
436+
genesis.hash,
437+
1000,
438+
update.tx_update.txs[..1]
439+
.iter()
440+
.map(|tx| (**tx).clone())
441+
.collect(),
442+
);
443+
let events = wallet.apply_block_events(&block1, 1).unwrap();
444+
assert_eq!(events.len(), 2);
445+
446+
// apply spending block
447+
let spending_tx: Transaction = (*update.tx_update.txs[1].clone()).clone();
448+
let block2 = test_block(block1.block_hash(), 2000, vec![spending_tx.clone()]);
449+
let events = wallet.apply_block_events(&block2, 2).unwrap();
450+
assert_eq!(events.len(), 2);
451+
let new_tip2 = wallet.local_chain().tip().block_id();
452+
assert!(
453+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip == (1, block1.block_hash()).into() && new_tip == new_tip2)
454+
);
455+
assert!(
456+
matches!(events[1], WalletEvent::TxConfirmed { txid, block_time, old_block_time, .. } if
457+
txid == spending_tx.compute_txid() && block_time.block_id == (2, block2.block_hash()).into() && old_block_time.is_none())
458+
);
459+
460+
// apply reorg of spending block including the original spending tx
461+
let reorg_block2 = test_block(block1.block_hash(), 2100, vec![spending_tx.clone()]);
462+
let events = wallet.apply_block_events(&reorg_block2, 2).unwrap();
463+
assert_eq!(events.len(), 2);
464+
assert!(
465+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip ==
466+
(2, block2.block_hash()).into() && new_tip == (2, reorg_block2.block_hash()).into())
467+
);
468+
assert!(
469+
matches!(events[1], WalletEvent::TxConfirmed { txid, block_time, old_block_time, .. } if
470+
txid == spending_tx.compute_txid() && block_time.block_id == (2, reorg_block2.block_hash()).into() && old_block_time.is_some())
471+
);
472+
}

0 commit comments

Comments
 (0)