@@ -81,13 +81,18 @@ impl ShutdownScript {
8181 /// This is only needed and valid for channels supporting `option_simple_close`. Please refer
8282 /// to [BOLT-2] for more information.
8383 ///
84- /// Note this only supports creating a script with data of up to 76 bytes length via
85- /// [`PushBytes`] .
84+ /// Will return [`InvalidShutdownScript`] if the given data is not [BOLT-2] compliant based on
85+ /// the given features .
8686 ///
8787 /// [BOLT-2]: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#closing-negotiation-closing_complete-and-closing_sig
88- pub fn new_op_return < T : AsRef < PushBytes > > ( data : T ) -> Self {
88+ pub fn new_op_return < T : AsRef < PushBytes > > (
89+ data : T , features : & InitFeatures ,
90+ ) -> Result < Self , InvalidShutdownScript > {
8991 let script = ScriptBuf :: new_op_return ( data) ;
90- Self ( ShutdownScriptImpl :: Bolt2 ( script) )
92+ if !is_bolt2_compliant ( & script, features) {
93+ return Err ( InvalidShutdownScript { script } ) ;
94+ }
95+ Ok ( Self ( ShutdownScriptImpl :: Bolt2 ( script) ) )
9196 }
9297
9398 /// Generates a witness script pubkey from the given segwit version and program.
@@ -157,9 +162,8 @@ pub(crate) fn is_bolt2_compliant(script: &Script, features: &InitFeatures) -> bo
157162 return instruction_iter. next ( ) . is_none ( ) ;
158163 }
159164
160- // While `rust-bitcoin` doesn't allow to construct `PushBytes` from arrays
161- // longer than 75 bytes, itself curiously interprets `OP_PUSHDATA1` as
162- // `Instruction::PushBytes`, having us land here in this case, too.
165+ // `rust-bitcoin` interprets `OP_PUSHDATA1` as `Instruction::PushBytes`, having
166+ // us land here in this case, too.
163167 //
164168 // * `76` followed by `76` to `80` followed by exactly that many bytes
165169 if ( 76 ..=80 ) . contains ( & bytes. len ( ) ) {
@@ -228,13 +232,15 @@ mod shutdown_script_tests {
228232 use super :: ShutdownScript ;
229233
230234 use bitcoin:: opcodes;
231- use bitcoin:: script:: { Builder , ScriptBuf } ;
235+ use bitcoin:: script:: { Builder , PushBytes , ScriptBuf } ;
232236 use bitcoin:: secp256k1:: Secp256k1 ;
233237 use bitcoin:: secp256k1:: { PublicKey , SecretKey } ;
234238 use bitcoin:: { WitnessProgram , WitnessVersion } ;
235239
240+ use crate :: ln:: channelmanager:: provided_init_features;
236241 use crate :: prelude:: * ;
237242 use crate :: types:: features:: InitFeatures ;
243+ use crate :: util:: config:: UserConfig ;
238244
239245 fn pubkey ( ) -> bitcoin:: key:: PublicKey {
240246 let secp_ctx = Secp256k1 :: signing_only ( ) ;
@@ -310,8 +316,9 @@ mod shutdown_script_tests {
310316 #[ test]
311317 fn generates_op_return_from_data ( ) {
312318 let data = [ 6 ; 6 ] ;
319+ let features = provided_init_features ( & UserConfig :: default ( ) ) ;
313320 let op_return_script = ScriptBuf :: new_op_return ( & data) ;
314- let shutdown_script = ShutdownScript :: new_op_return ( & data) ;
321+ let shutdown_script = ShutdownScript :: new_op_return ( & data, & features ) . unwrap ( ) ;
315322 assert ! ( shutdown_script. is_compatible( & simple_close_features( ) ) ) ;
316323 assert ! ( !shutdown_script. is_compatible( & InitFeatures :: empty( ) ) ) ;
317324 assert_eq ! ( shutdown_script. into_inner( ) , op_return_script) ;
@@ -370,5 +377,11 @@ mod shutdown_script_tests {
370377 pushdata_vec. extend_from_slice ( & [ 1u8 ; 81 ] ) ;
371378 let pushdata_script = ScriptBuf :: from_bytes ( pushdata_vec) ;
372379 assert ! ( ShutdownScript :: try_from( pushdata_script) . is_err( ) ) ;
380+
381+ // - In `ShutdownScript::new_op_return` the OP_RETURN data is longer than 80 bytes.
382+ let features = provided_init_features ( & UserConfig :: default ( ) ) ;
383+ let big_buffer = & [ 0xfau8 ; 80 ] [ ..] ;
384+ let push_bytes: & PushBytes = big_buffer. try_into ( ) . unwrap ( ) ;
385+ assert ! ( ShutdownScript :: new_op_return( & push_bytes, & features) . is_err( ) ) ;
373386 }
374387}
0 commit comments