Replace big int with uint128 implementation
This commit is contained in:
parent
29dc54bf40
commit
a2daa2d5fc
72
base58.go
72
base58.go
|
@ -1,8 +1,8 @@
|
||||||
package moneroutil
|
package moneroutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"bytes"
|
||||||
"strings"
|
"lukechampine.com/uint128"
|
||||||
)
|
)
|
||||||
|
|
||||||
const BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
const BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||||
|
@ -17,58 +17,78 @@ var base58Lookup = map[string]int{
|
||||||
"q": 48, "r": 49, "s": 50, "t": 51, "u": 52, "v": 53, "w": 54, "x": 55,
|
"q": 48, "r": 49, "s": 50, "t": 51, "u": 52, "v": 53, "w": 54, "x": 55,
|
||||||
"y": 56, "z": 57,
|
"y": 56, "z": 57,
|
||||||
}
|
}
|
||||||
var bigBase = big.NewInt(58)
|
|
||||||
|
|
||||||
func encodeChunk(raw []byte, padding int) (result string) {
|
var base128 = uint128.From64(58)
|
||||||
remainder := new(big.Int)
|
|
||||||
remainder.SetBytes(raw)
|
func encodeChunk(raw []byte, padding int) (result []byte) {
|
||||||
bigZero := new(big.Int)
|
remainder := uint128.FromBytes(append(bytes.Repeat([]byte{0}, 16-len(raw)), raw...)).ReverseBytes()
|
||||||
for remainder.Cmp(bigZero) > 0 {
|
var current uint128.Uint128
|
||||||
current := new(big.Int)
|
for remainder.Cmp64(0) > 0 {
|
||||||
remainder.DivMod(remainder, bigBase, current)
|
remainder, current = remainder.QuoRem(base128)
|
||||||
result = string(BASE58[current.Int64()]) + result
|
result = append([]byte{BASE58[current.Lo]}, result...)
|
||||||
}
|
}
|
||||||
if len(result) < padding {
|
if len(result) < padding {
|
||||||
result = strings.Repeat("1", (padding-len(result))) + result
|
result = append(bytes.Repeat([]byte{'1'}, padding-len(result)), result...)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeChunk(encoded string) (result []byte) {
|
func decodeChunk(encoded string) (result []byte) {
|
||||||
bigResult := big.NewInt(0)
|
var bigResult uint128.Uint128
|
||||||
currentMultiplier := big.NewInt(1)
|
currentMultiplier := uint128.From64(1)
|
||||||
tmp := new(big.Int)
|
|
||||||
for i := len(encoded) - 1; i >= 0; i-- {
|
for i := len(encoded) - 1; i >= 0; i-- {
|
||||||
tmp.SetInt64(int64(base58Lookup[string(encoded[i])]))
|
bigResult = bigResult.Add(currentMultiplier.Mul64(uint64(base58Lookup[string(encoded[i])])))
|
||||||
tmp.Mul(currentMultiplier, tmp)
|
currentMultiplier = currentMultiplier.Mul(base128)
|
||||||
bigResult.Add(bigResult, tmp)
|
|
||||||
currentMultiplier.Mul(currentMultiplier, bigBase)
|
|
||||||
}
|
}
|
||||||
result = bigResult.Bytes()
|
result = make([]byte, 16)
|
||||||
return
|
bigResult.ReverseBytes().PutBytes(result)
|
||||||
|
switch len(encoded) {
|
||||||
|
case 0:
|
||||||
|
return result[8+8:]
|
||||||
|
case 2:
|
||||||
|
return result[8+7:]
|
||||||
|
case 3:
|
||||||
|
return result[8+6:]
|
||||||
|
case 5:
|
||||||
|
return result[8+5:]
|
||||||
|
case 6:
|
||||||
|
return result[8+4:]
|
||||||
|
case 7:
|
||||||
|
return result[8+3:]
|
||||||
|
case 9:
|
||||||
|
return result[8+2:]
|
||||||
|
case 10:
|
||||||
|
return result[8+1:]
|
||||||
|
case 11:
|
||||||
|
return result[8:]
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func EncodeMoneroBase58(data ...[]byte) (result string) {
|
func EncodeMoneroBase58(data ...[]byte) string {
|
||||||
var combined []byte
|
var combined []byte
|
||||||
for _, item := range data {
|
for _, item := range data {
|
||||||
combined = append(combined, item...)
|
combined = append(combined, item...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result := make([]byte, 0, len(data)*2)
|
||||||
length := len(combined)
|
length := len(combined)
|
||||||
rounds := length / 8
|
rounds := length / 8
|
||||||
for i := 0; i < rounds; i++ {
|
for i := 0; i < rounds; i++ {
|
||||||
result += encodeChunk(combined[i*8:(i+1)*8], 11)
|
result = append(result, encodeChunk(combined[i*8:(i+1)*8], 11)...)
|
||||||
}
|
}
|
||||||
if length%8 > 0 {
|
if length%8 > 0 {
|
||||||
result += encodeChunk(combined[rounds*8:], 7)
|
result = append(result, encodeChunk(combined[rounds*8:], 7)...)
|
||||||
}
|
}
|
||||||
return
|
return string(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DecodeMoneroBase58(data string) (result []byte) {
|
func DecodeMoneroBase58(data string) (result []byte) {
|
||||||
length := len(data)
|
length := len(data)
|
||||||
rounds := length / 11
|
rounds := length / 11
|
||||||
for i := 0; i < rounds; i++ {
|
for i := 0; i < rounds; i++ {
|
||||||
result = append(result, decodeChunk(data[i*11:(i+1)*11])...)
|
result = append(result, decodeChunk(data[i*11:i*11+11])...)
|
||||||
}
|
}
|
||||||
if length%11 > 0 {
|
if length%11 > 0 {
|
||||||
result = append(result, decodeChunk(data[rounds*11:])...)
|
result = append(result, decodeChunk(data[rounds*11:])...)
|
||||||
|
|
7
go.mod
7
go.mod
|
@ -2,6 +2,9 @@ module git.gammaspectra.live/P2Pool/moneroutil
|
||||||
|
|
||||||
go 1.19
|
go 1.19
|
||||||
|
|
||||||
require golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b
|
require (
|
||||||
|
golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b
|
||||||
|
lukechampine.com/uint128 v1.2.0
|
||||||
|
)
|
||||||
|
|
||||||
require golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec // indirect
|
require golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875 // indirect
|
||||||
|
|
14
go.sum
14
go.sum
|
@ -1,12 +1,6 @@
|
||||||
golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b h1:huxqepDufQpLLIRXiVkTvnxrzJlpwmIWAObmcCcUFr0=
|
golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b h1:huxqepDufQpLLIRXiVkTvnxrzJlpwmIWAObmcCcUFr0=
|
||||||
golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875 h1:AzgQNqF+FKwyQ5LbVrVqOcuuFB67N47F9+htZYH0wFM=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
|
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI=
|
|
||||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
|
|
Reference in a new issue