Skip to content

Add Option Upfront Shutdown#3655

Merged
Roasbeef merged 5 commits into
lightningnetwork:masterfrom
carlaKC:fundingmgr-optionupfrontshutdown
Dec 5, 2019
Merged

Add Option Upfront Shutdown#3655
Roasbeef merged 5 commits into
lightningnetwork:masterfrom
carlaKC:fundingmgr-optionupfrontshutdown

Conversation

@carlaKC
Copy link
Copy Markdown
Collaborator

@carlaKC carlaKC commented Oct 31, 2019

This PR adds support for option_upfront_shutdown_commitment, which allows nodes to specify a script to which funds should be paid out in the event of a cooperative close during channel negotiation.

Upfront shutdown addresses are set by default for channels that we open or accept if the remote peer supports this feature.

Replaces #449

Copy link
Copy Markdown
Contributor

@halseth halseth 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, things are coming together! Need to read up more on BOLT-2 before I can give it a more detailed look 😅

Comment thread lnwire/lnwire.go Outdated
Comment thread lnwire/accept_channel.go Outdated
Comment thread channeldb/channel.go Outdated
Comment thread fundingmanager.go Outdated
Comment thread discovery/mock_test.go Outdated
Comment thread peer.go Outdated
Comment thread server.go Outdated
Comment thread lnwire/features.go Outdated
Copy link
Copy Markdown
Contributor

@cfromknecht cfromknecht left a comment

Choose a reason for hiding this comment

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

@carlaKC solid PR! looks pretty complete to me, well tested and well documented :) completed an initial pass

Comment thread lnwire/accept_channel.go Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

note to self/spec: adding a TLV field after this seems difficult, as it requires knowing whether or not to expect the delivery address. we might accidentally parse a tlv stream into a delivery address, cc @Roasbeef @joostjager

Comment thread lnwire/accept_channel.go Outdated
Comment thread lnwire/shutdown.go Outdated
Comment thread lnwire/features.go Outdated
Comment thread lnwire/features.go Outdated
Comment thread lnwire/accept_channel.go Outdated
Comment thread channeldb/channel.go Outdated
Comment thread channeldb/channel.go Outdated
Comment thread fundingmanager.go Outdated
@wpaulino wpaulino removed their request for review October 31, 2019 17:43
@carlaKC carlaKC added the v0.9.0 label Oct 31, 2019
@carlaKC carlaKC force-pushed the fundingmgr-optionupfrontshutdown branch from a212935 to 49aa391 Compare November 1, 2019 09:57
@carlaKC
Copy link
Copy Markdown
Collaborator Author

carlaKC commented Nov 1, 2019

Pushed some small fixes + the ability to enable upfront shutdown a with enable_upfront_shutdown flag.

@joostjager joostjager added this to the 0.9.0 milestone Nov 1, 2019
Comment thread lnwire/open_channel.go Outdated
Comment thread lnwire/accept_channel.go Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The spec says

if both nodes advertised the option_upfront_shutdown_script feature:
MUST include either a valid shutdown_scriptpubkey as required by shutdown scriptpubkey, or a zero-length shutdown_scriptpubkey.`

I read this as we must write a zero length field in this case?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Checked this out and you're right about the 0 value 👍

So proceeding with the following:

  • Encode a 0 for empty shutdown address (fine for non upfront shutdown understanding lnd, will have to double check interop)
  • Encode len/addr when given a non-0 delivery address
  • Always try to decode with the EOF trick

Comment thread lnwire/open_channel.go Outdated
Comment thread server.go Outdated
Comment thread fundingmanager.go Outdated
Comment thread fundingmanager.go Outdated
Comment thread lnwallet/reservation.go Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

As there's no real validation going on here (other than the script size), I don't think this needs to go into the wallet. Instead, we can extend the normal contributions to encompass this new piece of information, as after the first two funding flow messages, all the necessary information is known.

Comment thread config.go Outdated
Comment thread discovery/mock_test.go Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure if this is a good move, as it may cause confusion when the interface is extended, but the tests aren't updated and fail. Also tbh, I didn't know this was possible :p

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

My argument for using this is that it results in tests failing loudly. If you extend an interface and a test uses the new function call it will panic, which you'll pick up and have to go see exactly what your change is affecting. If the tests need the new function, you will have to update the mock in your PR (as before), this just saves on some boilerplate :)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I like this boilerplate-free world :)

Comment thread lnwallet/reservation.go Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Following from my other comment, I think this can be handled as a contribution.

Comment thread lnwallet/wallet.go Outdated
@carlaKC carlaKC force-pushed the fundingmgr-optionupfrontshutdown branch from 49aa391 to a8a3a10 Compare November 6, 2019 13:29
@carlaKC carlaKC requested a review from joostjager as a code owner November 6, 2019 13:29
@carlaKC carlaKC force-pushed the fundingmgr-optionupfrontshutdown branch from a8a3a10 to 1b7c6e4 Compare November 6, 2019 13:35
@carlaKC carlaKC removed the request for review from joostjager November 6, 2019 13:36
Comment thread fundingmanager_test.go Outdated
@carlaKC carlaKC force-pushed the fundingmgr-optionupfrontshutdown branch 2 times, most recently from a24d0a2 to 3ff97a2 Compare November 8, 2019 15:10
@Roasbeef Roasbeef added enhancement Improvements to existing features / behaviour security General label for issues/PRs related to the security of the software spec wire protocol Encoding of messages for the communication between nodes P2 should be fixed if one has time labels Nov 9, 2019
Copy link
Copy Markdown
Contributor

@halseth halseth left a comment

Choose a reason for hiding this comment

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

Latest iteration looks very good!

Comment thread .golangci.yml Outdated
Comment thread lnwire/features.go Outdated
Comment thread discovery/mock_test.go Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I like this boilerplate-free world :)

Comment thread htlcswitch/link_test.go Outdated
Comment thread peer.go Outdated
Comment thread server.go Outdated
Comment thread config.go Outdated
Comment thread peer.go Outdated
Comment thread fundingmanager.go Outdated
Comment thread channeldb/channel.go Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What do you think about making the methods LocalShutdownScript() fetch directly from the database instead of this pre-populated field? Would it have any downsides?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The fields in OpenChannel are also used for writing to the DB, and threading the values through the funding flow (as part of chanState). Since we need the fields in OpenChannel to write it makes sense to read them in/accessin memory?

To keep them out of channel state completely, they'd need to be in ChannelReservation which leaks into lnwallet.

Comment thread lnwire/accept_channel_test.go Outdated
Comment thread lnwire/accept_channel_test.go Outdated
Comment thread lnwire/accept_channel_test.go Outdated
Comment thread lnwire/lnwire_test.go Outdated
Comment thread lnwire/accept_channel.go Outdated
Comment thread fundingmanager.go Outdated
Comment thread lnwallet/reservation.go Outdated
Comment thread server.go Outdated
Comment thread lnwallet/reservation.go Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is this necessary to set here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

We use the values on partialState when we call SyncPending in handleFundingCounterPartySigs or handleSingleFunderSigs, which both use the ChannelReservation.partialState.

I'm going to update to only set the values on partialState when we write to disk, but I do think it's a bit strange to have these two out of sync with each other. Fine for now, but future changes are going to have to know that this value is not set on partialState.

Comment thread fundingmanager.go Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

looks like the shutdown script can be moved to being part of the InitChannelReservation call?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Previously got some comments from @Roasbeef about having this data in contributions, which is why it's not in InitChannelReservation.

Having these addresses in ChannelReservation itself requires a method similar to this because we still need to lock the reservation and set the value. I think where we put this (contributions vs reservation itself) may depend on if/how we have plans to decouple funding manager/ wallet, which I don't have the best context for.

@carlaKC carlaKC force-pushed the fundingmgr-optionupfrontshutdown branch from dc6b000 to adf00b8 Compare November 19, 2019 20:01
@carlaKC carlaKC requested a review from halseth November 19, 2019 21:35
Comment thread lnwire/lnwire_test.go Outdated
Comment thread feature/default_sets.go Outdated
Comment thread chancloser.go Outdated
Comment thread peer.go Outdated
Comment thread peer.go Outdated
Copy link
Copy Markdown
Contributor

@cfromknecht cfromknecht left a comment

Choose a reason for hiding this comment

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

@carlaKC latest version is 🔥well tested and easy to follow, only minor comments

Comment thread lnwire/features.go Outdated
Comment thread lnwire/accept_channel_test.go Outdated
Comment thread peer.go Outdated
Comment thread chancloser.go Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is it possible to pull this into a helper so that isn't duplicated?

Comment thread chancloser_test.go Outdated
Comment thread channeldb/channel_test.go Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

typically we use all lower cases for test names, not a blocker tho

Comment thread fundingmanager.go Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

perhaps extract this closure as a member of the funding manager? can this pass it to both as, e.g., f.genDeliveryAddr

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Peer already has a genDeliveryScript, so this (as is, and if added to funding manager) results in some duplication. An alternative would be to expose genDeliveryScript on the peer interface, or move all of the logic in getUpfrontShutdownScript into f.genUpfrontShutdown?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it is just to avoid some clutter and indentation here, instead having the method be

func(f *fundingmanager) genDeliveryAddr() (lnwire.DeliveryAddress, error) {
			addr, err := f.cfg.Wallet.NewAddress(lnwallet.WitnessPubKey, false)
			if err != nil {
				return nil, err
			}
			return txscript.PayToAddrScript(addr)
}

@carlaKC carlaKC force-pushed the fundingmgr-optionupfrontshutdown branch from adf00b8 to ef67638 Compare November 25, 2019 08:49
@carlaKC
Copy link
Copy Markdown
Collaborator Author

carlaKC commented Nov 27, 2019

Done some testing to make sure these changes work with other impls/ lnd as is.

lnd:
Branch -> Master: open and close channel ok, does not set upfront for peers that don't support it
Branch -> Branch: local and remote upfront preserved through restart, shutdown addresss checked when appropriate

c-lightning:
Supports upfront shutdown
Open channel from lndl with and without upfront shutdown ok.
Open channel from c-lightning with and without upfront shutdown ok.

C-Lightning does disconnect from us on channel close, but this occurs on master as well, so I'm assuming that's because they only support single channels so do cleanup on close. Will double check.

eclair:
TBD

Just want to clarify the meaning of "MUST fail the connection" in BOLT 2 before requesting review again. Specifically whether we should error out of the close channel interaction or disconnect from the peer entirely.

@carlaKC carlaKC force-pushed the fundingmgr-optionupfrontshutdown branch 2 times, most recently from 0792a15 to e2b0509 Compare November 28, 2019 17:16
@carlaKC
Copy link
Copy Markdown
Collaborator Author

carlaKC commented Nov 28, 2019

Ecalir interop done, they don't support upfront shutdown so I just checked that channel open/close work as before.

Updated disconnection function call to permanently disconnect from the violating peer by removing them from our persistent peers. We do still have a channel open with the peer, and they will most likely just reconnect to us anyway (since we don't have the ability to ban).

stevenroose and others added 5 commits December 3, 2019 11:38
This commit adds the feature bit and additional fields
required in `open_channel` and `accept_channel` wire
messages for `option_upfront_shutdown_script`.
This commit enables signalling for the optional
upfront shutdown script feature bit.
This commit sets our close addresss to the address
specified by option upfront shutdown, if specified,
and disconnects from peers that fail to provide
their upfront shutdown address for coopertaive closes
of channels that were opened with the option set.
This commit adds fields for upfront shutdown scripts set
by the local and remote peer to the OpenChannel struct.
These values are optional, so they are added with their
own keys in the chanBucket in the DB.
This commit gets upfront shutdown scripts from openchannel and
acceptchannel wire messages sent from our peer and sets upfront
shutdown scripts in our open and accept channel messages when
the remote peer supports option upfront shutdown and we have
the feature enabled.
@carlaKC carlaKC force-pushed the fundingmgr-optionupfrontshutdown branch from e2b0509 to 9b35c34 Compare December 3, 2019 09:38
Copy link
Copy Markdown
Contributor

@halseth halseth left a comment

Choose a reason for hiding this comment

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

Awesome work, this LGTM now! 💯

Follow-up would be to enable the feature on channel opens. Maybe create an issue for that for someone to pick up? :)

Copy link
Copy Markdown
Contributor

@cfromknecht cfromknecht left a comment

Choose a reason for hiding this comment

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

beautiful PR, LGTM 💯

@halseth halseth removed the request for review from Roasbeef December 4, 2019 09:15
@carlaKC carlaKC requested a review from Roasbeef December 4, 2019 09:26
Copy link
Copy Markdown
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.

LGTM 💸

@Roasbeef Roasbeef merged commit 183797f into lightningnetwork:master Dec 5, 2019
@carlaKC carlaKC deleted the fundingmgr-optionupfrontshutdown branch April 3, 2020 09:21
@GlenCooper
Copy link
Copy Markdown
Contributor

👀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Improvements to existing features / behaviour P2 should be fixed if one has time security General label for issues/PRs related to the security of the software spec wire protocol Encoding of messages for the communication between nodes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants