Fabcoin Core  0.16.2
P2P Digital Currency
base58.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2017 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.end()[-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 {
215 class CFabcoinAddressVisitor : public boost::static_visitor<bool>
216 {
217 private:
218  CFabcoinAddress* addr;
219 
220 public:
221  CFabcoinAddressVisitor(CFabcoinAddress* addrIn) : addr(addrIn) {}
222 
223  bool operator()(const CKeyID& id) const { return addr->Set(id); }
224  bool operator()(const CScriptID& id) const { return addr->Set(id); }
225  bool operator()(const CNoDestination& no) const { return false; }
226 };
227 
228 } // namespace
229 
231 {
232  SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
233  return true;
234 }
235 
237 {
238  SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
239  return true;
240 }
241 
243 {
244  return boost::apply_visitor(CFabcoinAddressVisitor(this), dest);
245 }
246 
248 {
249  return IsValid(Params());
250 }
251 
252 bool CFabcoinAddress::IsValid(const CChainParams& params) const
253 {
254  bool fCorrectSize = vchData.size() == 20;
255  bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
257  return fCorrectSize && fKnownVersion;
258 }
259 
261 {
262  if (!IsValid())
263  return CNoDestination();
264  uint160 id;
265  memcpy(&id, vchData.data(), 20);
267  return CKeyID(id);
269  return CScriptID(id);
270  else
271  return CNoDestination();
272 }
273 
275 {
276  if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
277  return false;
278  uint160 id;
279  memcpy(&id, vchData.data(), 20);
280  keyID = CKeyID(id);
281  return true;
282 }
283 
285 {
287 }
288 
290 {
292 }
293 
294 void CFabcoinSecret::SetKey(const CKey& vchSecret)
295 {
296  assert(vchSecret.IsValid());
297  SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
298  if (vchSecret.IsCompressed())
299  vchData.push_back(1);
300 }
301 
303 {
304  CKey ret;
305  assert(vchData.size() >= 32);
306  ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1);
307  return ret;
308 }
309 
311 {
312  bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
313  bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
314  return fExpectedFormat && fCorrectVersion;
315 }
316 
317 bool CFabcoinSecret::SetString(const char* pszSecret)
318 {
319  return CBase58Data::SetString(pszSecret) && IsValid();
320 }
321 
322 bool CFabcoinSecret::SetString(const std::string& strSecret)
323 {
324  return SetString(strSecret.c_str());
325 }
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 SetString(const char *pszSecret)
Definition: base58.cpp:317
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:79
const unsigned char * begin() const
Definition: key.h:88
bool IsPubKeyHash() const
Definition: base58.cpp:289
base58-encoded Fabcoin addresses.
Definition: base58.h:104
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
assert(len-trim+(2 *lenIndices)<=WIDTH)
CChainParams defines various tweakable parameters of a given instance of the Fabcoin system...
Definition: chainparams.h:47
bool IsValid() const
Definition: base58.cpp:247
bool IsValid() const
Definition: base58.cpp:310
void SetData(const std::vector< unsigned char > &vchVersionIn, const void *pdata, size_t nSize)
Definition: base58.cpp:158
bool IsScript() const
Definition: base58.cpp:284
unsigned char * end()
Definition: uint256.h:70
const std::vector< unsigned char > & Base58Prefix(Base58Type type) const
Definition: chainparams.h:80
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:92
Base class for all base58-encoded data.
Definition: base58.h:71
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:95
void memory_cleanse(void *ptr, size_t len)
Definition: cleanse.cpp:10
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
std::string ToString() const
Definition: base58.cpp:193
uint256 Hash(const T1 pbegin, const T1 pend)
Compute the 256-bit hash of an object.
Definition: hash.h:70
CTxDestination Get() const
Definition: base58.cpp:260
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:73
bool SetString(const char *psz, unsigned int nVersionBytes=1)
Definition: base58.cpp:171
CKey GetKey()
Definition: base58.cpp:302
bool GetKeyID(CKeyID &keyID) const
Definition: base58.cpp:274
256-bit opaque blob.
Definition: uint256.h:132
uint8_t const size_t const size
Definition: sha3.h:20
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:29
160-bit opaque blob.
Definition: uint256.h:120
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:28
An encapsulated private key.
Definition: key.h:35
unsigned int size() const
Simple read-only vector-like interface.
Definition: key.h:87
uint32_t ch(uint32_t x, uint32_t y, uint32_t z)
Definition: picosha2.h:73
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 Set(const CKeyID &id)
Definition: base58.cpp:230
void SetKey(const CKey &vchSecret)
Definition: base58.cpp:294
int CompareTo(const CBase58Data &b58) const
Definition: base58.cpp:200