Skip to content

smite-ir: implement NodeAnnouncementGenerator#93

Merged
morehouse merged 3 commits into
masterfrom
node_announcement_generator
May 26, 2026
Merged

smite-ir: implement NodeAnnouncementGenerator#93
morehouse merged 3 commits into
masterfrom
node_announcement_generator

Conversation

@morehouse
Copy link
Copy Markdown
Owner

@morehouse morehouse commented May 22, 2026

Generates programs that send correctly-signed node_announcement messages to the target.

Verified that all 4 targets successfully decode the node_announcements we send and pass initial validation, including signature checks (except LND, which only checks signatures if we send a matching channel_announcement first). Once we can send channel_announcements that match the node_announcements, we will be able to exercise even deeper code paths.

ldk-coverage.tar.gz
lnd-coverage.tar.gz
cln-coverage.tar.gz
eclair-coverage.tar.gz

Ref: #71

Comment thread smite-ir-mutator/src/lib.rs Outdated
@@ -64,7 +64,11 @@ impl MutatorState {
/// Generates a fresh program from scratch using `OpenChannelGenerator`.
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.

rustdoc needs to be updated

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 on lines +22 to +27
let mut alias = [0u8; 32];
for b in &mut alias {
// BOLT 7 requires alias to be valid UTF-8, which Eclair actually
// enforces on decode.
*b = rng.random_range(0x00..=0x7F);
}
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 am assuming this is done just to give the fuzzer both valid UTF-8 and invalid UTF-8 paths, since after mutation the alias can certainly end up containing invalid UTF-8

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 think this is done so the initial alias is always valid UTF-8

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.

It turns out 32 completely random bytes are extremely unlikely to be valid UTF-8. LND, LDK, and CLN don't care about valid UTF-8 aliases for initial validation, but Eclair rejects such messages immediately.

This line just limits to ASCII characters to ensure valid UTF-8 initially, while mutators are still able to create invalid aliases.

BTW I discovered a signature-verification issue in Eclair while exploring this: ACINQ/eclair#3314.

Comment thread smite-ir/src/tests.rs
);
}

fn generate_node_announcement_program(seed: u64) -> Program {
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.

generate_open_channel_program has 2 more tests that we could also add for generate_node_announcement_program if you want parity with open channel generator (since I see a lot of the same cases): validate_accepts_generated_program and generated_program_postcard_roundtrip.

Though they do not really test very different invariants, so it's up to you whether you want to add them

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.

Added both tests.

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.

LGTM!

ldk-coverage.tar.gz
lnd-coverage.tar.gz
cln-coverage.tar.gz
eclair-coverage.tar.gz

Mhh, maybe this could be added to CI.

Btw, why is branch coverage always - (0/0) for LDK? This doesn't mention it needs to be enabled, and bdk_wallet-2.3.0/src/wallet/changeset.rs contains branches in ChangeSet::merge(), and there is branch coverage for CLN.

Comment on lines +22 to +27
let mut alias = [0u8; 32];
for b in &mut alias {
// BOLT 7 requires alias to be valid UTF-8, which Eclair actually
// enforces on decode.
*b = rng.random_range(0x00..=0x7F);
}
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 think this is done so the initial alias is always valid UTF-8

Comment on lines +19 to +20
// rgb_color and alias are op-level params (not variable inputs) so the
// mutator can flip bits inside them without changing their lengths.
Copy link
Copy Markdown
Contributor

@ekzyis ekzyis May 26, 2026

Choose a reason for hiding this comment

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

nit: Do we expect there to be more cases? Wondering if this means we're missing a VariableType, like FixedBytes or UTF8.

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.

I don't think there's currently any other 3-byte fields or 32-byte UTF-8 that would benefit from a dedicated variable type. rgb_color and alias are mostly cosmetic, and I would be surprised if we found a benefit to cross-pollinating them between different messages. Of course we can always do that later if we do find some benefit.

morehouse added 3 commits May 26, 2026 15:16
Builds and sends a signed node_announcement message.
We now have two types of programs generated: open_channel programs and
node_announcement programs.  Rename relevant tests and helpers for
clarity.
@morehouse morehouse force-pushed the node_announcement_generator branch from 1c7d0b3 to 7414ea8 Compare May 26, 2026 20:18
@morehouse
Copy link
Copy Markdown
Owner Author

Mhh, maybe this could be added to CI.

My goal is for Smitebot (#70) to help with this eventually. The goal is to have a server constantly fuzzing with the smite master branch and generating updated coverage reports each day.

Btw, why is branch coverage always - (0/0) for LDK? This doesn't mention it needs to be enabled, and bdk_wallet-2.3.0/src/wallet/changeset.rs contains branches in ChangeSet::merge(), and there is branch coverage for CLN.

I looked into this and discovered the unstable -Z coverage-options=branch option that should give us branch instrumentation. But when I attempted to use it on LDK I got segfaults. It looks like this LLVM bug: llvm/llvm-project#189169.

So at least for now we're stuck with just line coverage.

@morehouse morehouse merged commit 995ae87 into master May 26, 2026
5 checks passed
@morehouse morehouse deleted the node_announcement_generator branch May 26, 2026 20:25
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