summary refs log tree commit diff
path: root/vendor/go.mau.fi/util/base58/base58.go
diff options
context:
space:
mode:
authorEmile <git@emile.space>2024-10-25 15:55:50 +0200
committerEmile <git@emile.space>2024-10-25 15:55:50 +0200
commitc90f36e3dd179d2de96f4f5fe38d8dc9a9de6dfe (patch)
tree89e9afb41c5bf76f48cfb09305a2d3db8d302b06 /vendor/go.mau.fi/util/base58/base58.go
parent98bbb0f559a8883bc47bae80607dbe326a448e61 (diff)
vendor HEAD main
Diffstat (limited to 'vendor/go.mau.fi/util/base58/base58.go')
-rw-r--r--vendor/go.mau.fi/util/base58/base58.go138
1 files changed, 138 insertions, 0 deletions
diff --git a/vendor/go.mau.fi/util/base58/base58.go b/vendor/go.mau.fi/util/base58/base58.go
new file mode 100644
index 0000000..8ee5956
--- /dev/null
+++ b/vendor/go.mau.fi/util/base58/base58.go
@@ -0,0 +1,138 @@
+// Copyright (c) 2013-2015 The btcsuite developers
+// 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.Int{
+	big.NewInt(0),
+	big.NewInt(58),
+	big.NewInt(58 * 58),
+	big.NewInt(58 * 58 * 58),
+	big.NewInt(58 * 58 * 58 * 58),
+	big.NewInt(58 * 58 * 58 * 58 * 58),
+	big.NewInt(58 * 58 * 58 * 58 * 58 * 58),
+	big.NewInt(58 * 58 * 58 * 58 * 58 * 58 * 58),
+	big.NewInt(58 * 58 * 58 * 58 * 58 * 58 * 58 * 58),
+	big.NewInt(58 * 58 * 58 * 58 * 58 * 58 * 58 * 58 * 58),
+	bigRadix10,
+}
+
+var bigRadix10 = big.NewInt(58 * 58 * 58 * 58 * 58 * 58 * 58 * 58 * 58 * 58) // 58^10
+
+// Decode decodes a modified base58 string to a byte slice.
+func Decode(b string) []byte {
+	answer := big.NewInt(0)
+	scratch := new(big.Int)
+
+	// Calculating with big.Int is slow for each iteration.
+	//    x += b58[b[i]] * j
+	//    j *= 58
+	//
+	// Instead we can try to do as much calculations on int64.
+	// We can represent a 10 digit base58 number using an int64.
+	//
+	// Hence we'll try to convert 10, base58 digits at a time.
+	// The rough idea is to calculate `t`, such that:
+	//
+	//   t := b58[b[i+9]] * 58^9 ... + b58[b[i+1]] * 58^1 + b58[b[i]] * 58^0
+	//   x *= 58^10
+	//   x += t
+	//
+	// Of course, in addition, we'll need to handle boundary condition when `b` is not multiple of 58^10.
+	// In that case we'll use the bigRadix[n] lookup for the appropriate power.
+	for t := b; len(t) > 0; {
+		n := len(t)
+		if n > 10 {
+			n = 10
+		}
+
+		total := uint64(0)
+		for _, v := range t[:n] {
+			tmp := b58[v]
+			if tmp == 255 {
+				return []byte("")
+			}
+			total = total*58 + uint64(tmp)
+		}
+
+		answer.Mul(answer, bigRadix[n])
+		scratch.SetUint64(total)
+		answer.Add(answer, scratch)
+
+		t = t[n:]
+	}
+
+	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)
+	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)
+
+	// maximum length of output is log58(2^(8*len(b))) == len(b) * 8 / log(58)
+	maxlen := int(float64(len(b))*1.365658237309761) + 1
+	answer := make([]byte, 0, maxlen)
+	mod := new(big.Int)
+	for x.Sign() > 0 {
+		// Calculating with big.Int is slow for each iteration.
+		//    x, mod = x / 58, x % 58
+		//
+		// Instead we can try to do as much calculations on int64.
+		//    x, mod = x / 58^10, x % 58^10
+		//
+		// Which will give us mod, which is 10 digit base58 number.
+		// We'll loop that 10 times to convert to the answer.
+
+		x.DivMod(x, bigRadix10, mod)
+		if x.Sign() == 0 {
+			// When x = 0, we need to ensure we don't add any extra zeros.
+			m := mod.Int64()
+			for m > 0 {
+				answer = append(answer, alphabet[m%58])
+				m /= 58
+			}
+		} else {
+			m := mod.Int64()
+			for i := 0; i < 10; i++ {
+				answer = append(answer, alphabet[m%58])
+				m /= 58
+			}
+		}
+	}
+
+	// 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)
+}