Dero Web Wallet derosuite. This repo contains changes required for webwallet. With this changes any Dero daemon can become web wallet. All changes are related to daemon rpc server and wallet to make it light and faster.
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.

128 lines
4.7KB

  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. // chunk are max 8 bytes long refer https://cryptonote.org/cns/cns007.txt for more documentation
  33. var bytes_to_base58_length_mapping = []int{
  34. 0, // 0 bytes of input, 0 byte of base58 output
  35. 2, // 1 byte of input, 2 bytes of base58 output
  36. 3, // 2 byte of input, 3 bytes of base58 output
  37. 5, // 3 byte of input, 5 bytes of base58 output
  38. 6, // 4 byte of input, 6 bytes of base58 output
  39. 7, // 5 byte of input, 7 bytes of base58 output
  40. 9, // 6 byte of input, 9 bytes of base58 output
  41. 10, // 7 byte of input, 10 bytes of base58 output
  42. 11, // 8 byte of input, 11 bytes of base58 output
  43. }
  44. // encode 8 byte chunk with necessary padding
  45. func encodeChunk(raw []byte) (result string) {
  46. remainder := new(big.Int)
  47. remainder.SetBytes(raw)
  48. bigZero := new(big.Int)
  49. for remainder.Cmp(bigZero) > 0 {
  50. current := new(big.Int)
  51. remainder.DivMod(remainder, bigBase, current)
  52. result = string(BASE58[current.Int64()]) + result
  53. }
  54. for i := range bytes_to_base58_length_mapping {
  55. if i == len(raw) {
  56. if len(result) < bytes_to_base58_length_mapping[i] {
  57. result = strings.Repeat("1", (bytes_to_base58_length_mapping[i]-len(result))) + result
  58. }
  59. return result
  60. }
  61. }
  62. return // we never reach here, if inputs are well-formed <= 8 bytes
  63. }
  64. // decode max 11 char base58 to 8 byte chunk as necessary
  65. // proper error handling is not being done
  66. func decodeChunk(encoded string) (result []byte) {
  67. bigResult := big.NewInt(0)
  68. currentMultiplier := big.NewInt(1)
  69. tmp := new(big.Int)
  70. for i := len(encoded) - 1; i >= 0; i-- {
  71. // make sure decoded character is a base58 char , otherwise return
  72. if strings.IndexAny(BASE58, string(encoded[i])) < 0 {
  73. return
  74. }
  75. tmp.SetInt64(int64(base58Lookup[string(encoded[i])]))
  76. tmp.Mul(currentMultiplier, tmp)
  77. bigResult.Add(bigResult, tmp)
  78. currentMultiplier.Mul(currentMultiplier, bigBase)
  79. }
  80. for i := range bytes_to_base58_length_mapping {
  81. if bytes_to_base58_length_mapping[i] == len(encoded) {
  82. result = append([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0}, bigResult.Bytes()...)
  83. return result[len(result)-i:] // return necessary bytes, initial zero appended as per mapping
  84. }
  85. }
  86. return // we never reach here, if inputs are well-formed <= 11 chars
  87. }
  88. // split into 8 byte chunks, process and merge back result
  89. func EncodeDeroBase58(data ...[]byte) (result string) {
  90. var combined []byte
  91. for _, item := range data {
  92. combined = append(combined, item...)
  93. }
  94. fullblocks := len(combined) / 8
  95. for i := 0; i < fullblocks; i++ { // process any chunks in 8 byte form
  96. result += encodeChunk(combined[i*8 : (i+1)*8])
  97. }
  98. if len(combined)%8 > 0 { // process last partial block
  99. result += encodeChunk(combined[fullblocks*8:])
  100. }
  101. return
  102. }
  103. // split into 11 char chunks, process and merge back result
  104. func DecodeDeroBase58(data string) (result []byte) {
  105. fullblocks := len(data) / 11
  106. for i := 0; i < fullblocks; i++ { // process partial block
  107. result = append(result, decodeChunk(data[i*11:(i+1)*11])...)
  108. }
  109. if len(data)%11 > 0 { // process last partial block
  110. result = append(result, decodeChunk(data[fullblocks*11:])...)
  111. }
  112. return
  113. }