bdk/crates/chain/tests/test_keychain_tracker.rs
志宇 a1172def7d
[bdk_chain_redesign] Revert some API changes
Methods of old structures that return transaction(s) no longer return
`TxNode`, but `Transaction` as done previously.

`TxInGraph` is renamed to `TxNode`, while the internal `TxNode` is
renamed to `TxNodeInternal`.
2023-03-31 11:55:11 +08:00

241 lines
6.2 KiB
Rust

#![cfg(feature = "miniscript")]
#[macro_use]
mod common;
use bdk_chain::{
keychain::{Balance, KeychainTracker},
miniscript::{
bitcoin::{secp256k1::Secp256k1, OutPoint, PackedLockTime, Transaction, TxOut},
Descriptor,
},
BlockId, ConfirmationTime, TxHeight,
};
use bitcoin::TxIn;
#[test]
fn test_insert_tx() {
let mut tracker = KeychainTracker::default();
let secp = Secp256k1::new();
let (descriptor, _) = Descriptor::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/0/*)").unwrap();
tracker.add_keychain((), descriptor.clone());
let txout = TxOut {
value: 100_000,
script_pubkey: descriptor.at_derivation_index(5).script_pubkey(),
};
let tx = Transaction {
version: 0x01,
lock_time: PackedLockTime(0),
input: vec![],
output: vec![txout],
};
let _ = tracker.txout_index.reveal_to_target(&(), 5);
let changeset = tracker
.insert_tx_preview(tx.clone(), ConfirmationTime::Unconfirmed)
.unwrap();
tracker.apply_changeset(changeset);
assert_eq!(
tracker
.chain_graph()
.transactions_in_chain()
.collect::<Vec<_>>(),
vec![(&ConfirmationTime::Unconfirmed, &tx,)]
);
assert_eq!(
tracker
.txout_index
.txouts_of_keychain(&())
.collect::<Vec<_>>(),
vec![(
5,
OutPoint {
txid: tx.txid(),
vout: 0
}
)]
);
}
#[test]
fn test_balance() {
use core::str::FromStr;
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd)]
enum Keychain {
One,
Two,
}
let mut tracker = KeychainTracker::default();
let one = Descriptor::from_str("tr([73c5da0a/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/*)#rg247h69").unwrap();
let two = Descriptor::from_str("tr([73c5da0a/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/1/*)#ju05rz2a").unwrap();
tracker.add_keychain(Keychain::One, one);
tracker.add_keychain(Keychain::Two, two);
let tx1 = Transaction {
version: 0x01,
lock_time: PackedLockTime(0),
input: vec![],
output: vec![TxOut {
value: 13_000,
script_pubkey: tracker
.txout_index
.reveal_next_spk(&Keychain::One)
.0
.1
.clone(),
}],
};
let tx2 = Transaction {
version: 0x01,
lock_time: PackedLockTime(0),
input: vec![],
output: vec![TxOut {
value: 7_000,
script_pubkey: tracker
.txout_index
.reveal_next_spk(&Keychain::Two)
.0
.1
.clone(),
}],
};
let tx_coinbase = Transaction {
version: 0x01,
lock_time: PackedLockTime(0),
input: vec![TxIn::default()],
output: vec![TxOut {
value: 11_000,
script_pubkey: tracker
.txout_index
.reveal_next_spk(&Keychain::Two)
.0
.1
.clone(),
}],
};
assert!(tx_coinbase.is_coin_base());
let _ = tracker
.insert_checkpoint(BlockId {
height: 5,
hash: h!("1"),
})
.unwrap();
let should_trust = |keychain: &Keychain| match *keychain {
Keychain::One => false,
Keychain::Two => true,
};
assert_eq!(tracker.balance(should_trust), Balance::default());
let _ = tracker
.insert_tx(tx1.clone(), TxHeight::Unconfirmed)
.unwrap();
assert_eq!(
tracker.balance(should_trust),
Balance {
untrusted_pending: 13_000,
..Default::default()
}
);
let _ = tracker
.insert_tx(tx2.clone(), TxHeight::Unconfirmed)
.unwrap();
assert_eq!(
tracker.balance(should_trust),
Balance {
trusted_pending: 7_000,
untrusted_pending: 13_000,
..Default::default()
}
);
let _ = tracker
.insert_tx(tx_coinbase, TxHeight::Confirmed(0))
.unwrap();
assert_eq!(
tracker.balance(should_trust),
Balance {
trusted_pending: 7_000,
untrusted_pending: 13_000,
immature: 11_000,
..Default::default()
}
);
let _ = tracker.insert_tx(tx1, TxHeight::Confirmed(1)).unwrap();
assert_eq!(
tracker.balance(should_trust),
Balance {
trusted_pending: 7_000,
untrusted_pending: 0,
immature: 11_000,
confirmed: 13_000,
}
);
let _ = tracker.insert_tx(tx2, TxHeight::Confirmed(2)).unwrap();
assert_eq!(
tracker.balance(should_trust),
Balance {
trusted_pending: 0,
untrusted_pending: 0,
immature: 11_000,
confirmed: 20_000,
}
);
let _ = tracker
.insert_checkpoint(BlockId {
height: 98,
hash: h!("98"),
})
.unwrap();
assert_eq!(
tracker.balance(should_trust),
Balance {
trusted_pending: 0,
untrusted_pending: 0,
immature: 11_000,
confirmed: 20_000,
}
);
let _ = tracker
.insert_checkpoint(BlockId {
height: 99,
hash: h!("99"),
})
.unwrap();
assert_eq!(
tracker.balance(should_trust),
Balance {
trusted_pending: 0,
untrusted_pending: 0,
immature: 0,
confirmed: 31_000,
}
);
assert_eq!(tracker.balance_at(0), 0);
assert_eq!(tracker.balance_at(1), 13_000);
assert_eq!(tracker.balance_at(2), 20_000);
assert_eq!(tracker.balance_at(98), 20_000);
assert_eq!(tracker.balance_at(99), 31_000);
assert_eq!(tracker.balance_at(100), 31_000);
}