1 // Copyright (c) 2014-2015 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.
32 // Allocate enough space in big-endian base256 representation.
33 std::vector
<unsigned char> b256(strlen(psz
) * 733 / 1000 + 1); // log(58) / log(256), rounded up.
34 // Process the characters.
35 while (*psz
&& !isspace(*psz
)) {
36 // Decode base58 character
37 const char* ch
= strchr(pszBase58
, *psz
);
40 // Apply "b256 = b256 * 58 + ch".
41 int carry
= ch
- pszBase58
;
42 for (std::vector
<unsigned char>::reverse_iterator it
= b256
.rbegin(); it
!= b256
.rend(); it
++) {
50 // Skip trailing spaces.
55 // Skip leading zeroes in b256.
56 std::vector
<unsigned char>::iterator it
= b256
.begin();
57 while (it
!= b256
.end() && *it
== 0)
59 // Copy result into output vector.
60 vch
.reserve(zeroes
+ (b256
.end() - it
));
61 vch
.assign(zeroes
, 0x00);
62 while (it
!= b256
.end())
63 vch
.push_back(*(it
++));
67 std::string
EncodeBase58(const unsigned char* pbegin
, const unsigned char* pend
)
69 // Skip & count leading zeroes.
72 while (pbegin
!= pend
&& *pbegin
== 0) {
76 // Allocate enough space in big-endian base58 representation.
77 int size
= (pend
- pbegin
) * 138 / 100 + 1; // log(256) / log(58), rounded up.
78 std::vector
<unsigned char> b58(size
);
80 while (pbegin
!= pend
) {
83 // Apply "b58 = b58 * 256 + ch".
84 for (std::vector
<unsigned char>::reverse_iterator it
= b58
.rbegin(); (carry
!= 0 || i
< length
) && (it
!= b58
.rend()); it
++, i
++) {
94 // Skip leading zeroes in base58 result.
95 std::vector
<unsigned char>::iterator it
= b58
.begin() + (size
- length
);
96 while (it
!= b58
.end() && *it
== 0)
98 // Translate the result into a string.
100 str
.reserve(zeroes
+ (b58
.end() - it
));
101 str
.assign(zeroes
, '1');
102 while (it
!= b58
.end())
103 str
+= pszBase58
[*(it
++)];
107 std::string
EncodeBase58(const std::vector
<unsigned char>& vch
)
109 return EncodeBase58(&vch
[0], &vch
[0] + vch
.size());
112 bool DecodeBase58(const std::string
& str
, std::vector
<unsigned char>& vchRet
)
114 return DecodeBase58(str
.c_str(), vchRet
);
117 std::string
EncodeBase58Check(const std::vector
<unsigned char>& vchIn
)
119 // add 4-byte hash check to the end
120 std::vector
<unsigned char> vch(vchIn
);
121 uint256 hash
= Hash(vch
.begin(), vch
.end());
122 vch
.insert(vch
.end(), (unsigned char*)&hash
, (unsigned char*)&hash
+ 4);
123 return EncodeBase58(vch
);
126 bool DecodeBase58Check(const char* psz
, std::vector
<unsigned char>& vchRet
)
128 if (!DecodeBase58(psz
, vchRet
) ||
129 (vchRet
.size() < 4)) {
133 // re-calculate the checksum, insure it matches the included 4-byte checksum
134 uint256 hash
= Hash(vchRet
.begin(), vchRet
.end() - 4);
135 if (memcmp(&hash
, &vchRet
.end()[-4], 4) != 0) {
139 vchRet
.resize(vchRet
.size() - 4);
143 bool DecodeBase58Check(const std::string
& str
, std::vector
<unsigned char>& vchRet
)
145 return DecodeBase58Check(str
.c_str(), vchRet
);
148 CBase58Data::CBase58Data()
154 void CBase58Data::SetData(const std::vector
<unsigned char>& vchVersionIn
, const void* pdata
, size_t nSize
)
156 vchVersion
= vchVersionIn
;
157 vchData
.resize(nSize
);
158 if (!vchData
.empty())
159 memcpy(&vchData
[0], pdata
, nSize
);
162 void CBase58Data::SetData(const std::vector
<unsigned char>& vchVersionIn
, const unsigned char* pbegin
, const unsigned char* pend
)
164 SetData(vchVersionIn
, (void*)pbegin
, pend
- pbegin
);
167 bool CBase58Data::SetString(const char* psz
, unsigned int nVersionBytes
)
169 std::vector
<unsigned char> vchTemp
;
170 bool rc58
= DecodeBase58Check(psz
, vchTemp
);
171 if ((!rc58
) || (vchTemp
.size() < nVersionBytes
)) {
176 vchVersion
.assign(vchTemp
.begin(), vchTemp
.begin() + nVersionBytes
);
177 vchData
.resize(vchTemp
.size() - nVersionBytes
);
178 if (!vchData
.empty())
179 memcpy(&vchData
[0], &vchTemp
[nVersionBytes
], vchData
.size());
180 memory_cleanse(&vchTemp
[0], vchTemp
.size());
184 bool CBase58Data::SetString(const std::string
& str
)
186 return SetString(str
.c_str());
189 std::string
CBase58Data::ToString() const
191 std::vector
<unsigned char> vch
= vchVersion
;
192 vch
.insert(vch
.end(), vchData
.begin(), vchData
.end());
193 return EncodeBase58Check(vch
);
196 int CBase58Data::CompareTo(const CBase58Data
& b58
) const
198 if (vchVersion
< b58
.vchVersion
)
200 if (vchVersion
> b58
.vchVersion
)
202 if (vchData
< b58
.vchData
)
204 if (vchData
> b58
.vchData
)
211 class CBitcoinAddressVisitor
: public boost::static_visitor
<bool>
214 CBitcoinAddress
* addr
;
217 CBitcoinAddressVisitor(CBitcoinAddress
* addrIn
) : addr(addrIn
) {}
219 bool operator()(const CKeyID
& id
) const { return addr
->Set(id
); }
220 bool operator()(const CScriptID
& id
) const { return addr
->Set(id
); }
221 bool operator()(const CNoDestination
& no
) const { return false; }
226 bool CBitcoinAddress::Set(const CKeyID
& id
)
228 SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS
), &id
, 20);
232 bool CBitcoinAddress::Set(const CScriptID
& id
)
234 SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS
), &id
, 20);
238 bool CBitcoinAddress::Set(const CTxDestination
& dest
)
240 return boost::apply_visitor(CBitcoinAddressVisitor(this), dest
);
243 bool CBitcoinAddress::IsValid() const
245 return IsValid(Params());
248 bool CBitcoinAddress::IsValid(const CChainParams
& params
) const
250 bool fCorrectSize
= vchData
.size() == 20;
251 bool fKnownVersion
= vchVersion
== params
.Base58Prefix(CChainParams::PUBKEY_ADDRESS
) ||
252 vchVersion
== params
.Base58Prefix(CChainParams::SCRIPT_ADDRESS
);
253 return fCorrectSize
&& fKnownVersion
;
256 CTxDestination
CBitcoinAddress::Get() const
259 return CNoDestination();
261 memcpy(&id
, &vchData
[0], 20);
262 if (vchVersion
== Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS
))
264 else if (vchVersion
== Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS
))
265 return CScriptID(id
);
267 return CNoDestination();
270 bool CBitcoinAddress::GetKeyID(CKeyID
& keyID
) const
272 if (!IsValid() || vchVersion
!= Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS
))
275 memcpy(&id
, &vchData
[0], 20);
280 bool CBitcoinAddress::IsScript() const
282 return IsValid() && vchVersion
== Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS
);
285 void CBitcoinSecret::SetKey(const CKey
& vchSecret
)
287 assert(vchSecret
.IsValid());
288 SetData(Params().Base58Prefix(CChainParams::SECRET_KEY
), vchSecret
.begin(), vchSecret
.size());
289 if (vchSecret
.IsCompressed())
290 vchData
.push_back(1);
293 CKey
CBitcoinSecret::GetKey()
296 assert(vchData
.size() >= 32);
297 ret
.Set(vchData
.begin(), vchData
.begin() + 32, vchData
.size() > 32 && vchData
[32] == 1);
301 bool CBitcoinSecret::IsValid() const
303 bool fExpectedFormat
= vchData
.size() == 32 || (vchData
.size() == 33 && vchData
[32] == 1);
304 bool fCorrectVersion
= vchVersion
== Params().Base58Prefix(CChainParams::SECRET_KEY
);
305 return fExpectedFormat
&& fCorrectVersion
;
308 bool CBitcoinSecret::SetString(const char* pszSecret
)
310 return CBase58Data::SetString(pszSecret
) && IsValid();
313 bool CBitcoinSecret::SetString(const std::string
& strSecret
)
315 return SetString(strSecret
.c_str());