Skip to content

smite-ir: generate compliant shutdown scripts#58

Open
morehouse wants to merge 2 commits intomasterfrom
ir_shutdown_script
Open

smite-ir: generate compliant shutdown scripts#58
morehouse wants to merge 2 commits intomasterfrom
ir_shutdown_script

Conversation

@morehouse
Copy link
Copy Markdown
Owner

Helps the fuzzer choose BOLT 2 compliant shutdown scripts so that deeper paths can be reached in the open_channel->accept_channel flow.

This change in combination with #57 are required to get past open_channel message validation in LDK.

Ref: #5 (Milestone 1)

In the following commit, we will need to mutate fixed byte arrays that
are not 32 bytes long.
Copy link
Copy Markdown
Contributor

@NishantBansal2003 NishantBansal2003 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Comment thread smite-ir/src/operation.rs
Comment on lines +106 to +109
/// `OP_DUP OP_HASH160 <20-byte hash> OP_EQUALVERIFY OP_CHECKSIG`.
P2pkh([u8; 20]),
/// `OP_HASH160 <20-byte hash> OP_EQUAL`.
P2sh([u8; 20]),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see legacy P2PKH or P2SH mentioned in BOLT 2 (https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#requirements-31)

However, from the code, I can see that CLN, LDK, and Eclair accept them, but LND does not (is it fine to have it like this?)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bolt02 mentions this:

The scriptpubkey forms include only standard segwit forms accepted by the Bitcoin network, which ensures the resulting transaction will propagate to miners. However old nodes may send non-segwit scripts, which may be accepted for backwards-compatibility (with a caveat to force-close if this output doesn't meet dust relay requirements).

So I think it's for backward compatibility and LND started to drop it

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, those types have been removed from the spec. But since the legacy code exists in multiple implementations, I figured we should exercise that code.

Copy link
Copy Markdown
Contributor

@ekzyis ekzyis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one typo, LGTM otherwise

Comment thread smite-ir/src/operation.rs
Comment on lines +106 to +109
/// `OP_DUP OP_HASH160 <20-byte hash> OP_EQUALVERIFY OP_CHECKSIG`.
P2pkh([u8; 20]),
/// `OP_HASH160 <20-byte hash> OP_EQUAL`.
P2sh([u8; 20]),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bolt02 mentions this:

The scriptpubkey forms include only standard segwit forms accepted by the Bitcoin network, which ensures the resulting transaction will propagate to miners. However old nodes may send non-segwit scripts, which may be accepted for backwards-compatibility (with a caveat to force-close if this output doesn't meet dust relay requirements).

So I think it's for backward compatibility and LND started to drop it

Comment on lines +331 to +334
// Always send the TLV: a zero-length value is the BOLT 2 opt-out
// signal when option_upfront_shutdown_script is negotiated.
// Omitting it is a protocol violation in that case.
upfront_shutdown_script: Some(resolve_bytes(variables, inputs[18])?.to_vec()),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I verified that it's also okay to send upfront_shutdown_script when we did not signal option_upfront_shutdown_script during init exchange.

I see that this is documented for ShutdownScriptVariant:

accepted regardless of feature negotiation.

Could make sense to also add a small note here?

diff --git a/smite-scenarios/src/executor.rs b/smite-scenarios/src/executor.rs
index f05481a..b0e541e 100644
--- a/smite-scenarios/src/executor.rs
+++ b/smite-scenarios/src/executor.rs
@@ -330,7 +330,8 @@ fn build_open_channel(
         tlvs: OpenChannelTlvs {
             // Always send the TLV: a zero-length value is the BOLT 2 opt-out
             // signal when option_upfront_shutdown_script is negotiated.
-            // Omitting it is a protocol violation in that case.
+            // Omitting it is a protocol violation in that case. Including if
+            // not negotiated is not.
             upfront_shutdown_script: Some(resolve_bytes(variables, inputs[18])?.to_vec()),
             channel_type: nonempty_or_none(resolve_features(variables, inputs[19])?),
         },

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment thread smite-ir/src/operation.rs Outdated
/// `ANYSEGWIT_MIN_VERSION..=ANYSEGWIT_MAX_VERSION`, if the program is
/// outside `ANYSEGWIT_MIN_PROGRAM_LEN..=ANYSEGWIT_MAX_PROGRAM_LEN` bytes,
/// or if `OpReturn` data is outside
/// `OP_RETURN_MAX_DATA_LEN..=OP_RETURN_MAX_DATA_LEN` bytes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// `OP_RETURN_MAX_DATA_LEN..=OP_RETURN_MAX_DATA_LEN` bytes.
/// `OP_RETURN_MIN_DATA_LEN..=OP_RETURN_MAX_DATA_LEN` bytes.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Done.

Comment thread smite-ir/src/operation.rs
Self::Empty => Vec::new(),
Self::P2pkh(h) => {
let mut out = Vec::with_capacity(25);
out.extend_from_slice(&[0x76, 0xa9, 0x14]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: #51 adds the bitcoin crate. We could then use bitcoin::opcodes here in a follow-up PR. But it would require casting OpCode to u8 or updating our types to use OpCode instead of u8.

Helps the fuzzer choose BOLT 2 compliant shutdown scripts so that deeper
paths can be reached in the open_channel->accept_channel flow.
@morehouse morehouse force-pushed the ir_shutdown_script branch from 8475d0d to 752608f Compare April 30, 2026 17:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants