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 /** base58-encoded Bitcoin addresses.
216 * Public-key-hash-addresses have version 0 (or 111 testnet).
217 * The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
218 * Script-hash-addresses have version 5 (or 196 testnet).
219 * The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
221 class CBitcoinAddress
: public CBase58Data
{
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
¶ms
) const;
230 CBitcoinAddress(const CTxDestination
&dest
) { Set(dest
); }
231 CBitcoinAddress(const std::string
& strAddress
) { SetString(strAddress
); }
232 CBitcoinAddress(const char* pszAddress
) { SetString(pszAddress
); }
234 CTxDestination
Get() const;
237 class CBitcoinAddressVisitor
: public boost::static_visitor
<bool>
240 CBitcoinAddress
* addr
;
243 explicit CBitcoinAddressVisitor(CBitcoinAddress
* addrIn
) : addr(addrIn
) {}
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; }
252 bool CBitcoinAddress::Set(const CKeyID
& id
)
254 SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS
), &id
, 20);
258 bool CBitcoinAddress::Set(const CScriptID
& id
)
260 SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS
), &id
, 20);
264 bool CBitcoinAddress::Set(const CTxDestination
& dest
)
266 return boost::apply_visitor(CBitcoinAddressVisitor(this), dest
);
269 bool CBitcoinAddress::IsValid() const
271 return IsValid(Params());
274 bool CBitcoinAddress::IsValid(const CChainParams
& params
) const
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
;
282 CTxDestination
CBitcoinAddress::Get() const
285 return CNoDestination();
287 memcpy(&id
, vchData
.data(), 20);
288 if (vchVersion
== Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS
))
290 else if (vchVersion
== Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS
))
291 return CScriptID(id
);
293 return CNoDestination();
296 void CBitcoinSecret::SetKey(const CKey
& vchSecret
)
298 assert(vchSecret
.IsValid());
299 SetData(Params().Base58Prefix(CChainParams::SECRET_KEY
), vchSecret
.begin(), vchSecret
.size());
300 if (vchSecret
.IsCompressed())
301 vchData
.push_back(1);
304 CKey
CBitcoinSecret::GetKey()
307 assert(vchData
.size() >= 32);
308 ret
.Set(vchData
.begin(), vchData
.begin() + 32, vchData
.size() > 32 && vchData
[32] == 1);
312 bool CBitcoinSecret::IsValid() const
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
;
319 bool CBitcoinSecret::SetString(const char* pszSecret
)
321 return CBase58Data::SetString(pszSecret
) && IsValid();
324 bool CBitcoinSecret::SetString(const std::string
& strSecret
)
326 return SetString(strSecret
.c_str());
329 std::string
EncodeDestination(const CTxDestination
& dest
)
331 CBitcoinAddress
addr(dest
);
332 if (!addr
.IsValid()) return "";
333 return addr
.ToString();
336 CTxDestination
DecodeDestination(const std::string
& str
)
338 return CBitcoinAddress(str
).Get();
341 bool IsValidDestinationString(const std::string
& str
, const CChainParams
& params
)
343 return CBitcoinAddress(str
).IsValid(params
);
346 bool IsValidDestinationString(const std::string
& str
)
348 return CBitcoinAddress(str
).IsValid();