Skip to content

Commit 04256a7

Browse files
committed
test: test_enable_anti_fee_sniping
1 parent 2c3e48e commit 04256a7

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

src/selection.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,3 +233,73 @@ impl Selection {
233233
)
234234
}
235235
}
236+
237+
#[cfg(test)]
238+
mod test {
239+
use super::*;
240+
241+
use bitcoin::{
242+
absolute, secp256k1::Secp256k1, transaction, Amount, ScriptBuf, Transaction, TxIn, TxOut,
243+
};
244+
use miniscript::{plan::Assets, Descriptor, DescriptorPublicKey};
245+
246+
#[test]
247+
fn test_enable_anti_fee_sniping() -> anyhow::Result<()> {
248+
let secp = Secp256k1::new();
249+
250+
let s = "tr([83737d5e/86h/1h/0h]tpubDDR5GgtoxS8fJyjjvdahN4VzV5DV6jtbcyvVXhEKq2XtpxjxBXmxH3r8QrNbQqHg4bJM1EGkxi7Pjfkgnui9jQWqS7kxHvX6rhUeriLDKxz/0/*)";
251+
let desc = Descriptor::parse_descriptor(&secp, s).unwrap().0;
252+
let def_desc = desc.at_derivation_index(0).unwrap();
253+
let script_pubkey = def_desc.script_pubkey();
254+
let desc_pk: DescriptorPublicKey = "[83737d5e/86h/1h/0h]tpubDDR5GgtoxS8fJyjjvdahN4VzV5DV6jtbcyvVXhEKq2XtpxjxBXmxH3r8QrNbQqHg4bJM1EGkxi7Pjfkgnui9jQWqS7kxHvX6rhUeriLDKxz/0/*".parse()?;
255+
let assets = Assets::new().add(desc_pk);
256+
let plan = def_desc.plan(&assets).expect("failed to create plan");
257+
258+
let prev_tx = Transaction {
259+
version: transaction::Version::TWO,
260+
lock_time: absolute::LockTime::ZERO,
261+
input: vec![TxIn::default()],
262+
output: vec![TxOut {
263+
script_pubkey,
264+
value: Amount::from_sat(10_000),
265+
}],
266+
};
267+
268+
// Assume the current height is 2500, and previous tx confirms at height 2000.
269+
let current_height = 2_500;
270+
let status = crate::TxStatus {
271+
height: absolute::Height::from_consensus(2_000)?,
272+
time: absolute::Time::from_consensus(500_000_000)?,
273+
};
274+
let input = Input::from_prev_tx(plan, prev_tx, 0, Some(status))?;
275+
let output = Output::with_script(ScriptBuf::new(), Amount::from_sat(9_000));
276+
let selection = Selection {
277+
inputs: vec![input.clone()],
278+
outputs: vec![output],
279+
};
280+
281+
let psbt = selection.create_psbt(PsbtParams {
282+
fallback_locktime: absolute::LockTime::from_consensus(current_height),
283+
enable_anti_fee_sniping: true,
284+
fallback_sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
285+
..Default::default()
286+
})?;
287+
288+
let tx = psbt.unsigned_tx;
289+
290+
if tx.lock_time > absolute::LockTime::ZERO {
291+
// Check locktime
292+
let min_height = current_height.saturating_sub(100);
293+
assert!((min_height..=current_height).contains(&tx.lock_time.to_consensus_u32()));
294+
} else {
295+
// Check sequence
296+
let confirmations =
297+
input.confirmations(absolute::Height::from_consensus(current_height)?);
298+
let min_sequence = confirmations.saturating_sub(100);
299+
let sequence_value = tx.input[0].sequence.to_consensus_u32();
300+
assert!((min_sequence..=confirmations).contains(&sequence_value));
301+
}
302+
303+
Ok(())
304+
}
305+
}

0 commit comments

Comments
 (0)