Include counterpart_node_id in TransactionType - #4393

Merged
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-02-include-counterparty-node-id
Feb 6, 2026
Merged

Include counterpart_node_id in TransactionType#4393
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-02-include-counterparty-node-id

Conversation

@tnull

@tnulltnull commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

Closes#4391

In #4353 we added a TransactionType that also indicated the ChannelIds associated with the broadcasted transaction. However, as pointed out there, ChannelIds might are always just guranteed to be unique on a per-counterparty basis.

Therefore, we here track the counterparty_node_id side-by-side with the ChannelId, which notably also requires to track it as part of Event::SpendableOutputs and in OutputSweeper.

@ldk-reviews-bot

ldk-reviews-bot commented Feb 6, 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.

if let Some(channel_id) = output_info.channel_id {
if !channel_ids.contains(&channel_id) {
channel_ids.push(channel_id);
if let (Some(counterparty_node_id), Some(channel_id)) =

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Want to point out that this will result in an empty channels for already-tracked entries on upgrade. We'll need to see how to handle that case downstream I guess. Technically we'd need to make the tracking an Option<PublicKey> but that's just odd.

This adds an optional `counterparty_node_id` field to the
`SpendableOutputs` event, providing users with information about which
channel counterparty the spendable outputs belong to.
The field uses TLV type 3 (odd) for backwards compatibility, meaning
older versions will safely ignore it during deserialization. When
reading events serialized by older LDK versions, this field will be
`None`.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This adds an optional `counterparty_node_id` field to
`TrackedSpendableOutput` and updates the `track_spendable_outputs`
method signatures on both `OutputSweeper` and `OutputSweeperSync` to
accept this new parameter.
The field uses TLV type 3 (odd) for backwards compatibility. When
reading outputs tracked with LDK 0.2 and prior, this field will be
`None`.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This adds `counterparty_node_id` tracking to all `TransactionType`
variants, enabling downstream users to identify the channel counterparty
associated with each broadcast transaction.
For single-channel variants (`CooperativeClose`, `UnilateralClose`,
`AnchorBump`, `Claim`, `Splice`), the counterparty is stored directly.
For multi-channel variants (`Funding`, `Sweep`), the type now uses
`Vec<(PublicKey, ChannelId)>` to pair each channel with its counterparty.
The `OnchainTxHandler` now stores `counterparty_node_id` and provides a
`set_counterparty_node_id` method for initialization during
deserialization of older data.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
@tnull
tnullforce-pushed the 2026-02-include-counterparty-node-id branch from ad4cc6c to 56f12c8CompareFebruary 6, 2026 12:25
.list_channels()
.into_iter()
.any(|cd| cd.channel_id == ch_id && cd.is_channel_ready);
.find(|cd| cd.channel_id == ch_id && cd.is_channel_ready);

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.

might make sense to filter by UCID here as well. Technically channel id isn't unique for 0confs even if is_channel_ready.

@TheBlueMatt
TheBlueMatt merged commit 94d1e5e into lightningdevkit:mainFeb 6, 2026
17 of 19 checks passed
@codecov

codecovBot commented Feb 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.46602% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.02%. Comparing base (372ba65) to head (56f12c8).
⚠️ Report is 13 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channelmanager.rs60.00%8 Missing ⚠️
lightning/src/ln/channel.rs50.00%5 Missing ⚠️
lightning/src/util/sweep.rs82.35%1 Missing and 2 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4393 +/- ##
==========================================
- Coverage 86.04% 86.02% -0.02% 
==========================================
Files 156 156 Lines 103002 103046 +44 Branches 103002 103046 +44 ==========================================
+ Hits 88627 88646 +19 - Misses 11865 11888 +23 - Partials 2510 2512 +2 
FlagCoverage Δ
tests86.02% <84.46%> (-0.02%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for freeto 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.

Add counterparty node ids (+ user channel ids) to TransactionType

3 participants

@tnull@ldk-reviews-bot@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Include counterpart_node_id in TransactionType - #4393

Merged
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-02-include-counterparty-node-id
Feb 6, 2026
Merged

Include counterpart_node_id in TransactionType#4393
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-02-include-counterparty-node-id

Conversation

@tnull

@tnulltnull commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

Closes#4391

In #4353 we added a TransactionType that also indicated the ChannelIds associated with the broadcasted transaction. However, as pointed out there, ChannelIds might are always just guranteed to be unique on a per-counterparty basis.

Therefore, we here track the counterparty_node_id side-by-side with the ChannelId, which notably also requires to track it as part of Event::SpendableOutputs and in OutputSweeper.

@ldk-reviews-bot

ldk-reviews-bot commented Feb 6, 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.

if let Some(channel_id) = output_info.channel_id {
if !channel_ids.contains(&channel_id) {
channel_ids.push(channel_id);
if let (Some(counterparty_node_id), Some(channel_id)) =

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Want to point out that this will result in an empty channels for already-tracked entries on upgrade. We'll need to see how to handle that case downstream I guess. Technically we'd need to make the tracking an Option<PublicKey> but that's just odd.

This adds an optional `counterparty_node_id` field to the
`SpendableOutputs` event, providing users with information about which
channel counterparty the spendable outputs belong to.
The field uses TLV type 3 (odd) for backwards compatibility, meaning
older versions will safely ignore it during deserialization. When
reading events serialized by older LDK versions, this field will be
`None`.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This adds an optional `counterparty_node_id` field to
`TrackedSpendableOutput` and updates the `track_spendable_outputs`
method signatures on both `OutputSweeper` and `OutputSweeperSync` to
accept this new parameter.
The field uses TLV type 3 (odd) for backwards compatibility. When
reading outputs tracked with LDK 0.2 and prior, this field will be
`None`.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This adds `counterparty_node_id` tracking to all `TransactionType`
variants, enabling downstream users to identify the channel counterparty
associated with each broadcast transaction.
For single-channel variants (`CooperativeClose`, `UnilateralClose`,
`AnchorBump`, `Claim`, `Splice`), the counterparty is stored directly.
For multi-channel variants (`Funding`, `Sweep`), the type now uses
`Vec<(PublicKey, ChannelId)>` to pair each channel with its counterparty.
The `OnchainTxHandler` now stores `counterparty_node_id` and provides a
`set_counterparty_node_id` method for initialization during
deserialization of older data.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
@tnull
tnullforce-pushed the 2026-02-include-counterparty-node-id branch from ad4cc6c to 56f12c8CompareFebruary 6, 2026 12:25
.list_channels()
.into_iter()
.any(|cd| cd.channel_id == ch_id && cd.is_channel_ready);
.find(|cd| cd.channel_id == ch_id && cd.is_channel_ready);

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.

might make sense to filter by UCID here as well. Technically channel id isn't unique for 0confs even if is_channel_ready.

@TheBlueMatt
TheBlueMatt merged commit 94d1e5e into lightningdevkit:mainFeb 6, 2026
17 of 19 checks passed
@codecov

codecovBot commented Feb 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.46602% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.02%. Comparing base (372ba65) to head (56f12c8).
⚠️ Report is 13 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channelmanager.rs60.00%8 Missing ⚠️
lightning/src/ln/channel.rs50.00%5 Missing ⚠️
lightning/src/util/sweep.rs82.35%1 Missing and 2 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4393 +/- ##
==========================================
- Coverage 86.04% 86.02% -0.02% 
==========================================
Files 156 156 Lines 103002 103046 +44 Branches 103002 103046 +44 ==========================================
+ Hits 88627 88646 +19 - Misses 11865 11888 +23 - Partials 2510 2512 +2 
FlagCoverage Δ
tests86.02% <84.46%> (-0.02%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for freeto 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.

Add counterparty node ids (+ user channel ids) to TransactionType

3 participants

@tnull@ldk-reviews-bot@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Include counterpart_node_id in TransactionType - #4393

Merged
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-02-include-counterparty-node-id
Feb 6, 2026
Merged

Include counterpart_node_id in TransactionType#4393
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-02-include-counterparty-node-id

Conversation

@tnull

@tnulltnull commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

Closes#4391

In #4353 we added a TransactionType that also indicated the ChannelIds associated with the broadcasted transaction. However, as pointed out there, ChannelIds might are always just guranteed to be unique on a per-counterparty basis.

Therefore, we here track the counterparty_node_id side-by-side with the ChannelId, which notably also requires to track it as part of Event::SpendableOutputs and in OutputSweeper.

@ldk-reviews-bot

ldk-reviews-bot commented Feb 6, 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.

if let Some(channel_id) = output_info.channel_id {
if !channel_ids.contains(&channel_id) {
channel_ids.push(channel_id);
if let (Some(counterparty_node_id), Some(channel_id)) =

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Want to point out that this will result in an empty channels for already-tracked entries on upgrade. We'll need to see how to handle that case downstream I guess. Technically we'd need to make the tracking an Option<PublicKey> but that's just odd.

This adds an optional `counterparty_node_id` field to the
`SpendableOutputs` event, providing users with information about which
channel counterparty the spendable outputs belong to.
The field uses TLV type 3 (odd) for backwards compatibility, meaning
older versions will safely ignore it during deserialization. When
reading events serialized by older LDK versions, this field will be
`None`.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This adds an optional `counterparty_node_id` field to
`TrackedSpendableOutput` and updates the `track_spendable_outputs`
method signatures on both `OutputSweeper` and `OutputSweeperSync` to
accept this new parameter.
The field uses TLV type 3 (odd) for backwards compatibility. When
reading outputs tracked with LDK 0.2 and prior, this field will be
`None`.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This adds `counterparty_node_id` tracking to all `TransactionType`
variants, enabling downstream users to identify the channel counterparty
associated with each broadcast transaction.
For single-channel variants (`CooperativeClose`, `UnilateralClose`,
`AnchorBump`, `Claim`, `Splice`), the counterparty is stored directly.
For multi-channel variants (`Funding`, `Sweep`), the type now uses
`Vec<(PublicKey, ChannelId)>` to pair each channel with its counterparty.
The `OnchainTxHandler` now stores `counterparty_node_id` and provides a
`set_counterparty_node_id` method for initialization during
deserialization of older data.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
@tnull
tnullforce-pushed the 2026-02-include-counterparty-node-id branch from ad4cc6c to 56f12c8CompareFebruary 6, 2026 12:25
.list_channels()
.into_iter()
.any(|cd| cd.channel_id == ch_id && cd.is_channel_ready);
.find(|cd| cd.channel_id == ch_id && cd.is_channel_ready);

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.

might make sense to filter by UCID here as well. Technically channel id isn't unique for 0confs even if is_channel_ready.

@TheBlueMatt
TheBlueMatt merged commit 94d1e5e into lightningdevkit:mainFeb 6, 2026
17 of 19 checks passed
@codecov

codecovBot commented Feb 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.46602% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.02%. Comparing base (372ba65) to head (56f12c8).
⚠️ Report is 13 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channelmanager.rs60.00%8 Missing ⚠️
lightning/src/ln/channel.rs50.00%5 Missing ⚠️
lightning/src/util/sweep.rs82.35%1 Missing and 2 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4393 +/- ##
==========================================
- Coverage 86.04% 86.02% -0.02% 
==========================================
Files 156 156 Lines 103002 103046 +44 Branches 103002 103046 +44 ==========================================
+ Hits 88627 88646 +19 - Misses 11865 11888 +23 - Partials 2510 2512 +2 
FlagCoverage Δ
tests86.02% <84.46%> (-0.02%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for freeto 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.

Add counterparty node ids (+ user channel ids) to TransactionType

3 participants

@tnull@ldk-reviews-bot@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', '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('^' + ".*" + '
Skip to content

Include counterpart_node_id in TransactionType - #4393

Merged
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-02-include-counterparty-node-id
Feb 6, 2026
Merged

Include counterpart_node_id in TransactionType#4393
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-02-include-counterparty-node-id

Conversation

@tnull

@tnulltnull commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

Closes#4391

In #4353 we added a TransactionType that also indicated the ChannelIds associated with the broadcasted transaction. However, as pointed out there, ChannelIds might are always just guranteed to be unique on a per-counterparty basis.

Therefore, we here track the counterparty_node_id side-by-side with the ChannelId, which notably also requires to track it as part of Event::SpendableOutputs and in OutputSweeper.

@ldk-reviews-bot

ldk-reviews-bot commented Feb 6, 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.

if let Some(channel_id) = output_info.channel_id {
if !channel_ids.contains(&channel_id) {
channel_ids.push(channel_id);
if let (Some(counterparty_node_id), Some(channel_id)) =

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Want to point out that this will result in an empty channels for already-tracked entries on upgrade. We'll need to see how to handle that case downstream I guess. Technically we'd need to make the tracking an Option<PublicKey> but that's just odd.

This adds an optional `counterparty_node_id` field to the
`SpendableOutputs` event, providing users with information about which
channel counterparty the spendable outputs belong to.
The field uses TLV type 3 (odd) for backwards compatibility, meaning
older versions will safely ignore it during deserialization. When
reading events serialized by older LDK versions, this field will be
`None`.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This adds an optional `counterparty_node_id` field to
`TrackedSpendableOutput` and updates the `track_spendable_outputs`
method signatures on both `OutputSweeper` and `OutputSweeperSync` to
accept this new parameter.
The field uses TLV type 3 (odd) for backwards compatibility. When
reading outputs tracked with LDK 0.2 and prior, this field will be
`None`.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This adds `counterparty_node_id` tracking to all `TransactionType`
variants, enabling downstream users to identify the channel counterparty
associated with each broadcast transaction.
For single-channel variants (`CooperativeClose`, `UnilateralClose`,
`AnchorBump`, `Claim`, `Splice`), the counterparty is stored directly.
For multi-channel variants (`Funding`, `Sweep`), the type now uses
`Vec<(PublicKey, ChannelId)>` to pair each channel with its counterparty.
The `OnchainTxHandler` now stores `counterparty_node_id` and provides a
`set_counterparty_node_id` method for initialization during
deserialization of older data.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
@tnull
tnullforce-pushed the 2026-02-include-counterparty-node-id branch from ad4cc6c to 56f12c8CompareFebruary 6, 2026 12:25
.list_channels()
.into_iter()
.any(|cd| cd.channel_id == ch_id && cd.is_channel_ready);
.find(|cd| cd.channel_id == ch_id && cd.is_channel_ready);

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.

might make sense to filter by UCID here as well. Technically channel id isn't unique for 0confs even if is_channel_ready.

@TheBlueMatt
TheBlueMatt merged commit 94d1e5e into lightningdevkit:mainFeb 6, 2026
17 of 19 checks passed
@codecov

codecovBot commented Feb 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.46602% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.02%. Comparing base (372ba65) to head (56f12c8).
⚠️ Report is 13 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channelmanager.rs60.00%8 Missing ⚠️
lightning/src/ln/channel.rs50.00%5 Missing ⚠️
lightning/src/util/sweep.rs82.35%1 Missing and 2 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4393 +/- ##
==========================================
- Coverage 86.04% 86.02% -0.02% 
==========================================
Files 156 156 Lines 103002 103046 +44 Branches 103002 103046 +44 ==========================================
+ Hits 88627 88646 +19 - Misses 11865 11888 +23 - Partials 2510 2512 +2 
FlagCoverage Δ
tests86.02% <84.46%> (-0.02%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for freeto 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.

Add counterparty node ids (+ user channel ids) to TransactionType

3 participants

@tnull@ldk-reviews-bot@TheBlueMatt
, '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" + '
Skip to content

Include counterpart_node_id in TransactionType - #4393

Merged
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-02-include-counterparty-node-id
Feb 6, 2026
Merged

Include counterpart_node_id in TransactionType#4393
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-02-include-counterparty-node-id

Conversation

@tnull

@tnulltnull commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

Closes#4391

In #4353 we added a TransactionType that also indicated the ChannelIds associated with the broadcasted transaction. However, as pointed out there, ChannelIds might are always just guranteed to be unique on a per-counterparty basis.

Therefore, we here track the counterparty_node_id side-by-side with the ChannelId, which notably also requires to track it as part of Event::SpendableOutputs and in OutputSweeper.

@ldk-reviews-bot

ldk-reviews-bot commented Feb 6, 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.

if let Some(channel_id) = output_info.channel_id {
if !channel_ids.contains(&channel_id) {
channel_ids.push(channel_id);
if let (Some(counterparty_node_id), Some(channel_id)) =

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Want to point out that this will result in an empty channels for already-tracked entries on upgrade. We'll need to see how to handle that case downstream I guess. Technically we'd need to make the tracking an Option<PublicKey> but that's just odd.

This adds an optional `counterparty_node_id` field to the
`SpendableOutputs` event, providing users with information about which
channel counterparty the spendable outputs belong to.
The field uses TLV type 3 (odd) for backwards compatibility, meaning
older versions will safely ignore it during deserialization. When
reading events serialized by older LDK versions, this field will be
`None`.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This adds an optional `counterparty_node_id` field to
`TrackedSpendableOutput` and updates the `track_spendable_outputs`
method signatures on both `OutputSweeper` and `OutputSweeperSync` to
accept this new parameter.
The field uses TLV type 3 (odd) for backwards compatibility. When
reading outputs tracked with LDK 0.2 and prior, this field will be
`None`.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This adds `counterparty_node_id` tracking to all `TransactionType`
variants, enabling downstream users to identify the channel counterparty
associated with each broadcast transaction.
For single-channel variants (`CooperativeClose`, `UnilateralClose`,
`AnchorBump`, `Claim`, `Splice`), the counterparty is stored directly.
For multi-channel variants (`Funding`, `Sweep`), the type now uses
`Vec<(PublicKey, ChannelId)>` to pair each channel with its counterparty.
The `OnchainTxHandler` now stores `counterparty_node_id` and provides a
`set_counterparty_node_id` method for initialization during
deserialization of older data.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
@tnull
tnullforce-pushed the 2026-02-include-counterparty-node-id branch from ad4cc6c to 56f12c8CompareFebruary 6, 2026 12:25
.list_channels()
.into_iter()
.any(|cd| cd.channel_id == ch_id && cd.is_channel_ready);
.find(|cd| cd.channel_id == ch_id && cd.is_channel_ready);

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.

might make sense to filter by UCID here as well. Technically channel id isn't unique for 0confs even if is_channel_ready.

@TheBlueMatt
TheBlueMatt merged commit 94d1e5e into lightningdevkit:mainFeb 6, 2026
17 of 19 checks passed
@codecov

codecovBot commented Feb 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.46602% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.02%. Comparing base (372ba65) to head (56f12c8).
⚠️ Report is 13 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channelmanager.rs60.00%8 Missing ⚠️
lightning/src/ln/channel.rs50.00%5 Missing ⚠️
lightning/src/util/sweep.rs82.35%1 Missing and 2 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4393 +/- ##
==========================================
- Coverage 86.04% 86.02% -0.02% 
==========================================
Files 156 156 Lines 103002 103046 +44 Branches 103002 103046 +44 ==========================================
+ Hits 88627 88646 +19 - Misses 11865 11888 +23 - Partials 2510 2512 +2 
FlagCoverage Δ
tests86.02% <84.46%> (-0.02%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for freeto 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.

Add counterparty node ids (+ user channel ids) to TransactionType

3 participants

@tnull@ldk-reviews-bot@TheBlueMatt
, '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('^' + ".*" + '
Skip to content

Include counterpart_node_id in TransactionType - #4393

Merged
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-02-include-counterparty-node-id
Feb 6, 2026
Merged

Include counterpart_node_id in TransactionType#4393
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-02-include-counterparty-node-id

Conversation

@tnull

@tnulltnull commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

Closes#4391

In #4353 we added a TransactionType that also indicated the ChannelIds associated with the broadcasted transaction. However, as pointed out there, ChannelIds might are always just guranteed to be unique on a per-counterparty basis.

Therefore, we here track the counterparty_node_id side-by-side with the ChannelId, which notably also requires to track it as part of Event::SpendableOutputs and in OutputSweeper.

@ldk-reviews-bot

ldk-reviews-bot commented Feb 6, 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.

if let Some(channel_id) = output_info.channel_id {
if !channel_ids.contains(&channel_id) {
channel_ids.push(channel_id);
if let (Some(counterparty_node_id), Some(channel_id)) =

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Want to point out that this will result in an empty channels for already-tracked entries on upgrade. We'll need to see how to handle that case downstream I guess. Technically we'd need to make the tracking an Option<PublicKey> but that's just odd.

This adds an optional `counterparty_node_id` field to the
`SpendableOutputs` event, providing users with information about which
channel counterparty the spendable outputs belong to.
The field uses TLV type 3 (odd) for backwards compatibility, meaning
older versions will safely ignore it during deserialization. When
reading events serialized by older LDK versions, this field will be
`None`.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This adds an optional `counterparty_node_id` field to
`TrackedSpendableOutput` and updates the `track_spendable_outputs`
method signatures on both `OutputSweeper` and `OutputSweeperSync` to
accept this new parameter.
The field uses TLV type 3 (odd) for backwards compatibility. When
reading outputs tracked with LDK 0.2 and prior, this field will be
`None`.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This adds `counterparty_node_id` tracking to all `TransactionType`
variants, enabling downstream users to identify the channel counterparty
associated with each broadcast transaction.
For single-channel variants (`CooperativeClose`, `UnilateralClose`,
`AnchorBump`, `Claim`, `Splice`), the counterparty is stored directly.
For multi-channel variants (`Funding`, `Sweep`), the type now uses
`Vec<(PublicKey, ChannelId)>` to pair each channel with its counterparty.
The `OnchainTxHandler` now stores `counterparty_node_id` and provides a
`set_counterparty_node_id` method for initialization during
deserialization of older data.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
@tnull
tnullforce-pushed the 2026-02-include-counterparty-node-id branch from ad4cc6c to 56f12c8CompareFebruary 6, 2026 12:25
.list_channels()
.into_iter()
.any(|cd| cd.channel_id == ch_id && cd.is_channel_ready);
.find(|cd| cd.channel_id == ch_id && cd.is_channel_ready);

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.

might make sense to filter by UCID here as well. Technically channel id isn't unique for 0confs even if is_channel_ready.

@TheBlueMatt
TheBlueMatt merged commit 94d1e5e into lightningdevkit:mainFeb 6, 2026
17 of 19 checks passed
@codecov

codecovBot commented Feb 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.46602% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.02%. Comparing base (372ba65) to head (56f12c8).
⚠️ Report is 13 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channelmanager.rs60.00%8 Missing ⚠️
lightning/src/ln/channel.rs50.00%5 Missing ⚠️
lightning/src/util/sweep.rs82.35%1 Missing and 2 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4393 +/- ##
==========================================
- Coverage 86.04% 86.02% -0.02% 
==========================================
Files 156 156 Lines 103002 103046 +44 Branches 103002 103046 +44 ==========================================
+ Hits 88627 88646 +19 - Misses 11865 11888 +23 - Partials 2510 2512 +2 
FlagCoverage Δ
tests86.02% <84.46%> (-0.02%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for freeto 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.

Add counterparty node ids (+ user channel ids) to TransactionType

3 participants

@tnull@ldk-reviews-bot@TheBlueMatt
, '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); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Include counterpart_node_id in TransactionType - #4393

Merged
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-02-include-counterparty-node-id
Feb 6, 2026
Merged

Include counterpart_node_id in TransactionType#4393
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-02-include-counterparty-node-id

Conversation

@tnull

@tnulltnull commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

Closes#4391

In #4353 we added a TransactionType that also indicated the ChannelIds associated with the broadcasted transaction. However, as pointed out there, ChannelIds might are always just guranteed to be unique on a per-counterparty basis.

Therefore, we here track the counterparty_node_id side-by-side with the ChannelId, which notably also requires to track it as part of Event::SpendableOutputs and in OutputSweeper.

@ldk-reviews-bot

ldk-reviews-bot commented Feb 6, 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.

if let Some(channel_id) = output_info.channel_id {
if !channel_ids.contains(&channel_id) {
channel_ids.push(channel_id);
if let (Some(counterparty_node_id), Some(channel_id)) =

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Want to point out that this will result in an empty channels for already-tracked entries on upgrade. We'll need to see how to handle that case downstream I guess. Technically we'd need to make the tracking an Option<PublicKey> but that's just odd.

This adds an optional `counterparty_node_id` field to the
`SpendableOutputs` event, providing users with information about which
channel counterparty the spendable outputs belong to.
The field uses TLV type 3 (odd) for backwards compatibility, meaning
older versions will safely ignore it during deserialization. When
reading events serialized by older LDK versions, this field will be
`None`.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This adds an optional `counterparty_node_id` field to
`TrackedSpendableOutput` and updates the `track_spendable_outputs`
method signatures on both `OutputSweeper` and `OutputSweeperSync` to
accept this new parameter.
The field uses TLV type 3 (odd) for backwards compatibility. When
reading outputs tracked with LDK 0.2 and prior, this field will be
`None`.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This adds `counterparty_node_id` tracking to all `TransactionType`
variants, enabling downstream users to identify the channel counterparty
associated with each broadcast transaction.
For single-channel variants (`CooperativeClose`, `UnilateralClose`,
`AnchorBump`, `Claim`, `Splice`), the counterparty is stored directly.
For multi-channel variants (`Funding`, `Sweep`), the type now uses
`Vec<(PublicKey, ChannelId)>` to pair each channel with its counterparty.
The `OnchainTxHandler` now stores `counterparty_node_id` and provides a
`set_counterparty_node_id` method for initialization during
deserialization of older data.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
@tnull
tnullforce-pushed the 2026-02-include-counterparty-node-id branch from ad4cc6c to 56f12c8CompareFebruary 6, 2026 12:25
.list_channels()
.into_iter()
.any(|cd| cd.channel_id == ch_id && cd.is_channel_ready);
.find(|cd| cd.channel_id == ch_id && cd.is_channel_ready);

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.

might make sense to filter by UCID here as well. Technically channel id isn't unique for 0confs even if is_channel_ready.

@TheBlueMatt
TheBlueMatt merged commit 94d1e5e into lightningdevkit:mainFeb 6, 2026
17 of 19 checks passed
@codecov

codecovBot commented Feb 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.46602% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.02%. Comparing base (372ba65) to head (56f12c8).
⚠️ Report is 13 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channelmanager.rs60.00%8 Missing ⚠️
lightning/src/ln/channel.rs50.00%5 Missing ⚠️
lightning/src/util/sweep.rs82.35%1 Missing and 2 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4393 +/- ##
==========================================
- Coverage 86.04% 86.02% -0.02% 
==========================================
Files 156 156 Lines 103002 103046 +44 Branches 103002 103046 +44 ==========================================
+ Hits 88627 88646 +19 - Misses 11865 11888 +23 - Partials 2510 2512 +2 
FlagCoverage Δ
tests86.02% <84.46%> (-0.02%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for freeto 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.

Add counterparty node ids (+ user channel ids) to TransactionType

3 participants

@tnull@ldk-reviews-bot@TheBlueMatt
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Include counterpart_node_id in TransactionType - #4393

Merged
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-02-include-counterparty-node-id
Feb 6, 2026
Merged

Include counterpart_node_id in TransactionType#4393
TheBlueMatt merged 3 commits into
lightningdevkit:mainfrom
tnull:2026-02-include-counterparty-node-id

Conversation

@tnull

@tnulltnull commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

Closes#4391

In #4353 we added a TransactionType that also indicated the ChannelIds associated with the broadcasted transaction. However, as pointed out there, ChannelIds might are always just guranteed to be unique on a per-counterparty basis.

Therefore, we here track the counterparty_node_id side-by-side with the ChannelId, which notably also requires to track it as part of Event::SpendableOutputs and in OutputSweeper.

@ldk-reviews-bot

ldk-reviews-bot commented Feb 6, 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.

if let Some(channel_id) = output_info.channel_id {
if !channel_ids.contains(&channel_id) {
channel_ids.push(channel_id);
if let (Some(counterparty_node_id), Some(channel_id)) =

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Want to point out that this will result in an empty channels for already-tracked entries on upgrade. We'll need to see how to handle that case downstream I guess. Technically we'd need to make the tracking an Option<PublicKey> but that's just odd.

This adds an optional `counterparty_node_id` field to the
`SpendableOutputs` event, providing users with information about which
channel counterparty the spendable outputs belong to.
The field uses TLV type 3 (odd) for backwards compatibility, meaning
older versions will safely ignore it during deserialization. When
reading events serialized by older LDK versions, this field will be
`None`.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This adds an optional `counterparty_node_id` field to
`TrackedSpendableOutput` and updates the `track_spendable_outputs`
method signatures on both `OutputSweeper` and `OutputSweeperSync` to
accept this new parameter.
The field uses TLV type 3 (odd) for backwards compatibility. When
reading outputs tracked with LDK 0.2 and prior, this field will be
`None`.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This adds `counterparty_node_id` tracking to all `TransactionType`
variants, enabling downstream users to identify the channel counterparty
associated with each broadcast transaction.
For single-channel variants (`CooperativeClose`, `UnilateralClose`,
`AnchorBump`, `Claim`, `Splice`), the counterparty is stored directly.
For multi-channel variants (`Funding`, `Sweep`), the type now uses
`Vec<(PublicKey, ChannelId)>` to pair each channel with its counterparty.
The `OnchainTxHandler` now stores `counterparty_node_id` and provides a
`set_counterparty_node_id` method for initialization during
deserialization of older data.
Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
@tnull
tnullforce-pushed the 2026-02-include-counterparty-node-id branch from ad4cc6c to 56f12c8CompareFebruary 6, 2026 12:25
.list_channels()
.into_iter()
.any(|cd| cd.channel_id == ch_id && cd.is_channel_ready);
.find(|cd| cd.channel_id == ch_id && cd.is_channel_ready);

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.

might make sense to filter by UCID here as well. Technically channel id isn't unique for 0confs even if is_channel_ready.

@TheBlueMatt
TheBlueMatt merged commit 94d1e5e into lightningdevkit:mainFeb 6, 2026
17 of 19 checks passed
@codecov

codecovBot commented Feb 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.46602% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.02%. Comparing base (372ba65) to head (56f12c8).
⚠️ Report is 13 commits behind head on main.

Files with missing linesPatch %Lines
lightning/src/ln/channelmanager.rs60.00%8 Missing ⚠️
lightning/src/ln/channel.rs50.00%5 Missing ⚠️
lightning/src/util/sweep.rs82.35%1 Missing and 2 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #4393 +/- ##
==========================================
- Coverage 86.04% 86.02% -0.02% 
==========================================
Files 156 156 Lines 103002 103046 +44 Branches 103002 103046 +44 ==========================================
+ Hits 88627 88646 +19 - Misses 11865 11888 +23 - Partials 2510 2512 +2 
FlagCoverage Δ
tests86.02% <84.46%> (-0.02%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for freeto 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.

Add counterparty node ids (+ user channel ids) to TransactionType

3 participants

@tnull@ldk-reviews-bot@TheBlueMatt