-
Notifications
You must be signed in to change notification settings - Fork 113
Insert channel funding outputs into Wallet #726
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
base: main
Are you sure you want to change the base?
Insert channel funding outputs into Wallet #726
Conversation
|
👋 Thanks for assigning @jkczyz as a reviewer! |
091e391 to
d7f8bc9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense to me. Do we think this is worth a backport for 0.7 or are we fine waiting for 0.8 with shipping this?
The different cases in the event handler could use a comment or two to explain when we'd land on which side of the if/else clauses there. Also, we really need to be careful with just replaying events in cases where we don't expect immediate resolution of the error on retry, as we'd otherwise just spin and block any other event processing. This could also use better test coverage to show why we need this change in the first place.
Besides that, also pinging @jkczyz as a second reviewer on this.
src/event.rs
Outdated
| self.logger, | ||
| "Failed to find channel info for pending channel {channel_id} with counterparty {counterparty_node_id}" | ||
| ); | ||
| return Err(ReplayEvent()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would induce an infinite loop in event handling, no? Rather than doing this, we probably need to just log the error for now, and abort the flow when we can with 0.3? Also, would it make sense to add a debug_assert here, given that we expect this always to be avaialble? (same below)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error below can only happen on a persistence failure, elsewhere in the event handling we replay on those errors so I think it makes sense to keep as is.
For this one, it should always be available so I will just change to a debug_assert
| }, | ||
| } | ||
| } else { | ||
| log_info!( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In what case would we end up in this else branch, and would we need to do something related to the redeemscript, too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the docs, the funding_txo "Will be None if the channel's funding transaction reached an acceptable depth prior to version 0.2". Since this was also added in 0.2, the redeem script would also be None so there shouldn't be anything to add. Either way, we need the funding txo to be able to insert so we can't add it.
| node_b.splice_in(&user_channel_id_b, node_a.node_id(), 4_000_000).unwrap(); | ||
|
|
||
| expect_splice_pending_event!(node_a, node_b.node_id()); | ||
| let txo = expect_splice_pending_event!(node_a, node_b.node_id()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These test changes pass on main. Can you add coverage for the cases where the previous approach would lead to inaccurate fee estimations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bug/issue only exists with bitcoind syncing so to do so, we'd have to change the test to sync with bitcoind rpc. Is that wanted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bug/issue only exists with bitcoind syncing so to do so, we'd have to change the test to sync with bitcoind rpc. Is that wanted?
Sure, feel free to do so. Alternatively, you could also add a _bitcoind variant test case (ofc reusing the logic) so we have two test cases for bitcoind and esplora - that's if we think there would be more chain source specific edge cases.
| } | ||
| } | ||
|
|
||
| impl UniffiCustomTypeConverter for ScriptBuf { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: While this should be fine for now, we generally try to get away from the UniffiCustomTypeConverter approach, and instead convert more and more objects to proper interfaces.
d7f8bc9 to
b2c3793
Compare
|
🔔 1st Reminder Hey @jkczyz! This PR has been waiting for your review. |
|
🔔 2nd Reminder Hey @jkczyz! This PR has been waiting for your review. |
| ); | ||
| }, | ||
| Some(output) => { | ||
| if let Err(e) = self.wallet.insert_txo(funding_txo, output) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm... I guess we didn't really need the redeem script in ChannelPending and SplicePending since we only need the previous funding output in the wallet for the next splice. Might have been better in ChannelReady. We'd be able to avoid the look-up, although it wouldn't remove the Option check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah sadly I messed up here, i think we needed to add the redeem script along with the new channel size so we had the full utxo information
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, though if we insert the previous funding txo when initiating the splice as mentioned in the other comment, then I think we'll have all the necessary information in ChannelDetails? Essentially, we'd be lazily adding the previous funding output to the wallet when initiating the splice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made so we add it before a splice-in. I still think this one is good to keep so if you're doing any other wallet related action, it will have a more complete set of information and you don't need to initiate a splice for it to have the channel information
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think this one is good to keep so if you're doing any other wallet related action, it will have a more complete set of information and you don't need to initiate a splice for it to have the channel information
Could you provide an example for what else we would use this information? If we don't need it I'd prefer to drop this change to declutter the logic here and avoid the extra persistence roundtrip.
| let chans = | ||
| self.channel_manager.list_channels_with_counterparty(&counterparty_node_id); | ||
| let chan_output = chans | ||
| .iter() | ||
| .find(|c| c.user_channel_id == user_channel_id) | ||
| .and_then(|c| c.get_funding_output()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing this in ChannelReady wouldn't work for splicing preexisting channels. Wonder if we should instead do this when initiating a splice? There we already look up the channel. It would also let us use the real shared_input when selecting UTXOs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing this in ChannelReady wouldn't work for splicing preexisting channels.
I dont think this is right, in the docs it says we get a ChannelReady for splices, also my test seems to confirm
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, we do get it for spliced channels, but we need the initial funding output because that is the one being spent. And for channels existing before this change, we would have already processed the ChannelReady event for the initial funding.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah i see for backward compat sake, added!
b2c3793 to
8518f3d
Compare
src/lib.rs
Outdated
| let shared_output = bitcoin::TxOut { | ||
| value: shared_input.previous_utxo.value + Amount::from_sat(splice_amount_sats), | ||
| script_pubkey: make_funding_redeemscript(&dummy_pubkey, &dummy_pubkey).to_p2wsh(), | ||
| script_pubkey: funding_output.script_pubkey, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should still be the dummy one or note that it is not really the shared output's script_pubkey. I guess the amount is already fake since we don't know what the counterparty will contribute.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added a comment
| self.wallet.insert_txo(funding_txo.into_bitcoin_outpoint(), funding_output).map_err( | ||
| |e| { | ||
| log_error!(self.logger, "Failed to splice channel: {:?}", e); | ||
| Error::ChannelSplicingFailed | ||
| }, | ||
| )?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tnull Don't know what the convention is here. Should we replace the Error::PersistenceFailed here with Error::ChannelSplicingFailed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think it's preferable to bubble up the PersistenceFailed error.
…lices LDK gives us the actual funding output so we no longer need to create a dummy one with fake pubkeys
We insert a channel's funding utxo into our wallet so we can later calculate the fees for the transaction, otherwise our wallet would have incomplete information. We do it before the splice-in and not just on the ChannelReady event to ensure better backwards compatibility.
When doing a splice, to properly calculate fees we need the channel's funding utxo in our wallet, otherwise our wallet won't know the channel's original size. This adds the channel funding txo on ChannelReady events and modifies the splicing test to make sure we can calculate fees on splice-ins.
Exposes the funding_redeem_script that LDK already exposes
8518f3d to
4c3450e
Compare
tnull
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excuse the delay here
| self.wallet.insert_txo(funding_txo.into_bitcoin_outpoint(), funding_output).map_err( | ||
| |e| { | ||
| log_error!(self.logger, "Failed to splice channel: {:?}", e); | ||
| Error::ChannelSplicingFailed | ||
| }, | ||
| )?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think it's preferable to bubble up the PersistenceFailed error.
| ); | ||
| }, | ||
| Some(output) => { | ||
| if let Err(e) = self.wallet.insert_txo(funding_txo, output) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think this one is good to keep so if you're doing any other wallet related action, it will have a more complete set of information and you don't need to initiate a splice for it to have the channel information
Could you provide an example for what else we would use this information? If we don't need it I'd prefer to drop this change to declutter the logic here and avoid the extra persistence roundtrip.
| node_b.splice_in(&user_channel_id_b, node_a.node_id(), 4_000_000).unwrap(); | ||
|
|
||
| expect_splice_pending_event!(node_a, node_b.node_id()); | ||
| let txo = expect_splice_pending_event!(node_a, node_b.node_id()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bug/issue only exists with bitcoind syncing so to do so, we'd have to change the test to sync with bitcoind rpc. Is that wanted?
Sure, feel free to do so. Alternatively, you could also add a _bitcoind variant test case (ofc reusing the logic) so we have two test cases for bitcoind and esplora - that's if we think there would be more chain source specific edge cases.
| /// When a channel is spliced, this continues to refer to the original pre-splice channel | ||
| /// state until the splice transaction reaches sufficient confirmations to be locked (and we | ||
| /// exchange `splice_locked` messages with our peer). | ||
| pub funding_redeem_script: Option<bitcoin::ScriptBuf>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Please import ScriptBuf instead of using the bitcoin:: prefix.
When doing a splice, to properly calculate fees we need the channel's funding utxo in our wallet, otherwise our wallet won't know the channel's original size. This adds the channel funding txo on ChannelReady events and modifies the splicing test to make sure we can calculate fees on splice-ins.