1 // Copyright (c) 2014 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.
18 #include <boost/variant/apply_visitor.hpp>
19 #include <boost/variant/static_visitor.hpp>
21 /** All alphanumeric characters except for "0", "I", "O", and "l" */
22 static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
24 bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
26 // Skip leading spaces.
27 while (*psz && isspace(*psz))
29 // Skip and count leading '1's.
35 // Allocate enough space in big-endian base256 representation.
36 std::vector<unsigned char> b256(strlen(psz) * 733 / 1000 + 1); // log(58) / log(256), rounded up.
37 // Process the characters.
38 while (*psz && !isspace(*psz)) {
39 // Decode base58 character
40 const char* ch = strchr(pszBase58, *psz);
43 // Apply "b256 = b256 * 58 + ch".
44 int carry = ch - pszBase58;
45 for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); it != b256.rend(); it++) {
53 // Skip trailing spaces.
58 // Skip leading zeroes in b256.
59 std::vector<unsigned char>::iterator it = b256.begin();
60 while (it != b256.end() && *it == 0)
62 // Copy result into output vector.
63 vch.reserve(zeroes + (b256.end() - it));
64 vch.assign(zeroes, 0x00);
65 while (it != b256.end())
66 vch.push_back(*(it++));
70 std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
72 // Skip & count leading zeroes.
74 while (pbegin != pend && *pbegin == 0) {
78 // Allocate enough space in big-endian base58 representation.
79 std::vector<unsigned char> b58((pend - pbegin) * 138 / 100 + 1); // log(256) / log(58), rounded up.
81 while (pbegin != pend) {
83 // Apply "b58 = b58 * 256 + ch".
84 for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); it != b58.rend(); it++) {
92 // Skip leading zeroes in base58 result.
93 std::vector<unsigned char>::iterator it = b58.begin();
94 while (it != b58.end() && *it == 0)
96 // Translate the result into a string.
98 str.reserve(zeroes + (b58.end() - it));
99 str.assign(zeroes, '1');
100 while (it != b58.end())
101 str += pszBase58[*(it++)];
105 std::string EncodeBase58(const std::vector<unsigned char>& vch)
107 return EncodeBase58(&vch[0], &vch[0] + vch.size());
110 bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
112 return DecodeBase58(str.c_str(), vchRet);
115 std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
117 // add 4-byte hash check to the end
118 std::vector<unsigned char> vch(vchIn);
119 uint256 hash = Hash(vch.begin(), vch.end());
120 vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
121 return EncodeBase58(vch);
124 bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
126 if (!DecodeBase58(psz, vchRet) ||
127 (vchRet.size() < 4)) {
131 // re-calculate the checksum, insure it matches the included 4-byte checksum
132 uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4);
133 if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) {
137 vchRet.resize(vchRet.size() - 4);
141 bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
143 return DecodeBase58Check(str.c_str(), vchRet);
146 CBase58Data::CBase58Data()
152 void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const void* pdata, size_t nSize)
154 vchVersion = vchVersionIn;
155 vchData.resize(nSize);
156 if (!vchData.empty())
157 memcpy(&vchData[0], pdata, nSize);
160 void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend)
162 SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
165 bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes)
167 std::vector<unsigned char> vchTemp;
168 bool rc58 = DecodeBase58Check(psz, vchTemp);
169 if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
174 vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
175 vchData.resize(vchTemp.size() - nVersionBytes);
176 if (!vchData.empty())
177 memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size());
178 memory_cleanse(&vchTemp[0], vchData.size());
182 bool CBase58Data::SetString(const std::string& str, unsigned int nVersionBytes)
184 return SetString(str.c_str(), nVersionBytes);
187 std::string CBase58Data::ToString() const
189 std::vector<unsigned char> vch = vchVersion;
190 vch.insert(vch.end(), vchData.begin(), vchData.end());
191 return EncodeBase58Check(vch);
194 int CBase58Data::CompareTo(const CBase58Data& b58) const
196 if (vchVersion < b58.vchVersion)
198 if (vchVersion > b58.vchVersion)
200 if (vchData < b58.vchData)
202 if (vchData > b58.vchData)
209 class CBitcoinAddressVisitor : public boost::static_visitor<bool>
212 CBitcoinAddress* addr;
215 CBitcoinAddressVisitor(CBitcoinAddress* addrIn) : addr(addrIn) {}
217 bool operator()(const CKeyID& id) const { return addr->Set(id); }
218 bool operator()(const CScriptID& id) const { return addr->Set(id); }
219 bool operator()(const CNoDestination& no) const { return false; }
224 bool CBitcoinAddress::Set(const CKeyID& id)
226 SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
230 bool CBitcoinAddress::Set(const CScriptID& id)
232 SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
236 bool CBitcoinAddress::Set(const CTxDestination& dest)
238 return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
241 bool CBitcoinAddress::IsValid() const
243 return IsValid(Params());
246 bool CBitcoinAddress::IsValid(const CChainParams& params) const
248 bool fCorrectSize = vchData.size() == 20;
249 bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
250 vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
251 return fCorrectSize && fKnownVersion;
254 bool CBitcoinAddress::SetString(const char* pszAddress)
256 return CBase58Data::SetString(pszAddress, 1);//2);
259 bool CBitcoinAddress::SetString(const std::string& strAddress)
261 return SetString(strAddress.c_str());
264 CTxDestination CBitcoinAddress::Get() const
267 return CNoDestination();
269 memcpy(&id, &vchData[0], 20);
270 if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
272 else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
273 return CScriptID(id);
275 return CNoDestination();
278 bool CBitcoinAddress::GetIndexKey(uint160& hashBytes, int& type) const
282 } else if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)) {
283 memcpy(&hashBytes, &vchData[0], 20);
286 } else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS)) {
287 memcpy(&hashBytes, &vchData[0], 20);
295 bool CBitcoinAddress::GetKeyID(CKeyID& keyID) const
297 if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
300 memcpy(&id, &vchData[0], 20);
305 bool CBitcoinAddress::IsScript() const
307 return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
310 void CBitcoinSecret::SetKey(const CKey& vchSecret)
312 assert(vchSecret.IsValid());
313 SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
314 if (vchSecret.IsCompressed())
315 vchData.push_back(1);
318 CKey CBitcoinSecret::GetKey()
321 assert(vchData.size() >= 32);
322 ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1);
326 bool CBitcoinSecret::IsValid() const
328 bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
329 bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
330 return fExpectedFormat && fCorrectVersion;
333 bool CBitcoinSecret::SetString(const char* pszSecret)
335 return CBase58Data::SetString(pszSecret, 1) && IsValid();
338 bool CBitcoinSecret::SetString(const std::string& strSecret)
340 return SetString(strSecret.c_str());
343 template<class DATA_TYPE, CChainParams::Base58Type PREFIX, size_t SER_SIZE>
344 bool CZCEncoding<DATA_TYPE, PREFIX, SER_SIZE>::Set(const DATA_TYPE& addr)
346 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
348 std::vector<unsigned char> addrSerialized(ss.begin(), ss.end());
349 assert(addrSerialized.size() == SER_SIZE);
350 SetData(Params().Base58Prefix(PREFIX), &addrSerialized[0], SER_SIZE);
354 template<class DATA_TYPE, CChainParams::Base58Type PREFIX, size_t SER_SIZE>
355 DATA_TYPE CZCEncoding<DATA_TYPE, PREFIX, SER_SIZE>::Get() const
357 if (vchData.size() != SER_SIZE) {
358 throw std::runtime_error(
359 PrependName(" is invalid")
363 if (vchVersion != Params().Base58Prefix(PREFIX)) {
364 throw std::runtime_error(
365 PrependName(" is for wrong network type")
369 std::vector<unsigned char> serialized(vchData.begin(), vchData.end());
371 CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
377 // Explicit instantiations for libzcash::PaymentAddress
378 template bool CZCEncoding<libzcash::PaymentAddress,
379 CChainParams::ZCPAYMENT_ADDRRESS,
380 libzcash::SerializedPaymentAddressSize>::Set(const libzcash::PaymentAddress& addr);
381 template libzcash::PaymentAddress CZCEncoding<libzcash::PaymentAddress,
382 CChainParams::ZCPAYMENT_ADDRRESS,
383 libzcash::SerializedPaymentAddressSize>::Get() const;
385 // Explicit instantiations for libzcash::ViewingKey
386 template bool CZCEncoding<libzcash::ViewingKey,
387 CChainParams::ZCVIEWING_KEY,
388 libzcash::SerializedViewingKeySize>::Set(const libzcash::ViewingKey& vk);
389 template libzcash::ViewingKey CZCEncoding<libzcash::ViewingKey,
390 CChainParams::ZCVIEWING_KEY,
391 libzcash::SerializedViewingKeySize>::Get() const;
393 // Explicit instantiations for libzcash::SpendingKey
394 template bool CZCEncoding<libzcash::SpendingKey,
395 CChainParams::ZCSPENDING_KEY,
396 libzcash::SerializedSpendingKeySize>::Set(const libzcash::SpendingKey& sk);
397 template libzcash::SpendingKey CZCEncoding<libzcash::SpendingKey,
398 CChainParams::ZCSPENDING_KEY,
399 libzcash::SerializedSpendingKeySize>::Get() const;