You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

92 lines
3.1 KiB

  1. // Copyright 2017-2018 DERO Project. All rights reserved.
  2. // Use of this source code in any form is governed by RESEARCH license.
  3. // license can be found in the LICENSE file.
  4. // GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8
  5. //
  6. //
  7. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
  8. // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  9. // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  10. // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  11. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  12. // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  13. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  14. // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  15. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16. package address
  17. import "strings"
  18. import "math/big"
  19. // all characters in the base58
  20. const BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
  21. var base58Lookup = map[string]int{
  22. "1": 0, "2": 1, "3": 2, "4": 3, "5": 4, "6": 5, "7": 6, "8": 7,
  23. "9": 8, "A": 9, "B": 10, "C": 11, "D": 12, "E": 13, "F": 14, "G": 15,
  24. "H": 16, "J": 17, "K": 18, "L": 19, "M": 20, "N": 21, "P": 22, "Q": 23,
  25. "R": 24, "S": 25, "T": 26, "U": 27, "V": 28, "W": 29, "X": 30, "Y": 31,
  26. "Z": 32, "a": 33, "b": 34, "c": 35, "d": 36, "e": 37, "f": 38, "g": 39,
  27. "h": 40, "i": 41, "j": 42, "k": 43, "m": 44, "n": 45, "o": 46, "p": 47,
  28. "q": 48, "r": 49, "s": 50, "t": 51, "u": 52, "v": 53, "w": 54, "x": 55,
  29. "y": 56, "z": 57,
  30. }
  31. var bigBase = big.NewInt(58)
  32. func encodeChunk(raw []byte, padding int) (result string) {
  33. remainder := new(big.Int)
  34. remainder.SetBytes(raw)
  35. bigZero := new(big.Int)
  36. for remainder.Cmp(bigZero) > 0 {
  37. current := new(big.Int)
  38. remainder.DivMod(remainder, bigBase, current)
  39. result = string(BASE58[current.Int64()]) + result
  40. }
  41. if len(result) < padding {
  42. result = strings.Repeat("1", (padding-len(result))) + result
  43. }
  44. return
  45. }
  46. func decodeChunk(encoded string) (result []byte) {
  47. bigResult := big.NewInt(0)
  48. currentMultiplier := big.NewInt(1)
  49. tmp := new(big.Int)
  50. for i := len(encoded) - 1; i >= 0; i-- {
  51. tmp.SetInt64(int64(base58Lookup[string(encoded[i])]))
  52. tmp.Mul(currentMultiplier, tmp)
  53. bigResult.Add(bigResult, tmp)
  54. currentMultiplier.Mul(currentMultiplier, bigBase)
  55. }
  56. result = bigResult.Bytes()
  57. return
  58. }
  59. func EncodeDeroBase58(data ...[]byte) (result string) {
  60. var combined []byte
  61. for _, item := range data {
  62. combined = append(combined, item...)
  63. }
  64. length := len(combined)
  65. rounds := length / 8
  66. for i := 0; i < rounds; i++ {
  67. result += encodeChunk(combined[i*8:(i+1)*8], 11)
  68. }
  69. if length%8 > 0 {
  70. result += encodeChunk(combined[rounds*8:], 7)
  71. }
  72. return
  73. }
  74. func DecodeDeroBase58(data string) (result []byte) {
  75. length := len(data)
  76. rounds := length / 11
  77. for i := 0; i < rounds; i++ {
  78. result = append(result, decodeChunk(data[i*11:(i+1)*11])...)
  79. }
  80. if length%11 > 0 {
  81. result = append(result, decodeChunk(data[rounds*11:])...)
  82. }
  83. return
  84. }