Skip to content

Add Shared Input support in interactive TX construction #3842

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

optout21
Copy link
Contributor

@optout21 optout21 commented Jun 10, 2025

In interactive TX construction, add support for shared input:

  • if we expect a shared input, make sure that the remote node provides it
  • if we provide a shared input, make sure that it's accounted appropriately

Additionally, the prevtx field of the TxAddInput message is changed to Optional, as it should not be set for the shared input (it cannot, as the full funding transaction is not stored on the acceptor side) (spec discussion: lightning/bolts#1160 (comment))

To be used by splicing, see #3736 .

Note: this PR does not include splicing negotiation.

@ldk-reviews-bot
Copy link

ldk-reviews-bot commented Jun 10, 2025

👋 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.

@optout21 optout21 marked this pull request as ready for review June 11, 2025 19:03
@optout21 optout21 requested review from jkczyz, wpaulino and dunxen June 11, 2025 19:03
@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @dunxen @jkczyz! 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.

1 similar comment
@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @dunxen @jkczyz! 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

🔔 2nd Reminder

Hey @dunxen @jkczyz! 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.

1 similar comment
@ldk-reviews-bot
Copy link

🔔 2nd Reminder

Hey @dunxen @jkczyz! 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.

@optout21
Copy link
Contributor Author

Great, can you push those changes here then and rework the shared funding input work to follow a similar approach?

I managed to do it: first I refactored the shared output support as discussed, then added shared input support in a similar style. Although this PR does not include spicing, I also checked the changes with splicing (shared input is used there).

@optout21 optout21 force-pushed the shared-input branch 5 times, most recently from 166e364 to b2e0da8 Compare June 16, 2025 13:47
@optout21 optout21 requested a review from wpaulino June 17, 2025 03:10
@optout21
Copy link
Contributor Author

@wpaulino thanks for the comments. I will process them (I've re-requested review accidentally, please ignore that).

@ldk-reviews-bot
Copy link

🔔 3rd Reminder

Hey @dunxen @jkczyz @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.

1 similar comment
@ldk-reviews-bot
Copy link

🔔 3rd Reminder

Hey @dunxen @jkczyz @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

🔔 1st Reminder

Hey @dunxen @jkczyz @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.

Copy link

codecov bot commented Jun 19, 2025

Codecov Report

Attention: Patch coverage is 89.61240% with 67 lines in your changes missing coverage. Please review.

Project coverage is 90.10%. Comparing base (bed20cf) to head (e4dd8be).
Report is 34 commits behind head on main.

Files with missing lines Patch % Lines
lightning/src/ln/interactivetxs.rs 90.30% 51 Missing and 7 partials ⚠️
lightning/src/ln/channel.rs 54.54% 5 Missing ⚠️
lightning/src/util/ser.rs 63.63% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3842      +/-   ##
==========================================
+ Coverage   89.72%   90.10%   +0.38%     
==========================================
  Files         164      165       +1     
  Lines      133359   132400     -959     
  Branches   133359   132400     -959     
==========================================
- Hits       119651   119296     -355     
+ Misses      11037    10728     -309     
+ Partials     2671     2376     -295     

☔ 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.

@optout21 optout21 requested a review from wpaulino June 28, 2025 20:29
@ldk-reviews-bot
Copy link

🔔 8th Reminder

Hey @dunxen @jkczyz @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.

1 similar comment
@ldk-reviews-bot
Copy link

🔔 8th Reminder

Hey @dunxen @jkczyz @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

🔔 1st Reminder

Hey @dunxen @jkczyz @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.

Copy link
Contributor

@jkczyz jkczyz left a comment

Choose a reason for hiding this comment

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

Refactor commit looks great!

@ldk-reviews-bot
Copy link

🔔 9th Reminder

Hey @dunxen @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

🔔 2nd Reminder

Hey @dunxen @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.

@optout21
Copy link
Contributor Author

optout21 commented Jul 2, 2025

Review comments addressed, some minor (doc) changes applied.
I've squashed the fixups into the 2 main commits.
Ready for review from my part.

@ldk-reviews-bot
Copy link

🔔 10th Reminder

Hey @dunxen @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

🔔 3rd Reminder

Hey @dunxen @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

🔔 11th Reminder

Hey @dunxen @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

🔔 4th Reminder

Hey @dunxen @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.

Comment on lines 1926 to 1928
if is_initiator {
our_funding_inputs_weight =
our_funding_inputs_weight.saturating_add(estimate_input_weight(output).to_wu());
} else {
return Err(AbortReason::PrevTxOutInvalid);
our_funding_inputs_weight.saturating_add(P2WSH_INPUT_WEIGHT_LOWER_BOUND);
Copy link
Contributor

Choose a reason for hiding this comment

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

As a reader of the method though, it seems clearer to keep all the additional weight tracking when we're the initiator in one place.

@ldk-reviews-bot
Copy link

🔔 12th Reminder

Hey @dunxen! 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.

@jkczyz jkczyz self-assigned this Jul 10, 2025
Copy link
Contributor

@jkczyz jkczyz left a comment

Choose a reason for hiding this comment

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

Taking this PR on since @optout21 is unavailable for a week.

Comment on lines 1926 to 1928
if is_initiator {
our_funding_inputs_weight =
our_funding_inputs_weight.saturating_add(estimate_input_weight(output).to_wu());
} else {
return Err(AbortReason::PrevTxOutInvalid);
our_funding_inputs_weight.saturating_add(P2WSH_INPUT_WEIGHT_LOWER_BOUND);
Copy link
Contributor

Choose a reason for hiding this comment

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

I ended up moving this since doing so is more consistent with how the shared output is included in the weight. That is, shared output weight is not included in our_funding_outputs_weight, so including the shared input in our_funding_inputs_weight is not consistent.

@jkczyz jkczyz requested a review from wpaulino July 10, 2025 16:21
}

let our_funding_outputs_weight = funding_outputs.iter().fold(0u64, |weight, out| {
weight.saturating_add(get_output_weight(&out.tx_out().script_pubkey).to_wu())
weight.saturating_add(get_output_weight(&out.script_pubkey).to_wu())
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like we're not considering the total output amount to see if we can afford the fee. We need to subtract it from total_input_satoshis and that amount must be enough to cover our contribution and fees.

Copy link
Contributor

Choose a reason for hiding this comment

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

Updated along with the test.

Copy link
Contributor

@wpaulino wpaulino left a comment

Choose a reason for hiding this comment

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

LGTM after squash

let shared_funding_output = TxOut {
value: Amount::from_sat(funding.get_value_satoshis()),
script_pubkey: funding.get_funding_redeemscript().to_p2wsh(),
};

let interactive_tx_constructor = Some(InteractiveTxConstructor::new(
Copy link
Contributor

Choose a reason for hiding this comment

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

Pre-existing, but it looks like we shouldn't be initializing a constructor now, and should be relying on begin_interactive_funding_tx_construction to do it instead. Let's leave it for a follow-up.

@jkczyz jkczyz requested a review from wpaulino July 11, 2025 02:47
);
(OutPoint { txid, vout }, prev_output.clone(), local_owned)
}

Copy link

Choose a reason for hiding this comment

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

The test case description says "makes fees insufficient for initiator" but the implementation adds 1 to the adjusted amount rather than subtracting 1. To properly make the fees insufficient, consider subtracting 1 instead:

// makes fees insufficient for initiator
shared_output_a: generate_funding_txout(
    amount_adjusted_with_p2wpkh_fee - 1,
    amount_adjusted_with_p2wpkh_fee - 1,
),

This would ensure the test correctly verifies the behavior when fees are insufficient.

Suggested change
// makes fees insufficient for initiator
shared_output_a: generate_funding_txout(
amount_adjusted_with_p2wpkh_fee - 1,
amount_adjusted_with_p2wpkh_fee - 1,
),

Spotted by Diamond

Is this helpful? React 👍 or 👎 to let us know.

Copy link
Contributor

Choose a reason for hiding this comment

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

The code is correct, but the comment in the test is misleading. Will make a fix shortly.

optout21 added 2 commits July 11, 2025 09:45
This simplifies tracking separately the expected and actual shared output.
In the initiator case, we can just provide the shared output separately,
instead of including it within other outputs, and marking which one is the output.
We can use the same field for the intended shared output in the initiator
case, and the expected one in the acceptor case.
In interactivetxs, add support for shared inputs, similar to shared outputs.
A shared input is optional, and is used in case of splicing to add
the current funding as an input.
);
let tx_common_fields_fee =
fee_for_weight(TEST_FEERATE_SATS_PER_KW, TX_COMMON_FIELDS_WEIGHT);

let amount_adjusted_with_p2wpkh_fee =
1_000_000 - p2wpkh_fee - outputs_fee - tx_common_fields_fee;
1_000_000 - p2wpkh_fee - outputs_fee - tx_common_fields_fee + 1;
Copy link
Contributor

Choose a reason for hiding this comment

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

It isn't clear to me why we add one here and also whenever we use this variable below.

@ldk-reviews-bot
Copy link

🔔 13th Reminder

Hey @dunxen @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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

5 participants