• 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

56.25
/zpay32/bech32.go
1
package zpay32
2

3
import (
4
        "fmt"
5
        "strings"
6
)
7

8
const charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
9

10
var gen = []int{0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3}
11

12
// NOTE: This method it a slight modification of the method bech32.Decode found
13
// btcutil, allowing strings to be more than 90 characters.
14

15
// decodeBech32 decodes a bech32 encoded string, returning the human-readable
16
// part and the data part excluding the checksum.
17
// Note: the data will be base32 encoded, that is each element of the returned
18
// byte array will encode 5 bits of data. Use the ConvertBits method to convert
19
// this to 8-bit representation.
20
func decodeBech32(bech string) (string, []byte, error) {
3✔
21
        // The maximum allowed length for a bech32 string is 90. It must also
3✔
22
        // be at least 8 characters, since it needs a non-empty HRP, a
3✔
23
        // separator, and a 6 character checksum.
3✔
24
        // NB: The 90 character check specified in BIP173 is skipped here, to
3✔
25
        // allow strings longer than 90 characters.
3✔
26
        if len(bech) < 8 {
3✔
UNCOV
27
                return "", nil, fmt.Errorf("invalid bech32 string length %d",
×
UNCOV
28
                        len(bech))
×
UNCOV
29
        }
×
30
        // Only        ASCII characters between 33 and 126 are allowed.
31
        for i := 0; i < len(bech); i++ {
6✔
32
                if bech[i] < 33 || bech[i] > 126 {
3✔
UNCOV
33
                        return "", nil, fmt.Errorf("invalid character in "+
×
UNCOV
34
                                "string: '%c'", bech[i])
×
UNCOV
35
                }
×
36
        }
37

38
        // The characters must be either all lowercase or all uppercase.
39
        lower := strings.ToLower(bech)
3✔
40
        upper := strings.ToUpper(bech)
3✔
41
        if bech != lower && bech != upper {
3✔
UNCOV
42
                return "", nil, fmt.Errorf("string not all lowercase or all " +
×
UNCOV
43
                        "uppercase")
×
UNCOV
44
        }
×
45

46
        // We'll work with the lowercase string from now on.
47
        bech = lower
3✔
48

3✔
49
        // The string is invalid if the last '1' is non-existent, it is the
3✔
50
        // first character of the string (no human-readable part) or one of the
3✔
51
        // last 6 characters of the string (since checksum cannot contain '1'),
3✔
52
        // or if the string is more than 90 characters in total.
3✔
53
        one := strings.LastIndexByte(bech, '1')
3✔
54
        if one < 1 || one+7 > len(bech) {
3✔
UNCOV
55
                return "", nil, fmt.Errorf("invalid index of 1")
×
UNCOV
56
        }
×
57

58
        // The human-readable part is everything before the last '1'.
59
        hrp := bech[:one]
3✔
60
        data := bech[one+1:]
3✔
61

3✔
62
        // Each character corresponds to the byte with value of the index in
3✔
63
        // 'charset'.
3✔
64
        decoded, err := toBytes(data)
3✔
65
        if err != nil {
3✔
UNCOV
66
                return "", nil, fmt.Errorf("failed converting data to bytes: "+
×
UNCOV
67
                        "%v", err)
×
UNCOV
68
        }
×
69

70
        if !bech32VerifyChecksum(hrp, decoded) {
3✔
UNCOV
71
                moreInfo := ""
×
UNCOV
72
                checksum := bech[len(bech)-6:]
×
UNCOV
73
                expected, err := toChars(bech32Checksum(hrp,
×
UNCOV
74
                        decoded[:len(decoded)-6]))
×
UNCOV
75
                if err == nil {
×
UNCOV
76
                        moreInfo = fmt.Sprintf("Expected %v, got %v.",
×
UNCOV
77
                                expected, checksum)
×
UNCOV
78
                }
×
UNCOV
79
                return "", nil, fmt.Errorf("checksum failed. " + moreInfo)
×
80
        }
81

82
        // We exclude the last 6 bytes, which is the checksum.
83
        return hrp, decoded[:len(decoded)-6], nil
3✔
84
}
85

86
// toBytes converts each character in the string 'chars' to the value of the
87
// index of the corresponding character in 'charset'.
88
func toBytes(chars string) ([]byte, error) {
3✔
89
        decoded := make([]byte, 0, len(chars))
3✔
90
        for i := 0; i < len(chars); i++ {
6✔
91
                index := strings.IndexByte(charset, chars[i])
3✔
92
                if index < 0 {
3✔
UNCOV
93
                        return nil, fmt.Errorf("invalid character not part of "+
×
UNCOV
94
                                "charset: %v", chars[i])
×
UNCOV
95
                }
×
96
                decoded = append(decoded, byte(index))
3✔
97
        }
98
        return decoded, nil
3✔
99
}
100

101
// toChars converts the byte slice 'data' to a string where each byte in 'data'
102
// encodes the index of a character in 'charset'.
UNCOV
103
func toChars(data []byte) (string, error) {
×
UNCOV
104
        result := make([]byte, 0, len(data))
×
UNCOV
105
        for _, b := range data {
×
UNCOV
106
                if int(b) >= len(charset) {
×
107
                        return "", fmt.Errorf("invalid data byte: %v", b)
×
108
                }
×
UNCOV
109
                result = append(result, charset[b])
×
110
        }
UNCOV
111
        return string(result), nil
×
112
}
113

114
// For more details on the checksum calculation, please refer to BIP 173.
UNCOV
115
func bech32Checksum(hrp string, data []byte) []byte {
×
UNCOV
116
        // Convert the bytes to list of integers, as this is needed for the
×
UNCOV
117
        // checksum calculation.
×
UNCOV
118
        integers := make([]int, len(data))
×
UNCOV
119
        for i, b := range data {
×
UNCOV
120
                integers[i] = int(b)
×
UNCOV
121
        }
×
UNCOV
122
        values := append(bech32HrpExpand(hrp), integers...)
×
UNCOV
123
        values = append(values, []int{0, 0, 0, 0, 0, 0}...)
×
UNCOV
124
        polymod := bech32Polymod(values) ^ 1
×
UNCOV
125
        var res []byte
×
UNCOV
126
        for i := 0; i < 6; i++ {
×
UNCOV
127
                res = append(res, byte((polymod>>uint(5*(5-i)))&31))
×
UNCOV
128
        }
×
UNCOV
129
        return res
×
130
}
131

132
// For more details on the polymod calculation, please refer to BIP 173.
133
func bech32Polymod(values []int) int {
3✔
134
        chk := 1
3✔
135
        for _, v := range values {
6✔
136
                b := chk >> 25
3✔
137
                chk = (chk&0x1ffffff)<<5 ^ v
3✔
138
                for i := 0; i < 5; i++ {
6✔
139
                        if (b>>uint(i))&1 == 1 {
6✔
140
                                chk ^= gen[i]
3✔
141
                        }
3✔
142
                }
143
        }
144
        return chk
3✔
145
}
146

147
// For more details on HRP expansion, please refer to BIP 173.
148
func bech32HrpExpand(hrp string) []int {
3✔
149
        v := make([]int, 0, len(hrp)*2+1)
3✔
150
        for i := 0; i < len(hrp); i++ {
6✔
151
                v = append(v, int(hrp[i]>>5))
3✔
152
        }
3✔
153
        v = append(v, 0)
3✔
154
        for i := 0; i < len(hrp); i++ {
6✔
155
                v = append(v, int(hrp[i]&31))
3✔
156
        }
3✔
157
        return v
3✔
158
}
159

160
// For more details on the checksum verification, please refer to BIP 173.
161
func bech32VerifyChecksum(hrp string, data []byte) bool {
3✔
162
        integers := make([]int, len(data))
3✔
163
        for i, b := range data {
6✔
164
                integers[i] = int(b)
3✔
165
        }
3✔
166
        concat := append(bech32HrpExpand(hrp), integers...)
3✔
167
        return bech32Polymod(concat) == 1
3✔
168
}
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