diff --git a/address_test.go b/address_test.go index 942542d..933e95a 100644 --- a/address_test.go +++ b/address_test.go @@ -63,28 +63,32 @@ func TestAddress(t *testing.T) { address: "9xYZvCDf6aFdLd7Qawg5XHZitWLKoeFvcLHfe5GxsGCFLbXSWeQNKciXX9YN4T7nPPLcpqYLUdrFiY77nQYeH9RuK9bogZJ", }, } - var base58 string - var spendingKey, viewingKey []byte - for _, test := range tests { - spendingKey, _ = hex.DecodeString(test.spendingKeyHex) - viewingKey, _ = hex.DecodeString(test.viewingKeyHex) - address, _ := NewAddress(test.address) - if address.network != test.network { - t.Errorf("%s: want: %d, got: %d", test.name, test.network, address.network) - continue - } - if bytes.Compare(address.spendingKey, spendingKey) != 0 { - t.Errorf("%s: want: %x, got: %x", test.name, spendingKey, address.spendingKey) - continue - } - if bytes.Compare(address.viewingKey, viewingKey) != 0 { - t.Errorf("%s: want: %x, got: %x", test.name, viewingKey, address.viewingKey) - continue - } - base58 = address.Base58() - if base58 != test.address { - t.Errorf("%s: want: %s, got: %s", test.name, test.address, base58) - continue + + for i := 0; i < 50000; i++ { + + var base58 string + var spendingKey, viewingKey []byte + for _, test := range tests { + spendingKey, _ = hex.DecodeString(test.spendingKeyHex) + viewingKey, _ = hex.DecodeString(test.viewingKeyHex) + address, _ := NewAddress(test.address) + if address.network != test.network { + t.Errorf("%s: want: %d, got: %d", test.name, test.network, address.network) + continue + } + if bytes.Compare(address.spendingKey, spendingKey) != 0 { + t.Errorf("%s: want: %x, got: %x", test.name, spendingKey, address.spendingKey) + continue + } + if bytes.Compare(address.viewingKey, viewingKey) != 0 { + t.Errorf("%s: want: %x, got: %x", test.name, viewingKey, address.viewingKey) + continue + } + base58 = address.Base58() + if base58 != test.address { + t.Errorf("%s: want: %s, got: %s", test.name, test.address, base58) + continue + } } } } diff --git a/base58.go b/base58.go index 5ee9735..4e954db 100644 --- a/base58.go +++ b/base58.go @@ -1,7 +1,6 @@ package moneroutil import ( - "bytes" "lukechampine.com/uint128" ) @@ -20,17 +19,22 @@ var base58Lookup = map[string]int{ var base128 = uint128.From64(58) -func encodeChunk(raw []byte, padding int) (result []byte) { - remainder := uint128.FromBytes(append(bytes.Repeat([]byte{0}, 16-len(raw)), raw...)).ReverseBytes() +func encodeChunk(raw []byte, padding int, buf []byte) []byte { + var data [16]byte + copy(data[16-len(raw):], raw) + remainder := uint128.FromBytesBE(data[:]) var current uint128.Uint128 for remainder.Cmp64(0) > 0 { remainder, current = remainder.QuoRem(base128) - result = append([]byte{BASE58[current.Lo]}, result...) + buf = append(buf, BASE58[current.Lo]) } - if len(result) < padding { - result = append(bytes.Repeat([]byte{'1'}, padding-len(result)), result...) + for len(buf) < padding { + buf = append(buf, '1') } - return + 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(encoded string) (result []byte) { @@ -67,19 +71,21 @@ func decodeChunk(encoded string) (result []byte) { } func EncodeMoneroBase58(data ...[]byte) string { - var combined []byte + //preallocate common case + combined := make([]byte, 0, 96) for _, item := range data { combined = append(combined, item...) } - result := make([]byte, 0, len(data)*2) + 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], 11)...) + result = append(result, encodeChunk(combined[i*8:(i+1)*8], 11, buf[:0])...) } if length%8 > 0 { - result = append(result, encodeChunk(combined[rounds*8:], 7)...) + result = append(result, encodeChunk(combined[rounds*8:], 7, buf[:0])...) } return string(result) } diff --git a/go.mod b/go.mod index 88da694..28b51aa 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module git.gammaspectra.live/P2Pool/moneroutil go 1.19 require ( - golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b - lukechampine.com/uint128 v1.2.0 + golang.org/x/crypto v0.9.0 + lukechampine.com/uint128 v1.3.0 ) -require golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875 // indirect +require golang.org/x/sys v0.8.0 // indirect diff --git a/go.sum b/go.sum index 11150ed..fd3f72d 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,6 @@ -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/sys v0.0.0-20221006211917-84dc82d7e875 h1:AzgQNqF+FKwyQ5LbVrVqOcuuFB67N47F9+htZYH0wFM= -golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= -lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo= +lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=