diff --git a/src/base58.cpp b/src/base58.cpp index f59eb6ba2..f3eb73e45 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -5,19 +5,20 @@ #include "base58.h" #include "hash.h" +#include "script/script.h" #include "uint256.h" #include "version.h" #include "streams.h" -#include -#include -#include -#include -#include #include #include +#include +#include +#include + + /** All alphanumeric characters except for "0", "I", "O", and "l" */ static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; @@ -206,89 +207,55 @@ int CBase58Data::CompareTo(const CBase58Data& b58) const namespace { -class CBitcoinAddressVisitor : public boost::static_visitor +class DestinationEncoder : public boost::static_visitor { private: - CBitcoinAddress* addr; + const CChainParams& m_params; public: - CBitcoinAddressVisitor(CBitcoinAddress* addrIn) : addr(addrIn) {} + DestinationEncoder(const CChainParams& params) : m_params(params) {} - bool operator()(const CKeyID& id) const { return addr->Set(id); } - bool operator()(const CScriptID& id) const { return addr->Set(id); } - bool operator()(const CNoDestination& no) const { return false; } + 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 ""; } }; -} // anon namespace - -bool CBitcoinAddress::Set(const CKeyID& id) +CTxDestination DecodeDestination(const std::string& str, const CChainParams& params) { - SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20); - return true; -} - -bool CBitcoinAddress::Set(const CScriptID& id) -{ - SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20); - return true; -} - -bool CBitcoinAddress::Set(const CTxDestination& dest) -{ - return boost::apply_visitor(CBitcoinAddressVisitor(this), dest); -} - -bool CBitcoinAddress::IsValid() const -{ - return IsValid(Params()); -} - -bool CBitcoinAddress::IsValid(const CChainParams& params) const -{ - bool fCorrectSize = vchData.size() == 20; - bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) || - vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS); - return fCorrectSize && fKnownVersion; -} - -bool CBitcoinAddress::SetString(const char* pszAddress) -{ - return CBase58Data::SetString(pszAddress, 2); -} - -bool CBitcoinAddress::SetString(const std::string& strAddress) -{ - return SetString(strAddress.c_str()); -} - -CTxDestination CBitcoinAddress::Get() const -{ - if (!IsValid()) - return CNoDestination(); - uint160 id; - memcpy(&id, vchData.data(), 20); - if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)) - return CKeyID(id); - else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS)) - return CScriptID(id); - else - return CNoDestination(); -} - -bool CBitcoinAddress::GetKeyID(CKeyID& keyID) const -{ - if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)) - return false; - uint160 id; - memcpy(&id, vchData.data(), 20); - keyID = CKeyID(id); - return true; -} - -bool CBitcoinAddress::IsScript() const -{ - return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS); + 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) { @@ -323,6 +290,26 @@ 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) { diff --git a/src/base58.h b/src/base58.h index 38262fb95..9e90db78f 100644 --- a/src/base58.h +++ b/src/base58.h @@ -17,7 +17,6 @@ #include "chainparams.h" #include "key.h" #include "pubkey.h" -#include "script/script.h" #include "script/standard.h" #include "support/allocators/zeroafterfree.h" #include "zcash/Address.hpp" @@ -140,32 +139,6 @@ public: CZCSpendingKey(const libzcash::SpendingKey& addr) { Set(addr); } }; -/** 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. - * Script-hash-addresses have version 5 (or 196 testnet). - * The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script. - */ -class CBitcoinAddress : public CBase58Data { -public: - bool Set(const CKeyID &id); - bool Set(const CScriptID &id); - bool Set(const CTxDestination &dest); - bool IsValid() const; - bool IsValid(const CChainParams ¶ms) const; - bool SetString(const char* pszSecret); - bool SetString(const std::string& strSecret); - - CBitcoinAddress() {} - CBitcoinAddress(const CTxDestination &dest) { Set(dest); } - CBitcoinAddress(const std::string& strAddress) { SetString(strAddress); } - CBitcoinAddress(const char* pszAddress) { SetString(pszAddress); } - - CTxDestination Get() const; - bool GetKeyID(CKeyID &keyID) const; - bool IsScript() const; -}; - /** * A base58-encoded secret key */ @@ -214,4 +187,9 @@ public: 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); + #endif // BITCOIN_BASE58_H diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 82e72d0bd..1158563f2 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -240,12 +240,11 @@ static void MutateTxAddOutAddr(CMutableTransaction& tx, const std::string& strIn // extract and validate ADDRESS std::string strAddr = strInput.substr(pos + 1, std::string::npos); - CBitcoinAddress addr(strAddr); - if (!addr.IsValid()) + CTxDestination destination = DecodeDestination(strAddr); + if (!IsValidDestination(destination)) { throw std::runtime_error("invalid TX output address"); - - // build standard output script via GetScriptForDestination() - CScript scriptPubKey = GetScriptForDestination(addr.Get()); + } + CScript scriptPubKey = GetScriptForDestination(destination); // construct TxOut, append to transaction output list CTxOut txout(value, scriptPubKey); diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 1ce12de65..2c9aed2ea 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -502,10 +502,10 @@ std::string CChainParams::GetFoundersRewardAddressAtHeight(int nHeight) const { CScript CChainParams::GetFoundersRewardScriptAtHeight(int nHeight) const { assert(nHeight > 0 && nHeight <= consensus.GetLastFoundersRewardBlockHeight()); - CBitcoinAddress address(GetFoundersRewardAddressAtHeight(nHeight).c_str()); - assert(address.IsValid()); - assert(address.IsScript()); - CScriptID scriptID = boost::get(address.Get()); // Get() returns a boost variant + CTxDestination address = DecodeDestination(GetFoundersRewardAddressAtHeight(nHeight).c_str()); + assert(IsValidDestination(address)); + assert(boost::get(&address) != nullptr); + CScriptID scriptID = boost::get(address); // address is a boost variant CScript script = CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL; return script; } diff --git a/src/core_write.cpp b/src/core_write.cpp index 533fedfe7..df1f83456 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -143,8 +143,9 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey, out.pushKV("type", GetTxnOutputType(type)); UniValue a(UniValue::VARR); - BOOST_FOREACH(const CTxDestination& addr, addresses) - a.push_back(CBitcoinAddress(addr).ToString()); + for (const CTxDestination& addr : addresses) { + a.push_back(EncodeDestination(addr)); + } out.pushKV("addresses", a); } diff --git a/src/gtest/test_foundersreward.cpp b/src/gtest/test_foundersreward.cpp index 8ffe51280..a3d2b8c56 100644 --- a/src/gtest/test_foundersreward.cpp +++ b/src/gtest/test_foundersreward.cpp @@ -59,7 +59,7 @@ TEST(founders_reward_test, create_testnet_2of3multisig) { pWallet->AddCScript(result); pWallet->SetAddressBook(innerID, "", "receive"); - std::string address = CBitcoinAddress(innerID).ToString(); + std::string address = EncodeDestination(innerID); addresses.push_back(address); } diff --git a/src/init.cpp b/src/init.cpp index 56d886c74..06d5fc171 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1079,8 +1079,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) #ifdef ENABLE_MINING if (mapArgs.count("-mineraddress")) { - CBitcoinAddress addr; - if (!addr.SetString(mapArgs["-mineraddress"])) { + CTxDestination addr = DecodeDestination(mapArgs["-mineraddress"]); + if (!IsValidDestination(addr)) { return InitError(strprintf( _("Invalid address for -mineraddress=: '%s' (must be a transparent address)"), mapArgs["-mineraddress"])); @@ -1717,9 +1717,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) bool minerAddressInLocalWallet = false; if (pwalletMain) { // Address has alreday been validated - CBitcoinAddress addr(mapArgs["-mineraddress"]); - CKeyID keyID; - addr.GetKeyID(keyID); + CTxDestination addr = DecodeDestination(mapArgs["-mineraddress"]); + CKeyID keyID = boost::get(addr); minerAddressInLocalWallet = pwalletMain->HaveKey(keyID); } if (GetBoolArg("-minetolocalwallet", true) && !minerAddressInLocalWallet) { diff --git a/src/miner.cpp b/src/miner.cpp index bff90928e..44e28f82b 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -395,9 +395,9 @@ boost::optional GetMinerScriptPubKey() #endif { CKeyID keyID; - CBitcoinAddress addr; - if (addr.SetString(GetArg("-mineraddress", ""))) { - addr.GetKeyID(keyID); + CTxDestination addr = DecodeDestination(GetArg("-mineraddress", "")); + if (IsValidDestination(addr)) { + keyID = boost::get(addr); } else { #ifdef ENABLE_WALLET CPubKey pubkey; diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 96dbb756a..1f863ae70 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -137,8 +137,9 @@ public: obj.push_back(Pair("script", GetTxnOutputType(whichType))); obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end()))); UniValue a(UniValue::VARR); - BOOST_FOREACH(const CTxDestination& addr, addresses) - a.push_back(CBitcoinAddress(addr).ToString()); + for (const CTxDestination& addr : addresses) { + a.push_back(EncodeDestination(addr)); + } obj.push_back(Pair("addresses", a)); if (whichType == TX_MULTISIG) obj.push_back(Pair("sigsrequired", nRequired)); @@ -178,15 +179,14 @@ UniValue validateaddress(const UniValue& params, bool fHelp) LOCK(cs_main); #endif - CBitcoinAddress address(params[0].get_str()); - bool isValid = address.IsValid(); + CTxDestination dest = DecodeDestination(params[0].get_str()); + bool isValid = IsValidDestination(dest); UniValue ret(UniValue::VOBJ); ret.push_back(Pair("isvalid", isValid)); if (isValid) { - CTxDestination dest = address.Get(); - string currentAddress = address.ToString(); + std::string currentAddress = EncodeDestination(dest); ret.push_back(Pair("address", currentAddress)); CScript scriptPubKey = GetScriptForDestination(dest); @@ -293,17 +293,16 @@ CScript _createmultisig_redeemScript(const UniValue& params) const std::string& ks = keys[i].get_str(); #ifdef ENABLE_WALLET // Case 1: Bitcoin address and we have full public key: - CBitcoinAddress address(ks); - if (pwalletMain && address.IsValid()) - { - CKeyID keyID; - if (!address.GetKeyID(keyID)) - throw runtime_error( - strprintf("%s does not refer to a key",ks)); + CTxDestination dest = DecodeDestination(ks); + if (pwalletMain && IsValidDestination(dest)) { + const CKeyID *keyID = boost::get(&dest); + if (!keyID) { + throw std::runtime_error(strprintf("%s does not refer to a key", ks)); + } CPubKey vchPubKey; - if (!pwalletMain->GetPubKey(keyID, vchPubKey)) - throw runtime_error( - strprintf("no full public key for address %s",ks)); + if (!pwalletMain->GetPubKey(*keyID, vchPubKey)) { + throw std::runtime_error(strprintf("no full public key for address %s", ks)); + } if (!vchPubKey.IsFullyValid()) throw runtime_error(" Invalid public key: "+ks); pubkeys[i] = vchPubKey; @@ -367,10 +366,9 @@ UniValue createmultisig(const UniValue& params, bool fHelp) // Construct using pay-to-script-hash: CScript inner = _createmultisig_redeemScript(params); CScriptID innerID(inner); - CBitcoinAddress address(innerID); UniValue result(UniValue::VOBJ); - result.push_back(Pair("address", address.ToString())); + result.push_back(Pair("address", EncodeDestination(innerID))); result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end()))); return result; @@ -405,13 +403,15 @@ UniValue verifymessage(const UniValue& params, bool fHelp) string strSign = params[1].get_str(); string strMessage = params[2].get_str(); - CBitcoinAddress addr(strAddress); - if (!addr.IsValid()) + CTxDestination destination = DecodeDestination(strAddress); + if (!IsValidDestination(destination)) { throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address"); + } - CKeyID keyID; - if (!addr.GetKeyID(keyID)) + const CKeyID *keyID = boost::get(&destination); + if (!keyID) { throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); + } bool fInvalid = false; vector vchSig = DecodeBase64(strSign.c_str(), &fInvalid); @@ -427,7 +427,7 @@ UniValue verifymessage(const UniValue& params, bool fHelp) if (!pubkey.RecoverCompact(ss.GetHash(), vchSig)) return false; - return (pubkey.GetID() == keyID); + return (pubkey.GetID() == *keyID); } UniValue setmocktime(const UniValue& params, bool fHelp) diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 7e03df07a..3f6981619 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -50,8 +50,9 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fInclud out.push_back(Pair("type", GetTxnOutputType(type))); UniValue a(UniValue::VARR); - BOOST_FOREACH(const CTxDestination& addr, addresses) - a.push_back(CBitcoinAddress(addr).ToString()); + for (const CTxDestination& addr : addresses) { + a.push_back(EncodeDestination(addr)); + } out.push_back(Pair("addresses", a)); } @@ -492,18 +493,19 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) rawTx.vin.push_back(in); } - set setAddress; + std::set destinations; vector addrList = sendTo.getKeys(); - BOOST_FOREACH(const string& name_, addrList) { - CBitcoinAddress address(name_); - if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Zcash address: ")+name_); + for (const std::string& name_ : addrList) { + CTxDestination destination = DecodeDestination(name_); + if (!IsValidDestination(destination)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Zcash address: ") + name_); + } - if (setAddress.count(address)) - throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_); - setAddress.insert(address); + if (!destinations.insert(destination).second) { + throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_); + } - CScript scriptPubKey = GetScriptForDestination(address.Get()); + CScript scriptPubKey = GetScriptForDestination(destination); CAmount nAmount = AmountFromValue(sendTo[name_]); CTxOut out(nAmount, scriptPubKey); @@ -646,7 +648,7 @@ UniValue decodescript(const UniValue& params, bool fHelp) } ScriptPubKeyToJSON(script, r, false); - r.push_back(Pair("p2sh", CBitcoinAddress(CScriptID(script)).ToString())); + r.push_back(Pair("p2sh", EncodeDestination(CScriptID(script)))); return r; } diff --git a/src/script/standard.cpp b/src/script/standard.cpp index ce50e3aad..88cde3698 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -316,3 +316,7 @@ CScript GetScriptForMultisig(int nRequired, const std::vector& keys) script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG; return script; } + +bool IsValidDestination(const CTxDestination& dest) { + return dest.which() != 0; +} diff --git a/src/script/standard.h b/src/script/standard.h index da778878b..fdb02f7c7 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -78,10 +78,13 @@ public: * * CNoDestination: no destination set * * CKeyID: TX_PUBKEYHASH destination * * CScriptID: TX_SCRIPTHASH destination - * A CTxDestination is the internal data type encoded in a CBitcoinAddress + * A CTxDestination is the internal data type encoded in a bitcoin address */ typedef boost::variant CTxDestination; +/** Check whether a CTxDestination is a CNoDestination. */ +bool IsValidDestination(const CTxDestination& dest); + const char* GetTxnOutputType(txnouttype t); bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector >& vSolutionsRet); diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 361d8b8ea..0531aaadf 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -123,7 +123,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid))); std::vector result; CBitcoinSecret secret; - CBitcoinAddress addr; + CTxDestination destination; SelectParams(CBaseChainParams::MAIN); for (size_t idx = 0; idx < tests.size(); idx++) { @@ -147,7 +147,6 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) { bool isCompressed = find_value(metadata, "isCompressed").get_bool(); // Must be valid private key - // Note: CBitcoinSecret::SetString tests isValid, whereas CBitcoinAddress does not! BOOST_CHECK_MESSAGE(secret.SetString(exp_base58string), "!SetString:"+ strTest); BOOST_CHECK_MESSAGE(secret.IsValid(), "!IsValid:" + strTest); CKey privkey = secret.GetKey(); @@ -155,18 +154,17 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) BOOST_CHECK_MESSAGE(privkey.size() == exp_payload.size() && std::equal(privkey.begin(), privkey.end(), exp_payload.begin()), "key mismatch:" + strTest); // Private key must be invalid public key - addr.SetString(exp_base58string); - BOOST_CHECK_MESSAGE(!addr.IsValid(), "IsValid privkey as pubkey:" + strTest); + destination = DecodeDestination(exp_base58string); + BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid privkey as pubkey:" + strTest); } else { std::string exp_addrType = find_value(metadata, "addrType").get_str(); // "script" or "pubkey" // Must be valid public key - BOOST_CHECK_MESSAGE(addr.SetString(exp_base58string), "SetString:" + strTest); - BOOST_CHECK_MESSAGE(addr.IsValid(), "!IsValid:" + strTest); - BOOST_CHECK_MESSAGE(addr.IsScript() == (exp_addrType == "script"), "isScript mismatch" + strTest); - CTxDestination dest = addr.Get(); - BOOST_CHECK_MESSAGE(boost::apply_visitor(TestAddrTypeVisitor(exp_addrType), dest), "addrType mismatch" + strTest); + destination = DecodeDestination(exp_base58string); + BOOST_CHECK_MESSAGE(IsValidDestination(destination), "!IsValid:" + strTest); + BOOST_CHECK_MESSAGE((boost::get(&destination) != nullptr) == (exp_addrType == "script"), "isScript mismatch" + strTest); + BOOST_CHECK_MESSAGE(boost::apply_visitor(TestAddrTypeVisitor(exp_addrType), destination), "addrType mismatch" + strTest); // Public key must be invalid private key secret.SetString(exp_base58string); @@ -229,17 +227,11 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) BOOST_ERROR("Bad addrtype: " << strTest); continue; } - CBitcoinAddress addrOut; - BOOST_CHECK_MESSAGE(addrOut.Set(dest), "encode dest: " + strTest); - BOOST_CHECK_MESSAGE(addrOut.ToString() == exp_base58string, "mismatch: " + strTest); + std::string address = EncodeDestination(dest); + BOOST_CHECK_MESSAGE(address == exp_base58string, "mismatch: " + strTest); } } - // Visiting a CNoDestination must fail - CBitcoinAddress dummyAddr; - CTxDestination nodest = CNoDestination(); - BOOST_CHECK(!dummyAddr.Set(nodest)); - SelectParams(CBaseChainParams::MAIN); } @@ -249,7 +241,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_invalid) UniValue tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases std::vector result; CBitcoinSecret secret; - CBitcoinAddress addr; + CTxDestination destination; for (size_t idx = 0; idx < tests.size(); idx++) { UniValue test = tests[idx]; @@ -262,8 +254,8 @@ BOOST_AUTO_TEST_CASE(base58_keys_invalid) std::string exp_base58string = test[0].get_str(); // must be invalid as public and as private key - addr.SetString(exp_base58string); - BOOST_CHECK_MESSAGE(!addr.IsValid(), "IsValid pubkey:" + strTest); + destination = DecodeDestination(exp_base58string); + BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid pubkey:" + strTest); secret.SetString(exp_base58string); BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid privkey:" + strTest); } diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 37e1eb244..ed997a95a 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -21,17 +21,16 @@ using namespace std; using namespace libzcash; -static const string strSecret1 ("5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj"); -static const string strSecret2 ("5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3"); -static const string strSecret1C ("Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw"); -static const string strSecret2C ("L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g"); -static const CBitcoinAddress addr1 ("t1h8SqgtM3QM5e2M8EzhhT1yL2PXXtA6oqe"); -static const CBitcoinAddress addr2 ("t1Xxa5ZVPKvs9bGMn7aWTiHjyHvR31XkUst"); -static const CBitcoinAddress addr1C("t1ffus9J1vhxvFqLoExGBRPjE7BcJxiSCTC"); -static const CBitcoinAddress addr2C("t1VJL2dPUyXK7avDRGqhqQA5bw2eEMdhyg6"); +static const std::string strSecret1 = "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj"; +static const std::string strSecret2 = "5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3"; +static const std::string strSecret1C = "Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw"; +static const std::string strSecret2C = "L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g"; +static const std::string addr1 = "t1h8SqgtM3QM5e2M8EzhhT1yL2PXXtA6oqe"; +static const std::string addr2 = "t1Xxa5ZVPKvs9bGMn7aWTiHjyHvR31XkUst"; +static const std::string addr1C = "t1ffus9J1vhxvFqLoExGBRPjE7BcJxiSCTC"; +static const std::string addr2C = "t1VJL2dPUyXK7avDRGqhqQA5bw2eEMdhyg6"; - -static const string strAddressBad("t1aMkLwU1LcMZYN7TgXUJAwzA1r44dbLkSp"); +static const std::string strAddressBad = "t1aMkLwU1LcMZYN7TgXUJAwzA1r44dbLkSp"; #ifdef KEY_TESTS_DUMPINFO @@ -56,7 +55,7 @@ void dumpKeyInfo(uint256 privkey) key.SetSecret(secret, fCompressed); vector vchPubKey = key.GetPubKey(); printf(" * pubkey (hex): %s\n", HexStr(vchPubKey).c_str()); - printf(" * address (base58): %s\n", CBitcoinAddress(vchPubKey).ToString().c_str()); + printf(" * address (base58): %s\n", EncodeDestination(vchPubKey).c_str()); } } #endif @@ -107,10 +106,10 @@ BOOST_AUTO_TEST_CASE(key_test1) BOOST_CHECK(!key2C.VerifyPubKey(pubkey2)); BOOST_CHECK(key2C.VerifyPubKey(pubkey2C)); - BOOST_CHECK(addr1.Get() == CTxDestination(pubkey1.GetID())); - BOOST_CHECK(addr2.Get() == CTxDestination(pubkey2.GetID())); - BOOST_CHECK(addr1C.Get() == CTxDestination(pubkey1C.GetID())); - BOOST_CHECK(addr2C.Get() == CTxDestination(pubkey2C.GetID())); + BOOST_CHECK(DecodeDestination(addr1) == CTxDestination(pubkey1.GetID())); + BOOST_CHECK(DecodeDestination(addr2) == CTxDestination(pubkey2.GetID())); + BOOST_CHECK(DecodeDestination(addr1C) == CTxDestination(pubkey1C.GetID())); + BOOST_CHECK(DecodeDestination(addr2C) == CTxDestination(pubkey2C.GetID())); for (int n=0; n<16; n++) { diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 54ff5337a..f4e892f8c 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -68,18 +68,18 @@ BOOST_AUTO_TEST_CASE(rpc_addmultisig) const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4"; UniValue v; - CBitcoinAddress address; + CTxDestination address; BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false)); - address.SetString(v.get_str()); - BOOST_CHECK(address.IsValid() && address.IsScript()); + address = DecodeDestination(v.get_str()); + BOOST_CHECK(IsValidDestination(address) && boost::get(&address) != nullptr); BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex, address2Hex), false)); - address.SetString(v.get_str()); - BOOST_CHECK(address.IsValid() && address.IsScript()); + address = DecodeDestination(v.get_str()); + BOOST_CHECK(IsValidDestination(address) && boost::get(&address) != nullptr); BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(2, address1Hex, address2Hex), false)); - address.SetString(v.get_str()); - BOOST_CHECK(address.IsValid() && address.IsScript()); + address = DecodeDestination(v.get_str()); + BOOST_CHECK(IsValidDestination(address) && boost::get(&address) != nullptr); BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error); BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error); @@ -103,7 +103,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) LOCK2(cs_main, pwalletMain->cs_wallet); CPubKey demoPubkey = pwalletMain->GenerateNewKey(); - CBitcoinAddress demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID())); + CTxDestination demoAddress(CTxDestination(demoPubkey.GetID())); UniValue retValue; string strAccount = ""; string strPurpose = "receive"; @@ -116,14 +116,14 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) }); CPubKey setaccountDemoPubkey = pwalletMain->GenerateNewKey(); - CBitcoinAddress setaccountDemoAddress = CBitcoinAddress(CTxDestination(setaccountDemoPubkey.GetID())); + CTxDestination setaccountDemoAddress(CTxDestination(setaccountDemoPubkey.GetID())); /********************************* * setaccount *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("setaccount " + setaccountDemoAddress.ToString() + " \"\"")); + BOOST_CHECK_NO_THROW(CallRPC("setaccount " + EncodeDestination(setaccountDemoAddress) + " \"\"")); /* Accounts are disabled */ - BOOST_CHECK_THROW(CallRPC("setaccount " + setaccountDemoAddress.ToString() + " nullaccount"), runtime_error); + BOOST_CHECK_THROW(CallRPC("setaccount " + EncodeDestination(setaccountDemoAddress) + " nullaccount"), runtime_error); /* t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1GpgV is not owned by the test wallet. */ BOOST_CHECK_THROW(CallRPC("setaccount t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1GpgV nullaccount"), runtime_error); BOOST_CHECK_THROW(CallRPC("setaccount"), runtime_error); @@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) * getbalance *********************************/ BOOST_CHECK_NO_THROW(CallRPC("getbalance")); - BOOST_CHECK_THROW(CallRPC("getbalance " + demoAddress.ToString()), runtime_error); + BOOST_CHECK_THROW(CallRPC("getbalance " + EncodeDestination(demoAddress)), runtime_error); /********************************* * listunspent @@ -177,10 +177,10 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) * listtransactions *********************************/ BOOST_CHECK_NO_THROW(CallRPC("listtransactions")); - BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + demoAddress.ToString())); - BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + demoAddress.ToString() + " 20")); - BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + demoAddress.ToString() + " 20 0")); - BOOST_CHECK_THROW(CallRPC("listtransactions " + demoAddress.ToString() + " not_int"), runtime_error); + BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + EncodeDestination(demoAddress))); + BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + EncodeDestination(demoAddress) + " 20")); + BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + EncodeDestination(demoAddress) + " 20 0")); + BOOST_CHECK_THROW(CallRPC("listtransactions " + EncodeDestination(demoAddress) + " not_int"), runtime_error); /********************************* * listlockunspent @@ -217,33 +217,33 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) /* Accounts are deprecated */ BOOST_CHECK_THROW(CallRPC("getaccountaddress accountThatDoesntExists"), runtime_error); BOOST_CHECK_NO_THROW(retValue = CallRPC("getaccountaddress " + strAccount)); - BOOST_CHECK(CBitcoinAddress(retValue.get_str()).Get() == demoAddress.Get()); + BOOST_CHECK(DecodeDestination(retValue.get_str()) == demoAddress); /********************************* * getaccount *********************************/ BOOST_CHECK_THROW(CallRPC("getaccount"), runtime_error); - BOOST_CHECK_NO_THROW(CallRPC("getaccount " + demoAddress.ToString())); + BOOST_CHECK_NO_THROW(CallRPC("getaccount " + EncodeDestination(demoAddress))); /********************************* * signmessage + verifymessage *********************************/ - BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + demoAddress.ToString() + " mymessage")); + BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + EncodeDestination(demoAddress) + " mymessage")); BOOST_CHECK_THROW(CallRPC("signmessage"), runtime_error); /* Should throw error because this address is not loaded in the wallet */ BOOST_CHECK_THROW(CallRPC("signmessage t1h8SqgtM3QM5e2M8EzhhT1yL2PXXtA6oqe mymessage"), runtime_error); /* missing arguments */ - BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString()), runtime_error); - BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str()), runtime_error); + BOOST_CHECK_THROW(CallRPC("verifymessage " + EncodeDestination(demoAddress)), runtime_error); + BOOST_CHECK_THROW(CallRPC("verifymessage " + EncodeDestination(demoAddress) + " " + retValue.get_str()), runtime_error); /* Illegal address */ BOOST_CHECK_THROW(CallRPC("verifymessage t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1Gpg " + retValue.get_str() + " mymessage"), runtime_error); /* wrong address */ BOOST_CHECK(CallRPC("verifymessage t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1GpgV " + retValue.get_str() + " mymessage").get_bool() == false); /* Correct address and signature but wrong message */ - BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " wrongmessage").get_bool() == false); + BOOST_CHECK(CallRPC("verifymessage " + EncodeDestination(demoAddress) + " " + retValue.get_str() + " wrongmessage").get_bool() == false); /* Correct address, message and signature*/ - BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " mymessage").get_bool() == true); + BOOST_CHECK(CallRPC("verifymessage " + EncodeDestination(demoAddress) + " " + retValue.get_str() + " mymessage").get_bool() == true); /********************************* * getaddressesbyaccount @@ -254,7 +254,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) BOOST_CHECK_EQUAL(4, arr.size()); bool notFound = true; for (auto a : arr.getValues()) { - notFound &= CBitcoinAddress(a.get_str()).Get() != demoAddress.Get(); + notFound &= DecodeDestination(a.get_str()) != demoAddress; } BOOST_CHECK(!notFound); diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index 2c9cdcb1d..cae42019a 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -73,8 +73,8 @@ AsyncRPCOperation_mergetoaddress::AsyncRPCOperation_mergetoaddress( throw JSONRPCError(RPC_INVALID_PARAMETER, "Recipient parameter missing"); } - toTaddr_ = CBitcoinAddress(std::get<0>(recipient)); - isToTaddr_ = toTaddr_.IsValid(); + toTaddr_ = DecodeDestination(std::get<0>(recipient)); + isToTaddr_ = IsValidDestination(toTaddr_); isToZaddr_ = false; if (!isToTaddr_) { @@ -246,7 +246,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() rawTx.vin.push_back(in); } if (isToTaddr_) { - CScript scriptPubKey = GetScriptForDestination(toTaddr_.Get()); + CScript scriptPubKey = GetScriptForDestination(toTaddr_); CTxOut out(sendAmount, scriptPubKey); rawTx.vout.push_back(out); } diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.h b/src/wallet/asyncrpcoperation_mergetoaddress.h index 9b291cdf6..3de54ca63 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.h +++ b/src/wallet/asyncrpcoperation_mergetoaddress.h @@ -86,7 +86,7 @@ private: MergeToAddressRecipient recipient_; bool isToTaddr_; bool isToZaddr_; - CBitcoinAddress toTaddr_; + CTxDestination toTaddr_; PaymentAddress toPaymentAddress_; uint256 joinSplitPubKey_; diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 567fb7248..73a9360d7 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -74,8 +74,8 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany( throw JSONRPCError(RPC_INVALID_PARAMETER, "No recipients"); } - fromtaddr_ = CBitcoinAddress(fromAddress); - isfromtaddr_ = fromtaddr_.IsValid(); + fromtaddr_ = DecodeDestination(fromAddress); + isfromtaddr_ = IsValidDestination(fromtaddr_); isfromzaddr_ = false; if (!isfromtaddr_) { @@ -829,7 +829,8 @@ void AsyncRPCOperation_sendmany::sign_send_raw_transaction(UniValue obj) bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) { - set setAddress = {fromtaddr_}; + std::set destinations; + destinations.insert(fromtaddr_); vector vecOutputs; LOCK2(cs_main, pwalletMain->cs_wallet); @@ -845,13 +846,13 @@ bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) { continue; } - if (setAddress.size()) { + if (destinations.size()) { CTxDestination address; if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) { continue; } - if (!setAddress.count(address)) { + if (!destinations.count(address)) { continue; } } @@ -1101,12 +1102,12 @@ void AsyncRPCOperation_sendmany::add_taddr_outputs_to_tx() { std::string outputAddress = std::get<0>(r); CAmount nAmount = std::get<1>(r); - CBitcoinAddress address(outputAddress); - if (!address.IsValid()) { + CTxDestination address = DecodeDestination(outputAddress); + if (!IsValidDestination(address)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid output address, not a valid taddr."); } - CScript scriptPubKey = GetScriptForDestination(address.Get()); + CScript scriptPubKey = GetScriptForDestination(address); CTxOut out(nAmount, scriptPubKey); rawTx.vout.push_back(out); diff --git a/src/wallet/asyncrpcoperation_sendmany.h b/src/wallet/asyncrpcoperation_sendmany.h index 97c4533f1..1d2dc0f3d 100644 --- a/src/wallet/asyncrpcoperation_sendmany.h +++ b/src/wallet/asyncrpcoperation_sendmany.h @@ -79,7 +79,7 @@ private: std::string fromaddress_; bool isfromtaddr_; bool isfromzaddr_; - CBitcoinAddress fromtaddr_; + CTxDestination fromtaddr_; PaymentAddress frompaymentaddress_; SpendingKey spendingkey_; diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 0e232373d..59a22b37b 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -129,7 +129,7 @@ UniValue importprivkey(const UniValue& params, bool fHelp) // Don't throw error in case a key is already there if (pwalletMain->HaveKey(vchAddress)) { - return CBitcoinAddress(vchAddress).ToString(); + return EncodeDestination(vchAddress); } pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = 1; @@ -145,7 +145,7 @@ UniValue importprivkey(const UniValue& params, bool fHelp) } } - return CBitcoinAddress(vchAddress).ToString(); + return EncodeDestination(vchAddress); } UniValue importaddress(const UniValue& params, bool fHelp) @@ -175,9 +175,9 @@ UniValue importaddress(const UniValue& params, bool fHelp) CScript script; - CBitcoinAddress address(params[0].get_str()); - if (address.IsValid()) { - script = GetScriptForDestination(address.Get()); + CTxDestination dest = DecodeDestination(params[0].get_str()); + if (IsValidDestination(dest)) { + script = GetScriptForDestination(dest); } else if (IsHex(params[0].get_str())) { std::vector data(ParseHex(params[0].get_str())); script = CScript(data.begin(), data.end()); @@ -199,8 +199,8 @@ UniValue importaddress(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script"); // add to address book or update label - if (address.IsValid()) - pwalletMain->SetAddressBook(address.Get(), strLabel, "receive"); + if (IsValidDestination(dest)) + pwalletMain->SetAddressBook(dest, strLabel, "receive"); // Don't throw error in case an address is already there if (pwalletMain->HaveWatchOnly(script)) @@ -333,7 +333,7 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys assert(key.VerifyPubKey(pubkey)); CKeyID keyid = pubkey.GetID(); if (pwalletMain->HaveKey(keyid)) { - LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString()); + LogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid)); continue; } int64_t nTime = DecodeDumpTime(vstr[1]); @@ -351,7 +351,7 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys fLabel = true; } } - LogPrintf("Importing %s...\n", CBitcoinAddress(keyid).ToString()); + LogPrintf("Importing %s...\n", EncodeDestination(keyid)); if (!pwalletMain->AddKeyPubKey(key, pubkey)) { fGood = false; continue; @@ -405,16 +405,19 @@ UniValue dumpprivkey(const UniValue& params, bool fHelp) EnsureWalletIsUnlocked(); - string strAddress = params[0].get_str(); - CBitcoinAddress address; - if (!address.SetString(strAddress)) + std::string strAddress = params[0].get_str(); + CTxDestination dest = DecodeDestination(strAddress); + if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address"); - CKeyID keyID; - if (!address.GetKeyID(keyID)) + } + const CKeyID *keyID = boost::get(&dest); + if (!keyID) { throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key"); + } CKey vchSecret; - if (!pwalletMain->GetKey(keyID, vchSecret)) + if (!pwalletMain->GetKey(*keyID, vchSecret)) { throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known"); + } return CBitcoinSecret(vchSecret).ToString(); } @@ -515,7 +518,7 @@ UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys) for (std::vector >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) { const CKeyID &keyid = it->second; std::string strTime = EncodeDumpTime(it->first); - std::string strAddr = CBitcoinAddress(keyid).ToString(); + std::string strAddr = EncodeDestination(keyid); CKey key; if (pwalletMain->GetKey(keyid, key)) { if (pwalletMain->mapAddressBook.count(keyid)) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 8cdc3a092..23bfea02c 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -146,11 +146,11 @@ UniValue getnewaddress(const UniValue& params, bool fHelp) pwalletMain->SetAddressBook(keyID, strAccount, "receive"); - return CBitcoinAddress(keyID).ToString(); + return EncodeDestination(keyID); } -CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false) +CTxDestination GetAccountAddress(std::string strAccount, bool bForceNew=false) { CWalletDB walletdb(pwalletMain->strWalletFile); @@ -184,7 +184,7 @@ CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false) walletdb.WriteAccount(strAccount, account); } - return CBitcoinAddress(account.vchPubKey.GetID()); + return account.vchPubKey.GetID(); } UniValue getaccountaddress(const UniValue& params, bool fHelp) @@ -214,7 +214,7 @@ UniValue getaccountaddress(const UniValue& params, bool fHelp) UniValue ret(UniValue::VSTR); - ret = GetAccountAddress(strAccount).ToString(); + ret = EncodeDestination(GetAccountAddress(strAccount)); return ret; } @@ -250,7 +250,7 @@ UniValue getrawchangeaddress(const UniValue& params, bool fHelp) CKeyID keyID = vchPubKey.GetID(); - return CBitcoinAddress(keyID).ToString(); + return EncodeDestination(keyID); } @@ -273,25 +273,25 @@ UniValue setaccount(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - CBitcoinAddress address(params[0].get_str()); - if (!address.IsValid()) + CTxDestination dest = DecodeDestination(params[0].get_str()); + if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address"); + } string strAccount; if (params.size() > 1) strAccount = AccountFromValue(params[1]); // Only add the account if the address is yours. - if (IsMine(*pwalletMain, address.Get())) - { + if (IsMine(*pwalletMain, dest)) { // Detect when changing the account of an address that is the 'unused current key' of another account: - if (pwalletMain->mapAddressBook.count(address.Get())) - { - string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name; - if (address == GetAccountAddress(strOldAccount)) + if (pwalletMain->mapAddressBook.count(dest)) { + std::string strOldAccount = pwalletMain->mapAddressBook[dest].name; + if (dest == GetAccountAddress(strOldAccount)) { GetAccountAddress(strOldAccount, true); + } } - pwalletMain->SetAddressBook(address.Get(), strAccount, "receive"); + pwalletMain->SetAddressBook(dest, strAccount, "receive"); } else throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address"); @@ -320,14 +320,16 @@ UniValue getaccount(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - CBitcoinAddress address(params[0].get_str()); - if (!address.IsValid()) + CTxDestination dest = DecodeDestination(params[0].get_str()); + if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address"); + } - string strAccount; - map::iterator mi = pwalletMain->mapAddressBook.find(address.Get()); - if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty()) + std::string strAccount; + std::map::iterator mi = pwalletMain->mapAddressBook.find(dest); + if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty()) { strAccount = (*mi).second.name; + } return strAccount; } @@ -359,12 +361,12 @@ UniValue getaddressesbyaccount(const UniValue& params, bool fHelp) // Find all addresses that have the given account UniValue ret(UniValue::VARR); - BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook) - { - const CBitcoinAddress& address = item.first; - const string& strName = item.second.name; - if (strName == strAccount) - ret.push_back(address.ToString()); + for (const std::pair& item : pwalletMain->mapAddressBook) { + const CTxDestination& dest = item.first; + const std::string& strName = item.second.name; + if (strName == strAccount) { + ret.push_back(EncodeDestination(dest)); + } } return ret; } @@ -431,9 +433,10 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - CBitcoinAddress address(params[0].get_str()); - if (!address.IsValid()) + CTxDestination dest = DecodeDestination(params[0].get_str()); + if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address"); + } // Amount CAmount nAmount = AmountFromValue(params[1]); @@ -453,7 +456,7 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp) EnsureWalletIsUnlocked(); - SendMoney(address.Get(), nAmount, fSubtractFeeFromAmount, wtx); + SendMoney(dest, nAmount, fSubtractFeeFromAmount, wtx); return wtx.GetHash().GetHex(); } @@ -489,18 +492,18 @@ UniValue listaddressgroupings(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); UniValue jsonGroupings(UniValue::VARR); - map balances = pwalletMain->GetAddressBalances(); - BOOST_FOREACH(set grouping, pwalletMain->GetAddressGroupings()) - { + std::map balances = pwalletMain->GetAddressBalances(); + for (const std::set& grouping : pwalletMain->GetAddressGroupings()) { UniValue jsonGrouping(UniValue::VARR); - BOOST_FOREACH(CTxDestination address, grouping) + for (const CTxDestination& address : grouping) { UniValue addressInfo(UniValue::VARR); - addressInfo.push_back(CBitcoinAddress(address).ToString()); + addressInfo.push_back(EncodeDestination(address)); addressInfo.push_back(ValueFromAmount(balances[address])); { - if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end()) - addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name); + if (pwalletMain->mapAddressBook.find(address) != pwalletMain->mapAddressBook.end()) { + addressInfo.push_back(pwalletMain->mapAddressBook.find(address)->second.name); + } } jsonGrouping.push_back(addressInfo); } @@ -542,17 +545,20 @@ UniValue signmessage(const UniValue& params, bool fHelp) string strAddress = params[0].get_str(); string strMessage = params[1].get_str(); - CBitcoinAddress addr(strAddress); - if (!addr.IsValid()) + CTxDestination dest = DecodeDestination(strAddress); + if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address"); + } - CKeyID keyID; - if (!addr.GetKeyID(keyID)) + const CKeyID *keyID = boost::get(&dest); + if (!keyID) { throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); + } CKey key; - if (!pwalletMain->GetKey(keyID, key)) + if (!pwalletMain->GetKey(*keyID, key)) { throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available"); + } CHashWriter ss(SER_GETHASH, 0); ss << strMessageMagic; @@ -593,12 +599,14 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); // Bitcoin address - CBitcoinAddress address = CBitcoinAddress(params[0].get_str()); - if (!address.IsValid()) + CTxDestination dest = DecodeDestination(params[0].get_str()); + if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address"); - CScript scriptPubKey = GetScriptForDestination(address.Get()); - if (!IsMine(*pwalletMain, scriptPubKey)) + } + CScript scriptPubKey = GetScriptForDestination(dest); + if (!IsMine(*pwalletMain, scriptPubKey)) { return ValueFromAmount(0); + } // Minimum confirmations int nMinDepth = 1; @@ -907,10 +915,11 @@ UniValue sendfrom(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - string strAccount = AccountFromValue(params[0]); - CBitcoinAddress address(params[1].get_str()); - if (!address.IsValid()) + std::string strAccount = AccountFromValue(params[0]); + CTxDestination dest = DecodeDestination(params[1].get_str()); + if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address"); + } CAmount nAmount = AmountFromValue(params[2]); if (nAmount <= 0) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send"); @@ -932,7 +941,7 @@ UniValue sendfrom(const UniValue& params, bool fHelp) if (nAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); - SendMoney(address.Get(), nAmount, false, wtx); + SendMoney(dest, nAmount, false, wtx); return wtx.GetHash().GetHex(); } @@ -996,22 +1005,23 @@ UniValue sendmany(const UniValue& params, bool fHelp) if (params.size() > 4) subtractFeeFromAmount = params[4].get_array(); - set setAddress; - vector vecSend; + std::set destinations; + std::vector vecSend; CAmount totalAmount = 0; - vector keys = sendTo.getKeys(); - BOOST_FOREACH(const string& name_, keys) - { - CBitcoinAddress address(name_); - if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Zcash address: ")+name_); + std::vector keys = sendTo.getKeys(); + for (const std::string& name_ : keys) { + CTxDestination dest = DecodeDestination(name_); + if (!IsValidDestination(dest)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Zcash address: ") + name_); + } - if (setAddress.count(address)) - throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_); - setAddress.insert(address); + if (destinations.count(dest)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_); + } + destinations.insert(dest); - CScript scriptPubKey = GetScriptForDestination(address.Get()); + CScript scriptPubKey = GetScriptForDestination(dest); CAmount nAmount = AmountFromValue(sendTo[name_]); if (nAmount <= 0) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send"); @@ -1097,7 +1107,7 @@ UniValue addmultisigaddress(const UniValue& params, bool fHelp) pwalletMain->AddCScript(inner); pwalletMain->SetAddressBook(innerID, strAccount, "send"); - return CBitcoinAddress(innerID).ToString(); + return EncodeDestination(innerID); } @@ -1133,10 +1143,9 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts) filter = filter | ISMINE_WATCH_ONLY; // Tally - map mapTally; - for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) - { - const CWalletTx& wtx = (*it).second; + std::map mapTally; + for (const std::pair& pairWtx : pwalletMain->mapWallet) { + const CWalletTx& wtx = pairWtx.second; if (wtx.IsCoinBase() || !CheckFinalTx(wtx)) continue; @@ -1166,12 +1175,11 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts) // Reply UniValue ret(UniValue::VARR); - map mapAccountTally; - BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook) - { - const CBitcoinAddress& address = item.first; - const string& strAccount = item.second.name; - map::iterator it = mapTally.find(address); + std::map mapAccountTally; + for (const std::pair& item : pwalletMain->mapAddressBook) { + const CTxDestination& dest = item.first; + const std::string& strAccount = item.second.name; + std::map::iterator it = mapTally.find(dest); if (it == mapTally.end() && !fIncludeEmpty) continue; @@ -1197,7 +1205,7 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts) UniValue obj(UniValue::VOBJ); if(fIsWatchonly) obj.push_back(Pair("involvesWatchonly", true)); - obj.push_back(Pair("address", address.ToString())); + obj.push_back(Pair("address", EncodeDestination(dest))); obj.push_back(Pair("account", strAccount)); obj.push_back(Pair("amount", ValueFromAmount(nAmount))); obj.push_back(Pair("confirmations", (nConf == std::numeric_limits::max() ? 0 : nConf))); @@ -1308,9 +1316,9 @@ UniValue listreceivedbyaccount(const UniValue& params, bool fHelp) static void MaybePushAddress(UniValue & entry, const CTxDestination &dest) { - CBitcoinAddress addr; - if (addr.Set(dest)) - entry.push_back(Pair("address", addr.ToString())); + if (IsValidDestination(dest)) { + entry.push_back(Pair("address", EncodeDestination(dest))); + } } void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter) @@ -2367,17 +2375,18 @@ UniValue listunspent(const UniValue& params, bool fHelp) if (params.size() > 1) nMaxDepth = params[1].get_int(); - set setAddress; + std::set destinations; if (params.size() > 2) { UniValue inputs = params[2].get_array(); for (size_t idx = 0; idx < inputs.size(); idx++) { const UniValue& input = inputs[idx]; - CBitcoinAddress address(input.get_str()); - if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Zcash address: ")+input.get_str()); - if (setAddress.count(address)) - throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str()); - setAddress.insert(address); + CTxDestination dest = DecodeDestination(input.get_str()); + if (!IsValidDestination(dest)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Zcash address: ") + input.get_str()); + } + if (!destinations.insert(dest).second) { + throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str()); + } } } @@ -2394,7 +2403,7 @@ UniValue listunspent(const UniValue& params, bool fHelp) const CScript& scriptPubKey = out.tx->vout[out.i].scriptPubKey; bool fValidAddress = ExtractDestination(scriptPubKey, address); - if (setAddress.size() && (!fValidAddress || !setAddress.count(address))) + if (destinations.size() && (!fValidAddress || !destinations.count(address))) continue; UniValue entry(UniValue::VOBJ); @@ -2403,7 +2412,7 @@ UniValue listunspent(const UniValue& params, bool fHelp) entry.push_back(Pair("generated", out.tx->IsCoinBase())); if (fValidAddress) { - entry.push_back(Pair("address", CBitcoinAddress(address).ToString())); + entry.push_back(Pair("address", EncodeDestination(address))); if (pwalletMain->mapAddressBook.count(address)) entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name)); @@ -3129,16 +3138,16 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp) } CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ignoreUnspendable=true) { - set setAddress; + std::set destinations; vector vecOutputs; CAmount balance = 0; if (transparentAddress.length() > 0) { - CBitcoinAddress taddr = CBitcoinAddress(transparentAddress); - if (!taddr.IsValid()) { + CTxDestination taddr = DecodeDestination(transparentAddress); + if (!IsValidDestination(taddr)) { throw std::runtime_error("invalid transparent address"); } - setAddress.insert(taddr); + destinations.insert(taddr); } LOCK2(cs_main, pwalletMain->cs_wallet); @@ -3154,13 +3163,13 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ign continue; } - if (setAddress.size()) { + if (destinations.size()) { CTxDestination address; if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) { continue; } - if (!setAddress.count(address)) { + if (!destinations.count(address)) { continue; } } @@ -3288,8 +3297,8 @@ UniValue z_getbalance(const UniValue& params, bool fHelp) // Check that the from address is valid. auto fromaddress = params[0].get_str(); bool fromTaddr = false; - CBitcoinAddress taddr(fromaddress); - fromTaddr = taddr.IsValid(); + CTxDestination taddr = DecodeDestination(fromaddress); + fromTaddr = IsValidDestination(taddr); libzcash::PaymentAddress zaddr; if (!fromTaddr) { CZCPaymentAddress address(fromaddress); @@ -3522,8 +3531,8 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) // Check that the from address is valid. auto fromaddress = params[0].get_str(); bool fromTaddr = false; - CBitcoinAddress taddr(fromaddress); - fromTaddr = taddr.IsValid(); + CTxDestination taddr = DecodeDestination(fromaddress); + fromTaddr = IsValidDestination(taddr); libzcash::PaymentAddress zaddr; if (!fromTaddr) { CZCPaymentAddress address(fromaddress); @@ -3568,8 +3577,8 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) string address = find_value(o, "address").get_str(); bool isZaddr = false; - CBitcoinAddress taddr(address); - if (!taddr.IsValid()) { + CTxDestination taddr = DecodeDestination(address); + if (!IsValidDestination(taddr)) { try { CZCPaymentAddress zaddr(address); zaddr.Get(); @@ -3743,10 +3752,10 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp) // Validate the from address auto fromaddress = params[0].get_str(); bool isFromWildcard = fromaddress == "*"; - CBitcoinAddress taddr; + CTxDestination taddr; if (!isFromWildcard) { - taddr = CBitcoinAddress(fromaddress); - if (!taddr.IsValid()) { + taddr = DecodeDestination(fromaddress); + if (!IsValidDestination(taddr)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or \"*\"."); } } @@ -3791,9 +3800,9 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp) size_t mempoolLimit = (nLimit != 0) ? nLimit : (overwinterActive ? 0 : (size_t)GetArg("-mempooltxinputlimit", 0)); // Set of addresses to filter utxos by - set setAddress = {}; + std::set destinations = {}; if (!isFromWildcard) { - setAddress.insert(taddr); + destinations.insert(taddr); } // Get available utxos @@ -3811,7 +3820,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp) continue; } // If taddr is not wildcard "*", filter utxos - if (setAddress.size()>0 && !setAddress.count(address)) { + if (destinations.size() > 0 && !destinations.count(address)) { continue; } @@ -3823,8 +3832,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp) CAmount nValue = out.tx->vout[out.i].nValue; if (!maxedOutFlag) { - CBitcoinAddress ba(address); - size_t increase = (ba.IsScript()) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE; + size_t increase = (boost::get(&address) != nullptr) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE; if (estimatedTxSize + increase >= MAX_TX_SIZE || (mempoolLimit > 0 && utxoCounter > mempoolLimit)) { @@ -3967,7 +3975,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) bool useAny = false; bool useAnyUTXO = false; bool useAnyNote = false; - std::set taddrs = {}; + std::set taddrs = {}; std::set zaddrs = {}; UniValue addresses = params[0].get_array(); @@ -3990,8 +3998,8 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) } else if (address == "ANY_ZADDR") { useAnyNote = true; } else { - CBitcoinAddress taddr(address); - if (taddr.IsValid()) { + CTxDestination taddr = DecodeDestination(address); + if (IsValidDestination(taddr)) { // Ignore any listed t-addrs if we are using all of them if (!(useAny || useAnyUTXO)) { taddrs.insert(taddr); @@ -4019,8 +4027,8 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) // Validate the destination address auto destaddress = params[1].get_str(); bool isToZaddr = false; - CBitcoinAddress taddr(destaddress); - if (!taddr.IsValid()) { + CTxDestination taddr = DecodeDestination(destaddress); + if (!IsValidDestination(taddr)) { try { CZCPaymentAddress zaddr(destaddress); zaddr.Get(); @@ -4116,8 +4124,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) CAmount nValue = out.tx->vout[out.i].nValue; if (!maxedOutUTXOsFlag) { - CBitcoinAddress ba(address); - size_t increase = (ba.IsScript()) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE; + size_t increase = (boost::get(&address) != nullptr) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE; if (estimatedTxSize + increase >= MAX_TX_SIZE || (mempoolLimit > 0 && utxoCounter > mempoolLimit)) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 448dd50e7..3db3e26c3 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -300,7 +300,7 @@ bool CWallet::LoadCScript(const CScript& redeemScript) * these. Do not add them to the wallet and warn. */ if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) { - std::string strAddr = CBitcoinAddress(CScriptID(redeemScript)).ToString(); + std::string strAddr = EncodeDestination(CScriptID(redeemScript)); LogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n", __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr); return true; @@ -3018,9 +3018,9 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const string& strNam strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) ); if (!fFileBacked) return false; - if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose)) + if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(EncodeDestination(address), strPurpose)) return false; - return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName); + return CWalletDB(strWalletFile).WriteName(EncodeDestination(address), strName); } bool CWallet::DelAddressBook(const CTxDestination& address) @@ -3031,7 +3031,7 @@ bool CWallet::DelAddressBook(const CTxDestination& address) if(fFileBacked) { // Delete destdata tuples associated with address - std::string strAddress = CBitcoinAddress(address).ToString(); + std::string strAddress = EncodeDestination(address); BOOST_FOREACH(const PAIRTYPE(string, string) &item, mapAddressBook[address].destdata) { CWalletDB(strWalletFile).EraseDestData(strAddress, item.first); @@ -3044,8 +3044,8 @@ bool CWallet::DelAddressBook(const CTxDestination& address) if (!fFileBacked) return false; - CWalletDB(strWalletFile).ErasePurpose(CBitcoinAddress(address).ToString()); - return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString()); + CWalletDB(strWalletFile).ErasePurpose(EncodeDestination(address)); + return CWalletDB(strWalletFile).EraseName(EncodeDestination(address)); } bool CWallet::SetDefaultKey(const CPubKey &vchPubKey) @@ -3573,7 +3573,7 @@ bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, co mapAddressBook[dest].destdata.insert(std::make_pair(key, value)); if (!fFileBacked) return true; - return CWalletDB(strWalletFile).WriteDestData(CBitcoinAddress(dest).ToString(), key, value); + return CWalletDB(strWalletFile).WriteDestData(EncodeDestination(dest), key, value); } bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key) @@ -3582,7 +3582,7 @@ bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key) return false; if (!fFileBacked) return true; - return CWalletDB(strWalletFile).EraseDestData(CBitcoinAddress(dest).ToString(), key); + return CWalletDB(strWalletFile).EraseDestData(EncodeDestination(dest), key); } bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value) diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index dc1b40d95..8b4a7be2c 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -409,13 +409,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, { string strAddress; ssKey >> strAddress; - ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()].name; + ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].name; } else if (strType == "purpose") { string strAddress; ssKey >> strAddress; - ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()].purpose; + ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].purpose; } else if (strType == "tx") { @@ -698,7 +698,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, ssKey >> strAddress; ssKey >> strKey; ssValue >> strValue; - if (!pwallet->LoadDestData(CBitcoinAddress(strAddress).Get(), strKey, strValue)) + if (!pwallet->LoadDestData(DecodeDestination(strAddress), strKey, strValue)) { strErr = "Error reading wallet database: LoadDestData failed"; return false;