Skip to content

Commit 6746a16

Browse files
committed
Minor updates after feedback
* An empty script is only allowed when sent as upfront shutdown script, so make sure that check is only done for accept/open_channel situations. * Instead of reimplementing a variant of is_witness_script, just call it and verify that the witness version is not 0. * Fixed an outdated comment after a test copy/paste.
1 parent ffaca7f commit 6746a16

File tree

2 files changed

+13
-36
lines changed

2 files changed

+13
-36
lines changed

lightning/src/ln/channel.rs

Lines changed: 12 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use std::ops::Deref;
4545
#[cfg(any(test, feature = "fuzztarget"))]
4646
use std::sync::Mutex;
4747
use bitcoin::hashes::hex::ToHex;
48+
use bitcoin::blockdata::opcodes::all::OP_PUSHBYTES_0;
4849

4950
#[cfg(test)]
5051
pub struct ChannelValueStat {
@@ -737,12 +738,12 @@ impl<Signer: Sign> Channel<Signer> {
737738
let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() {
738739
match &msg.shutdown_scriptpubkey {
739740
&OptionalField::Present(ref script) => {
740-
if is_unsupported_shutdown_script(&their_features, script) {
741-
return Err(ChannelError::Close(format!("Peer is signaling upfront_shutdown but has provided a non-accepted scriptpubkey format. script: ({})", script.to_bytes().to_hex())));
742-
}
743-
741+
// Peer is signaling upfront_shutdown and has opt-out with a 0-length script. We don't enforce anything
744742
if script.len() == 0 {
745743
None
744+
// Peer is signaling upfront_shutdown and has provided a non-accepted scriptpubkey format. Fail the channel
745+
} else if is_unsupported_shutdown_script(&their_features, script) {
746+
return Err(ChannelError::Close(format!("Peer is signaling upfront_shutdown but has provided a non-accepted scriptpubkey format. script: ({})", script.to_bytes().to_hex())));
746747
} else {
747748
Some(script.clone())
748749
}
@@ -1438,12 +1439,12 @@ impl<Signer: Sign> Channel<Signer> {
14381439
let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() {
14391440
match &msg.shutdown_scriptpubkey {
14401441
&OptionalField::Present(ref script) => {
1441-
if is_unsupported_shutdown_script(&their_features, script) {
1442-
return Err(ChannelError::Close(format!("Peer is signaling upfront_shutdown but has provided a non-accepted scriptpubkey format. script: ({})", script.to_bytes().to_hex())));
1443-
}
1444-
1442+
// Peer is signaling upfront_shutdown and has opt-out with a 0-length script. We don't enforce anything
14451443
if script.len() == 0 {
14461444
None
1445+
// Peer is signaling upfront_shutdown and has provided a non-accepted scriptpubkey format. Fail the channel
1446+
} else if is_unsupported_shutdown_script(&their_features, script) {
1447+
return Err(ChannelError::Close(format!("Peer is signaling upfront_shutdown but has provided a non-accepted scriptpubkey format. script: ({})", script.to_bytes().to_hex())));
14471448
} else {
14481449
Some(script.clone())
14491450
}
@@ -4211,40 +4212,16 @@ impl<Signer: Sign> Channel<Signer> {
42114212
fn is_unsupported_shutdown_script(their_features: &InitFeatures, script: &Script) -> bool {
42124213
// We restrain shutdown scripts to standards forms to avoid transactions not propagating on the p2p tx-relay network
42134214

4214-
// Providing an empty is supported
4215-
let script_lenght = script.len();
4216-
if script_lenght == 0 {
4217-
return false;
4218-
}
4219-
42204215
// BOLT 2 says we must only send a scriptpubkey of certain standard forms,
42214216
// which for a a BIP-141-compliant witness program is at max 42 bytes in length.
42224217
// So don't let the remote peer feed us some super fee-heavy script.
4223-
let is_script_too_long = script_lenght > 42;
4218+
let is_script_too_long = script.len() > 42;
42244219
if is_script_too_long {
42254220
return true;
42264221
}
42274222

4228-
if their_features.supports_shutdown_anysegwit() {
4229-
// A scriptPubKey (or redeemScript as defined in BIP16/P2SH) that consists of a 1-byte
4230-
// push opcode (for 1 to 16) followed by a data push between 2 and 40 bytes gets a new
4231-
// special meaning.
4232-
let min_vernum: u8 = opcodes::all::OP_PUSHNUM_1.into_u8();
4233-
let max_vernum: u8 = opcodes::all::OP_PUSHNUM_16.into_u8();
4234-
let script_bytes = script.as_bytes();
4235-
let is_anysegwit = script.len() >= 3
4236-
&& script.len() <= 42
4237-
// PUSHNUM_1-PUSHNUM_16
4238-
&& (script_bytes[0] >= min_vernum && script_bytes[0] <= max_vernum)
4239-
// Second byte push opcode 2-40 bytes
4240-
&& script_bytes[1] >= opcodes::all::OP_PUSHBYTES_2.into_u8()
4241-
&& script_bytes[1] <= opcodes::all::OP_PUSHBYTES_40.into_u8()
4242-
// Check that the rest of the script has the correct size
4243-
&& script.len() - 2 == script_bytes[1] as usize;
4244-
4245-
if is_anysegwit {
4246-
return false;
4247-
}
4223+
if their_features.supports_shutdown_anysegwit() && script.is_witness_program() && script.as_bytes()[0] != OP_PUSHBYTES_0.into_u8() {
4224+
return false;
42484225
}
42494226

42504227
return !script.is_p2pkh() && !script.is_p2sh() && !script.is_v0_p2wpkh() && !script.is_v0_p2wsh()

lightning/src/ln/functional_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7369,7 +7369,7 @@ fn test_shutdown_script_segwit_but_not_anysegwit() {
73697369
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &user_cfgs);
73707370
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
73717371

7372-
//// We test that if the remote peer does not accept opt_shutdown_anysegwit, the witness program cannot be used on shutdown
7372+
//// We test that if shutdown any segwit is supported and we send a witness script with 0 version, this is not accepted
73737373
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, InitFeatures::known(), InitFeatures::known());
73747374
nodes[1].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id()).unwrap();
73757375
let mut node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());

0 commit comments

Comments
 (0)