Master Core  v0.0.9 - 2abfd2849db8ba7a83957c64eb976b406713c123
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
base58.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014 The Bitcoin developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include "base58.h"
6 
7 #include "hash.h"
8 #include "uint256.h"
9 
10 #include <assert.h>
11 #include <stdint.h>
12 #include <string.h>
13 #include <vector>
14 #include <string>
15 #include <boost/variant/apply_visitor.hpp>
16 #include <boost/variant/static_visitor.hpp>
17 
18 /* All alphanumeric characters except for "0", "I", "O", and "l" */
19 static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
20 
21 bool DecodeBase58(const char *psz, std::vector<unsigned char>& vch) {
22  // Skip leading spaces.
23  while (*psz && isspace(*psz))
24  psz++;
25  // Skip and count leading '1's.
26  int zeroes = 0;
27  while (*psz == '1') {
28  zeroes++;
29  psz++;
30  }
31  // Allocate enough space in big-endian base256 representation.
32  std::vector<unsigned char> b256(strlen(psz) * 733 / 1000 + 1); // log(58) / log(256), rounded up.
33  // Process the characters.
34  while (*psz && !isspace(*psz)) {
35  // Decode base58 character
36  const char *ch = strchr(pszBase58, *psz);
37  if (ch == NULL)
38  return false;
39  // Apply "b256 = b256 * 58 + ch".
40  int carry = ch - pszBase58;
41  for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); it != b256.rend(); it++) {
42  carry += 58 * (*it);
43  *it = carry % 256;
44  carry /= 256;
45  }
46  assert(carry == 0);
47  psz++;
48  }
49  // Skip trailing spaces.
50  while (isspace(*psz))
51  psz++;
52  if (*psz != 0)
53  return false;
54  // Skip leading zeroes in b256.
55  std::vector<unsigned char>::iterator it = b256.begin();
56  while (it != b256.end() && *it == 0)
57  it++;
58  // Copy result into output vector.
59  vch.reserve(zeroes + (b256.end() - it));
60  vch.assign(zeroes, 0x00);
61  while (it != b256.end())
62  vch.push_back(*(it++));
63  return true;
64 }
65 
66 std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend) {
67  // Skip & count leading zeroes.
68  int zeroes = 0;
69  while (pbegin != pend && *pbegin == 0) {
70  pbegin++;
71  zeroes++;
72  }
73  // Allocate enough space in big-endian base58 representation.
74  std::vector<unsigned char> b58((pend - pbegin) * 138 / 100 + 1); // log(256) / log(58), rounded up.
75  // Process the bytes.
76  while (pbegin != pend) {
77  int carry = *pbegin;
78  // Apply "b58 = b58 * 256 + ch".
79  for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); it != b58.rend(); it++) {
80  carry += 256 * (*it);
81  *it = carry % 58;
82  carry /= 58;
83  }
84  assert(carry == 0);
85  pbegin++;
86  }
87  // Skip leading zeroes in base58 result.
88  std::vector<unsigned char>::iterator it = b58.begin();
89  while (it != b58.end() && *it == 0)
90  it++;
91  // Translate the result into a string.
92  std::string str;
93  str.reserve(zeroes + (b58.end() - it));
94  str.assign(zeroes, '1');
95  while (it != b58.end())
96  str += pszBase58[*(it++)];
97  return str;
98 }
99 
100 std::string EncodeBase58(const std::vector<unsigned char>& vch) {
101  return EncodeBase58(&vch[0], &vch[0] + vch.size());
102 }
103 
104 bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet) {
105  return DecodeBase58(str.c_str(), vchRet);
106 }
107 
108 std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn) {
109  // add 4-byte hash check to the end
110  std::vector<unsigned char> vch(vchIn);
111  uint256 hash = Hash(vch.begin(), vch.end());
112  vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
113  return EncodeBase58(vch);
114 }
115 
116 bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet) {
117  if (!DecodeBase58(psz, vchRet) ||
118  (vchRet.size() < 4))
119  {
120  vchRet.clear();
121  return false;
122  }
123  // re-calculate the checksum, insure it matches the included 4-byte checksum
124  uint256 hash = Hash(vchRet.begin(), vchRet.end()-4);
125  if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
126  {
127  vchRet.clear();
128  return false;
129  }
130  vchRet.resize(vchRet.size()-4);
131  return true;
132 }
133 
134 bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet) {
135  return DecodeBase58Check(str.c_str(), vchRet);
136 }
137 
139  vchVersion.clear();
140  vchData.clear();
141 }
142 
143 void CBase58Data::SetData(const std::vector<unsigned char> &vchVersionIn, const void* pdata, size_t nSize) {
144  vchVersion = vchVersionIn;
145  vchData.resize(nSize);
146  if (!vchData.empty())
147  memcpy(&vchData[0], pdata, nSize);
148 }
149 
150 void CBase58Data::SetData(const std::vector<unsigned char> &vchVersionIn, const unsigned char *pbegin, const unsigned char *pend) {
151  SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
152 }
153 
154 bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes) {
155  std::vector<unsigned char> vchTemp;
156  bool rc58 = DecodeBase58Check(psz, vchTemp);
157  if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
158  vchData.clear();
159  vchVersion.clear();
160  return false;
161  }
162  vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
163  vchData.resize(vchTemp.size() - nVersionBytes);
164  if (!vchData.empty())
165  memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size());
166  OPENSSL_cleanse(&vchTemp[0], vchData.size());
167  return true;
168 }
169 
170 bool CBase58Data::SetString(const std::string& str) {
171  return SetString(str.c_str());
172 }
173 
174 std::string CBase58Data::ToString() const {
175  std::vector<unsigned char> vch = vchVersion;
176  vch.insert(vch.end(), vchData.begin(), vchData.end());
177  return EncodeBase58Check(vch);
178 }
179 
180 int CBase58Data::CompareTo(const CBase58Data& b58) const {
181  if (vchVersion < b58.vchVersion) return -1;
182  if (vchVersion > b58.vchVersion) return 1;
183  if (vchData < b58.vchData) return -1;
184  if (vchData > b58.vchData) return 1;
185  return 0;
186 }
187 
188 namespace {
189  class CBitcoinAddressVisitor : public boost::static_visitor<bool> {
190  private:
191  CBitcoinAddress *addr;
192  public:
193  CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { }
194 
195  bool operator()(const CKeyID &id) const { return addr->Set(id); }
196  bool operator()(const CScriptID &id) const { return addr->Set(id); }
197  bool operator()(const CNoDestination &no) const { return false; }
198  };
199 };
200 
201 bool CBitcoinAddress::Set(const CKeyID &id) {
202  SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
203  return true;
204 }
205 
207  SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
208  return true;
209 }
210 
212  return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
213 }
214 
216  bool fCorrectSize = vchData.size() == 20;
217  bool fKnownVersion = vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
219  return fCorrectSize && fKnownVersion;
220 }
221 
223  if (!IsValid())
224  return CNoDestination();
225  uint160 id;
226  memcpy(&id, &vchData[0], 20);
227  if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
228  return CKeyID(id);
229  else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
230  return CScriptID(id);
231  else
232  return CNoDestination();
233 }
234 
235 bool CBitcoinAddress::GetKeyID(CKeyID &keyID) const {
236  if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
237  return false;
238  uint160 id;
239  memcpy(&id, &vchData[0], 20);
240  keyID = CKeyID(id);
241  return true;
242 }
243 
246 }
247 
248 void CBitcoinSecret::SetKey(const CKey& vchSecret) {
249  assert(vchSecret.IsValid());
250  SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
251  if (vchSecret.IsCompressed())
252  vchData.push_back(1);
253 }
254 
256  CKey ret;
257  ret.Set(&vchData[0], &vchData[32], vchData.size() > 32 && vchData[32] == 1);
258  return ret;
259 }
260 
262  bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
263  bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
264  return fExpectedFormat && fCorrectVersion;
265 }
266 
267 bool CBitcoinSecret::SetString(const char* pszSecret) {
268  return CBase58Data::SetString(pszSecret) && IsValid();
269 }
270 
271 bool CBitcoinSecret::SetString(const std::string& strSecret) {
272  return SetString(strSecret.c_str());
273 }
bool DecodeBase58(const char *psz, std::vector< unsigned char > &vch)
Decode a base58-encoded string (psz) into a byte vector (vchRet).
Definition: base58.cpp:21
bool IsValid() const
Definition: base58.cpp:215
void SetKey(const CKey &vchSecret)
Definition: base58.cpp:248
const unsigned char * begin() const
Definition: key.h:234
bool IsScript() const
Definition: base58.cpp:244
CKey GetKey()
Definition: base58.cpp:255
std::string EncodeBase58(const unsigned char *pbegin, const unsigned char *pend)
Encode a byte sequence as a base58-encoded string.
Definition: base58.cpp:66
vector_uchar vchData
Definition: base58.h:76
bool IsValid() const
Definition: base58.cpp:261
base58-encoded Bitcoin addresses.
Definition: base58.h:101
void SetData(const std::vector< unsigned char > &vchVersionIn, const void *pdata, size_t nSize)
Definition: base58.cpp:143
CTxDestination Get() const
Definition: base58.cpp:222
const std::vector< unsigned char > & Base58Prefix(Base58Type type) const
Definition: chainparams.h:66
bool GetKeyID(CKeyID &keyID) const
Definition: base58.cpp:235
bool IsValid() const
Definition: key.h:238
bool SetString(const char *pszSecret)
Definition: base58.cpp:267
Base class for all base58-encoded data.
Definition: base58.h:68
bool IsCompressed() const
Definition: key.h:241
bool Set(const CKeyID &id)
Definition: base58.cpp:201
bool DecodeBase58Check(const char *psz, std::vector< unsigned char > &vchRet)
Decode a base58-encoded string (psz) that includes a checksum into a byte vector (vchRet), return true if decoding is successful.
Definition: base58.cpp:116
std::string ToString() const
Definition: base58.cpp:174
uint256 Hash(const T1 pbegin, const T1 pend)
Definition: hash.h:19
static const char * pszBase58
Definition: base58.cpp:19
void Set(const T pbegin, const T pend, bool fCompressedIn)
Definition: key.h:218
bool SetString(const char *psz, unsigned int nVersionBytes=1)
Definition: base58.cpp:154
256-bit unsigned integer
Definition: uint256.h:531
const CChainParams & Params()
Return the currently selected parameters.
void * memcpy(void *a, const void *b, size_t c)
Definition: glibc_compat.cpp:7
A reference to a CKey: the Hash160 of its serialized public key.
Definition: key.h:26
160-bit unsigned integer
Definition: uint256.h:419
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: key.h:34
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: script.h:218
An encapsulated private key.
Definition: key.h:179
unsigned int size() const
Definition: key.h:233
std::string EncodeBase58Check(const std::vector< unsigned char > &vchIn)
Encode a byte vector into a base58-encoded string, including checksum.
Definition: base58.cpp:108
std::vector< unsigned char > vchVersion
Definition: base58.h:72
int CompareTo(const CBase58Data &b58) const
Definition: base58.cpp:180