') + ')', '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); } })(); })(); [Draft] RefundingChannel: combine FundedChannel and PendingV2Channel using a trait for Pending by optout21 · Pull Request #3720 · lightningdevkit/rust-lightning · GitHub
Skip to content

[Draft] RefundingChannel: combine FundedChannel and PendingV2Channel using a trait for Pending - #3720

Closed
optout21 wants to merge 2 commits into
lightningdevkit:mainfrom
optout21:splicing-state2
Closed

[Draft] RefundingChannel: combine FundedChannel and PendingV2Channel using a trait for Pending#3720
optout21 wants to merge 2 commits into
lightningdevkit:mainfrom
optout21:splicing-state2

Conversation

@optout21

Copy link
Copy Markdown
Contributor

This is a simpler version of #3702.

The goal: create a RefundingChannel phase, for splice negotiation, that can act both as a funded channel (pre-splice) and pending channel (transaction negotiation).

How?

  • a new trait PendingV2ChannelTrait (name TBD) created, and PendingV2Channel implements it. Most implememtations are moved from the struct to the trait
  • new RefundingChannel that has a FundedChannel for the funded, and several fields from pending for the pending.
  • The funded channel can be accessed through as_funded() or directly
  • The pending channel can be accessed through the pending trait

@ldk-reviews-bot

ldk-reviews-bot commented Apr 8, 2025

Copy link
Copy Markdown

👋 I see @wpaulino was un-assigned.
If you'd like another reviewer assignemnt, please click here.

fn funding(&self) -> &FundingScope;
fn funding_mut(&mut self) -> &mut FundingScope;
fn funding_and_context_mut(&mut self) -> (&mut FundingScope, &mut ChannelContext<SP>);
fn dual_funding_context(&self) -> &DualFundingChannelContext;

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.

Do we only need to use dual_funding_context in begin_interactive_funding_tx_construction? If so, seems like it should be passed into that and consumed rather than needing a method. Then you wouldn't need swap_out_dual_funding_context_inputs either.

In other words, can DualFundingChannelContext be constructed immediately before calling begin_interactive_funding_tx_construction rather than being a field on each channel type?

Comment threadlightning/src/ln/channel.rs Outdated
Comment on lines +2295 to +2296
// TODO Naming
pub(super) trait PendingV2ChannelTrait<SP: Deref> where SP::Target: SignerProvider {

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.

How about FundingTxConstruction?

@ldk-reviews-bot

Copy link
Copy Markdown

👋 The first review has been submitted!

Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer.

@jkczyz
jkczyz requested a review from wpaulinoApril 8, 2025 22:33
@optout21

Copy link
Copy Markdown
ContributorAuthor

One additional idea to consider, as discussed today: don't introduce new phase/channelstruct, but keep using FundedChannel throughout spicing, with additional fields needed placed in an optional Splicing struct.

@wpaulino
wpaulino removed their request for review April 10, 2025 00:42
@optout21

Copy link
Copy Markdown
ContributorAuthor

Continued in #3736, closing this one

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.

3 participants

@optout21@ldk-reviews-bot@jkczyz