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

lightningnetwork / lnd / 15561477203

10 Jun 2025 01:54PM UTC coverage: 58.351% (-10.1%) from 68.487%
15561477203

Pull #9356

github

web-flow
Merge 6440b25db into c6d6d4c0b
Pull Request #9356: lnrpc: add incoming/outgoing channel ids filter to forwarding history request

33 of 36 new or added lines in 2 files covered. (91.67%)

28366 existing lines in 455 files now uncovered.

97715 of 167461 relevant lines covered (58.35%)

1.81 hits per line

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

0.0
/channeldb/migration/lnwire21/signature.go
1
package lnwire
2

3
import (
4
        "fmt"
5

6
        "github.com/btcsuite/btcd/btcec/v2/ecdsa"
7
        "github.com/lightningnetwork/lnd/input"
8
)
9

10
// Sig is a fixed-sized ECDSA signature. Unlike Bitcoin, we use fixed sized
11
// signatures on the wire, instead of DER encoded signatures. This type
12
// provides several methods to convert to/from a regular Bitcoin DER encoded
13
// signature (raw bytes and *ecdsa.Signature).
14
type Sig [64]byte
15

16
// NewSigFromRawSignature returns a Sig from a Bitcoin raw signature encoded in
17
// the canonical DER encoding.
UNCOV
18
func NewSigFromRawSignature(sig []byte) (Sig, error) {
×
UNCOV
19
        var b Sig
×
UNCOV
20

×
UNCOV
21
        if len(sig) == 0 {
×
22
                return b, fmt.Errorf("cannot decode empty signature")
×
23
        }
×
24

25
        // Extract lengths of R and S. The DER representation is laid out as
26
        // 0x30 <length> 0x02 <length r> r 0x02 <length s> s
27
        // which means the length of R is the 4th byte and the length of S
28
        // is the second byte after R ends. 0x02 signifies a length-prefixed,
29
        // zero-padded, big-endian bigint. 0x30 signifies a DER signature.
30
        // See the Serialize() method for ecdsa.Signature for details.
UNCOV
31
        rLen := sig[3]
×
UNCOV
32
        sLen := sig[5+rLen]
×
UNCOV
33

×
UNCOV
34
        // Check to make sure R and S can both fit into their intended buffers.
×
UNCOV
35
        // We check S first because these code blocks decrement sLen and rLen
×
UNCOV
36
        // in the case of a 33-byte 0-padded integer returned from Serialize()
×
UNCOV
37
        // and rLen is used in calculating array indices for S. We can track
×
UNCOV
38
        // this with additional variables, but it's more efficient to just
×
UNCOV
39
        // check S first.
×
UNCOV
40
        if sLen > 32 {
×
41
                if (sLen > 33) || (sig[6+rLen] != 0x00) {
×
42
                        return b, fmt.Errorf("S is over 32 bytes long " +
×
43
                                "without padding")
×
44
                }
×
45
                sLen--
×
46
                copy(b[64-sLen:], sig[7+rLen:])
×
UNCOV
47
        } else {
×
UNCOV
48
                copy(b[64-sLen:], sig[6+rLen:])
×
UNCOV
49
        }
×
50

51
        // Do the same for R as we did for S
UNCOV
52
        if rLen > 32 {
×
UNCOV
53
                if (rLen > 33) || (sig[4] != 0x00) {
×
54
                        return b, fmt.Errorf("R is over 32 bytes long " +
×
55
                                "without padding")
×
56
                }
×
UNCOV
57
                rLen--
×
UNCOV
58
                copy(b[32-rLen:], sig[5:5+rLen])
×
59
        } else {
×
60
                copy(b[32-rLen:], sig[4:4+rLen])
×
61
        }
×
62

UNCOV
63
        return b, nil
×
64
}
65

66
// NewSigFromSignature creates a new signature as used on the wire, from an
67
// existing ecdsa.Signature.
UNCOV
68
func NewSigFromSignature(e input.Signature) (Sig, error) {
×
UNCOV
69
        if e == nil {
×
70
                return Sig{}, fmt.Errorf("cannot decode empty signature")
×
71
        }
×
72

73
        // Serialize the signature with all the checks that entails.
UNCOV
74
        return NewSigFromRawSignature(e.Serialize())
×
75
}
76

77
// ToSignature converts the fixed-sized signature to a ecdsa.Signature objects
78
// which can be used for signature validation checks.
79
func (b *Sig) ToSignature() (*ecdsa.Signature, error) {
×
80
        // Parse the signature with strict checks.
×
81
        sigBytes := b.ToSignatureBytes()
×
82
        sig, err := ecdsa.ParseDERSignature(sigBytes)
×
83
        if err != nil {
×
84
                return nil, err
×
85
        }
×
86

87
        return sig, nil
×
88
}
89

90
// ToSignatureBytes serializes the target fixed-sized signature into the raw
91
// bytes of a DER encoding.
92
func (b *Sig) ToSignatureBytes() []byte {
×
93
        // Extract canonically-padded bigint representations from buffer
×
94
        r := extractCanonicalPadding(b[0:32])
×
95
        s := extractCanonicalPadding(b[32:64])
×
96
        rLen := uint8(len(r))
×
97
        sLen := uint8(len(s))
×
98

×
99
        // Create a canonical serialized signature. DER format is:
×
100
        // 0x30 <length> 0x02 <length r> r 0x02 <length s> s
×
101
        sigBytes := make([]byte, 6+rLen+sLen)
×
102
        sigBytes[0] = 0x30            // DER signature magic value
×
103
        sigBytes[1] = 4 + rLen + sLen // Length of rest of signature
×
104
        sigBytes[2] = 0x02            // Big integer magic value
×
105
        sigBytes[3] = rLen            // Length of R
×
106
        sigBytes[rLen+4] = 0x02       // Big integer magic value
×
107
        sigBytes[rLen+5] = sLen       // Length of S
×
108
        copy(sigBytes[4:], r)         // Copy R
×
109
        copy(sigBytes[rLen+6:], s)    // Copy S
×
110

×
111
        return sigBytes
×
112
}
×
113

114
// extractCanonicalPadding is a utility function to extract the canonical
115
// padding of a big-endian integer from the wire encoding (a 0-padded
116
// big-endian integer) such that it passes btcec.canonicalPadding test.
117
func extractCanonicalPadding(b []byte) []byte {
×
118
        for i := 0; i < len(b); i++ {
×
119
                // Found first non-zero byte.
×
120
                if b[i] > 0 {
×
121
                        // If the MSB is set, we need zero padding.
×
122
                        if b[i]&0x80 == 0x80 {
×
123
                                return append([]byte{0x00}, b[i:]...)
×
124
                        }
×
125
                        return b[i:]
×
126
                }
127
        }
128
        return []byte{0x00}
×
129
}
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