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

lightningnetwork / lnd / 13408822928

19 Feb 2025 08:59AM UTC coverage: 41.123% (-17.7%) from 58.794%
13408822928

Pull #9521

github

web-flow
Merge d2f397b3c into 0e8786348
Pull Request #9521: unit: remove GOACC, use Go 1.20 native coverage functionality

92496 of 224923 relevant lines covered (41.12%)

18825.83 hits per line

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

16.03
/watchtower/blob/commitments.go
1
package blob
2

3
import (
4
        "fmt"
5

6
        "github.com/btcsuite/btcd/wire"
7
        "github.com/lightningnetwork/lnd/input"
8
        "github.com/lightningnetwork/lnd/lntypes"
9
        "github.com/lightningnetwork/lnd/lnwallet"
10
        "github.com/lightningnetwork/lnd/lnwire"
11
)
12

13
// CommitmentType characterises the various properties of the breach commitment
14
// transaction.
15
type CommitmentType uint8
16

17
const (
18
        // LegacyCommitment represents a legacy commitment transaction where
19
        // anchor outputs are not yet used and so the to_remote output is just
20
        // a regular but tweaked P2WKH.
21
        LegacyCommitment CommitmentType = iota
22

23
        // LegacyTweaklessCommitment is similar to the LegacyCommitment with the
24
        // added detail of the to_remote output not being tweaked.
25
        LegacyTweaklessCommitment
26

27
        // AnchorCommitment represents the commitment transaction of an
28
        // anchor channel. The key differences are that the to_remote is
29
        // encumbered by a 1 block CSV and so is thus a P2WSH output.
30
        AnchorCommitment
31

32
        // TaprootCommitment represents the commitment transaction of a simple
33
        // taproot channel.
34
        TaprootCommitment
35
)
36

37
// ToLocalInput constructs the input that will be used to spend the to_local
38
// output.
39
func (c CommitmentType) ToLocalInput(info *lnwallet.BreachRetribution) (
40
        input.Input, error) {
×
41

×
42
        witnessType, err := c.ToLocalWitnessType()
×
43
        if err != nil {
×
44
                return nil, err
×
45
        }
×
46

47
        return input.NewBaseInput(
×
48
                &info.RemoteOutpoint, witnessType, info.RemoteOutputSignDesc, 0,
×
49
        ), nil
×
50
}
51

52
// ToRemoteInput constructs the input that will be used to spend the to_remote
53
// output.
54
func (c CommitmentType) ToRemoteInput(info *lnwallet.BreachRetribution) (
55
        input.Input, error) {
×
56

×
57
        witnessType, err := c.ToRemoteWitnessType()
×
58
        if err != nil {
×
59
                return nil, err
×
60
        }
×
61

62
        switch c {
×
63
        case LegacyCommitment, LegacyTweaklessCommitment:
×
64
                return input.NewBaseInput(
×
65
                        &info.LocalOutpoint, witnessType,
×
66
                        info.LocalOutputSignDesc, 0,
×
67
                ), nil
×
68

69
        case AnchorCommitment, TaprootCommitment:
×
70
                // Anchor and Taproot channels have a CSV-encumbered to-remote
×
71
                // output. We'll construct a CSV input and assign the proper CSV
×
72
                // delay of 1.
×
73
                return input.NewCsvInput(
×
74
                        &info.LocalOutpoint, witnessType,
×
75
                        info.LocalOutputSignDesc, 0, 1,
×
76
                ), nil
×
77

78
        default:
×
79
                return nil, fmt.Errorf("unknown commitment type: %v", c)
×
80
        }
81
}
82

83
// ToLocalWitnessType is the input type of the to_local output.
84
func (c CommitmentType) ToLocalWitnessType() (input.WitnessType, error) {
×
85
        switch c {
×
86
        case LegacyTweaklessCommitment, LegacyCommitment, AnchorCommitment:
×
87
                return input.CommitmentRevoke, nil
×
88

89
        case TaprootCommitment:
×
90
                return input.TaprootCommitmentRevoke, nil
×
91

92
        default:
×
93
                return nil, fmt.Errorf("unknown commitment type: %v", c)
×
94
        }
95
}
96

97
// ToRemoteWitnessType is the input type of the to_remote output.
98
func (c CommitmentType) ToRemoteWitnessType() (input.WitnessType, error) {
×
99
        switch c {
×
100
        case LegacyTweaklessCommitment:
×
101
                return input.CommitSpendNoDelayTweakless, nil
×
102

103
        case LegacyCommitment:
×
104
                return input.CommitmentNoDelay, nil
×
105

106
        case AnchorCommitment:
×
107
                return input.CommitmentToRemoteConfirmed, nil
×
108

109
        case TaprootCommitment:
×
110
                return input.TaprootRemoteCommitSpend, nil
×
111

112
        default:
×
113
                return nil, fmt.Errorf("unknown commitment type: %v", c)
×
114
        }
115
}
116

117
// ToRemoteWitnessSize is the size of the witness that will be required to spend
118
// the to_remote output.
119
func (c CommitmentType) ToRemoteWitnessSize() (lntypes.WeightUnit, error) {
×
120
        switch c {
×
121
        // Legacy channels (both tweaked and non-tweaked) spend from P2WKH
122
        // output.
123
        case LegacyTweaklessCommitment, LegacyCommitment:
×
124
                return input.P2WKHWitnessSize, nil
×
125

126
        // Anchor channels spend a to-remote confirmed P2WSH output.
127
        case AnchorCommitment:
×
128
                return input.ToRemoteConfirmedWitnessSize, nil
×
129

130
        // Taproot channels spend a confirmed P2SH output.
131
        case TaprootCommitment:
×
132
                return input.TaprootToRemoteWitnessSize, nil
×
133

134
        default:
×
135
                return 0, fmt.Errorf("unknown commitment type: %v", c)
×
136
        }
137
}
138

139
// ToLocalWitnessSize is the size of the witness that will be required to spend
140
// the to_local output.
141
func (c CommitmentType) ToLocalWitnessSize() (lntypes.WeightUnit, error) {
×
142
        switch c {
×
143
        // An older ToLocalPenaltyWitnessSize constant used to underestimate the
144
        // size by one byte. The difference in weight can cause different output
145
        // values on the sweep transaction, so we mimic the original bug and
146
        // create signatures using the original weight estimate.
147
        case LegacyTweaklessCommitment, LegacyCommitment:
×
148
                return input.ToLocalPenaltyWitnessSize - 1, nil
×
149

150
        case AnchorCommitment:
×
151
                return input.ToLocalPenaltyWitnessSize, nil
×
152

153
        case TaprootCommitment:
×
154
                return input.TaprootToLocalRevokeWitnessSize, nil
×
155

156
        default:
×
157
                return 0, fmt.Errorf("unknown commitment type: %v", c)
×
158
        }
159
}
160

161
// ParseRawSig parses a wire.TxWitness and creates an lnwire.Sig.
162
func (c CommitmentType) ParseRawSig(witness wire.TxWitness) (lnwire.Sig,
163
        error) {
×
164

×
165
        // Check that the witness has at least one item since this is required
×
166
        // for all commitment types to follow.
×
167
        if len(witness) < 1 {
×
168
                return lnwire.Sig{}, fmt.Errorf("the witness should have at " +
×
169
                        "least one element")
×
170
        }
×
171

172
        // Check that the first witness element is non-nil. This is to ensure
173
        // that the witness length checks below do not panic.
174
        if witness[0] == nil {
×
175
                return lnwire.Sig{}, fmt.Errorf("the first witness element " +
×
176
                        "should not be nil")
×
177
        }
×
178

179
        switch c {
×
180
        case LegacyCommitment, LegacyTweaklessCommitment, AnchorCommitment:
×
181
                // Parse the DER-encoded signature from the first position of
×
182
                // the resulting witness. We trim an extra byte to remove the
×
183
                // sighash flag.
×
184
                rawSignature := witness[0][:len(witness[0])-1]
×
185

×
186
                // Re-encode the DER signature into a fixed-size 64 byte
×
187
                // signature.
×
188
                return lnwire.NewSigFromECDSARawSignature(rawSignature)
×
189

190
        case TaprootCommitment:
×
191
                rawSignature := witness[0]
×
192
                if len(rawSignature) > 64 {
×
193
                        rawSignature = witness[0][:len(witness[0])-1]
×
194
                }
×
195

196
                // Re-encode the schnorr signature into a fixed-size 64 byte
197
                // signature.
198
                return lnwire.NewSigFromSchnorrRawSignature(rawSignature)
×
199

200
        default:
×
201
                return lnwire.Sig{}, fmt.Errorf("unknown commitment type: %v",
×
202
                        c)
×
203
        }
204
}
205

206
// NewJusticeKit can be used to construct a new JusticeKit depending on the
207
// CommitmentType.
208
func (c CommitmentType) NewJusticeKit(sweepScript []byte,
209
        breachInfo *lnwallet.BreachRetribution, withToRemote bool) (JusticeKit,
210
        error) {
14✔
211

14✔
212
        switch c {
14✔
213
        case LegacyCommitment, LegacyTweaklessCommitment:
8✔
214
                return newLegacyJusticeKit(
8✔
215
                        sweepScript, breachInfo, withToRemote,
8✔
216
                ), nil
8✔
217

218
        case AnchorCommitment:
2✔
219
                return newAnchorJusticeKit(
2✔
220
                        sweepScript, breachInfo, withToRemote,
2✔
221
                ), nil
2✔
222

223
        case TaprootCommitment:
4✔
224
                return newTaprootJusticeKit(
4✔
225
                        sweepScript, breachInfo, withToRemote,
4✔
226
                )
4✔
227

228
        default:
×
229
                return nil, fmt.Errorf("unknown commitment type: %v", c)
×
230
        }
231
}
232

233
// EmptyJusticeKit returns the appropriate empty justice kit for the given
234
// CommitmentType.
235
func (c CommitmentType) EmptyJusticeKit() (JusticeKit, error) {
6✔
236
        switch c {
6✔
237
        case LegacyTweaklessCommitment, LegacyCommitment:
4✔
238
                return &legacyJusticeKit{}, nil
4✔
239

240
        case AnchorCommitment:
×
241
                return &anchorJusticeKit{
×
242
                        legacyJusticeKit: legacyJusticeKit{},
×
243
                }, nil
×
244

245
        case TaprootCommitment:
2✔
246
                return &taprootJusticeKit{}, nil
2✔
247

248
        default:
×
249
                return nil, fmt.Errorf("unknown commitment type: %v", c)
×
250
        }
251
}
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