text: // Copyright (c) 2009-2010 Satoshi Nakamoto
  // Copyright (c) 2009-2014 The Bitcoin developers
  // Copyright (c) 2017-2019 The PIVX developers
  // Copyright (c) 2020 The Klimatas developers
  // Distributed under the MIT software license, see the accompanying
  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  /**
   * Why base-58 instead of standard base-64 encoding?
   * - Don't want 0OIl characters that look the same in some fonts and
   *      could be used to create visually identical looking account numbers.
   * - A string with non-alphanumeric characters is not as easily accepted as an account number.
   * - E-mail usually won't line-break if there's no punctuation to break at.
   * - Double-clicking selects the whole number as one word if it's all alphanumeric.
   */
  #ifndef BITCOIN_BASE58_H
  #define BITCOIN_BASE58_H
  
  #include "chainparams.h"
  #include "key.h"
  #include "pubkey.h"
  #include "script/script.h"
  #include "script/standard.h"
  
  #include <string>
  #include <vector>
  
  /**
   * Encode a byte sequence as a base58-encoded string.
   * pbegin and pend cannot be NULL, unless both are.
   */
  std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend);
  
  /**
   * Encode a byte vector as a base58-encoded string
   */
  std::string EncodeBase58(const std::vector<unsigned char>& vch);
  
  /**
   * Decode a base58-encoded string (psz) into a byte vector (vchRet).
   * return true if decoding is successful.
   * psz cannot be NULL.
   */
  bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet);
  
  /**
   * Decode a base58-encoded string (psz) into a string.
   * psz cannot be NULL.
   */
  std::string DecodeBase58(const char* psz);
  
  /**
   * Decode a base58-encoded string (str) into a byte vector (vchRet).
   * return true if decoding is successful.
   */
  bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet);
  
  /**
   * Encode a byte vector into a base58-encoded string, including checksum
   */
  std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn);
  
  /**
   * Decode a base58-encoded string (psz) that includes a checksum into a byte
   * vector (vchRet), return true if decoding is successful
   */
  inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet);
  
  /**
   * Decode a base58-encoded string (str) that includes a checksum into a byte
   * vector (vchRet), return true if decoding is successful
   */
  inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet);
  
  /**
   * Base class for all base58-encoded data
   */
  class CBase58Data
  {
  protected:
      //! the version byte(s)
      std::vector<unsigned char> vchVersion;
  
      //! the actually encoded data
      typedef std::vector<unsigned char, zero_after_free_allocator<unsigned char> > vector_uchar;
      vector_uchar vchData;
  
      CBase58Data();
      void SetData(const std::vector<unsigned char>& vchVersionIn, const void* pdata, size_t nSize);
      void SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend);
  
  public:
      bool SetString(const char* psz, unsigned int nVersionBytes = 1);
      bool SetString(const std::string& str);
      std::string ToString() const;
      int CompareTo(const CBase58Data& b58) const;
  
      bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; }
      bool operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; }
      bool operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; }
      bool operator<(const CBase58Data& b58) const { return CompareTo(b58) < 0; }
      bool operator>(const CBase58Data& b58) const { return CompareTo(b58) > 0; }
  };
  
  /** base58-encoded KTS addresses.
   * Public-key-hash-addresses have version 0 (or 111 testnet).
   * The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
   * Script-hash-addresses have version 5 (or 196 testnet).
   * The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
   */
  class CBitcoinAddress : public CBase58Data
  {
  public:
      bool Set(const CKeyID& id, const CChainParams::Base58Type addrType = CChainParams::PUBKEY_ADDRESS);
      bool Set(const CScriptID& id);
      bool Set(const CTxDestination& dest, const CChainParams::Base58Type addrType = CChainParams::PUBKEY_ADDRESS);
      bool IsValid() const;
      bool IsValid(const CChainParams& params) const;
  
      CBitcoinAddress() {}
      CBitcoinAddress(const CTxDestination& dest, const CChainParams::Base58Type addrType = CChainParams::PUBKEY_ADDRESS) { Set(dest, addrType); }
      CBitcoinAddress(const std::string& strAddress) { SetString(strAddress); }
      CBitcoinAddress(const char* pszAddress) { SetString(pszAddress); }
  
      CTxDestination Get() const;
      bool GetKeyID(CKeyID& keyID) const;
      bool IsScript() const;
      bool IsStakingAddress() const;
  
  
      // Helpers
      static const CBitcoinAddress newCSInstance(const CTxDestination& dest) {
          return CBitcoinAddress(dest, CChainParams::STAKING_ADDRESS);
      }
  
      static const CBitcoinAddress newInstance(const CTxDestination& dest) {
          return CBitcoinAddress(dest, CChainParams::PUBKEY_ADDRESS);
      }
  };
  
  /**
   * A base58-encoded secret key
   */
  class CBitcoinSecret : public CBase58Data
  {
  public:
      void SetKey(const CKey& vchSecret);
      CKey GetKey();
      bool IsValid() const;
      bool SetString(const char* pszSecret);
      bool SetString(const std::string& strSecret);
  
      CBitcoinSecret(const CKey& vchSecret) { SetKey(vchSecret); }
      CBitcoinSecret() {}
  };
  
  template <typename K, int Size, CChainParams::Base58Type Type>
  class CBitcoinExtKeyBase : public CBase58Data
  {
  public:
      void SetKey(const K& key)
      {
          unsigned char vch[Size];
          key.Encode(vch);
          SetData(Params().Base58Prefix(Type), vch, vch + Size);
      }
  
      K GetKey()
      {
          K ret;
          ret.Decode(&vchData[0], &vchData[Size]);
          return ret;
      }
  
      CBitcoinExtKeyBase(const K& key)
      {
          SetKey(key);
      }
  
      CBitcoinExtKeyBase() {}
  };
  
  typedef CBitcoinExtKeyBase<CExtKey, 74, CChainParams::EXT_SECRET_KEY> CBitcoinExtKey;
  typedef CBitcoinExtKeyBase<CExtPubKey, 74, CChainParams::EXT_PUBLIC_KEY> CBitcoinExtPubKey;
  
  #endif // BITCOIN_BASE58_H
  