') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Classify onchain transactions by tnull · Pull Request #791 · lightningdevkit/ldk-node · GitHub
Skip to content

Classify onchain transactions - #791

Merged
tnull merged 4 commits into
lightningdevkit:mainfrom
tnull:2026-02-track-onchain-tx-types
Jul 9, 2026
Merged

Classify onchain transactions#791
tnull merged 4 commits into
lightningdevkit:mainfrom
tnull:2026-02-track-onchain-tx-types

Conversation

@tnull

@tnulltnull commented Feb 11, 2026

Copy link
Copy Markdown
Collaborator

Fixes#447.

In #888 we started exposing TransactionType for funding-related transactions. Here, we continue that work and also classify the remaining transaction types so they are shown in the payment store.

@tnulltnull added this to the 0.8 milestone Feb 11, 2026
@tnulltnull self-assigned this Feb 11, 2026
@ldk-reviews-bot

ldk-reviews-bot commented Feb 11, 2026

Copy link
Copy Markdown

👋 Thanks for assigning @jkczyz 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.

@tnull
tnull marked this pull request as draft February 11, 2026 14:40
@tnulltnull moved this to Goal: Merge in Weekly GoalsFeb 11, 2026
@tnulltnull changed the title 2026 02 track onchain tx typesClassify onchain transactionsFeb 11, 2026
Comment threadsrc/payment/store.rs
/// The confirmation status of this payment.
status: ConfirmationStatus,
/// The type of the on-chain transaction, if known.
tx_type: Option<TransactionType>,

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, we should probably just default to Onchain if we don't know what it is.

Comment threadsrc/tx_broadcaster.rs Outdated
{
queue_sender: mpsc::Sender<Vec<Transaction>>,
queue_receiver: Mutex<mpsc::Receiver<Vec<Transaction>>>,
tx_types: std::sync::Mutex<HashMap<Txid, TransactionType>>,

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.

If we broadcast the transaction but restart before the wallet syncs, won't we lose this data?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yeah, we need to double-check whether we need to persist this. I think most channel-related transactions will be regenerated/rebroadcast after restart, but not sure if that would be the case for splice-related data?

jkczyz added a commit to jkczyz/ldk-node that referenced this pull request Jun 25, 2026
On-chain payment records don't capture what a transaction was for -- a
channel open, splice, close, sweep, or a plain send. Record that
classification on each on-chain payment, derived from the type LDK
reports when broadcasting the transaction, so it survives restarts
alongside the payment.
The tag keeps only which channels a transaction relates to; amounts and
fees stay on the payment. Existing records keep decoding unchanged.
Compatible with the on-chain transaction classification proposed in lightningdevkit#791.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jkczyz added a commit to jkczyz/ldk-node that referenced this pull request Jun 26, 2026
On-chain payment records don't capture what a transaction was for -- a
channel open, splice, close, sweep, or a plain send. Record that
classification on each on-chain payment, derived from the type LDK
reports when broadcasting the transaction, so it survives restarts
alongside the payment.
The tag keeps only which channels a transaction relates to; amounts and
fees stay on the payment. Existing records keep decoding unchanged.
Compatible with the on-chain transaction classification proposed in lightningdevkit#791.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jkczyz added a commit to jkczyz/ldk-node that referenced this pull request Jun 26, 2026
On-chain payment records don't capture what a transaction was for -- a
channel open, splice, close, sweep, or a plain send. Record that
classification on each on-chain payment, derived from the type LDK
reports when broadcasting the transaction, so it survives restarts
alongside the payment.
The tag keeps only which channels a transaction relates to; amounts and
fees stay on the payment. Existing records keep decoding unchanged.
Compatible with the on-chain transaction classification proposed in lightningdevkit#791.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tnull
tnullforce-pushed the 2026-02-track-onchain-tx-types branch from d0dfd93 to e487cddCompareJune 29, 2026 14:04
@tnull
tnull requested a review from jkczyzJune 29, 2026 14:06
@tnull
tnull marked this pull request as ready for review June 29, 2026 14:06
@tnull
tnullforce-pushed the 2026-02-track-onchain-tx-types branch from e487cdd to 811ddebCompareJune 29, 2026 14:06
Comment threadsrc/wallet/mod.rs Outdated
Comment on lines 1718 to 1725

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.

Should we persist before broadcasting like we do for splices?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Done in a fixup.

@tnull
tnullforce-pushed the 2026-02-track-onchain-tx-types branch from 811ddeb to 57b7115CompareJuly 6, 2026 11:03
@tnull
tnull requested a review from jkczyzJuly 6, 2026 11:03

@jkczyzjkczyz left a comment

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.

LGTM. Please squash

@tnull
tnullforce-pushed the 2026-02-track-onchain-tx-types branch from 57b7115 to 0bca623CompareJuly 7, 2026 07:42
@tnull
tnull requested a review from jkczyzJuly 8, 2026 06:50
jkczyz
jkczyz previously approved these changes Jul 8, 2026
@jkczyz

Copy link
Copy Markdown
Contributor

Oops, looks like this needs a rebase.

Use the receiver node for receive-side on-chain checks.
Co-Authored-By: HAL 9000
tnull added 3 commits July 8, 2026 16:12
Avoid tagging ordinary wallet sends and rebroadcasts as LDK sweeps.
They should remain on-chain payments with no transaction type.
Co-Authored-By: HAL 9000
Keep known on-chain transaction types across wallet sync updates.
Co-Authored-By: HAL 9000
Record close, claim, anchor-bump, and sweep broadcasts.
Wallet sync can then retain the LDK transaction type.
Co-Authored-By: HAL 9000
@tnull
tnullforce-pushed the 2026-02-track-onchain-tx-types branch from 0bca623 to d66e53fCompareJuly 8, 2026 14:23
@tnull
tnull requested a review from jkczyzJuly 8, 2026 14:24
@tnull

tnull commented Jul 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Oops, looks like this needs a rebase.

Rebased

@tnull

tnull commented Jul 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Failing test is unrelated flake (passes locally), need to fix in another PR

@tnull
tnull merged commit 942087b into lightningdevkit:mainJul 9, 2026
17 of 23 checks passed
@github-project-automationgithub-project-automationBot moved this from Goal: Merge to Done in Weekly GoalsJul 9, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Create new PaymentKind variants for channel funding/closing on-chain transactions

3 participants

@tnull@ldk-reviews-bot@jkczyz