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

lightningnetwork / lnd / 13586005509

28 Feb 2025 10:14AM UTC coverage: 68.629% (+9.9%) from 58.77%
13586005509

Pull #9521

github

web-flow
Merge 37d3a70a5 into 8532955b3
Pull Request #9521: unit: remove GOACC, use Go 1.20 native coverage functionality

129950 of 189351 relevant lines covered (68.63%)

23726.46 hits per line

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

89.24
/lnwire/signature.go
1
package lnwire
2

3
import (
4
        "errors"
5
        "fmt"
6

7
        "github.com/btcsuite/btcd/btcec/v2/ecdsa"
8
        "github.com/btcsuite/btcd/btcec/v2/schnorr"
9
        "github.com/lightningnetwork/lnd/input"
10
        "github.com/lightningnetwork/lnd/tlv"
11
)
12

13
var (
14
        errSigTooShort = errors.New("malformed signature: too short")
15
        errBadLength   = errors.New("malformed signature: bad length")
16
        errBadRLength  = errors.New("malformed signature: bogus R length")
17
        errBadSLength  = errors.New("malformed signature: bogus S length")
18
        errRTooLong    = errors.New("R is over 32 bytes long without padding")
19
        errSTooLong    = errors.New("S is over 32 bytes long without padding")
20
)
21

22
// sigType represents the type of signature that is carried within the Sig.
23
// Today this can either be an ECDSA sig or a schnorr sig. Both of these can
24
// fit cleanly into 64 bytes.
25
type sigType uint
26

27
const (
28
        // sigTypeECDSA represents an ECDSA signature.
29
        sigTypeECDSA sigType = iota
30

31
        // sigTypeSchnorr represents a schnorr signature.
32
        sigTypeSchnorr
33
)
34

35
// Sig is a fixed-sized ECDSA signature or 64-byte schnorr signature. For the
36
// ECDSA sig, unlike Bitcoin, we use fixed sized signatures on the wire,
37
// instead of DER encoded signatures. This type provides several methods to
38
// convert to/from a regular Bitcoin DER encoded signature (raw bytes and
39
// *ecdsa.Signature).
40
type Sig struct {
41
        bytes [64]byte
42

43
        sigType sigType
44
}
45

46
// ForceSchnorr forces the signature to be interpreted as a schnorr signature.
47
// This is useful when reading an HTLC sig off the wire for a taproot channel.
48
// In this case, in order to obtain an input.Signature, we need to know that
49
// the sig is a schnorr sig.
50
func (s *Sig) ForceSchnorr() {
526✔
51
        s.sigType = sigTypeSchnorr
526✔
52
}
526✔
53

54
// RawBytes returns the raw bytes of signature.
55
func (s *Sig) RawBytes() []byte {
2,105✔
56
        return s.bytes[:]
2,105✔
57
}
2,105✔
58

59
// Copy copies the signature into a new Sig instance.
60
func (s *Sig) Copy() Sig {
1✔
61
        var sCopy Sig
1✔
62
        copy(sCopy.bytes[:], s.bytes[:])
1✔
63
        sCopy.sigType = s.sigType
1✔
64

1✔
65
        return sCopy
1✔
66
}
1✔
67

68
// Record returns a Record that can be used to encode or decode the backing
69
// object.
70
//
71
// This returns a record that serializes the sig as a 64-byte fixed size
72
// signature.
73
func (s *Sig) Record() tlv.Record {
1,284✔
74
        // We set a type here as zero as it isn't needed when used as a
1,284✔
75
        // RecordT.
1,284✔
76
        return tlv.MakePrimitiveRecord(0, &s.bytes)
1,284✔
77
}
1,284✔
78

79
// NewSigFromWireECDSA returns a Sig instance based on an ECDSA signature
80
// that's already in the 64-byte format we expect.
81
func NewSigFromWireECDSA(sig []byte) (Sig, error) {
554✔
82
        if len(sig) != 64 {
554✔
83
                return Sig{}, fmt.Errorf("%w: %v bytes", errSigTooShort,
×
84
                        len(sig))
×
85
        }
×
86

87
        var s Sig
554✔
88
        copy(s.bytes[:], sig)
554✔
89

554✔
90
        return s, nil
554✔
91
}
92

93
// NewSigFromECDSARawSignature returns a Sig from a Bitcoin raw signature
94
// encoded in the canonical DER encoding.
95
func NewSigFromECDSARawSignature(sig []byte) (Sig, error) {
32,927✔
96
        var b [64]byte
32,927✔
97

32,927✔
98
        // Check the total length is above the minimal.
32,927✔
99
        if len(sig) < ecdsa.MinSigLen {
32,929✔
100
                return Sig{}, errSigTooShort
2✔
101
        }
2✔
102

103
        // The DER representation is laid out as:
104
        //   0x30 <length> 0x02 <length r> r 0x02 <length s> s
105
        // which means the length of R is the 4th byte and the length of S is
106
        // the second byte after R ends. 0x02 signifies a length-prefixed,
107
        // zero-padded, big-endian bigint. 0x30 signifies a DER signature.
108
        // See the Serialize() method for ecdsa.Signature for details.
109

110
        // Reading <length>, remaining: [0x02 <length r> r 0x02 <length s> s]
111
        sigLen := int(sig[1])
32,925✔
112

32,925✔
113
        // siglen should be less than the entire message and greater than
32,925✔
114
        // the minimal message size.
32,925✔
115
        if sigLen+2 > len(sig) || sigLen+2 < ecdsa.MinSigLen {
32,928✔
116
                return Sig{}, errBadLength
3✔
117
        }
3✔
118

119
        // Reading <length r>, remaining: [r 0x02 <length s> s]
120
        rLen := int(sig[3])
32,922✔
121

32,922✔
122
        // rLen must be positive and must be able to fit in other elements.
32,922✔
123
        // Assuming s is one byte, then we have 0x30, <length>, 0x20,
32,922✔
124
        // <length r>, 0x20, <length s>, s, a total of 7 bytes.
32,922✔
125
        if rLen <= 0 || rLen+7 > len(sig) {
32,925✔
126
                return Sig{}, errBadRLength
3✔
127
        }
3✔
128

129
        // Reading <length s>, remaining: [s]
130
        sLen := int(sig[5+rLen])
32,919✔
131

32,919✔
132
        // S should be the rest of the string.
32,919✔
133
        // sLen must be positive and must be able to fit in other elements.
32,919✔
134
        // We know r is rLen bytes, and we have 0x30, <length>, 0x20,
32,919✔
135
        // <length r>, 0x20, <length s>, a total of rLen+6 bytes.
32,919✔
136
        if sLen <= 0 || sLen+rLen+6 > len(sig) {
32,922✔
137
                return Sig{}, errBadSLength
3✔
138
        }
3✔
139

140
        // Check to make sure R and S can both fit into their intended buffers.
141
        // We check S first because these code blocks decrement sLen and rLen
142
        // in the case of a 33-byte 0-padded integer returned from Serialize()
143
        // and rLen is used in calculating array indices for S. We can track
144
        // this with additional variables, but it's more efficient to just
145
        // check S first.
146
        if sLen > 32 {
32,921✔
147
                if (sLen > 33) || (sig[6+rLen] != 0x00) {
7✔
148
                        return Sig{}, errSTooLong
2✔
149
                }
2✔
150
                sLen--
3✔
151
                copy(b[64-sLen:], sig[7+rLen:])
3✔
152
        } else {
32,911✔
153
                copy(b[64-sLen:], sig[6+rLen:])
32,911✔
154
        }
32,911✔
155

156
        // Do the same for R as we did for S
157
        if rLen > 32 {
61,755✔
158
                if (rLen > 33) || (sig[4] != 0x00) {
28,843✔
159
                        return Sig{}, errRTooLong
2✔
160
                }
2✔
161
                rLen--
28,839✔
162
                copy(b[32-rLen:], sig[5:5+rLen])
28,839✔
163
        } else {
4,076✔
164
                copy(b[32-rLen:], sig[4:4+rLen])
4,076✔
165
        }
4,076✔
166

167
        return Sig{
32,912✔
168
                bytes:   b,
32,912✔
169
                sigType: sigTypeECDSA,
32,912✔
170
        }, nil
32,912✔
171
}
172

173
// NewSigFromSchnorrRawSignature converts a raw schnorr signature into an
174
// lnwire.Sig.
175
func NewSigFromSchnorrRawSignature(sig []byte) (Sig, error) {
1,464✔
176
        var s Sig
1,464✔
177
        copy(s.bytes[:], sig)
1,464✔
178
        s.sigType = sigTypeSchnorr
1,464✔
179

1,464✔
180
        return s, nil
1,464✔
181
}
1,464✔
182

183
// NewSigFromSignature creates a new signature as used on the wire, from an
184
// existing ecdsa.Signature or schnorr.Signature.
185
func NewSigFromSignature(e input.Signature) (Sig, error) {
32,525✔
186
        if e == nil {
32,526✔
187
                return Sig{}, fmt.Errorf("cannot decode empty signature")
1✔
188
        }
1✔
189

190
        // Nil is still a valid interface, apparently. So we need a more
191
        // explicit check here.
192
        if ecsig, ok := e.(*ecdsa.Signature); ok && ecsig == nil {
32,525✔
193
                return Sig{}, fmt.Errorf("cannot decode empty signature")
1✔
194
        }
1✔
195

196
        switch ecSig := e.(type) {
32,523✔
197
        // If this is a schnorr signature, then we can just pack it as normal,
198
        // since the default encoding is already 64 bytes.
199
        case *schnorr.Signature:
81✔
200
                return NewSigFromSchnorrRawSignature(e.Serialize())
81✔
201

202
        // For ECDSA signatures, we'll need to do a bit more work to map the
203
        // signature into a compact 64 byte form.
204
        case *ecdsa.Signature:
32,445✔
205
                // Serialize the signature with all the checks that entails.
32,445✔
206
                return NewSigFromECDSARawSignature(e.Serialize())
32,445✔
207

208
        default:
×
209
                return Sig{}, fmt.Errorf("unknown wire sig type: %T", ecSig)
×
210
        }
211
}
212

213
// ToSignature converts the fixed-sized signature to a input.Signature which
214
// can be used for signature validation checks.
215
func (s *Sig) ToSignature() (input.Signature, error) {
7,197✔
216
        switch s.sigType {
7,197✔
217
        case sigTypeSchnorr:
80✔
218
                return schnorr.ParseSignature(s.bytes[:])
80✔
219

220
        case sigTypeECDSA:
7,120✔
221
                // Parse the signature with strict checks.
7,120✔
222
                sigBytes := s.ToSignatureBytes()
7,120✔
223
                sig, err := ecdsa.ParseDERSignature(sigBytes)
7,120✔
224
                if err != nil {
7,137✔
225
                        return nil, err
17✔
226
                }
17✔
227

228
                return sig, nil
7,103✔
229

230
        default:
×
231
                return nil, fmt.Errorf("unknown sig type: %v", s.sigType)
×
232
        }
233
}
234

235
// ToSignatureBytes serializes the target fixed-sized signature into the
236
// encoding of the primary domain for the signature. For ECDSA signatures, this
237
// is the raw bytes of a DER encoding.
238
func (s *Sig) ToSignatureBytes() []byte {
10,209✔
239
        switch s.sigType {
10,209✔
240
        // For ECDSA signatures, we'll convert to DER encoding.
241
        case sigTypeECDSA:
10,209✔
242
                // Extract canonically-padded bigint representations from buffer
10,209✔
243
                r := extractCanonicalPadding(s.bytes[0:32])
10,209✔
244
                s := extractCanonicalPadding(s.bytes[32:64])
10,209✔
245
                rLen := uint8(len(r))
10,209✔
246
                sLen := uint8(len(s))
10,209✔
247

10,209✔
248
                // Create a canonical serialized signature. DER format is:
10,209✔
249
                // 0x30 <length> 0x02 <length r> r 0x02 <length s> s
10,209✔
250
                sigBytes := make([]byte, 6+rLen+sLen)
10,209✔
251
                sigBytes[0] = 0x30            // DER signature magic value
10,209✔
252
                sigBytes[1] = 4 + rLen + sLen // Length of rest of signature
10,209✔
253
                sigBytes[2] = 0x02            // Big integer magic value
10,209✔
254
                sigBytes[3] = rLen            // Length of R
10,209✔
255
                sigBytes[rLen+4] = 0x02       // Big integer magic value
10,209✔
256
                sigBytes[rLen+5] = sLen       // Length of S
10,209✔
257
                copy(sigBytes[4:], r)         // Copy R
10,209✔
258
                copy(sigBytes[rLen+6:], s)    // Copy S
10,209✔
259

10,209✔
260
                return sigBytes
10,209✔
261

262
        // For schnorr signatures, we can use the same internal 64 bytes.
263
        case sigTypeSchnorr:
×
264
                // We'll make a copy of the signature so we don't return a
×
265
                // reference into the raw slice.
×
266
                var sig [64]byte
×
267
                copy(sig[:], s.bytes[:])
×
268
                return sig[:]
×
269

270
        default:
×
271
                // TODO(roasbeef): can only be called via public methods so
×
272
                // never reachable?
×
273
                panic("sig type not set")
×
274
        }
275
}
276

277
// extractCanonicalPadding is a utility function to extract the canonical
278
// padding of a big-endian integer from the wire encoding (a 0-padded
279
// big-endian integer) such that it passes btcec.canonicalPadding test.
280
func extractCanonicalPadding(b []byte) []byte {
20,415✔
281
        for i := 0; i < len(b); i++ {
43,021✔
282
                // Found first non-zero byte.
22,606✔
283
                if b[i] > 0 {
42,992✔
284
                        // If the MSB is set, we need zero padding.
20,386✔
285
                        if b[i]&0x80 == 0x80 {
25,486✔
286
                                return append([]byte{0x00}, b[i:]...)
5,100✔
287
                        }
5,100✔
288
                        return b[i:]
15,289✔
289
                }
290
        }
291
        return []byte{0x00}
29✔
292
}
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