diff --git a/src/Makefile.am b/src/Makefile.am index 451a9154c..2057fba26 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -152,6 +152,7 @@ BITCOIN_CORE_H = \ httpserver.h \ init.h \ key.h \ + key_io.h \ keystore.h \ dbwrapper.h \ limitedmap.h \ @@ -368,6 +369,7 @@ libbitcoin_common_a_SOURCES = \ core_write.cpp \ hash.cpp \ key.cpp \ + key_io.cpp \ keystore.cpp \ netbase.cpp \ primitives/block.cpp \ diff --git a/src/base58.cpp b/src/base58.cpp index f3eb73e45..137ce2c9e 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -4,21 +4,12 @@ #include "base58.h" -#include "hash.h" -#include "script/script.h" -#include "uint256.h" +#include +#include -#include "version.h" -#include "streams.h" - -#include -#include - -#include #include #include - /** All alphanumeric characters except for "0", "I", "O", and "l" */ static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; @@ -143,227 +134,3 @@ bool DecodeBase58Check(const std::string& str, std::vector& vchRe { return DecodeBase58Check(str.c_str(), vchRet); } - -CBase58Data::CBase58Data() -{ - vchVersion.clear(); - vchData.clear(); -} - -void CBase58Data::SetData(const std::vector& 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& 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 vchTemp; - bool rc58 = DecodeBase58Check(psz, vchTemp); - if ((!rc58) || (vchTemp.size() < nVersionBytes)) { - vchData.clear(); - vchVersion.clear(); - 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, unsigned int nVersionBytes) -{ - return SetString(str.c_str(), nVersionBytes); -} - -std::string CBase58Data::ToString() const -{ - std::vector 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 -{ -private: - const CChainParams& m_params; - -public: - DestinationEncoder(const CChainParams& params) : m_params(params) {} - - std::string operator()(const CKeyID& id) const - { - std::vector data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS); - data.insert(data.end(), id.begin(), id.end()); - return EncodeBase58Check(data); - } - - std::string operator()(const CScriptID& id) const - { - std::vector 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) -{ - std::vector data; - uint160 hash; - if (DecodeBase58Check(str, data)) { - // base58-encoded Bitcoin addresses. - // Public-key-hash-addresses have version 0 (or 111 testnet). - // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key. - const std::vector& 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); - } - // Script-hash-addresses have version 5 (or 196 testnet). - // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script. - const std::vector& 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(); -} -} // namespace - -void CBitcoinSecret::SetKey(const CKey& vchSecret) -{ - assert(vchSecret.IsValid()); - SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size()); - if (vchSecret.IsCompressed()) - vchData.push_back(1); -} - -CKey CBitcoinSecret::GetKey() -{ - CKey ret; - assert(vchData.size() >= 32); - ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1); - return ret; -} - -bool CBitcoinSecret::IsValid() const -{ - bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1); - bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY); - return fExpectedFormat && fCorrectVersion; -} - -bool CBitcoinSecret::SetString(const char* pszSecret) -{ - return CBase58Data::SetString(pszSecret, 1) && IsValid(); -} - -bool CBitcoinSecret::SetString(const std::string& strSecret) -{ - return SetString(strSecret.c_str()); -} - -std::string EncodeDestination(const CTxDestination& dest) -{ - return boost::apply_visitor(DestinationEncoder(Params()), dest); -} - -CTxDestination DecodeDestination(const std::string& str) -{ - return DecodeDestination(str, Params()); -} - -bool IsValidDestinationString(const std::string& str, const CChainParams& params) -{ - return IsValidDestination(DecodeDestination(str, params)); -} - -bool IsValidDestinationString(const std::string& str) -{ - return IsValidDestinationString(str, Params()); -} - -template -bool CZCEncoding::Set(const DATA_TYPE& addr) -{ - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << addr; - std::vector addrSerialized(ss.begin(), ss.end()); - assert(addrSerialized.size() == SER_SIZE); - SetData(Params().Base58Prefix(PREFIX), &addrSerialized[0], SER_SIZE); - return true; -} - -template -DATA_TYPE CZCEncoding::Get() const -{ - if (vchData.size() != SER_SIZE) { - throw std::runtime_error( - PrependName(" is invalid") - ); - } - - if (vchVersion != Params().Base58Prefix(PREFIX)) { - throw std::runtime_error( - PrependName(" is for wrong network type") - ); - } - - std::vector serialized(vchData.begin(), vchData.end()); - - CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION); - DATA_TYPE ret; - ss >> ret; - return ret; -} - -// Explicit instantiations for libzcash::PaymentAddress -template bool CZCEncoding::Set(const libzcash::PaymentAddress& addr); -template libzcash::PaymentAddress CZCEncoding::Get() const; - -// Explicit instantiations for libzcash::ViewingKey -template bool CZCEncoding::Set(const libzcash::ViewingKey& vk); -template libzcash::ViewingKey CZCEncoding::Get() const; - -// Explicit instantiations for libzcash::SpendingKey -template bool CZCEncoding::Set(const libzcash::SpendingKey& sk); -template libzcash::SpendingKey CZCEncoding::Get() const; diff --git a/src/base58.h b/src/base58.h index 9e90db78f..3c926fca0 100644 --- a/src/base58.h +++ b/src/base58.h @@ -14,13 +14,6 @@ #ifndef BITCOIN_BASE58_H #define BITCOIN_BASE58_H -#include "chainparams.h" -#include "key.h" -#include "pubkey.h" -#include "script/standard.h" -#include "support/allocators/zeroafterfree.h" -#include "zcash/Address.hpp" - #include #include @@ -57,139 +50,12 @@ std::string EncodeBase58Check(const std::vector& vchIn); * Decode a base58-encoded string (psz) that includes a checksum into a byte * vector (vchRet), return true if decoding is successful */ -inline bool DecodeBase58Check(const char* psz, std::vector& vchRet); +bool DecodeBase58Check(const char* psz, std::vector& vchRet); /** * Decode a base58-encoded string (str) that includes a checksum into a byte * vector (vchRet), return true if decoding is successful */ -inline bool DecodeBase58Check(const std::string& str, std::vector& vchRet); - -/** - * Base class for all base58-encoded data - */ -class CBase58Data -{ -protected: - //! the version byte(s) - std::vector vchVersion; - - //! the actually encoded data - typedef std::vector > vector_uchar; - vector_uchar vchData; - - CBase58Data(); - void SetData(const std::vector &vchVersionIn, const void* pdata, size_t nSize); - void SetData(const std::vector &vchVersionIn, const unsigned char *pbegin, const unsigned char *pend); - -public: - bool SetString(const char* psz, unsigned int nVersionBytes); - bool SetString(const std::string& str, unsigned int nVersionBytes); - std::string ToString() const; - int CompareTo(const CBase58Data& b58) const; - - bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; } - bool operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; } - bool operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; } - bool operator< (const CBase58Data& b58) const { return CompareTo(b58) < 0; } - bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; } -}; - -template -class CZCEncoding : public CBase58Data { -protected: - virtual std::string PrependName(const std::string& s) const = 0; - -public: - bool Set(const DATA_TYPE& addr); - - DATA_TYPE Get() const; -}; - -class CZCPaymentAddress : public CZCEncoding { -protected: - std::string PrependName(const std::string& s) const { return "payment address" + s; } - -public: - CZCPaymentAddress() {} - - CZCPaymentAddress(const std::string& strAddress) { SetString(strAddress.c_str(), 2); } - CZCPaymentAddress(const libzcash::PaymentAddress& addr) { Set(addr); } -}; - -class CZCViewingKey : public CZCEncoding { -protected: - std::string PrependName(const std::string& s) const { return "viewing key" + s; } - -public: - CZCViewingKey() {} - - CZCViewingKey(const std::string& strViewingKey) { SetString(strViewingKey.c_str(), 3); } - CZCViewingKey(const libzcash::ViewingKey& vk) { Set(vk); } -}; - -class CZCSpendingKey : public CZCEncoding { -protected: - std::string PrependName(const std::string& s) const { return "spending key" + s; } - -public: - CZCSpendingKey() {} - - CZCSpendingKey(const std::string& strAddress) { SetString(strAddress.c_str(), 2); } - CZCSpendingKey(const libzcash::SpendingKey& addr) { Set(addr); } -}; - -/** - * A base58-encoded secret key - */ -class CBitcoinSecret : public CBase58Data -{ -public: - void SetKey(const CKey& vchSecret); - CKey GetKey(); - bool IsValid() const; - bool SetString(const char* pszSecret); - bool SetString(const std::string& strSecret); - - CBitcoinSecret(const CKey& vchSecret) { SetKey(vchSecret); } - CBitcoinSecret() {} -}; - -template class CBitcoinExtKeyBase : public CBase58Data -{ -public: - void SetKey(const K &key) { - unsigned char vch[Size]; - key.Encode(vch); - SetData(Params().Base58Prefix(Type), vch, vch+Size); - } - - K GetKey() { - K ret; - if (vchData.size() == Size) { - // If base58 encoded data does not hold an ext key, return a !IsValid() key - ret.Decode(vchData.data()); - } - return ret; - } - - CBitcoinExtKeyBase(const K &key) { - SetKey(key); - } - - CBitcoinExtKeyBase(const std::string& strBase58c) { - SetString(strBase58c.c_str(), Params().Base58Prefix(Type).size()); - } - - CBitcoinExtKeyBase() {} -}; - -typedef CBitcoinExtKeyBase CBitcoinExtKey; -typedef CBitcoinExtKeyBase CBitcoinExtPubKey; - -std::string EncodeDestination(const CTxDestination& dest); -CTxDestination DecodeDestination(const std::string& str); -bool IsValidDestinationString(const std::string& str); -bool IsValidDestinationString(const std::string& str, const CChainParams& params); +bool DecodeBase58Check(const std::string& str, std::vector& vchRet); #endif // BITCOIN_BASE58_H diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 1158563f2..3ee3c0169 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -2,12 +2,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "base58.h" #include "clientversion.h" #include "coins.h" #include "consensus/consensus.h" #include "consensus/upgrades.h" #include "core_io.h" +#include "key_io.h" #include "keystore.h" #include "primitives/transaction.h" #include "script/script.h" @@ -400,12 +400,10 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& strInput) for (size_t kidx = 0; kidx < keysObj.size(); kidx++) { if (!keysObj[kidx].isStr()) throw std::runtime_error("privatekey not a std::string"); - CBitcoinSecret vchSecret; - bool fGood = vchSecret.SetString(keysObj[kidx].getValStr()); - if (!fGood) + CKey key = DecodeSecret(keysObj[kidx].getValStr()); + if (!key.IsValid()) { throw std::runtime_error("privatekey not valid"); - - CKey key = vchSecret.GetKey(); + } tempKeystore.AddKey(key); } diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 2c9aed2ea..d75231ce3 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -3,6 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "key_io.h" #include "main.h" #include "crypto/equihash.h" @@ -13,8 +14,6 @@ #include -#include "base58.h" - #include "chainparamsseeds.h" static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, const uint256& nNonce, const std::vector& nSolution, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) diff --git a/src/core_write.cpp b/src/core_write.cpp index df1f83456..43344656b 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -4,7 +4,7 @@ #include "core_io.h" -#include "base58.h" +#include "key_io.h" #include "primitives/transaction.h" #include "script/script.h" #include "script/standard.h" diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 6d37fdfac..ade815788 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -1,8 +1,8 @@ #include "httprpc.h" -#include "base58.h" #include "chainparams.h" #include "httpserver.h" +#include "key_io.h" #include "rpcprotocol.h" #include "rpcserver.h" #include "random.h" diff --git a/src/init.cpp b/src/init.cpp index 06d5fc171..2962f3b9a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -11,9 +11,6 @@ #include "crypto/common.h" #include "addrman.h" #include "amount.h" -#ifdef ENABLE_MINING -#include "base58.h" -#endif #include "checkpoints.h" #include "compat/sanity.h" #include "consensus/upgrades.h" @@ -21,6 +18,9 @@ #include "httpserver.h" #include "httprpc.h" #include "key.h" +#ifdef ENABLE_MINING +#include "key_io.h" +#endif #include "main.h" #include "metrics.h" #include "miner.h" diff --git a/src/key_io.cpp b/src/key_io.cpp new file mode 100644 index 000000000..77d63cca4 --- /dev/null +++ b/src/key_io.cpp @@ -0,0 +1,254 @@ +// Copyright (c) 2014-2016 The Bitcoin Core developers +// Copyright (c) 2016-2018 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include