raw
experimental-genesis    1 //  /****************************\
experimental-genesis 2 // * EXPERIMENTAL BRANCH. *
experimental-genesis 3 // * FOR LABORATORY USE ONLY. *
experimental-genesis 4 // ********************************
experimental-genesis 5 // ************
experimental-genesis 6 // **************
experimental-genesis 7 // ****************
experimental-genesis 8 // **** **** ****
experimental-genesis 9 // *** *** ***
experimental-genesis 10 // *** *** ***
experimental-genesis 11 // *** * * **
experimental-genesis 12 // ******** ********
experimental-genesis 13 // ******* ******
experimental-genesis 14 // *** **
experimental-genesis 15 // * ******* **
experimental-genesis 16 // ** * * * * *
experimental-genesis 17 // ** * * ***
experimental-genesis 18 // **** * * * * ****
experimental-genesis 19 // **** *** * * ** ***
experimental-genesis 20 // **** ********* ******
experimental-genesis 21 // ******* ***** *******
experimental-genesis 22 // ********* ****** **
experimental-genesis 23 // ** ****** ******
experimental-genesis 24 // ** ******* **
experimental-genesis 25 // ** ******* ***
experimental-genesis 26 // **** ******** ************
experimental-genesis 27 // ************ ************
experimental-genesis 28 // ******** *******
experimental-genesis 29 // ****** ****
experimental-genesis 30 // *** ***
experimental-genesis 31 // ********************************
experimental-genesis 32 // Copyright (c) 2009-2010 Satoshi Nakamoto
experimental-genesis 33 // Copyright (c) 2011 The Bitcoin Developers
experimental-genesis 34 // Distributed under the MIT/X11 software license, see the accompanying
experimental-genesis 35 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
experimental-genesis 36
experimental-genesis 37
experimental-genesis 38 //
experimental-genesis 39 // Why base-58 instead of standard base-64 encoding?
experimental-genesis 40 // - Don't want 0OIl characters that look the same in some fonts and
experimental-genesis 41 // could be used to create visually identical looking account numbers.
experimental-genesis 42 // - A string with non-alphanumeric characters is not as easily accepted as an account number.
experimental-genesis 43 // - E-mail usually won't line-break if there's no punctuation to break at.
experimental-genesis 44 // - Doubleclicking selects the whole number as one word if it's all alphanumeric.
experimental-genesis 45 //
experimental-genesis 46 #ifndef BITCOIN_BASE58_H
experimental-genesis 47 #define BITCOIN_BASE58_H
experimental-genesis 48
experimental-genesis 49 #include <string>
experimental-genesis 50 #include <vector>
experimental-genesis 51 #include "bignum.h"
experimental-genesis 52
experimental-genesis 53 static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
experimental-genesis 54
experimental-genesis 55 // Encode a byte sequence as a base58-encoded string
experimental-genesis 56 inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
experimental-genesis 57 {
experimental-genesis 58 CAutoBN_CTX pctx;
experimental-genesis 59 CBigNum bn58 = 58;
experimental-genesis 60 CBigNum bn0 = 0;
experimental-genesis 61
experimental-genesis 62 // Convert big endian data to little endian
experimental-genesis 63 // Extra zero at the end make sure bignum will interpret as a positive number
experimental-genesis 64 std::vector<unsigned char> vchTmp(pend-pbegin+1, 0);
experimental-genesis 65 reverse_copy(pbegin, pend, vchTmp.begin());
experimental-genesis 66
experimental-genesis 67 // Convert little endian data to bignum
experimental-genesis 68 CBigNum bn;
experimental-genesis 69 bn.setvch(vchTmp);
experimental-genesis 70
experimental-genesis 71 // Convert bignum to std::string
experimental-genesis 72 std::string str;
experimental-genesis 73 // Expected size increase from base58 conversion is approximately 137%
experimental-genesis 74 // use 138% to be safe
experimental-genesis 75 str.reserve((pend - pbegin) * 138 / 100 + 1);
experimental-genesis 76 CBigNum dv;
experimental-genesis 77 CBigNum rem;
experimental-genesis 78 while (bn > bn0)
experimental-genesis 79 {
experimental-genesis 80 if (!BN_div(&dv, &rem, &bn, &bn58, pctx))
experimental-genesis 81 throw bignum_error("EncodeBase58 : BN_div failed");
experimental-genesis 82 bn = dv;
experimental-genesis 83 unsigned int c = rem.getulong();
experimental-genesis 84 str += pszBase58[c];
experimental-genesis 85 }
experimental-genesis 86
experimental-genesis 87 // Leading zeroes encoded as base58 zeros
experimental-genesis 88 for (const unsigned char* p = pbegin; p < pend && *p == 0; p++)
experimental-genesis 89 str += pszBase58[0];
experimental-genesis 90
experimental-genesis 91 // Convert little endian std::string to big endian
experimental-genesis 92 reverse(str.begin(), str.end());
experimental-genesis 93 return str;
experimental-genesis 94 }
experimental-genesis 95
experimental-genesis 96 // Encode a byte vector as a base58-encoded string
experimental-genesis 97 inline std::string EncodeBase58(const std::vector<unsigned char>& vch)
experimental-genesis 98 {
experimental-genesis 99 return EncodeBase58(&vch[0], &vch[0] + vch.size());
experimental-genesis 100 }
experimental-genesis 101
experimental-genesis 102 // Decode a base58-encoded string psz into byte vector vchRet
experimental-genesis 103 // returns true if decoding is succesful
experimental-genesis 104 inline bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet)
experimental-genesis 105 {
experimental-genesis 106 CAutoBN_CTX pctx;
experimental-genesis 107 vchRet.clear();
experimental-genesis 108 CBigNum bn58 = 58;
experimental-genesis 109 CBigNum bn = 0;
experimental-genesis 110 CBigNum bnChar;
experimental-genesis 111 while (isspace(*psz))
experimental-genesis 112 psz++;
experimental-genesis 113
experimental-genesis 114 // Convert big endian string to bignum
experimental-genesis 115 for (const char* p = psz; *p; p++)
experimental-genesis 116 {
experimental-genesis 117 const char* p1 = strchr(pszBase58, *p);
experimental-genesis 118 if (p1 == NULL)
experimental-genesis 119 {
experimental-genesis 120 while (isspace(*p))
experimental-genesis 121 p++;
experimental-genesis 122 if (*p != '\0')
experimental-genesis 123 return false;
experimental-genesis 124 break;
experimental-genesis 125 }
experimental-genesis 126 bnChar.setulong(p1 - pszBase58);
experimental-genesis 127 if (!BN_mul(&bn, &bn, &bn58, pctx))
experimental-genesis 128 throw bignum_error("DecodeBase58 : BN_mul failed");
experimental-genesis 129 bn += bnChar;
experimental-genesis 130 }
experimental-genesis 131
experimental-genesis 132 // Get bignum as little endian data
experimental-genesis 133 std::vector<unsigned char> vchTmp = bn.getvch();
experimental-genesis 134
experimental-genesis 135 // Trim off sign byte if present
experimental-genesis 136 if (vchTmp.size() >= 2 && vchTmp.end()[-1] == 0 && vchTmp.end()[-2] >= 0x80)
experimental-genesis 137 vchTmp.erase(vchTmp.end()-1);
experimental-genesis 138
experimental-genesis 139 // Restore leading zeros
experimental-genesis 140 int nLeadingZeros = 0;
experimental-genesis 141 for (const char* p = psz; *p == pszBase58[0]; p++)
experimental-genesis 142 nLeadingZeros++;
experimental-genesis 143 vchRet.assign(nLeadingZeros + vchTmp.size(), 0);
experimental-genesis 144
experimental-genesis 145 // Convert little endian data to big endian
experimental-genesis 146 reverse_copy(vchTmp.begin(), vchTmp.end(), vchRet.end() - vchTmp.size());
experimental-genesis 147 return true;
experimental-genesis 148 }
experimental-genesis 149
experimental-genesis 150 // Decode a base58-encoded string str into byte vector vchRet
experimental-genesis 151 // returns true if decoding is succesful
experimental-genesis 152 inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
experimental-genesis 153 {
experimental-genesis 154 return DecodeBase58(str.c_str(), vchRet);
experimental-genesis 155 }
experimental-genesis 156
experimental-genesis 157
experimental-genesis 158
experimental-genesis 159
experimental-genesis 160 // Encode a byte vector to a base58-encoded string, including checksum
experimental-genesis 161 inline std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
experimental-genesis 162 {
experimental-genesis 163 // add 4-byte hash check to the end
experimental-genesis 164 std::vector<unsigned char> vch(vchIn);
experimental-genesis 165 uint256 hash = Hash(vch.begin(), vch.end());
experimental-genesis 166 vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
experimental-genesis 167 return EncodeBase58(vch);
experimental-genesis 168 }
experimental-genesis 169
experimental-genesis 170 // Decode a base58-encoded string psz that includes a checksum, into byte vector vchRet
experimental-genesis 171 // returns true if decoding is succesful
experimental-genesis 172 inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
experimental-genesis 173 {
experimental-genesis 174 if (!DecodeBase58(psz, vchRet))
experimental-genesis 175 return false;
experimental-genesis 176 if (vchRet.size() < 4)
experimental-genesis 177 {
experimental-genesis 178 vchRet.clear();
experimental-genesis 179 return false;
experimental-genesis 180 }
experimental-genesis 181 uint256 hash = Hash(vchRet.begin(), vchRet.end()-4);
experimental-genesis 182 if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
experimental-genesis 183 {
experimental-genesis 184 vchRet.clear();
experimental-genesis 185 return false;
experimental-genesis 186 }
experimental-genesis 187 vchRet.resize(vchRet.size()-4);
experimental-genesis 188 return true;
experimental-genesis 189 }
experimental-genesis 190
experimental-genesis 191 // Decode a base58-encoded string str that includes a checksum, into byte vector vchRet
experimental-genesis 192 // returns true if decoding is succesful
experimental-genesis 193 inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
experimental-genesis 194 {
experimental-genesis 195 return DecodeBase58Check(str.c_str(), vchRet);
experimental-genesis 196 }
experimental-genesis 197
experimental-genesis 198
experimental-genesis 199
experimental-genesis 200
experimental-genesis 201
experimental-genesis 202 // Base class for all base58-encoded data
experimental-genesis 203 class CBase58Data
experimental-genesis 204 {
experimental-genesis 205 protected:
experimental-genesis 206 // the version byte
experimental-genesis 207 unsigned char nVersion;
experimental-genesis 208
experimental-genesis 209 // the actually encoded data
experimental-genesis 210 std::vector<unsigned char> vchData;
experimental-genesis 211
experimental-genesis 212 CBase58Data()
experimental-genesis 213 {
experimental-genesis 214 nVersion = 0;
experimental-genesis 215 vchData.clear();
experimental-genesis 216 }
experimental-genesis 217
experimental-genesis 218 ~CBase58Data()
experimental-genesis 219 {
experimental-genesis 220 // zero the memory, as it may contain sensitive data
experimental-genesis 221 if (!vchData.empty())
experimental-genesis 222 memset(&vchData[0], 0, vchData.size());
experimental-genesis 223 }
experimental-genesis 224
experimental-genesis 225 void SetData(int nVersionIn, const void* pdata, size_t nSize)
experimental-genesis 226 {
experimental-genesis 227 nVersion = nVersionIn;
experimental-genesis 228 vchData.resize(nSize);
experimental-genesis 229 if (!vchData.empty())
experimental-genesis 230 memcpy(&vchData[0], pdata, nSize);
experimental-genesis 231 }
experimental-genesis 232
experimental-genesis 233 void SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend)
experimental-genesis 234 {
experimental-genesis 235 SetData(nVersionIn, (void*)pbegin, pend - pbegin);
experimental-genesis 236 }
experimental-genesis 237
experimental-genesis 238 public:
experimental-genesis 239 bool SetString(const char* psz)
experimental-genesis 240 {
experimental-genesis 241 std::vector<unsigned char> vchTemp;
experimental-genesis 242 DecodeBase58Check(psz, vchTemp);
experimental-genesis 243 if (vchTemp.empty())
experimental-genesis 244 {
experimental-genesis 245 vchData.clear();
experimental-genesis 246 nVersion = 0;
experimental-genesis 247 return false;
experimental-genesis 248 }
experimental-genesis 249 nVersion = vchTemp[0];
experimental-genesis 250 vchData.resize(vchTemp.size() - 1);
experimental-genesis 251 if (!vchData.empty())
experimental-genesis 252 memcpy(&vchData[0], &vchTemp[1], vchData.size());
experimental-genesis 253 memset(&vchTemp[0], 0, vchTemp.size());
experimental-genesis 254 return true;
experimental-genesis 255 }
experimental-genesis 256
experimental-genesis 257 bool SetString(const std::string& str)
experimental-genesis 258 {
experimental-genesis 259 return SetString(str.c_str());
experimental-genesis 260 }
experimental-genesis 261
experimental-genesis 262 std::string ToString() const
experimental-genesis 263 {
experimental-genesis 264 std::vector<unsigned char> vch(1, nVersion);
experimental-genesis 265 vch.insert(vch.end(), vchData.begin(), vchData.end());
experimental-genesis 266 return EncodeBase58Check(vch);
experimental-genesis 267 }
experimental-genesis 268
experimental-genesis 269 int CompareTo(const CBase58Data& b58) const
experimental-genesis 270 {
experimental-genesis 271 if (nVersion < b58.nVersion) return -1;
experimental-genesis 272 if (nVersion > b58.nVersion) return 1;
experimental-genesis 273 if (vchData < b58.vchData) return -1;
experimental-genesis 274 if (vchData > b58.vchData) return 1;
experimental-genesis 275 return 0;
experimental-genesis 276 }
experimental-genesis 277
experimental-genesis 278 bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; }
experimental-genesis 279 bool operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; }
experimental-genesis 280 bool operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; }
experimental-genesis 281 bool operator< (const CBase58Data& b58) const { return CompareTo(b58) < 0; }
experimental-genesis 282 bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; }
experimental-genesis 283 };
experimental-genesis 284
experimental-genesis 285 // base58-encoded bitcoin addresses
experimental-genesis 286 // Addresses have version 0 or 111 (testnet)
experimental-genesis 287 // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key
experimental-genesis 288 class CBitcoinAddress : public CBase58Data
experimental-genesis 289 {
experimental-genesis 290 public:
experimental-genesis 291 bool SetHash160(const uint160& hash160)
experimental-genesis 292 {
experimental-genesis 293 SetData(fTestNet ? 111 : 0, &hash160, 20);
experimental-genesis 294 return true;
experimental-genesis 295 }
experimental-genesis 296
experimental-genesis 297 bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
experimental-genesis 298 {
experimental-genesis 299 return SetHash160(Hash160(vchPubKey));
experimental-genesis 300 }
experimental-genesis 301
experimental-genesis 302 bool IsValid() const
experimental-genesis 303 {
experimental-genesis 304 int nExpectedSize = 20;
experimental-genesis 305 bool fExpectTestNet = false;
experimental-genesis 306 switch(nVersion)
experimental-genesis 307 {
experimental-genesis 308 case 0:
experimental-genesis 309 break;
experimental-genesis 310
experimental-genesis 311 case 111:
experimental-genesis 312 fExpectTestNet = true;
experimental-genesis 313 break;
experimental-genesis 314
experimental-genesis 315 default:
experimental-genesis 316 return false;
experimental-genesis 317 }
experimental-genesis 318 return fExpectTestNet == fTestNet && vchData.size() == nExpectedSize;
experimental-genesis 319 }
experimental-genesis 320
experimental-genesis 321 CBitcoinAddress()
experimental-genesis 322 {
experimental-genesis 323 }
experimental-genesis 324
experimental-genesis 325 CBitcoinAddress(uint160 hash160In)
experimental-genesis 326 {
experimental-genesis 327 SetHash160(hash160In);
experimental-genesis 328 }
experimental-genesis 329
experimental-genesis 330 CBitcoinAddress(const std::vector<unsigned char>& vchPubKey)
experimental-genesis 331 {
experimental-genesis 332 SetPubKey(vchPubKey);
experimental-genesis 333 }
experimental-genesis 334
experimental-genesis 335 CBitcoinAddress(const std::string& strAddress)
experimental-genesis 336 {
experimental-genesis 337 SetString(strAddress);
experimental-genesis 338 }
experimental-genesis 339
experimental-genesis 340 CBitcoinAddress(const char* pszAddress)
experimental-genesis 341 {
experimental-genesis 342 SetString(pszAddress);
experimental-genesis 343 }
experimental-genesis 344
experimental-genesis 345 uint160 GetHash160() const
experimental-genesis 346 {
experimental-genesis 347 assert(vchData.size() == 20);
experimental-genesis 348 uint160 hash160;
experimental-genesis 349 memcpy(&hash160, &vchData[0], 20);
experimental-genesis 350 return hash160;
experimental-genesis 351 }
experimental-genesis 352 };
experimental-genesis 353
experimental-genesis 354 #endif