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

lightningnetwork / lnd / 12313002221

13 Dec 2024 09:25AM UTC coverage: 57.486% (+8.6%) from 48.92%
12313002221

push

github

web-flow
Merge pull request #9343 from ellemouton/contextGuard

fn: expand the ContextGuard and add tests

101902 of 177264 relevant lines covered (57.49%)

24909.26 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