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

lightningnetwork / lnd / 17027244024

17 Aug 2025 11:32PM UTC coverage: 57.287% (-9.5%) from 66.765%
17027244024

Pull #10167

github

web-flow
Merge fcb4f4303 into fb1adfc21
Pull Request #10167: multi: bump Go to 1.24.6

3 of 18 new or added lines in 6 files covered. (16.67%)

28537 existing lines in 457 files now uncovered.

99094 of 172978 relevant lines covered (57.29%)

1.78 hits per line

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

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

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

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

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

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

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

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

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

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

87
// toBytes converts each character in the string 'chars' to the value of the
88
// index of the corresponding character in 'charset'.
UNCOV
89
func toBytes(chars string) ([]byte, error) {
×
UNCOV
90
        decoded := make([]byte, 0, len(chars))
×
UNCOV
91
        for i := 0; i < len(chars); i++ {
×
UNCOV
92
                index := strings.IndexByte(charset, chars[i])
×
UNCOV
93
                if index < 0 {
×
94
                        return nil, fmt.Errorf("invalid character not part of "+
×
95
                                "charset: %v", chars[i])
×
96
                }
×
UNCOV
97
                decoded = append(decoded, byte(index))
×
98
        }
UNCOV
99
        return decoded, nil
×
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) {
×
105
        result := make([]byte, 0, len(data))
×
106
        for _, b := range data {
×
107
                if int(b) >= len(charset) {
×
108
                        return "", fmt.Errorf("invalid data byte: %v", b)
×
109
                }
×
110
                result = append(result, charset[b])
×
111
        }
112
        return string(result), nil
×
113
}
114

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

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

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

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