From 5c8ff0d448ffdc6340b195ddfa2128d5f21a839b Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 22 Aug 2017 18:02:33 -0700 Subject: Introduce wrappers around CBitcoinAddress This patch removes the need for the intermediary Base58 type CBitcoinAddress, by providing {Encode,Decode,IsValid}Destination function that directly operate on the conversion between strings and CTxDestination. --- src/wallet/rpcdump.cpp | 83 ++++++++++++------------- src/wallet/rpcwallet.cpp | 159 +++++++++++++++++++++++++---------------------- src/wallet/wallet.cpp | 16 ++--- src/wallet/walletdb.cpp | 6 +- 4 files changed, 137 insertions(+), 127 deletions(-) (limited to 'src/wallet') diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index db6f6b48ac..9539cc9f42 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -181,7 +181,7 @@ UniValue abortrescan(const JSONRPCRequest& request) return true; } -void ImportAddress(CWallet*, const CBitcoinAddress& address, const std::string& strLabel); +void ImportAddress(CWallet*, const CTxDestination& dest, const std::string& strLabel); void ImportScript(CWallet* const pwallet, const CScript& script, const std::string& strLabel, bool isRedeemScript) { if (!isRedeemScript && ::IsMine(*pwallet, script) == ISMINE_SPENDABLE) { @@ -198,7 +198,7 @@ void ImportScript(CWallet* const pwallet, const CScript& script, const std::stri if (!pwallet->HaveCScript(script) && !pwallet->AddCScript(script)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet"); } - ImportAddress(pwallet, CBitcoinAddress(CScriptID(script)), strLabel); + ImportAddress(pwallet, CScriptID(script), strLabel); } else { CTxDestination destination; if (ExtractDestination(script, destination)) { @@ -207,13 +207,13 @@ void ImportScript(CWallet* const pwallet, const CScript& script, const std::stri } } -void ImportAddress(CWallet* const pwallet, const CBitcoinAddress& address, const std::string& strLabel) +void ImportAddress(CWallet* const pwallet, const CTxDestination& dest, const std::string& strLabel) { - CScript script = GetScriptForDestination(address.Get()); + CScript script = GetScriptForDestination(dest); ImportScript(pwallet, script, strLabel, false); // add to address book or update label - if (address.IsValid()) - pwallet->SetAddressBook(address.Get(), strLabel, "receive"); + if (IsValidDestination(dest)) + pwallet->SetAddressBook(dest, strLabel, "receive"); } UniValue importaddress(const JSONRPCRequest& request) @@ -265,11 +265,12 @@ UniValue importaddress(const JSONRPCRequest& request) LOCK2(cs_main, pwallet->cs_wallet); - CBitcoinAddress address(request.params[0].get_str()); - if (address.IsValid()) { - if (fP2SH) + CTxDestination dest = DecodeDestination(request.params[0].get_str()); + if (IsValidDestination(dest)) { + if (fP2SH) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead"); - ImportAddress(pwallet, address, strLabel); + } + ImportAddress(pwallet, dest, strLabel); } else if (IsHex(request.params[0].get_str())) { std::vector data(ParseHex(request.params[0].get_str())); ImportScript(pwallet, CScript(data.begin(), data.end()), strLabel, fP2SH); @@ -432,7 +433,7 @@ UniValue importpubkey(const JSONRPCRequest& request) LOCK2(cs_main, pwallet->cs_wallet); - ImportAddress(pwallet, CBitcoinAddress(pubKey.GetID()), strLabel); + ImportAddress(pwallet, pubKey.GetID(), strLabel); ImportScript(pwallet, GetScriptForRawPubKey(pubKey), strLabel, false); if (fRescan) @@ -506,7 +507,7 @@ UniValue importwallet(const JSONRPCRequest& request) assert(key.VerifyPubKey(pubkey)); CKeyID keyid = pubkey.GetID(); if (pwallet->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]); @@ -524,7 +525,7 @@ UniValue importwallet(const JSONRPCRequest& request) fLabel = true; } } - LogPrintf("Importing %s...\n", CBitcoinAddress(keyid).ToString()); + LogPrintf("Importing %s...\n", EncodeDestination(keyid)); if (!pwallet->AddKeyPubKey(key, pubkey)) { fGood = false; continue; @@ -573,14 +574,16 @@ UniValue dumpprivkey(const JSONRPCRequest& request) EnsureWalletIsUnlocked(pwallet); std::string strAddress = request.params[0].get_str(); - CBitcoinAddress address; - if (!address.SetString(strAddress)) + CTxDestination dest = DecodeDestination(strAddress); + if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin 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 (!pwallet->GetKey(keyID, vchSecret)) { + if (!pwallet->GetKey(*keyID, vchSecret)) { throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known"); } return CBitcoinSecret(vchSecret).ToString(); @@ -659,7 +662,7 @@ UniValue dumpwallet(const JSONRPCRequest& request) 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 (pwallet->GetKey(keyid, key)) { file << strprintf("%s %s ", CBitcoinSecret(key).ToString(), strTime); @@ -715,14 +718,14 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6 // Parse the output. CScript script; - CBitcoinAddress address; + CTxDestination dest; if (!isScript) { - address = CBitcoinAddress(output); - if (!address.IsValid()) { + dest = DecodeDestination(output); + if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); } - script = GetScriptForDestination(address.Get()); + script = GetScriptForDestination(dest); } else { if (!IsHex(output)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid scriptPubKey"); @@ -780,8 +783,8 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6 throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet"); } - CBitcoinAddress redeemAddress = CBitcoinAddress(CScriptID(redeemScript)); - CScript redeemDestination = GetScriptForDestination(redeemAddress.Get()); + CTxDestination redeem_dest = CScriptID(redeemScript); + CScript redeemDestination = GetScriptForDestination(redeem_dest); if (::IsMine(*pwallet, redeemDestination) == ISMINE_SPENDABLE) { throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script"); @@ -794,8 +797,8 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6 } // add to address book or update label - if (address.IsValid()) { - pwallet->SetAddressBook(address.Get(), label, "receive"); + if (IsValidDestination(dest)) { + pwallet->SetAddressBook(dest, label, "receive"); } // Import private keys. @@ -854,27 +857,25 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key"); } - CBitcoinAddress pubKeyAddress = CBitcoinAddress(pubKey.GetID()); + CTxDestination pubkey_dest = pubKey.GetID(); // Consistency check. - if (!isScript && !(pubKeyAddress.Get() == address.Get())) { + if (!isScript && !(pubkey_dest == dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed"); } // Consistency check. if (isScript) { - CBitcoinAddress scriptAddress; CTxDestination destination; if (ExtractDestination(script, destination)) { - scriptAddress = CBitcoinAddress(destination); - if (!(scriptAddress.Get() == pubKeyAddress.Get())) { + if (!(destination == pubkey_dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed"); } } } - CScript pubKeyScript = GetScriptForDestination(pubKeyAddress.Get()); + CScript pubKeyScript = GetScriptForDestination(pubkey_dest); if (::IsMine(*pwallet, pubKeyScript) == ISMINE_SPENDABLE) { throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script"); @@ -887,8 +888,8 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6 } // add to address book or update label - if (pubKeyAddress.IsValid()) { - pwallet->SetAddressBook(pubKeyAddress.Get(), label, "receive"); + if (IsValidDestination(pubkey_dest)) { + pwallet->SetAddressBook(pubkey_dest, label, "receive"); } // TODO Is this necessary? @@ -927,21 +928,19 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6 CPubKey pubKey = key.GetPubKey(); assert(key.VerifyPubKey(pubKey)); - CBitcoinAddress pubKeyAddress = CBitcoinAddress(pubKey.GetID()); + CTxDestination pubkey_dest = pubKey.GetID(); // Consistency check. - if (!isScript && !(pubKeyAddress.Get() == address.Get())) { + if (!isScript && !(pubkey_dest == dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed"); } // Consistency check. if (isScript) { - CBitcoinAddress scriptAddress; CTxDestination destination; if (ExtractDestination(script, destination)) { - scriptAddress = CBitcoinAddress(destination); - if (!(scriptAddress.Get() == pubKeyAddress.Get())) { + if (!(destination == pubkey_dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed"); } } @@ -980,8 +979,8 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6 if (scriptPubKey.getType() == UniValue::VOBJ) { // add to address book or update label - if (address.IsValid()) { - pwallet->SetAddressBook(address.Get(), label, "receive"); + if (IsValidDestination(dest)) { + pwallet->SetAddressBook(dest, label, "receive"); } } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index e3639e4682..637ca04e82 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -170,18 +170,18 @@ UniValue getnewaddress(const JSONRPCRequest& request) pwallet->SetAddressBook(keyID, strAccount, "receive"); - return CBitcoinAddress(keyID).ToString(); + return EncodeDestination(keyID); } -CBitcoinAddress GetAccountAddress(CWallet* const pwallet, std::string strAccount, bool bForceNew=false) +CTxDestination GetAccountAddress(CWallet* const pwallet, std::string strAccount, bool bForceNew=false) { CPubKey pubKey; if (!pwallet->GetAccountPubkey(pubKey, strAccount, bForceNew)) { throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); } - return CBitcoinAddress(pubKey.GetID()); + return pubKey.GetID(); } UniValue getaccountaddress(const JSONRPCRequest& request) @@ -213,7 +213,7 @@ UniValue getaccountaddress(const JSONRPCRequest& request) UniValue ret(UniValue::VSTR); - ret = GetAccountAddress(pwallet, strAccount).ToString(); + ret = EncodeDestination(GetAccountAddress(pwallet, strAccount)); return ret; } @@ -252,7 +252,7 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request) CKeyID keyID = vchPubKey.GetID(); - return CBitcoinAddress(keyID).ToString(); + return EncodeDestination(keyID); } @@ -277,24 +277,25 @@ UniValue setaccount(const JSONRPCRequest& request) LOCK2(cs_main, pwallet->cs_wallet); - CBitcoinAddress address(request.params[0].get_str()); - if (!address.IsValid()) + CTxDestination dest = DecodeDestination(request.params[0].get_str()); + if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); + } std::string strAccount; if (!request.params[1].isNull()) strAccount = AccountFromValue(request.params[1]); // Only add the account if the address is yours. - if (IsMine(*pwallet, address.Get())) { + if (IsMine(*pwallet, dest)) { // Detect when changing the account of an address that is the 'unused current key' of another account: - if (pwallet->mapAddressBook.count(address.Get())) { - std::string strOldAccount = pwallet->mapAddressBook[address.Get()].name; - if (address == GetAccountAddress(pwallet, strOldAccount)) { + if (pwallet->mapAddressBook.count(dest)) { + std::string strOldAccount = pwallet->mapAddressBook[dest].name; + if (dest == GetAccountAddress(pwallet, strOldAccount)) { GetAccountAddress(pwallet, strOldAccount, true); } } - pwallet->SetAddressBook(address.Get(), strAccount, "receive"); + pwallet->SetAddressBook(dest, strAccount, "receive"); } else throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address"); @@ -325,12 +326,13 @@ UniValue getaccount(const JSONRPCRequest& request) LOCK2(cs_main, pwallet->cs_wallet); - CBitcoinAddress address(request.params[0].get_str()); - if (!address.IsValid()) + CTxDestination dest = DecodeDestination(request.params[0].get_str()); + if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); + } std::string strAccount; - std::map::iterator mi = pwallet->mapAddressBook.find(address.Get()); + std::map::iterator mi = pwallet->mapAddressBook.find(dest); if (mi != pwallet->mapAddressBook.end() && !(*mi).second.name.empty()) { strAccount = (*mi).second.name; } @@ -367,11 +369,12 @@ UniValue getaddressesbyaccount(const JSONRPCRequest& request) // Find all addresses that have the given account UniValue ret(UniValue::VARR); - for (const std::pair& item : pwallet->mapAddressBook) { - const CBitcoinAddress& address = item.first; + for (const std::pair& item : pwallet->mapAddressBook) { + const CTxDestination& dest = item.first; const std::string& strName = item.second.name; - if (strName == strAccount) - ret.push_back(address.ToString()); + if (strName == strAccount) { + ret.push_back(EncodeDestination(dest)); + } } return ret; } @@ -454,9 +457,10 @@ UniValue sendtoaddress(const JSONRPCRequest& request) ObserveSafeMode(); LOCK2(cs_main, pwallet->cs_wallet); - CBitcoinAddress address(request.params[0].get_str()); - if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); + CTxDestination dest = DecodeDestination(request.params[0].get_str()); + if (!IsValidDestination(dest)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } // Amount CAmount nAmount = AmountFromValue(request.params[1]); @@ -493,7 +497,7 @@ UniValue sendtoaddress(const JSONRPCRequest& request) EnsureWalletIsUnlocked(pwallet); - SendMoney(pwallet, address.Get(), nAmount, fSubtractFeeFromAmount, wtx, coin_control); + SendMoney(pwallet, dest, nAmount, fSubtractFeeFromAmount, wtx, coin_control); return wtx.GetHash().GetHex(); } @@ -533,16 +537,16 @@ UniValue listaddressgroupings(const JSONRPCRequest& request) UniValue jsonGroupings(UniValue::VARR); std::map balances = pwallet->GetAddressBalances(); - for (std::set grouping : pwallet->GetAddressGroupings()) { + for (const std::set& grouping : pwallet->GetAddressGroupings()) { UniValue jsonGrouping(UniValue::VARR); - for (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 (pwallet->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwallet->mapAddressBook.end()) { - addressInfo.push_back(pwallet->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name); + if (pwallet->mapAddressBook.find(address) != pwallet->mapAddressBook.end()) { + addressInfo.push_back(pwallet->mapAddressBook.find(address)->second.name); } } jsonGrouping.push_back(addressInfo); @@ -587,16 +591,18 @@ UniValue signmessage(const JSONRPCRequest& request) std::string strAddress = request.params[0].get_str(); std::string strMessage = request.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 (!pwallet->GetKey(keyID, key)) { + if (!pwallet->GetKey(*keyID, key)) { throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available"); } @@ -642,10 +648,11 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request) LOCK2(cs_main, pwallet->cs_wallet); // Bitcoin address - CBitcoinAddress address = CBitcoinAddress(request.params[0].get_str()); - if (!address.IsValid()) + CTxDestination dest = DecodeDestination(request.params[0].get_str()); + if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); - CScript scriptPubKey = GetScriptForDestination(address.Get()); + } + CScript scriptPubKey = GetScriptForDestination(dest); if (!IsMine(*pwallet, scriptPubKey)) { return ValueFromAmount(0); } @@ -915,9 +922,10 @@ UniValue sendfrom(const JSONRPCRequest& request) LOCK2(cs_main, pwallet->cs_wallet); std::string strAccount = AccountFromValue(request.params[0]); - CBitcoinAddress address(request.params[1].get_str()); - if (!address.IsValid()) + CTxDestination dest = DecodeDestination(request.params[1].get_str()); + if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); + } CAmount nAmount = AmountFromValue(request.params[2]); if (nAmount <= 0) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send"); @@ -940,7 +948,7 @@ UniValue sendfrom(const JSONRPCRequest& request) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); CCoinControl no_coin_control; // This is a deprecated API - SendMoney(pwallet, address.Get(), nAmount, false, wtx, no_coin_control); + SendMoney(pwallet, dest, nAmount, false, wtx, no_coin_control); return wtx.GetHash().GetHex(); } @@ -1032,22 +1040,23 @@ UniValue sendmany(const JSONRPCRequest& request) } } - std::set setAddress; + std::set destinations; std::vector vecSend; CAmount totalAmount = 0; std::vector keys = sendTo.getKeys(); - for (const std::string& name_ : keys) - { - CBitcoinAddress address(name_); - if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ")+name_); + for (const std::string& name_ : keys) { + CTxDestination dest = DecodeDestination(name_); + if (!IsValidDestination(dest)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + name_); + } - if (setAddress.count(address)) - throw JSONRPCError(RPC_INVALID_PARAMETER, std::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"); @@ -1138,7 +1147,7 @@ UniValue addmultisigaddress(const JSONRPCRequest& request) pwallet->AddCScript(inner); pwallet->SetAddressBook(innerID, strAccount, "send"); - return CBitcoinAddress(innerID).ToString(); + return EncodeDestination(innerID); } class Witnessifier : public boost::static_visitor @@ -1226,12 +1235,12 @@ UniValue addwitnessaddress(const JSONRPCRequest& request) } } - CBitcoinAddress address(request.params[0].get_str()); - if (!address.IsValid()) + CTxDestination dest = DecodeDestination(request.params[0].get_str()); + if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); + } Witnessifier w(pwallet); - CTxDestination dest = address.Get(); bool ret = boost::apply_visitor(w, dest); if (!ret) { throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet, or the key is uncompressed"); @@ -1239,7 +1248,7 @@ UniValue addwitnessaddress(const JSONRPCRequest& request) pwallet->SetAddressBook(w.result, "", "receive"); - return CBitcoinAddress(w.result).ToString(); + return EncodeDestination(w.result); } struct tallyitem @@ -1274,7 +1283,7 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA filter = filter | ISMINE_WATCH_ONLY; // Tally - std::map mapTally; + std::map mapTally; for (const std::pair& pairWtx : pwallet->mapWallet) { const CWalletTx& wtx = pairWtx.second; @@ -1307,10 +1316,10 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA // Reply UniValue ret(UniValue::VARR); std::map mapAccountTally; - for (const std::pair& item : pwallet->mapAddressBook) { - const CBitcoinAddress& address = item.first; + for (const std::pair& item : pwallet->mapAddressBook) { + const CTxDestination& dest = item.first; const std::string& strAccount = item.second.name; - std::map::iterator it = mapTally.find(address); + std::map::iterator it = mapTally.find(dest); if (it == mapTally.end() && !fIncludeEmpty) continue; @@ -1336,7 +1345,7 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA 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))); @@ -1461,9 +1470,9 @@ UniValue listreceivedbyaccount(const JSONRPCRequest& request) 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))); + } } /** @@ -2717,18 +2726,19 @@ UniValue listunspent(const JSONRPCRequest& request) nMaxDepth = request.params[1].get_int(); } - std::set setAddress; + std::set destinations; if (!request.params[2].isNull()) { RPCTypeCheckArgument(request.params[2], UniValue::VARR); UniValue inputs = request.params[2].get_array(); for (unsigned int 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, std::string("Invalid Bitcoin address: ")+input.get_str()); - if (setAddress.count(address)) - throw JSONRPCError(RPC_INVALID_PARAMETER, std::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 Bitcoin address: ") + input.get_str()); + } + if (!destinations.insert(dest).second) { + throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str()); + } } } @@ -2770,7 +2780,7 @@ UniValue listunspent(const JSONRPCRequest& request) const CScript& scriptPubKey = out.tx->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); @@ -2778,7 +2788,7 @@ UniValue listunspent(const JSONRPCRequest& request) entry.push_back(Pair("vout", out.i)); if (fValidAddress) { - entry.push_back(Pair("address", CBitcoinAddress(address).ToString())); + entry.push_back(Pair("address", EncodeDestination(address))); if (pwallet->mapAddressBook.count(address)) { entry.push_back(Pair("account", pwallet->mapAddressBook[address].name)); @@ -2901,12 +2911,13 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) true, true); if (options.exists("changeAddress")) { - CBitcoinAddress address(options["changeAddress"].get_str()); + CTxDestination dest = DecodeDestination(options["changeAddress"].get_str()); - if (!address.IsValid()) + if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "changeAddress must be a valid bitcoin address"); + } - coinControl.destChange = address.Get(); + coinControl.destChange = dest; } if (options.exists("changePosition")) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index d1d2060b0c..584324feb5 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -307,7 +307,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; @@ -3072,9 +3072,9 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& s } NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address) != ISMINE_NO, strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) ); - if (!strPurpose.empty() && !CWalletDB(*dbw).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose)) + if (!strPurpose.empty() && !CWalletDB(*dbw).WritePurpose(EncodeDestination(address), strPurpose)) return false; - return CWalletDB(*dbw).WriteName(CBitcoinAddress(address).ToString(), strName); + return CWalletDB(*dbw).WriteName(EncodeDestination(address), strName); } bool CWallet::DelAddressBook(const CTxDestination& address) @@ -3083,7 +3083,7 @@ bool CWallet::DelAddressBook(const CTxDestination& address) LOCK(cs_wallet); // mapAddressBook // Delete destdata tuples associated with address - std::string strAddress = CBitcoinAddress(address).ToString(); + std::string strAddress = EncodeDestination(address); for (const std::pair &item : mapAddressBook[address].destdata) { CWalletDB(*dbw).EraseDestData(strAddress, item.first); @@ -3093,8 +3093,8 @@ bool CWallet::DelAddressBook(const CTxDestination& address) NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address) != ISMINE_NO, "", CT_DELETED); - CWalletDB(*dbw).ErasePurpose(CBitcoinAddress(address).ToString()); - return CWalletDB(*dbw).EraseName(CBitcoinAddress(address).ToString()); + CWalletDB(*dbw).ErasePurpose(EncodeDestination(address)); + return CWalletDB(*dbw).EraseName(EncodeDestination(address)); } const std::string& CWallet::GetAccountName(const CScript& scriptPubKey) const @@ -3711,14 +3711,14 @@ bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, co return false; mapAddressBook[dest].destdata.insert(std::make_pair(key, value)); - return CWalletDB(*dbw).WriteDestData(CBitcoinAddress(dest).ToString(), key, value); + return CWalletDB(*dbw).WriteDestData(EncodeDestination(dest), key, value); } bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key) { if (!mapAddressBook[dest].destdata.erase(key)) return false; - return CWalletDB(*dbw).EraseDestData(CBitcoinAddress(dest).ToString(), key); + return CWalletDB(*dbw).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 12da3cce64..52370a8eb5 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -253,13 +253,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, { std::string strAddress; ssKey >> strAddress; - ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()].name; + ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].name; } else if (strType == "purpose") { std::string strAddress; ssKey >> strAddress; - ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()].purpose; + ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].purpose; } else if (strType == "tx") { @@ -493,7 +493,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; -- cgit v1.2.3