Base58.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. This file is part of cpp-ethereum.
  3. cpp-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. cpp-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /** @file Base58.cpp
  15. * Adapted from code found on https://github.com/bitcoin/bitcoin/blob/master/src/base58.cpp
  16. * Licenced under The MIT License.
  17. * @author The Bitcoin core developers (original)
  18. * @author Gav Wood <i@gavwood.com> (minor modifications and reformating)
  19. * @date 2015
  20. */
  21. #include "Base58.h"
  22. using namespace std;
  23. using namespace dev;
  24. std::string dev::AlphabetIPFS("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
  25. std::string dev::AlphabetFlickr("123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ");
  26. bytes dev::fromBase58(string const& _s, string const& _alphabet)
  27. {
  28. auto index = _s.begin();
  29. // Skip and count leading '1's.
  30. int zeroes = 0;
  31. while (*index == _alphabet[0])
  32. {
  33. zeroes++;
  34. index++;
  35. }
  36. // Allocate enough space in big-endian base256 representation.
  37. // log(58) / log(256), rounded up.
  38. bytes ret((_s.size() - zeroes) * 733 / 1000 + 1);
  39. // Process the characters.
  40. while (index != _s.end())
  41. {
  42. // Decode base58 character
  43. size_t carry = _alphabet.find(*index);
  44. if (carry == string::npos)
  45. throw invalid_argument("Invalid character in base-58 string");
  46. // Apply "ret = ret * 58 + ch".
  47. for (auto it = ret.rbegin(); it != ret.rend(); it++)
  48. {
  49. carry += 58 * (*it);
  50. *it = carry % 256;
  51. carry /= 256;
  52. }
  53. assert(carry == 0);
  54. index++;
  55. }
  56. // Skip leading zeroes.
  57. while (!ret.front())
  58. ret.erase(ret.begin());
  59. // Re-insert zeroes.
  60. for (int i = 0; i < zeroes; ++i)
  61. ret.insert(ret.begin(), 0);
  62. return ret;
  63. }
  64. string dev::toBase58(bytesConstRef _d, string const& _alphabet)
  65. {
  66. auto begin = _d.data();
  67. auto end = _d.data() + _d.size();
  68. // Skip & count leading zeroes.
  69. int zeroes = 0;
  70. for (; begin != end && !*begin; begin++, zeroes++) {}
  71. // Allocate enough space in big-endian base58 representation.
  72. // log(256) / log(58), rounded up.
  73. std::vector<unsigned char> b58((end - begin) * 138 / 100 + 1);
  74. // Process the bytes.
  75. while (begin != end)
  76. {
  77. int carry = *begin;
  78. // Apply "b58 = b58 * 256 + ch".
  79. for (auto it = b58.rbegin(); it != b58.rend(); it++)
  80. {
  81. carry += 256 * (*it);
  82. *it = carry % 58;
  83. carry /= 58;
  84. }
  85. assert(!carry);
  86. begin++;
  87. }
  88. // Skip leading zeroes in base58 result.
  89. auto it = b58.begin();
  90. while (it != b58.end() && !*it)
  91. it++;
  92. // Translate the result into a string.
  93. std::string ret;
  94. ret.reserve(zeroes + (b58.end() - it));
  95. ret.assign(zeroes, '1');
  96. while (it != b58.end())
  97. ret += _alphabet[*(it++)];
  98. return ret;
  99. }