Skip to content

Commit 6c5c755

Browse files
committed
test(wallet): add tests for apply_block_events
Also did minor cleanup of apply_update_events tests.
1 parent 193609f commit 6c5c755

File tree

1 file changed

+180
-9
lines changed

1 file changed

+180
-9
lines changed

tests/wallet_event.rs

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

11+
/// apply_update_events tests.
1012
#[test]
1113
fn test_new_confirmed_tx_event() {
1214
let (desc, change_desc) = get_test_wpkh_and_change_desc();
@@ -27,9 +29,8 @@ fn test_new_confirmed_tx_event() {
2729
);
2830
assert!(matches!(&events[1], WalletEvent::TxConfirmed {tx, ..} if tx.output.len() == 1));
2931
assert!(
30-
matches!(events[2], WalletEvent::TxConfirmed {block_time, ..} if block_time.block_id.height == 2000)
32+
matches!(&events[2], WalletEvent::TxConfirmed {tx, block_time, ..} if block_time.block_id.height == 2000 && tx.output.len() == 2)
3133
);
32-
assert!(matches!(&events[2], WalletEvent::TxConfirmed {tx, ..} if tx.output.len() == 2));
3334
}
3435

3536
#[test]
@@ -86,7 +87,6 @@ fn test_tx_replaced_event() {
8687
update.tx_update.seen_ats = [(orig_txid, 210)].into();
8788
let events = wallet.apply_update_events(update).unwrap();
8889
assert_eq!(events.len(), 1);
89-
assert!(matches!(events[0], WalletEvent::TxUnconfirmed { .. }));
9090
assert!(
9191
matches!(&events[0], WalletEvent::TxUnconfirmed {tx, ..} if tx.compute_txid() == orig_txid)
9292
);
@@ -107,9 +107,8 @@ fn test_tx_replaced_event() {
107107
let events = wallet.apply_update_events(update).unwrap();
108108
assert_eq!(events.len(), 2);
109109
assert!(matches!(events[0], WalletEvent::TxUnconfirmed { txid, .. } if txid == rbf_txid));
110-
assert!(matches!(events[1], WalletEvent::TxReplaced { txid, ..} if txid == orig_txid));
111110
assert!(
112-
matches!(&events[1], WalletEvent::TxReplaced {conflicts, ..} if conflicts.len() == 1 &&
111+
matches!(&events[1], WalletEvent::TxReplaced {txid, conflicts, ..} if *txid == orig_txid && conflicts.len() == 1 &&
113112
conflicts.contains(&(0, rbf_txid)))
114113
);
115114
}
@@ -139,7 +138,6 @@ fn test_tx_confirmed_event() {
139138
update.tx_update.seen_ats = [(new_txid, 210)].into();
140139
let events = wallet.apply_update_events(update).unwrap();
141140
assert_eq!(events.len(), 1);
142-
assert!(matches!(events[0], WalletEvent::TxUnconfirmed { .. }));
143141
assert!(
144142
matches!(&events[0], WalletEvent::TxUnconfirmed {tx, ..} if tx.compute_txid() == new_txid)
145143
);
@@ -196,7 +194,6 @@ fn test_tx_confirmed_new_block_event() {
196194
update.tx_update.seen_ats = [(new_txid, 210)].into();
197195
let events = wallet.apply_update_events(update).unwrap();
198196
assert_eq!(events.len(), 1);
199-
assert!(matches!(events[0], WalletEvent::TxUnconfirmed { .. }));
200197
assert!(
201198
matches!(&events[0], WalletEvent::TxUnconfirmed {tx, ..} if tx.compute_txid() == new_txid)
202199
);
@@ -280,7 +277,6 @@ fn test_tx_dropped_event() {
280277
update.tx_update.seen_ats = [(new_txid, 210)].into();
281278
let events = wallet.apply_update_events(update).unwrap();
282279
assert_eq!(events.len(), 1);
283-
assert!(matches!(events[0], WalletEvent::TxUnconfirmed { .. }));
284280
assert!(
285281
matches!(&events[0], WalletEvent::TxUnconfirmed {tx, ..} if tx.compute_txid() == new_txid)
286282
);
@@ -293,3 +289,178 @@ fn test_tx_dropped_event() {
293289
assert_eq!(events.len(), 1);
294290
assert!(matches!(events[0], WalletEvent::TxDropped { txid, .. } if txid == new_txid));
295291
}
292+
293+
// apply_block_events tests.
294+
295+
fn test_block(prev_blockhash: BlockHash, time: u32, txdata: Vec<Transaction>) -> Block {
296+
Block {
297+
header: Header {
298+
version: Default::default(),
299+
prev_blockhash,
300+
merkle_root: TxMerkleNode::all_zeros(),
301+
time,
302+
bits: Default::default(),
303+
nonce: time,
304+
},
305+
txdata,
306+
}
307+
}
308+
309+
#[test]
310+
fn test_apply_block_new_confirmed_tx_event() {
311+
let (desc, change_desc) = get_test_wpkh_and_change_desc();
312+
let (mut wallet, _, update) = new_wallet_and_funding_update(desc, Some(change_desc));
313+
314+
let genesis = BlockId {
315+
height: 0,
316+
hash: wallet.local_chain().genesis_hash(),
317+
};
318+
// apply empty block
319+
let block1 = test_block(genesis.hash, 1000, vec![]);
320+
let events = wallet.apply_block_events(&block1, 1).unwrap();
321+
assert_eq!(events.len(), 1);
322+
323+
// apply funding block
324+
let block2 = test_block(
325+
block1.block_hash(),
326+
2000,
327+
update.tx_update.txs[..1]
328+
.iter()
329+
.map(|tx| (**tx).clone())
330+
.collect(),
331+
);
332+
let events = wallet.apply_block_events(&block2, 2).unwrap();
333+
assert_eq!(events.len(), 2);
334+
let new_tip2 = wallet.local_chain().tip().block_id();
335+
assert!(
336+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip == (1, block1.block_hash()).into() && new_tip == new_tip2)
337+
);
338+
assert!(
339+
matches!(&events[1], WalletEvent::TxConfirmed { tx, block_time, ..} if block_time.block_id.height == 2 && tx.output.len() == 1)
340+
);
341+
342+
// apply empty block
343+
let block3 = test_block(block2.block_hash(), 3000, vec![]);
344+
let events = wallet.apply_block_events(&block3, 3).unwrap();
345+
assert_eq!(events.len(), 1);
346+
347+
// apply spending block
348+
let block4 = test_block(
349+
block3.block_hash(),
350+
4000,
351+
update.tx_update.txs[1..]
352+
.iter()
353+
.map(|tx| (**tx).clone())
354+
.collect(),
355+
);
356+
let events = wallet.apply_block_events(&block4, 4).unwrap();
357+
let new_tip3 = wallet.local_chain().tip().block_id();
358+
assert_eq!(events.len(), 2);
359+
assert!(
360+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip == (3, block3.block_hash()).into() && new_tip == new_tip3)
361+
);
362+
assert!(
363+
matches!(&events[1], WalletEvent::TxConfirmed {tx, block_time, ..} if block_time.block_id.height == 4 && tx.output.len() == 2)
364+
);
365+
}
366+
367+
#[test]
368+
fn test_apply_block_tx_unconfirmed_event() {
369+
let (desc, change_desc) = get_test_wpkh_and_change_desc();
370+
let (mut wallet, _, update) = new_wallet_and_funding_update(desc, Some(change_desc));
371+
// apply funding block
372+
let genesis = BlockId {
373+
height: 0,
374+
hash: wallet.local_chain().genesis_hash(),
375+
};
376+
let block1 = test_block(
377+
genesis.hash,
378+
1000,
379+
update.tx_update.txs[..1]
380+
.iter()
381+
.map(|tx| (**tx).clone())
382+
.collect(),
383+
);
384+
let events = wallet.apply_block_events(&block1, 1).unwrap();
385+
assert_eq!(events.len(), 2);
386+
387+
// apply spending block
388+
let block2 = test_block(
389+
block1.block_hash(),
390+
2000,
391+
update.tx_update.txs[1..]
392+
.iter()
393+
.map(|tx| (**tx).clone())
394+
.collect(),
395+
);
396+
let events = wallet.apply_block_events(&block2, 2).unwrap();
397+
assert_eq!(events.len(), 2);
398+
let new_tip2 = wallet.local_chain().tip().block_id();
399+
assert!(
400+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip == (1, block1.block_hash()).into() && new_tip == new_tip2)
401+
);
402+
assert!(
403+
matches!(&events[1], WalletEvent::TxConfirmed {block_time, tx, ..} if block_time.block_id.height == 2 && tx.output.len() == 2)
404+
);
405+
406+
// apply reorg of spending block without previously confirmed tx
407+
let reorg_block2 = test_block(block1.block_hash(), 2100, vec![]);
408+
let events = wallet.apply_block_events(&reorg_block2, 2).unwrap();
409+
assert_eq!(events.len(), 2);
410+
assert!(
411+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip ==
412+
(2, block2.block_hash()).into() && new_tip == (2, reorg_block2.block_hash()).into())
413+
);
414+
assert!(
415+
matches!(&events[1], WalletEvent::TxUnconfirmed {tx, old_block_time, ..} if
416+
tx.output.len() == 2 && old_block_time.is_some())
417+
);
418+
}
419+
420+
#[test]
421+
fn test_apply_block_tx_confirmed_new_block_event() {
422+
let (desc, change_desc) = get_test_wpkh_and_change_desc();
423+
let (mut wallet, _, update) = new_wallet_and_funding_update(desc, Some(change_desc));
424+
// apply funding block
425+
let genesis = BlockId {
426+
height: 0,
427+
hash: wallet.local_chain().genesis_hash(),
428+
};
429+
let block1 = test_block(
430+
genesis.hash,
431+
1000,
432+
update.tx_update.txs[..1]
433+
.iter()
434+
.map(|tx| (**tx).clone())
435+
.collect(),
436+
);
437+
let events = wallet.apply_block_events(&block1, 1).unwrap();
438+
assert_eq!(events.len(), 2);
439+
440+
// apply spending block
441+
let spending_tx: Transaction = (*update.tx_update.txs[1].clone()).clone();
442+
let block2 = test_block(block1.block_hash(), 2000, vec![spending_tx.clone()]);
443+
let events = wallet.apply_block_events(&block2, 2).unwrap();
444+
assert_eq!(events.len(), 2);
445+
let new_tip2 = wallet.local_chain().tip().block_id();
446+
assert!(
447+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip == (1, block1.block_hash()).into() && new_tip == new_tip2)
448+
);
449+
assert!(
450+
matches!(events[1], WalletEvent::TxConfirmed { txid, block_time, old_block_time, .. } if
451+
txid == spending_tx.compute_txid() && block_time.block_id == (2, block2.block_hash()).into() && old_block_time.is_none())
452+
);
453+
454+
// apply reorg of spending block including the original spending tx
455+
let reorg_block2 = test_block(block1.block_hash(), 2100, vec![spending_tx.clone()]);
456+
let events = wallet.apply_block_events(&reorg_block2, 2).unwrap();
457+
assert_eq!(events.len(), 2);
458+
assert!(
459+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip ==
460+
(2, block2.block_hash()).into() && new_tip == (2, reorg_block2.block_hash()).into())
461+
);
462+
assert!(
463+
matches!(events[1], WalletEvent::TxConfirmed { txid, block_time, old_block_time, .. } if
464+
txid == spending_tx.compute_txid() && block_time.block_id == (2, reorg_block2.block_hash()).into() && old_block_time.is_some())
465+
);
466+
}

0 commit comments

Comments
 (0)