]> Git Repo - VerusCoin.git/blame - src/base58.h
Merge pull request #2336 from petertodd/invalid-opcode-coverage
[VerusCoin.git] / src / base58.h
CommitLineData
0a61b0df 1// Copyright (c) 2009-2010 Satoshi Nakamoto
88216419 2// Copyright (c) 2009-2012 The Bitcoin Developers
0a61b0df 3// Distributed under the MIT/X11 software license, see the accompanying
3a25a2b9 4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
0a61b0df 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.
814efd6f 13// - Double-clicking selects the whole number as one word if it's all alphanumeric.
0a61b0df 14//
223b6f1b
WL
15#ifndef BITCOIN_BASE58_H
16#define BITCOIN_BASE58_H
0a61b0df 17
223b6f1b
WL
18#include <string>
19#include <vector>
0f8a6477 20
223b6f1b 21#include "bignum.h"
15a8590e 22#include "key.h"
10254401 23#include "script.h"
d0b0925b 24#include "allocators.h"
0a61b0df 25
26static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
27
d825e6a3 28// Encode a byte sequence as a base58-encoded string
223b6f1b 29inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
0a61b0df 30{
31 CAutoBN_CTX pctx;
32 CBigNum bn58 = 58;
33 CBigNum bn0 = 0;
34
35 // Convert big endian data to little endian
36 // Extra zero at the end make sure bignum will interpret as a positive number
223b6f1b 37 std::vector<unsigned char> vchTmp(pend-pbegin+1, 0);
0a61b0df 38 reverse_copy(pbegin, pend, vchTmp.begin());
39
40 // Convert little endian data to bignum
41 CBigNum bn;
42 bn.setvch(vchTmp);
43
223b6f1b
WL
44 // Convert bignum to std::string
45 std::string str;
a9d3af88
DH
46 // Expected size increase from base58 conversion is approximately 137%
47 // use 138% to be safe
0a61b0df 48 str.reserve((pend - pbegin) * 138 / 100 + 1);
49 CBigNum dv;
50 CBigNum rem;
51 while (bn > bn0)
52 {
53 if (!BN_div(&dv, &rem, &bn, &bn58, pctx))
54 throw bignum_error("EncodeBase58 : BN_div failed");
55 bn = dv;
56 unsigned int c = rem.getulong();
57 str += pszBase58[c];
58 }
59
60 // Leading zeroes encoded as base58 zeros
61 for (const unsigned char* p = pbegin; p < pend && *p == 0; p++)
62 str += pszBase58[0];
63
223b6f1b 64 // Convert little endian std::string to big endian
0a61b0df 65 reverse(str.begin(), str.end());
66 return str;
67}
68
d825e6a3 69// Encode a byte vector as a base58-encoded string
223b6f1b 70inline std::string EncodeBase58(const std::vector<unsigned char>& vch)
0a61b0df 71{
72 return EncodeBase58(&vch[0], &vch[0] + vch.size());
73}
74
d825e6a3 75// Decode a base58-encoded string psz into byte vector vchRet
7790f391 76// returns true if decoding is successful
223b6f1b 77inline bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet)
0a61b0df 78{
79 CAutoBN_CTX pctx;
80 vchRet.clear();
81 CBigNum bn58 = 58;
82 CBigNum bn = 0;
83 CBigNum bnChar;
84 while (isspace(*psz))
85 psz++;
86
87 // Convert big endian string to bignum
88 for (const char* p = psz; *p; p++)
89 {
90 const char* p1 = strchr(pszBase58, *p);
91 if (p1 == NULL)
92 {
93 while (isspace(*p))
94 p++;
95 if (*p != '\0')
96 return false;
97 break;
98 }
99 bnChar.setulong(p1 - pszBase58);
100 if (!BN_mul(&bn, &bn, &bn58, pctx))
101 throw bignum_error("DecodeBase58 : BN_mul failed");
102 bn += bnChar;
103 }
104
105 // Get bignum as little endian data
223b6f1b 106 std::vector<unsigned char> vchTmp = bn.getvch();
0a61b0df 107
108 // Trim off sign byte if present
109 if (vchTmp.size() >= 2 && vchTmp.end()[-1] == 0 && vchTmp.end()[-2] >= 0x80)
110 vchTmp.erase(vchTmp.end()-1);
111
112 // Restore leading zeros
113 int nLeadingZeros = 0;
114 for (const char* p = psz; *p == pszBase58[0]; p++)
115 nLeadingZeros++;
116 vchRet.assign(nLeadingZeros + vchTmp.size(), 0);
117
118 // Convert little endian data to big endian
119 reverse_copy(vchTmp.begin(), vchTmp.end(), vchRet.end() - vchTmp.size());
120 return true;
121}
122
d825e6a3 123// Decode a base58-encoded string str into byte vector vchRet
e7494052 124// returns true if decoding is successful
223b6f1b 125inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
0a61b0df 126{
127 return DecodeBase58(str.c_str(), vchRet);
128}
129
130
131
132
d825e6a3 133// Encode a byte vector to a base58-encoded string, including checksum
223b6f1b 134inline std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
0a61b0df 135{
136 // add 4-byte hash check to the end
223b6f1b 137 std::vector<unsigned char> vch(vchIn);
0a61b0df 138 uint256 hash = Hash(vch.begin(), vch.end());
139 vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
140 return EncodeBase58(vch);
141}
142
d825e6a3 143// Decode a base58-encoded string psz that includes a checksum, into byte vector vchRet
e7494052 144// returns true if decoding is successful
223b6f1b 145inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
0a61b0df 146{
147 if (!DecodeBase58(psz, vchRet))
148 return false;
149 if (vchRet.size() < 4)
150 {
151 vchRet.clear();
152 return false;
153 }
154 uint256 hash = Hash(vchRet.begin(), vchRet.end()-4);
155 if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
156 {
157 vchRet.clear();
158 return false;
159 }
160 vchRet.resize(vchRet.size()-4);
161 return true;
162}
163
d825e6a3 164// Decode a base58-encoded string str that includes a checksum, into byte vector vchRet
e7494052 165// returns true if decoding is successful
223b6f1b 166inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
0a61b0df 167{
168 return DecodeBase58Check(str.c_str(), vchRet);
169}
170
171
172
173
174
6b8de05d 175/** Base class for all base58-encoded data */
cb61b8dc 176class CBase58Data
0a61b0df 177{
2ffba736 178protected:
d825e6a3 179 // the version byte
2ffba736 180 unsigned char nVersion;
d825e6a3
PW
181
182 // the actually encoded data
d0b0925b
PK
183 typedef std::vector<unsigned char, zero_after_free_allocator<unsigned char> > vector_uchar;
184 vector_uchar vchData;
0a61b0df 185
cb61b8dc 186 CBase58Data()
2ffba736 187 {
cb61b8dc
PW
188 nVersion = 0;
189 vchData.clear();
190 }
191
cb61b8dc
PW
192 void SetData(int nVersionIn, const void* pdata, size_t nSize)
193 {
194 nVersion = nVersionIn;
195 vchData.resize(nSize);
03f8b545
AJ
196 if (!vchData.empty())
197 memcpy(&vchData[0], pdata, nSize);
cb61b8dc
PW
198 }
199
200 void SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend)
201 {
202 SetData(nVersionIn, (void*)pbegin, pend - pbegin);
2ffba736 203 }
0a61b0df 204
cb61b8dc
PW
205public:
206 bool SetString(const char* psz)
2ffba736
PW
207 {
208 std::vector<unsigned char> vchTemp;
cb61b8dc 209 DecodeBase58Check(psz, vchTemp);
2ffba736
PW
210 if (vchTemp.empty())
211 {
212 vchData.clear();
213 nVersion = 0;
214 return false;
215 }
216 nVersion = vchTemp[0];
217 vchData.resize(vchTemp.size() - 1);
03f8b545
AJ
218 if (!vchData.empty())
219 memcpy(&vchData[0], &vchTemp[1], vchData.size());
0f8a6477 220 OPENSSL_cleanse(&vchTemp[0], vchData.size());
2ffba736
PW
221 return true;
222 }
0a61b0df 223
cb61b8dc
PW
224 bool SetString(const std::string& str)
225 {
226 return SetString(str.c_str());
227 }
228
229 std::string ToString() const
2ffba736 230 {
cb61b8dc
PW
231 std::vector<unsigned char> vch(1, nVersion);
232 vch.insert(vch.end(), vchData.begin(), vchData.end());
233 return EncodeBase58Check(vch);
2ffba736 234 }
0a61b0df 235
cb61b8dc 236 int CompareTo(const CBase58Data& b58) const
2ffba736 237 {
cb61b8dc 238 if (nVersion < b58.nVersion) return -1;
03f8b545 239 if (nVersion > b58.nVersion) return 1;
cb61b8dc
PW
240 if (vchData < b58.vchData) return -1;
241 if (vchData > b58.vchData) return 1;
242 return 0;
243 }
244
245 bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; }
246 bool operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; }
247 bool operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; }
248 bool operator< (const CBase58Data& b58) const { return CompareTo(b58) < 0; }
249 bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; }
250};
251
ff0ee876 252/** base58-encoded Bitcoin addresses.
6b8de05d
PW
253 * Public-key-hash-addresses have version 0 (or 111 testnet).
254 * The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
255 * Script-hash-addresses have version 5 (or 196 testnet).
256 * The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
257 */
10254401
PW
258class CBitcoinAddress;
259class CBitcoinAddressVisitor : public boost::static_visitor<bool>
260{
261private:
262 CBitcoinAddress *addr;
263public:
264 CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { }
265 bool operator()(const CKeyID &id) const;
266 bool operator()(const CScriptID &id) const;
267 bool operator()(const CNoDestination &no) const;
268};
269
cb61b8dc
PW
270class CBitcoinAddress : public CBase58Data
271{
272public:
9e470585 273 enum
cb61b8dc 274 {
9e470585
GA
275 PUBKEY_ADDRESS = 0,
276 SCRIPT_ADDRESS = 5,
ce336fdc 277 PUBKEY_ADDRESS_TEST = 111,
9e470585
GA
278 SCRIPT_ADDRESS_TEST = 196,
279 };
280
10254401
PW
281 bool Set(const CKeyID &id) {
282 SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &id, 20);
9e470585 283 return true;
cb61b8dc
PW
284 }
285
10254401
PW
286 bool Set(const CScriptID &id) {
287 SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &id, 20);
288 return true;
2ffba736
PW
289 }
290
10254401 291 bool Set(const CTxDestination &dest)
e679ec96 292 {
10254401 293 return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
e679ec96
GA
294 }
295
2ffba736
PW
296 bool IsValid() const
297 {
9fb89c26 298 unsigned int nExpectedSize = 20;
2ffba736
PW
299 bool fExpectTestNet = false;
300 switch(nVersion)
301 {
9e470585 302 case PUBKEY_ADDRESS:
e679ec96
GA
303 nExpectedSize = 20; // Hash of public key
304 fExpectTestNet = false;
305 break;
9e470585 306 case SCRIPT_ADDRESS:
922e8e29 307 nExpectedSize = 20; // Hash of CScript
e679ec96 308 fExpectTestNet = false;
2ffba736
PW
309 break;
310
9e470585 311 case PUBKEY_ADDRESS_TEST:
e679ec96
GA
312 nExpectedSize = 20;
313 fExpectTestNet = true;
314 break;
9e470585 315 case SCRIPT_ADDRESS_TEST:
e679ec96 316 nExpectedSize = 20;
2ffba736
PW
317 fExpectTestNet = true;
318 break;
0a61b0df 319
2ffba736
PW
320 default:
321 return false;
322 }
323 return fExpectTestNet == fTestNet && vchData.size() == nExpectedSize;
324 }
0a61b0df 325
2ffba736
PW
326 CBitcoinAddress()
327 {
2ffba736
PW
328 }
329
10254401 330 CBitcoinAddress(const CTxDestination &dest)
2ffba736 331 {
10254401 332 Set(dest);
2ffba736 333 }
0a61b0df 334
2ffba736
PW
335 CBitcoinAddress(const std::string& strAddress)
336 {
cb61b8dc 337 SetString(strAddress);
2ffba736
PW
338 }
339
340 CBitcoinAddress(const char* pszAddress)
341 {
cb61b8dc 342 SetString(pszAddress);
2ffba736
PW
343 }
344
10254401
PW
345 CTxDestination Get() const {
346 if (!IsValid())
347 return CNoDestination();
348 switch (nVersion) {
349 case PUBKEY_ADDRESS:
350 case PUBKEY_ADDRESS_TEST: {
351 uint160 id;
352 memcpy(&id, &vchData[0], 20);
353 return CKeyID(id);
354 }
355 case SCRIPT_ADDRESS:
356 case SCRIPT_ADDRESS_TEST: {
357 uint160 id;
358 memcpy(&id, &vchData[0], 20);
359 return CScriptID(id);
360 }
361 }
362 return CNoDestination();
363 }
364
365 bool GetKeyID(CKeyID &keyID) const {
366 if (!IsValid())
367 return false;
368 switch (nVersion) {
369 case PUBKEY_ADDRESS:
370 case PUBKEY_ADDRESS_TEST: {
371 uint160 id;
372 memcpy(&id, &vchData[0], 20);
373 keyID = CKeyID(id);
374 return true;
375 }
376 default: return false;
377 }
378 }
379
380 bool IsScript() const {
381 if (!IsValid())
382 return false;
383 switch (nVersion) {
384 case SCRIPT_ADDRESS:
385 case SCRIPT_ADDRESS_TEST: {
386 return true;
387 }
388 default: return false;
389 }
2ffba736 390 }
2ffba736 391};
223b6f1b 392
10254401
PW
393bool inline CBitcoinAddressVisitor::operator()(const CKeyID &id) const { return addr->Set(id); }
394bool inline CBitcoinAddressVisitor::operator()(const CScriptID &id) const { return addr->Set(id); }
395bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const { return false; }
396
6b8de05d 397/** A base58-encoded secret key */
15a8590e
PW
398class CBitcoinSecret : public CBase58Data
399{
400public:
11529c6e 401 void SetSecret(const CSecret& vchSecret, bool fCompressed)
ea0796bd 402 {
11529c6e 403 assert(vchSecret.size() == 32);
15a8590e 404 SetData(fTestNet ? 239 : 128, &vchSecret[0], vchSecret.size());
11529c6e
PW
405 if (fCompressed)
406 vchData.push_back(1);
15a8590e
PW
407 }
408
11529c6e 409 CSecret GetSecret(bool &fCompressedOut)
15a8590e
PW
410 {
411 CSecret vchSecret;
11529c6e
PW
412 vchSecret.resize(32);
413 memcpy(&vchSecret[0], &vchData[0], 32);
414 fCompressedOut = vchData.size() == 33;
15a8590e
PW
415 return vchSecret;
416 }
417
418 bool IsValid() const
419 {
15a8590e
PW
420 bool fExpectTestNet = false;
421 switch(nVersion)
422 {
423 case 128:
424 break;
425
426 case 239:
427 fExpectTestNet = true;
428 break;
429
430 default:
431 return false;
432 }
11529c6e 433 return fExpectTestNet == fTestNet && (vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1));
15a8590e
PW
434 }
435
b3a6e613
CM
436 bool SetString(const char* pszSecret)
437 {
438 return CBase58Data::SetString(pszSecret) && IsValid();
439 }
440
441 bool SetString(const std::string& strSecret)
442 {
443 return SetString(strSecret.c_str());
444 }
445
11529c6e 446 CBitcoinSecret(const CSecret& vchSecret, bool fCompressed)
15a8590e 447 {
11529c6e 448 SetSecret(vchSecret, fCompressed);
15a8590e
PW
449 }
450
451 CBitcoinSecret()
452 {
453 }
454};
455
d0b0925b 456#endif // BITCOIN_BASE58_H
This page took 0.144917 seconds and 4 git commands to generate.