bolts icon indicating copy to clipboard operation
bolts copied to clipboard

Extension/dynamic commitments

Open ProofOfKeags opened this issue 2 years ago • 7 comments

This PR specifies an extension-bolt to allow channel parameters to be renegotiated after channel open without requiring channel closure.

ProofOfKeags avatar Nov 06 '23 19:11 ProofOfKeags

If it's closing_tx_1, we need to broadcast kickoff_tx first. If it's closing_tx_2, we can save one tx.

Paging @Roasbeef and @jharveyb for confirmation, but I believe if we do closing_tx_2 then that cut-through will prevent it from being nicely compatible with Taproot Assets stuff. I am not familiar enough with the details of Taproot Assets to confirm this. I think the main question I have is whether you can load assets into a channel during this kickoff step or not. If you can't then there's no reason we can't cut-through. If you can, then the cut-through would probably destroy those assets, which would be bad.

Since the legacy output necessarily can't have tapas in it, we only have to worry about the case where the kickoff would be hypothetically able to put them in. I realize this is something I haven't gotten clarification on that I need to.

The other thing I'm trying to understand is, if the goal is to upgrade to STC, I don't think we need to change the funding output? We just need to create new commit tx with p2tr outputs, and let it spend the original funding output, then there's no need to build the kickoff tx?

STC means that the funding output of the channel is p2tr, not that we want to change the commitment outputs to p2tr (although it would be assumed that we would do those too).

ProofOfKeags avatar May 03 '24 21:05 ProofOfKeags

Did some digging and found this in the TAP channel bLIP:

As the Taproot Assets protocol is a overlay system on top of the Taproot script template, the impact of Taproot Assets on the Simple Taproot Assets channel type is minimal. At a high level, one can bind Taproot Assets to a given P2TR output simply by including the asset tree root commitment within the committed tapscript tree. From here, the channel type simply needs to ensure that any subsequent spends from that output includes a new valid commitment (including valid witness data) in the outputs.

This seems to indicate that the kickoff transaction would be capable of loading assets into a channel by adding its own tapleaf to the tap tree, so we need to prohibit cut-through in that case. Currently this proposal does not specify any mechanism for doing this, but explicitly blessing cut-through would make this impossible without some sort of special casing.

ProofOfKeags avatar May 03 '24 22:05 ProofOfKeags

The major question that I have for this PR is whether you'd be open to breaking the change up into two parts:

  1. Rules + commitment update (not including STC channel_type)
  2. Funding output update

I am SO open to this that I have actually advocated for this before internally at LL, so thank you for the ammunition 😈 CC @Roasbeef

That said, there is a nasty problem that we have to deal with if we go that route. The current channel_type value we have is a bit of a disaster in terms of what precisely it is referring to. It is a not-quite-orthogonal configuration space with the following "axes":

  • Do we include anchor outputs?
  • Do we rotate the to_remote key?
  • Do we include fees on SS-HTLC txs?
  • Can we reference this channel by an alias?
  • Can we use this channel before its funding tx is mined?
  • Are we using output p2wsh output or a p2tr output?

Hypothetically if these were all truly orthogonal, we could negotiate the axes here independently and just exclude the funding output script from consideration for the time being and it would be relatively well-specified with that small stipulation. We would also then be able to exclude the zeroconf axis from renegotiation as well because its simply an incoherent request.

Of these different type axes they fall into 3 categories:

  1. They change/determine the function by which we render abstract channel state to concrete commitment transactions (option_anchors, option_static_remote_key, option_zero_fee_htlc_tx)
  2. They change/determine the funding output/script itself (option_simple_taproot)
  3. They change/determine the rules of engagement on when/how channel state can be updated (option_scid_alias, option_zeroconf)

These categories also appear stable to me as we can easily map the opening channel parameters onto them quite easily:

  • Rendering: dust_limit_satoshis, to_self_delay, all of the basepoints
  • Rules of Engagement: max_htlc_value_in_flight_msat, max_accepted_htlcs, channel_reserve_satoshis, htlc_minimum_msat (updated via gossip)
  • Funding Output Conversion: funding_pubkey

I think people are rightly dreading the idea of having to implement the funding output conversion of the proposal and I think the desire to break these proposals up comes from a place of wanting incremental improvement. Fair enough! Let's look into the future a bit, though. Let's say now that we already have point 1 from your breakup suggestion and now we definitely want to implement point 2. Do we want to implement a new negotiation scheme? My intuition here is no. We would want to piggy back on the existing negotiation scheme and add a provision for executing the new (more complicated) change. Feel free to contest this, but the rest of my explanation assumes you'll agree.

If we want to take advantage of the existing negotiation scheme we can somewhat easily implement the execution capability incrementally. After all, the existing negotiation scheme, as specified, allows for naming the particular parameters that you would like to reject. You could have a spec compliant implementation of this proposal that just always rejects upgrades to taproot. On a more practical level you would probably just reject any channel type you don't know how to interpret but the net result is the same. Later, should you decide to allow the new channel type altogether, you can implement the new execution capability and then simply stop rejecting requests to change that parameter.


With that out of the way there is still a question of how to organize the documents and whether or not we want to have separate documents for various pieces here:

As is, achieving interop on this proposal is blocked on a second implementation of STC because you can't get coverage for kickoff without supporting the option_taproot type

This is definitely a procedural hiccup. I see what you mean. If this proposal includes the spec'ed execution of a funding output conversion, do we technically have interop if we just implement negotiation but unconditionally reject everything? That's a hard question to answer and would welcome any thoughts on both how important this procedural issue is and any suggestions on how to do it given that this mechanism may be extensible into the future.

It puts a mechanism in place that we could use to upgrade to V3 channels, which is another important security improvement.

This is definitely the thing that has me scratching my head as I'm unaware of the details of V3 channels. Can you point me to anything that describes them? I assume it has to do with package relay policy and that at minimum we have a different version number on the commitment tx graph, but I'm not fully up to speed on the state-of-the-art here.

ProofOfKeags avatar May 16 '24 23:05 ProofOfKeags

Of these different type axes they fall into 3 categories

The difficulty here is that option_simple_taproot also falls into the commitment transaction category (1). There is a path here where we consider this upgrade mechanism to only apply to categories 1+3, and upgrade to a taproot commitment with a v0 funding output - would be interested in hearing how hairy that would be to implement for folks.

Let's say now that we already have point 1 from your breakup suggestion and now we definitely want to implement point 2. Do we want to implement a new negotiation scheme? My intuition here is no.

This seems to be the heart of the disagreement on how to go about part (2), so I don't think this is a foregone conclusion. I don't want to spam up this PR with that cross-proposal discussion so I've opened up a thread on delving here, but tl;dr I think that focusing on part (1) first is an incremental step forward that doesn't bias how we go about (2).

do we technically have interop if we just implement negotiation but unconditionally reject everything?

Given that the kickoff transaction is the bulk of complexity of the proposal, I'd say not? For the sake of comparison, I wouldn't consider interactive tx to have interop if we all just implemented tx_abort.

This is definitely the thing that has me scratching my head as I'm unaware of the details of V3 channels. Can you point me to anything that describes them

By "upgrade to V3 channels", I mean have a protocol in place that allows us to upgrade our commitment transaction format (#1 in your list of upgrade types). We'd still need to do the protocol work of defining what that commitment transaction looks like, implementing a subset of what's written up here here (specifically, without ephemeral anchors) - also added some details in that delving post.

carlaKC avatar May 17 '24 17:05 carlaKC

The difficulty here is that option_simple_taproot also falls into the commitment transaction category (1). There is a path here where we consider this upgrade mechanism to only apply to categories 1+3, and upgrade to a taproot commitment with a v0 funding output - would be interested in hearing how hairy that would be to implement for folks.

I think I see what you mean here in that by changing the funding output we have no choice but to also change the commitment tx rendering process since the commitment tx references the funding output by construction. What I'm not quite following here is the statement "...and upgrade to a taproot commitment with a v0 funding output". Do you mean "introduce a separate proposal to upgrade to taproot from a v0 funding output"?

This seems to be the heart of the disagreement on how to go about part (2), so I don't think this is a foregone conclusion.

I definitely do not believe it is a foregone conclusion, I just wanted to track the assumption in the rest of the argument to flesh it out entirely. If you don't want to implement that part you could always unconditionally reject chantype upgrades that include option_simple_taproot.

Given that the kickoff transaction is the bulk of complexity of the proposal, I'd say not? For the sake of comparison, I wouldn't consider interactive tx to have interop if we all just implemented tx_abort.

It really depends on what interop is trying to communicate. In the case of tx_abort it seems like definitely not, but what if you implement splicing in a way that always rejects splice-ins but not splice-outs?

If we assume that there are aspects to these protocols that are left up to the discretion of node policy, then we have to assume we might encounter any valid node policy.

When things are "interoperable" to me it means that I should not reach any state that results in UB. That's a somewhat low bar and may be unsatisfying. The next natural line in the sand is "I should be able to reach at least one non-erroring terminal state". Finally, the most stringent "I should be able to reach all non-erroring terminal states". The last one seems impossible in the presence of any discretionary rejections. Maybe this is another candidate for a delving thread.

I guess what I'm asking you here is, if I were to tell you implementations A and B "have interop" what expectations do you have of that claim, and which of those expectations do you depend on.

By "upgrade to V3 channels", I mean have a protocol in place that allows us to upgrade our commitment transaction format (no. 1). We'd still need to do the protocol work of defining what that commitment transaction looks like, implementing a subset of what's written up here here (specifically, without ephemeral anchors) - also added some details in that delving post.

Got it. Yeah I believe this would fit quite neatly into the existing proposal framework and it definitely falls under the rendering parameters for sure. This ship may have sailed but I really hope we factor channel_type into its constituent parts rather than continuing to overload it.

ProofOfKeags avatar May 17 '24 19:05 ProofOfKeags

"...and upgrade to a taproot commitment with a v0 funding output". Do you mean "introduce a separate proposal to upgrade to taproot from a v0 funding output"?

Definitely not (no moar proposals plz 😅 )! Meant that we could use dynamic commitments to only update our commitment transaction to use taproot without upgrading the funding output, introducing an inbetween channel type that has a segwit v0 funding output but uses taproot commitments. But as you point out, that certainly muddies the meaning of channel_type and I think it would probably be ugly to implement so not suggesting that we take that path.

This ship may have sailed but I really hope we factor channel_type into its constituent parts rather than continuing to overload it.

Looks like we've had this conversation before, my take from reading through that discussion is that we're only going to move forward in an "additive" manner rather than face this explosion of channel type permutations which makes sense to me. LMK if I'm missing your point here?


Maybe this is another candidate for a delving thread.

Yeah def off topic for on this PR - delving or Monday's spec meeting 👍

That said, my sub-cent opinions here

what if you implement splicing in a way that always rejects splice-ins but not splice-outs?

I wouldn't consider that sufficient interop to merge to the bolts fwiw.

If we assume that there are aspects to these protocols that are left up to the discretion of node policy, then we have to assume we might encounter any valid node policy.

Indeed, but if we don't ever reach the state where two implementations don't add a features then (by my understanding) it shouldn't be a bolt and we should blip it.

carlaKC avatar May 17 '24 20:05 carlaKC

Meant that we could use dynamic commitments to only update our commitment transaction to use taproot without upgrading the funding output, introducing an inbetween channel type that has a segwit v0 funding output but uses taproot commitments. But as you point out, that certainly muddies the meaning of channel_type and I think it would probably be ugly to implement so not suggesting that we take that path.

If such a channel type were to exist then yes we definitely could without issue. I don't think we (LND) are prioritizing making such a channel type a reality though. LND is interested in converting the funding output because we want to put taproot assets into the channel which requires the funding output change. I'm not a Tap wizard though so I am not 100% sure what the details of those constraints are.

ProofOfKeags avatar May 18 '24 00:05 ProofOfKeags