Add Option Upfront Shutdown#3655
Conversation
halseth
left a comment
There was a problem hiding this comment.
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 😅
cfromknecht
left a comment
There was a problem hiding this comment.
@carlaKC solid PR! looks pretty complete to me, well tested and well documented :) completed an initial pass
There was a problem hiding this comment.
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
a212935 to
49aa391
Compare
|
Pushed some small fixes + the ability to enable upfront shutdown a with |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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/addrwhen given a non-0 delivery address - Always try to decode with the EOF trick
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 :)
There was a problem hiding this comment.
I like this boilerplate-free world :)
There was a problem hiding this comment.
Following from my other comment, I think this can be handled as a contribution.
49aa391 to
a8a3a10
Compare
a8a3a10 to
1b7c6e4
Compare
a24d0a2 to
3ff97a2
Compare
halseth
left a comment
There was a problem hiding this comment.
Latest iteration looks very good!
There was a problem hiding this comment.
I like this boilerplate-free world :)
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
is this necessary to set here?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
looks like the shutdown script can be moved to being part of the InitChannelReservation call?
There was a problem hiding this comment.
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.
dc6b000 to
adf00b8
Compare
cfromknecht
left a comment
There was a problem hiding this comment.
@carlaKC latest version is 🔥well tested and easy to follow, only minor comments
There was a problem hiding this comment.
is it possible to pull this into a helper so that isn't duplicated?
There was a problem hiding this comment.
typically we use all lower cases for test names, not a blocker tho
There was a problem hiding this comment.
perhaps extract this closure as a member of the funding manager? can this pass it to both as, e.g., f.genDeliveryAddr
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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)
}adf00b8 to
ef67638
Compare
|
Done some testing to make sure these changes work with other impls/ lnd as is. lnd: c-lightning: 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: 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. |
0792a15 to
e2b0509
Compare
|
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). |
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.
e2b0509 to
9b35c34
Compare
halseth
left a comment
There was a problem hiding this comment.
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? :)
cfromknecht
left a comment
There was a problem hiding this comment.
beautiful PR, LGTM 💯
|
👀 |
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