]> Git Repo - VerusCoin.git/blob - src/base58.h
Merge pull request #3637
[VerusCoin.git] / src / base58.h
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2013 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 // Why base-58 instead of standard base-64 encoding?
8 // - Don't want 0OIl characters that look the same in some fonts and
9 //      could be used to create visually identical looking account numbers.
10 // - A string with non-alphanumeric characters is not as easily accepted as an account number.
11 // - E-mail usually won't line-break if there's no punctuation to break at.
12 // - Double-clicking selects the whole number as one word if it's all alphanumeric.
13 //
14 #ifndef BITCOIN_BASE58_H
15 #define BITCOIN_BASE58_H
16
17 #include "chainparams.h"
18 #include "hash.h"
19 #include "key.h"
20 #include "script.h"
21 #include "uint256.h"
22
23 #include <string>
24 #include <vector>
25
26 #include <boost/variant/apply_visitor.hpp>
27 #include <boost/variant/static_visitor.hpp>
28
29 /**
30  * Encode a byte sequence as a base58-encoded string.
31  * pbegin and pend cannot be NULL, unless both are.
32  */
33 std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend);
34
35 /**
36  * Encode a byte vector as a base58-encoded string
37  */
38 inline std::string EncodeBase58(const std::vector<unsigned char>& vch)
39 {
40     return EncodeBase58(&vch[0], &vch[0] + vch.size());
41 }
42
43 /**
44  * Decode a base58-encoded string (psz) into a byte vector (vchRet).
45  * return true if decoding is successful.
46  * psz cannot be NULL.
47  */
48 bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet);
49
50 /**
51  * Decode a base58-encoded string (str) into a byte vector (vchRet).
52  * return true if decoding is successful.
53  */
54 inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
55 {
56     return DecodeBase58(str.c_str(), vchRet);
57 }
58
59 /**
60  * Encode a byte vector into a base58-encoded string, including checksum
61  */
62 inline std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
63 {
64     // add 4-byte hash check to the end
65     std::vector<unsigned char> vch(vchIn);
66     uint256 hash = Hash(vch.begin(), vch.end());
67     vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
68     return EncodeBase58(vch);
69 }
70
71 /**
72  * Decode a base58-encoded string (psz) that includes a checksum into a byte
73  * vector (vchRet), return true if decoding is successful
74  */
75 inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
76 {
77     if (!DecodeBase58(psz, vchRet))
78         return false;
79     if (vchRet.size() < 4)
80     {
81         vchRet.clear();
82         return false;
83     }
84     // re-calculate the checksum, insure it matches the included 4-byte checksum
85     uint256 hash = Hash(vchRet.begin(), vchRet.end()-4);
86     if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
87     {
88         vchRet.clear();
89         return false;
90     }
91     vchRet.resize(vchRet.size()-4);
92     return true;
93 }
94
95 /**
96  * Decode a base58-encoded string (str) that includes a checksum into a byte
97  * vector (vchRet), return true if decoding is successful
98  */
99 inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
100 {
101     return DecodeBase58Check(str.c_str(), vchRet);
102 }
103
104 /**
105  * Base class for all base58-encoded data
106  */
107 class CBase58Data
108 {
109 protected:
110     // the version byte(s)
111     std::vector<unsigned char> vchVersion;
112
113     // the actually encoded data
114     typedef std::vector<unsigned char, zero_after_free_allocator<unsigned char> > vector_uchar;
115     vector_uchar vchData;
116
117     CBase58Data()
118     {
119         vchVersion.clear();
120         vchData.clear();
121     }
122
123     void SetData(const std::vector<unsigned char> &vchVersionIn, const void* pdata, size_t nSize)
124     {
125         vchVersion = vchVersionIn;
126         vchData.resize(nSize);
127         if (!vchData.empty())
128             memcpy(&vchData[0], pdata, nSize);
129     }
130
131     void SetData(const std::vector<unsigned char> &vchVersionIn, const unsigned char *pbegin, const unsigned char *pend)
132     {
133         SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
134     }
135
136 public:
137     bool SetString(const char* psz, unsigned int nVersionBytes = 1)
138     {
139         std::vector<unsigned char> vchTemp;
140         DecodeBase58Check(psz, vchTemp);
141         if (vchTemp.size() < nVersionBytes)
142         {
143             vchData.clear();
144             vchVersion.clear();
145             return false;
146         }
147         vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
148         vchData.resize(vchTemp.size() - nVersionBytes);
149         if (!vchData.empty())
150             memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size());
151         OPENSSL_cleanse(&vchTemp[0], vchData.size());
152         return true;
153     }
154
155     bool SetString(const std::string& str)
156     {
157         return SetString(str.c_str());
158     }
159
160     std::string ToString() const
161     {
162         std::vector<unsigned char> vch = vchVersion;
163         vch.insert(vch.end(), vchData.begin(), vchData.end());
164         return EncodeBase58Check(vch);
165     }
166
167     int CompareTo(const CBase58Data& b58) const
168     {
169         if (vchVersion < b58.vchVersion) return -1;
170         if (vchVersion > b58.vchVersion) return  1;
171         if (vchData < b58.vchData)   return -1;
172         if (vchData > b58.vchData)   return  1;
173         return 0;
174     }
175
176     bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; }
177     bool operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; }
178     bool operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; }
179     bool operator< (const CBase58Data& b58) const { return CompareTo(b58) <  0; }
180     bool operator> (const CBase58Data& b58) const { return CompareTo(b58) >  0; }
181 };
182
183 /** base58-encoded Bitcoin addresses.
184  * Public-key-hash-addresses have version 0 (or 111 testnet).
185  * The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
186  * Script-hash-addresses have version 5 (or 196 testnet).
187  * The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
188  */
189 class CBitcoinAddress;
190 class CBitcoinAddressVisitor : public boost::static_visitor<bool>
191 {
192 private:
193     CBitcoinAddress *addr;
194 public:
195     CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { }
196     bool operator()(const CKeyID &id) const;
197     bool operator()(const CScriptID &id) const;
198     bool operator()(const CNoDestination &no) const;
199 };
200
201 class CBitcoinAddress : public CBase58Data
202 {
203 public:
204     bool Set(const CKeyID &id) {
205         SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
206         return true;
207     }
208
209     bool Set(const CScriptID &id) {
210         SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
211         return true;
212     }
213
214     bool Set(const CTxDestination &dest)
215     {
216         return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
217     }
218
219     bool IsValid() const
220     {
221         bool fCorrectSize = vchData.size() == 20;
222         bool fKnownVersion = vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
223                              vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
224         return fCorrectSize && fKnownVersion;
225     }
226
227     CBitcoinAddress()
228     {
229     }
230
231     CBitcoinAddress(const CTxDestination &dest)
232     {
233         Set(dest);
234     }
235
236     CBitcoinAddress(const std::string& strAddress)
237     {
238         SetString(strAddress);
239     }
240
241     CBitcoinAddress(const char* pszAddress)
242     {
243         SetString(pszAddress);
244     }
245
246     CTxDestination Get() const {
247         if (!IsValid())
248             return CNoDestination();
249         uint160 id;
250         memcpy(&id, &vchData[0], 20);
251         if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
252             return CKeyID(id);
253         else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
254             return CScriptID(id);
255         else
256             return CNoDestination();
257     }
258
259     bool GetKeyID(CKeyID &keyID) const {
260         if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
261             return false;
262         uint160 id;
263         memcpy(&id, &vchData[0], 20);
264         keyID = CKeyID(id);
265         return true;
266     }
267
268     bool IsScript() const {
269         return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
270     }
271 };
272
273 bool inline CBitcoinAddressVisitor::operator()(const CKeyID &id) const         { return addr->Set(id); }
274 bool inline CBitcoinAddressVisitor::operator()(const CScriptID &id) const      { return addr->Set(id); }
275 bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const { return false; }
276
277 /**
278  * A base58-encoded secret key
279  */
280 class CBitcoinSecret : public CBase58Data
281 {
282 public:
283     void SetKey(const CKey& vchSecret)
284     {
285         assert(vchSecret.IsValid());
286         SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
287         if (vchSecret.IsCompressed())
288             vchData.push_back(1);
289     }
290
291     CKey GetKey()
292     {
293         CKey ret;
294         ret.Set(&vchData[0], &vchData[32], vchData.size() > 32 && vchData[32] == 1);
295         return ret;
296     }
297
298     bool IsValid() const
299     {
300         bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
301         bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
302         return fExpectedFormat && fCorrectVersion;
303     }
304
305     bool SetString(const char* pszSecret)
306     {
307         return CBase58Data::SetString(pszSecret) && IsValid();
308     }
309
310     bool SetString(const std::string& strSecret)
311     {
312         return SetString(strSecret.c_str());
313     }
314
315     CBitcoinSecret(const CKey& vchSecret)
316     {
317         SetKey(vchSecret);
318     }
319
320     CBitcoinSecret()
321     {
322     }
323 };
324
325 template<typename K, int Size, CChainParams::Base58Type Type> class CBitcoinExtKeyBase : public CBase58Data
326 {
327 public:
328     void SetKey(const K &key) {
329         unsigned char vch[Size];
330         key.Encode(vch);
331         SetData(Params().Base58Prefix(Type), vch, vch+Size);
332     }
333
334     K GetKey() {
335         K ret;
336         ret.Decode(&vchData[0], &vchData[Size]);
337         return ret;
338     }
339
340     CBitcoinExtKeyBase(const K &key) {
341         SetKey(key);
342     }
343
344     CBitcoinExtKeyBase() {}
345 };
346
347 typedef CBitcoinExtKeyBase<CExtKey, 74, CChainParams::EXT_SECRET_KEY> CBitcoinExtKey;
348 typedef CBitcoinExtKeyBase<CExtPubKey, 74, CChainParams::EXT_PUBLIC_KEY> CBitcoinExtPubKey;
349
350 #endif // BITCOIN_BASE58_H
This page took 0.043977 seconds and 4 git commands to generate.