Introduce FundingContributionBuilder API#4516
Introduce FundingContributionBuilder API#4516wpaulino wants to merge 2 commits intolightningdevkit:mainfrom
Conversation
|
👋 Thanks for assigning @jkczyz as a reviewer! |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4516 +/- ##
==========================================
+ Coverage 86.14% 86.26% +0.11%
==========================================
Files 160 160
Lines 108046 109045 +999
Branches 108046 109045 +999
==========================================
+ Hits 93080 94071 +991
+ Misses 12346 12332 -14
- Partials 2620 2642 +22
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
0968836 to
2da45ef
Compare
|
Leaving the explicit input support for a follow-up as this PR is large enough already. |
| .await | ||
| .map_err(|_| FundingContributionError::CoinSelectionFailed)?; | ||
|
|
||
| return Ok(FundingContribution::new( |
There was a problem hiding this comment.
Nit: unnecessary return in final expression position. Same on line 740 for the sync variant.
| return Ok(FundingContribution::new( | |
| Ok(FundingContribution::new( |
Review SummaryNew Issues Found (this pass)
Previously Flagged Issues (still present)
Inline Comments Posted
|
| for output in outputs { | ||
| builder = builder.add_output(output); | ||
| } |
There was a problem hiding this comment.
Could we make a private add_outputs that simply moves the input Vec?
|
|
||
| /// Creates a [`FundingContribution`] for both adding and removing funds from a channel using | ||
| /// `wallet` to perform coin selection. | ||
| impl FundingTemplate { |
There was a problem hiding this comment.
Hmm... I think the diff may be saner if these methods were kept in the original impl block.
There was a problem hiding this comment.
The methods haven't moved, rather the diffing logic isn't happy with FundingBuilder being added above FundingTemplate.
There was a problem hiding this comment.
Yeah, so can't we leave these in the other impl block (i.e., below without_prior_contribution)?
Currently, we have build_funding_contribution and the FundingTemplate impl block removals split across two FundingBuilderInner impl blocks, a FundingBuilder impl block, an AsyncFundingBuilder impl block, and a SyncFundingBuilder impl block.
TheBlueMatt
left a comment
There was a problem hiding this comment.
I didn't look too deeply at the tests but basically LGTM.
It does not require coin selection, so the wallet argument is not necessary.
This commit introduces a `FundingBuilder`, following the builder pattern, to iteratively construct a `FundingContribution`. It supports adding/removing value (which may trigger a coin selection attempt), adding/remove outputs, and amending prior contributions (which was previously not possible). A `FundingBuilder` may be obtained in two ways: via `FundingTemplate::contribution_builder` (which resumes from the prior contribution to amend if available) or `FundingTemplate::without_prior_contribution_builder` to start from scratch and fully replace the prior contribution. When `FundingBuilder::build` is called, we attempt to build the contribution iteratively such that coin selection is our last resort. The splice-related convenience methods on `FundingTemplate` now map to the `FundingBuilder` under the hood.
2da45ef to
19b230b
Compare
|
Had to rebase due to a small import conflict. |
| return Some(adjusted); | ||
| } | ||
| } | ||
| return None; |
There was a problem hiding this comment.
Bug: When the request matches the prior exactly but holder_balance is None, this early return at line 418 skips amend_without_coin_selection entirely. For input-backed contributions, amend_without_coin_selection does not need holder_balance (lines 1157-1211 don't use it), so it could succeed. This means rbf_prior_contribution_sync(None, max_feerate, wallet) unnecessarily re-runs coin selection for input-backed prior contributions when holder_balance is None — potentially yielding a different input set than the prior had.
This is covered by the test at line 2890 (test_rbf_sync_holder_balance_none_falls_through_to_coin_selection), which expects coin selection, so this appears intentional. But worth noting that the amend_without_coin_selection path could handle this case without requiring a wallet.
| } | ||
|
|
||
| if self.value_added == Amount::ZERO && self.outputs.is_empty() { | ||
| return Err(FundingContributionError::InvalidSpliceValue); |
There was a problem hiding this comment.
The validation here catches value_added == 0 && outputs.is_empty(), which blocks the RBF "same request" path for splice-out prior contributions that had value_added == 0 and outputs == []. While this shouldn't arise in normal use (a prior contribution with both zero is meaningless), there's a subtle interaction: if someone calls with_prior_contribution(...) on a fresh template (no prior) without calling any mutation methods, they'd hit this error. The error message "Invalid splice value" doesn't hint that they need to call add_value or add_output first. Consider a more descriptive variant like EmptyContribution or adding a hint to the InvalidSpliceValue display message.
TheBlueMatt
left a comment
There was a problem hiding this comment.
needs rebase again tho
jkczyz
left a comment
There was a problem hiding this comment.
Code looks good, but I think merging some impl blocks will help the diff.
|
|
||
| /// Creates a [`FundingContribution`] for both adding and removing funds from a channel using | ||
| /// `wallet` to perform coin selection. | ||
| impl FundingTemplate { |
There was a problem hiding this comment.
Yeah, so can't we leave these in the other impl block (i.e., below without_prior_contribution)?
Currently, we have build_funding_contribution and the FundingTemplate impl block removals split across two FundingBuilderInner impl blocks, a FundingBuilder impl block, an AsyncFundingBuilder impl block, and a SyncFundingBuilder impl block.
| impl FundingTemplate { | ||
| /// Creates a [`FundingContribution`] for adding funds to a channel using `wallet` to perform | ||
| /// coin selection. | ||
| impl<State> FundingBuilderInner<State> { |
There was a problem hiding this comment.
Can this be combined with the other impl block for FundingBuilderInner?
| for output in outputs { | ||
| builder = builder.add_output(output); | ||
| } |
Looking for initial feedback on the design, still needs to be cleaned up a good bit.