[6/?] - lnwallet+chancloser: update channel state machine and co-op close for musig2 flow#7345
Conversation
There was a problem hiding this comment.
I wonder if it's possible to only have this taproot check in a single place, quite challenging i guess. atm it's scattered in all the "components", like CreateHtlcSuccessTx also does this check.
There was a problem hiding this comment.
Yeah it's a bit scattered right now. In other PR @joostjager brought up the idea we initially had to sort of split things out into more of a set of "builder" implementations of a new interface. The idea then is that we'd init the commitment/HTLC builder once, then call into that. That way we can remove all the branching we have for taproot vs not. It's a bigger change/refactor though, so happy to pursue it, but I think makes sense to defer for another PR series.
The other upcoming change we have is the taproot assets set of changes, which'll add yet another channel type, which brings its own unique attriobutes along. I think this would be a good time to make such a change.
ellemouton
left a comment
There was a problem hiding this comment.
high level first pass comments 🤓
9636891 to
717c9a3
Compare
58e6bef to
ce6879c
Compare
717c9a3 to
4a43a07
Compare
781a70f to
2d4df80
Compare
4a43a07 to
2882db4
Compare
b9e8011 to
ee8526b
Compare
ee8526b to
763d774
Compare
|
Pushed up a new version, added tests for co-op close, and also tests for channel re-establish, PTAL! |
b3a68b0 to
07d8f36
Compare
| if chanType.IsTaproot() { | ||
| taprootOutputKey, err := input.TaprootSecondLevelHtlcScript( | ||
| revocationKey, delayKey, csvDelay, | ||
| ) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| pkScript, err = input.PayToTaprootScript(taprootOutputKey) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
There was a problem hiding this comment.
no longer need this since the switch now happens in SecondLevelHtlcScript :)
| } | ||
|
|
||
| default: | ||
| witnessScript, err = input.SecondLevelHtlcScript( |
There was a problem hiding this comment.
missing error check for this
| @@ -3299,7 +3299,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing, | |||
|
|
|||
| // If the HTLC isn't dust, then we'll create an empty sign job | |||
There was a problem hiding this comment.
nit: commit message is a bit stale I think. The We also modify the sigpool to now use a input.Signature everywhere part was in 5e7a97c
| // log is a channel-specific logging instance. | ||
| log btclog.Logger | ||
|
|
||
| // taprootNonceProducer is used to generate a shachain tree for the |
There was a problem hiding this comment.
nit: commit message a bit stale. This commit updates all the signature validation methods for the channel & not only the HTLC validation
| case isTaproot && isInitiator && !feeMatchesOffer: | ||
| return nil, false, fmt.Errorf("fee rate for "+ | ||
| "taproot channels was not accepted: "+ | ||
| "sent %v, got %v", | ||
| c.idealFeeSat, remoteProposedFee) |
There was a problem hiding this comment.
should we send some kind of warning to the peer here?
There was a problem hiding this comment.
also - related to earlier question - should we make sure to re-set our closing verification nonce here? to ensure when we try close again that we dont use same nonce (since MusigChanCloser struct is still the same I think. I dont think it gets refreshed)
There was a problem hiding this comment.
Yeah we should actually send it back here: https://github.com/lightningnetwork/lnd/blob/master/peer/brontide.go#L3528-L3540
There was a problem hiding this comment.
What's try again mean here? When we fail above, the chancloser is removed.
There was a problem hiding this comment.
When we fail above, the chancloser is removed.
Indeed - missed this. Mah bad
yyforyongyu
left a comment
There was a problem hiding this comment.
Reviewed this PR to get a better understanding of the following PRs, think we need to fix CI tho.
| // another musig2 session. In order to permit our implementation to not have to | ||
| // write any secret nonce state to disk, we'll use the _next_ shachain | ||
| // pre-image as our primary randomness source. When used to generate the nonce | ||
| // again to broadcast our commitment hte current height will be used. |
There was a problem hiding this comment.
| // again to broadcast our commitment hte current height will be used. | |
| // again to broadcast our commitment the current height will be used. |
| // We'll compare the proposed total fee, to what we've proposed during | ||
| // the negotiations. If it doesn't match any of our prior offers, then | ||
| // we'll attempt to ratchet the fee closer to | ||
| // If this is a taproot channel, then it MUST have a partial |
There was a problem hiding this comment.
Something to do in the future, a general pattern we can have is case msg: processMsg or handleMsg, eg, here we'd have processCloseFeeNegotition to avoid the ever-growing long method and it's also easier to reason about it and test.
| // NewCommitState wraps the various signatures needed to properly | ||
| // propose/accept a new commitment state. This includes the signer's nonce for | ||
| // musig2 channels. | ||
| type NewCommitState struct { |
There was a problem hiding this comment.
maybe NextCommitState? New sounds like you are initializing a struct here.
|
|
||
| // If we use the original offer, then Alice should accept this message, | ||
| // and finalize the shutdown process. We expect a message here as Alice | ||
| // will echo back the final message. |
There was a problem hiding this comment.
the spec doesn't explicitly say that we're allowed to echo back the final message -- this came up when we were testing zero-conf with LDK. I don't think we should change this here, but figured I'd point out
We need to export the enum as it'll now be used in areas such as the chan closer.
…to accept In this commit, we add a new NewCommitState struct. This preps us for the future change wherein a partial signature is also added to the mix. All related tests and type signatures have also been updated accordingly.
…ation In this commit, we update the channel state machine with a new set of functional options that can be used to create/set the musig session state. When a channel is made during the funding process, the set of nonces we want to use is already known, so we allow them to be passed in. Similarly, once the channel is confirmed, then we'll need to create another channel instance that this times carries the newly generated nonces to send along side funding_locked. We also add some utility methods to permit callers to properly generate nonces in the various contexts.
In this commit, we update the genRemoteHtlcSigJobs function to be able to generate taproot jobs. We also modify the sigpool to now use a input.Signature everywhere. This'll allow us to pass around both ECDSA and Schnorr signatures via the same interface. We use a tapscript sighash in this case, as all the HTLC spends will actually be script path spends.
In this commit, we update the genHtlcSigValidationJobs function to be taproot aware. As we actually need a schnorr signature for the taproot validation, we need to coerce the entire wire type into a schnorr sig with the ForceSchnorr() method.
In this commit, we update the co-op close flow to support the new musig2 keyspend flow. We'll use some new functional options to allow a caller to pass in an active musig2 session. If this is present, then we'll use that to complete the musig2 flow by signing with a partial signature, and then ultimately combining the signatures at the end.
In this commit, we fix a bug in the `deriveMusig2Shachain` function where it didn't actually use the passed in revocation root as part of the hmac invocation. We also modify the function to be more generally useable as well, as now the caller can just pass in the revocation root things should be derived from.
In this commit, we update the ChanSyncMsg to populate nonce information. With this change, we can now hide nonce generation further down in the pipeline and ensure that all callers will have the expected fields populated.
Before this commit, we would conditionally generate nonces in RevokeCurrentCommitment. We move this to generateRevocation as this is called when doing channel sync, and we want to make sure we send the correct set of nonces.
In this commit, we update the logic to handle nonce init in ProcessChanSyncMsg. Once a channel is already open, this is where we'll get the new nonce data from the remote party we'll use to gain the nonce we need to sign for their next state.
07d8f36 to
5c09d61
Compare
d4b6877 to
7764f65
Compare
Change Description
In this PR, we update the channel state machine to be aware of the new musig2 flow. Along the way, we update some util functions to ensure we can use them to generate scripts/transactions for both segwit v0 and v1 channels.
In this new flow, each time we send a signature, we sig a partial sig along with the nonce that we used to sign. Upon receiving that signature, the remote party will use the nonce to complete their local session (for that state).
Each time a signature is received, a party will generate another nonce that'll be used to create their next local state. This next local/verification nonce is then sent alongside the revoke_and_ack message. Upon receiving the revocation, the party that originally sent the sig, can then use the new local nonce to prep the session for the next state.
We also update the co-op close state machine to be proper taproot aware. This involves setting the new nonce and partial signatures fields in the shutdown and closing signed messages. The other big change here is that we'll short circuit most of the co-op close flow. Rather than attempt a "negotiation", we'll just have the responder accept w/e the initiator sends, as they're the ones that pay the fees in the end.
In the next PR, we'll hook the new reservation flow up to the funding manager, and fill out the other functionality needed for the other sub-systems to be aware of the new channel type.
Steps to Test
Steps for reviewers to follow to test the change.
Pull Request Checklist
Testing
Code Style and Documentation
[skip ci]in the commit message for small changes.📝 Please see our Contribution Guidelines for further guidance.