aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rpc/misc.cpp66
-rw-r--r--src/rpc/rawtransaction.cpp16
-rw-r--r--src/rpc/server.cpp11
-rw-r--r--src/rpc/server.h6
-rw-r--r--src/utilstrencodings.cpp3
-rw-r--r--src/utilstrencodings.h3
-rw-r--r--src/wallet/rpcdump.cpp258
-rw-r--r--src/wallet/rpcwallet.cpp638
-rw-r--r--src/wallet/rpcwallet.h13
-rw-r--r--src/wallet/wallet.cpp6
-rw-r--r--src/wallet/wallet.h3
11 files changed, 600 insertions, 423 deletions
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index c84eab7d23..23515f116f 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -14,6 +14,7 @@
#include "util.h"
#include "utilstrencodings.h"
#ifdef ENABLE_WALLET
+#include "wallet/rpcwallet.h"
#include "wallet/wallet.h"
#include "wallet/walletdb.h"
#endif
@@ -70,7 +71,9 @@ UniValue getinfo(const JSONRPCRequest& request)
);
#ifdef ENABLE_WALLET
- LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+
+ LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : NULL);
#else
LOCK(cs_main);
#endif
@@ -82,9 +85,9 @@ UniValue getinfo(const JSONRPCRequest& request)
obj.push_back(Pair("version", CLIENT_VERSION));
obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
#ifdef ENABLE_WALLET
- if (pwalletMain) {
- obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
- obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
+ if (pwallet) {
+ obj.push_back(Pair("walletversion", pwallet->GetVersion()));
+ obj.push_back(Pair("balance", ValueFromAmount(pwallet->GetBalance())));
}
#endif
obj.push_back(Pair("blocks", (int)chainActive.Height()));
@@ -95,12 +98,13 @@ UniValue getinfo(const JSONRPCRequest& request)
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("testnet", Params().NetworkIDString() == CBaseChainParams::TESTNET));
#ifdef ENABLE_WALLET
- if (pwalletMain) {
- obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
- obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
+ if (pwallet) {
+ obj.push_back(Pair("keypoololdest", pwallet->GetOldestKeyPoolTime()));
+ obj.push_back(Pair("keypoolsize", (int)pwallet->GetKeyPoolSize()));
+ }
+ if (pwallet && pwallet->IsCrypted()) {
+ obj.push_back(Pair("unlocked_until", pwallet->nRelockTime));
}
- if (pwalletMain && pwalletMain->IsCrypted())
- obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
#endif
obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
@@ -112,13 +116,17 @@ UniValue getinfo(const JSONRPCRequest& request)
class DescribeAddressVisitor : public boost::static_visitor<UniValue>
{
public:
+ CWallet * const pwallet;
+
+ DescribeAddressVisitor(CWallet *_pwallet) : pwallet(_pwallet) {}
+
UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
UniValue operator()(const CKeyID &keyID) const {
UniValue obj(UniValue::VOBJ);
CPubKey vchPubKey;
obj.push_back(Pair("isscript", false));
- if (pwalletMain && pwalletMain->GetPubKey(keyID, vchPubKey)) {
+ if (pwallet && pwallet->GetPubKey(keyID, vchPubKey)) {
obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
}
@@ -129,7 +137,7 @@ public:
UniValue obj(UniValue::VOBJ);
CScript subscript;
obj.push_back(Pair("isscript", true));
- if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) {
+ if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
std::vector<CTxDestination> addresses;
txnouttype whichType;
int nRequired;
@@ -177,7 +185,9 @@ UniValue validateaddress(const JSONRPCRequest& request)
);
#ifdef ENABLE_WALLET
- LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+
+ LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : NULL);
#else
LOCK(cs_main);
#endif
@@ -197,16 +207,17 @@ UniValue validateaddress(const JSONRPCRequest& request)
ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
#ifdef ENABLE_WALLET
- isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
+ isminetype mine = pwallet ? IsMine(*pwallet, dest) : ISMINE_NO;
ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
- UniValue detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
+ UniValue detail = boost::apply_visitor(DescribeAddressVisitor(pwallet), dest);
ret.pushKVs(detail);
- if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
- ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
+ if (pwallet && pwallet->mapAddressBook.count(dest)) {
+ ret.push_back(Pair("account", pwallet->mapAddressBook[dest].name));
+ }
CKeyID keyID;
- if (pwalletMain) {
- const auto& meta = pwalletMain->mapKeyMetadata;
+ if (pwallet) {
+ const auto& meta = pwallet->mapKeyMetadata;
auto it = address.GetKeyID(keyID) ? meta.find(keyID) : meta.end();
if (it == meta.end()) {
it = meta.find(CScriptID(scriptPubKey));
@@ -224,10 +235,13 @@ UniValue validateaddress(const JSONRPCRequest& request)
return ret;
}
+// Needed even with !ENABLE_WALLET, to pass (ignored) pointers around
+class CWallet;
+
/**
* Used by addmultisigaddress / createmultisig:
*/
-CScript _createmultisig_redeemScript(const UniValue& params)
+CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniValue& params)
{
int nRequired = params[0].get_int();
const UniValue& keys = params[1].get_array();
@@ -249,16 +263,16 @@ CScript _createmultisig_redeemScript(const UniValue& params)
#ifdef ENABLE_WALLET
// Case 1: Bitcoin address and we have full public key:
CBitcoinAddress address(ks);
- if (pwalletMain && address.IsValid())
- {
+ if (pwallet && address.IsValid()) {
CKeyID keyID;
if (!address.GetKeyID(keyID))
throw runtime_error(
strprintf("%s does not refer to a key",ks));
CPubKey vchPubKey;
- if (!pwalletMain->GetPubKey(keyID, vchPubKey))
+ if (!pwallet->GetPubKey(keyID, vchPubKey)) {
throw runtime_error(
strprintf("no full public key for address %s",ks));
+ }
if (!vchPubKey.IsFullyValid())
throw runtime_error(" Invalid public key: "+ks);
pubkeys[i] = vchPubKey;
@@ -290,6 +304,12 @@ CScript _createmultisig_redeemScript(const UniValue& params)
UniValue createmultisig(const JSONRPCRequest& request)
{
+#ifdef ENABLE_WALLET
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+#else
+ CWallet * const pwallet = NULL;
+#endif
+
if (request.fHelp || request.params.size() < 2 || request.params.size() > 2)
{
string msg = "createmultisig nrequired [\"key\",...]\n"
@@ -320,7 +340,7 @@ UniValue createmultisig(const JSONRPCRequest& request)
}
// Construct using pay-to-script-hash:
- CScript inner = _createmultisig_redeemScript(request.params);
+ CScript inner = _createmultisig_redeemScript(pwallet, request.params);
CScriptID innerID(inner);
CBitcoinAddress address(innerID);
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index bf16f27498..79b27d0475 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -24,6 +24,7 @@
#include "uint256.h"
#include "utilstrencodings.h"
#ifdef ENABLE_WALLET
+#include "wallet/rpcwallet.h"
#include "wallet/wallet.h"
#endif
@@ -594,6 +595,10 @@ static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::
UniValue signrawtransaction(const JSONRPCRequest& request)
{
+#ifdef ENABLE_WALLET
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+#endif
+
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
throw runtime_error(
"signrawtransaction \"hexstring\" ( [{\"txid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\",\"redeemScript\":\"hex\"},...] [\"privatekey1\",...] sighashtype )\n"
@@ -603,7 +608,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
"The third optional argument (may be null) is an array of base58-encoded private\n"
"keys that, if given, will be the only keys used to sign the transaction.\n"
#ifdef ENABLE_WALLET
- + HelpRequiringPassphrase() + "\n"
+ + HelpRequiringPassphrase(pwallet) + "\n"
#endif
"\nArguments:\n"
@@ -654,7 +659,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
);
#ifdef ENABLE_WALLET
- LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
+ LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : NULL);
#else
LOCK(cs_main);
#endif
@@ -717,8 +722,9 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
}
}
#ifdef ENABLE_WALLET
- else if (pwalletMain)
- EnsureWalletIsUnlocked();
+ else if (pwallet) {
+ EnsureWalletIsUnlocked(pwallet);
+ }
#endif
// Add previous txouts given in the RPC call:
@@ -785,7 +791,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
}
#ifdef ENABLE_WALLET
- const CKeyStore& keystore = ((fGivenKeys || !pwalletMain) ? tempKeystore : *pwalletMain);
+ const CKeyStore& keystore = ((fGivenKeys || !pwallet) ? tempKeystore : *pwallet);
#else
const CKeyStore& keystore = tempKeystore;
#endif
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index 0d29f245ae..f418d71e71 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -178,7 +178,7 @@ vector<unsigned char> ParseHexO(const UniValue& o, string strKey)
* Note: This interface may still be subject to change.
*/
-std::string CRPCTable::help(const std::string& strCommand) const
+std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& helpreq) const
{
string strRet;
string category;
@@ -189,16 +189,19 @@ std::string CRPCTable::help(const std::string& strCommand) const
vCommands.push_back(make_pair(mi->second->category + mi->first, mi->second));
sort(vCommands.begin(), vCommands.end());
+ JSONRPCRequest jreq(helpreq);
+ jreq.fHelp = true;
+ jreq.params = UniValue();
+
BOOST_FOREACH(const PAIRTYPE(string, const CRPCCommand*)& command, vCommands)
{
const CRPCCommand *pcmd = command.second;
string strMethod = pcmd->name;
if ((strCommand != "" || pcmd->category == "hidden") && strMethod != strCommand)
continue;
+ jreq.strMethod = strMethod;
try
{
- JSONRPCRequest jreq;
- jreq.fHelp = true;
rpcfn_type pfn = pcmd->actor;
if (setDone.insert(pfn).second)
(*pfn)(jreq);
@@ -247,7 +250,7 @@ UniValue help(const JSONRPCRequest& jsonRequest)
if (jsonRequest.params.size() > 0)
strCommand = jsonRequest.params[0].get_str();
- return tableRPC.help(strCommand);
+ return tableRPC.help(strCommand, jsonRequest);
}
diff --git a/src/rpc/server.h b/src/rpc/server.h
index 52f82866dc..68d8a6ec96 100644
--- a/src/rpc/server.h
+++ b/src/rpc/server.h
@@ -154,7 +154,7 @@ private:
public:
CRPCTable();
const CRPCCommand* operator[](const std::string& name) const;
- std::string help(const std::string& name) const;
+ std::string help(const std::string& name, const JSONRPCRequest& helpreq) const;
/**
* Execute a method.
@@ -190,16 +190,12 @@ extern uint256 ParseHashO(const UniValue& o, std::string strKey);
extern std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName);
extern std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey);
-extern int64_t nWalletUnlockTime;
extern CAmount AmountFromValue(const UniValue& value);
extern UniValue ValueFromAmount(const CAmount& amount);
extern double GetDifficulty(const CBlockIndex* blockindex = NULL);
-extern std::string HelpRequiringPassphrase();
extern std::string HelpExampleCli(const std::string& methodname, const std::string& args);
extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
-extern void EnsureWalletIsUnlocked();
-
bool StartRPC();
void InterruptRPC();
void StopRPC();
diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp
index 025040c43a..29ae57940f 100644
--- a/src/utilstrencodings.cpp
+++ b/src/utilstrencodings.cpp
@@ -19,7 +19,8 @@ static const string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO
static const string SAFE_CHARS[] =
{
CHARS_ALPHA_NUM + " .,;-_/:?@()", // SAFE_CHARS_DEFAULT
- CHARS_ALPHA_NUM + " .,;-_?@" // SAFE_CHARS_UA_COMMENT
+ CHARS_ALPHA_NUM + " .,;-_?@", // SAFE_CHARS_UA_COMMENT
+ CHARS_ALPHA_NUM + ".-_", // SAFE_CHARS_FILENAME
};
string SanitizeString(const string& str, int rule)
diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h
index cb6f014fc2..e2a1b9bef9 100644
--- a/src/utilstrencodings.h
+++ b/src/utilstrencodings.h
@@ -26,7 +26,8 @@
enum SafeChars
{
SAFE_CHARS_DEFAULT, //!< The full set of allowed chars
- SAFE_CHARS_UA_COMMENT //!< BIP-0014 subset
+ SAFE_CHARS_UA_COMMENT, //!< BIP-0014 subset
+ SAFE_CHARS_FILENAME, //!< Chars allowed in filenames
};
/**
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 20a3cbda1e..182a62cbb1 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -16,6 +16,8 @@
#include "merkleblock.h"
#include "core_io.h"
+#include "rpcwallet.h"
+
#include <fstream>
#include <stdint.h>
@@ -29,9 +31,6 @@
using namespace std;
-void EnsureWalletIsUnlocked();
-bool EnsureWalletIsAvailable(bool avoidException);
-
std::string static EncodeDumpTime(int64_t nTime) {
return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime);
}
@@ -77,9 +76,11 @@ std::string DecodeDumpString(const std::string &str) {
UniValue importprivkey(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
-
+ }
+
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw runtime_error(
"importprivkey \"bitcoinprivkey\" ( \"label\" ) ( rescan )\n"
@@ -101,9 +102,9 @@ UniValue importprivkey(const JSONRPCRequest& request)
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
- EnsureWalletIsUnlocked();
+ EnsureWalletIsUnlocked(pwallet);
string strSecret = request.params[0].get_str();
string strLabel = "";
@@ -130,66 +131,73 @@ UniValue importprivkey(const JSONRPCRequest& request)
assert(key.VerifyPubKey(pubkey));
CKeyID vchAddress = pubkey.GetID();
{
- pwalletMain->MarkDirty();
- pwalletMain->SetAddressBook(vchAddress, strLabel, "receive");
+ pwallet->MarkDirty();
+ pwallet->SetAddressBook(vchAddress, strLabel, "receive");
// Don't throw error in case a key is already there
- if (pwalletMain->HaveKey(vchAddress))
+ if (pwallet->HaveKey(vchAddress)) {
return NullUniValue;
+ }
- pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = 1;
+ pwallet->mapKeyMetadata[vchAddress].nCreateTime = 1;
- if (!pwalletMain->AddKeyPubKey(key, pubkey))
+ if (!pwallet->AddKeyPubKey(key, pubkey)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
+ }
// whenever a key is imported, we need to scan the whole chain
- pwalletMain->UpdateTimeFirstKey(1);
+ pwallet->UpdateTimeFirstKey(1);
if (fRescan) {
- pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
+ pwallet->ScanForWalletTransactions(chainActive.Genesis(), true);
}
}
return NullUniValue;
}
-void ImportAddress(const CBitcoinAddress& address, const string& strLabel);
-void ImportScript(const CScript& script, const string& strLabel, bool isRedeemScript)
+void ImportAddress(CWallet*, const CBitcoinAddress& address, const string& strLabel);
+void ImportScript(CWallet * const pwallet, const CScript& script, const string& strLabel, bool isRedeemScript)
{
- if (!isRedeemScript && ::IsMine(*pwalletMain, script) == ISMINE_SPENDABLE)
+ if (!isRedeemScript && ::IsMine(*pwallet, script) == ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
+ }
- pwalletMain->MarkDirty();
+ pwallet->MarkDirty();
- if (!pwalletMain->HaveWatchOnly(script) && !pwalletMain->AddWatchOnly(script, 0 /* nCreateTime */))
+ if (!pwallet->HaveWatchOnly(script) && !pwallet->AddWatchOnly(script, 0 /* nCreateTime */)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
+ }
if (isRedeemScript) {
- if (!pwalletMain->HaveCScript(script) && !pwalletMain->AddCScript(script))
+ if (!pwallet->HaveCScript(script) && !pwallet->AddCScript(script)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
- ImportAddress(CBitcoinAddress(CScriptID(script)), strLabel);
+ }
+ ImportAddress(pwallet, CBitcoinAddress(CScriptID(script)), strLabel);
} else {
CTxDestination destination;
if (ExtractDestination(script, destination)) {
- pwalletMain->SetAddressBook(destination, strLabel, "receive");
+ pwallet->SetAddressBook(destination, strLabel, "receive");
}
}
}
-void ImportAddress(const CBitcoinAddress& address, const string& strLabel)
+void ImportAddress(CWallet * const pwallet, const CBitcoinAddress& address, const string& strLabel)
{
CScript script = GetScriptForDestination(address.Get());
- ImportScript(script, strLabel, false);
+ ImportScript(pwallet, script, strLabel, false);
// add to address book or update label
if (address.IsValid())
- pwalletMain->SetAddressBook(address.Get(), strLabel, "receive");
+ pwallet->SetAddressBook(address.Get(), strLabel, "receive");
}
UniValue importaddress(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
-
+ }
+
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
throw runtime_error(
"importaddress \"address\" ( \"label\" rescan p2sh )\n"
@@ -230,24 +238,24 @@ UniValue importaddress(const JSONRPCRequest& request)
if (request.params.size() > 3)
fP2SH = request.params[3].get_bool();
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
CBitcoinAddress address(request.params[0].get_str());
if (address.IsValid()) {
if (fP2SH)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead");
- ImportAddress(address, strLabel);
+ ImportAddress(pwallet, address, strLabel);
} else if (IsHex(request.params[0].get_str())) {
std::vector<unsigned char> data(ParseHex(request.params[0].get_str()));
- ImportScript(CScript(data.begin(), data.end()), strLabel, fP2SH);
+ ImportScript(pwallet, CScript(data.begin(), data.end()), strLabel, fP2SH);
} else {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address or script");
}
if (fRescan)
{
- pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
- pwalletMain->ReacceptWalletTransactions();
+ pwallet->ScanForWalletTransactions(chainActive.Genesis(), true);
+ pwallet->ReacceptWalletTransactions();
}
return NullUniValue;
@@ -255,8 +263,10 @@ UniValue importaddress(const JSONRPCRequest& request)
UniValue importprunedfunds(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() != 2)
throw runtime_error(
@@ -271,7 +281,7 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
if (!DecodeHexTx(tx, request.params[0].get_str()))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
uint256 hashTx = tx.GetHash();
- CWalletTx wtx(pwalletMain, MakeTransactionRef(std::move(tx)));
+ CWalletTx wtx(pwallet, MakeTransactionRef(std::move(tx)));
CDataStream ssMB(ParseHexV(request.params[1], "proof"), SER_NETWORK, PROTOCOL_VERSION);
CMerkleBlock merkleBlock;
@@ -302,10 +312,10 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
wtx.nIndex = txnIndex;
wtx.hashBlock = merkleBlock.header.GetHash();
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
- if (pwalletMain->IsMine(wtx)) {
- pwalletMain->AddToWallet(wtx, false);
+ if (pwallet->IsMine(wtx)) {
+ pwallet->AddToWallet(wtx, false);
return NullUniValue;
}
@@ -314,8 +324,10 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
UniValue removeprunedfunds(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() != 1)
throw runtime_error(
@@ -329,7 +341,7 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
+ HelpExampleRpc("removprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
uint256 hash;
hash.SetHex(request.params[0].get_str());
@@ -337,7 +349,7 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
vHash.push_back(hash);
vector<uint256> vHashOut;
- if(pwalletMain->ZapSelectTx(vHash, vHashOut) != DB_LOAD_OK) {
+ if (pwallet->ZapSelectTx(vHash, vHashOut) != DB_LOAD_OK) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Could not properly delete the transaction.");
}
@@ -350,8 +362,10 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
UniValue importpubkey(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
throw runtime_error(
@@ -391,15 +405,15 @@ UniValue importpubkey(const JSONRPCRequest& request)
if (!pubKey.IsFullyValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
- ImportAddress(CBitcoinAddress(pubKey.GetID()), strLabel);
- ImportScript(GetScriptForRawPubKey(pubKey), strLabel, false);
+ ImportAddress(pwallet, CBitcoinAddress(pubKey.GetID()), strLabel);
+ ImportScript(pwallet, GetScriptForRawPubKey(pubKey), strLabel, false);
if (fRescan)
{
- pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
- pwalletMain->ReacceptWalletTransactions();
+ pwallet->ScanForWalletTransactions(chainActive.Genesis(), true);
+ pwallet->ReacceptWalletTransactions();
}
return NullUniValue;
@@ -408,9 +422,11 @@ UniValue importpubkey(const JSONRPCRequest& request)
UniValue importwallet(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
-
+ }
+
if (request.fHelp || request.params.size() != 1)
throw runtime_error(
"importwallet \"filename\"\n"
@@ -429,9 +445,9 @@ UniValue importwallet(const JSONRPCRequest& request)
if (fPruneMode)
throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode");
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
- EnsureWalletIsUnlocked();
+ EnsureWalletIsUnlocked(pwallet);
ifstream file;
file.open(request.params[0].get_str().c_str(), std::ios::in | std::ios::ate);
@@ -445,9 +461,9 @@ UniValue importwallet(const JSONRPCRequest& request)
int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
file.seekg(0, file.beg);
- pwalletMain->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI
+ pwallet->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI
while (file.good()) {
- pwalletMain->ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))));
+ pwallet->ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))));
std::string line;
std::getline(file, line);
if (line.empty() || line[0] == '#')
@@ -464,7 +480,7 @@ UniValue importwallet(const JSONRPCRequest& request)
CPubKey pubkey = key.GetPubKey();
assert(key.VerifyPubKey(pubkey));
CKeyID keyid = pubkey.GetID();
- if (pwalletMain->HaveKey(keyid)) {
+ if (pwallet->HaveKey(keyid)) {
LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString());
continue;
}
@@ -484,27 +500,27 @@ UniValue importwallet(const JSONRPCRequest& request)
}
}
LogPrintf("Importing %s...\n", CBitcoinAddress(keyid).ToString());
- if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
+ if (!pwallet->AddKeyPubKey(key, pubkey)) {
fGood = false;
continue;
}
- pwalletMain->mapKeyMetadata[keyid].nCreateTime = nTime;
+ pwallet->mapKeyMetadata[keyid].nCreateTime = nTime;
if (fLabel)
- pwalletMain->SetAddressBook(keyid, strLabel, "receive");
+ pwallet->SetAddressBook(keyid, strLabel, "receive");
nTimeBegin = std::min(nTimeBegin, nTime);
}
file.close();
- pwalletMain->ShowProgress("", 100); // hide progress dialog in GUI
+ pwallet->ShowProgress("", 100); // hide progress dialog in GUI
CBlockIndex *pindex = chainActive.Tip();
while (pindex && pindex->pprev && pindex->GetBlockTime() > nTimeBegin - 7200)
pindex = pindex->pprev;
- pwalletMain->UpdateTimeFirstKey(nTimeBegin);
+ pwallet->UpdateTimeFirstKey(nTimeBegin);
LogPrintf("Rescanning last %i blocks\n", chainActive.Height() - pindex->nHeight + 1);
- pwalletMain->ScanForWalletTransactions(pindex);
- pwalletMain->MarkDirty();
+ pwallet->ScanForWalletTransactions(pindex);
+ pwallet->MarkDirty();
if (!fGood)
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
@@ -514,9 +530,11 @@ UniValue importwallet(const JSONRPCRequest& request)
UniValue dumpprivkey(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
-
+ }
+
if (request.fHelp || request.params.size() != 1)
throw runtime_error(
"dumpprivkey \"address\"\n"
@@ -532,9 +550,9 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
+ HelpExampleRpc("dumpprivkey", "\"myaddress\"")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
- EnsureWalletIsUnlocked();
+ EnsureWalletIsUnlocked(pwallet);
string strAddress = request.params[0].get_str();
CBitcoinAddress address;
@@ -544,17 +562,20 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
if (!address.GetKeyID(keyID))
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key");
CKey vchSecret;
- if (!pwalletMain->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();
}
UniValue dumpwallet(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
-
+ }
+
if (request.fHelp || request.params.size() != 1)
throw runtime_error(
"dumpwallet \"filename\"\n"
@@ -566,9 +587,9 @@ UniValue dumpwallet(const JSONRPCRequest& request)
+ HelpExampleRpc("dumpwallet", "\"test\"")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
- EnsureWalletIsUnlocked();
+ EnsureWalletIsUnlocked(pwallet);
ofstream file;
file.open(request.params[0].get_str().c_str());
@@ -577,8 +598,8 @@ UniValue dumpwallet(const JSONRPCRequest& request)
std::map<CTxDestination, int64_t> mapKeyBirth;
std::set<CKeyID> setKeyPool;
- pwalletMain->GetKeyBirthTimes(mapKeyBirth);
- pwalletMain->GetAllReserveKeys(setKeyPool);
+ pwallet->GetKeyBirthTimes(mapKeyBirth);
+ pwallet->GetAllReserveKeys(setKeyPool);
// sort time/key pairs
std::vector<std::pair<int64_t, CKeyID> > vKeyBirth;
@@ -598,12 +619,11 @@ UniValue dumpwallet(const JSONRPCRequest& request)
file << "\n";
// add the base58check encoded extended master if the wallet uses HD
- CKeyID masterKeyID = pwalletMain->GetHDChain().masterKeyID;
+ CKeyID masterKeyID = pwallet->GetHDChain().masterKeyID;
if (!masterKeyID.IsNull())
{
CKey key;
- if (pwalletMain->GetKey(masterKeyID, key))
- {
+ if (pwallet->GetKey(masterKeyID, key)) {
CExtKey masterKey;
masterKey.SetMaster(key.begin(), key.size());
@@ -618,20 +638,20 @@ UniValue dumpwallet(const JSONRPCRequest& request)
std::string strTime = EncodeDumpTime(it->first);
std::string strAddr = CBitcoinAddress(keyid).ToString();
CKey key;
- if (pwalletMain->GetKey(keyid, key)) {
+ if (pwallet->GetKey(keyid, key)) {
file << strprintf("%s %s ", CBitcoinSecret(key).ToString(), strTime);
- if (pwalletMain->mapAddressBook.count(keyid)) {
- file << strprintf("label=%s", EncodeDumpString(pwalletMain->mapAddressBook[keyid].name));
+ if (pwallet->mapAddressBook.count(keyid)) {
+ file << strprintf("label=%s", EncodeDumpString(pwallet->mapAddressBook[keyid].name));
} else if (keyid == masterKeyID) {
file << "hdmaster=1";
} else if (setKeyPool.count(keyid)) {
file << "reserve=1";
- } else if (pwalletMain->mapKeyMetadata[keyid].hdKeypath == "m") {
+ } else if (pwallet->mapKeyMetadata[keyid].hdKeypath == "m") {
file << "inactivehdmaster=1";
} else {
file << "change=1";
}
- file << strprintf(" # addr=%s%s\n", strAddr, (pwalletMain->mapKeyMetadata[keyid].hdKeypath.size() > 0 ? " hdkeypath="+pwalletMain->mapKeyMetadata[keyid].hdKeypath : ""));
+ file << strprintf(" # addr=%s%s\n", strAddr, (pwallet->mapKeyMetadata[keyid].hdKeypath.size() > 0 ? " hdkeypath="+pwallet->mapKeyMetadata[keyid].hdKeypath : ""));
}
}
file << "\n";
@@ -641,7 +661,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
}
-UniValue ProcessImport(const UniValue& data, const int64_t timestamp)
+UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp)
{
try {
bool success = false;
@@ -723,32 +743,32 @@ UniValue ProcessImport(const UniValue& data, const int64_t timestamp)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid P2SH address / script");
}
- pwalletMain->MarkDirty();
+ pwallet->MarkDirty();
- if (!pwalletMain->HaveWatchOnly(redeemScript) && !pwalletMain->AddWatchOnly(redeemScript, timestamp)) {
+ if (!pwallet->HaveWatchOnly(redeemScript) && !pwallet->AddWatchOnly(redeemScript, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
- if (!pwalletMain->HaveCScript(redeemScript) && !pwalletMain->AddCScript(redeemScript)) {
+ if (!pwallet->HaveCScript(redeemScript) && !pwallet->AddCScript(redeemScript)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
}
CBitcoinAddress redeemAddress = CBitcoinAddress(CScriptID(redeemScript));
CScript redeemDestination = GetScriptForDestination(redeemAddress.Get());
- if (::IsMine(*pwalletMain, redeemDestination) == ISMINE_SPENDABLE) {
+ if (::IsMine(*pwallet, redeemDestination) == ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
}
- pwalletMain->MarkDirty();
+ pwallet->MarkDirty();
- if (!pwalletMain->HaveWatchOnly(redeemDestination) && !pwalletMain->AddWatchOnly(redeemDestination, timestamp)) {
+ if (!pwallet->HaveWatchOnly(redeemDestination) && !pwallet->AddWatchOnly(redeemDestination, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
// add to address book or update label
if (address.IsValid()) {
- pwalletMain->SetAddressBook(address.Get(), label, "receive");
+ pwallet->SetAddressBook(address.Get(), label, "receive");
}
// Import private keys.
@@ -773,20 +793,20 @@ UniValue ProcessImport(const UniValue& data, const int64_t timestamp)
assert(key.VerifyPubKey(pubkey));
CKeyID vchAddress = pubkey.GetID();
- pwalletMain->MarkDirty();
- pwalletMain->SetAddressBook(vchAddress, label, "receive");
+ pwallet->MarkDirty();
+ pwallet->SetAddressBook(vchAddress, label, "receive");
- if (pwalletMain->HaveKey(vchAddress)) {
+ if (pwallet->HaveKey(vchAddress)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key");
}
- pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = timestamp;
+ pwallet->mapKeyMetadata[vchAddress].nCreateTime = timestamp;
- if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
+ if (!pwallet->AddKeyPubKey(key, pubkey)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
}
- pwalletMain->UpdateTimeFirstKey(timestamp);
+ pwallet->UpdateTimeFirstKey(timestamp);
}
}
@@ -829,31 +849,31 @@ UniValue ProcessImport(const UniValue& data, const int64_t timestamp)
CScript pubKeyScript = GetScriptForDestination(pubKeyAddress.Get());
- if (::IsMine(*pwalletMain, pubKeyScript) == ISMINE_SPENDABLE) {
+ if (::IsMine(*pwallet, pubKeyScript) == ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
}
- pwalletMain->MarkDirty();
+ pwallet->MarkDirty();
- if (!pwalletMain->HaveWatchOnly(pubKeyScript) && !pwalletMain->AddWatchOnly(pubKeyScript, timestamp)) {
+ if (!pwallet->HaveWatchOnly(pubKeyScript) && !pwallet->AddWatchOnly(pubKeyScript, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
// add to address book or update label
if (pubKeyAddress.IsValid()) {
- pwalletMain->SetAddressBook(pubKeyAddress.Get(), label, "receive");
+ pwallet->SetAddressBook(pubKeyAddress.Get(), label, "receive");
}
// TODO Is this necessary?
CScript scriptRawPubKey = GetScriptForRawPubKey(pubKey);
- if (::IsMine(*pwalletMain, scriptRawPubKey) == ISMINE_SPENDABLE) {
+ if (::IsMine(*pwallet, scriptRawPubKey) == ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
}
- pwalletMain->MarkDirty();
+ pwallet->MarkDirty();
- if (!pwalletMain->HaveWatchOnly(scriptRawPubKey) && !pwalletMain->AddWatchOnly(scriptRawPubKey, timestamp)) {
+ if (!pwallet->HaveWatchOnly(scriptRawPubKey) && !pwallet->AddWatchOnly(scriptRawPubKey, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
@@ -901,40 +921,40 @@ UniValue ProcessImport(const UniValue& data, const int64_t timestamp)
}
CKeyID vchAddress = pubKey.GetID();
- pwalletMain->MarkDirty();
- pwalletMain->SetAddressBook(vchAddress, label, "receive");
+ pwallet->MarkDirty();
+ pwallet->SetAddressBook(vchAddress, label, "receive");
- if (pwalletMain->HaveKey(vchAddress)) {
+ if (pwallet->HaveKey(vchAddress)) {
return false;
}
- pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = timestamp;
+ pwallet->mapKeyMetadata[vchAddress].nCreateTime = timestamp;
- if (!pwalletMain->AddKeyPubKey(key, pubKey)) {
+ if (!pwallet->AddKeyPubKey(key, pubKey)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
}
- pwalletMain->UpdateTimeFirstKey(timestamp);
+ pwallet->UpdateTimeFirstKey(timestamp);
success = true;
}
// Import scriptPubKey only.
if (pubKeys.size() == 0 && keys.size() == 0) {
- if (::IsMine(*pwalletMain, script) == ISMINE_SPENDABLE) {
+ if (::IsMine(*pwallet, script) == ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
}
- pwalletMain->MarkDirty();
+ pwallet->MarkDirty();
- if (!pwalletMain->HaveWatchOnly(script) && !pwalletMain->AddWatchOnly(script, timestamp)) {
+ if (!pwallet->HaveWatchOnly(script) && !pwallet->AddWatchOnly(script, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
if (scriptPubKey.getType() == UniValue::VOBJ) {
// add to address book or update label
if (address.IsValid()) {
- pwalletMain->SetAddressBook(address.Get(), label, "receive");
+ pwallet->SetAddressBook(address.Get(), label, "receive");
}
}
@@ -974,6 +994,11 @@ int64_t GetImportTimestamp(const UniValue& data, int64_t now)
UniValue importmulti(const JSONRPCRequest& mainRequest)
{
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(mainRequest);
+ if (!EnsureWalletIsAvailable(pwallet, mainRequest.fHelp)) {
+ return NullUniValue;
+ }
+
// clang-format off
if (mainRequest.fHelp || mainRequest.params.size() < 1 || mainRequest.params.size() > 2)
throw runtime_error(
@@ -1012,9 +1037,6 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
" [{ \"success\": true } , { \"success\": false, \"error\": { \"code\": -1, \"message\": \"Internal Server Error\"} }, ... ]\n");
// clang-format on
- if (!EnsureWalletIsAvailable(mainRequest.fHelp)) {
- return NullUniValue;
- }
RPCTypeCheck(mainRequest.params, boost::assign::list_of(UniValue::VARR)(UniValue::VOBJ));
@@ -1031,8 +1053,8 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
}
}
- LOCK2(cs_main, pwalletMain->cs_wallet);
- EnsureWalletIsUnlocked();
+ LOCK2(cs_main, pwallet->cs_wallet);
+ EnsureWalletIsUnlocked(pwallet);
// Verify all timestamps are present before importing any keys.
const int64_t now = chainActive.Tip() ? chainActive.Tip()->GetMedianTimePast() : 0;
@@ -1054,7 +1076,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
BOOST_FOREACH (const UniValue& data, requests.getValues()) {
const int64_t timestamp = std::max(GetImportTimestamp(data, now), minimumTimestamp);
- const UniValue result = ProcessImport(data, timestamp);
+ const UniValue result = ProcessImport(pwallet, data, timestamp);
response.push_back(result);
if (!fRescan) {
@@ -1076,8 +1098,8 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
CBlockIndex* pindex = nLowestTimestamp > minimumTimestamp ? chainActive.FindEarliestAtLeast(std::max<int64_t>(nLowestTimestamp - 7200, 0)) : chainActive.Genesis();
CBlockIndex* scannedRange = nullptr;
if (pindex) {
- scannedRange = pwalletMain->ScanForWalletTransactions(pindex, true);
- pwalletMain->ReacceptWalletTransactions();
+ scannedRange = pwallet->ScanForWalletTransactions(pindex, true);
+ pwallet->ReacceptWalletTransactions();
}
if (!scannedRange || scannedRange->nHeight > pindex->nHeight) {
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index d785c95ae0..5ef93ac532 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -29,20 +29,21 @@
using namespace std;
-int64_t nWalletUnlockTime;
-static CCriticalSection cs_nWalletUnlockTime;
+CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
+{
+ return pwalletMain;
+}
-std::string HelpRequiringPassphrase()
+std::string HelpRequiringPassphrase(CWallet * const pwallet)
{
- return pwalletMain && pwalletMain->IsCrypted()
+ return pwallet && pwallet->IsCrypted()
? "\nRequires wallet passphrase to be set with walletpassphrase call."
: "";
}
-bool EnsureWalletIsAvailable(bool avoidException)
+bool EnsureWalletIsAvailable(CWallet * const pwallet, bool avoidException)
{
- if (!pwalletMain)
- {
+ if (!pwallet) {
if (!avoidException)
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
else
@@ -51,10 +52,11 @@ bool EnsureWalletIsAvailable(bool avoidException)
return true;
}
-void EnsureWalletIsUnlocked()
+void EnsureWalletIsUnlocked(CWallet * const pwallet)
{
- if (pwalletMain->IsLocked())
+ if (pwallet->IsLocked()) {
throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
+ }
}
void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
@@ -106,8 +108,10 @@ string AccountFromValue(const UniValue& value)
UniValue getnewaddress(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() > 1)
throw runtime_error(
@@ -124,32 +128,34 @@ UniValue getnewaddress(const JSONRPCRequest& request)
+ HelpExampleRpc("getnewaddress", "")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
// Parse the account first so we don't generate a key if there's an error
string strAccount;
if (request.params.size() > 0)
strAccount = AccountFromValue(request.params[0]);
- if (!pwalletMain->IsLocked())
- pwalletMain->TopUpKeyPool();
+ if (!pwallet->IsLocked()) {
+ pwallet->TopUpKeyPool();
+ }
// Generate a new key that is added to wallet
CPubKey newKey;
- if (!pwalletMain->GetKeyFromPool(newKey))
+ if (!pwallet->GetKeyFromPool(newKey)) {
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
+ }
CKeyID keyID = newKey.GetID();
- pwalletMain->SetAddressBook(keyID, strAccount, "receive");
+ pwallet->SetAddressBook(keyID, strAccount, "receive");
return CBitcoinAddress(keyID).ToString();
}
-CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
+CBitcoinAddress GetAccountAddress(CWallet * const pwallet, string strAccount, bool bForceNew=false)
{
CPubKey pubKey;
- if (!pwalletMain->GetAccountPubkey(pubKey, strAccount, bForceNew)) {
+ if (!pwallet->GetAccountPubkey(pubKey, strAccount, bForceNew)) {
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
}
@@ -158,8 +164,10 @@ CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
UniValue getaccountaddress(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() != 1)
throw runtime_error(
@@ -176,22 +184,24 @@ UniValue getaccountaddress(const JSONRPCRequest& request)
+ HelpExampleRpc("getaccountaddress", "\"myaccount\"")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
// Parse the account first so we don't generate a key if there's an error
string strAccount = AccountFromValue(request.params[0]);
UniValue ret(UniValue::VSTR);
- ret = GetAccountAddress(strAccount).ToString();
+ ret = GetAccountAddress(pwallet, strAccount).ToString();
return ret;
}
UniValue getrawchangeaddress(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() > 1)
throw runtime_error(
@@ -205,12 +215,13 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request)
+ HelpExampleRpc("getrawchangeaddress", "")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
- if (!pwalletMain->IsLocked())
- pwalletMain->TopUpKeyPool();
+ if (!pwallet->IsLocked()) {
+ pwallet->TopUpKeyPool();
+ }
- CReserveKey reservekey(pwalletMain);
+ CReserveKey reservekey(pwallet);
CPubKey vchPubKey;
if (!reservekey.GetReservedKey(vchPubKey))
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
@@ -225,8 +236,10 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request)
UniValue setaccount(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw runtime_error(
@@ -240,7 +253,7 @@ UniValue setaccount(const JSONRPCRequest& request)
+ HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"tabby\"")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
CBitcoinAddress address(request.params[0].get_str());
if (!address.IsValid())
@@ -251,16 +264,15 @@ UniValue setaccount(const JSONRPCRequest& request)
strAccount = AccountFromValue(request.params[1]);
// Only add the account if the address is yours.
- if (IsMine(*pwalletMain, address.Get()))
- {
+ if (IsMine(*pwallet, address.Get())) {
// 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))
- GetAccountAddress(strOldAccount, true);
+ if (pwallet->mapAddressBook.count(address.Get())) {
+ string strOldAccount = pwallet->mapAddressBook[address.Get()].name;
+ if (address == GetAccountAddress(pwallet, strOldAccount)) {
+ GetAccountAddress(pwallet, strOldAccount, true);
+ }
}
- pwalletMain->SetAddressBook(address.Get(), strAccount, "receive");
+ pwallet->SetAddressBook(address.Get(), strAccount, "receive");
}
else
throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
@@ -271,8 +283,10 @@ UniValue setaccount(const JSONRPCRequest& request)
UniValue getaccount(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() != 1)
throw runtime_error(
@@ -287,24 +301,27 @@ UniValue getaccount(const JSONRPCRequest& request)
+ HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ 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");
string strAccount;
- map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(address.Get());
- if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty())
+ map<CTxDestination, CAddressBookData>::iterator mi = pwallet->mapAddressBook.find(address.Get());
+ if (mi != pwallet->mapAddressBook.end() && !(*mi).second.name.empty()) {
strAccount = (*mi).second.name;
+ }
return strAccount;
}
UniValue getaddressesbyaccount(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() != 1)
throw runtime_error(
@@ -322,14 +339,13 @@ UniValue getaddressesbyaccount(const JSONRPCRequest& request)
+ HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
string strAccount = AccountFromValue(request.params[0]);
// Find all addresses that have the given account
UniValue ret(UniValue::VARR);
- BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
- {
+ for (const std::pair<CBitcoinAddress, CAddressBookData>& item : pwallet->mapAddressBook) {
const CBitcoinAddress& address = item.first;
const string& strName = item.second.name;
if (strName == strAccount)
@@ -338,9 +354,9 @@ UniValue getaddressesbyaccount(const JSONRPCRequest& request)
return ret;
}
-static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew)
+static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew)
{
- CAmount curBalance = pwalletMain->GetBalance();
+ CAmount curBalance = pwallet->GetBalance();
// Check amount
if (nValue <= 0)
@@ -349,27 +365,28 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr
if (nValue > curBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
- if (pwalletMain->GetBroadcastTransactions() && !g_connman)
+ if (pwallet->GetBroadcastTransactions() && !g_connman) {
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
+ }
// Parse Bitcoin address
CScript scriptPubKey = GetScriptForDestination(address);
// Create and send the transaction
- CReserveKey reservekey(pwalletMain);
+ CReserveKey reservekey(pwallet);
CAmount nFeeRequired;
std::string strError;
vector<CRecipient> vecSend;
int nChangePosRet = -1;
CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
vecSend.push_back(recipient);
- if (!pwalletMain->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError)) {
+ if (!pwallet->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError)) {
if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
throw JSONRPCError(RPC_WALLET_ERROR, strError);
}
CValidationState state;
- if (!pwalletMain->CommitTransaction(wtxNew, reservekey, g_connman.get(), state)) {
+ if (!pwallet->CommitTransaction(wtxNew, reservekey, g_connman.get(), state)) {
strError = strprintf("Error: The transaction was rejected! Reason given: %s", state.GetRejectReason());
throw JSONRPCError(RPC_WALLET_ERROR, strError);
}
@@ -377,14 +394,16 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr
UniValue sendtoaddress(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() < 2 || request.params.size() > 5)
throw runtime_error(
"sendtoaddress \"address\" amount ( \"comment\" \"comment_to\" subtractfeefromamount )\n"
"\nSend an amount to a given address.\n"
- + HelpRequiringPassphrase() +
+ + HelpRequiringPassphrase(pwallet) +
"\nArguments:\n"
"1. \"address\" (string, required) The bitcoin address to send to.\n"
"2. \"amount\" (numeric or string, required) The amount in " + CURRENCY_UNIT + " to send. eg 0.1\n"
@@ -404,7 +423,7 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
+ HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
CBitcoinAddress address(request.params[0].get_str());
if (!address.IsValid())
@@ -426,17 +445,19 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
if (request.params.size() > 4)
fSubtractFeeFromAmount = request.params[4].get_bool();
- EnsureWalletIsUnlocked();
+ EnsureWalletIsUnlocked(pwallet);
- SendMoney(address.Get(), nAmount, fSubtractFeeFromAmount, wtx);
+ SendMoney(pwallet, address.Get(), nAmount, fSubtractFeeFromAmount, wtx);
return wtx.GetHash().GetHex();
}
UniValue listaddressgroupings(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp)
throw runtime_error(
@@ -461,12 +482,11 @@ UniValue listaddressgroupings(const JSONRPCRequest& request)
+ HelpExampleRpc("listaddressgroupings", "")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
UniValue jsonGroupings(UniValue::VARR);
- map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
- BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
- {
+ map<CTxDestination, CAmount> balances = pwallet->GetAddressBalances();
+ for (set<CTxDestination> grouping : pwallet->GetAddressGroupings()) {
UniValue jsonGrouping(UniValue::VARR);
BOOST_FOREACH(CTxDestination address, grouping)
{
@@ -474,8 +494,9 @@ UniValue listaddressgroupings(const JSONRPCRequest& request)
addressInfo.push_back(CBitcoinAddress(address).ToString());
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 (pwallet->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwallet->mapAddressBook.end()) {
+ addressInfo.push_back(pwallet->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name);
+ }
}
jsonGrouping.push_back(addressInfo);
}
@@ -486,14 +507,16 @@ UniValue listaddressgroupings(const JSONRPCRequest& request)
UniValue signmessage(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() != 2)
throw runtime_error(
"signmessage \"address\" \"message\"\n"
"\nSign a message with the private key of an address"
- + HelpRequiringPassphrase() + "\n"
+ + HelpRequiringPassphrase(pwallet) + "\n"
"\nArguments:\n"
"1. \"address\" (string, required) The bitcoin address to use for the private key.\n"
"2. \"message\" (string, required) The message to create a signature of.\n"
@@ -510,9 +533,9 @@ UniValue signmessage(const JSONRPCRequest& request)
+ HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"my message\"")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
- EnsureWalletIsUnlocked();
+ EnsureWalletIsUnlocked(pwallet);
string strAddress = request.params[0].get_str();
string strMessage = request.params[1].get_str();
@@ -526,8 +549,9 @@ UniValue signmessage(const JSONRPCRequest& request)
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
CKey key;
- if (!pwalletMain->GetKey(keyID, key))
+ if (!pwallet->GetKey(keyID, key)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
+ }
CHashWriter ss(SER_GETHASH, 0);
ss << strMessageMagic;
@@ -542,8 +566,10 @@ UniValue signmessage(const JSONRPCRequest& request)
UniValue getreceivedbyaddress(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw runtime_error(
@@ -565,15 +591,16 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request)
+ HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", 6")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
// Bitcoin address
CBitcoinAddress address = CBitcoinAddress(request.params[0].get_str());
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
CScript scriptPubKey = GetScriptForDestination(address.Get());
- if (!IsMine(*pwalletMain, scriptPubKey))
+ if (!IsMine(*pwallet, scriptPubKey)) {
return ValueFromAmount(0);
+ }
// Minimum confirmations
int nMinDepth = 1;
@@ -582,9 +609,8 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request)
// Tally
CAmount nAmount = 0;
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
- {
- const CWalletTx& wtx = (*it).second;
+ for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
+ const CWalletTx& wtx = pairWtx.second;
if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
continue;
@@ -600,8 +626,10 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request)
UniValue getreceivedbyaccount(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw runtime_error(
@@ -623,7 +651,7 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
+ HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
// Minimum confirmations
int nMinDepth = 1;
@@ -632,22 +660,22 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
// Get the set of pub keys assigned to account
string strAccount = AccountFromValue(request.params[0]);
- set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
+ set<CTxDestination> setAddress = pwallet->GetAccountAddresses(strAccount);
// Tally
CAmount nAmount = 0;
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
- {
- const CWalletTx& wtx = (*it).second;
+ for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
+ const CWalletTx& wtx = pairWtx.second;
if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
continue;
BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
{
CTxDestination address;
- if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
+ if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwallet, address) && setAddress.count(address)) {
if (wtx.GetDepthInMainChain() >= nMinDepth)
nAmount += txout.nValue;
+ }
}
}
@@ -657,8 +685,10 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
UniValue getbalance(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() > 3)
throw runtime_error(
@@ -693,10 +723,10 @@ UniValue getbalance(const JSONRPCRequest& request)
+ HelpExampleRpc("getbalance", "\"*\", 6")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
if (request.params.size() == 0)
- return ValueFromAmount(pwalletMain->GetBalance());
+ return ValueFromAmount(pwallet->GetBalance());
int nMinDepth = 1;
if (request.params.size() > 1)
@@ -714,9 +744,8 @@ UniValue getbalance(const JSONRPCRequest& request)
// TxIns spending from the wallet. This also has fewer restrictions on
// which unconfirmed transactions are considered trusted.
CAmount nBalance = 0;
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
- {
- const CWalletTx& wtx = (*it).second;
+ for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
+ const CWalletTx& wtx = pairWtx.second;
if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
continue;
@@ -739,31 +768,35 @@ UniValue getbalance(const JSONRPCRequest& request)
string strAccount = AccountFromValue(request.params[0]);
- CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, filter);
+ CAmount nBalance = pwallet->GetAccountBalance(strAccount, nMinDepth, filter);
return ValueFromAmount(nBalance);
}
UniValue getunconfirmedbalance(const JSONRPCRequest &request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() > 0)
throw runtime_error(
"getunconfirmedbalance\n"
"Returns the server's total unconfirmed balance\n");
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
- return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
+ return ValueFromAmount(pwallet->GetUnconfirmedBalance());
}
UniValue movecmd(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() < 3 || request.params.size() > 5)
throw runtime_error(
@@ -786,7 +819,7 @@ UniValue movecmd(const JSONRPCRequest& request)
+ HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
string strFrom = AccountFromValue(request.params[0]);
string strTo = AccountFromValue(request.params[1]);
@@ -800,8 +833,9 @@ UniValue movecmd(const JSONRPCRequest& request)
if (request.params.size() > 4)
strComment = request.params[4].get_str();
- if (!pwalletMain->AccountMove(strFrom, strTo, nAmount, strComment))
+ if (!pwallet->AccountMove(strFrom, strTo, nAmount, strComment)) {
throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
+ }
return true;
}
@@ -809,14 +843,16 @@ UniValue movecmd(const JSONRPCRequest& request)
UniValue sendfrom(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() < 3 || request.params.size() > 6)
throw runtime_error(
"sendfrom \"fromaccount\" \"toaddress\" amount ( minconf \"comment\" \"comment_to\" )\n"
"\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a bitcoin address."
- + HelpRequiringPassphrase() + "\n"
+ + HelpRequiringPassphrase(pwallet) + "\n"
"\nArguments:\n"
"1. \"fromaccount\" (string, required) The name of the account to send funds from. May be the default account using \"\".\n"
" Specifying an account does not influence coin selection, but it does associate the newly created\n"
@@ -841,7 +877,7 @@ UniValue sendfrom(const JSONRPCRequest& request)
+ HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
string strAccount = AccountFromValue(request.params[0]);
CBitcoinAddress address(request.params[1].get_str());
@@ -861,14 +897,14 @@ UniValue sendfrom(const JSONRPCRequest& request)
if (request.params.size() > 5 && !request.params[5].isNull() && !request.params[5].get_str().empty())
wtx.mapValue["to"] = request.params[5].get_str();
- EnsureWalletIsUnlocked();
+ EnsureWalletIsUnlocked(pwallet);
// Check funds
- CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
+ CAmount nBalance = pwallet->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
if (nAmount > nBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
- SendMoney(address.Get(), nAmount, false, wtx);
+ SendMoney(pwallet, address.Get(), nAmount, false, wtx);
return wtx.GetHash().GetHex();
}
@@ -876,14 +912,16 @@ UniValue sendfrom(const JSONRPCRequest& request)
UniValue sendmany(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() < 2 || request.params.size() > 5)
throw runtime_error(
"sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n"
"\nSend multiple times. Amounts are double-precision floating point numbers."
- + HelpRequiringPassphrase() + "\n"
+ + HelpRequiringPassphrase(pwallet) + "\n"
"\nArguments:\n"
"1. \"fromaccount\" (string, required) DEPRECATED. The account to send the funds from. Should be \"\" for the default account\n"
"2. \"amounts\" (string, required) A json object with addresses and amounts\n"
@@ -915,10 +953,11 @@ UniValue sendmany(const JSONRPCRequest& request)
+ HelpExampleRpc("sendmany", "\"\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
- if (pwalletMain->GetBroadcastTransactions() && !g_connman)
+ if (pwallet->GetBroadcastTransactions() && !g_connman) {
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
+ }
string strAccount = AccountFromValue(request.params[0]);
UniValue sendTo = request.params[1].get_obj();
@@ -967,23 +1006,23 @@ UniValue sendmany(const JSONRPCRequest& request)
vecSend.push_back(recipient);
}
- EnsureWalletIsUnlocked();
+ EnsureWalletIsUnlocked(pwallet);
// Check funds
- CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
+ CAmount nBalance = pwallet->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
if (totalAmount > nBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
// Send
- CReserveKey keyChange(pwalletMain);
+ CReserveKey keyChange(pwallet);
CAmount nFeeRequired = 0;
int nChangePosRet = -1;
string strFailReason;
- bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason);
+ bool fCreated = pwallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason);
if (!fCreated)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
CValidationState state;
- if (!pwalletMain->CommitTransaction(wtx, keyChange, g_connman.get(), state)) {
+ if (!pwallet->CommitTransaction(wtx, keyChange, g_connman.get(), state)) {
strFailReason = strprintf("Transaction commit failed:: %s", state.GetRejectReason());
throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
}
@@ -992,12 +1031,14 @@ UniValue sendmany(const JSONRPCRequest& request)
}
// Defined in rpc/misc.cpp
-extern CScript _createmultisig_redeemScript(const UniValue& params);
+extern CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniValue& params);
UniValue addmultisigaddress(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
{
@@ -1027,38 +1068,41 @@ UniValue addmultisigaddress(const JSONRPCRequest& request)
throw runtime_error(msg);
}
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
string strAccount;
if (request.params.size() > 2)
strAccount = AccountFromValue(request.params[2]);
// Construct using pay-to-script-hash:
- CScript inner = _createmultisig_redeemScript(request.params);
+ CScript inner = _createmultisig_redeemScript(pwallet, request.params);
CScriptID innerID(inner);
- pwalletMain->AddCScript(inner);
+ pwallet->AddCScript(inner);
- pwalletMain->SetAddressBook(innerID, strAccount, "send");
+ pwallet->SetAddressBook(innerID, strAccount, "send");
return CBitcoinAddress(innerID).ToString();
}
class Witnessifier : public boost::static_visitor<bool>
{
public:
+ CWallet * const pwallet;
CScriptID result;
+ Witnessifier(CWallet *_pwallet) : pwallet(_pwallet) {}
+
bool operator()(const CNoDestination &dest) const { return false; }
bool operator()(const CKeyID &keyID) {
CPubKey pubkey;
- if (pwalletMain) {
+ if (pwallet) {
CScript basescript = GetScriptForDestination(keyID);
isminetype typ;
- typ = IsMine(*pwalletMain, basescript, SIGVERSION_WITNESS_V0);
+ typ = IsMine(*pwallet, basescript, SIGVERSION_WITNESS_V0);
if (typ != ISMINE_SPENDABLE && typ != ISMINE_WATCH_SOLVABLE)
return false;
CScript witscript = GetScriptForWitness(basescript);
- pwalletMain->AddCScript(witscript);
+ pwallet->AddCScript(witscript);
result = CScriptID(witscript);
return true;
}
@@ -1067,7 +1111,7 @@ public:
bool operator()(const CScriptID &scriptID) {
CScript subscript;
- if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) {
+ if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
int witnessversion;
std::vector<unsigned char> witprog;
if (subscript.IsWitnessProgram(witnessversion, witprog)) {
@@ -1075,11 +1119,11 @@ public:
return true;
}
isminetype typ;
- typ = IsMine(*pwalletMain, subscript, SIGVERSION_WITNESS_V0);
+ typ = IsMine(*pwallet, subscript, SIGVERSION_WITNESS_V0);
if (typ != ISMINE_SPENDABLE && typ != ISMINE_WATCH_SOLVABLE)
return false;
CScript witscript = GetScriptForWitness(subscript);
- pwalletMain->AddCScript(witscript);
+ pwallet->AddCScript(witscript);
result = CScriptID(witscript);
return true;
}
@@ -1089,8 +1133,10 @@ public:
UniValue addwitnessaddress(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() < 1 || request.params.size() > 1)
{
@@ -1119,14 +1165,14 @@ UniValue addwitnessaddress(const JSONRPCRequest& request)
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
- Witnessifier w;
+ 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");
}
- pwalletMain->SetAddressBook(w.result, "", "receive");
+ pwallet->SetAddressBook(w.result, "", "receive");
return CBitcoinAddress(w.result).ToString();
}
@@ -1145,7 +1191,7 @@ struct tallyitem
}
};
-UniValue ListReceived(const UniValue& params, bool fByAccounts)
+UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByAccounts)
{
// Minimum confirmations
int nMinDepth = 1;
@@ -1164,9 +1210,8 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
// Tally
map<CBitcoinAddress, tallyitem> mapTally;
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
- {
- const CWalletTx& wtx = (*it).second;
+ for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
+ const CWalletTx& wtx = pairWtx.second;
if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
continue;
@@ -1181,7 +1226,7 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
if (!ExtractDestination(txout.scriptPubKey, address))
continue;
- isminefilter mine = IsMine(*pwalletMain, address);
+ isminefilter mine = IsMine(*pwallet, address);
if(!(mine & filter))
continue;
@@ -1197,8 +1242,7 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
// Reply
UniValue ret(UniValue::VARR);
map<string, tallyitem> mapAccountTally;
- BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
- {
+ for (const std::pair<CBitcoinAddress, CAddressBookData>& item : pwallet->mapAddressBook) {
const CBitcoinAddress& address = item.first;
const string& strAccount = item.second.name;
map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
@@ -1267,8 +1311,10 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
UniValue listreceivedbyaddress(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() > 3)
throw runtime_error(
@@ -1302,15 +1348,17 @@ UniValue listreceivedbyaddress(const JSONRPCRequest& request)
+ HelpExampleRpc("listreceivedbyaddress", "6, true, true")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
- return ListReceived(request.params, false);
+ return ListReceived(pwallet, request.params, false);
}
UniValue listreceivedbyaccount(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() > 3)
throw runtime_error(
@@ -1339,9 +1387,9 @@ UniValue listreceivedbyaccount(const JSONRPCRequest& request)
+ HelpExampleRpc("listreceivedbyaccount", "6, true, true")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
- return ListReceived(request.params, true);
+ return ListReceived(pwallet, request.params, true);
}
static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
@@ -1351,7 +1399,7 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
entry.push_back(Pair("address", addr.ToString()));
}
-void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
+void ListTransactions(CWallet * const pwallet, const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
{
CAmount nFee;
string strSentAccount;
@@ -1369,14 +1417,16 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
BOOST_FOREACH(const COutputEntry& s, listSent)
{
UniValue entry(UniValue::VOBJ);
- if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
+ if (involvesWatchonly || (::IsMine(*pwallet, s.destination) & ISMINE_WATCH_ONLY)) {
entry.push_back(Pair("involvesWatchonly", true));
+ }
entry.push_back(Pair("account", strSentAccount));
MaybePushAddress(entry, s.destination);
entry.push_back(Pair("category", "send"));
entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
- if (pwalletMain->mapAddressBook.count(s.destination))
- entry.push_back(Pair("label", pwalletMain->mapAddressBook[s.destination].name));
+ if (pwallet->mapAddressBook.count(s.destination)) {
+ entry.push_back(Pair("label", pwallet->mapAddressBook[s.destination].name));
+ }
entry.push_back(Pair("vout", s.vout));
entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
if (fLong)
@@ -1392,13 +1442,15 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
BOOST_FOREACH(const COutputEntry& r, listReceived)
{
string account;
- if (pwalletMain->mapAddressBook.count(r.destination))
- account = pwalletMain->mapAddressBook[r.destination].name;
+ if (pwallet->mapAddressBook.count(r.destination)) {
+ account = pwallet->mapAddressBook[r.destination].name;
+ }
if (fAllAccounts || (account == strAccount))
{
UniValue entry(UniValue::VOBJ);
- if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
+ if (involvesWatchonly || (::IsMine(*pwallet, r.destination) & ISMINE_WATCH_ONLY)) {
entry.push_back(Pair("involvesWatchonly", true));
+ }
entry.push_back(Pair("account", account));
MaybePushAddress(entry, r.destination);
if (wtx.IsCoinBase())
@@ -1415,8 +1467,9 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
entry.push_back(Pair("category", "receive"));
}
entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
- if (pwalletMain->mapAddressBook.count(r.destination))
+ if (pwallet->mapAddressBook.count(r.destination)) {
entry.push_back(Pair("label", account));
+ }
entry.push_back(Pair("vout", r.vout));
if (fLong)
WalletTxToJSON(wtx, entry);
@@ -1445,8 +1498,10 @@ void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Un
UniValue listtransactions(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() > 4)
throw runtime_error(
@@ -1508,7 +1563,7 @@ UniValue listtransactions(const JSONRPCRequest& request)
+ HelpExampleRpc("listtransactions", "\"*\", 20, 100")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
string strAccount = "*";
if (request.params.size() > 0)
@@ -1531,14 +1586,14 @@ UniValue listtransactions(const JSONRPCRequest& request)
UniValue ret(UniValue::VARR);
- const CWallet::TxItems & txOrdered = pwalletMain->wtxOrdered;
+ const CWallet::TxItems & txOrdered = pwallet->wtxOrdered;
// iterate backwards until we have nCount items to return:
for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
{
CWalletTx *const pwtx = (*it).second.first;
if (pwtx != 0)
- ListTransactions(*pwtx, strAccount, 0, true, ret, filter);
+ ListTransactions(pwallet, *pwtx, strAccount, 0, true, ret, filter);
CAccountingEntry *const pacentry = (*it).second.second;
if (pacentry != 0)
AcentryToJSON(*pacentry, strAccount, ret);
@@ -1573,8 +1628,10 @@ UniValue listtransactions(const JSONRPCRequest& request)
UniValue listaccounts(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() > 2)
throw runtime_error(
@@ -1599,7 +1656,7 @@ UniValue listaccounts(const JSONRPCRequest& request)
+ HelpExampleRpc("listaccounts", "6")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
int nMinDepth = 1;
if (request.params.size() > 0)
@@ -1610,14 +1667,14 @@ UniValue listaccounts(const JSONRPCRequest& request)
includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
map<string, CAmount> mapAccountBalances;
- BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) {
- if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me
+ for (const std::pair<CTxDestination, CAddressBookData>& entry : pwallet->mapAddressBook) {
+ if (IsMine(*pwallet, entry.first) & includeWatchonly) { // This address belongs to me
mapAccountBalances[entry.second.name] = 0;
+ }
}
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
- {
- const CWalletTx& wtx = (*it).second;
+ for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
+ const CWalletTx& wtx = pairWtx.second;
CAmount nFee;
string strSentAccount;
list<COutputEntry> listReceived;
@@ -1632,14 +1689,15 @@ UniValue listaccounts(const JSONRPCRequest& request)
if (nDepth >= nMinDepth)
{
BOOST_FOREACH(const COutputEntry& r, listReceived)
- if (pwalletMain->mapAddressBook.count(r.destination))
- mapAccountBalances[pwalletMain->mapAddressBook[r.destination].name] += r.amount;
+ if (pwallet->mapAddressBook.count(r.destination)) {
+ mapAccountBalances[pwallet->mapAddressBook[r.destination].name] += r.amount;
+ }
else
mapAccountBalances[""] += r.amount;
}
}
- const list<CAccountingEntry> & acentries = pwalletMain->laccentries;
+ const list<CAccountingEntry> & acentries = pwallet->laccentries;
BOOST_FOREACH(const CAccountingEntry& entry, acentries)
mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
@@ -1652,8 +1710,10 @@ UniValue listaccounts(const JSONRPCRequest& request)
UniValue listsinceblock(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp)
throw runtime_error(
@@ -1696,7 +1756,7 @@ UniValue listsinceblock(const JSONRPCRequest& request)
+ HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
const CBlockIndex *pindex = NULL;
int target_confirms = 1;
@@ -1738,12 +1798,11 @@ UniValue listsinceblock(const JSONRPCRequest& request)
UniValue transactions(UniValue::VARR);
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
- {
- CWalletTx tx = (*it).second;
+ for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
+ CWalletTx tx = pairWtx.second;
if (depth == -1 || tx.GetDepthInMainChain() < depth)
- ListTransactions(tx, "*", 0, true, transactions, filter);
+ ListTransactions(pwallet, tx, "*", 0, true, transactions, filter);
}
CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
@@ -1758,8 +1817,10 @@ UniValue listsinceblock(const JSONRPCRequest& request)
UniValue gettransaction(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw runtime_error(
@@ -1806,7 +1867,7 @@ UniValue gettransaction(const JSONRPCRequest& request)
+ HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
uint256 hash;
hash.SetHex(request.params[0].get_str());
@@ -1817,9 +1878,10 @@ UniValue gettransaction(const JSONRPCRequest& request)
filter = filter | ISMINE_WATCH_ONLY;
UniValue entry(UniValue::VOBJ);
- if (!pwalletMain->mapWallet.count(hash))
+ if (!pwallet->mapWallet.count(hash)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
- const CWalletTx& wtx = pwalletMain->mapWallet[hash];
+ }
+ const CWalletTx& wtx = pwallet->mapWallet[hash];
CAmount nCredit = wtx.GetCredit(filter);
CAmount nDebit = wtx.GetDebit(filter);
@@ -1833,7 +1895,7 @@ UniValue gettransaction(const JSONRPCRequest& request)
WalletTxToJSON(wtx, entry);
UniValue details(UniValue::VARR);
- ListTransactions(wtx, "*", 0, false, details, filter);
+ ListTransactions(pwallet, wtx, "*", 0, false, details, filter);
entry.push_back(Pair("details", details));
string strHex = EncodeHexTx(static_cast<CTransaction>(wtx), RPCSerializationFlags());
@@ -1844,8 +1906,10 @@ UniValue gettransaction(const JSONRPCRequest& request)
UniValue abandontransaction(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() != 1)
throw runtime_error(
@@ -1863,15 +1927,17 @@ UniValue abandontransaction(const JSONRPCRequest& request)
+ HelpExampleRpc("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
uint256 hash;
hash.SetHex(request.params[0].get_str());
- if (!pwalletMain->mapWallet.count(hash))
+ if (!pwallet->mapWallet.count(hash)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
- if (!pwalletMain->AbandonTransaction(hash))
+ }
+ if (!pwallet->AbandonTransaction(hash)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not eligible for abandonment");
+ }
return NullUniValue;
}
@@ -1879,8 +1945,10 @@ UniValue abandontransaction(const JSONRPCRequest& request)
UniValue backupwallet(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() != 1)
throw runtime_error(
@@ -1893,11 +1961,12 @@ UniValue backupwallet(const JSONRPCRequest& request)
+ HelpExampleRpc("backupwallet", "\"backup.dat\"")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
string strDest = request.params[0].get_str();
- if (!pwalletMain->BackupWallet(strDest))
+ if (!pwallet->BackupWallet(strDest)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
+ }
return NullUniValue;
}
@@ -1905,14 +1974,16 @@ UniValue backupwallet(const JSONRPCRequest& request)
UniValue keypoolrefill(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() > 1)
throw runtime_error(
"keypoolrefill ( newsize )\n"
"\nFills the keypool."
- + HelpRequiringPassphrase() + "\n"
+ + HelpRequiringPassphrase(pwallet) + "\n"
"\nArguments\n"
"1. newsize (numeric, optional, default=100) The new keypool size\n"
"\nExamples:\n"
@@ -1920,7 +1991,7 @@ UniValue keypoolrefill(const JSONRPCRequest& request)
+ HelpExampleRpc("keypoolrefill", "")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
// 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
unsigned int kpSize = 0;
@@ -1930,11 +2001,12 @@ UniValue keypoolrefill(const JSONRPCRequest& request)
kpSize = (unsigned int)request.params[0].get_int();
}
- EnsureWalletIsUnlocked();
- pwalletMain->TopUpKeyPool(kpSize);
+ EnsureWalletIsUnlocked(pwallet);
+ pwallet->TopUpKeyPool(kpSize);
- if (pwalletMain->GetKeyPoolSize() < kpSize)
+ if (pwallet->GetKeyPoolSize() < kpSize) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
+ }
return NullUniValue;
}
@@ -1942,17 +2014,19 @@ UniValue keypoolrefill(const JSONRPCRequest& request)
static void LockWallet(CWallet* pWallet)
{
- LOCK(cs_nWalletUnlockTime);
- nWalletUnlockTime = 0;
+ LOCK(pWallet->cs_wallet);
+ pWallet->nRelockTime = 0;
pWallet->Lock();
}
UniValue walletpassphrase(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
- if (pwalletMain->IsCrypted() && (request.fHelp || request.params.size() != 2))
+ if (pwallet->IsCrypted() && (request.fHelp || request.params.size() != 2)) {
throw runtime_error(
"walletpassphrase \"passphrase\" timeout\n"
"\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
@@ -1971,13 +2045,15 @@ UniValue walletpassphrase(const JSONRPCRequest& request)
"\nAs json rpc call\n"
+ HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
);
+ }
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
if (request.fHelp)
return true;
- if (!pwalletMain->IsCrypted())
+ if (!pwallet->IsCrypted()) {
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
+ }
// Note that the walletpassphrase is stored in request.params[0] which is not mlock()ed
SecureString strWalletPass;
@@ -1988,20 +2064,20 @@ UniValue walletpassphrase(const JSONRPCRequest& request)
if (strWalletPass.length() > 0)
{
- if (!pwalletMain->Unlock(strWalletPass))
+ if (!pwallet->Unlock(strWalletPass)) {
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
+ }
}
else
throw runtime_error(
"walletpassphrase <passphrase> <timeout>\n"
"Stores the wallet decryption key in memory for <timeout> seconds.");
- pwalletMain->TopUpKeyPool();
+ pwallet->TopUpKeyPool();
int64_t nSleepTime = request.params[1].get_int64();
- LOCK(cs_nWalletUnlockTime);
- nWalletUnlockTime = GetTime() + nSleepTime;
- RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
+ pwallet->nRelockTime = GetTime() + nSleepTime;
+ RPCRunLater(strprintf("lockwallet(%s)", pwallet->strWalletFile), boost::bind(LockWallet, pwallet), nSleepTime);
return NullUniValue;
}
@@ -2009,10 +2085,12 @@ UniValue walletpassphrase(const JSONRPCRequest& request)
UniValue walletpassphrasechange(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
- if (pwalletMain->IsCrypted() && (request.fHelp || request.params.size() != 2))
+ if (pwallet->IsCrypted() && (request.fHelp || request.params.size() != 2)) {
throw runtime_error(
"walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
"\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
@@ -2023,13 +2101,15 @@ UniValue walletpassphrasechange(const JSONRPCRequest& request)
+ HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
+ HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
);
+ }
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
if (request.fHelp)
return true;
- if (!pwalletMain->IsCrypted())
+ if (!pwallet->IsCrypted()) {
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
+ }
// TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
// Alternately, find a way to make request.params[0] mlock()'d to begin with.
@@ -2046,8 +2126,9 @@ UniValue walletpassphrasechange(const JSONRPCRequest& request)
"walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
"Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
- if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
+ if (!pwallet->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass)) {
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
+ }
return NullUniValue;
}
@@ -2055,10 +2136,12 @@ UniValue walletpassphrasechange(const JSONRPCRequest& request)
UniValue walletlock(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
- if (pwalletMain->IsCrypted() && (request.fHelp || request.params.size() != 0))
+ if (pwallet->IsCrypted() && (request.fHelp || request.params.size() != 0)) {
throw runtime_error(
"walletlock\n"
"\nRemoves the wallet encryption key from memory, locking the wallet.\n"
@@ -2074,30 +2157,31 @@ UniValue walletlock(const JSONRPCRequest& request)
"\nAs json rpc call\n"
+ HelpExampleRpc("walletlock", "")
);
+ }
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
if (request.fHelp)
return true;
- if (!pwalletMain->IsCrypted())
+ if (!pwallet->IsCrypted()) {
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
-
- {
- LOCK(cs_nWalletUnlockTime);
- pwalletMain->Lock();
- nWalletUnlockTime = 0;
}
+ pwallet->Lock();
+ pwallet->nRelockTime = 0;
+
return NullUniValue;
}
UniValue encryptwallet(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
- if (!pwalletMain->IsCrypted() && (request.fHelp || request.params.size() != 1))
+ if (!pwallet->IsCrypted() && (request.fHelp || request.params.size() != 1)) {
throw runtime_error(
"encryptwallet \"passphrase\"\n"
"\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
@@ -2120,13 +2204,15 @@ UniValue encryptwallet(const JSONRPCRequest& request)
"\nAs a json rpc call\n"
+ HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
);
+ }
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
if (request.fHelp)
return true;
- if (pwalletMain->IsCrypted())
+ if (pwallet->IsCrypted()) {
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
+ }
// TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
// Alternately, find a way to make request.params[0] mlock()'d to begin with.
@@ -2139,8 +2225,9 @@ UniValue encryptwallet(const JSONRPCRequest& request)
"encryptwallet <passphrase>\n"
"Encrypts the wallet with <passphrase>.");
- if (!pwalletMain->EncryptWallet(strWalletPass))
+ if (!pwallet->EncryptWallet(strWalletPass)) {
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
+ }
// BDB seems to have a bad habit of writing old data into
// slack space in .dat files; that is bad if the old data is
@@ -2151,8 +2238,10 @@ UniValue encryptwallet(const JSONRPCRequest& request)
UniValue lockunspent(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw runtime_error(
@@ -2191,7 +2280,7 @@ UniValue lockunspent(const JSONRPCRequest& request)
+ HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
if (request.params.size() == 1)
RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VBOOL));
@@ -2202,7 +2291,7 @@ UniValue lockunspent(const JSONRPCRequest& request)
if (request.params.size() == 1) {
if (fUnlock)
- pwalletMain->UnlockAllCoins();
+ pwallet->UnlockAllCoins();
return true;
}
@@ -2230,9 +2319,9 @@ UniValue lockunspent(const JSONRPCRequest& request)
COutPoint outpt(uint256S(txid), nOutput);
if (fUnlock)
- pwalletMain->UnlockCoin(outpt);
+ pwallet->UnlockCoin(outpt);
else
- pwalletMain->LockCoin(outpt);
+ pwallet->LockCoin(outpt);
}
return true;
@@ -2240,8 +2329,10 @@ UniValue lockunspent(const JSONRPCRequest& request)
UniValue listlockunspent(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() > 0)
throw runtime_error(
@@ -2269,10 +2360,10 @@ UniValue listlockunspent(const JSONRPCRequest& request)
+ HelpExampleRpc("listlockunspent", "")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
vector<COutPoint> vOutpts;
- pwalletMain->ListLockedCoins(vOutpts);
+ pwallet->ListLockedCoins(vOutpts);
UniValue ret(UniValue::VARR);
@@ -2289,8 +2380,10 @@ UniValue listlockunspent(const JSONRPCRequest& request)
UniValue settxfee(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() < 1 || request.params.size() > 1)
throw runtime_error(
@@ -2305,7 +2398,7 @@ UniValue settxfee(const JSONRPCRequest& request)
+ HelpExampleRpc("settxfee", "0.00001")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
// Amount
CAmount nAmount = AmountFromValue(request.params[0]);
@@ -2316,8 +2409,10 @@ UniValue settxfee(const JSONRPCRequest& request)
UniValue getwalletinfo(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() != 0)
throw runtime_error(
@@ -2341,20 +2436,21 @@ UniValue getwalletinfo(const JSONRPCRequest& request)
+ HelpExampleRpc("getwalletinfo", "")
);
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
UniValue obj(UniValue::VOBJ);
- obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
- obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
- obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwalletMain->GetUnconfirmedBalance())));
- obj.push_back(Pair("immature_balance", ValueFromAmount(pwalletMain->GetImmatureBalance())));
- obj.push_back(Pair("txcount", (int)pwalletMain->mapWallet.size()));
- obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
- obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
- if (pwalletMain->IsCrypted())
- obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
+ obj.push_back(Pair("walletversion", pwallet->GetVersion()));
+ obj.push_back(Pair("balance", ValueFromAmount(pwallet->GetBalance())));
+ obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwallet->GetUnconfirmedBalance())));
+ obj.push_back(Pair("immature_balance", ValueFromAmount(pwallet->GetImmatureBalance())));
+ obj.push_back(Pair("txcount", (int)pwallet->mapWallet.size()));
+ obj.push_back(Pair("keypoololdest", pwallet->GetOldestKeyPoolTime()));
+ obj.push_back(Pair("keypoolsize", (int)pwallet->GetKeyPoolSize()));
+ if (pwallet->IsCrypted()) {
+ obj.push_back(Pair("unlocked_until", pwallet->nRelockTime));
+ }
obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
- CKeyID masterKeyID = pwalletMain->GetHDChain().masterKeyID;
+ CKeyID masterKeyID = pwallet->GetHDChain().masterKeyID;
if (!masterKeyID.IsNull())
obj.push_back(Pair("hdmasterkeyid", masterKeyID.GetHex()));
return obj;
@@ -2362,8 +2458,10 @@ UniValue getwalletinfo(const JSONRPCRequest& request)
UniValue resendwallettransactions(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() != 0)
throw runtime_error(
@@ -2377,9 +2475,9 @@ UniValue resendwallettransactions(const JSONRPCRequest& request)
if (!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
- LOCK2(cs_main, pwalletMain->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
- std::vector<uint256> txids = pwalletMain->ResendWalletTransactionsBefore(GetTime(), g_connman.get());
+ std::vector<uint256> txids = pwallet->ResendWalletTransactionsBefore(GetTime(), g_connman.get());
UniValue result(UniValue::VARR);
BOOST_FOREACH(const uint256& txid, txids)
{
@@ -2390,8 +2488,10 @@ UniValue resendwallettransactions(const JSONRPCRequest& request)
UniValue listunspent(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() > 4)
throw runtime_error(
@@ -2469,9 +2569,9 @@ UniValue listunspent(const JSONRPCRequest& request)
UniValue results(UniValue::VARR);
vector<COutput> vecOutputs;
- assert(pwalletMain != NULL);
- LOCK2(cs_main, pwalletMain->cs_wallet);
- pwalletMain->AvailableCoins(vecOutputs, !include_unsafe, NULL, true);
+ assert(pwallet != NULL);
+ LOCK2(cs_main, pwallet->cs_wallet);
+ pwallet->AvailableCoins(vecOutputs, !include_unsafe, NULL, true);
BOOST_FOREACH(const COutput& out, vecOutputs) {
if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
continue;
@@ -2490,14 +2590,16 @@ UniValue listunspent(const JSONRPCRequest& request)
if (fValidAddress) {
entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
- if (pwalletMain->mapAddressBook.count(address))
- entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
+ if (pwallet->mapAddressBook.count(address)) {
+ entry.push_back(Pair("account", pwallet->mapAddressBook[address].name));
+ }
if (scriptPubKey.IsPayToScriptHash()) {
const CScriptID& hash = boost::get<CScriptID>(address);
CScript redeemScript;
- if (pwalletMain->GetCScript(hash, redeemScript))
+ if (pwallet->GetCScript(hash, redeemScript)) {
entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
+ }
}
}
@@ -2514,8 +2616,10 @@ UniValue listunspent(const JSONRPCRequest& request)
UniValue fundrawtransaction(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp))
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
+ }
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw runtime_error(
@@ -2656,8 +2760,9 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
CAmount nFeeOut;
string strFailReason;
- if(!pwalletMain->FundTransaction(tx, nFeeOut, overrideEstimatedFeerate, feeRate, changePosition, strFailReason, includeWatching, lockUnspents, setSubtractFeeFromOutputs, reserveChangeKey, changeAddress))
+ if (!pwallet->FundTransaction(tx, nFeeOut, overrideEstimatedFeerate, feeRate, changePosition, strFailReason, includeWatching, lockUnspents, setSubtractFeeFromOutputs, reserveChangeKey, changeAddress)) {
throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
+ }
UniValue result(UniValue::VOBJ);
result.push_back(Pair("hex", EncodeHexTx(tx)));
@@ -2674,7 +2779,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
// calculation, but we should be able to refactor after priority is removed).
// NOTE: this requires that all inputs must be in mapWallet (eg the tx should
// be IsAllFromMe).
-int64_t CalculateMaximumSignedTxSize(const CTransaction &tx)
+int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, CWallet &wallet)
{
CMutableTransaction txNew(tx);
std::vector<pair<CWalletTx *, unsigned int>> vCoins;
@@ -2682,11 +2787,11 @@ int64_t CalculateMaximumSignedTxSize(const CTransaction &tx)
// IsAllFromMe(ISMINE_SPENDABLE), so every input should already be in our
// wallet, with a valid index into the vout array.
for (auto& input : tx.vin) {
- const auto mi = pwalletMain->mapWallet.find(input.prevout.hash);
- assert(mi != pwalletMain->mapWallet.end() && input.prevout.n < mi->second.tx->vout.size());
+ const auto mi = wallet.mapWallet.find(input.prevout.hash);
+ assert(mi != wallet.mapWallet.end() && input.prevout.n < mi->second.tx->vout.size());
vCoins.emplace_back(make_pair(&(mi->second), input.prevout.n));
}
- if (!pwalletMain->DummySignTx(txNew, vCoins)) {
+ if (!wallet.DummySignTx(txNew, vCoins)) {
// This should never happen, because IsAllFromMe(ISMINE_SPENDABLE)
// implies that we can sign for every input.
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction contains inputs that cannot be signed");
@@ -2696,9 +2801,10 @@ int64_t CalculateMaximumSignedTxSize(const CTransaction &tx)
UniValue bumpfee(const JSONRPCRequest& request)
{
- if (!EnsureWalletIsAvailable(request.fHelp)) {
+ CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;
- }
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
throw runtime_error(
@@ -2748,14 +2854,14 @@ UniValue bumpfee(const JSONRPCRequest& request)
hash.SetHex(request.params[0].get_str());
// retrieve the original tx from the wallet
- LOCK2(cs_main, pwalletMain->cs_wallet);
- EnsureWalletIsUnlocked();
- if (!pwalletMain->mapWallet.count(hash)) {
+ LOCK2(cs_main, pwallet->cs_wallet);
+ EnsureWalletIsUnlocked(pwallet);
+ if (!pwallet->mapWallet.count(hash)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
}
- CWalletTx& wtx = pwalletMain->mapWallet[hash];
+ CWalletTx& wtx = pwallet->mapWallet[hash];
- if (pwalletMain->HasWalletSpend(hash)) {
+ if (pwallet->HasWalletSpend(hash)) {
throw JSONRPCError(RPC_MISC_ERROR, "Transaction has descendants in the wallet");
}
@@ -2781,7 +2887,7 @@ UniValue bumpfee(const JSONRPCRequest& request)
// check that original tx consists entirely of our inputs
// if not, we can't bump the fee, because the wallet has no way of knowing the value of the other inputs (thus the fee)
- if (!pwalletMain->IsAllFromMe(wtx, ISMINE_SPENDABLE)) {
+ if (!pwallet->IsAllFromMe(wtx, ISMINE_SPENDABLE)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction contains inputs that don't belong to this wallet");
}
@@ -2789,7 +2895,7 @@ UniValue bumpfee(const JSONRPCRequest& request)
// if there was no change output or multiple change outputs, fail
int nOutput = -1;
for (size_t i = 0; i < wtx.tx->vout.size(); ++i) {
- if (pwalletMain->IsChange(wtx.tx->vout[i])) {
+ if (pwallet->IsChange(wtx.tx->vout[i])) {
if (nOutput != -1) {
throw JSONRPCError(RPC_MISC_ERROR, "Transaction has multiple change outputs");
}
@@ -2802,7 +2908,7 @@ UniValue bumpfee(const JSONRPCRequest& request)
// Calculate the expected size of the new transaction.
int64_t txSize = GetVirtualTransactionSize(*(wtx.tx));
- const int64_t maxNewTxSize = CalculateMaximumSignedTxSize(*wtx.tx);
+ const int64_t maxNewTxSize = CalculateMaximumSignedTxSize(*wtx.tx, *pwallet);
// optional parameters
bool specifiedConfirmTarget = false;
@@ -2932,12 +3038,12 @@ UniValue bumpfee(const JSONRPCRequest& request)
CTransaction txNewConst(tx);
int nIn = 0;
for (auto& input : tx.vin) {
- std::map<uint256, CWalletTx>::const_iterator mi = pwalletMain->mapWallet.find(input.prevout.hash);
- assert(mi != pwalletMain->mapWallet.end() && input.prevout.n < mi->second.tx->vout.size());
+ std::map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(input.prevout.hash);
+ assert(mi != pwallet->mapWallet.end() && input.prevout.n < mi->second.tx->vout.size());
const CScript& scriptPubKey = mi->second.tx->vout[input.prevout.n].scriptPubKey;
const CAmount& amount = mi->second.tx->vout[input.prevout.n].nValue;
SignatureData sigdata;
- if (!ProduceSignature(TransactionSignatureCreator(pwalletMain, &txNewConst, nIn, amount, SIGHASH_ALL), scriptPubKey, sigdata)) {
+ if (!ProduceSignature(TransactionSignatureCreator(pwallet, &txNewConst, nIn, amount, SIGHASH_ALL), scriptPubKey, sigdata)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Can't sign transaction.");
}
UpdateTransaction(tx, nIn, sigdata);
@@ -2945,8 +3051,8 @@ UniValue bumpfee(const JSONRPCRequest& request)
}
// commit/broadcast the tx
- CReserveKey reservekey(pwalletMain);
- CWalletTx wtxBumped(pwalletMain, MakeTransactionRef(std::move(tx)));
+ CReserveKey reservekey(pwallet);
+ CWalletTx wtxBumped(pwallet, MakeTransactionRef(std::move(tx)));
wtxBumped.mapValue = wtx.mapValue;
wtxBumped.mapValue["replaces_txid"] = hash.ToString();
wtxBumped.vOrderForm = wtx.vOrderForm;
@@ -2954,7 +3060,7 @@ UniValue bumpfee(const JSONRPCRequest& request)
wtxBumped.fTimeReceivedIsTxTime = true;
wtxBumped.fFromMe = true;
CValidationState state;
- if (!pwalletMain->CommitTransaction(wtxBumped, reservekey, g_connman.get(), state)) {
+ if (!pwallet->CommitTransaction(wtxBumped, reservekey, g_connman.get(), state)) {
// NOTE: CommitTransaction never returns false, so this should never happen.
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Error: The transaction was rejected! Reason given: %s", state.GetRejectReason()));
}
@@ -2967,7 +3073,7 @@ UniValue bumpfee(const JSONRPCRequest& request)
}
// mark the original tx as bumped
- if (!pwalletMain->MarkReplaced(wtx.GetHash(), wtxBumped.GetHash())) {
+ if (!pwallet->MarkReplaced(wtx.GetHash(), wtxBumped.GetHash())) {
// TODO: see if JSON-RPC has a standard way of returning a response
// along with an exception. It would be good to return information about
// wtxBumped to the caller even if marking the original transaction
diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h
index 3a68ccf1b2..bd5dad18ca 100644
--- a/src/wallet/rpcwallet.h
+++ b/src/wallet/rpcwallet.h
@@ -6,7 +6,20 @@
#define BITCOIN_WALLET_RPCWALLET_H
class CRPCTable;
+class JSONRPCRequest;
void RegisterWalletRPCCommands(CRPCTable &t);
+/**
+ * Figures out what wallet, if any, to use for a JSONRPCRequest.
+ *
+ * @param[in] request JSONRPCRequest that wishes to access a wallet
+ * @return NULL if no wallet should be used, or a pointer to the CWallet
+ */
+CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest&);
+
+std::string HelpRequiringPassphrase(CWallet *);
+void EnsureWalletIsUnlocked(CWallet *);
+bool EnsureWalletIsAvailable(CWallet *, bool avoidException);
+
#endif //BITCOIN_WALLET_RPCWALLET_H
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 4231e02c4a..70fc54350d 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -3770,6 +3770,12 @@ bool CWallet::InitLoadWallet()
std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
+ if (walletFile.find_first_of("/\\") != std::string::npos) {
+ return InitError(_("-wallet parameter must only specify a filename (not a path)"));
+ } else if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) {
+ return InitError(_("Invalid characters in -wallet filename"));
+ }
+
CWallet * const pwallet = CreateWalletFromFile(walletFile);
if (!pwallet) {
return false;
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 98e4fb87b9..176063c27f 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -768,6 +768,9 @@ public:
//! Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
bool LoadWatchOnly(const CScript &dest);
+ //! Holds a timestamp at which point the wallet is scheduled (externally) to be relocked. Caller must arrange for actual relocking to occur via Lock().
+ int64_t nRelockTime;
+
bool Unlock(const SecureString& strWalletPassphrase);
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
bool EncryptWallet(const SecureString& strWalletPassphrase);