Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/rpcwallet.cpp
Show First 20 Lines • Show All 138 Lines • ▼ Show 20 Lines | if (!pwalletMain->GetKeyFromPool(newKey)) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_WALLET_KEYPOOL_RAN_OUT, | RPC_WALLET_KEYPOOL_RAN_OUT, | ||||
"Error: Keypool ran out, please call keypoolrefill first"); | "Error: Keypool ran out, please call keypoolrefill first"); | ||||
} | } | ||||
CKeyID keyID = newKey.GetID(); | CKeyID keyID = newKey.GetID(); | ||||
pwalletMain->SetAddressBook(keyID, strAccount, "receive"); | pwalletMain->SetAddressBook(keyID, strAccount, "receive"); | ||||
return CBitcoinAddress(keyID).ToString(); | return EncodeDestination(keyID); | ||||
} | } | ||||
CBitcoinAddress GetAccountAddress(std::string strAccount, | CTxDestination GetAccountAddress(std::string strAccount, | ||||
bool bForceNew = false) { | bool bForceNew = false) { | ||||
CPubKey pubKey; | CPubKey pubKey; | ||||
if (!pwalletMain->GetAccountPubkey(pubKey, strAccount, bForceNew)) { | if (!pwalletMain->GetAccountPubkey(pubKey, strAccount, bForceNew)) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_WALLET_KEYPOOL_RAN_OUT, | RPC_WALLET_KEYPOOL_RAN_OUT, | ||||
"Error: Keypool ran out, please call keypoolrefill first"); | "Error: Keypool ran out, please call keypoolrefill first"); | ||||
} | } | ||||
return CBitcoinAddress(pubKey.GetID()); | return pubKey.GetID(); | ||||
} | } | ||||
static UniValue getaccountaddress(const Config &config, | static UniValue getaccountaddress(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (!EnsureWalletIsAvailable(request.fHelp)) { | if (!EnsureWalletIsAvailable(request.fHelp)) { | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
Show All 19 Lines | static UniValue getaccountaddress(const Config &config, | ||||
LOCK2(cs_main, pwalletMain->cs_wallet); | LOCK2(cs_main, pwalletMain->cs_wallet); | ||||
// Parse the account first so we don't generate a key if there's an error | // Parse the account first so we don't generate a key if there's an error | ||||
std::string strAccount = AccountFromValue(request.params[0]); | std::string strAccount = AccountFromValue(request.params[0]); | ||||
UniValue ret(UniValue::VSTR); | UniValue ret(UniValue::VSTR); | ||||
ret = GetAccountAddress(strAccount).ToString(); | ret = EncodeDestination(GetAccountAddress(strAccount)); | ||||
return ret; | return ret; | ||||
} | } | ||||
static UniValue getrawchangeaddress(const Config &config, | static UniValue getrawchangeaddress(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (!EnsureWalletIsAvailable(request.fHelp)) { | if (!EnsureWalletIsAvailable(request.fHelp)) { | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
Show All 23 Lines | if (!reservekey.GetReservedKey(vchPubKey)) { | ||||
RPC_WALLET_KEYPOOL_RAN_OUT, | RPC_WALLET_KEYPOOL_RAN_OUT, | ||||
"Error: Keypool ran out, please call keypoolrefill first"); | "Error: Keypool ran out, please call keypoolrefill first"); | ||||
} | } | ||||
reservekey.KeepKey(); | reservekey.KeepKey(); | ||||
CKeyID keyID = vchPubKey.GetID(); | CKeyID keyID = vchPubKey.GetID(); | ||||
return CBitcoinAddress(keyID).ToString(); | return EncodeDestination(keyID); | ||||
} | } | ||||
static UniValue setaccount(const Config &config, | static UniValue setaccount(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (!EnsureWalletIsAvailable(request.fHelp)) { | if (!EnsureWalletIsAvailable(request.fHelp)) { | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
Show All 13 Lines | if (request.fHelp || request.params.size() < 1 || | ||||
"\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"tabby\"") + | "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"tabby\"") + | ||||
HelpExampleRpc( | HelpExampleRpc( | ||||
"setaccount", | "setaccount", | ||||
"\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"tabby\"")); | "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"tabby\"")); | ||||
} | } | ||||
LOCK2(cs_main, pwalletMain->cs_wallet); | LOCK2(cs_main, pwalletMain->cs_wallet); | ||||
CBitcoinAddress address(request.params[0].get_str()); | CTxDestination dest = DecodeDestination(request.params[0].get_str()); | ||||
if (!address.IsValid()) { | if (!IsValidDestination(dest)) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Invalid Bitcoin address"); | "Invalid Bitcoin address"); | ||||
} | } | ||||
std::string strAccount; | std::string strAccount; | ||||
if (request.params.size() > 1) { | if (request.params.size() > 1) { | ||||
strAccount = AccountFromValue(request.params[1]); | strAccount = AccountFromValue(request.params[1]); | ||||
} | } | ||||
// Only add the account if the address is yours. | // 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 | // Detect when changing the account of an address that is the 'unused | ||||
// current key' of another account: | // current key' of another account: | ||||
if (pwalletMain->mapAddressBook.count(address.Get())) { | if (pwalletMain->mapAddressBook.count(dest)) { | ||||
std::string strOldAccount = | std::string strOldAccount = pwalletMain->mapAddressBook[dest].name; | ||||
pwalletMain->mapAddressBook[address.Get()].name; | if (dest == GetAccountAddress(strOldAccount)) { | ||||
if (address == GetAccountAddress(strOldAccount)) { | |||||
GetAccountAddress(strOldAccount, true); | GetAccountAddress(strOldAccount, true); | ||||
} | } | ||||
} | } | ||||
pwalletMain->SetAddressBook(address.Get(), strAccount, "receive"); | pwalletMain->SetAddressBook(dest, strAccount, "receive"); | ||||
} else { | } else { | ||||
throw JSONRPCError(RPC_MISC_ERROR, | throw JSONRPCError(RPC_MISC_ERROR, | ||||
"setaccount can only be used with own address"); | "setaccount can only be used with own address"); | ||||
} | } | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
Show All 17 Lines | if (request.fHelp || request.params.size() != 1) { | ||||
HelpExampleCli("getaccount", | HelpExampleCli("getaccount", | ||||
"\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"") + | "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"") + | ||||
HelpExampleRpc("getaccount", | HelpExampleRpc("getaccount", | ||||
"\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"")); | "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"")); | ||||
} | } | ||||
LOCK2(cs_main, pwalletMain->cs_wallet); | LOCK2(cs_main, pwalletMain->cs_wallet); | ||||
CBitcoinAddress address(request.params[0].get_str()); | CTxDestination dest = DecodeDestination(request.params[0].get_str()); | ||||
if (!address.IsValid()) { | if (!IsValidDestination(dest)) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Invalid Bitcoin address"); | "Invalid Bitcoin address"); | ||||
} | } | ||||
std::string strAccount; | std::string strAccount; | ||||
std::map<CTxDestination, CAddressBookData>::iterator mi = | std::map<CTxDestination, CAddressBookData>::iterator mi = | ||||
pwalletMain->mapAddressBook.find(address.Get()); | pwalletMain->mapAddressBook.find(dest); | ||||
if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty()) { | if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty()) { | ||||
strAccount = (*mi).second.name; | strAccount = (*mi).second.name; | ||||
} | } | ||||
return strAccount; | return strAccount; | ||||
} | } | ||||
static UniValue getaddressesbyaccount(const Config &config, | static UniValue getaddressesbyaccount(const Config &config, | ||||
Show All 21 Lines | static UniValue getaddressesbyaccount(const Config &config, | ||||
} | } | ||||
LOCK2(cs_main, pwalletMain->cs_wallet); | LOCK2(cs_main, pwalletMain->cs_wallet); | ||||
std::string strAccount = AccountFromValue(request.params[0]); | std::string strAccount = AccountFromValue(request.params[0]); | ||||
// Find all addresses that have the given account | // Find all addresses that have the given account | ||||
UniValue ret(UniValue::VARR); | UniValue ret(UniValue::VARR); | ||||
for (const std::pair<CBitcoinAddress, CAddressBookData> &item : | for (const std::pair<CTxDestination, CAddressBookData> &item : | ||||
pwalletMain->mapAddressBook) { | pwalletMain->mapAddressBook) { | ||||
const CBitcoinAddress &address = item.first; | const CTxDestination &dest = item.first; | ||||
const std::string &strName = item.second.name; | 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; | return ret; | ||||
} | } | ||||
static void SendMoney(const CTxDestination &address, CAmount nValue, | static void SendMoney(const CTxDestination &address, CAmount nValue, | ||||
bool fSubtractFeeFromAmount, CWalletTx &wtxNew) { | bool fSubtractFeeFromAmount, CWalletTx &wtxNew) { | ||||
CAmount curBalance = pwalletMain->GetBalance(); | CAmount curBalance = pwalletMain->GetBalance(); | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | if (request.fHelp || request.params.size() < 2 || | ||||
"\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true") + | "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true") + | ||||
HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvay" | HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvay" | ||||
"dd\", 0.1, \"donation\", \"seans " | "dd\", 0.1, \"donation\", \"seans " | ||||
"outpost\"")); | "outpost\"")); | ||||
} | } | ||||
LOCK2(cs_main, pwalletMain->cs_wallet); | LOCK2(cs_main, pwalletMain->cs_wallet); | ||||
CBitcoinAddress address(request.params[0].get_str()); | CTxDestination dest = DecodeDestination(request.params[0].get_str()); | ||||
if (!address.IsValid()) { | if (!IsValidDestination(dest)) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); | ||||
"Invalid Bitcoin address"); | |||||
} | } | ||||
// Amount | // Amount | ||||
CAmount nAmount = AmountFromValue(request.params[1]); | CAmount nAmount = AmountFromValue(request.params[1]); | ||||
if (nAmount <= 0) { | if (nAmount <= 0) { | ||||
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send"); | throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send"); | ||||
} | } | ||||
Show All 10 Lines | static UniValue sendtoaddress(const Config &config, | ||||
bool fSubtractFeeFromAmount = false; | bool fSubtractFeeFromAmount = false; | ||||
if (request.params.size() > 4) { | if (request.params.size() > 4) { | ||||
fSubtractFeeFromAmount = request.params[4].get_bool(); | fSubtractFeeFromAmount = request.params[4].get_bool(); | ||||
} | } | ||||
EnsureWalletIsUnlocked(); | EnsureWalletIsUnlocked(); | ||||
SendMoney(address.Get(), nAmount, fSubtractFeeFromAmount, wtx); | SendMoney(dest, nAmount, fSubtractFeeFromAmount, wtx); | ||||
return wtx.GetId().GetHex(); | return wtx.GetId().GetHex(); | ||||
} | } | ||||
static UniValue listaddressgroupings(const Config &config, | static UniValue listaddressgroupings(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (!EnsureWalletIsAvailable(request.fHelp)) { | if (!EnsureWalletIsAvailable(request.fHelp)) { | ||||
return NullUniValue; | return NullUniValue; | ||||
Show All 25 Lines | if (request.fHelp) { | ||||
HelpExampleRpc("listaddressgroupings", "")); | HelpExampleRpc("listaddressgroupings", "")); | ||||
} | } | ||||
LOCK2(cs_main, pwalletMain->cs_wallet); | LOCK2(cs_main, pwalletMain->cs_wallet); | ||||
UniValue jsonGroupings(UniValue::VARR); | UniValue jsonGroupings(UniValue::VARR); | ||||
std::map<CTxDestination, CAmount> balances = | std::map<CTxDestination, CAmount> balances = | ||||
pwalletMain->GetAddressBalances(); | pwalletMain->GetAddressBalances(); | ||||
for (std::set<CTxDestination> grouping : | for (const std::set<CTxDestination> &grouping : | ||||
pwalletMain->GetAddressGroupings()) { | pwalletMain->GetAddressGroupings()) { | ||||
UniValue jsonGrouping(UniValue::VARR); | UniValue jsonGrouping(UniValue::VARR); | ||||
for (CTxDestination address : grouping) { | for (const CTxDestination &address : grouping) { | ||||
UniValue addressInfo(UniValue::VARR); | UniValue addressInfo(UniValue::VARR); | ||||
addressInfo.push_back(CBitcoinAddress(address).ToString()); | addressInfo.push_back(EncodeDestination(address)); | ||||
addressInfo.push_back(ValueFromAmount(balances[address])); | addressInfo.push_back(ValueFromAmount(balances[address])); | ||||
if (pwalletMain->mapAddressBook.find( | if (pwalletMain->mapAddressBook.find(address) != | ||||
CBitcoinAddress(address).Get()) != | |||||
pwalletMain->mapAddressBook.end()) { | pwalletMain->mapAddressBook.end()) { | ||||
addressInfo.push_back(pwalletMain->mapAddressBook | addressInfo.push_back( | ||||
.find(CBitcoinAddress(address).Get()) | pwalletMain->mapAddressBook.find(address)->second.name); | ||||
->second.name); | |||||
} | } | ||||
jsonGrouping.push_back(addressInfo); | jsonGrouping.push_back(addressInfo); | ||||
} | } | ||||
jsonGroupings.push_back(jsonGrouping); | jsonGroupings.push_back(jsonGrouping); | ||||
} | } | ||||
return jsonGroupings; | return jsonGroupings; | ||||
} | } | ||||
Show All 37 Lines | static UniValue signmessage(const Config &config, | ||||
LOCK2(cs_main, pwalletMain->cs_wallet); | LOCK2(cs_main, pwalletMain->cs_wallet); | ||||
EnsureWalletIsUnlocked(); | EnsureWalletIsUnlocked(); | ||||
std::string strAddress = request.params[0].get_str(); | std::string strAddress = request.params[0].get_str(); | ||||
std::string strMessage = request.params[1].get_str(); | std::string strMessage = request.params[1].get_str(); | ||||
CBitcoinAddress addr(strAddress); | CTxDestination dest = DecodeDestination(strAddress); | ||||
if (!addr.IsValid()) { | if (!IsValidDestination(dest)) { | ||||
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address"); | throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address"); | ||||
} | } | ||||
CKeyID keyID; | const CKeyID *keyID = boost::get<CKeyID>(&dest); | ||||
if (!addr.GetKeyID(keyID)) { | if (!keyID) { | ||||
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); | throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); | ||||
} | } | ||||
CKey key; | CKey key; | ||||
if (!pwalletMain->GetKey(keyID, key)) { | if (!pwalletMain->GetKey(*keyID, key)) { | ||||
throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available"); | throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available"); | ||||
} | } | ||||
CHashWriter ss(SER_GETHASH, 0); | CHashWriter ss(SER_GETHASH, 0); | ||||
ss << strMessageMagic; | ss << strMessageMagic; | ||||
ss << strMessage; | ss << strMessage; | ||||
std::vector<uint8_t> vchSig; | std::vector<uint8_t> vchSig; | ||||
Show All 39 Lines | if (request.fHelp || request.params.size() < 1 || | ||||
"\nAs a json rpc call\n" + | "\nAs a json rpc call\n" + | ||||
HelpExampleRpc("getreceivedbyaddress", | HelpExampleRpc("getreceivedbyaddress", | ||||
"\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", 6")); | "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", 6")); | ||||
} | } | ||||
LOCK2(cs_main, pwalletMain->cs_wallet); | LOCK2(cs_main, pwalletMain->cs_wallet); | ||||
// Bitcoin address | // Bitcoin address | ||||
CBitcoinAddress address = CBitcoinAddress(request.params[0].get_str()); | CTxDestination dest = DecodeDestination(request.params[0].get_str()); | ||||
if (!address.IsValid()) { | if (!IsValidDestination(dest)) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Invalid Bitcoin address"); | "Invalid Bitcoin address"); | ||||
} | } | ||||
CScript scriptPubKey = GetScriptForDestination(dest); | |||||
CScript scriptPubKey = GetScriptForDestination(address.Get()); | |||||
if (!IsMine(*pwalletMain, scriptPubKey)) { | if (!IsMine(*pwalletMain, scriptPubKey)) { | ||||
return ValueFromAmount(0); | return ValueFromAmount(0); | ||||
} | } | ||||
// Minimum confirmations | // Minimum confirmations | ||||
int nMinDepth = 1; | int nMinDepth = 1; | ||||
if (request.params.size() > 1) { | if (request.params.size() > 1) { | ||||
nMinDepth = request.params[1].get_int(); | nMinDepth = request.params[1].get_int(); | ||||
▲ Show 20 Lines • Show All 360 Lines • ▼ Show 20 Lines | if (request.fHelp || request.params.size() < 3 || | ||||
HelpExampleRpc("sendfrom", | HelpExampleRpc("sendfrom", | ||||
"\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", " | "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", " | ||||
"0.01, 6, \"donation\", \"seans outpost\"")); | "0.01, 6, \"donation\", \"seans outpost\"")); | ||||
} | } | ||||
LOCK2(cs_main, pwalletMain->cs_wallet); | LOCK2(cs_main, pwalletMain->cs_wallet); | ||||
std::string strAccount = AccountFromValue(request.params[0]); | std::string strAccount = AccountFromValue(request.params[0]); | ||||
CBitcoinAddress address(request.params[1].get_str()); | CTxDestination dest = DecodeDestination(request.params[1].get_str()); | ||||
if (!address.IsValid()) { | if (!IsValidDestination(dest)) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Invalid Bitcoin address"); | "Invalid Bitcoin address"); | ||||
} | } | ||||
CAmount nAmount = AmountFromValue(request.params[2]); | CAmount nAmount = AmountFromValue(request.params[2]); | ||||
if (nAmount <= 0) { | if (nAmount <= 0) { | ||||
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send"); | throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send"); | ||||
} | } | ||||
int nMinDepth = 1; | int nMinDepth = 1; | ||||
if (request.params.size() > 3) { | if (request.params.size() > 3) { | ||||
nMinDepth = request.params[3].get_int(); | nMinDepth = request.params[3].get_int(); | ||||
Show All 16 Lines | static UniValue sendfrom(const Config &config, const JSONRPCRequest &request) { | ||||
// Check funds | // Check funds | ||||
CAmount nBalance = | CAmount nBalance = | ||||
pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); | pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); | ||||
if (nAmount > nBalance) { | if (nAmount > nBalance) { | ||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, | throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, | ||||
"Account has insufficient funds"); | "Account has insufficient funds"); | ||||
} | } | ||||
SendMoney(address.Get(), nAmount, false, wtx); | SendMoney(dest, nAmount, false, wtx); | ||||
return wtx.GetId().GetHex(); | return wtx.GetId().GetHex(); | ||||
} | } | ||||
static UniValue sendmany(const Config &config, const JSONRPCRequest &request) { | static UniValue sendmany(const Config &config, const JSONRPCRequest &request) { | ||||
if (!EnsureWalletIsAvailable(request.fHelp)) { | if (!EnsureWalletIsAvailable(request.fHelp)) { | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | if (request.params.size() > 3 && !request.params[3].isNull() && | ||||
wtx.mapValue["comment"] = request.params[3].get_str(); | wtx.mapValue["comment"] = request.params[3].get_str(); | ||||
} | } | ||||
UniValue subtractFeeFromAmount(UniValue::VARR); | UniValue subtractFeeFromAmount(UniValue::VARR); | ||||
if (request.params.size() > 4) { | if (request.params.size() > 4) { | ||||
subtractFeeFromAmount = request.params[4].get_array(); | subtractFeeFromAmount = request.params[4].get_array(); | ||||
} | } | ||||
std::set<CBitcoinAddress> setAddress; | std::set<CTxDestination> destinations; | ||||
std::vector<CRecipient> vecSend; | std::vector<CRecipient> vecSend; | ||||
CAmount totalAmount = 0; | CAmount totalAmount = 0; | ||||
std::vector<std::string> keys = sendTo.getKeys(); | std::vector<std::string> keys = sendTo.getKeys(); | ||||
for (const std::string &name_ : keys) { | for (const std::string &name_ : keys) { | ||||
CBitcoinAddress address(name_); | CTxDestination dest = DecodeDestination(name_); | ||||
if (!address.IsValid()) { | if (!IsValidDestination(dest)) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
std::string("Invalid Bitcoin address: ") + | std::string("Invalid Bitcoin address: ") + | ||||
name_); | name_); | ||||
} | } | ||||
if (setAddress.count(address)) { | if (destinations.count(dest)) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_INVALID_PARAMETER, | RPC_INVALID_PARAMETER, | ||||
std::string("Invalid parameter, duplicated address: ") + name_); | std::string("Invalid parameter, duplicated address: ") + name_); | ||||
} | } | ||||
setAddress.insert(address); | destinations.insert(dest); | ||||
CScript scriptPubKey = GetScriptForDestination(address.Get()); | CScript scriptPubKey = GetScriptForDestination(dest); | ||||
CAmount nAmount = AmountFromValue(sendTo[name_]); | CAmount nAmount = AmountFromValue(sendTo[name_]); | ||||
if (nAmount <= 0) { | if (nAmount <= 0) { | ||||
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send"); | throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send"); | ||||
} | } | ||||
totalAmount += nAmount; | totalAmount += nAmount; | ||||
bool fSubtractFeeFromAmount = false; | bool fSubtractFeeFromAmount = false; | ||||
for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) { | for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) { | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | static UniValue addmultisigaddress(const Config &config, | ||||
} | } | ||||
// Construct using pay-to-script-hash: | // Construct using pay-to-script-hash: | ||||
CScript inner = createmultisig_redeemScript(request.params); | CScript inner = createmultisig_redeemScript(request.params); | ||||
CScriptID innerID(inner); | CScriptID innerID(inner); | ||||
pwalletMain->AddCScript(inner); | pwalletMain->AddCScript(inner); | ||||
pwalletMain->SetAddressBook(innerID, strAccount, "send"); | pwalletMain->SetAddressBook(innerID, strAccount, "send"); | ||||
return CBitcoinAddress(innerID).ToString(); | return EncodeDestination(innerID); | ||||
} | } | ||||
struct tallyitem { | struct tallyitem { | ||||
CAmount nAmount; | CAmount nAmount; | ||||
int nConf; | int nConf; | ||||
std::vector<uint256> txids; | std::vector<uint256> txids; | ||||
bool fIsWatchonly; | bool fIsWatchonly; | ||||
tallyitem() { | tallyitem() { | ||||
Show All 17 Lines | if (params.size() > 1) { | ||||
fIncludeEmpty = params[1].get_bool(); | fIncludeEmpty = params[1].get_bool(); | ||||
} | } | ||||
isminefilter filter = ISMINE_SPENDABLE; | isminefilter filter = ISMINE_SPENDABLE; | ||||
if (params.size() > 2 && params[2].get_bool()) | if (params.size() > 2 && params[2].get_bool()) | ||||
filter = filter | ISMINE_WATCH_ONLY; | filter = filter | ISMINE_WATCH_ONLY; | ||||
// Tally | // Tally | ||||
std::map<CBitcoinAddress, tallyitem> mapTally; | std::map<CTxDestination, tallyitem> mapTally; | ||||
for (std::map<uint256, CWalletTx>::iterator it = | for (std::map<uint256, CWalletTx>::iterator it = | ||||
pwalletMain->mapWallet.begin(); | pwalletMain->mapWallet.begin(); | ||||
it != pwalletMain->mapWallet.end(); ++it) { | it != pwalletMain->mapWallet.end(); ++it) { | ||||
const CWalletTx &wtx = (*it).second; | const CWalletTx &wtx = (*it).second; | ||||
CValidationState state; | CValidationState state; | ||||
if (wtx.IsCoinBase() || | if (wtx.IsCoinBase() || | ||||
!ContextualCheckTransactionForCurrentBlock( | !ContextualCheckTransactionForCurrentBlock( | ||||
Show All 26 Lines | for (std::map<uint256, CWalletTx>::iterator it = | ||||
item.fIsWatchonly = true; | item.fIsWatchonly = true; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// Reply | // Reply | ||||
UniValue ret(UniValue::VARR); | UniValue ret(UniValue::VARR); | ||||
std::map<std::string, tallyitem> mapAccountTally; | std::map<std::string, tallyitem> mapAccountTally; | ||||
for (const std::pair<CBitcoinAddress, CAddressBookData> &item : | for (const std::pair<CTxDestination, CAddressBookData> &item : | ||||
pwalletMain->mapAddressBook) { | pwalletMain->mapAddressBook) { | ||||
const CBitcoinAddress &address = item.first; | const CTxDestination &dest = item.first; | ||||
const std::string &strAccount = item.second.name; | const std::string &strAccount = item.second.name; | ||||
std::map<CBitcoinAddress, tallyitem>::iterator it = | std::map<CTxDestination, tallyitem>::iterator it = mapTally.find(dest); | ||||
mapTally.find(address); | |||||
if (it == mapTally.end() && !fIncludeEmpty) { | if (it == mapTally.end() && !fIncludeEmpty) { | ||||
continue; | continue; | ||||
} | } | ||||
CAmount nAmount = 0; | CAmount nAmount = 0; | ||||
int nConf = std::numeric_limits<int>::max(); | int nConf = std::numeric_limits<int>::max(); | ||||
bool fIsWatchonly = false; | bool fIsWatchonly = false; | ||||
if (it != mapTally.end()) { | if (it != mapTally.end()) { | ||||
nAmount = (*it).second.nAmount; | nAmount = (*it).second.nAmount; | ||||
nConf = (*it).second.nConf; | nConf = (*it).second.nConf; | ||||
fIsWatchonly = (*it).second.fIsWatchonly; | fIsWatchonly = (*it).second.fIsWatchonly; | ||||
} | } | ||||
if (fByAccounts) { | if (fByAccounts) { | ||||
tallyitem &_item = mapAccountTally[strAccount]; | tallyitem &_item = mapAccountTally[strAccount]; | ||||
_item.nAmount += nAmount; | _item.nAmount += nAmount; | ||||
_item.nConf = std::min(_item.nConf, nConf); | _item.nConf = std::min(_item.nConf, nConf); | ||||
_item.fIsWatchonly = fIsWatchonly; | _item.fIsWatchonly = fIsWatchonly; | ||||
} else { | } else { | ||||
UniValue obj(UniValue::VOBJ); | UniValue obj(UniValue::VOBJ); | ||||
if (fIsWatchonly) { | if (fIsWatchonly) { | ||||
obj.push_back(Pair("involvesWatchonly", true)); | 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("account", strAccount)); | ||||
obj.push_back(Pair("amount", ValueFromAmount(nAmount))); | obj.push_back(Pair("amount", ValueFromAmount(nAmount))); | ||||
obj.push_back( | obj.push_back( | ||||
Pair("confirmations", | Pair("confirmations", | ||||
(nConf == std::numeric_limits<int>::max() ? 0 : nConf))); | (nConf == std::numeric_limits<int>::max() ? 0 : nConf))); | ||||
if (!fByAccounts) { | if (!fByAccounts) { | ||||
obj.push_back(Pair("label", strAccount)); | obj.push_back(Pair("label", strAccount)); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 127 Lines • ▼ Show 20 Lines | static UniValue listreceivedbyaccount(const Config &config, | ||||
} | } | ||||
LOCK2(cs_main, pwalletMain->cs_wallet); | LOCK2(cs_main, pwalletMain->cs_wallet); | ||||
return ListReceived(config, request.params, true); | return ListReceived(config, request.params, true); | ||||
} | } | ||||
static void MaybePushAddress(UniValue &entry, const CTxDestination &dest) { | static void MaybePushAddress(UniValue &entry, const CTxDestination &dest) { | ||||
CBitcoinAddress addr; | if (IsValidDestination(dest)) { | ||||
if (addr.Set(dest)) { | entry.push_back(Pair("address", EncodeDestination(dest))); | ||||
entry.push_back(Pair("address", addr.ToString())); | |||||
} | } | ||||
} | } | ||||
void ListTransactions(const CWalletTx &wtx, const std::string &strAccount, | void ListTransactions(const CWalletTx &wtx, const std::string &strAccount, | ||||
int nMinDepth, bool fLong, UniValue &ret, | int nMinDepth, bool fLong, UniValue &ret, | ||||
const isminefilter &filter) { | const isminefilter &filter) { | ||||
CAmount nFee; | CAmount nFee; | ||||
std::string strSentAccount; | std::string strSentAccount; | ||||
▲ Show 20 Lines • Show All 1,430 Lines • ▼ Show 20 Lines | static UniValue listunspent(const Config &config, | ||||
} | } | ||||
int nMaxDepth = 9999999; | int nMaxDepth = 9999999; | ||||
if (request.params.size() > 1 && !request.params[1].isNull()) { | if (request.params.size() > 1 && !request.params[1].isNull()) { | ||||
RPCTypeCheckArgument(request.params[1], UniValue::VNUM); | RPCTypeCheckArgument(request.params[1], UniValue::VNUM); | ||||
nMaxDepth = request.params[1].get_int(); | nMaxDepth = request.params[1].get_int(); | ||||
} | } | ||||
std::set<CBitcoinAddress> setAddress; | std::set<CTxDestination> destinations; | ||||
if (request.params.size() > 2 && !request.params[2].isNull()) { | if (request.params.size() > 2 && !request.params[2].isNull()) { | ||||
RPCTypeCheckArgument(request.params[2], UniValue::VARR); | RPCTypeCheckArgument(request.params[2], UniValue::VARR); | ||||
UniValue inputs = request.params[2].get_array(); | UniValue inputs = request.params[2].get_array(); | ||||
for (size_t idx = 0; idx < inputs.size(); idx++) { | for (size_t idx = 0; idx < inputs.size(); idx++) { | ||||
const UniValue &input = inputs[idx]; | const UniValue &input = inputs[idx]; | ||||
CBitcoinAddress address(input.get_str()); | CTxDestination dest = DecodeDestination(input.get_str()); | ||||
if (!address.IsValid()) { | if (!IsValidDestination(dest)) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
std::string("Invalid Bitcoin address: ") + | std::string("Invalid Bitcoin address: ") + | ||||
input.get_str()); | input.get_str()); | ||||
} | } | ||||
if (setAddress.count(address)) { | if (!destinations.insert(dest).second) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_INVALID_PARAMETER, | RPC_INVALID_PARAMETER, | ||||
std::string("Invalid parameter, duplicated address: ") + | std::string("Invalid parameter, duplicated address: ") + | ||||
input.get_str()); | input.get_str()); | ||||
} | } | ||||
setAddress.insert(address); | |||||
} | } | ||||
} | } | ||||
bool include_unsafe = true; | bool include_unsafe = true; | ||||
if (request.params.size() > 3 && !request.params[3].isNull()) { | if (request.params.size() > 3 && !request.params[3].isNull()) { | ||||
RPCTypeCheckArgument(request.params[3], UniValue::VBOOL); | RPCTypeCheckArgument(request.params[3], UniValue::VBOOL); | ||||
include_unsafe = request.params[3].get_bool(); | include_unsafe = request.params[3].get_bool(); | ||||
} | } | ||||
UniValue results(UniValue::VARR); | UniValue results(UniValue::VARR); | ||||
std::vector<COutput> vecOutputs; | std::vector<COutput> vecOutputs; | ||||
assert(pwalletMain != nullptr); | assert(pwalletMain != nullptr); | ||||
LOCK2(cs_main, pwalletMain->cs_wallet); | LOCK2(cs_main, pwalletMain->cs_wallet); | ||||
pwalletMain->AvailableCoins(vecOutputs, !include_unsafe, nullptr, true); | pwalletMain->AvailableCoins(vecOutputs, !include_unsafe, nullptr, true); | ||||
for (const COutput &out : vecOutputs) { | for (const COutput &out : vecOutputs) { | ||||
if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth) { | if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth) { | ||||
continue; | continue; | ||||
} | } | ||||
CTxDestination address; | CTxDestination address; | ||||
const CScript &scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey; | const CScript &scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey; | ||||
bool fValidAddress = ExtractDestination(scriptPubKey, address); | bool fValidAddress = ExtractDestination(scriptPubKey, address); | ||||
if (setAddress.size() && | if (destinations.size() && | ||||
(!fValidAddress || !setAddress.count(address))) { | (!fValidAddress || !destinations.count(address))) | ||||
continue; | continue; | ||||
} | |||||
UniValue entry(UniValue::VOBJ); | UniValue entry(UniValue::VOBJ); | ||||
entry.push_back(Pair("txid", out.tx->GetId().GetHex())); | entry.push_back(Pair("txid", out.tx->GetId().GetHex())); | ||||
entry.push_back(Pair("vout", out.i)); | entry.push_back(Pair("vout", out.i)); | ||||
if (fValidAddress) { | if (fValidAddress) { | ||||
{ | entry.push_back(Pair("address", EncodeDestination(address))); | ||||
entry.push_back( | |||||
Pair("address", CBitcoinAddress(address).ToString())); | |||||
} | |||||
if (pwalletMain->mapAddressBook.count(address)) { | if (pwalletMain->mapAddressBook.count(address)) { | ||||
entry.push_back( | entry.push_back( | ||||
Pair("account", pwalletMain->mapAddressBook[address].name)); | Pair("account", pwalletMain->mapAddressBook[address].name)); | ||||
} | } | ||||
if (scriptPubKey.IsPayToScriptHash()) { | if (scriptPubKey.IsPayToScriptHash()) { | ||||
const CScriptID &hash = boost::get<CScriptID>(address); | const CScriptID &hash = boost::get<CScriptID>(address); | ||||
▲ Show 20 Lines • Show All 134 Lines • ▼ Show 20 Lines | if (request.params.size() > 1) { | ||||
{"lockUnspents", UniValueType(UniValue::VBOOL)}, | {"lockUnspents", UniValueType(UniValue::VBOOL)}, | ||||
{"reserveChangeKey", UniValueType(UniValue::VBOOL)}, | {"reserveChangeKey", UniValueType(UniValue::VBOOL)}, | ||||
{"feeRate", UniValueType()}, // will be checked below | {"feeRate", UniValueType()}, // will be checked below | ||||
{"subtractFeeFromOutputs", UniValueType(UniValue::VARR)}, | {"subtractFeeFromOutputs", UniValueType(UniValue::VARR)}, | ||||
}, | }, | ||||
true, true); | true, true); | ||||
if (options.exists("changeAddress")) { | 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( | throw JSONRPCError( | ||||
RPC_INVALID_ADDRESS_OR_KEY, | RPC_INVALID_ADDRESS_OR_KEY, | ||||
"changeAddress must be a valid bitcoin address"); | "changeAddress must be a valid bitcoin address"); | ||||
} | } | ||||
changeAddress = address.Get(); | changeAddress = dest; | ||||
} | } | ||||
if (options.exists("changePosition")) { | if (options.exists("changePosition")) { | ||||
changePosition = options["changePosition"].get_int(); | changePosition = options["changePosition"].get_int(); | ||||
} | } | ||||
if (options.exists("includeWatching")) { | if (options.exists("includeWatching")) { | ||||
includeWatching = options["includeWatching"].get_bool(); | includeWatching = options["includeWatching"].get_bool(); | ||||
▲ Show 20 Lines • Show All 130 Lines • Show Last 20 Lines |