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

lightningnetwork / lnd / 19155841408

07 Nov 2025 02:03AM UTC coverage: 66.675% (-0.04%) from 66.712%
19155841408

Pull #10352

github

web-flow
Merge e4313eba8 into 096ab65b1
Pull Request #10352: [WIP] chainrpc: return Unavailable while notifier starts

137328 of 205965 relevant lines covered (66.68%)

21333.36 hits per line

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

98.21
/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) {
653✔
21
        // The maximum allowed length for a bech32 string is 90. It must also
653✔
22
        // be at least 8 characters, since it needs a non-empty HRP, a
653✔
23
        // separator, and a 6 character checksum.
653✔
24
        // NB: The 90 character check specified in BIP173 is skipped here, to
653✔
25
        // allow strings longer than 90 characters.
653✔
26
        if len(bech) < 8 {
683✔
27
                return "", nil, fmt.Errorf("invalid bech32 string length %d",
30✔
28
                        len(bech))
30✔
29
        }
30✔
30
        // Only        ASCII characters between 33 and 126 are allowed.
31
        for i := 0; i < len(bech); i++ {
234,125✔
32
                if bech[i] < 33 || bech[i] > 126 {
233,571✔
33
                        return "", nil, fmt.Errorf("invalid character in "+
69✔
34
                                "string: '%c'", bech[i])
69✔
35
                }
69✔
36
        }
37

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

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

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

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

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

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

80
                return "", nil, fmt.Errorf("checksum failed. %s", moreInfo)
40✔
81
        }
82

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

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

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

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

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

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

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