Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ BITCOIN_CORE_H = \
activemasternode.h \
addrdb.h \
addrman.h \
attributes.h \
arith_uint256.h \
amount.h \
base58.h \
Expand Down Expand Up @@ -286,10 +287,12 @@ BITCOIN_CORE_H = \
util/memory.h \
util/system.h \
util/macros.h \
util/string.h \
util/threadnames.h \
utilstrencodings.h \
utilmoneystr.h \
utiltime.h \
util/vector.h \
validation.h \
validationinterface.h \
version.h \
Expand Down Expand Up @@ -394,7 +397,6 @@ libbitcoin_wallet_a_SOURCES = \
interfaces/wallet.cpp \
addressbook.cpp \
crypter.cpp \
key_io.cpp \
legacy/stakemodifier.cpp \
kernel.cpp \
wallet/db.cpp \
Expand Down Expand Up @@ -496,6 +498,7 @@ libbitcoin_common_a_SOURCES = \
coins.cpp \
compressor.cpp \
consensus/merkle.cpp \
key_io.cpp \
primitives/block.cpp \
primitives/transaction.cpp \
zpiv/zerocoin.cpp \
Expand Down Expand Up @@ -557,6 +560,7 @@ libbitcoin_util_a_SOURCES = \
utilmoneystr.cpp \
util/threadnames.cpp \
utilstrencodings.cpp \
util/string.cpp \
utiltime.cpp \
$(BITCOIN_CORE_H) \
$(LIBSAPLING_H)
Expand Down
22 changes: 22 additions & 0 deletions src/attributes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_ATTRIBUTES_H
#define BITCOIN_ATTRIBUTES_H

#if defined(__has_cpp_attribute)
# if __has_cpp_attribute(nodiscard)
# define NODISCARD [[nodiscard]]
# endif
#endif
#ifndef NODISCARD
# if defined(_MSC_VER) && _MSC_VER >= 1700
# define NODISCARD _Check_return_
# else
# define NODISCARD __attribute__((warn_unused_result))
# endif
#endif

#endif // BITCOIN_ATTRIBUTES_H
217 changes: 19 additions & 198 deletions src/base58.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@
#include "base58.h"

#include "hash.h"
#include "script/script.h"
#include "uint256.h"
#include "util/string.h"

#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include "uint256.h"

#include <algorithm>
#include <assert.h>
#include <sstream>
#include <vector>

#include <limits>

/** All alphanumeric characters except for "0", "I", "O", and "l" */
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch, int max_ret_len)
{
// Skip leading spaces.
while (*psz && isspace(*psz))
Expand All @@ -30,6 +30,7 @@ bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
int length = 0;
while (*psz == '1') {
zeroes++;
if (zeroes > max_ret_len) return false;
psz++;
}
// Allocate enough space in big-endian base256 representation.
Expand All @@ -51,6 +52,7 @@ bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
}
assert(carry == 0);
length = i;
if (length + zeroes > max_ret_len) return false;
psz++;
}
// Skip trailing spaces.
Expand All @@ -60,8 +62,6 @@ bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
return false;
// Skip leading zeroes in b256.
std::vector<unsigned char>::iterator it = b256.begin() + (size - length);
while (it != b256.end() && *it == 0)
it++;
// Copy result into output vector.
vch.reserve(zeroes + (b256.end() - it));
vch.assign(zeroes, 0x00);
Expand All @@ -70,10 +70,10 @@ bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
return true;
}

std::string DecodeBase58(const char* psz)
std::string DecodeBase58(const char* psz, int max_ret_len)
{
std::vector<unsigned char> vch;
DecodeBase58(psz, vch);
DecodeBase58(psz, vch, max_ret_len);
std::stringstream ss;
ss << std::hex;

Expand Down Expand Up @@ -130,9 +130,12 @@ std::string EncodeBase58(const std::vector<unsigned char>& vch)
return EncodeBase58(vch.data(), vch.data() + vch.size());
}

bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len)
{
return DecodeBase58(str.c_str(), vchRet);
if (!ValidAsCString(str)) {
return false;
}
return DecodeBase58(str.c_str(), vchRet, max_ret_len);
}

std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
Expand All @@ -144,9 +147,9 @@ std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
return EncodeBase58(vch);
}

bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet, int max_ret_len)
{
if (!DecodeBase58(psz, vchRet) ||
if (!DecodeBase58(psz, vchRet, max_ret_len > std::numeric_limits<int>::max() - 4 ? std::numeric_limits<int>::max() : max_ret_len + 4) ||
(vchRet.size() < 4)) {
vchRet.clear();
return false;
Expand All @@ -161,192 +164,10 @@ bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
return true;
}

bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret)
{
return DecodeBase58Check(str.c_str(), vchRet);
}

CBase58Data::CBase58Data()
{
vchVersion.clear();
vchData.clear();
}

void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const void* pdata, size_t nSize)
{
vchVersion = vchVersionIn;
vchData.resize(nSize);
if (!vchData.empty())
memcpy(vchData.data(), pdata, nSize);
}

void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend)
{
SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
}

bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes)
{
std::vector<unsigned char> vchTemp;
bool rc58 = DecodeBase58Check(psz, vchTemp);
if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
vchData.clear();
vchVersion.clear();
if (!ValidAsCString(str)) {
return false;
}
vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
vchData.resize(vchTemp.size() - nVersionBytes);
if (!vchData.empty())
memcpy(vchData.data(), vchTemp.data() + nVersionBytes, vchData.size());
memory_cleanse(vchTemp.data(), vchTemp.size());
return true;
}

bool CBase58Data::SetString(const std::string& str)
{
if (str.empty())
return false;
return SetString(str.c_str());
}

std::string CBase58Data::ToString() const
{
std::vector<unsigned char> vch = vchVersion;
vch.insert(vch.end(), vchData.begin(), vchData.end());
return EncodeBase58Check(vch);
}

int CBase58Data::CompareTo(const CBase58Data& b58) const
{
if (vchVersion < b58.vchVersion)
return -1;
if (vchVersion > b58.vchVersion)
return 1;
if (vchData < b58.vchData)
return -1;
if (vchData > b58.vchData)
return 1;
return 0;
}

namespace
{
class DestinationEncoder : public boost::static_visitor<std::string>
{
private:
const CChainParams& m_params;
const CChainParams::Base58Type m_addrType;

public:
DestinationEncoder(const CChainParams& params, const CChainParams::Base58Type _addrType = CChainParams::PUBKEY_ADDRESS) : m_params(params), m_addrType(_addrType) {}

std::string operator()(const CKeyID& id) const
{
std::vector<unsigned char> data = m_params.Base58Prefix(m_addrType);
data.insert(data.end(), id.begin(), id.end());
return EncodeBase58Check(data);
}

std::string operator()(const CScriptID& id) const
{
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
data.insert(data.end(), id.begin(), id.end());
return EncodeBase58Check(data);
}

std::string operator()(const CNoDestination& no) const { return ""; }
};

CTxDestination DecodeDestination(const std::string& str, const CChainParams& params, bool& isStaking)
{
std::vector<unsigned char> data;
uint160 hash;
if (DecodeBase58Check(str, data)) {
// base58-encoded PIVX addresses.
// Public-key-hash-addresses have version 30 (or 139 testnet).
// The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin());
return CKeyID(hash);
}
// Public-key-hash-coldstaking-addresses have version 63 (or 73 testnet).
const std::vector<unsigned char>& staking_prefix = params.Base58Prefix(CChainParams::STAKING_ADDRESS);
if (data.size() == hash.size() + staking_prefix.size() && std::equal(staking_prefix.begin(), staking_prefix.end(), data.begin())) {
isStaking = true;
std::copy(data.begin() + staking_prefix.size(), data.end(), hash.begin());
return CKeyID(hash);
}
// Script-hash-addresses have version 13 (or 19 testnet).
// The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin());
return CScriptID(hash);
}
}
return CNoDestination();
}

} // anon namespace

CKey DecodeSecret(const std::string& str)
{
CKey key;
std::vector<unsigned char> data;
if (DecodeBase58Check(str, data)) {
const std::vector<unsigned char>& privkey_prefix = Params().Base58Prefix(CChainParams::SECRET_KEY);
if ((data.size() == 32 + privkey_prefix.size() || (data.size() == 33 + privkey_prefix.size() && data.back() == 1)) &&
std::equal(privkey_prefix.begin(), privkey_prefix.end(), data.begin())) {
bool compressed = data.size() == 33 + privkey_prefix.size();
key.Set(data.begin() + privkey_prefix.size(), data.begin() + privkey_prefix.size() + 32, compressed);
}
}
memory_cleanse(data.data(), data.size());
return key;
}

std::string EncodeSecret(const CKey& key)
{
assert(key.IsValid());
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::SECRET_KEY);
data.insert(data.end(), key.begin(), key.end());
if (key.IsCompressed()) {
data.push_back(1);
}
std::string ret = EncodeBase58Check(data);
memory_cleanse(data.data(), data.size());
return ret;
}

std::string EncodeDestination(const CTxDestination& dest, bool isStaking)
{
return EncodeDestination(dest, isStaking ? CChainParams::STAKING_ADDRESS : CChainParams::PUBKEY_ADDRESS);
}

std::string EncodeDestination(const CTxDestination& dest, const CChainParams::Base58Type addrType)
{
return boost::apply_visitor(DestinationEncoder(Params(), addrType), dest);
}

CTxDestination DecodeDestination(const std::string& str)
{
bool isStaking;
return DecodeDestination(str, Params(), isStaking);
}

CTxDestination DecodeDestination(const std::string& str, bool& isStaking)
{
return DecodeDestination(str, Params(), isStaking);
}

bool IsValidDestinationString(const std::string& str, bool fStaking, const CChainParams& params)
{
bool isStaking = false;
return IsValidDestination(DecodeDestination(str, params, isStaking)) && (isStaking == fStaking);
}

bool IsValidDestinationString(const std::string& str, bool isStaking)
{
return IsValidDestinationString(str, isStaking, Params());
return DecodeBase58Check(str.c_str(), vchRet, max_ret);
}
Loading