Browse Source

Merge #8775: RPC refactoring: Access wallet using new GetWalletForJSONRPCRequest

d678771 Wallet: Sanitise -wallet parameter (Luke Dashjr)
9756be3 Wallet/RPC: Use filename rather than CWallet pointer, for lockwallet RPCRunLater job name (Luke Dashjr)
86be48a More tightly couple EnsureWalletIsAvailable with GetWalletForJSONRPCRequest where appropriate (Luke Dashjr)
a435632 Move wallet RPC declarations to rpcwallet.h (Luke Dashjr)
ad15734 RPC: Pass on JSONRPCRequest metadata (URI/user/etc) for "help" method (Luke Dashjr)
bf8a04a Reformat touched lines with C++11 (Luke Dashjr)
2e518e3 Move nWalletUnlockTime to CWallet::nRelockTime, and name timed task unique per CWallet (Luke Dashjr)
d77ad6d RPC: Do all wallet access through new GetWalletForJSONRPCRequest (Luke Dashjr)
eca550f RPC/Wallet: Pass CWallet as pointer to helper functions (Luke Dashjr)

Tree-SHA512: bfd592da841693390e16f83b451503eb5cedb71208089aa32b3fc45e973555584a3ed7696dd239f6409324464d565dacf0f3d0e36e8e13ae6a7843848465f960
0.15
Wladimir J. van der Laan 8 years ago
parent
commit
eb281842b7
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 66
      src/rpc/misc.cpp
  2. 16
      src/rpc/rawtransaction.cpp
  3. 11
      src/rpc/server.cpp
  4. 6
      src/rpc/server.h
  5. 3
      src/utilstrencodings.cpp
  6. 3
      src/utilstrencodings.h
  7. 258
      src/wallet/rpcdump.cpp
  8. 638
      src/wallet/rpcwallet.cpp
  9. 13
      src/wallet/rpcwallet.h
  10. 6
      src/wallet/wallet.cpp
  11. 3
      src/wallet/wallet.h

66
src/rpc/misc.cpp

@ -14,6 +14,7 @@ @@ -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) @@ -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) @@ -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) @@ -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) @@ -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: @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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);

16
src/rpc/rawtransaction.cpp

@ -24,6 +24,7 @@ @@ -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:: @@ -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) @@ -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) @@ -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) @@ -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) @@ -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

11
src/rpc/server.cpp

@ -178,7 +178,7 @@ vector<unsigned char> ParseHexO(const UniValue& o, string strKey) @@ -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 @@ -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) @@ -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);
}

6
src/rpc/server.h

@ -154,7 +154,7 @@ private: @@ -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); @@ -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();

3
src/utilstrencodings.cpp

@ -19,7 +19,8 @@ static const string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO @@ -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)

3
src/utilstrencodings.h

@ -26,7 +26,8 @@ @@ -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
};
/**

258
src/wallet/rpcdump.cpp

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
#include "merkleblock.h"
#include "core_io.h"
#include "rpcwallet.h"
#include <fstream>
#include <stdint.h>
@ -29,9 +31,6 @@ @@ -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) { @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) {

638
src/wallet/rpcwallet.cpp

File diff suppressed because it is too large Load Diff

13
src/wallet/rpcwallet.h

@ -6,7 +6,20 @@ @@ -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

6
src/wallet/wallet.cpp

@ -3770,6 +3770,12 @@ bool CWallet::InitLoadWallet() @@ -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;

3
src/wallet/wallet.h

@ -768,6 +768,9 @@ public: @@ -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);

Loading…
Cancel
Save