Skip to content

Commit 68d5fb3

Browse files
committed
Merge pull request #4165
f6b7c64 Move base58.h implementation code to base58.cpp (Pieter Wuille)
2 parents 029f490 + f6b7c64 commit 68d5fb3

File tree

3 files changed

+219
-227
lines changed

3 files changed

+219
-227
lines changed

src/base58.cpp

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,18 @@
22
// Distributed under the MIT/X11 software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5+
#include "base58.h"
6+
7+
#include "hash.h"
8+
#include "uint256.h"
9+
510
#include <assert.h>
611
#include <stdint.h>
712
#include <string.h>
813
#include <vector>
914
#include <string>
15+
#include <boost/variant/apply_visitor.hpp>
16+
#include <boost/variant/static_visitor.hpp>
1017

1118
/* All alphanumeric characters except for "0", "I", "O", and "l" */
1219
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
@@ -89,3 +96,179 @@ std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
8996
str += pszBase58[*(it++)];
9097
return str;
9198
}
99+
100+
std::string EncodeBase58(const std::vector<unsigned char>& vch) {
101+
return EncodeBase58(&vch[0], &vch[0] + vch.size());
102+
}
103+
104+
bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet) {
105+
return DecodeBase58(str.c_str(), vchRet);
106+
}
107+
108+
std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn) {
109+
// add 4-byte hash check to the end
110+
std::vector<unsigned char> vch(vchIn);
111+
uint256 hash = Hash(vch.begin(), vch.end());
112+
vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
113+
return EncodeBase58(vch);
114+
}
115+
116+
bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet) {
117+
if (!DecodeBase58(psz, vchRet))
118+
return false;
119+
if (vchRet.size() < 4)
120+
{
121+
vchRet.clear();
122+
return false;
123+
}
124+
// re-calculate the checksum, insure it matches the included 4-byte checksum
125+
uint256 hash = Hash(vchRet.begin(), vchRet.end()-4);
126+
if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
127+
{
128+
vchRet.clear();
129+
return false;
130+
}
131+
vchRet.resize(vchRet.size()-4);
132+
return true;
133+
}
134+
135+
bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet) {
136+
return DecodeBase58Check(str.c_str(), vchRet);
137+
}
138+
139+
CBase58Data::CBase58Data() {
140+
vchVersion.clear();
141+
vchData.clear();
142+
}
143+
144+
void CBase58Data::SetData(const std::vector<unsigned char> &vchVersionIn, const void* pdata, size_t nSize) {
145+
vchVersion = vchVersionIn;
146+
vchData.resize(nSize);
147+
if (!vchData.empty())
148+
memcpy(&vchData[0], pdata, nSize);
149+
}
150+
151+
void CBase58Data::SetData(const std::vector<unsigned char> &vchVersionIn, const unsigned char *pbegin, const unsigned char *pend) {
152+
SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
153+
}
154+
155+
bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes) {
156+
std::vector<unsigned char> vchTemp;
157+
DecodeBase58Check(psz, vchTemp);
158+
if (vchTemp.size() < nVersionBytes) {
159+
vchData.clear();
160+
vchVersion.clear();
161+
return false;
162+
}
163+
vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
164+
vchData.resize(vchTemp.size() - nVersionBytes);
165+
if (!vchData.empty())
166+
memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size());
167+
OPENSSL_cleanse(&vchTemp[0], vchData.size());
168+
return true;
169+
}
170+
171+
bool CBase58Data::SetString(const std::string& str) {
172+
return SetString(str.c_str());
173+
}
174+
175+
std::string CBase58Data::ToString() const {
176+
std::vector<unsigned char> vch = vchVersion;
177+
vch.insert(vch.end(), vchData.begin(), vchData.end());
178+
return EncodeBase58Check(vch);
179+
}
180+
181+
int CBase58Data::CompareTo(const CBase58Data& b58) const {
182+
if (vchVersion < b58.vchVersion) return -1;
183+
if (vchVersion > b58.vchVersion) return 1;
184+
if (vchData < b58.vchData) return -1;
185+
if (vchData > b58.vchData) return 1;
186+
return 0;
187+
}
188+
189+
namespace {
190+
class CBitcoinAddressVisitor : public boost::static_visitor<bool> {
191+
private:
192+
CBitcoinAddress *addr;
193+
public:
194+
CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { }
195+
196+
bool operator()(const CKeyID &id) const { return addr->Set(id); }
197+
bool operator()(const CScriptID &id) const { return addr->Set(id); }
198+
bool operator()(const CNoDestination &no) const { return false; }
199+
};
200+
};
201+
202+
bool CBitcoinAddress::Set(const CKeyID &id) {
203+
SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
204+
return true;
205+
}
206+
207+
bool CBitcoinAddress::Set(const CScriptID &id) {
208+
SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
209+
return true;
210+
}
211+
212+
bool CBitcoinAddress::Set(const CTxDestination &dest) {
213+
return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
214+
}
215+
216+
bool CBitcoinAddress::IsValid() const {
217+
bool fCorrectSize = vchData.size() == 20;
218+
bool fKnownVersion = vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
219+
vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
220+
return fCorrectSize && fKnownVersion;
221+
}
222+
223+
CTxDestination CBitcoinAddress::Get() const {
224+
if (!IsValid())
225+
return CNoDestination();
226+
uint160 id;
227+
memcpy(&id, &vchData[0], 20);
228+
if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
229+
return CKeyID(id);
230+
else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
231+
return CScriptID(id);
232+
else
233+
return CNoDestination();
234+
}
235+
236+
bool CBitcoinAddress::GetKeyID(CKeyID &keyID) const {
237+
if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
238+
return false;
239+
uint160 id;
240+
memcpy(&id, &vchData[0], 20);
241+
keyID = CKeyID(id);
242+
return true;
243+
}
244+
245+
bool CBitcoinAddress::IsScript() const {
246+
return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
247+
}
248+
249+
void CBitcoinSecret::SetKey(const CKey& vchSecret) {
250+
assert(vchSecret.IsValid());
251+
SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
252+
if (vchSecret.IsCompressed())
253+
vchData.push_back(1);
254+
}
255+
256+
CKey CBitcoinSecret::GetKey() {
257+
CKey ret;
258+
ret.Set(&vchData[0], &vchData[32], vchData.size() > 32 && vchData[32] == 1);
259+
return ret;
260+
}
261+
262+
bool CBitcoinSecret::IsValid() const {
263+
bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
264+
bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
265+
return fExpectedFormat && fCorrectVersion;
266+
}
267+
268+
bool CBitcoinSecret::SetString(const char* pszSecret) {
269+
return CBase58Data::SetString(pszSecret) && IsValid();
270+
}
271+
272+
bool CBitcoinSecret::SetString(const std::string& strSecret) {
273+
return SetString(strSecret.c_str());
274+
}

0 commit comments

Comments
 (0)