Skip to content

Introduce new commitment format to enforce channel lease expirations in scripts#5549

Closed
wpaulino wants to merge 29 commits intolightningnetwork:masterfrom
wpaulino:channel-lease-script-enforcement
Closed

Introduce new commitment format to enforce channel lease expirations in scripts#5549
wpaulino wants to merge 29 commits intolightningnetwork:masterfrom
wpaulino:channel-lease-script-enforcement

Conversation

@wpaulino
Copy link
Contributor

@wpaulino wpaulino commented Jul 21, 2021

This PR introduces a new commitment format that's intended for use by channels resulting from Lightning Pool leases. This new commitment format builds upon the recently proposed anchors with zero HTLC fees commitment format, with an additional constraint on any outputs that pay directly to the channel initiator (also known as the channel seller in Pool). This additional constraints consists of an additional CLTV that requires a channel lease's expiration to be met before the channel initiator is able to claim their funds back from the channel. This unfortunately doesn't serve as a guarantee that the channel purchased cannot be closed prematurely, as we still need to allow the commitment transaction to be broadcast to resolve in-flight HTLCs, but instead serves as an incentive to prevent the channel initiator from prematurely closing out a channel as they won't be able to claim their funds until the lease expires.

This additional CLTV requirement for the channel initiator is found within the following three witness scripts in commitment transactions with anchors:

  • to_local output witness script:
OP_IF
    <revocation_pubkey>
OP_ELSE
    <lease_maturity> OP_CHECKLOCKTIMEVERIFY OP_DROP <------- new
    <to_self_delay> OP_CHECKSEQUENCEVERIFY OP_DROP
    <local_delayed_pubkey>
OP_ENDIF
OP_CHECKSIG
  • to_remote output witness script:
<remote_pubkey> OP_CHECKSIGVERIFY
<lease_maturity> OP_CHECKLOCKTIMEVERIFY OP_DROP <------- new
1 OP_CHECKSEQUENCEVERIFY
  • Second-level HTLC timeout transaction output witness script:
OP_IF
    <revocation_pubkey>
OP_ELSE
    <lease_maturity> OP_CHECKLOCKTIMEVERIFY OP_DROP <------- new
    <to_self_delay> OP_CHECKSEQUENCEVERIFY OP_DROP
    <local_delayed_pubkey>
OP_ENDIF
OP_CHECKSIG

Note that this constraint only applies to the channel initiator, so given Alice (initiator) & Bob have a leased channel using this new commitment type:

  • Alice's commitment transaction:
    • to_local: OP_IF <revocation_pubkey> OP_ELSE <lease_maturity> OP_CHECKLOCKTIMEVERIFY OP_DROP <to_self_delay> OP_CHECKSEQUENCEVERIFY OP_DROP <local_delayed_pubkey> OP_ENDIF OP_CHECKSIG
    • to_remote: <remote_pubkey> OP_CHECKSIGVERIFY 1 OP_CHECKSEQUENCEVERIFY
  • Bob's commitment transaction:
    • to_local: OP_IF <revocation_pubkey> OP_ELSE <to_self_delay> OP_CHECKSEQUENCEVERIFY OP_DROP <local_delayed_pubkey> OP_ENDIF OP_CHECKSIG
    • to_remote: <remote_pubkey> OP_CHECKSIGVERIFY <lease_maturity> OP_CHECKLOCKTIMEVERIFY OP_DROP 1 OP_CHECKSEQUENCEVERIFY

Depends on #5373.

@wpaulino wpaulino requested a review from Roasbeef July 21, 2021 01:05
Copy link
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

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

Really happy to see that all the refactoring we did before/during the anchor output saga helped to guide and compress the final diff off this new channel type! Completed an initial pass, but will do a few more takes, with one of the focusing primarily on the itests, as well as the sweeper bug fix (?) inserted within the diff.

Comment on lines 105 to 106
Copy link
Member

Choose a reason for hiding this comment

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

Not something we need to do right now, but thinking in the future we might want to create sort of embedded sub-structs that house all the unique params for a given channel type. This way things get less cluttered as more channel tyupes are added overtime.

@wpaulino wpaulino requested a review from Roasbeef July 29, 2021 19:52
Copy link
Collaborator

@guggero guggero left a comment

Choose a reason for hiding this comment

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

Did a high-level pass, still need to digest and think about the implications of those changes a bit more.
Great work on everything I've seen so far! Commits read well and diff is comparatively small for all it achieves.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I assume at one point we'd require any Pool maker to have this turned off?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's off by default, but yes. Funding a script enforced channel with this flag enabled will fail.

Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: move error outside of switch too?

Roasbeef and others added 21 commits July 30, 2021 14:55
In this commit, we add a new TLV record that's intended to be used as an
explicit channel commitment type for a new form of funding negotiation,
and later on a dynamic commitment upgrade protocol. As defined, we have
3 channel types: base (the OG), tweakless, and anchors w/ zero fee
HTLCs. We omit the original variant of anchors as it was never truly
deployed from the PoV of lnd.
In this commit, we add a new ChannelType field as a new TLV record to
the OpenChannel message. During this change, we make a few tweaks to the
generic TLV encode/decode methods for the ExtraOpaqueData struct to have
it work on the level of tlv.RecordProducer instead of tlv.Record, as
this reduces line noise a bit.

We also partially undo existing logic that would attempt to "prepend"
any new TLV records to the end of the ExtraOpaqueData if one was already
present within the struct. This is based on the assumption that if we've
read a message from disk to order to re-send/transmit it, then the
ExtraOpaqueData is fully populated so we'll write that as is. Otherwise,
a message is being encoded for the first time, and we expect all fields
that are known TLV fields to be specified within the struct itself.

This change required the unit tests to be modified slightly, as we'll
always encode a fresh set of TLV records if none was already specified
within the struct.
If these bits are present, then both sides can examine the new
CommitmentType TLV field that's present and use this in place of the
existing implicit commiment type negotiation. With this change, it's now
possible to actually deprecate old unsupported commitment types
properly.
This field will be examined later down the stack along with the set of
feature bits to determine if explicit channel commitment type
negotiation is possible or not.
This commit adds the ability for a channel initiator/responder to
determine whether the channel to be opened can use a specific commitment
type through explicit negotiation. It also includes the existing
implicit negotiation logic to fall back on if explicit negotiation is
not supported.
In this commit, we modify the existing logic that defaults to implicit
commitment type negotiation to support explicit negotiation if the new
feature bit is set. This change allows us to ditch the notion of a
"default" commitment type, as we'll now use feature bits to signal our
understanding of a commiment type, but allow peers to select which
commitment type they actually wish to use.

In addition, this explicit negotiation removes the need for using the
required bit of any commitment types. Instead, if an implementation
wishes to no longer support a commitment type, they should simply stop
advertising the optional bit.
The new commitment type consists of adding an additional CLTV
requirement to guarantee a leased channel's expiration on any commitment
and HTLC outputs that pay directly to the channel initiator.
This witness generators and weight estimates added only apply for the
new script-enforced leased channel commitment type.
This commit modifies the channel state machine to be able to derive the
proper commitment and second-level HTLC output scripts required by the
new script-enforced leased channel commitment type.
wpaulino added 8 commits July 30, 2021 15:22
In order to sweep the commitment and HTLC outputs belonging to a
script-enforced leased channel, each resolver must know whether the
additional CLTV clause on the channel initiator applies to them. To do
so, we retrieve the historical channel state stored within the database
and supplement it to the resolvers to provide them with what's needed in
order to sweep the necessary outputs and resolve their respective
contracts.
This aims to cover an edge case and also serves as an optimization of
what happens when an input that was offered to the Sweeper with an
exclusive group is re-offered without one. This happens every time we
attempt to sweep the different possible anchors of a channel at the time
of broadcast, as we don't know which commitment transaction will end up
confirming in the chain. Once the commitment transaction confirms
however, we know which anchor output to act upon and re-offer it to the
Sweeper without an exclusive group. At this point, the Sweeper will
continue to attempt sweeping the other anchor output versions even know
we know they are not valid.
We update several of our integration tests that exercise different
scenarios with regards to the broadcast of a channel commitment
transaction with HTLCs in-flight to use the new commitment type for
channel leases. We do this to ensure we have complete coverage of said
channel commitment type. This required changing several assumptions
throughout the tests based on when we should expect sweeps to happen.
@Roasbeef Roasbeef added this to the v0.14.0 milestone Aug 31, 2021
@Roasbeef
Copy link
Member

Roasbeef commented Sep 1, 2021

The dep PR has landed, will remake this one (rebased) so we can continue review+testing there.

@Roasbeef
Copy link
Member

Rebased version: #5709

@Roasbeef Roasbeef closed this Sep 11, 2021
@wpaulino wpaulino deleted the channel-lease-script-enforcement branch October 27, 2021 19:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants