github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/common/base58.cpp (about)

     1  // Copyright (c) 2014-2017 The Bitcoin Core developers
     2  // Distributed under the MIT software license, see the accompanying
     3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
     4  
     5  #include "common/base58.h"
     6  
     7  #include <assert.h>
     8  #include <string.h>
     9  
    10  namespace neb {
    11  /** All alphanumeric characters except for "0", "I", "O", and "l" */
    12  static const char *psz_base58 =
    13      "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
    14  static const int8_t map_base58[256] = {
    15      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    16      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    17      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  1,  2,  3,  4,  5,  6,  7,
    18      8,  -1, -1, -1, -1, -1, -1, -1, 9,  10, 11, 12, 13, 14, 15, 16, -1, 17, 18,
    19      19, 20, 21, -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1,
    20      -1, -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46, 47, 48,
    21      49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    22      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    23      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    24      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    25      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    26      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    27      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    28      -1, -1, -1, -1, -1, -1, -1, -1, -1,
    29  };
    30  
    31  bool decode_base58(const char *psz, std::vector<unsigned char> &vch) {
    32    // Skip leading spaces.
    33    while (*psz && isspace(*psz))
    34      psz++;
    35    // Skip and count leading '1's.
    36    int zeroes = 0;
    37    int length = 0;
    38    while (*psz == '1') {
    39      zeroes++;
    40      psz++;
    41    }
    42    // Allocate enough space in big-endian base256 representation.
    43    int size = strlen(psz) * 733 / 1000 + 1; // log(58) / log(256), rounded up.
    44    std::vector<unsigned char> b256(size);
    45    // Process the characters.
    46    static_assert(
    47        sizeof(map_base58) / sizeof(map_base58[0]) == 256,
    48        "map_base58.size() should be 256"); // guarantee not out of range
    49    while (*psz && !isspace(*psz)) {
    50      // Decode base58 character
    51      int carry = map_base58[(uint8_t)*psz];
    52      if (carry == -1) // Invalid b58 character
    53        return false;
    54      int i = 0;
    55      for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin();
    56           (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
    57        carry += 58 * (*it);
    58        *it = carry % 256;
    59        carry /= 256;
    60      }
    61      assert(carry == 0);
    62      length = i;
    63      psz++;
    64    }
    65    // Skip trailing spaces.
    66    while (isspace(*psz))
    67      psz++;
    68    if (*psz != 0)
    69      return false;
    70    // Skip leading zeroes in b256.
    71    std::vector<unsigned char>::iterator it = b256.begin() + (size - length);
    72    while (it != b256.end() && *it == 0)
    73      it++;
    74    // Copy result into output vector.
    75    vch.reserve(zeroes + (b256.end() - it));
    76    vch.assign(zeroes, 0x00);
    77    while (it != b256.end())
    78      vch.push_back(*(it++));
    79    return true;
    80  }
    81  
    82  std::string encode_base58(const unsigned char *pbegin,
    83                            const unsigned char *pend) {
    84    // Skip & count leading zeroes.
    85    int zeroes = 0;
    86    int length = 0;
    87    while (pbegin != pend && *pbegin == 0) {
    88      pbegin++;
    89      zeroes++;
    90    }
    91    // Allocate enough space in big-endian base58 representation.
    92    int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up.
    93    std::vector<unsigned char> b58(size);
    94    // Process the bytes.
    95    while (pbegin != pend) {
    96      int carry = *pbegin;
    97      int i = 0;
    98      // Apply "b58 = b58 * 256 + ch".
    99      for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin();
   100           (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
   101        carry += 256 * (*it);
   102        *it = carry % 58;
   103        carry /= 58;
   104      }
   105  
   106      assert(carry == 0);
   107      length = i;
   108      pbegin++;
   109    }
   110    // Skip leading zeroes in base58 result.
   111    std::vector<unsigned char>::iterator it = b58.begin() + (size - length);
   112    while (it != b58.end() && *it == 0)
   113      it++;
   114    // Translate the result into a string.
   115    std::string str;
   116    str.reserve(zeroes + (b58.end() - it));
   117    str.assign(zeroes, '1');
   118    while (it != b58.end())
   119      str += psz_base58[*(it++)];
   120    return str;
   121  }
   122  
   123  std::string encode_base58(const std::vector<unsigned char> &vch) {
   124    return encode_base58(vch.data(), vch.data() + vch.size());
   125  }
   126  
   127  bool decode_base58(const std::string &str, std::vector<unsigned char> &vchRet) {
   128    return decode_base58(str.c_str(), vchRet);
   129  }
   130  } // namespace neb