Open ProofOfKeags opened 11 months ago
To keep the project focused, this is the list of the design goals in order of priority. With my current understanding of the problem set, it seems like it is possible (but still unknown) that not all of these goals is possible to realize simultaneously. Therefore, if it is found to be either impossible or prohibitively complex to implement, we will sacrifice later goals to accomplish earlier ones in the below list.
open_channel
and accept_channel
channel_type
s, including aforementioned STCschannel_type
s (protocol cannot directly specify anything that implies knowledge of the output script that the post-conversion commitment transaction spends)In addition to this we will need to make sure that various protocol flows are satisfactorily immune to pinning issues, though I'm less sure about how to precisely put that in the priority list. After that we may wish to golf on certain transaction structures to save chain-space, round-trips, and wire-space.
CC @Roasbeef @saubyk please chime with any issues you have with this as a design target
Thanks @ProofOfKeags for putting this list together. Couple of comments from my end.
Convert to Taproot Channels from pre-taproot channels WITHOUT spending pre-taproot channelpoint UTXO
This is for my education. Is it technically possible to change a pre-taproot channel to taproot one without spending the channel point UTXO?
Convert between all currently defined channel_types, including aforementioned STCs
Is there an advantage in building it in a general way making it possible to convert b/w any channel type? Also curious about the engineering complexity in making it general vis-a-vis a specific use case of converting option_static_remotekey
/option_anchor_outputs
to option_simple_taproot
? Wondering if there would ever be a use case of converting from taproot to others and if the associated engineering complexity would be worth it
Is it technically possible to change a pre-taproot channel to taproot one without spending the channel point UTXO?
Fundamentally what is required is being able to spend the legacy channelpoint UTXO into a Taproot channelpoint UTXO. However, this transaction doesn't need to be published. In fact, if it is published, without a wide deployment of Taproot aware (G175) implementations, then the channel will be rendered unusable by implementations that can't understand G175 channel announcements. So technically we are still "spending" the channelpoint UTXO, but this is not true from the perspective of the braoder network.
Is there an advantage in building it in a general way making it possible to convert b/w any channel type?
Prooooobably not? It depends on whether channel types that are developed later are always preferable to earlier ones. Even if they are, though, if we have a facility that can do arbitrary conversions, then even with a monotonically "better" channel type, being able to skip intermediate channel types could be desirable. All of this is theoretical though.
Also curious about the engineering complexity in making it general vis-a-vis a specific use case of converting option_static_remotekey/option_anchor_outputs to option_simple_taproot
My take on this is that designing a system to do one specific thing is the easiest, followed by designing a system to handle the general case. The largest maintenance burden is incurred when we design a system to handle a list of enumerated things and handle them in ways that reference the particulars of that case. This requires that we understand the properties of the existing system fairly well. However, the more we generalize the designs we create, the better we will understand those properties, creating a virtuous cycle.
Wondering if there would ever be a use case of converting from taproot to others and if the associated engineering complexity would be worth it
I sincerely doubt that from a user perspective this is ever going to be worth it. However, I suspect at this moment that a solution that allows for this case is one that will be far more future proof than one that takes advantage of the particulars of the channel types we currently use.
May be good to also unify some of the content in this issue as it's already identified some of the relevant integration/implementation sides. One example is the ChainWatcher
recognizing that a force close can now occur if the kick off transaction hits the chain, or if the commitment does.
Design Goals
Convert to Taproot Channels from pre-taproot channels WITHOUT spending pre-taproot channelpoint UTXO Modify all Channel Constraints that are originally set in open_channel and accept_channel
I think it's useful view the greater proposal as made up of two phases: expression and execution.
IMO from the get go, we'll want to make sure that just about everything we can think of can be expressed with the set of TLVs advertised. I think we're already most of the way there, but still need to catch up with the current BOLT draft.
Execution on the other hand is distinct in my mind as there're certain proposals that can be generically executed, eg: updating all the channel constraints, as then for the next state, the new constraints are applied. Others will require a new "execution module" for each possible transition. One example is going from static key to anchors vs anchors to taproot channels. For the sake of the channel type conversion, the only concrete transition I think we should be concerned with is: static key to taproot chans (or anchors for public chans*), anchors to taproot chans, and taproot chans' to taproot chans.
Allow multiple Dynamic Channel conversions over the lifetime of the channel WITHOUT spending original channelpoin This is currently the most at-risk requirement in our current design due to needing a revocation scheme for the "kickoff transaction"
As we discussed offline, I don't think we need a revocation scheme for the kick off transaction, although if designing from the group up with no constraints w.r.t time, I think we'd add one in. IMO the ideal revocation scheme here uses the primitives from this paper, which needs musig2 adaptor sigs. We'll need this eventually for PTLC, but I don't think we need to go down that side quest at this moment.
Instead, we'd accept that when breaching the breacher needs to first broadcast the kick off, then go ahead and breach. I don't really see this as a grieving vector, as it just terminates after a single road: they broadcast 2 txs, then we enact justice. It isn't like eltoo where they can continue to broadcast the very next one, over and over again and waste our time. This is where the ChainWatcher
will also be important: if the kick off transaction also encodes a sequence number in the locktime+sequence, then it can use this to detect a breach at the earliest possible point.
I don't really see this as a grieving vector as it just terminates after a single road
In a world where we don't have a revocation for the kickoff itself, the griefing vector comes from the situation where they broadcast an old kickoff but do not broadcast an actual breach transaction. Sans breach transaction, we can't enact justice. However we also can't broadcast our own followup to the kickoff since it too has been revoked. This leaves money locked up in the kickoff output until either party decides to broadcast a revoked commitment built off of that old kickoff, which neither one has the incentive to do. The equilibrium here if we take the broadcast of an old kickoff as given is for neither party to broadcast the valid but revoked commitments they have built off of the kickoff, leaving the channelpoint buried.
Of course, in LN today, due to breach/justice mechanic a party always has the opportunity to nuke all of their own money by broadcasting a revoked commitment, however I don't believe there is a precedent for nuking your own money in order to nuke your counterparty's. If channel liquidity is heavily imbalanced then there could be a scenario when I nuke 1k sats to cause you to lose 100k sats.
I think it's useful view the greater proposal as made up of two phases: expression and execution.
This feels like a good delineation and we can get TLVs locked down pretty quickly I'm not so worried about that.
Others will require a new "execution module" for each possible transition.
Yeah I think we can also specify that if the implementation doesn't have a valid execution module for that transition then it can just bounce the dyncomm proposal at the beginning of the negotiation. Having an implementation that is incapable of a transition is not dissimilar from having a user unwilling to do a transition.
I took a break from working out these details to finish up my first draft of the actual proposal language. That work can be tracked here
During yesterday's design meeting we discussed the following items:
The initiator of the DynComm upgrade will pay the fees, even if they were not the initial channel funder
:+1:
It's been a long time since I updated the status of this issue. So here is where we are at:
The spec draft is largely complete. Since we are not yet clear on how useful multiple funding output changes will be, we are in the immediate implementation plan going to block multiple dynamic commitment upgrades that would require funding output changes. This is a reasonable limitation to start out with. If we want to allow subsequent changes, since they will be infrequent we will not revoke prior kickoff transactions, nor will we cut-through them. Instead they will be chained until we decide that it is necessary to optimize this workflow. The odds are that YAGNI.
We are no proceeding with a number of CSM refactors that will allow us to insert the DynComm execution into the existing updateLog process. This is important because the CSM has been carefully designed to remain consistent in the presence of arbitrarily timed power failure. Since DynComms fundamentally is making a change to the CSM itself, and it is important to remember precisely when those CSM parameters changed with respect to the local and remote commitment heights, we need to make sure that we follow the same sequential processing that the current CSM does.
This issue is meant to be a living document to track the state of the Dynamic Commitments project.
The driving force behind the desire to have dynamic commitments is to allow us to "upgrade" an existing channel to use the Taproot Channels that are introduced in LND 0.17.0. The proposal has goals beyond simply upgrading channels to Taproot, but this is noted to prevent excessive scope creep and keep focused.
As part of the Dynamic Commitments work there is spec work that must be mostly complete before we embark on any implementation within LND.
This issue will be updated to reflect the current state of the overall project.
Implementation Plan
fn
tools #8653