Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

base58.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2015 The Bitcoin Core developers
2 // Distributed under the MIT 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 
19 static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
20 
21 bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
22 {
23  // Skip leading spaces.
24  while (*psz && isspace(*psz))
25  psz++;
26  // Skip and count leading '1's.
27  int zeroes = 0;
28  int length = 0;
29  while (*psz == '1') {
30  zeroes++;
31  psz++;
32  }
33  // Allocate enough space in big-endian base256 representation.
34  int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up.
35  std::vector<unsigned char> b256(size);
36  // Process the characters.
37  while (*psz && !isspace(*psz)) {
38  // Decode base58 character
39  const char* ch = strchr(pszBase58, *psz);
40  if (ch == nullptr)
41  return false;
42  // Apply "b256 = b256 * 58 + ch".
43  int carry = ch - pszBase58;
44  int i = 0;
45  for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
46  carry += 58 * (*it);
47  *it = carry % 256;
48  carry /= 256;
49  }
50  assert(carry == 0);
51  length = i;
52  psz++;
53  }
54  // Skip trailing spaces.
55  while (isspace(*psz))
56  psz++;
57  if (*psz != 0)
58  return false;
59  // Skip leading zeroes in b256.
60  std::vector<unsigned char>::iterator it = b256.begin() + (size - length);
61  while (it != b256.end() && *it == 0)
62  it++;
63  // Copy result into output vector.
64  vch.reserve(zeroes + (b256.end() - it));
65  vch.assign(zeroes, 0x00);
66  while (it != b256.end())
67  vch.push_back(*(it++));
68  return true;
69 }
70 
71 std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
72 {
73  // Skip & count leading zeroes.
74  int zeroes = 0;
75  int length = 0;
76  while (pbegin != pend && *pbegin == 0) {
77  pbegin++;
78  zeroes++;
79  }
80  // Allocate enough space in big-endian base58 representation.
81  int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up.
82  std::vector<unsigned char> b58(size);
83  // Process the bytes.
84  while (pbegin != pend) {
85  int carry = *pbegin;
86  int i = 0;
87  // Apply "b58 = b58 * 256 + ch".
88  for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
89  carry += 256 * (*it);
90  *it = carry % 58;
91  carry /= 58;
92  }
93 
94  assert(carry == 0);
95  length = i;
96  pbegin++;
97  }
98  // Skip leading zeroes in base58 result.
99  std::vector<unsigned char>::iterator it = b58.begin() + (size - length);
100  while (it != b58.end() && *it == 0)
101  it++;
102  // Translate the result into a string.
103  std::string str;
104  str.reserve(zeroes + (b58.end() - it));
105  str.assign(zeroes, '1');
106  while (it != b58.end())
107  str += pszBase58[*(it++)];
108  return str;
109 }
110 
111 std::string EncodeBase58(const std::vector<unsigned char>& vch)
112 {
113  return EncodeBase58(vch.data(), vch.data() + vch.size());
114 }
115 
116 bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
117 {
118  return DecodeBase58(str.c_str(), vchRet);
119 }
120 
121 std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
122 {
123  // add 4-byte hash check to the end
124  std::vector<unsigned char> vch(vchIn);
125  uint256 hash = Hash(vch.begin(), vch.end());
126  vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
127  return EncodeBase58(vch);
128 }
129 
130 bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
131 {
132  if (!DecodeBase58(psz, vchRet) ||
133  (vchRet.size() < 4)) {
134  vchRet.clear();
135  return false;
136  }
137  // re-calculate the checksum, ensure it matches the included 4-byte checksum
138  uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4);
139  if (memcmp(&hash, &vchRet[vchRet.size() - 4], 4) != 0) {
140  vchRet.clear();
141  return false;
142  }
143  vchRet.resize(vchRet.size() - 4);
144  return true;
145 }
146 
147 bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
148 {
149  return DecodeBase58Check(str.c_str(), vchRet);
150 }
151 
153 {
154  vchVersion.clear();
155  vchData.clear();
156 }
157 
158 void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const void* pdata, size_t nSize)
159 {
160  vchVersion = vchVersionIn;
161  vchData.resize(nSize);
162  if (!vchData.empty())
163  memcpy(vchData.data(), pdata, nSize);
164 }
165 
166 void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend)
167 {
168  SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
169 }
170 
171 bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes)
172 {
173  std::vector<unsigned char> vchTemp;
174  bool rc58 = DecodeBase58Check(psz, vchTemp);
175  if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
176  vchData.clear();
177  vchVersion.clear();
178  return false;
179  }
180  vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
181  vchData.resize(vchTemp.size() - nVersionBytes);
182  if (!vchData.empty())
183  memcpy(vchData.data(), vchTemp.data() + nVersionBytes, vchData.size());
184  memory_cleanse(vchTemp.data(), vchTemp.size());
185  return true;
186 }
187 
188 bool CBase58Data::SetString(const std::string& str)
189 {
190  return SetString(str.c_str());
191 }
192 
193 std::string CBase58Data::ToString() const
194 {
195  std::vector<unsigned char> vch = vchVersion;
196  vch.insert(vch.end(), vchData.begin(), vchData.end());
197  return EncodeBase58Check(vch);
198 }
199 
200 int CBase58Data::CompareTo(const CBase58Data& b58) const
201 {
202  if (vchVersion < b58.vchVersion)
203  return -1;
204  if (vchVersion > b58.vchVersion)
205  return 1;
206  if (vchData < b58.vchData)
207  return -1;
208  if (vchData > b58.vchData)
209  return 1;
210  return 0;
211 }
212 
213 namespace
214 {
221 class CBitcoinAddress : public CBase58Data {
222 public:
223  bool Set(const CKeyID &id);
224  bool Set(const CScriptID &id);
225  bool Set(const CTxDestination &dest);
226  bool IsValid() const;
227  bool IsValid(const CChainParams &params) const;
228 
229  CBitcoinAddress() {}
230  CBitcoinAddress(const CTxDestination &dest) { Set(dest); }
231  CBitcoinAddress(const std::string& strAddress) { SetString(strAddress); }
232  CBitcoinAddress(const char* pszAddress) { SetString(pszAddress); }
233 
234  CTxDestination Get() const;
235 };
236 
237 class CBitcoinAddressVisitor : public boost::static_visitor<bool>
238 {
239 private:
240  CBitcoinAddress* addr;
241 
242 public:
243  explicit CBitcoinAddressVisitor(CBitcoinAddress* addrIn) : addr(addrIn) {}
244 
245  bool operator()(const CKeyID& id) const { return addr->Set(id); }
246  bool operator()(const CScriptID& id) const { return addr->Set(id); }
247  bool operator()(const CNoDestination& no) const { return false; }
248 };
249 
250 } // namespace
251 
252 bool CBitcoinAddress::Set(const CKeyID& id)
253 {
254  SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
255  return true;
256 }
257 
258 bool CBitcoinAddress::Set(const CScriptID& id)
259 {
260  SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
261  return true;
262 }
263 
264 bool CBitcoinAddress::Set(const CTxDestination& dest)
265 {
266  return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
267 }
268 
269 bool CBitcoinAddress::IsValid() const
270 {
271  return IsValid(Params());
272 }
273 
274 bool CBitcoinAddress::IsValid(const CChainParams& params) const
275 {
276  bool fCorrectSize = vchData.size() == 20;
277  bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
278  vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
279  return fCorrectSize && fKnownVersion;
280 }
281 
282 CTxDestination CBitcoinAddress::Get() const
283 {
284  if (!IsValid())
285  return CNoDestination();
286  uint160 id;
287  memcpy(&id, vchData.data(), 20);
288  if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
289  return CKeyID(id);
290  else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
291  return CScriptID(id);
292  else
293  return CNoDestination();
294 }
295 
296 void CBitcoinSecret::SetKey(const CKey& vchSecret)
297 {
298  assert(vchSecret.IsValid());
299  SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
300  if (vchSecret.IsCompressed())
301  vchData.push_back(1);
302 }
303 
305 {
306  CKey ret;
307  assert(vchData.size() >= 32);
308  ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1);
309  return ret;
310 }
311 
313 {
314  bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
315  bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
316  return fExpectedFormat && fCorrectVersion;
317 }
318 
319 bool CBitcoinSecret::SetString(const char* pszSecret)
320 {
321  return CBase58Data::SetString(pszSecret) && IsValid();
322 }
323 
324 bool CBitcoinSecret::SetString(const std::string& strSecret)
325 {
326  return SetString(strSecret.c_str());
327 }
328 
329 std::string EncodeDestination(const CTxDestination& dest)
330 {
331  CBitcoinAddress addr(dest);
332  if (!addr.IsValid()) return "";
333  return addr.ToString();
334 }
335 
336 CTxDestination DecodeDestination(const std::string& str)
337 {
338  return CBitcoinAddress(str).Get();
339 }
340 
341 bool IsValidDestinationString(const std::string& str, const CChainParams& params)
342 {
343  return CBitcoinAddress(str).IsValid(params);
344 }
345 
346 bool IsValidDestinationString(const std::string& str)
347 {
348  return CBitcoinAddress(str).IsValid();
349 }
350 
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
void SetKey(const CKey &vchSecret)
Definition: base58.cpp:296
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:80
CKey GetKey()
Definition: base58.cpp:304
CTxDestination DecodeDestination(const std::string &str)
Definition: base58.cpp:336
std::string EncodeBase58(const unsigned char *pbegin, const unsigned char *pend)
Why base-58 instead of standard base-64 encoding?
Definition: base58.cpp:71
vector_uchar vchData
Definition: base58.h:79
int CompareTo(const CBase58Data &b58) const
Definition: base58.cpp:200
CChainParams defines various tweakable parameters of a given instance of the Dash system...
Definition: chainparams.h:41
void SetData(const std::vector< unsigned char > &vchVersionIn, const void *pdata, size_t nSize)
Definition: base58.cpp:158
const unsigned char * begin() const
Definition: key.h:89
bool SetString(const char *pszSecret)
Definition: base58.cpp:319
std::string ToString() const
Definition: base58.cpp:193
Base class for all base58-encoded data.
Definition: base58.h:71
void memory_cleanse(void *ptr, size_t len)
Definition: cleanse.cpp:31
bool IsValidDestinationString(const std::string &str, const CChainParams &params)
Definition: base58.cpp:341
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:130
unsigned int size() const
Simple read-only vector-like interface.
Definition: key.h:88
uint256 Hash(const T1 pbegin, const T1 pend)
Compute the 256-bit hash of an object.
Definition: hash.h:84
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:96
static const char * pszBase58
All alphanumeric characters except for "0", "I", "O", and "l".
Definition: base58.cpp:19
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:74
bool SetString(const char *psz, unsigned int nVersionBytes=1)
Definition: base58.cpp:171
256-bit opaque blob.
Definition: uint256.h:123
bool IsValid() const
Definition: base58.cpp:312
std::string EncodeDestination(const CTxDestination &dest)
Definition: base58.cpp:329
const CChainParams & Params()
Return the currently selected parameters.
void * memcpy(void *a, const void *b, size_t c)
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:20
160-bit opaque blob.
Definition: uint256.h:112
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:22
An encapsulated private key.
Definition: key.h:27
std::string EncodeBase58Check(const std::vector< unsigned char > &vchIn)
Encode a byte vector into a base58-encoded string, including checksum.
Definition: base58.cpp:121
std::vector< unsigned char > vchVersion
the version byte(s)
Definition: base58.h:75
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:93
const std::vector< unsigned char > & Base58Prefix(Base58Type type) const
Definition: chainparams.h:79
Released under the MIT license