Skip to content

Commit 541193e

Browse files
committed
f - Add ShutdownScript::is_compatible
1 parent 0457359 commit 541193e

File tree

1 file changed

+59
-4
lines changed

1 file changed

+59
-4
lines changed

lightning/src/ln/script.rs

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,26 @@ impl ShutdownScript {
9999
ShutdownScriptImpl::Bolt2(_) => None,
100100
}
101101
}
102+
103+
/// Returns whether the shutdown script is compatible with the features as defined by BOLT #2.
104+
///
105+
/// Specifically, checks for compliance with feature `option_shutdown_anysegwit`.
106+
pub fn is_compatible(&self, features: &InitFeatures) -> bool {
107+
match &self.0 {
108+
ShutdownScriptImpl::Legacy(_) => true,
109+
ShutdownScriptImpl::Bolt2(script) => is_bolt2_compliant(script, features),
110+
}
111+
}
112+
}
113+
114+
fn is_bolt2_compliant(script: &Script, features: &InitFeatures) -> bool {
115+
if script.is_p2pkh() || script.is_p2sh() || script.is_v0_p2wpkh() || script.is_v0_p2wsh() {
116+
true
117+
} else if features.supports_shutdown_anysegwit() {
118+
script.is_witness_program() && script.as_bytes()[0] != SEGWIT_V0.into_u8()
119+
} else {
120+
false
121+
}
102122
}
103123

104124
impl From<PublicKey> for ShutdownScript {
@@ -119,10 +139,8 @@ impl TryFrom<(Script, &InitFeatures)> for ShutdownScript {
119139
type Error = InvalidShutdownScript;
120140

121141
fn try_from((script, features): (Script, &InitFeatures)) -> Result<Self, Self::Error> {
122-
if script.is_p2pkh() || script.is_p2sh() || script.is_v0_p2wpkh() || script.is_v0_p2wsh() {
142+
if is_bolt2_compliant(&script, features) {
123143
Ok(Self(ShutdownScriptImpl::Bolt2(script)))
124-
} else if features.supports_shutdown_anysegwit() && script.is_witness_program() && script.as_bytes()[0] != SEGWIT_V0.into_u8() {
125-
Ok(Self(ShutdownScriptImpl::Bolt2(script))) // option_shutdown_anysegwit
126144
} else {
127145
Err(InvalidShutdownScript(script))
128146
}
@@ -147,6 +165,7 @@ mod shutdown_script_tests {
147165
use bitcoin::blockdata::script::{Builder, Script};
148166
use bitcoin::secp256k1::Secp256k1;
149167
use bitcoin::secp256k1::key::{PublicKey, SecretKey};
168+
use ln::features::InitFeatures;
150169
use std::convert::TryFrom;
151170

152171
fn pubkey() -> bitcoin::util::ecdsa::PublicKey {
@@ -173,6 +192,8 @@ mod shutdown_script_tests {
173192
let p2wpkh_script = Script::new_v0_wpkh(&pubkey_hash);
174193

175194
let shutdown_script = ShutdownScript::from(pubkey.key);
195+
assert!(shutdown_script.is_compatible(&InitFeatures::known()));
196+
assert!(shutdown_script.is_compatible(&InitFeatures::known().clear_shutdown_anysegwit()));
176197
assert_eq!(shutdown_script.into_inner(), p2wpkh_script);
177198
}
178199

@@ -182,6 +203,8 @@ mod shutdown_script_tests {
182203
let p2pkh_script = Script::new_p2pkh(&pubkey_hash);
183204

184205
let shutdown_script = ShutdownScript::new_p2pkh(&pubkey_hash);
206+
assert!(shutdown_script.is_compatible(&InitFeatures::known()));
207+
assert!(shutdown_script.is_compatible(&InitFeatures::known().clear_shutdown_anysegwit()));
185208
assert_eq!(shutdown_script.into_inner(), p2pkh_script);
186209
assert!(ShutdownScript::try_from(p2pkh_script).is_ok());
187210
}
@@ -192,6 +215,8 @@ mod shutdown_script_tests {
192215
let p2sh_script = Script::new_p2sh(&script_hash);
193216

194217
let shutdown_script = ShutdownScript::new_p2sh(&script_hash);
218+
assert!(shutdown_script.is_compatible(&InitFeatures::known()));
219+
assert!(shutdown_script.is_compatible(&InitFeatures::known().clear_shutdown_anysegwit()));
195220
assert_eq!(shutdown_script.into_inner(), p2sh_script);
196221
assert!(ShutdownScript::try_from(p2sh_script).is_ok());
197222
}
@@ -202,6 +227,8 @@ mod shutdown_script_tests {
202227
let p2wpkh_script = Script::new_v0_wpkh(&pubkey_hash);
203228

204229
let shutdown_script = ShutdownScript::new_p2wpkh(&pubkey_hash);
230+
assert!(shutdown_script.is_compatible(&InitFeatures::known()));
231+
assert!(shutdown_script.is_compatible(&InitFeatures::known().clear_shutdown_anysegwit()));
205232
assert_eq!(shutdown_script.into_inner(), p2wpkh_script);
206233
assert!(ShutdownScript::try_from(p2wpkh_script).is_ok());
207234
}
@@ -212,19 +239,47 @@ mod shutdown_script_tests {
212239
let p2wsh_script = Script::new_v0_wsh(&script_hash);
213240

214241
let shutdown_script = ShutdownScript::new_p2wsh(&script_hash);
242+
assert!(shutdown_script.is_compatible(&InitFeatures::known()));
243+
assert!(shutdown_script.is_compatible(&InitFeatures::known().clear_shutdown_anysegwit()));
215244
assert_eq!(shutdown_script.into_inner(), p2wsh_script);
216245
assert!(ShutdownScript::try_from(p2wsh_script).is_ok());
217246
}
218247

248+
#[test]
249+
fn generates_segwit_from_v0_witness_program() {
250+
let witness_program = Script::new_witness_program(u5::try_from_u8(0).unwrap(), &[0; 20]);
251+
252+
let shutdown_script = ShutdownScript::new_witness_program(u5::try_from_u8(0).unwrap(), &[0; 20]);
253+
assert!(shutdown_script.is_compatible(&InitFeatures::known()));
254+
assert!(shutdown_script.is_compatible(&InitFeatures::known().clear_shutdown_anysegwit()));
255+
assert_eq!(shutdown_script.into_inner(), witness_program);
256+
}
257+
258+
#[test]
259+
fn generates_segwit_from_non_v0_witness_program() {
260+
let witness_program = Script::new_witness_program(u5::try_from_u8(16).unwrap(), &[0; 40]);
261+
262+
let shutdown_script = ShutdownScript::new_witness_program(u5::try_from_u8(16).unwrap(), &[0; 40]);
263+
assert!(shutdown_script.is_compatible(&InitFeatures::known()));
264+
assert!(!shutdown_script.is_compatible(&InitFeatures::known().clear_shutdown_anysegwit()));
265+
assert_eq!(shutdown_script.into_inner(), witness_program);
266+
}
267+
219268
#[test]
220269
fn fails_from_unsupported_script() {
221270
let op_return = Script::new_op_return(&[0; 42]);
222271
assert!(ShutdownScript::try_from(op_return).is_err());
223272
}
224273

225274
#[test]
226-
fn fails_from_invalid_segwit_v0_program() {
275+
fn fails_from_invalid_segwit_v0_witness_program() {
227276
let witness_program = Script::new_witness_program(u5::try_from_u8(0).unwrap(), &[0; 2]);
228277
assert!(ShutdownScript::try_from(witness_program).is_err());
229278
}
279+
280+
#[test]
281+
fn fails_from_invalid_segwit_non_v0_witness_program() {
282+
let witness_program = Script::new_witness_program(u5::try_from_u8(16).unwrap(), &[0; 42]);
283+
assert!(ShutdownScript::try_from(witness_program).is_err());
284+
}
230285
}

0 commit comments

Comments
 (0)