OSDN Git Service

feat: add processIssuing (#152)
[bytom/vapor.git] / vendor / github.com / bytom / common / bech32 / bech32.go
diff --git a/vendor/github.com/bytom/common/bech32/bech32.go b/vendor/github.com/bytom/common/bech32/bech32.go
new file mode 100644 (file)
index 0000000..dc0c84f
--- /dev/null
@@ -0,0 +1,248 @@
+package bech32
+
+import (
+       "fmt"
+       "strings"
+)
+
+const charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
+
+var gen = []int{0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3}
+
+// Decode decodes a bech32 encoded string, returning the human-readable
+// part and the data part excluding the checksum.
+func Bech32Decode(bech string) (string, []byte, error) {
+       // The maximum allowed length for a bech32 string is 90. It must also
+       // be at least 8 characters, since it needs a non-empty HRP, a
+       // separator, and a 6 character checksum.
+       if len(bech) < 8 || len(bech) > 90 {
+               return "", nil, fmt.Errorf("invalid bech32 string length %d",
+                       len(bech))
+       }
+       // Only ASCII characters between 33 and 126 are allowed.
+       for i := 0; i < len(bech); i++ {
+               if bech[i] < 33 || bech[i] > 126 {
+                       return "", nil, fmt.Errorf("invalid character in "+
+                               "string: '%c'", bech[i])
+               }
+       }
+
+       // The characters must be either all lowercase or all uppercase.
+       lower := strings.ToLower(bech)
+       upper := strings.ToUpper(bech)
+       if bech != lower && bech != upper {
+               return "", nil, fmt.Errorf("string not all lowercase or all " +
+                       "uppercase")
+       }
+
+       // We'll work with the lowercase string from now on.
+       bech = lower
+
+       // The string is invalid if the last '1' is non-existent, it is the
+       // first character of the string (no human-readable part) or one of the
+       // last 6 characters of the string (since checksum cannot contain '1'),
+       // or if the string is more than 90 characters in total.
+       one := strings.LastIndexByte(bech, '1')
+       if one < 1 || one+7 > len(bech) {
+               return "", nil, fmt.Errorf("invalid index of 1")
+       }
+
+       // The human-readable part is everything before the last '1'.
+       hrp := bech[:one]
+       data := bech[one+1:]
+
+       // Each character corresponds to the byte with value of the index in
+       // 'charset'.
+       decoded, err := toBytes(data)
+       if err != nil {
+               return "", nil, fmt.Errorf("failed converting data to bytes: "+
+                       "%v", err)
+       }
+
+       if !bech32VerifyChecksum(hrp, decoded) {
+               moreInfo := ""
+               checksum := bech[len(bech)-6:]
+               expected, err := toChars(bech32Checksum(hrp,
+                       decoded[:len(decoded)-6]))
+               if err == nil {
+                       moreInfo = fmt.Sprintf("Expected %v, got %v.",
+                               expected, checksum)
+               }
+               return "", nil, fmt.Errorf("checksum failed. " + moreInfo)
+       }
+
+       // We exclude the last 6 bytes, which is the checksum.
+       return hrp, decoded[:len(decoded)-6], nil
+}
+
+// Encode encodes a byte slice into a bech32 string with the
+// human-readable part hrb. Note that the bytes must each encode 5 bits
+// (base32).
+func Bech32Encode(hrp string, data []byte) (string, error) {
+       // Calculate the checksum of the data and append it at the end.
+       checksum := bech32Checksum(hrp, data)
+       combined := append(data, checksum...)
+
+       // The resulting bech32 string is the concatenation of the hrp, the
+       // separator 1, data and checksum. Everything after the separator is
+       // represented using the specified charset.
+       dataChars, err := toChars(combined)
+       if err != nil {
+               return "", fmt.Errorf("unable to convert data bytes to chars: "+
+                       "%v", err)
+       }
+       return hrp + "1" + dataChars, nil
+}
+
+// toBytes converts each character in the string 'chars' to the value of the
+// index of the correspoding character in 'charset'.
+func toBytes(chars string) ([]byte, error) {
+       decoded := make([]byte, 0, len(chars))
+       for i := 0; i < len(chars); i++ {
+               index := strings.IndexByte(charset, chars[i])
+               if index < 0 {
+                       return nil, fmt.Errorf("invalid character not part of "+
+                               "charset: %v", chars[i])
+               }
+               decoded = append(decoded, byte(index))
+       }
+       return decoded, nil
+}
+
+// toChars converts the byte slice 'data' to a string where each byte in 'data'
+// encodes the index of a character in 'charset'.
+func toChars(data []byte) (string, error) {
+       result := make([]byte, 0, len(data))
+       for _, b := range data {
+               if int(b) >= len(charset) {
+                       return "", fmt.Errorf("invalid data byte: %v", b)
+               }
+               result = append(result, charset[b])
+       }
+       return string(result), nil
+}
+
+// ConvertBits converts a byte slice where each byte is encoding fromBits bits,
+// to a byte slice where each byte is encoding toBits bits.
+func ConvertBits(data []byte, fromBits, toBits uint8, pad bool) ([]byte, error) {
+       if fromBits < 1 || fromBits > 8 || toBits < 1 || toBits > 8 {
+               return nil, fmt.Errorf("only bit groups between 1 and 8 allowed")
+       }
+
+       // The final bytes, each byte encoding toBits bits.
+       var regrouped []byte
+
+       // Keep track of the next byte we create and how many bits we have
+       // added to it out of the toBits goal.
+       nextByte := byte(0)
+       filledBits := uint8(0)
+
+       for _, b := range data {
+
+               // Discard unused bits.
+               b = b << (8 - fromBits)
+
+               // How many bits remaining to extract from the input data.
+               remFromBits := fromBits
+               for remFromBits > 0 {
+                       // How many bits remaining to be added to the next byte.
+                       remToBits := toBits - filledBits
+
+                       // The number of bytes to next extract is the minimum of
+                       // remFromBits and remToBits.
+                       toExtract := remFromBits
+                       if remToBits < toExtract {
+                               toExtract = remToBits
+                       }
+
+                       // Add the next bits to nextByte, shifting the already
+                       // added bits to the left.
+                       nextByte = (nextByte << toExtract) | (b >> (8 - toExtract))
+
+                       // Discard the bits we just extracted and get ready for
+                       // next iteration.
+                       b = b << toExtract
+                       remFromBits -= toExtract
+                       filledBits += toExtract
+
+                       // If the nextByte is completely filled, we add it to
+                       // our regrouped bytes and start on the next byte.
+                       if filledBits == toBits {
+                               regrouped = append(regrouped, nextByte)
+                               filledBits = 0
+                               nextByte = 0
+                       }
+               }
+       }
+
+       // We pad any unfinished group if specified.
+       if pad && filledBits > 0 {
+               nextByte = nextByte << (toBits - filledBits)
+               regrouped = append(regrouped, nextByte)
+               filledBits = 0
+               nextByte = 0
+       }
+
+       // Any incomplete group must be <= 4 bits, and all zeroes.
+       if filledBits > 0 && (filledBits > 4 || nextByte != 0) {
+               return nil, fmt.Errorf("invalid incomplete group")
+       }
+
+       return regrouped, nil
+}
+
+// For more details on the checksum calculation, please refer to BIP 173.
+func bech32Checksum(hrp string, data []byte) []byte {
+       // Convert the bytes to list of integers, as this is needed for the
+       // checksum calculation.
+       integers := make([]int, len(data))
+       for i, b := range data {
+               integers[i] = int(b)
+       }
+       values := append(bech32HrpExpand(hrp), integers...)
+       values = append(values, []int{0, 0, 0, 0, 0, 0}...)
+       polymod := bech32Polymod(values) ^ 1
+       var res []byte
+       for i := 0; i < 6; i++ {
+               res = append(res, byte((polymod>>uint(5*(5-i)))&31))
+       }
+       return res
+}
+
+// For more details on the polymod calculation, please refer to BIP 173.
+func bech32Polymod(values []int) int {
+       chk := 1
+       for _, v := range values {
+               b := chk >> 25
+               chk = (chk&0x1ffffff)<<5 ^ v
+               for i := 0; i < 5; i++ {
+                       if (b>>uint(i))&1 == 1 {
+                               chk ^= gen[i]
+                       }
+               }
+       }
+       return chk
+}
+
+// For more details on HRP expansion, please refer to BIP 173.
+func bech32HrpExpand(hrp string) []int {
+       v := make([]int, 0, len(hrp)*2+1)
+       for i := 0; i < len(hrp); i++ {
+               v = append(v, int(hrp[i]>>5))
+       }
+       v = append(v, 0)
+       for i := 0; i < len(hrp); i++ {
+               v = append(v, int(hrp[i]&31))
+       }
+       return v
+}
+
+// For more details on the checksum verification, please refer to BIP 173.
+func bech32VerifyChecksum(hrp string, data []byte) bool {
+       integers := make([]int, len(data))
+       for i, b := range data {
+               integers[i] = int(b)
+       }
+       concat := append(bech32HrpExpand(hrp), integers...)
+       return bech32Polymod(concat) == 1
+}