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

lightningnetwork / lnd / 12199391122

06 Dec 2024 01:10PM UTC coverage: 49.807% (-9.1%) from 58.933%
12199391122

push

github

web-flow
Merge pull request #9337 from Guayaba221/patch-1

chore: fix typo in ruby.md

100137 of 201051 relevant lines covered (49.81%)

2.07 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) {
4✔
21
        // The maximum allowed length for a bech32 string is 90. It must also
4✔
22
        // be at least 8 characters, since it needs a non-empty HRP, a
4✔
23
        // separator, and a 6 character checksum.
4✔
24
        // NB: The 90 character check specified in BIP173 is skipped here, to
4✔
25
        // allow strings longer than 90 characters.
4✔
26
        if len(bech) < 8 {
4✔
27
                return "", nil, fmt.Errorf("invalid bech32 string length %d",
×
28
                        len(bech))
×
29
        }
×
30
        // Only        ASCII characters between 33 and 126 are allowed.
31
        for i := 0; i < len(bech); i++ {
8✔
32
                if bech[i] < 33 || bech[i] > 126 {
4✔
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.
39
        lower := strings.ToLower(bech)
4✔
40
        upper := strings.ToUpper(bech)
4✔
41
        if bech != lower && bech != upper {
4✔
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.
47
        bech = lower
4✔
48

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

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

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

70
        if !bech32VerifyChecksum(hrp, decoded) {
4✔
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
                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
4✔
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) {
4✔
89
        decoded := make([]byte, 0, len(chars))
4✔
90
        for i := 0; i < len(chars); i++ {
8✔
91
                index := strings.IndexByte(charset, chars[i])
4✔
92
                if index < 0 {
4✔
93
                        return nil, fmt.Errorf("invalid character not part of "+
×
94
                                "charset: %v", chars[i])
×
95
                }
×
96
                decoded = append(decoded, byte(index))
4✔
97
        }
98
        return decoded, nil
4✔
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'.
103
func toChars(data []byte) (string, error) {
×
104
        result := make([]byte, 0, len(data))
×
105
        for _, b := range data {
×
106
                if int(b) >= len(charset) {
×
107
                        return "", fmt.Errorf("invalid data byte: %v", b)
×
108
                }
×
109
                result = append(result, charset[b])
×
110
        }
111
        return string(result), nil
×
112
}
113

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

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

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

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