From d77ad6d41666b4c41abe1ba3b63300df1903643e Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 25 Oct 2016 07:45:57 +0000 Subject: [PATCH] RPC: Do all wallet access through new GetWalletForJSONRPCRequest --- src/rpc/misc.cpp | 42 ++-- src/rpc/rawtransaction.cpp | 14 +- src/rpc/server.h | 1 + src/wallet/rpcdump.cpp | 148 +++++++----- src/wallet/rpcwallet.cpp | 480 ++++++++++++++++++++++--------------- 5 files changed, 400 insertions(+), 285 deletions(-) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index f8e9acb08..c9bbce856 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -70,7 +70,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 +84,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,11 +97,11 @@ 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 (pwalletMain && pwalletMain->IsCrypted()) + if (pwallet && pwallet->IsCrypted()) obj.push_back(Pair("unlocked_until", nWalletUnlockTime)); obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK()))); #endif @@ -181,7 +183,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 @@ -201,16 +205,16 @@ 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(pwalletMain), 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)); @@ -294,6 +298,12 @@ CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniValue& pa 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" @@ -324,7 +334,7 @@ UniValue createmultisig(const JSONRPCRequest& request) } // Construct using pay-to-script-hash: - CScript inner = _createmultisig_redeemScript(pwalletMain, 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 faafe9829..5c75fecac 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -594,6 +594,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 +607,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(pwalletMain) + "\n" + + HelpRequiringPassphrase(pwallet) + "\n" #endif "\nArguments:\n" @@ -654,7 +658,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 +721,8 @@ UniValue signrawtransaction(const JSONRPCRequest& request) } } #ifdef ENABLE_WALLET - else if (pwalletMain) - EnsureWalletIsUnlocked(pwalletMain); + else if (pwallet) + EnsureWalletIsUnlocked(pwallet); #endif // Add previous txouts given in the RPC call: @@ -785,7 +789,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.h b/src/rpc/server.h index b32eaaa13..b8f0373ac 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -202,6 +202,7 @@ class CWallet; #ifdef ENABLE_WALLET // New code should accessing the wallet should be under the ../wallet/ directory +CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest&); std::string HelpRequiringPassphrase(CWallet *); void EnsureWalletIsUnlocked(CWallet *); bool EnsureWalletIsAvailable(CWallet *, bool avoidException); diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 9f71d74e3..f0df76c92 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -74,7 +74,9 @@ std::string DecodeDumpString(const std::string &str) { UniValue importprivkey(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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) @@ -98,9 +100,9 @@ UniValue importprivkey(const JSONRPCRequest& request) ); - LOCK2(cs_main, pwalletMain->cs_wallet); + LOCK2(cs_main, pwallet->cs_wallet); - EnsureWalletIsUnlocked(pwalletMain); + EnsureWalletIsUnlocked(pwallet); string strSecret = request.params[0].get_str(); string strLabel = ""; @@ -127,23 +129,23 @@ 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); } } @@ -184,7 +186,9 @@ void ImportAddress(CWallet * const pwallet, const CBitcoinAddress& address, cons UniValue importaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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) @@ -227,24 +231,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(pwalletMain, address, strLabel); + ImportAddress(pwallet, address, strLabel); } else if (IsHex(request.params[0].get_str())) { std::vector data(ParseHex(request.params[0].get_str())); - ImportScript(pwalletMain, 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; @@ -252,7 +256,9 @@ UniValue importaddress(const JSONRPCRequest& request) UniValue importprunedfunds(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() != 2) @@ -268,7 +274,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; @@ -299,10 +305,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; } @@ -311,7 +317,9 @@ UniValue importprunedfunds(const JSONRPCRequest& request) UniValue removeprunedfunds(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() != 1) @@ -326,7 +334,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()); @@ -334,7 +342,7 @@ UniValue removeprunedfunds(const JSONRPCRequest& request) vHash.push_back(hash); vector 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."); } @@ -347,7 +355,9 @@ UniValue removeprunedfunds(const JSONRPCRequest& request) UniValue importpubkey(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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) @@ -388,15 +398,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(pwalletMain, CBitcoinAddress(pubKey.GetID()), strLabel); - ImportScript(pwalletMain, 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; @@ -405,7 +415,9 @@ UniValue importpubkey(const JSONRPCRequest& request) UniValue importwallet(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() != 1) @@ -426,9 +438,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(pwalletMain); + EnsureWalletIsUnlocked(pwallet); ifstream file; file.open(request.params[0].get_str().c_str(), std::ios::in | std::ios::ate); @@ -442,9 +454,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] == '#') @@ -461,7 +473,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; } @@ -481,27 +493,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"); @@ -511,7 +523,9 @@ UniValue importwallet(const JSONRPCRequest& request) UniValue dumpprivkey(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() != 1) @@ -529,9 +543,9 @@ UniValue dumpprivkey(const JSONRPCRequest& request) + HelpExampleRpc("dumpprivkey", "\"myaddress\"") ); - LOCK2(cs_main, pwalletMain->cs_wallet); + LOCK2(cs_main, pwallet->cs_wallet); - EnsureWalletIsUnlocked(pwalletMain); + EnsureWalletIsUnlocked(pwallet); string strAddress = request.params[0].get_str(); CBitcoinAddress address; @@ -541,7 +555,7 @@ 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(); } @@ -549,7 +563,9 @@ UniValue dumpprivkey(const JSONRPCRequest& request) UniValue dumpwallet(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() != 1) @@ -563,9 +579,9 @@ UniValue dumpwallet(const JSONRPCRequest& request) + HelpExampleRpc("dumpwallet", "\"test\"") ); - LOCK2(cs_main, pwalletMain->cs_wallet); + LOCK2(cs_main, pwallet->cs_wallet); - EnsureWalletIsUnlocked(pwalletMain); + EnsureWalletIsUnlocked(pwallet); ofstream file; file.open(request.params[0].get_str().c_str()); @@ -574,8 +590,8 @@ UniValue dumpwallet(const JSONRPCRequest& request) std::map mapKeyBirth; std::set setKeyPool; - pwalletMain->GetKeyBirthTimes(mapKeyBirth); - pwalletMain->GetAllReserveKeys(setKeyPool); + pwallet->GetKeyBirthTimes(mapKeyBirth); + pwallet->GetAllReserveKeys(setKeyPool); // sort time/key pairs std::vector > vKeyBirth; @@ -595,11 +611,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()); @@ -615,20 +631,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"; @@ -971,6 +987,8 @@ int64_t GetImportTimestamp(const UniValue& data, int64_t now) UniValue importmulti(const JSONRPCRequest& mainRequest) { + CWallet * const pwallet = GetWalletForJSONRPCRequest(mainRequest); + // clang-format off if (mainRequest.fHelp || mainRequest.params.size() < 1 || mainRequest.params.size() > 2) throw runtime_error( @@ -1009,7 +1027,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) " [{ \"success\": true } , { \"success\": false, \"error\": { \"code\": -1, \"message\": \"Internal Server Error\"} }, ... ]\n"); // clang-format on - if (!EnsureWalletIsAvailable(pwalletMain, mainRequest.fHelp)) { + if (!EnsureWalletIsAvailable(pwallet, mainRequest.fHelp)) { return NullUniValue; } @@ -1028,8 +1046,8 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) } } - LOCK2(cs_main, pwalletMain->cs_wallet); - EnsureWalletIsUnlocked(pwalletMain); + 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; @@ -1051,7 +1069,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(pwalletMain, data, timestamp); + const UniValue result = ProcessImport(pwallet, data, timestamp); response.push_back(result); if (!fRescan) { @@ -1073,8 +1091,8 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) CBlockIndex* pindex = nLowestTimestamp > minimumTimestamp ? chainActive.FindEarliestAtLeast(std::max(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 179d42fca..478d92cda 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -32,6 +32,11 @@ using namespace std; int64_t nWalletUnlockTime; static CCriticalSection cs_nWalletUnlockTime; +CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request) +{ + return pwalletMain; +} + std::string HelpRequiringPassphrase(CWallet * const pwallet) { return pwallet && pwallet->IsCrypted() @@ -106,7 +111,9 @@ string AccountFromValue(const UniValue& value) UniValue getnewaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() > 1) @@ -124,23 +131,23 @@ 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(); } @@ -158,7 +165,9 @@ CBitcoinAddress GetAccountAddress(CWallet * const pwallet, string strAccount, bo UniValue getaccountaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() != 1) @@ -176,21 +185,23 @@ 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(pwalletMain, strAccount).ToString(); + ret = GetAccountAddress(pwallet, strAccount).ToString(); return ret; } UniValue getrawchangeaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() > 1) @@ -205,12 +216,12 @@ 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,7 +236,9 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request) UniValue setaccount(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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) @@ -240,7 +253,7 @@ UniValue setaccount(const JSONRPCRequest& request) + HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"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,16 @@ 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())) + if (pwallet->mapAddressBook.count(address.Get())) { - string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name; - if (address == GetAccountAddress(pwalletMain, strOldAccount)) - GetAccountAddress(pwalletMain, strOldAccount, true); + 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,7 +284,9 @@ UniValue setaccount(const JSONRPCRequest& request) UniValue getaccount(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() != 1) @@ -287,15 +302,15 @@ UniValue getaccount(const JSONRPCRequest& request) + HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"") ); - 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::iterator mi = pwalletMain->mapAddressBook.find(address.Get()); - if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty()) + map::iterator mi = pwallet->mapAddressBook.find(address.Get()); + if (mi != pwallet->mapAddressBook.end() && !(*mi).second.name.empty()) strAccount = (*mi).second.name; return strAccount; } @@ -303,7 +318,9 @@ UniValue getaccount(const JSONRPCRequest& request) UniValue getaddressesbyaccount(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() != 1) @@ -322,13 +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) + BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwallet->mapAddressBook) { const CBitcoinAddress& address = item.first; const string& strName = item.second.name; @@ -377,14 +394,16 @@ static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CA UniValue sendtoaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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(pwalletMain) + + + 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,16 +445,18 @@ UniValue sendtoaddress(const JSONRPCRequest& request) if (request.params.size() > 4) fSubtractFeeFromAmount = request.params[4].get_bool(); - EnsureWalletIsUnlocked(pwalletMain); + EnsureWalletIsUnlocked(pwallet); - SendMoney(pwalletMain, address.Get(), nAmount, fSubtractFeeFromAmount, wtx); + SendMoney(pwallet, address.Get(), nAmount, fSubtractFeeFromAmount, wtx); return wtx.GetHash().GetHex(); } UniValue listaddressgroupings(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp) @@ -461,11 +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 balances = pwalletMain->GetAddressBalances(); - BOOST_FOREACH(set grouping, pwalletMain->GetAddressGroupings()) + map balances = pwallet->GetAddressBalances(); + BOOST_FOREACH(set grouping, pwallet->GetAddressGroupings()) { UniValue jsonGrouping(UniValue::VARR); BOOST_FOREACH(CTxDestination address, grouping) @@ -474,8 +495,8 @@ 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(pwalletMain, 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(pwalletMain) + "\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", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"my message\"") ); - LOCK2(cs_main, pwalletMain->cs_wallet); + LOCK2(cs_main, pwallet->cs_wallet); - EnsureWalletIsUnlocked(pwalletMain); + EnsureWalletIsUnlocked(pwallet); string strAddress = request.params[0].get_str(); string strMessage = request.params[1].get_str(); @@ -526,7 +549,7 @@ 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); @@ -542,7 +565,9 @@ UniValue signmessage(const JSONRPCRequest& request) UniValue getreceivedbyaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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) @@ -565,14 +590,14 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request) + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", 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 @@ -582,7 +607,7 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request) // Tally CAmount nAmount = 0; - for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + for (map::iterator it = pwallet->mapWallet.begin(); it != pwallet->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx)) @@ -600,7 +625,9 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request) UniValue getreceivedbyaccount(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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) @@ -623,7 +650,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,11 +659,11 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request) // Get the set of pub keys assigned to account string strAccount = AccountFromValue(request.params[0]); - set setAddress = pwalletMain->GetAccountAddresses(strAccount); + set setAddress = pwallet->GetAccountAddresses(strAccount); // Tally CAmount nAmount = 0; - for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + for (map::iterator it = pwallet->mapWallet.begin(); it != pwallet->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx)) @@ -645,7 +672,7 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request) 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,7 +684,9 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request) UniValue getbalance(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() > 3) @@ -693,10 +722,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,7 +743,7 @@ 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::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + for (map::iterator it = pwallet->mapWallet.begin(); it != pwallet->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0) @@ -739,14 +768,16 @@ 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(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() > 0) @@ -754,15 +785,17 @@ UniValue getunconfirmedbalance(const JSONRPCRequest &request) "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(pwalletMain, 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) @@ -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,7 +833,7 @@ 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 +842,16 @@ UniValue movecmd(const JSONRPCRequest& request) UniValue sendfrom(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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(pwalletMain) + "\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 +876,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 +896,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(pwalletMain); + 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(pwalletMain, address.Get(), nAmount, false, wtx); + SendMoney(pwallet, address.Get(), nAmount, false, wtx); return wtx.GetHash().GetHex(); } @@ -876,14 +911,16 @@ UniValue sendfrom(const JSONRPCRequest& request) UniValue sendmany(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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(pwalletMain) + "\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,9 +952,9 @@ UniValue sendmany(const JSONRPCRequest& request) + HelpExampleRpc("sendmany", "\"\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":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]); @@ -967,23 +1004,23 @@ UniValue sendmany(const JSONRPCRequest& request) vecSend.push_back(recipient); } - EnsureWalletIsUnlocked(pwalletMain); + 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); } @@ -996,7 +1033,9 @@ extern CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniVa UniValue addmultisigaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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,18 +1066,18 @@ 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(pwalletMain, 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(); } @@ -1092,7 +1131,9 @@ public: UniValue addwitnessaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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) @@ -1122,14 +1163,14 @@ UniValue addwitnessaddress(const JSONRPCRequest& request) if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); - Witnessifier w(pwalletMain); + 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(); } @@ -1270,7 +1311,9 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA UniValue listreceivedbyaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() > 3) @@ -1305,14 +1348,16 @@ UniValue listreceivedbyaddress(const JSONRPCRequest& request) + HelpExampleRpc("listreceivedbyaddress", "6, true, true") ); - LOCK2(cs_main, pwalletMain->cs_wallet); + LOCK2(cs_main, pwallet->cs_wallet); - return ListReceived(pwalletMain, request.params, false); + return ListReceived(pwallet, request.params, false); } UniValue listreceivedbyaccount(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() > 3) @@ -1342,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(pwalletMain, request.params, true); + return ListReceived(pwallet, request.params, true); } static void MaybePushAddress(UniValue & entry, const CTxDestination &dest) @@ -1448,7 +1493,9 @@ void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Un UniValue listtransactions(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() > 4) @@ -1511,7 +1558,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) @@ -1534,14 +1581,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(pwalletMain, *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); @@ -1576,7 +1623,9 @@ UniValue listtransactions(const JSONRPCRequest& request) UniValue listaccounts(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() > 2) @@ -1602,7 +1651,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) @@ -1613,12 +1662,12 @@ UniValue listaccounts(const JSONRPCRequest& request) includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY; map mapAccountBalances; - BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) { - if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me + BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwallet->mapAddressBook) { + if (IsMine(*pwallet, entry.first) & includeWatchonly) // This address belongs to me mapAccountBalances[entry.second.name] = 0; } - for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + for (map::iterator it = pwallet->mapWallet.begin(); it != pwallet->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; CAmount nFee; @@ -1635,14 +1684,14 @@ 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 & acentries = pwalletMain->laccentries; + const list & acentries = pwallet->laccentries; BOOST_FOREACH(const CAccountingEntry& entry, acentries) mapAccountBalances[entry.strAccount] += entry.nCreditDebit; @@ -1655,7 +1704,9 @@ UniValue listaccounts(const JSONRPCRequest& request) UniValue listsinceblock(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp) @@ -1699,7 +1750,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; @@ -1741,12 +1792,12 @@ UniValue listsinceblock(const JSONRPCRequest& request) UniValue transactions(UniValue::VARR); - for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++) + for (map::iterator it = pwallet->mapWallet.begin(); it != pwallet->mapWallet.end(); it++) { CWalletTx tx = (*it).second; if (depth == -1 || tx.GetDepthInMainChain() < depth) - ListTransactions(pwalletMain, tx, "*", 0, true, transactions, filter); + ListTransactions(pwallet, tx, "*", 0, true, transactions, filter); } CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms]; @@ -1761,7 +1812,9 @@ UniValue listsinceblock(const JSONRPCRequest& request) UniValue gettransaction(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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) @@ -1809,7 +1862,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()); @@ -1820,9 +1873,9 @@ 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); @@ -1836,7 +1889,7 @@ UniValue gettransaction(const JSONRPCRequest& request) WalletTxToJSON(wtx, entry); UniValue details(UniValue::VARR); - ListTransactions(pwalletMain, wtx, "*", 0, false, details, filter); + ListTransactions(pwallet, wtx, "*", 0, false, details, filter); entry.push_back(Pair("details", details)); string strHex = EncodeHexTx(static_cast(wtx), RPCSerializationFlags()); @@ -1847,7 +1900,9 @@ UniValue gettransaction(const JSONRPCRequest& request) UniValue abandontransaction(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() != 1) @@ -1866,14 +1921,14 @@ 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; @@ -1882,7 +1937,9 @@ UniValue abandontransaction(const JSONRPCRequest& request) UniValue backupwallet(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() != 1) @@ -1896,10 +1953,10 @@ 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; @@ -1908,14 +1965,16 @@ UniValue backupwallet(const JSONRPCRequest& request) UniValue keypoolrefill(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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(pwalletMain) + "\n" + + HelpRequiringPassphrase(pwallet) + "\n" "\nArguments\n" "1. newsize (numeric, optional, default=100) The new keypool size\n" "\nExamples:\n" @@ -1923,7 +1982,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; @@ -1933,10 +1992,10 @@ UniValue keypoolrefill(const JSONRPCRequest& request) kpSize = (unsigned int)request.params[0].get_int(); } - EnsureWalletIsUnlocked(pwalletMain); - 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; @@ -1952,10 +2011,12 @@ static void LockWallet(CWallet* pWallet) UniValue walletpassphrase(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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" @@ -1975,11 +2036,11 @@ UniValue walletpassphrase(const JSONRPCRequest& request) + 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 @@ -1991,7 +2052,7 @@ 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 @@ -1999,12 +2060,12 @@ UniValue walletpassphrase(const JSONRPCRequest& request) "walletpassphrase \n" "Stores the wallet decryption key in memory for 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); + RPCRunLater("lockwallet", boost::bind(LockWallet, pwallet), nSleepTime); return NullUniValue; } @@ -2012,10 +2073,12 @@ UniValue walletpassphrase(const JSONRPCRequest& request) UniValue walletpassphrasechange(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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" @@ -2027,11 +2090,11 @@ UniValue walletpassphrasechange(const JSONRPCRequest& request) + 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) @@ -2049,7 +2112,7 @@ UniValue walletpassphrasechange(const JSONRPCRequest& request) "walletpassphrasechange \n" "Changes the wallet passphrase from to ."); - 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; @@ -2058,10 +2121,12 @@ UniValue walletpassphrasechange(const JSONRPCRequest& request) UniValue walletlock(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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" @@ -2078,16 +2143,16 @@ UniValue walletlock(const JSONRPCRequest& request) + 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(); + pwallet->Lock(); nWalletUnlockTime = 0; } @@ -2097,10 +2162,12 @@ UniValue walletlock(const JSONRPCRequest& request) UniValue encryptwallet(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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" @@ -2124,11 +2191,11 @@ UniValue encryptwallet(const JSONRPCRequest& request) + 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) @@ -2142,7 +2209,7 @@ UniValue encryptwallet(const JSONRPCRequest& request) "encryptwallet \n" "Encrypts the wallet with ."); - 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 @@ -2154,7 +2221,9 @@ UniValue encryptwallet(const JSONRPCRequest& request) UniValue lockunspent(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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) @@ -2194,7 +2263,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)); @@ -2205,7 +2274,7 @@ UniValue lockunspent(const JSONRPCRequest& request) if (request.params.size() == 1) { if (fUnlock) - pwalletMain->UnlockAllCoins(); + pwallet->UnlockAllCoins(); return true; } @@ -2233,9 +2302,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; @@ -2243,7 +2312,9 @@ UniValue lockunspent(const JSONRPCRequest& request) UniValue listlockunspent(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() > 0) @@ -2272,10 +2343,10 @@ UniValue listlockunspent(const JSONRPCRequest& request) + HelpExampleRpc("listlockunspent", "") ); - LOCK2(cs_main, pwalletMain->cs_wallet); + LOCK2(cs_main, pwallet->cs_wallet); vector vOutpts; - pwalletMain->ListLockedCoins(vOutpts); + pwallet->ListLockedCoins(vOutpts); UniValue ret(UniValue::VARR); @@ -2292,7 +2363,9 @@ UniValue listlockunspent(const JSONRPCRequest& request) UniValue settxfee(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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) @@ -2308,7 +2381,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]); @@ -2319,7 +2392,9 @@ UniValue settxfee(const JSONRPCRequest& request) UniValue getwalletinfo(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() != 0) @@ -2344,20 +2419,20 @@ 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("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", nWalletUnlockTime)); 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; @@ -2365,7 +2440,9 @@ UniValue getwalletinfo(const JSONRPCRequest& request) UniValue resendwallettransactions(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() != 0) @@ -2380,9 +2457,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 txids = pwalletMain->ResendWalletTransactionsBefore(GetTime(), g_connman.get()); + std::vector txids = pwallet->ResendWalletTransactionsBefore(GetTime(), g_connman.get()); UniValue result(UniValue::VARR); BOOST_FOREACH(const uint256& txid, txids) { @@ -2393,7 +2470,9 @@ UniValue resendwallettransactions(const JSONRPCRequest& request) UniValue listunspent(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, request.fHelp)) + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; if (request.fHelp || request.params.size() > 4) @@ -2472,9 +2551,9 @@ UniValue listunspent(const JSONRPCRequest& request) UniValue results(UniValue::VARR); vector 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; @@ -2493,13 +2572,13 @@ 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(address); CScript redeemScript; - if (pwalletMain->GetCScript(hash, redeemScript)) + if (pwallet->GetCScript(hash, redeemScript)) entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end()))); } } @@ -2517,7 +2596,9 @@ UniValue listunspent(const JSONRPCRequest& request) UniValue fundrawtransaction(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(pwalletMain, 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) @@ -2659,7 +2740,7 @@ 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); @@ -2699,9 +2780,10 @@ int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, CWallet &wallet) 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( @@ -2751,14 +2833,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"); } @@ -2784,7 +2866,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"); } @@ -2792,7 +2874,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"); } @@ -2935,12 +3017,12 @@ UniValue bumpfee(const JSONRPCRequest& request) CTransaction txNewConst(tx); int nIn = 0; for (auto& input : tx.vin) { - std::map::const_iterator mi = pwalletMain->mapWallet.find(input.prevout.hash); - assert(mi != pwalletMain->mapWallet.end() && input.prevout.n < mi->second.tx->vout.size()); + std::map::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); @@ -2948,8 +3030,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; @@ -2957,7 +3039,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())); } @@ -2970,7 +3052,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