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

lightningnetwork / lnd / 15736109134

18 Jun 2025 02:46PM UTC coverage: 58.197% (-10.1%) from 68.248%
15736109134

Pull #9752

github

web-flow
Merge d2634a68c into 31c74f20f
Pull Request #9752: routerrpc: reject payment to invoice that don't have payment secret or blinded paths

6 of 13 new or added lines in 2 files covered. (46.15%)

28331 existing lines in 455 files now uncovered.

97860 of 168153 relevant lines covered (58.2%)

1.81 hits per line

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

70.89
/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() {
3✔
51
        s.sigType = sigTypeSchnorr
3✔
52
}
3✔
53

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

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

×
UNCOV
65
        return sCopy
×
UNCOV
66
}
×
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 {
3✔
74
        // We set a type here as zero as it isn't needed when used as a
3✔
75
        // RecordT.
3✔
76
        return tlv.MakePrimitiveRecord(0, &s.bytes)
3✔
77
}
3✔
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) {
3✔
82
        if len(sig) != 64 {
3✔
83
                return Sig{}, fmt.Errorf("%w: %v bytes", errSigTooShort,
×
84
                        len(sig))
×
85
        }
×
86

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

3✔
90
        return s, nil
3✔
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) {
3✔
96
        var b [64]byte
3✔
97

3✔
98
        // Check the total length is above the minimal.
3✔
99
        if len(sig) < ecdsa.MinSigLen {
3✔
UNCOV
100
                return Sig{}, errSigTooShort
×
UNCOV
101
        }
×
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])
3✔
112

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

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

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

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

3✔
132
        // S should be the rest of the string.
3✔
133
        // sLen must be positive and must be able to fit in other elements.
3✔
134
        // We know r is rLen bytes, and we have 0x30, <length>, 0x20,
3✔
135
        // <length r>, 0x20, <length s>, a total of rLen+6 bytes.
3✔
136
        if sLen <= 0 || sLen+rLen+6 > len(sig) {
3✔
UNCOV
137
                return Sig{}, errBadSLength
×
UNCOV
138
        }
×
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 {
3✔
UNCOV
147
                if (sLen > 33) || (sig[6+rLen] != 0x00) {
×
UNCOV
148
                        return Sig{}, errSTooLong
×
UNCOV
149
                }
×
UNCOV
150
                sLen--
×
UNCOV
151
                copy(b[64-sLen:], sig[7+rLen:])
×
152
        } else {
3✔
153
                copy(b[64-sLen:], sig[6+rLen:])
3✔
154
        }
3✔
155

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

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

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

3✔
180
        return s, nil
3✔
181
}
3✔
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) {
3✔
186
        if e == nil {
3✔
UNCOV
187
                return Sig{}, fmt.Errorf("cannot decode empty signature")
×
UNCOV
188
        }
×
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 {
3✔
UNCOV
193
                return Sig{}, fmt.Errorf("cannot decode empty signature")
×
UNCOV
194
        }
×
195

196
        switch ecSig := e.(type) {
3✔
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:
3✔
200
                return NewSigFromSchnorrRawSignature(e.Serialize())
3✔
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:
3✔
205
                // Serialize the signature with all the checks that entails.
3✔
206
                return NewSigFromECDSARawSignature(e.Serialize())
3✔
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) {
3✔
216
        switch s.sigType {
3✔
217
        case sigTypeSchnorr:
3✔
218
                return schnorr.ParseSignature(s.bytes[:])
3✔
219

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

228
                return sig, nil
3✔
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 {
3✔
239
        switch s.sigType {
3✔
240
        // For ECDSA signatures, we'll convert to DER encoding.
241
        case sigTypeECDSA:
3✔
242
                // Extract canonically-padded bigint representations from buffer
3✔
243
                r := extractCanonicalPadding(s.bytes[0:32])
3✔
244
                s := extractCanonicalPadding(s.bytes[32:64])
3✔
245
                rLen := uint8(len(r))
3✔
246
                sLen := uint8(len(s))
3✔
247

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

3✔
260
                return sigBytes
3✔
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 {
3✔
281
        for i := 0; i < len(b); i++ {
6✔
282
                // Found first non-zero byte.
3✔
283
                if b[i] > 0 {
6✔
284
                        // If the MSB is set, we need zero padding.
3✔
285
                        if b[i]&0x80 == 0x80 {
6✔
286
                                return append([]byte{0x00}, b[i:]...)
3✔
287
                        }
3✔
288
                        return b[i:]
3✔
289
                }
290
        }
UNCOV
291
        return []byte{0x00}
×
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