Merge #12079: Improve prioritisetransaction test coverage
[bitcoinplatinum.git] / src / base58.cpp
blob499afbe3822f610e6ad889c1989ea40bacf822df
1 // Copyright (c) 2014-2017 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.
5 #include <base58.h>
7 #include <bech32.h>
8 #include <hash.h>
9 #include <script/script.h>
10 #include <uint256.h>
11 #include <utilstrencodings.h>
13 #include <boost/variant/apply_visitor.hpp>
14 #include <boost/variant/static_visitor.hpp>
16 #include <algorithm>
17 #include <assert.h>
18 #include <string.h>
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))
28 psz++;
29 // Skip and count leading '1's.
30 int zeroes = 0;
31 int length = 0;
32 while (*psz == '1') {
33 zeroes++;
34 psz++;
36 // Allocate enough space in big-endian base256 representation.
37 int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up.
38 std::vector<unsigned char> b256(size);
39 // Process the characters.
40 while (*psz && !isspace(*psz)) {
41 // Decode base58 character
42 const char* ch = strchr(pszBase58, *psz);
43 if (ch == nullptr)
44 return false;
45 // Apply "b256 = b256 * 58 + ch".
46 int carry = ch - pszBase58;
47 int i = 0;
48 for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
49 carry += 58 * (*it);
50 *it = carry % 256;
51 carry /= 256;
53 assert(carry == 0);
54 length = i;
55 psz++;
57 // Skip trailing spaces.
58 while (isspace(*psz))
59 psz++;
60 if (*psz != 0)
61 return false;
62 // Skip leading zeroes in b256.
63 std::vector<unsigned char>::iterator it = b256.begin() + (size - length);
64 while (it != b256.end() && *it == 0)
65 it++;
66 // Copy result into output vector.
67 vch.reserve(zeroes + (b256.end() - it));
68 vch.assign(zeroes, 0x00);
69 while (it != b256.end())
70 vch.push_back(*(it++));
71 return true;
74 std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
76 // Skip & count leading zeroes.
77 int zeroes = 0;
78 int length = 0;
79 while (pbegin != pend && *pbegin == 0) {
80 pbegin++;
81 zeroes++;
83 // Allocate enough space in big-endian base58 representation.
84 int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up.
85 std::vector<unsigned char> b58(size);
86 // Process the bytes.
87 while (pbegin != pend) {
88 int carry = *pbegin;
89 int i = 0;
90 // Apply "b58 = b58 * 256 + ch".
91 for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
92 carry += 256 * (*it);
93 *it = carry % 58;
94 carry /= 58;
97 assert(carry == 0);
98 length = i;
99 pbegin++;
101 // Skip leading zeroes in base58 result.
102 std::vector<unsigned char>::iterator it = b58.begin() + (size - length);
103 while (it != b58.end() && *it == 0)
104 it++;
105 // Translate the result into a string.
106 std::string str;
107 str.reserve(zeroes + (b58.end() - it));
108 str.assign(zeroes, '1');
109 while (it != b58.end())
110 str += pszBase58[*(it++)];
111 return str;
114 std::string EncodeBase58(const std::vector<unsigned char>& vch)
116 return EncodeBase58(vch.data(), vch.data() + vch.size());
119 bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
121 return DecodeBase58(str.c_str(), vchRet);
124 std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
126 // add 4-byte hash check to the end
127 std::vector<unsigned char> vch(vchIn);
128 uint256 hash = Hash(vch.begin(), vch.end());
129 vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
130 return EncodeBase58(vch);
133 bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
135 if (!DecodeBase58(psz, vchRet) ||
136 (vchRet.size() < 4)) {
137 vchRet.clear();
138 return false;
140 // re-calculate the checksum, ensure it matches the included 4-byte checksum
141 uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4);
142 if (memcmp(&hash, &vchRet[vchRet.size() - 4], 4) != 0) {
143 vchRet.clear();
144 return false;
146 vchRet.resize(vchRet.size() - 4);
147 return true;
150 bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
152 return DecodeBase58Check(str.c_str(), vchRet);
155 CBase58Data::CBase58Data()
157 vchVersion.clear();
158 vchData.clear();
161 void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const void* pdata, size_t nSize)
163 vchVersion = vchVersionIn;
164 vchData.resize(nSize);
165 if (!vchData.empty())
166 memcpy(vchData.data(), pdata, nSize);
169 void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend)
171 SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
174 bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes)
176 std::vector<unsigned char> vchTemp;
177 bool rc58 = DecodeBase58Check(psz, vchTemp);
178 if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
179 vchData.clear();
180 vchVersion.clear();
181 return false;
183 vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
184 vchData.resize(vchTemp.size() - nVersionBytes);
185 if (!vchData.empty())
186 memcpy(vchData.data(), vchTemp.data() + nVersionBytes, vchData.size());
187 memory_cleanse(vchTemp.data(), vchTemp.size());
188 return true;
191 bool CBase58Data::SetString(const std::string& str)
193 return SetString(str.c_str());
196 std::string CBase58Data::ToString() const
198 std::vector<unsigned char> vch = vchVersion;
199 vch.insert(vch.end(), vchData.begin(), vchData.end());
200 return EncodeBase58Check(vch);
203 int CBase58Data::CompareTo(const CBase58Data& b58) const
205 if (vchVersion < b58.vchVersion)
206 return -1;
207 if (vchVersion > b58.vchVersion)
208 return 1;
209 if (vchData < b58.vchData)
210 return -1;
211 if (vchData > b58.vchData)
212 return 1;
213 return 0;
216 namespace
218 class DestinationEncoder : public boost::static_visitor<std::string>
220 private:
221 const CChainParams& m_params;
223 public:
224 DestinationEncoder(const CChainParams& params) : m_params(params) {}
226 std::string operator()(const CKeyID& id) const
228 std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
229 data.insert(data.end(), id.begin(), id.end());
230 return EncodeBase58Check(data);
233 std::string operator()(const CScriptID& id) const
235 std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
236 data.insert(data.end(), id.begin(), id.end());
237 return EncodeBase58Check(data);
240 std::string operator()(const WitnessV0KeyHash& id) const
242 std::vector<unsigned char> data = {0};
243 ConvertBits<8, 5, true>(data, id.begin(), id.end());
244 return bech32::Encode(m_params.Bech32HRP(), data);
247 std::string operator()(const WitnessV0ScriptHash& id) const
249 std::vector<unsigned char> data = {0};
250 ConvertBits<8, 5, true>(data, id.begin(), id.end());
251 return bech32::Encode(m_params.Bech32HRP(), data);
254 std::string operator()(const WitnessUnknown& id) const
256 if (id.version < 1 || id.version > 16 || id.length < 2 || id.length > 40) {
257 return {};
259 std::vector<unsigned char> data = {(unsigned char)id.version};
260 ConvertBits<8, 5, true>(data, id.program, id.program + id.length);
261 return bech32::Encode(m_params.Bech32HRP(), data);
264 std::string operator()(const CNoDestination& no) const { return {}; }
267 CTxDestination DecodeDestination(const std::string& str, const CChainParams& params)
269 std::vector<unsigned char> data;
270 uint160 hash;
271 if (DecodeBase58Check(str, data)) {
272 // base58-encoded Bitcoin addresses.
273 // Public-key-hash-addresses have version 0 (or 111 testnet).
274 // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
275 const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
276 if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
277 std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin());
278 return CKeyID(hash);
280 // Script-hash-addresses have version 5 (or 196 testnet).
281 // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
282 const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
283 if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
284 std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin());
285 return CScriptID(hash);
288 data.clear();
289 auto bech = bech32::Decode(str);
290 if (bech.second.size() > 0 && bech.first == params.Bech32HRP()) {
291 // Bech32 decoding
292 int version = bech.second[0]; // The first 5 bit symbol is the witness version (0-16)
293 // The rest of the symbols are converted witness program bytes.
294 if (ConvertBits<5, 8, false>(data, bech.second.begin() + 1, bech.second.end())) {
295 if (version == 0) {
297 WitnessV0KeyHash keyid;
298 if (data.size() == keyid.size()) {
299 std::copy(data.begin(), data.end(), keyid.begin());
300 return keyid;
304 WitnessV0ScriptHash scriptid;
305 if (data.size() == scriptid.size()) {
306 std::copy(data.begin(), data.end(), scriptid.begin());
307 return scriptid;
310 return CNoDestination();
312 if (version > 16 || data.size() < 2 || data.size() > 40) {
313 return CNoDestination();
315 WitnessUnknown unk;
316 unk.version = version;
317 std::copy(data.begin(), data.end(), unk.program);
318 unk.length = data.size();
319 return unk;
322 return CNoDestination();
324 } // namespace
326 void CBitcoinSecret::SetKey(const CKey& vchSecret)
328 assert(vchSecret.IsValid());
329 SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
330 if (vchSecret.IsCompressed())
331 vchData.push_back(1);
334 CKey CBitcoinSecret::GetKey()
336 CKey ret;
337 assert(vchData.size() >= 32);
338 ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1);
339 return ret;
342 bool CBitcoinSecret::IsValid() const
344 bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
345 bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
346 return fExpectedFormat && fCorrectVersion;
349 bool CBitcoinSecret::SetString(const char* pszSecret)
351 return CBase58Data::SetString(pszSecret) && IsValid();
354 bool CBitcoinSecret::SetString(const std::string& strSecret)
356 return SetString(strSecret.c_str());
359 std::string EncodeDestination(const CTxDestination& dest)
361 return boost::apply_visitor(DestinationEncoder(Params()), dest);
364 CTxDestination DecodeDestination(const std::string& str)
366 return DecodeDestination(str, Params());
369 bool IsValidDestinationString(const std::string& str, const CChainParams& params)
371 return IsValidDestination(DecodeDestination(str, params));
374 bool IsValidDestinationString(const std::string& str)
376 return IsValidDestinationString(str, Params());