mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-03-25 23:16:16 +01:00
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.
This commit is contained in:
@@ -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<CTxDestination, CAddressBookData>::iterator mi = pwallet->mapAddressBook.find(address.Get());
|
||||
std::map<CTxDestination, CAddressBookData>::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<CBitcoinAddress, CAddressBookData>& item : pwallet->mapAddressBook) {
|
||||
const CBitcoinAddress& address = item.first;
|
||||
for (const std::pair<CTxDestination, CAddressBookData>& 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<CTxDestination, CAmount> balances = pwallet->GetAddressBalances();
|
||||
for (std::set<CTxDestination> grouping : pwallet->GetAddressGroupings()) {
|
||||
for (const std::set<CTxDestination>& 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<CKeyID>(&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<CBitcoinAddress> setAddress;
|
||||
std::set<CTxDestination> destinations;
|
||||
std::vector<CRecipient> vecSend;
|
||||
|
||||
CAmount totalAmount = 0;
|
||||
std::vector<std::string> 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<bool>
|
||||
@@ -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<CBitcoinAddress, tallyitem> mapTally;
|
||||
std::map<CTxDestination, tallyitem> mapTally;
|
||||
for (const std::pair<uint256, CWalletTx>& 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<std::string, tallyitem> mapAccountTally;
|
||||
for (const std::pair<CBitcoinAddress, CAddressBookData>& item : pwallet->mapAddressBook) {
|
||||
const CBitcoinAddress& address = item.first;
|
||||
for (const std::pair<CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
|
||||
const CTxDestination& dest = item.first;
|
||||
const std::string& strAccount = item.second.name;
|
||||
std::map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
|
||||
std::map<CTxDestination, tallyitem>::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<int>::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<CBitcoinAddress> setAddress;
|
||||
std::set<CTxDestination> 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"))
|
||||
|
||||
Reference in New Issue
Block a user