Initial commit, imported from https://git.gammaspectra.live/P2Pool/moneroutil commit 7b24ed2d11ce3f88ca88247778296d60a6129319
This commit is contained in:
commit
3e013d432d
8
LICENSE
Normal file
8
LICENSE
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
Monero Utilities
|
||||||
|
Copyright (c) 2013 Go Authors
|
||||||
|
Copyright (c) 2017 Paxos
|
||||||
|
|
||||||
|
Portion of the code is Go Author's property, licensed under the BSD-3 license
|
||||||
|
Portion of the code is Paxos's property, licensed under the MIT license
|
||||||
|
|
||||||
|
const.go and edwards25519.go are licensed under BSD-3 (see LICENSE-BSD), all other files are licensed under MIT (see LICENSE-MIT).
|
27
LICENSE-BSD
Normal file
27
LICENSE-BSD
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
Copyright (c) 2009 The Go Authors. All rights reserved
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
25
LICENSE-MIT
Normal file
25
LICENSE-MIT
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
Monero Utilities
|
||||||
|
Copyright (c) 2017, Paxos <jimmy.song@paxos.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any
|
||||||
|
person obtaining a copy of this software and associated
|
||||||
|
documentation files (the "Software"), to deal in the
|
||||||
|
Software without restriction, including without
|
||||||
|
limitation the rights to use, copy, modify, merge,
|
||||||
|
publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software
|
||||||
|
is furnished to do so, subject to the following
|
||||||
|
conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice
|
||||||
|
shall be included in all copies or substantial portions
|
||||||
|
of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||||
|
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||||
|
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||||
|
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
|
||||||
|
OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||||
|
THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
133
base58.go
Normal file
133
base58.go
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
package base58
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
)
|
||||||
|
|
||||||
|
const base58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
const reverseBase58 =
|
||||||
|
// 0 1 2 3 4 5 6 7 8 9 a b c d e f */
|
||||||
|
/* 00 */ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||||
|
/* 10 */ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||||
|
/* 20 */ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||||
|
/* 30 */ "\xff\x00\x01\x02\x03\x04\x05\x06\x07\x08\xff\xff\xff\xff\xff\xff" +
|
||||||
|
/* 40 */ "\xff\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\xff\x11\x12\x13\x14\x15\xff" +
|
||||||
|
/* 50 */ "\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\xff\xff\xff\xff\xff" +
|
||||||
|
/* 60 */ "\xff\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\xff\x2c\x2d\x2e" +
|
||||||
|
/* 70 */ "\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xff\xff\xff\xff\xff" +
|
||||||
|
/* 80 */ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||||
|
/* 90 */ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||||
|
/* a0 */ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||||
|
/* b0 */ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||||
|
/* c0 */ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||||
|
/* d0 */ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||||
|
/* e0 */ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
|
||||||
|
/* f0 */ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||||
|
|
||||||
|
func encodeChunk(raw []byte, buf []byte) []byte {
|
||||||
|
intToDecode := binary.BigEndian.Uint64(raw[:])
|
||||||
|
|
||||||
|
for intToDecode > 0 {
|
||||||
|
buf = append(buf, base58[intToDecode%58])
|
||||||
|
intToDecode /= 58
|
||||||
|
}
|
||||||
|
for len(buf) < 11 {
|
||||||
|
buf = append(buf, '1')
|
||||||
|
}
|
||||||
|
for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
|
||||||
|
buf[i], buf[j] = buf[j], buf[i]
|
||||||
|
}
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
func encodeChunkTail(raw []byte, buf []byte) []byte {
|
||||||
|
var data [8]byte
|
||||||
|
copy(data[8-len(raw):], raw)
|
||||||
|
|
||||||
|
intToDecode := binary.BigEndian.Uint64(data[:])
|
||||||
|
|
||||||
|
for intToDecode > 0 {
|
||||||
|
buf = append(buf, base58[intToDecode%58])
|
||||||
|
intToDecode /= 58
|
||||||
|
}
|
||||||
|
for len(buf) < 7 {
|
||||||
|
buf = append(buf, '1')
|
||||||
|
}
|
||||||
|
for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
|
||||||
|
buf[i], buf[j] = buf[j], buf[i]
|
||||||
|
}
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeChunk(buf []byte, encoded string) []byte {
|
||||||
|
var intResult uint64
|
||||||
|
currentMultiplier := uint64(1)
|
||||||
|
for i := len(encoded) - 1; i >= 0; i-- {
|
||||||
|
intResult += currentMultiplier * uint64(reverseBase58[encoded[i]])
|
||||||
|
// this can overflow, but only on the last iteration when i == 0 when all data is valid
|
||||||
|
currentMultiplier *= 58
|
||||||
|
}
|
||||||
|
|
||||||
|
var result [8]byte
|
||||||
|
binary.BigEndian.PutUint64(result[:], intResult)
|
||||||
|
switch len(encoded) {
|
||||||
|
case 0:
|
||||||
|
return append(buf, result[8:]...)
|
||||||
|
case 2:
|
||||||
|
return append(buf, result[7:]...)
|
||||||
|
case 3:
|
||||||
|
return append(buf, result[6:]...)
|
||||||
|
case 5:
|
||||||
|
return append(buf, result[5:]...)
|
||||||
|
case 6:
|
||||||
|
return append(buf, result[4:]...)
|
||||||
|
case 7:
|
||||||
|
return append(buf, result[3:]...)
|
||||||
|
case 9:
|
||||||
|
return append(buf, result[2:]...)
|
||||||
|
case 10:
|
||||||
|
return append(buf, result[1:]...)
|
||||||
|
case 11:
|
||||||
|
return append(buf, result[:]...)
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Encode(data ...[]byte) string {
|
||||||
|
//preallocate common case
|
||||||
|
combined := make([]byte, 0, 96)
|
||||||
|
for _, item := range data {
|
||||||
|
combined = append(combined, item...)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]byte, 0, len(combined)*2)
|
||||||
|
buf := make([]byte, 0, len(combined)*2)
|
||||||
|
length := len(combined)
|
||||||
|
rounds := length / 8
|
||||||
|
for i := 0; i < rounds; i++ {
|
||||||
|
result = append(result, encodeChunk(combined[i*8:(i+1)*8], buf[:0])...)
|
||||||
|
}
|
||||||
|
if length%8 > 0 {
|
||||||
|
result = append(result, encodeChunkTail(combined[rounds*8:], buf[:0])...)
|
||||||
|
}
|
||||||
|
return string(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Decode(data string) (result []byte) {
|
||||||
|
//common case
|
||||||
|
return DecodePreAllocated(make([]byte, 0, 69), data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecodePreAllocated(buf []byte, data string) (result []byte) {
|
||||||
|
result = buf
|
||||||
|
length := len(data)
|
||||||
|
rounds := length / 11
|
||||||
|
for i := 0; i < rounds; i++ {
|
||||||
|
result = decodeChunk(result, data[i*11:i*11+11])
|
||||||
|
}
|
||||||
|
if length%11 > 0 {
|
||||||
|
result = decodeChunk(result, data[rounds*11:])
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
16
base58_test.go
Normal file
16
base58_test.go
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package base58
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEncodeDecodeMoneroBase58Bounds(t *testing.T) {
|
||||||
|
data := make([]byte, 2048)
|
||||||
|
for i := range data {
|
||||||
|
data[i] = 0xff
|
||||||
|
}
|
||||||
|
if bytes.Compare(Decode(Encode(data)), data) != 0 {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue