[4/?] - input+lnwallet: prepare input package for funding logic, add new MusigSession abstraction #7340
Conversation
ellemouton
left a comment
There was a problem hiding this comment.
First pass looks good! In my next pass I will spend more time understanding the details of the last commit
There was a problem hiding this comment.
Gotta stamp something in the formatting guide here...
Crypt-iQ
left a comment
There was a problem hiding this comment.
Pretty straightforward, will have to see how it fits in with the other changes
73baf9c to
8b3a3d6
Compare
yyforyongyu
left a comment
There was a problem hiding this comment.
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.
I think we should enforce the check to make sure nonce is not repeated?
There was a problem hiding this comment.
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.
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.
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.
ellemouton
left a comment
There was a problem hiding this comment.
I think this is close!
691ecd9 to
d22a0f9
Compare
yyforyongyu
left a comment
There was a problem hiding this comment.
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.
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.
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.
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.
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. |
yyforyongyu
left a comment
There was a problem hiding this comment.
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
chanfundingpackage to be ready for the newmusig2channels.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
shachainproducer 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.