@@ -509,3 +509,55 @@ impl<'c> Selector<'c> {
509509 Some ( Selection :: new ( inputs, outputs) )
510510 }
511511}
512+
513+ #[ cfg_attr( coverage_nightly, coverage( off) ) ]
514+ #[ cfg( test) ]
515+ mod tests {
516+ use crate :: * ;
517+ use bitcoin:: {
518+ absolute, key:: Secp256k1 , secp256k1:: SecretKey , transaction, Amount , FeeRate , PrivateKey ,
519+ ScriptBuf , Transaction , TxIn , TxOut , Weight ,
520+ } ;
521+ use miniscript:: { plan:: Assets , DescriptorPublicKey } ;
522+ use std:: string:: ToString ;
523+
524+ fn setup_cltv_input ( cltv : absolute:: LockTime ) -> anyhow:: Result < Input > {
525+ let secp = Secp256k1 :: new ( ) ;
526+ let secret_key = SecretKey :: from_slice ( & [ 1_u8 ; 32 ] ) ?;
527+ let public_key = PrivateKey :: new ( secret_key, bitcoin:: Network :: Regtest ) . public_key ( & secp) ;
528+ let desc_str = format ! ( "wsh(and_v(v:pk({public_key}),after({cltv})))" ) ;
529+ let desc_pk: DescriptorPublicKey = public_key. to_string ( ) . parse ( ) ?;
530+ let ( desc, _) = Descriptor :: parse_descriptor ( & secp, & desc_str) ?;
531+ let plan = desc
532+ . at_derivation_index ( 0 ) ?
533+ . plan ( & Assets :: new ( ) . add ( desc_pk) . after ( cltv) )
534+ . expect ( "locktime asset must satisfy descriptor" ) ;
535+ let prev_tx = Transaction {
536+ version : transaction:: Version :: TWO ,
537+ lock_time : absolute:: LockTime :: ZERO ,
538+ input : vec ! [ TxIn :: default ( ) ] ,
539+ output : vec ! [ TxOut {
540+ script_pubkey: desc. at_derivation_index( 0 ) ?. script_pubkey( ) ,
541+ value: Amount :: ONE_BTC ,
542+ } ] ,
543+ } ;
544+ Ok ( Input :: from_prev_tx ( plan, prev_tx, 0 , None ) ?)
545+ }
546+
547+ #[ test]
548+ fn test_selector_rejects_mixed_absolute_locktime_units ( ) -> anyhow:: Result < ( ) > {
549+ let height_locked_input = setup_cltv_input ( absolute:: LockTime :: from_consensus ( 10_000 ) ) ?;
550+ let time_locked_input = setup_cltv_input ( absolute:: LockTime :: from_consensus ( 500_000_001 ) ) ?;
551+ let candidates = InputCandidates :: new ( [ ] , [ height_locked_input, time_locked_input] ) ;
552+ let params = SelectorParams :: new (
553+ FeeRate :: ZERO ,
554+ vec ! [ ] ,
555+ ChangeScript :: from_script ( ScriptBuf :: new ( ) , Weight :: ZERO ) ,
556+ ) ;
557+ assert ! ( matches!(
558+ Selector :: new( & candidates, params) ,
559+ Err ( SelectorError :: LockTypeMismatch )
560+ ) ) ;
561+ Ok ( ( ) )
562+ }
563+ }
0 commit comments