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