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.
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.
71 while (pbegin
!= pend
&& *pbegin
== 0) {
75 // Allocate enough space in big-endian base58 representation.
76 std::vector
<unsigned char> b58((pend
- pbegin
) * 138 / 100 + 1); // log(256) / log(58), rounded up.
78 while (pbegin
!= pend
) {
80 // Apply "b58 = b58 * 256 + ch".
81 for (std::vector
<unsigned char>::reverse_iterator it
= b58
.rbegin(); it
!= b58
.rend(); it
++) {
89 // Skip leading zeroes in base58 result.
90 std::vector
<unsigned char>::iterator it
= b58
.begin();
91 while (it
!= b58
.end() && *it
== 0)
93 // Translate the result into a string.
95 str
.reserve(zeroes
+ (b58
.end() - it
));
96 str
.assign(zeroes
, '1');
97 while (it
!= b58
.end())
98 str
+= pszBase58
[*(it
++)];
102 std::string
EncodeBase58(const std::vector
<unsigned char>& vch
)
104 return EncodeBase58(&vch
[0], &vch
[0] + vch
.size());
107 bool DecodeBase58(const std::string
& str
, std::vector
<unsigned char>& vchRet
)
109 return DecodeBase58(str
.c_str(), vchRet
);
112 std::string
EncodeBase58Check(const std::vector
<unsigned char>& vchIn
)
114 // add 4-byte hash check to the end
115 std::vector
<unsigned char> vch(vchIn
);
116 uint256 hash
= Hash(vch
.begin(), vch
.end());
117 vch
.insert(vch
.end(), (unsigned char*)&hash
, (unsigned char*)&hash
+ 4);
118 return EncodeBase58(vch
);
121 bool DecodeBase58Check(const char* psz
, std::vector
<unsigned char>& vchRet
)
123 if (!DecodeBase58(psz
, vchRet
) ||
124 (vchRet
.size() < 4)) {
128 // re-calculate the checksum, insure it matches the included 4-byte checksum
129 uint256 hash
= Hash(vchRet
.begin(), vchRet
.end() - 4);
130 if (memcmp(&hash
, &vchRet
.end()[-4], 4) != 0) {
134 vchRet
.resize(vchRet
.size() - 4);
138 bool DecodeBase58Check(const std::string
& str
, std::vector
<unsigned char>& vchRet
)
140 return DecodeBase58Check(str
.c_str(), vchRet
);
143 CBase58Data::CBase58Data()
149 void CBase58Data::SetData(const std::vector
<unsigned char>& vchVersionIn
, const void* pdata
, size_t nSize
)
151 vchVersion
= vchVersionIn
;
152 vchData
.resize(nSize
);
153 if (!vchData
.empty())
154 memcpy(&vchData
[0], pdata
, nSize
);
157 void CBase58Data::SetData(const std::vector
<unsigned char>& vchVersionIn
, const unsigned char* pbegin
, const unsigned char* pend
)
159 SetData(vchVersionIn
, (void*)pbegin
, pend
- pbegin
);
162 bool CBase58Data::SetString(const char* psz
, unsigned int nVersionBytes
)
164 std::vector
<unsigned char> vchTemp
;
165 bool rc58
= DecodeBase58Check(psz
, vchTemp
);
166 if ((!rc58
) || (vchTemp
.size() < nVersionBytes
)) {
171 vchVersion
.assign(vchTemp
.begin(), vchTemp
.begin() + nVersionBytes
);
172 vchData
.resize(vchTemp
.size() - nVersionBytes
);
173 if (!vchData
.empty())
174 memcpy(&vchData
[0], &vchTemp
[nVersionBytes
], vchData
.size());
175 memory_cleanse(&vchTemp
[0], vchData
.size());
179 bool CBase58Data::SetString(const std::string
& str
)
181 return SetString(str
.c_str());
184 std::string
CBase58Data::ToString() const
186 std::vector
<unsigned char> vch
= vchVersion
;
187 vch
.insert(vch
.end(), vchData
.begin(), vchData
.end());
188 return EncodeBase58Check(vch
);
191 int CBase58Data::CompareTo(const CBase58Data
& b58
) const
193 if (vchVersion
< b58
.vchVersion
)
195 if (vchVersion
> b58
.vchVersion
)
197 if (vchData
< b58
.vchData
)
199 if (vchData
> b58
.vchData
)
206 class CBitcoinAddressVisitor
: public boost::static_visitor
<bool>
209 CBitcoinAddress
* addr
;
212 CBitcoinAddressVisitor(CBitcoinAddress
* addrIn
) : addr(addrIn
) {}
214 bool operator()(const CKeyID
& id
) const { return addr
->Set(id
); }
215 bool operator()(const CScriptID
& id
) const { return addr
->Set(id
); }
216 bool operator()(const CNoDestination
& no
) const { return false; }
221 bool CBitcoinAddress::Set(const CKeyID
& id
)
223 SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS
), &id
, 20);
227 bool CBitcoinAddress::Set(const CScriptID
& id
)
229 SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS
), &id
, 20);
233 bool CBitcoinAddress::Set(const CTxDestination
& dest
)
235 return boost::apply_visitor(CBitcoinAddressVisitor(this), dest
);
238 bool CBitcoinAddress::IsValid() const
240 return IsValid(Params());
243 bool CBitcoinAddress::IsValid(const CChainParams
& params
) const
245 bool fCorrectSize
= vchData
.size() == 20;
246 bool fKnownVersion
= vchVersion
== params
.Base58Prefix(CChainParams::PUBKEY_ADDRESS
) ||
247 vchVersion
== params
.Base58Prefix(CChainParams::SCRIPT_ADDRESS
);
248 return fCorrectSize
&& fKnownVersion
;
251 CTxDestination
CBitcoinAddress::Get() const
254 return CNoDestination();
256 memcpy(&id
, &vchData
[0], 20);
257 if (vchVersion
== Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS
))
259 else if (vchVersion
== Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS
))
260 return CScriptID(id
);
262 return CNoDestination();
265 bool CBitcoinAddress::GetKeyID(CKeyID
& keyID
) const
267 if (!IsValid() || vchVersion
!= Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS
))
270 memcpy(&id
, &vchData
[0], 20);
275 bool CBitcoinAddress::IsScript() const
277 return IsValid() && vchVersion
== Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS
);
280 void CBitcoinSecret::SetKey(const CKey
& vchSecret
)
282 assert(vchSecret
.IsValid());
283 SetData(Params().Base58Prefix(CChainParams::SECRET_KEY
), vchSecret
.begin(), vchSecret
.size());
284 if (vchSecret
.IsCompressed())
285 vchData
.push_back(1);
288 CKey
CBitcoinSecret::GetKey()
291 assert(vchData
.size() >= 32);
292 ret
.Set(vchData
.begin(), vchData
.begin() + 32, vchData
.size() > 32 && vchData
[32] == 1);
296 bool CBitcoinSecret::IsValid() const
298 bool fExpectedFormat
= vchData
.size() == 32 || (vchData
.size() == 33 && vchData
[32] == 1);
299 bool fCorrectVersion
= vchVersion
== Params().Base58Prefix(CChainParams::SECRET_KEY
);
300 return fExpectedFormat
&& fCorrectVersion
;
303 bool CBitcoinSecret::SetString(const char* pszSecret
)
305 return CBase58Data::SetString(pszSecret
) && IsValid();
308 bool CBitcoinSecret::SetString(const std::string
& strSecret
)
310 return SetString(strSecret
.c_str());