OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / tendermint / go-wire / data / base58 / base58.go
1 // Copyright (c) 2013-2014 Conformal Systems LLC.
2 // Use of this source code is governed by an ISC
3 // license that can be found in the LICENSE file.
4 // Modified by Juan Benet (juan@benet.ai)
5
6 package base58
7
8 import (
9         "math/big"
10         "strings"
11
12         "github.com/pkg/errors"
13 )
14
15 // alphabet is the modified base58 alphabet used by Bitcoin.
16 const BTCAlphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
17 const FlickrAlphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
18
19 var bigRadix = big.NewInt(58)
20 var bigZero = big.NewInt(0)
21
22 // Decode decodes a modified base58 string to a byte slice, using BTCAlphabet
23 func Decode(b string) ([]byte, error) {
24         return DecodeAlphabet(b, BTCAlphabet)
25 }
26
27 // Encode encodes a byte slice to a modified base58 string, using BTCAlphabet
28 func Encode(b []byte) string {
29         return EncodeAlphabet(b, BTCAlphabet)
30 }
31
32 // DecodeAlphabet decodes a modified base58 string to a byte slice, using alphabet.
33 func DecodeAlphabet(b, alphabet string) ([]byte, error) {
34         answer := big.NewInt(0)
35         j := big.NewInt(1)
36
37         for i := len(b) - 1; i >= 0; i-- {
38                 tmp := strings.IndexAny(alphabet, string(b[i]))
39                 if tmp == -1 {
40                         return nil, errors.Errorf("Encountered unknown character: %s", string(b[i]))
41                 }
42                 idx := big.NewInt(int64(tmp))
43                 tmp1 := big.NewInt(0)
44                 tmp1.Mul(j, idx)
45
46                 answer.Add(answer, tmp1)
47                 j.Mul(j, bigRadix)
48         }
49
50         tmpval := answer.Bytes()
51
52         var numZeros int
53         for numZeros = 0; numZeros < len(b); numZeros++ {
54                 if b[numZeros] != alphabet[0] {
55                         break
56                 }
57         }
58         flen := numZeros + len(tmpval)
59         val := make([]byte, flen, flen)
60         copy(val[numZeros:], tmpval)
61
62         return val, nil
63 }
64
65 // Encode encodes a byte slice to a modified base58 string, using alphabet
66 func EncodeAlphabet(b []byte, alphabet string) string {
67         x := new(big.Int)
68         x.SetBytes(b)
69
70         answer := make([]byte, 0, len(b)*136/100)
71         for x.Cmp(bigZero) > 0 {
72                 mod := new(big.Int)
73                 x.DivMod(x, bigRadix, mod)
74                 answer = append(answer, alphabet[mod.Int64()])
75         }
76
77         // leading zero bytes
78         for _, i := range b {
79                 if i != 0 {
80                         break
81                 }
82                 answer = append(answer, alphabet[0])
83         }
84
85         // reverse
86         alen := len(answer)
87         for i := 0; i < alen/2; i++ {
88                 answer[i], answer[alen-1-i] = answer[alen-1-i], answer[i]
89         }
90
91         return string(answer)
92 }