Replace boost::variant with std::variant
[novacoin.git] / src / base58.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin Developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6
7 //
8 // Why base-58 instead of standard base-64 encoding?
9 // - Don't want 0OIl characters that look the same in some fonts and
10 //      could be used to create visually identical looking account numbers.
11 // - A string with non-alphanumeric characters is not as easily accepted as an account number.
12 // - E-mail usually won't line-break if there's no punctuation to break at.
13 // - Double-clicking selects the whole number as one word if it's all alphanumeric.
14 //
15
16 #include "base58.h"
17 #include "key.h"
18 #include "script.h"
19
20 static const std::array<char, 58> digits = {
21     '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
22     'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
23     'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm',
24     'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
25 };
26
27 static const std::array<signed char, 128> characterMap = {
28         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
29         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
30         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
31         -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1,
32         -1, 9,10,11,12,13,14,15,16,-1,17,18,19,20,21,-1,
33         22,23,24,25,26,27,28,29,30,31,32,-1,-1,-1,-1,-1,
34         -1,33,34,35,36,37,38,39,40,41,42,43,-1,44,45,46,
35         47,48,49,50,51,52,53,54,55,56,57,-1,-1,-1,-1,-1,
36 };
37
38 // Encode a byte sequence as a base58-encoded string
39 std::string EncodeBase58(const unsigned char* begin, const unsigned char* end)
40 {
41     // Skip & count leading zeroes.
42     int zeroes = 0;
43     int length = 0;
44     while (begin != end && *begin == 0) {
45         begin += 1;
46         zeroes += 1;
47     }
48
49     // Allocate enough space in big-endian base58 representation.
50     auto base58Size = (end - begin) * 138 / 100 + 1; // log(256) / log(58), rounded up.
51     std::vector<unsigned char> b58(base58Size);
52
53     while (begin != end) {
54         int carry = *begin;
55         int i = 0;
56         // Apply "b58 = b58 * 256 + ch".
57         for (auto b58it = b58.rbegin(); (carry != 0 || i < length) && (b58it != b58.rend());
58              b58it++, i++) {
59             carry += 256 * (*b58it);
60             *b58it = carry % 58;
61             carry /= 58;
62         }
63
64         assert(carry == 0);
65         length = i;
66         begin += 1;
67     }
68
69     // Skip leading zeroes in base58 result.
70     auto it = b58.begin() + (base58Size - length);
71     while (it != b58.end() && *it == 0) {
72         it++;
73     }
74
75     // Translate the result into a string.
76     std::string str;
77     str.reserve(zeroes + (b58.end() - it));
78     str.assign(zeroes, digits[0]);
79     while (it != b58.end()) {
80         str += digits[*it];
81         it += 1;
82     }
83     return str;
84 }
85
86 // Encode a byte vector as a base58-encoded string
87 std::string EncodeBase58(const std::vector<unsigned char>& vch)
88 {
89     return EncodeBase58(&vch[0], &vch[0] + vch.size());
90 }
91
92 // Decode a base58-encoded string psz into byte vector vchRet
93 // returns true if decoding is successful
94 bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet)
95 {
96     const auto* it = psz;
97     const char* end = it + strlen(psz);
98
99     // Skip leading spaces.
100     it = std::find_if_not(it, end, [](char c) { return std::isspace(c);});
101
102     // Skip and count leading zeros.
103     std::size_t zeroes = 0;
104     std::size_t length = 0;
105     while (it != end && *it == digits[0]) {
106         zeroes += 1;
107         it += 1;
108     }
109
110     // Allocate enough space in big-endian base256 representation.
111     std::size_t base258Size = (end - it) * 733 / 1000 + 1; // log(58) / log(256), rounded up.
112     std::vector<unsigned char> b256(base258Size);
113
114     // Process the characters.
115    while (it != end && !std::isspace(*it)) {
116         if (static_cast<unsigned char>(*it) >= 128) {
117             // Invalid b58 character
118             return false;
119         }
120
121         // Decode base58 character
122         int carry = characterMap[static_cast<unsigned char>(*it)];
123         if (carry == -1) {
124             // Invalid b58 character
125             return false;
126         }
127
128         std::size_t i = 0;
129         for (auto b256it = b256.rbegin(); (carry != 0 || i < length) && (b256it != b256.rend());
130              ++b256it, ++i) {
131             carry += 58 * (*b256it);
132             *b256it = static_cast<uint8_t>(carry % 256);
133             carry /= 256;
134         }
135         assert(carry == 0);
136         length = i;
137         it += 1;
138     }
139
140     // Skip trailing spaces.
141     it = std::find_if_not(it, end, [](char c) { return std::isspace(c);});
142     if (it != end) {
143         // Extra charaters at the end
144         return false;
145     }
146
147     // Skip leading zeroes in b256.
148     auto b256it = b256.begin() + (base258Size - length);
149     while (b256it != b256.end() && *b256it == 0) {
150         b256it++;
151     }
152
153     // Copy result into output vector.
154     vchRet.reserve(zeroes + (b256.end() - b256it));
155     vchRet.assign(zeroes, 0x00);
156     std::copy(b256it, b256.end(), std::back_inserter(vchRet));
157
158     return true;
159 }
160
161 // Decode a base58-encoded string str into byte vector vchRet
162 // returns true if decoding is successful
163 bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
164 {
165     return DecodeBase58(str.c_str(), vchRet);
166 }
167
168 // Encode a byte vector to a base58-encoded string, including checksum
169 std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
170 {
171     // add 4-byte hash check to the end
172     std::vector<unsigned char> vch(vchIn);
173     uint256 hash = Hash(vch.begin(), vch.end());
174     vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
175     return EncodeBase58(vch);
176 }
177
178 // Decode a base58-encoded string psz that includes a checksum, into byte vector vchRet
179 // returns true if decoding is successful
180 bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
181 {
182     if (!DecodeBase58(psz, vchRet))
183         return false;
184     if (vchRet.size() < 4)
185     {
186         vchRet.clear();
187         return false;
188     }
189     uint256 hash = Hash(vchRet.begin(), vchRet.end()-4);
190     if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
191     {
192         vchRet.clear();
193         return false;
194     }
195     vchRet.resize(vchRet.size()-4);
196     return true;
197 }
198
199 // Decode a base58-encoded string str that includes a checksum, into byte vector vchRet
200 // returns true if decoding is successful
201 bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
202 {
203     return DecodeBase58Check(str.c_str(), vchRet);
204 }
205
206     CBase58Data::CBase58Data()
207     {
208         nVersion = 0;
209         vchData.clear();
210     }
211
212     CBase58Data::~CBase58Data()
213     {
214         // zero the memory, as it may contain sensitive data
215         if (!vchData.empty())
216             OPENSSL_cleanse(&vchData[0], vchData.size());
217     }
218
219     void CBase58Data::SetData(int nVersionIn, const void* pdata, size_t nSize)
220     {
221         nVersion = nVersionIn;
222         vchData.resize(nSize);
223         if (!vchData.empty())
224             memcpy(&vchData[0], pdata, nSize);
225     }
226     
227     const std::vector<unsigned char> &CBase58Data::GetData() const
228     {
229         return vchData;
230     }
231
232     void CBase58Data::SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend)
233     {
234         SetData(nVersionIn, (void*)pbegin, pend - pbegin);
235     }
236
237     bool CBase58Data::SetString(const char* psz)
238     {
239         std::vector<unsigned char> vchTemp;
240         DecodeBase58Check(psz, vchTemp);
241         if (vchTemp.empty())
242         {
243             vchData.clear();
244             nVersion = 0;
245             return false;
246         }
247         nVersion = vchTemp[0];
248         vchData.resize(vchTemp.size() - 1);
249         if (!vchData.empty())
250             memcpy(&vchData[0], &vchTemp[1], vchData.size());
251         OPENSSL_cleanse(&vchTemp[0], vchData.size());
252         return true;
253     }
254
255     bool CBase58Data::SetString(const std::string& str)
256     {
257         return SetString(str.c_str());
258     }
259
260     std::string CBase58Data::ToString() const
261     {
262         std::vector<unsigned char> vch(1, nVersion);
263         vch.insert(vch.end(), vchData.begin(), vchData.end());
264         return EncodeBase58Check(vch);
265     }
266
267     int CBase58Data::CompareTo(const CBase58Data& b58) const
268     {
269         if (nVersion < b58.nVersion) return -1;
270         if (nVersion > b58.nVersion) return  1;
271         if (vchData < b58.vchData)   return -1;
272         if (vchData > b58.vchData)   return  1;
273         return 0;
274     }
275
276     namespace {
277         class CBitcoinAddressVisitor {
278         private:
279             CBitcoinAddress *addr;
280         public:
281             explicit CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { }
282
283             bool operator()(const CKeyID &id) const { return addr->Set(id); }
284             bool operator()(const CScriptID &id) const { return addr->Set(id); }
285             bool operator()(const CMalleablePubKey &mpk) const { return addr->Set(mpk); }
286             bool operator()([[maybe_unused]] const CNoDestination &no) const { return false; }
287         };
288     } // namespace
289
290     bool CBitcoinAddress::Set(const CKeyID &id) {
291         SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &id, 20);
292         return true;
293     }
294
295     bool CBitcoinAddress::Set(const CScriptID &id) {
296         SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &id, 20);
297         return true;
298     }
299
300     bool CBitcoinAddress::Set(const CTxDestination &dest)
301     {
302         return std::visit(CBitcoinAddressVisitor(this), dest);
303     }
304
305     bool CBitcoinAddress::Set(const CMalleablePubKey &mpk) {
306         std::vector<unsigned char> vchPubkeyPair = mpk.Raw();
307         SetData(fTestNet ? PUBKEY_PAIR_ADDRESS_TEST : PUBKEY_PAIR_ADDRESS, &vchPubkeyPair[0], 68);
308         return true;
309     }
310
311     bool CBitcoinAddress::Set(const CBitcoinAddress &dest)
312     {
313         nVersion = dest.nVersion;
314         vchData = dest.vchData;
315         return true;
316     }
317
318     bool CBitcoinAddress::IsValid() const
319     {
320         unsigned int nExpectedSize = 20;
321         bool fExpectTestNet = false;
322         bool fSimple = true;
323         switch(nVersion)
324         {
325             case PUBKEY_PAIR_ADDRESS:
326                 nExpectedSize = 68; // Serialized pair of public keys
327                 fExpectTestNet = false;
328                 fSimple = false;
329                 break;
330             case PUBKEY_ADDRESS:
331                 nExpectedSize = 20; // Hash of public key
332                 fExpectTestNet = false;
333                 break;
334             case SCRIPT_ADDRESS:
335                 nExpectedSize = 20; // Hash of CScript
336                 fExpectTestNet = false;
337                 break;
338
339             case PUBKEY_PAIR_ADDRESS_TEST:
340                 nExpectedSize = 68;
341                 fExpectTestNet = true;
342                 fSimple = false;
343                 break;
344             case PUBKEY_ADDRESS_TEST:
345                 nExpectedSize = 20;
346                 fExpectTestNet = true;
347                 break;
348             case SCRIPT_ADDRESS_TEST:
349                 nExpectedSize = 20;
350                 fExpectTestNet = true;
351                 break;
352
353             default:
354                 return false;
355         }
356
357         // Basic format sanity check
358         bool fSeemsSane = (fExpectTestNet == fTestNet && vchData.size() == nExpectedSize);
359
360         if (fSeemsSane && !fSimple)
361         {
362             // Perform additional checking
363             //    for pubkey pair addresses
364             CMalleablePubKey mpk;
365             mpk.setvch(vchData);
366             return mpk.IsValid();
367         }
368         else
369             return fSeemsSane;
370     }
371
372     CTxDestination CBitcoinAddress::Get() const {
373         if (!IsValid())
374             return CNoDestination();
375         switch (nVersion) {
376         case PUBKEY_ADDRESS:
377         case PUBKEY_ADDRESS_TEST: {
378             uint160 id;
379             memcpy(&id, &vchData[0], 20);
380             return CKeyID(id);
381         }
382         case SCRIPT_ADDRESS:
383         case SCRIPT_ADDRESS_TEST: {
384             uint160 id;
385             memcpy(&id, &vchData[0], 20);
386             return CScriptID(id);
387         }
388         }
389         return CNoDestination();
390     }
391
392     bool CBitcoinAddress::GetKeyID(CKeyID &keyID) const {
393         if (!IsValid())
394             return false;
395         switch (nVersion) {
396         case PUBKEY_ADDRESS:
397         case PUBKEY_ADDRESS_TEST: {
398             uint160 id;
399             memcpy(&id, &vchData[0], 20);
400             keyID = CKeyID(id);
401             return true;
402         }
403         case PUBKEY_PAIR_ADDRESS:
404         case PUBKEY_PAIR_ADDRESS_TEST:
405         {
406             CMalleablePubKey mPubKey;
407             mPubKey.setvch(vchData);
408             keyID = mPubKey.GetID();
409             return true;
410         }
411         default: return false;
412         }
413     }
414
415     bool CBitcoinAddress::IsScript() const {
416         if (!IsValid())
417             return false;
418         switch (nVersion) {
419         case SCRIPT_ADDRESS:
420         case SCRIPT_ADDRESS_TEST: {
421             return true;
422         }
423         default: return false;
424         }
425     }
426
427     bool CBitcoinAddress::IsPubKey() const {
428         if (!IsValid())
429             return false;
430         switch (nVersion) {
431         case PUBKEY_ADDRESS:
432         case PUBKEY_ADDRESS_TEST: {
433             return true;
434         }
435         default: return false;
436         }
437     }
438     
439     bool CBitcoinAddress::IsPair() const {
440         if (!IsValid())
441             return false;
442         switch (nVersion) {
443         case PUBKEY_PAIR_ADDRESS:
444         case PUBKEY_PAIR_ADDRESS_TEST: {
445             return true;
446         }
447         default: return false;
448         }
449     }
450
451     void CBitcoinSecret::SetSecret(const CSecret& vchSecret, bool fCompressed)
452     {
453         assert(vchSecret.size() == 32);
454         SetData(128 + (fTestNet ? CBitcoinAddress::PUBKEY_ADDRESS_TEST : CBitcoinAddress::PUBKEY_ADDRESS), &vchSecret[0], vchSecret.size());
455         if (fCompressed)
456             vchData.push_back(1);
457     }
458
459     CSecret CBitcoinSecret::GetSecret(bool &fCompressedOut)
460     {
461         CSecret vchSecret;
462         vchSecret.resize(32);
463         memcpy(&vchSecret[0], &vchData[0], 32);
464         fCompressedOut = vchData.size() == 33;
465         return vchSecret;
466     }
467
468     bool CBitcoinSecret::IsValid() const
469     {
470         bool fExpectTestNet = false;
471         switch(nVersion)
472         {
473             case (128 + CBitcoinAddress::PUBKEY_ADDRESS):
474                 break;
475
476             case (128 + CBitcoinAddress::PUBKEY_ADDRESS_TEST):
477                 fExpectTestNet = true;
478                 break;
479
480             default:
481                 return false;
482         }
483         return fExpectTestNet == fTestNet && (vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1));
484     }
485
486     bool CBitcoinSecret::SetString(const char* pszSecret)
487     {
488         return CBase58Data::SetString(pszSecret) && IsValid();
489     }
490
491     bool CBitcoinSecret::SetString(const std::string& strSecret)
492     {
493         return SetString(strSecret.c_str());
494     }
495
496     CBitcoinSecret::CBitcoinSecret(const CSecret& vchSecret, bool fCompressed)
497     {
498         SetSecret(vchSecret, fCompressed);
499     }