Skip to content

Commit d09c5e2

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

File tree

1 file changed

+180
-10
lines changed

1 file changed

+180
-10
lines changed

tests/wallet_event.rs

Lines changed: 180 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
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};
4-
use bdk_wallet::Update;
4+
use bdk_wallet::{SignOptions, Update};
55
use bitcoin::hashes::Hash;
6-
use bitcoin::{Address, Amount, BlockHash, FeeRate};
6+
use bitcoin::{Address, Amount, Block, BlockHash, FeeRate, Transaction, TxMerkleNode};
77
use core::str::FromStr;
88
use std::sync::Arc;
99

10+
/// apply_update_events tests.
1011
#[test]
1112
fn test_new_confirmed_tx_event() {
1213
let (desc, change_desc) = get_test_wpkh_and_change_desc();
@@ -27,9 +28,8 @@ fn test_new_confirmed_tx_event() {
2728
);
2829
assert!(matches!(&events[1], WalletEvent::TxConfirmed {tx, ..} if tx.output.len() == 1));
2930
assert!(
30-
matches!(events[2], WalletEvent::TxConfirmed {block_time, ..} if block_time.block_id.height == 2000)
31+
matches!(&events[2], WalletEvent::TxConfirmed {tx, block_time, ..} if block_time.block_id.height == 2000 && tx.output.len() == 2)
3132
);
32-
assert!(matches!(&events[2], WalletEvent::TxConfirmed {tx, ..} if tx.output.len() == 2));
3333
}
3434

3535
#[test]
@@ -86,7 +86,6 @@ fn test_tx_replaced_event() {
8686
update.tx_update.seen_ats = [(orig_txid, 210)].into();
8787
let events = wallet.apply_update_events(update).unwrap();
8888
assert_eq!(events.len(), 1);
89-
assert!(matches!(events[0], WalletEvent::TxUnconfirmed { .. }));
9089
assert!(
9190
matches!(&events[0], WalletEvent::TxUnconfirmed {tx, ..} if tx.compute_txid() == orig_txid)
9291
);
@@ -107,9 +106,8 @@ fn test_tx_replaced_event() {
107106
let events = wallet.apply_update_events(update).unwrap();
108107
assert_eq!(events.len(), 2);
109108
assert!(matches!(events[0], WalletEvent::TxUnconfirmed { txid, .. } if txid == rbf_txid));
110-
assert!(matches!(events[1], WalletEvent::TxReplaced { txid, ..} if txid == orig_txid));
111109
assert!(
112-
matches!(&events[1], WalletEvent::TxReplaced {conflicts, ..} if conflicts.len() == 1 &&
110+
matches!(&events[1], WalletEvent::TxReplaced {txid, conflicts, ..} if *txid == orig_txid && conflicts.len() == 1 &&
113111
conflicts.contains(&(0, rbf_txid)))
114112
);
115113
}
@@ -139,7 +137,6 @@ fn test_tx_confirmed_event() {
139137
update.tx_update.seen_ats = [(new_txid, 210)].into();
140138
let events = wallet.apply_update_events(update).unwrap();
141139
assert_eq!(events.len(), 1);
142-
assert!(matches!(events[0], WalletEvent::TxUnconfirmed { .. }));
143140
assert!(
144141
matches!(&events[0], WalletEvent::TxUnconfirmed {tx, ..} if tx.compute_txid() == new_txid)
145142
);
@@ -196,7 +193,6 @@ fn test_tx_confirmed_new_block_event() {
196193
update.tx_update.seen_ats = [(new_txid, 210)].into();
197194
let events = wallet.apply_update_events(update).unwrap();
198195
assert_eq!(events.len(), 1);
199-
assert!(matches!(events[0], WalletEvent::TxUnconfirmed { .. }));
200196
assert!(
201197
matches!(&events[0], WalletEvent::TxUnconfirmed {tx, ..} if tx.compute_txid() == new_txid)
202198
);
@@ -280,7 +276,6 @@ fn test_tx_dropped_event() {
280276
update.tx_update.seen_ats = [(new_txid, 210)].into();
281277
let events = wallet.apply_update_events(update).unwrap();
282278
assert_eq!(events.len(), 1);
283-
assert!(matches!(events[0], WalletEvent::TxUnconfirmed { .. }));
284279
assert!(
285280
matches!(&events[0], WalletEvent::TxUnconfirmed {tx, ..} if tx.compute_txid() == new_txid)
286281
);
@@ -293,3 +288,178 @@ fn test_tx_dropped_event() {
293288
assert_eq!(events.len(), 1);
294289
assert!(matches!(events[0], WalletEvent::TxDropped { txid, .. } if txid == new_txid));
295290
}
291+
292+
// apply_block_events tests.
293+
294+
fn test_block(prev_blockhash: BlockHash, time: u32, txdata: Vec<Transaction>) -> Block {
295+
Block {
296+
header: Header {
297+
version: Default::default(),
298+
prev_blockhash,
299+
merkle_root: TxMerkleNode::all_zeros(),
300+
time,
301+
bits: Default::default(),
302+
nonce: time,
303+
},
304+
txdata,
305+
}
306+
}
307+
308+
#[test]
309+
fn test_apply_block_new_confirmed_tx_event() {
310+
let (desc, change_desc) = get_test_wpkh_and_change_desc();
311+
let (mut wallet, _, update) = new_wallet_and_funding_update(desc, Some(change_desc));
312+
313+
let genesis = BlockId {
314+
height: 0,
315+
hash: wallet.local_chain().genesis_hash(),
316+
};
317+
// apply empty block
318+
let block1 = test_block(genesis.hash, 1000, vec![]);
319+
let events = wallet.apply_block_events(&block1, 1).unwrap();
320+
assert_eq!(events.len(), 1);
321+
322+
// apply funding block
323+
let block2 = test_block(
324+
block1.block_hash(),
325+
2000,
326+
update.tx_update.txs[..1]
327+
.iter()
328+
.map(|tx| (**tx).clone())
329+
.collect(),
330+
);
331+
let events = wallet.apply_block_events(&block2, 2).unwrap();
332+
assert_eq!(events.len(), 2);
333+
let new_tip2 = wallet.local_chain().tip().block_id();
334+
assert!(
335+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip == (1, block1.block_hash()).into() && new_tip == new_tip2)
336+
);
337+
assert!(
338+
matches!(&events[1], WalletEvent::TxConfirmed { tx, block_time, ..} if block_time.block_id.height == 2 && tx.output.len() == 1)
339+
);
340+
341+
// apply empty block
342+
let block3 = test_block(block2.block_hash(), 3000, vec![]);
343+
let events = wallet.apply_block_events(&block3, 3).unwrap();
344+
assert_eq!(events.len(), 1);
345+
346+
// apply spending block
347+
let block4 = test_block(
348+
block3.block_hash(),
349+
4000,
350+
update.tx_update.txs[1..]
351+
.iter()
352+
.map(|tx| (**tx).clone())
353+
.collect(),
354+
);
355+
let events = wallet.apply_block_events(&block4, 4).unwrap();
356+
let new_tip3 = wallet.local_chain().tip().block_id();
357+
assert_eq!(events.len(), 2);
358+
assert!(
359+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip == (3, block3.block_hash()).into() && new_tip == new_tip3)
360+
);
361+
assert!(
362+
matches!(&events[1], WalletEvent::TxConfirmed {tx, block_time, ..} if block_time.block_id.height == 4 && tx.output.len() == 2)
363+
);
364+
}
365+
366+
#[test]
367+
fn test_apply_block_tx_unconfirmed_event() {
368+
let (desc, change_desc) = get_test_wpkh_and_change_desc();
369+
let (mut wallet, _, update) = new_wallet_and_funding_update(desc, Some(change_desc));
370+
// apply funding block
371+
let genesis = BlockId {
372+
height: 0,
373+
hash: wallet.local_chain().genesis_hash(),
374+
};
375+
let block1 = test_block(
376+
genesis.hash,
377+
1000,
378+
update.tx_update.txs[..1]
379+
.iter()
380+
.map(|tx| (**tx).clone())
381+
.collect(),
382+
);
383+
let events = wallet.apply_block_events(&block1, 1).unwrap();
384+
assert_eq!(events.len(), 2);
385+
386+
// apply spending block
387+
let block2 = test_block(
388+
block1.block_hash(),
389+
2000,
390+
update.tx_update.txs[1..]
391+
.iter()
392+
.map(|tx| (**tx).clone())
393+
.collect(),
394+
);
395+
let events = wallet.apply_block_events(&block2, 2).unwrap();
396+
assert_eq!(events.len(), 2);
397+
let new_tip2 = wallet.local_chain().tip().block_id();
398+
assert!(
399+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip == (1, block1.block_hash()).into() && new_tip == new_tip2)
400+
);
401+
assert!(
402+
matches!(&events[1], WalletEvent::TxConfirmed {block_time, tx, ..} if block_time.block_id.height == 2 && tx.output.len() == 2)
403+
);
404+
405+
// apply reorg of spending block without previously confirmed tx
406+
let reorg_block2 = test_block(block1.block_hash(), 2100, vec![]);
407+
let events = wallet.apply_block_events(&reorg_block2, 2).unwrap();
408+
assert_eq!(events.len(), 2);
409+
assert!(
410+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip ==
411+
(2, block2.block_hash()).into() && new_tip == (2, reorg_block2.block_hash()).into())
412+
);
413+
assert!(
414+
matches!(&events[1], WalletEvent::TxUnconfirmed {tx, old_block_time, ..} if
415+
tx.output.len() == 2 && old_block_time.is_some())
416+
);
417+
}
418+
419+
#[test]
420+
fn test_apply_block_tx_confirmed_new_block_event() {
421+
let (desc, change_desc) = get_test_wpkh_and_change_desc();
422+
let (mut wallet, _, update) = new_wallet_and_funding_update(desc, Some(change_desc));
423+
// apply funding block
424+
let genesis = BlockId {
425+
height: 0,
426+
hash: wallet.local_chain().genesis_hash(),
427+
};
428+
let block1 = test_block(
429+
genesis.hash,
430+
1000,
431+
update.tx_update.txs[..1]
432+
.iter()
433+
.map(|tx| (**tx).clone())
434+
.collect(),
435+
);
436+
let events = wallet.apply_block_events(&block1, 1).unwrap();
437+
assert_eq!(events.len(), 2);
438+
439+
// apply spending block
440+
let spending_tx: Transaction = (*update.tx_update.txs[1].clone()).clone();
441+
let block2 = test_block(block1.block_hash(), 2000, vec![spending_tx.clone()]);
442+
let events = wallet.apply_block_events(&block2, 2).unwrap();
443+
assert_eq!(events.len(), 2);
444+
let new_tip2 = wallet.local_chain().tip().block_id();
445+
assert!(
446+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip == (1, block1.block_hash()).into() && new_tip == new_tip2)
447+
);
448+
assert!(
449+
matches!(events[1], WalletEvent::TxConfirmed { txid, block_time, old_block_time, .. } if
450+
txid == spending_tx.compute_txid() && block_time.block_id == (2, block2.block_hash()).into() && old_block_time.is_none())
451+
);
452+
453+
// apply reorg of spending block including the original spending tx
454+
let reorg_block2 = test_block(block1.block_hash(), 2100, vec![spending_tx.clone()]);
455+
let events = wallet.apply_block_events(&reorg_block2, 2).unwrap();
456+
assert_eq!(events.len(), 2);
457+
assert!(
458+
matches!(events[0], WalletEvent::ChainTipChanged { old_tip, new_tip } if old_tip ==
459+
(2, block2.block_hash()).into() && new_tip == (2, reorg_block2.block_hash()).into())
460+
);
461+
assert!(
462+
matches!(events[1], WalletEvent::TxConfirmed { txid, block_time, old_block_time, .. } if
463+
txid == spending_tx.compute_txid() && block_time.block_id == (2, reorg_block2.block_hash()).into() && old_block_time.is_some())
464+
);
465+
}

0 commit comments

Comments
 (0)