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