1 // Copyright (c) 2014-2016 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.
15 #include <boost/variant/apply_visitor.hpp>
16 #include <boost/variant/static_visitor.hpp>
18 /** All alphanumeric characters except for "0", "I", "O", and "l" */
19 static const char* pszBase58
= "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
21 bool DecodeBase58(const char* psz
, std::vector
<unsigned char>& vch
)
23 // Skip leading spaces.
24 while (*psz
&& isspace(*psz
))
26 // Skip and count leading '1's.
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
);
42 // Apply "b256 = b256 * 58 + ch".
43 int carry
= ch
- pszBase58
;
45 for (std::vector
<unsigned char>::reverse_iterator it
= b256
.rbegin(); (carry
!= 0 || i
< length
) && (it
!= b256
.rend()); ++it
, ++i
) {
54 // Skip trailing spaces.
59 // Skip leading zeroes in b256.
60 std::vector
<unsigned char>::iterator it
= b256
.begin() + (size
- length
);
61 while (it
!= b256
.end() && *it
== 0)
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
++));
71 std::string
EncodeBase58(const unsigned char* pbegin
, const unsigned char* pend
)
73 // Skip & count leading zeroes.
76 while (pbegin
!= pend
&& *pbegin
== 0) {
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
);
84 while (pbegin
!= pend
) {
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
++) {
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)
102 // Translate the result into a string.
104 str
.reserve(zeroes
+ (b58
.end() - it
));
105 str
.assign(zeroes
, '1');
106 while (it
!= b58
.end())
107 str
+= pszBase58
[*(it
++)];
111 std::string
EncodeBase58(const std::vector
<unsigned char>& vch
)
113 return EncodeBase58(vch
.data(), vch
.data() + vch
.size());
116 bool DecodeBase58(const std::string
& str
, std::vector
<unsigned char>& vchRet
)
118 return DecodeBase58(str
.c_str(), vchRet
);
121 std::string
EncodeBase58Check(const std::vector
<unsigned char>& vchIn
)
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
);
130 bool DecodeBase58Check(const char* psz
, std::vector
<unsigned char>& vchRet
)
132 if (!DecodeBase58(psz
, vchRet
) ||
133 (vchRet
.size() < 4)) {
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) {
143 vchRet
.resize(vchRet
.size() - 4);
147 bool DecodeBase58Check(const std::string
& str
, std::vector
<unsigned char>& vchRet
)
149 return DecodeBase58Check(str
.c_str(), vchRet
);
152 CBase58Data::CBase58Data()
158 void CBase58Data::SetData(const std::vector
<unsigned char>& vchVersionIn
, const void* pdata
, size_t nSize
)
160 vchVersion
= vchVersionIn
;
161 vchData
.resize(nSize
);
162 if (!vchData
.empty())
163 memcpy(vchData
.data(), pdata
, nSize
);
166 void CBase58Data::SetData(const std::vector
<unsigned char>& vchVersionIn
, const unsigned char* pbegin
, const unsigned char* pend
)
168 SetData(vchVersionIn
, (void*)pbegin
, pend
- pbegin
);
171 bool CBase58Data::SetString(const char* psz
, unsigned int nVersionBytes
)
173 std::vector
<unsigned char> vchTemp
;
174 bool rc58
= DecodeBase58Check(psz
, vchTemp
);
175 if ((!rc58
) || (vchTemp
.size() < nVersionBytes
)) {
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());
188 bool CBase58Data::SetString(const std::string
& str
)
190 return SetString(str
.c_str());
193 std::string
CBase58Data::ToString() const
195 std::vector
<unsigned char> vch
= vchVersion
;
196 vch
.insert(vch
.end(), vchData
.begin(), vchData
.end());
197 return EncodeBase58Check(vch
);
200 int CBase58Data::CompareTo(const CBase58Data
& b58
) const
202 if (vchVersion
< b58
.vchVersion
)
204 if (vchVersion
> b58
.vchVersion
)
206 if (vchData
< b58
.vchData
)
208 if (vchData
> b58
.vchData
)
215 class CBitcoinAddressVisitor
: public boost::static_visitor
<bool>
218 CBitcoinAddress
* addr
;
221 CBitcoinAddressVisitor(CBitcoinAddress
* addrIn
) : addr(addrIn
) {}
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; }
230 bool CBitcoinAddress::Set(const CKeyID
& id
)
232 SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS
), &id
, 20);
236 bool CBitcoinAddress::Set(const CScriptID
& id
)
238 SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS
), &id
, 20);
242 bool CBitcoinAddress::Set(const CTxDestination
& dest
)
244 return boost::apply_visitor(CBitcoinAddressVisitor(this), dest
);
247 bool CBitcoinAddress::IsValid() const
249 return IsValid(Params());
252 bool CBitcoinAddress::IsValid(const CChainParams
& params
) const
254 bool fCorrectSize
= vchData
.size() == 20;
255 bool fKnownVersion
= vchVersion
== params
.Base58Prefix(CChainParams::PUBKEY_ADDRESS
) ||
256 vchVersion
== params
.Base58Prefix(CChainParams::SCRIPT_ADDRESS
);
257 return fCorrectSize
&& fKnownVersion
;
260 CTxDestination
CBitcoinAddress::Get() const
263 return CNoDestination();
265 memcpy(&id
, vchData
.data(), 20);
266 if (vchVersion
== Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS
))
268 else if (vchVersion
== Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS
))
269 return CScriptID(id
);
271 return CNoDestination();
274 bool CBitcoinAddress::GetKeyID(CKeyID
& keyID
) const
276 if (!IsValid() || vchVersion
!= Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS
))
279 memcpy(&id
, vchData
.data(), 20);
284 bool CBitcoinAddress::IsScript() const
286 return IsValid() && vchVersion
== Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS
);
289 void CBitcoinSecret::SetKey(const CKey
& vchSecret
)
291 assert(vchSecret
.IsValid());
292 SetData(Params().Base58Prefix(CChainParams::SECRET_KEY
), vchSecret
.begin(), vchSecret
.size());
293 if (vchSecret
.IsCompressed())
294 vchData
.push_back(1);
297 CKey
CBitcoinSecret::GetKey()
300 assert(vchData
.size() >= 32);
301 ret
.Set(vchData
.begin(), vchData
.begin() + 32, vchData
.size() > 32 && vchData
[32] == 1);
305 bool CBitcoinSecret::IsValid() const
307 bool fExpectedFormat
= vchData
.size() == 32 || (vchData
.size() == 33 && vchData
[32] == 1);
308 bool fCorrectVersion
= vchVersion
== Params().Base58Prefix(CChainParams::SECRET_KEY
);
309 return fExpectedFormat
&& fCorrectVersion
;
312 bool CBitcoinSecret::SetString(const char* pszSecret
)
314 return CBase58Data::SetString(pszSecret
) && IsValid();
317 bool CBitcoinSecret::SetString(const std::string
& strSecret
)
319 return SetString(strSecret
.c_str());