@@ -81,13 +81,18 @@ impl ShutdownScript {
81
81
/// This is only needed and valid for channels supporting `option_simple_close`. Please refer
82
82
/// to [BOLT-2] for more information.
83
83
///
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 .
86
86
///
87
87
/// [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 > {
89
91
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) ) )
91
96
}
92
97
93
98
/// 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
157
162
return instruction_iter. next ( ) . is_none ( ) ;
158
163
}
159
164
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.
163
167
//
164
168
// * `76` followed by `76` to `80` followed by exactly that many bytes
165
169
if ( 76 ..=80 ) . contains ( & bytes. len ( ) ) {
@@ -228,13 +232,15 @@ mod shutdown_script_tests {
228
232
use super :: ShutdownScript ;
229
233
230
234
use bitcoin:: opcodes;
231
- use bitcoin:: script:: { Builder , ScriptBuf } ;
235
+ use bitcoin:: script:: { Builder , PushBytes , ScriptBuf } ;
232
236
use bitcoin:: secp256k1:: Secp256k1 ;
233
237
use bitcoin:: secp256k1:: { PublicKey , SecretKey } ;
234
238
use bitcoin:: { WitnessProgram , WitnessVersion } ;
235
239
240
+ use crate :: ln:: channelmanager:: provided_init_features;
236
241
use crate :: prelude:: * ;
237
242
use crate :: types:: features:: InitFeatures ;
243
+ use crate :: util:: config:: UserConfig ;
238
244
239
245
fn pubkey ( ) -> bitcoin:: key:: PublicKey {
240
246
let secp_ctx = Secp256k1 :: signing_only ( ) ;
@@ -310,8 +316,9 @@ mod shutdown_script_tests {
310
316
#[ test]
311
317
fn generates_op_return_from_data ( ) {
312
318
let data = [ 6 ; 6 ] ;
319
+ let features = provided_init_features ( & UserConfig :: default ( ) ) ;
313
320
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 ( ) ;
315
322
assert ! ( shutdown_script. is_compatible( & simple_close_features( ) ) ) ;
316
323
assert ! ( !shutdown_script. is_compatible( & InitFeatures :: empty( ) ) ) ;
317
324
assert_eq ! ( shutdown_script. into_inner( ) , op_return_script) ;
@@ -370,5 +377,11 @@ mod shutdown_script_tests {
370
377
pushdata_vec. extend_from_slice ( & [ 1u8 ; 81 ] ) ;
371
378
let pushdata_script = ScriptBuf :: from_bytes ( pushdata_vec) ;
372
379
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 ; 81 ] [ ..] ;
384
+ let push_bytes: & PushBytes = big_buffer. try_into ( ) . unwrap ( ) ;
385
+ assert ! ( ShutdownScript :: new_op_return( & push_bytes, & features) . is_err( ) ) ;
373
386
}
374
387
}
0 commit comments