• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 12583319996

02 Jan 2025 01:38PM UTC coverage: 57.522% (-1.1%) from 58.598%
12583319996

Pull #9361

github

starius
fn/ContextGuard: use context.AfterFunc to wait

Simplifies context cancellation handling by using context.AfterFunc instead of a
goroutine to wait for context cancellation. This approach avoids the overhead of
a goroutine during the waiting period.

For ctxQuitUnsafe, since g.quit is closed only in the Quit method (which also
cancels all associated contexts), waiting on context cancellation ensures the
same behavior without unnecessary dependency on g.quit.

Added a test to ensure that the Create method does not launch any goroutines.
Pull Request #9361: fn: optimize context guard

102587 of 178344 relevant lines covered (57.52%)

24734.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

6.58
/peer/musig_chan_closer.go
1
package peer
2

3
import (
4
        "fmt"
5

6
        "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
7
        "github.com/lightningnetwork/lnd/fn/v2"
8
        "github.com/lightningnetwork/lnd/input"
9
        "github.com/lightningnetwork/lnd/lnwallet"
10
        "github.com/lightningnetwork/lnd/lnwallet/chancloser"
11
        "github.com/lightningnetwork/lnd/lnwire"
12
)
13

14
// MusigChanCloser is an adapter over the normal channel state machine that
15
// allows the chan closer to handle the musig2 details of closing taproot
16
// channels.
17
type MusigChanCloser struct {
18
        channel *lnwallet.LightningChannel
19

20
        musigSession *lnwallet.MusigSession
21

22
        localNonce  *musig2.Nonces
23
        remoteNonce *musig2.Nonces
24
}
25

26
// NewMusigChanCloser creates a new musig chan closer from a normal channel.
27
func NewMusigChanCloser(channel *lnwallet.LightningChannel) *MusigChanCloser {
9✔
28
        return &MusigChanCloser{
9✔
29
                channel: channel,
9✔
30
        }
9✔
31
}
9✔
32

33
// ProposalClosingOpts returns the options that should be used when
34
// generating a new co-op close signature.
35
func (m *MusigChanCloser) ProposalClosingOpts() (
36
        []lnwallet.ChanCloseOpt, error) {
×
37

×
38
        switch {
×
39
        case m.localNonce == nil:
×
40
                return nil, fmt.Errorf("local nonce not generated")
×
41

42
        case m.remoteNonce == nil:
×
43
                return nil, fmt.Errorf("remote nonce not generated")
×
44
        }
45

46
        localKey, remoteKey := m.channel.MultiSigKeys()
×
47

×
48
        tapscriptTweak := fn.MapOption(lnwallet.TapscriptRootToTweak)(
×
49
                m.channel.State().TapscriptRoot,
×
50
        )
×
51

×
52
        m.musigSession = lnwallet.NewPartialMusigSession(
×
53
                *m.remoteNonce, localKey, remoteKey,
×
54
                m.channel.Signer, m.channel.FundingTxOut(),
×
55
                lnwallet.RemoteMusigCommit, tapscriptTweak,
×
56
        )
×
57

×
58
        err := m.musigSession.FinalizeSession(*m.localNonce)
×
59
        if err != nil {
×
60
                return nil, err
×
61
        }
×
62

63
        return []lnwallet.ChanCloseOpt{
×
64
                lnwallet.WithCoopCloseMusigSession(m.musigSession),
×
65
        }, nil
×
66
}
67

68
// CombineClosingOpts returns the options that should be used when combining
69
// the final musig partial signature. The method also maps the lnwire partial
70
// signatures into an input.Signature that can be used more generally.
71
func (m *MusigChanCloser) CombineClosingOpts(localSig,
72
        remoteSig lnwire.PartialSig) (input.Signature, input.Signature,
73
        []lnwallet.ChanCloseOpt, error) {
×
74

×
75
        if m.musigSession == nil {
×
76
                return nil, nil, nil, fmt.Errorf("musig session not created")
×
77
        }
×
78

79
        // We'll convert the wire partial signatures into an input.Signature
80
        // compliant struct so we can pass it into the final combination
81
        // function.
82
        localPartialSig := &lnwire.PartialSigWithNonce{
×
83
                PartialSig: localSig,
×
84
                Nonce:      m.localNonce.PubNonce,
×
85
        }
×
86
        remotePartialSig := &lnwire.PartialSigWithNonce{
×
87
                PartialSig: remoteSig,
×
88
                Nonce:      m.remoteNonce.PubNonce,
×
89
        }
×
90

×
91
        localMuSig := new(lnwallet.MusigPartialSig).FromWireSig(
×
92
                localPartialSig,
×
93
        )
×
94
        remoteMuSig := new(lnwallet.MusigPartialSig).FromWireSig(
×
95
                remotePartialSig,
×
96
        )
×
97

×
98
        opts := []lnwallet.ChanCloseOpt{
×
99
                lnwallet.WithCoopCloseMusigSession(m.musigSession),
×
100
        }
×
101

×
102
        // For taproot channels, we'll need to pass along the session so the
×
103
        // final combined signature can be created.
×
104
        return localMuSig, remoteMuSig, opts, nil
×
105
}
106

107
// ClosingNonce returns the nonce that should be used when generating the our
108
// partial signature for the remote party.
109
func (m *MusigChanCloser) ClosingNonce() (*musig2.Nonces, error) {
×
110
        if m.localNonce != nil {
×
111
                return m.localNonce, nil
×
112
        }
×
113

114
        localKey, _ := m.channel.MultiSigKeys()
×
115
        nonce, err := musig2.GenNonces(
×
116
                musig2.WithPublicKey(localKey.PubKey),
×
117
        )
×
118
        if err != nil {
×
119
                return nil, err
×
120
        }
×
121

122
        m.localNonce = nonce
×
123

×
124
        return nonce, nil
×
125
}
126

127
// InitRemoteNonce saves the remote nonce the party sent during their shutdown
128
// message so it can be used later to generate and verify signatures.
129
func (m *MusigChanCloser) InitRemoteNonce(nonce *musig2.Nonces) {
×
130
        m.remoteNonce = nonce
×
131
}
×
132

133
// A compile-time assertion to ensure MusigChanCloser implements the
134
// chancloser.MusigSession interface.
135
var _ chancloser.MusigSession = (*MusigChanCloser)(nil)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc