-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[4/?] - input+lnwallet: prepare input package for funding logic, add new MusigSession abstraction #7340
[4/?] - input+lnwallet: prepare input package for funding logic, add new MusigSession abstraction #7340
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First pass looks good! In my next pass I will spend more time understanding the details of the last commit
// FromWireSig maps a wire partial sig to this internal type that we'll use to | ||
// perform signature validation. | ||
func (p *MusigPartialSig) FromWireSig(sig *lnwire.PartialSigWithNonce, | ||
) *MusigPartialSig { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: format
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotta stamp something in the formatting guide here...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty straightforward, will have to see how it fits in with the other changes
73baf9c
to
8b3a3d6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we are missing unit tests here, can help with it if needed.
ff278d8
to
d7ccdef
Compare
8b3a3d6
to
6fc2387
Compare
@Roasbeef, remember to re-request review from reviewers when ready |
6fc2387
to
8819f71
Compare
Initial set of review comment addressed. Will request review again after I put up the unit tests. |
2be6b53
to
eecba46
Compare
083af6f
to
a8e8d06
Compare
a8e8d06
to
947096b
Compare
Unit tests added, PTAL! |
nonceOpts := []musig2.NonceGenOption{ | ||
musig2.WithPublicKey(m.localKey.PubKey), | ||
} | ||
if opts.customRand != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should enforce the check to make sure nonce is not repeated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, how would we go about that? The customRand
func in this case will use the new shachain root to derive nonces, also we'll start to pass in the txhash being signed into the nonce gen to further bind it.
We only set the custom rand for our local commitment, which means we only sign with this nonce when we go to broadcast.
Here's the argument I posted elsewhere for why imo the current approach is sound:
- we only use that verification nonce to sign when we broadcast
- we only ever have a single transaction valid to broadcast
- after we sign and broadcast, we have that saved tx to rebroadcast, this tx never changes and we can't modify it (since we have another sig)
- leaking the nonce needs us to sign with that key w/ two diff messages, which itself would mean we're broadcasting a revoked state
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I meant was, we'd make sure the opts is always set for m.commitType == localCommit
, so maybe we can return an error if opts.customRand == nil && m.commitType == localCommit
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By design it's meant to be an optional value though, we maintain similar control flow, but then allow the caller to specify this. I think a better area to add additional protections would be the channel state machine itself (part 6 in this series) where this is used.
This would also break the current test that exercises the "normal" random nonce paths.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is close!
691ecd9
to
d22a0f9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is good to go on my end once the redundant MuSig2Cleanup
is handled.
nonceOpts := []musig2.NonceGenOption{ | ||
musig2.WithPublicKey(m.localKey.PubKey), | ||
} | ||
if opts.customRand != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I meant was, we'd make sure the opts is always set for m.commitType == localCommit
, so maybe we can return an error if opts.customRand == nil && m.commitType == localCommit
.
lnwallet/musig_session.go
Outdated
|
||
defer func() { | ||
err := m.signer.MuSig2Cleanup(m.session.SessionID) | ||
if err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think MuSig2CombineSig
will clean up the session so this will always return an error because the session is not found. Maybe we shouldn't do the auto cleanup in MuSig2CombineSig
, or mention it in the method name or docs since it's error-prone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yeah good point, removed since it isn't necessary.
Initially I wanted to try to clean up the session as soon as possible, but realized that you need the session state present in order to do combine (so you can't clean up, then try to combine later the state won't be found). What I think we should do is add a defer CleanUp()
in the link itself, so this way whenever we hang up the connection we remove the active session. We then also want to do this in the state machine after a round trip is complete.
I need to revisit the force close code in the final part of this PR, I think it ends up re-creating the session so it can properly force close.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM pending @yyforyongyu 's comment re the session clean up 🥕 ⚡
(some linter things remain that I assume will be addressed in a final clean up commit once all the others are also in)
In this commit, we extract the musig2 session management into a new module. This allows us to re-use the session logic elsewhere in unit tests so we don't need to instantiate the entire wallet.
In this commit, we update the set of intents and assemblers to recognize musig2. For this change, we use a new bool, `musig2`, then use that to determine if we need to use the new taproot funding scripts or not.
…tment state In this commit, we add a series of abstractions that'll allow us to easily do funding and also state updates for the new taproot channels. A partial session is defined by the knowledge of a verification nonce. Once the remote party sends a signature, we learn of their signing nonce, and can then complete a session. By using a JIT nonce approach, we ensure that the signer can generate their nonces randomly and also at the very last step to avoid having to maintain state. For our local nonces, we also have an option to use a counter based nonce derived from the shachain instead of fully random nonces. This allows us to not have to store ay additional state. Instead, when we need to go to broadcast, we can just regenerate the nonce then use that to broadcast.
In this commit, we eliminate some code duplication by removing the old `HashMutex` struct as it just duplicates all the code with a different type (uint64 and hash). We then make the main Mutex struct take a type param, so the key can be parametrized when the struct is instantiated.
By using the multimutex here, we'll no longer rely on a single mutex for the entire musig session set like we used to. Instead, we can use the session ID to key into a map of mutexes and use those directly.
d22a0f9
to
7c85f02
Compare
Really been fighting the linter on this one...should be ✅ now with the latest push. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really been fighting the linter on this one...
Attack on linter series𖠆
LGTM🎉🎉🎉
Change Description
Depends on #7333 and #7331.
Only the last 3 commits are new. We'll also want to synchronize with #6974 as both the PRs update the deps to use the latest version of musig2.
In this PR, we first do a small refactoring to extract the musig2 session logic into a new package + struct. This allows use to re-use it later in tests w/o creating the entire wallet system.
Building on this, we then do some small prep to update the
chanfunding
package to be ready for the newmusig2
channels.The final change in this PR adds a new struct to encapsulate the new musig2 session logic for channels. A session can be created as soon as the verification nonce for the local party is known. At any time, we'll have two sessions: one for the remote commitment and one for the local commitment. A session can be finalized once the signing nonce (sent by the remote party) is known. When generating a signature, we'll use the remote party's verification nonce (the remote session), then generate a fresh nonce to complete the session. Similarly, when accepting a new state, we'll use the remote party's signing nonce to finalize the session, then verify the incoming signature.
For our local session, we'll use a counter-based system to generate the nonces we send to the remote party. The underlying counter here is the commitment height, which is then used by the existing
shachain
producer to generate fresh, but deterministic randomness. This lets us not have to store the secret nonce to disk, instead we'll just re-generate the nonce and use the sig we have on disk to combine, then create the final witness to broadcast.The next PR in this series uses this PR, and its dependents to implement the funding logic within the wallet itself (reservations).
Steps to Test
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.