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

lightningnetwork / lnd / 13211764208

08 Feb 2025 03:08AM UTC coverage: 49.288% (-9.5%) from 58.815%
13211764208

Pull #9489

github

calvinrzachman
itest: verify switchrpc server enforces send then track

We prevent the rpc server from allowing onion dispatches for
attempt IDs which have already been tracked by rpc clients.

This helps protect the client from leaking a duplicate onion
attempt. NOTE: This is not the only method for solving this
issue! The issue could be addressed via careful client side
programming which accounts for the uncertainty and async
nature of dispatching onions to a remote process via RPC.
This would require some lnd ChannelRouter changes for how
we intend to use these RPCs though.
Pull Request #9489: multi: add BuildOnion, SendOnion, and TrackOnion RPCs

474 of 990 new or added lines in 11 files covered. (47.88%)

27321 existing lines in 435 files now uncovered.

101192 of 205306 relevant lines covered (49.29%)

1.54 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