dca623d4ef
This change introduces an autogenerated base58 digit table to remove the need to find the index of a character in the modified base58 alphabet each time. Additionally, it removes some unnecessary big integer allocations to cut down on the GC churn. Before: BenchmarkBase58Encode 20 64998995 ns/op 0.08 MB/s BenchmarkBase58Decode 50 35965928 ns/op 0.19 MB/s Now: BenchmarkBase58Encode 20 64644351 ns/op 0.08 MB/s BenchmarkBase58Decode 200 7914748 ns/op 0.86 MB/s
75 lines
1.5 KiB
Go
75 lines
1.5 KiB
Go
// Copyright (c) 2013-2015 Conformal Systems LLC.
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package base58
|
|
|
|
import (
|
|
"math/big"
|
|
)
|
|
|
|
//go:generate go run genalphabet.go
|
|
|
|
var bigRadix = big.NewInt(58)
|
|
var bigZero = big.NewInt(0)
|
|
|
|
// Decode decodes a modified base58 string to a byte slice.
|
|
func Decode(b string) []byte {
|
|
answer := big.NewInt(0)
|
|
j := big.NewInt(1)
|
|
|
|
scratch := new(big.Int)
|
|
for i := len(b) - 1; i >= 0; i-- {
|
|
tmp := b58[b[i]]
|
|
if tmp == 255 {
|
|
return []byte("")
|
|
}
|
|
scratch.SetInt64(int64(tmp))
|
|
scratch.Mul(j, scratch)
|
|
answer.Add(answer, scratch)
|
|
j.Mul(j, bigRadix)
|
|
}
|
|
|
|
tmpval := answer.Bytes()
|
|
|
|
var numZeros int
|
|
for numZeros = 0; numZeros < len(b); numZeros++ {
|
|
if b[numZeros] != alphabetIdx0 {
|
|
break
|
|
}
|
|
}
|
|
flen := numZeros + len(tmpval)
|
|
val := make([]byte, flen, flen)
|
|
copy(val[numZeros:], tmpval)
|
|
|
|
return val
|
|
}
|
|
|
|
// Encode encodes a byte slice to a modified base58 string.
|
|
func Encode(b []byte) string {
|
|
x := new(big.Int)
|
|
x.SetBytes(b)
|
|
|
|
answer := make([]byte, 0, len(b)*136/100)
|
|
for x.Cmp(bigZero) > 0 {
|
|
mod := new(big.Int)
|
|
x.DivMod(x, bigRadix, mod)
|
|
answer = append(answer, alphabet[mod.Int64()])
|
|
}
|
|
|
|
// leading zero bytes
|
|
for _, i := range b {
|
|
if i != 0 {
|
|
break
|
|
}
|
|
answer = append(answer, alphabetIdx0)
|
|
}
|
|
|
|
// reverse
|
|
alen := len(answer)
|
|
for i := 0; i < alen/2; i++ {
|
|
answer[i], answer[alen-1-i] = answer[alen-1-i], answer[i]
|
|
}
|
|
|
|
return string(answer)
|
|
}
|