bitcoin_ext/
fee.rs

1
2use bitcoin::{ScriptBuf, TxOut, Weight};
3use bitcoin::Amount;
4
5
6/// The size in bytes of a fee anchor created with P2A script.
7pub const FEE_ANCHOR_WEIGHT: Weight = Weight::from_vb_unchecked(13);
8
9/// The witness size of a witness spending a dust anchor.
10pub const FEE_ANCHOR_SPEND_WEIGHT: Weight = Weight::from_wu(1);
11
12
13lazy_static! {
14	/// A pay-to-anchor (p2a) output script.
15	pub static ref P2A_SCRIPT: ScriptBuf = ScriptBuf::new_p2a();
16}
17
18/// Create a p2a fee anchor output with the given amount.
19pub fn fee_anchor_with_amount(amount: Amount) -> TxOut {
20	TxOut {
21		script_pubkey: P2A_SCRIPT.clone(),
22		value: amount,
23	}
24}
25
26/// Create a p2a fee anchor output with 0 value.
27pub fn fee_anchor() -> TxOut {
28	fee_anchor_with_amount(Amount::ZERO)
29}
30
31#[cfg(test)]
32mod test {
33	use bitcoin::{absolute::Height, psbt, transaction::Version, Transaction, TxIn, Witness};
34
35use super::*;
36
37	#[test]
38	fn test_dust_fee_anchor_size() {
39		assert_eq!(
40			FEE_ANCHOR_WEIGHT,
41			Weight::from_vb(bitcoin::consensus::serialize(&fee_anchor()).len() as u64).unwrap(),
42		);
43	}
44
45	#[test]
46	fn test_fee_anchor_spend_weight() {
47		let psbt_in = psbt::Input {
48			witness_utxo: Some(fee_anchor()),
49			final_script_witness: Some(Witness::new()),
50			..Default::default()
51		};
52
53		let psbt = psbt::Psbt {
54			inputs: vec![psbt_in],
55			outputs: vec![],
56
57			unsigned_tx: Transaction {
58				version: Version::TWO,
59				lock_time: bitcoin::absolute::LockTime::Blocks(Height::ZERO),
60				input: vec![TxIn::default()],
61				output: vec![],
62			},
63			xpub: Default::default(),
64			version: 0,
65			proprietary: Default::default(),
66			unknown: Default::default(),
67		};
68
69		assert_eq!(
70			psbt.extract_tx().unwrap().input[0].witness.size() as u64,
71			FEE_ANCHOR_SPEND_WEIGHT.to_wu(),
72		);
73	}
74}
75