11/// Test to demonstrate the RelLockTime issue in dsl.rs
22///
33/// The issue: older() macro uses .expect() on RelLockTime::from_consensus(),
4- /// which can panic if given an invalid value (> 16,777,215 ).
4+ /// which can panic if given an invalid value (> 65,535 ).
55///
66/// This file shows the problem and how to catch it.
77use bdk_wallet:: descriptor;
@@ -20,17 +20,18 @@ fn test_older_with_invalid_rellocktime_too_large() {
2020 ) ;
2121
2222 // Check that it's the right kind of error
23- if let Err ( descriptor:: DescriptorError :: RelLockTime ( _) ) = result {
24- // Good, it's the expected error type
23+ if let Err ( descriptor:: DescriptorError :: Miniscript ( miniscript:: Error :: RelativeLockTime ( _) ) ) =
24+ result
25+ {
2526 } else {
2627 panic ! ( "Expected RelLockTime error, got {:?}" , result) ;
2728 }
2829}
2930
3031#[ test]
3132fn test_older_with_valid_rellocktime_max ( ) {
32- // Max valid value is 16,777,215 (0xFFFFFF )
33- let max_valid_value = 16_777_215 ;
33+ // Max valid value is 65,535 (0xFFFF )
34+ let max_valid_value = 65_535 ;
3435 let result = descriptor ! ( wsh( older( max_valid_value) ) ) ;
3536 assert ! ( result. is_ok( ) , "Max valid RelLockTime should work" ) ;
3637}
@@ -70,33 +71,52 @@ fn test_demonstrate_proper_error_handling() {
7071 use miniscript:: RelLockTime ;
7172
7273 // Valid case
73- match RelLockTime :: from_consensus ( 144 ) {
74- Ok ( lock_time) => println ! ( "Valid: {:?}" , lock_time) ,
75- Err ( e) => println ! ( "Invalid: {}" , e) ,
76- }
74+ let valid_lock = RelLockTime :: from_consensus ( 144 ) ;
75+ assert ! (
76+ valid_lock. is_ok( ) ,
77+ "144 blocks should be a valid RelLockTime"
78+ ) ;
7779
78- // Invalid case - properly handled
79- match RelLockTime :: from_consensus ( 16_777_216 ) {
80- Ok ( lock_time) => println ! ( "Valid: {:?}" , lock_time) ,
81- Err ( e) => {
82- println ! ( "Invalid RelLockTime value: {}" , e) ;
83- }
84- }
80+ // Invalid case
81+ let invalid_value = 0x8000_0000 ;
82+ let invalid_result = RelLockTime :: from_consensus ( invalid_value) ;
83+ assert ! (
84+ invalid_result. is_err( ) ,
85+ "Value 0x{:x} should return a RelLockTime error" ,
86+ invalid_value
87+ ) ;
8588}
8689
8790#[ test]
8891fn test_rel_lock_time_error ( ) {
89- // Create a RelLockTimeError by trying to create an invalid RelLockTime
90- let invalid_value = 0x80000000u32 ; // Value that causes RelLockTime::from_consensus to fail
92+ // 1. Create the underlying RelLockTime error (high bit set)
93+ let invalid_value = 0x80000000u32 ;
9194 let rel_lock_time_result = miniscript:: RelLockTime :: from_consensus ( invalid_value) ;
9295 assert ! ( rel_lock_time_result. is_err( ) ) ;
96+
9397 let rel_lock_time_error = rel_lock_time_result. unwrap_err ( ) ;
9498
95- // Test the From impl
96- let error: descriptor:: DescriptorError = rel_lock_time_error. into ( ) ;
97- assert ! ( matches!( error, descriptor:: DescriptorError :: RelLockTime ( _) ) ) ;
99+ // 2. Wrap it in the Miniscript error variant (matching your new macro logic)
100+ let minisc_err = miniscript:: Error :: RelativeLockTime ( rel_lock_time_error) ;
101+
102+ // 3. Test the From impl (Miniscript -> DescriptorError)
103+ let error: descriptor:: DescriptorError = minisc_err. into ( ) ;
104+
105+ // Check that it matches the nested structure
106+ assert ! ( matches!(
107+ error,
108+ descriptor:: DescriptorError :: Miniscript ( miniscript:: Error :: RelativeLockTime ( _) )
109+ ) ) ;
98110
99- // Test the Display impl
111+ // 4. Test the Display impl
100112 let display_string = format ! ( "{}" , error) ;
101- assert ! ( display_string. starts_with( "RelLockTime error:" ) ) ;
113+
114+ // FIX: Since the error is now wrapped in DescriptorError::Miniscript,
115+ // the string likely starts with "Miniscript error:" or similar.
116+ // Using .contains() is more robust for nested errors.
117+ assert ! (
118+ display_string. contains( "relative locktime" ) ,
119+ "Display string was: '{}'" ,
120+ display_string
121+ ) ;
102122}
0 commit comments