Skip to content

Check correct merkle leaf size and validate txids on Electrum#4675

Merged
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-06-merkle-base-size
Jun 17, 2026
Merged

Check correct merkle leaf size and validate txids on Electrum#4675
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-06-merkle-base-size

Conversation

@tnull

@tnull tnull commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Just a few minor Electrum/Esplora fixes.

These findings were discovered by Project Loupe.

@ldk-reviews-bot

ldk-reviews-bot commented Jun 10, 2026

Copy link
Copy Markdown

👋 Thanks for assigning @wpaulino as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

Comment thread lightning-transaction-sync/src/electrum.rs
@ldk-claude-review-bot

ldk-claude-review-bot commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

I re-reviewed the current commit (1d13150) against my prior findings and verified the actual code state.

Correction to a prior finding: My earlier "output-spend path lacks the merkle-leaf check" asymmetry finding (inline at electrum.rs:376) was a false positive. The is_potentially_unsafe_merkle_leaf base-size check lives inside get_confirmed_tx (electrum.rs:468), and both the watched-transactions path (electrum.rs:343) and the watched-output spend path (electrum.rs:393) route through it. The output-spend path is therefore protected, so there is no residual 64-byte-leaf attack surface there. Please disregard that prior comment.

New inline comment posted:

  • lightning-transaction-sync/src/esplora.rs:394-395 — Stale comment ("at least 65 bytes in length") no longer matches the actual check (base_size() == 64).

Still standing (minor, previously noted, not re-posted inline):

  • The transaction_get_responses_are_verified_at_call_sites test (electrum.rs:545) asserts on source text via include_str! + concat! rather than behavior — brittle to refactors.

The core fix is correct: base_size() is the right metric for the 64-byte merkle-leaf weakness, and the added Electrum txid verifications correctly mirror Esplora's. No functional bugs found in this pass.

@ldk-reviews-bot ldk-reviews-bot requested a review from wpaulino June 10, 2026 14:24
@wpaulino

Copy link
Copy Markdown
Contributor

LGTM once the bot's comment is addressed

@tnull tnull self-assigned this Jun 11, 2026
@tnull tnull force-pushed the 2026-06-merkle-base-size branch from 57524e3 to 35e8dac Compare June 11, 2026 16:42
@tnull

tnull commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

Updated to line-wrap commit messages.

@ldk-reviews-bot

Copy link
Copy Markdown

🔔 1st Reminder

Hey @wpaulino! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot

Copy link
Copy Markdown

🔔 2nd Reminder

Hey @wpaulino! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@wpaulino wpaulino removed their request for review June 15, 2026 17:33
tnull added 3 commits June 17, 2026 09:07
Electrum confirmation checks must reject transactions whose non-witness
serialization is 64 bytes, since txids and Merkle leaves are computed
from that serialization. Witness padding can otherwise move total_size
above 64 without removing the inner-node ambiguity.

Co-Authored-By: HAL 9000

This finding was discovered by Project Loupe
Esplora confirmation checks must use the non-witness transaction size
for the 64-byte Merkle leaf guard. Witness padding can otherwise raise
total_size without changing the serialization hashed into the txid and
Merkle tree.

Co-Authored-By: HAL 9000

This finding was discovered by Project Loupe
Electrum confirmations must reject transaction_get responses whose body
does not compute the requested txid. Otherwise a malicious server can
substitute an unrelated transaction and provide matching Merkle data for
the substituted body.

Co-Authored-By: HAL 9000

This finding was discovered by Project Loupe
@tnull tnull force-pushed the 2026-06-merkle-base-size branch from 35e8dac to 1d13150 Compare June 17, 2026 07:22
@tnull tnull requested a review from wpaulino June 17, 2026 07:22
Comment thread lightning-transaction-sync/src/esplora.rs

@TheBlueMatt TheBlueMatt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks. Given these are just validation against a malicious server, which can certainly screw us in many other ways, is there a strong reason to want to backport this? Note that this does not resolve the issue of the merkle-tree-extension attack, where a valid transaction included in a block is 64 bytes and collides with a hash such that a proof can be forged for a different transaction. That is ultimately only solved by requesting a proof for the coinbase transaction in parallel, which I don't think is worth doing.

@TheBlueMatt TheBlueMatt merged commit 0e9734c into lightningdevkit:main Jun 17, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants