Feathercoin  0.5.0
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
base58.h
Go to the documentation of this file.
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 #ifndef BITCOIN_BASE58_H
16 #define BITCOIN_BASE58_H
17 
18 #include <string>
19 #include <vector>
20 
21 #include "bignum.h"
22 #include "key.h"
23 #include "script.h"
24 #include "allocators.h"
25 
26 static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
27 
28 // Encode a byte sequence as a base58-encoded string
29 inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
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
37  std::vector<unsigned char> vchTmp(pend-pbegin+1, 0);
38  reverse_copy(pbegin, pend, vchTmp.begin());
39 
40  // Convert little endian data to bignum
41  CBigNum bn;
42  bn.setvch(vchTmp);
43 
44  // Convert bignum to std::string
45  std::string str;
46  // Expected size increase from base58 conversion is approximately 137%
47  // use 138% to be safe
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 
64  // Convert little endian std::string to big endian
65  reverse(str.begin(), str.end());
66  return str;
67 }
68 
69 // Encode a byte vector as a base58-encoded string
70 inline std::string EncodeBase58(const std::vector<unsigned char>& vch)
71 {
72  return EncodeBase58(&vch[0], &vch[0] + vch.size());
73 }
74 
75 // Decode a base58-encoded string psz into byte vector vchRet
76 // returns true if decoding is successful
77 inline bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet)
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
106  std::vector<unsigned char> vchTmp = bn.getvch();
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 
123 // Decode a base58-encoded string str into byte vector vchRet
124 // returns true if decoding is successful
125 inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
126 {
127  return DecodeBase58(str.c_str(), vchRet);
128 }
129 
130 
131 
132 
133 // Encode a byte vector to a base58-encoded string, including checksum
134 inline std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
135 {
136  // add 4-byte hash check to the end
137  std::vector<unsigned char> vch(vchIn);
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 
143 // Decode a base58-encoded string psz that includes a checksum, into byte vector vchRet
144 // returns true if decoding is successful
145 inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
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 
164 // Decode a base58-encoded string str that includes a checksum, into byte vector vchRet
165 // returns true if decoding is successful
166 inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
167 {
168  return DecodeBase58Check(str.c_str(), vchRet);
169 }
170 
171 
172 
173 
174 
177 {
178 protected:
179  // the version byte
180  unsigned char nVersion;
181 
182  // the actually encoded data
183  typedef std::vector<unsigned char, zero_after_free_allocator<unsigned char> > vector_uchar;
184  vector_uchar vchData;
185 
187  {
188  nVersion = 0;
189  vchData.clear();
190  }
191 
192  void SetData(int nVersionIn, const void* pdata, size_t nSize)
193  {
194  nVersion = nVersionIn;
195  vchData.resize(nSize);
196  if (!vchData.empty())
197  memcpy(&vchData[0], pdata, nSize);
198  }
199 
200  void SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend)
201  {
202  SetData(nVersionIn, (void*)pbegin, pend - pbegin);
203  }
204 
205 public:
206  bool SetString(const char* psz)
207  {
208  std::vector<unsigned char> vchTemp;
209  DecodeBase58Check(psz, vchTemp);
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);
218  if (!vchData.empty())
219  memcpy(&vchData[0], &vchTemp[1], vchData.size());
220  OPENSSL_cleanse(&vchTemp[0], vchData.size());
221  return true;
222  }
223 
224  bool SetString(const std::string& str)
225  {
226  return SetString(str.c_str());
227  }
228 
229  std::string ToString() const
230  {
231  std::vector<unsigned char> vch(1, nVersion);
232  vch.insert(vch.end(), vchData.begin(), vchData.end());
233  return EncodeBase58Check(vch);
234  }
235 
236  int CompareTo(const CBase58Data& b58) const
237  {
238  if (nVersion < b58.nVersion) return -1;
239  if (nVersion > b58.nVersion) return 1;
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 
258 class CBitcoinAddress;
259 class CBitcoinAddressVisitor : public boost::static_visitor<bool>
260 {
261 private:
263 public:
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 
271 {
272 public:
273  enum
274  {
279  };
280 
281  bool Set(const CKeyID &id) {
283  return true;
284  }
285 
286  bool Set(const CScriptID &id) {
288  return true;
289  }
290 
291  bool Set(const CTxDestination &dest)
292  {
293  return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
294  }
295 
296  bool IsValid() const
297  {
298  unsigned int nExpectedSize = 20;
299  bool fExpectTestNet = false;
300  switch(nVersion)
301  {
302  case PUBKEY_ADDRESS:
303  nExpectedSize = 20; // Hash of public key
304  fExpectTestNet = false;
305  break;
306  case SCRIPT_ADDRESS:
307  nExpectedSize = 20; // Hash of CScript
308  fExpectTestNet = false;
309  break;
310 
311  case PUBKEY_ADDRESS_TEST:
312  nExpectedSize = 20;
313  fExpectTestNet = true;
314  break;
315  case SCRIPT_ADDRESS_TEST:
316  nExpectedSize = 20;
317  fExpectTestNet = true;
318  break;
319 
320  default:
321  return false;
322  }
323  return fExpectTestNet == fTestNet && vchData.size() == nExpectedSize;
324  }
325 
327  {
328  }
329 
331  {
332  Set(dest);
333  }
334 
335  CBitcoinAddress(const std::string& strAddress)
336  {
337  SetString(strAddress);
338  }
339 
340  CBitcoinAddress(const char* pszAddress)
341  {
342  SetString(pszAddress);
343  }
344 
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  }
390  }
391 };
392 
393 bool inline CBitcoinAddressVisitor::operator()(const CKeyID &id) const { return addr->Set(id); }
394 bool inline CBitcoinAddressVisitor::operator()(const CScriptID &id) const { return addr->Set(id); }
395 bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const { return false; }
396 
399 {
400 public:
401  enum
402  {
405  };
406 
407  void SetKey(const CKey& vchSecret)
408  {
409  assert(vchSecret.IsValid());
410  SetData(fTestNet ? PRIVKEY_ADDRESS_TEST : PRIVKEY_ADDRESS, vchSecret.begin(), vchSecret.size());
411  if (vchSecret.IsCompressed())
412  vchData.push_back(1);
413  }
414 
416  {
417  CKey ret;
418  ret.Set(&vchData[0], &vchData[32], vchData.size() > 32 && vchData[32] == 1);
419  return ret;
420  }
421 
422  bool IsValid() const
423  {
424  bool fExpectTestNet = false;
425  switch(nVersion)
426  {
427  case PRIVKEY_ADDRESS:
428  break;
429 
431  fExpectTestNet = true;
432  break;
433 
434  default:
435  return false;
436  }
437  return fExpectTestNet == fTestNet && (vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1));
438  }
439 
440  bool SetString(const char* pszSecret)
441  {
442  return CBase58Data::SetString(pszSecret) && IsValid();
443  }
444 
445  bool SetString(const std::string& strSecret)
446  {
447  return SetString(strSecret.c_str());
448  }
449 
450  CBitcoinSecret(const CKey& vchSecret)
451  {
452  SetKey(vchSecret);
453  }
454 
456  {
457  }
458 };
459 
460 #endif // BITCOIN_BASE58_H
void SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend)
Definition: base58.h:200
bool IsValid() const
Definition: base58.h:296
CBitcoinSecret()
Definition: base58.h:455
void SetKey(const CKey &vchSecret)
Definition: base58.h:407
const unsigned char * begin() const
Definition: key.h:222
bool IsScript() const
Definition: base58.h:380
unsigned char * end()
Definition: uint256.h:353
CKey GetKey()
Definition: base58.h:415
CBitcoinAddress * addr
Definition: base58.h:262
CBitcoinAddress(const CTxDestination &dest)
Definition: base58.h:330
unsigned char nVersion
Definition: base58.h:180
bool DecodeBase58(const char *psz, std::vector< unsigned char > &vchRet)
Definition: base58.h:77
CBitcoinAddressVisitor(CBitcoinAddress *addrIn)
Definition: base58.h:264
vector_uchar vchData
Definition: base58.h:184
unsigned long getulong() const
Definition: bignum.h:106
bool IsValid() const
Definition: base58.h:422
RAII encapsulated BN_CTX (OpenSSL bignum context)
Definition: bignum.h:23
bool DecodeBase58Check(const char *psz, std::vector< unsigned char > &vchRet)
Definition: base58.h:145
void setulong(unsigned long n)
Definition: bignum.h:100
CTxDestination Get() const
Definition: base58.h:345
bool GetKeyID(CKeyID &keyID) const
Definition: base58.h:365
bool IsValid() const
Definition: key.h:226
bool SetString(const char *pszSecret)
Definition: base58.h:440
std::vector< unsigned char, zero_after_free_allocator< unsigned char > > vector_uchar
Definition: base58.h:183
Base class for all base58-encoded data.
Definition: base58.h:176
bool IsCompressed() const
Definition: key.h:229
bool Set(const CKeyID &id)
Definition: base58.h:281
bool fTestNet
Definition: util.cpp:81
bool operator()(const CKeyID &id) const
Definition: base58.h:393
A base58-encoded secret key.
Definition: base58.h:398
bool SetString(const std::string &strSecret)
Definition: base58.h:445
bool operator==(const CBase58Data &b58) const
Definition: base58.h:245
C++ wrapper for BIGNUM (OpenSSL bignum)
Definition: bignum.h:51
std::vector< unsigned char > getvch() const
Definition: bignum.h:255
std::string ToString() const
Definition: base58.h:229
uint256 Hash(const T1 pbegin, const T1 pend)
Definition: hash.h:16
Errors thrown by the bignum class.
Definition: bignum.h:15
bool operator>(const CBase58Data &b58) const
Definition: base58.h:249
void Set(const T pbegin, const T pend, bool fCompressedIn)
Definition: key.h:206
CBase58Data()
Definition: base58.h:186
std::string EncodeBase58Check(const std::vector< unsigned char > &vchIn)
Definition: base58.h:134
bool SetString(const std::string &str)
Definition: base58.h:224
256-bit unsigned integer
Definition: uint256.h:537
CBitcoinSecret(const CKey &vchSecret)
Definition: base58.h:450
void setvch(const std::vector< unsigned char > &vch)
Definition: bignum.h:240
A reference to a CKey: the Hash160 of its serialized public key.
Definition: key.h:24
160-bit unsigned integer
Definition: uint256.h:422
bool Set(const CTxDestination &dest)
Definition: base58.h:291
bool SetString(const char *psz)
Definition: base58.h:206
std::string EncodeBase58(const unsigned char *pbegin, const unsigned char *pend)
Definition: base58.h:29
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: key.h:32
bool operator<(const CBase58Data &b58) const
Definition: base58.h:248
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: script.h:62
An encapsulated private key.
Definition: key.h:172
bool Set(const CScriptID &id)
Definition: base58.h:286
CBitcoinAddress(const char *pszAddress)
Definition: base58.h:340
void SetData(int nVersionIn, const void *pdata, size_t nSize)
Definition: base58.h:192
unsigned int size() const
Definition: key.h:221
CBitcoinAddress(const std::string &strAddress)
Definition: base58.h:335
int id
Definition: db_test.cc:1709
bool operator<=(const CBase58Data &b58) const
Definition: base58.h:246
uint32_t hash
Definition: cache.cc:34
int CompareTo(const CBase58Data &b58) const
Definition: base58.h:236
bool operator>=(const CBase58Data &b58) const
Definition: base58.h:247