aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/crypter.cpp2
-rw-r--r--src/wallet/crypter.h2
-rw-r--r--src/wallet/db.cpp28
-rw-r--r--src/wallet/db.h21
-rw-r--r--src/wallet/feebumper.cpp14
-rw-r--r--src/wallet/feebumper.h2
-rw-r--r--src/wallet/rpcdump.cpp46
-rw-r--r--src/wallet/rpcwallet.cpp91
-rw-r--r--src/wallet/test/accounting_tests.cpp2
-rw-r--r--src/wallet/test/crypto_tests.cpp5
-rw-r--r--src/wallet/test/wallet_test_fixture.cpp2
-rw-r--r--src/wallet/test/wallet_tests.cpp43
-rw-r--r--src/wallet/wallet.cpp217
-rw-r--r--src/wallet/wallet.h14
-rw-r--r--src/wallet/walletdb.cpp159
-rw-r--r--src/wallet/walletdb.h33
16 files changed, 353 insertions, 328 deletions
diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp
index fc318c1612..836c15b82c 100644
--- a/src/wallet/crypter.cpp
+++ b/src/wallet/crypter.cpp
@@ -285,7 +285,7 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
return false;
fUseCrypto = true;
- BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
+ for (KeyMap::value_type& mKey : mapKeys)
{
const CKey &key = mKey.second;
CPubKey vchPubKey = key.GetPubKey();
diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h
index 275e435f73..f1c4f57428 100644
--- a/src/wallet/crypter.h
+++ b/src/wallet/crypter.h
@@ -9,8 +9,6 @@
#include "serialize.h"
#include "support/allocators/secure.h"
-class uint256;
-
const unsigned int WALLET_CRYPTO_KEY_SIZE = 32;
const unsigned int WALLET_CRYPTO_SALT_SIZE = 8;
const unsigned int WALLET_CRYPTO_IV_SIZE = 16;
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index 25f6bdd9d9..844d610793 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -20,7 +20,6 @@
#include <boost/foreach.hpp>
#include <boost/thread.hpp>
-#include <boost/version.hpp>
//
// CDB
@@ -143,7 +142,7 @@ void CDBEnv::MakeMock()
fMockDb = true;
}
-CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, bool (*recoverFunc)(const std::string& strFile))
+CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, recoverFunc_type recoverFunc, std::string& out_backup_filename)
{
LOCK(cs_db);
assert(mapFileUseCount.count(strFile) == 0);
@@ -156,21 +155,21 @@ CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, bool (*recoverFu
return RECOVER_FAIL;
// Try to recover:
- bool fRecovered = (*recoverFunc)(strFile);
+ bool fRecovered = (*recoverFunc)(strFile, out_backup_filename);
return (fRecovered ? RECOVER_OK : RECOVER_FAIL);
}
-bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue))
+bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& newFilename)
{
// Recovery procedure:
- // move wallet file to wallet.timestamp.bak
+ // move wallet file to walletfilename.timestamp.bak
// Call Salvage with fAggressive=true to
// get as much data as possible.
// Rewrite salvaged data to fresh wallet file
// Set -rescan so any missing transactions will be
// found.
int64_t now = GetTime();
- std::string newFilename = strprintf("wallet.%d.bak", now);
+ newFilename = strprintf("%s.%d.bak", filename, now);
int result = bitdb.dbenv->dbrename(NULL, filename.c_str(), NULL,
newFilename.c_str(), DB_AUTO_COMMIT);
@@ -205,13 +204,12 @@ bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*reco
}
DbTxn* ptxn = bitdb.TxnBegin();
- BOOST_FOREACH(CDBEnv::KeyValPair& row, salvagedData)
+ for (CDBEnv::KeyValPair& row : salvagedData)
{
if (recoverKVcallback)
{
CDataStream ssKey(row.first, SER_DISK, CLIENT_VERSION);
CDataStream ssValue(row.second, SER_DISK, CLIENT_VERSION);
- std::string strType, strErr;
if (!(*recoverKVcallback)(callbackDataIn, ssKey, ssValue))
continue;
}
@@ -261,18 +259,19 @@ bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataD
return true;
}
-bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, bool (*recoverFunc)(const std::string& strFile))
+bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc)
{
if (fs::exists(dataDir / walletFile))
{
- CDBEnv::VerifyResult r = bitdb.Verify(walletFile, recoverFunc);
+ std::string backup_filename;
+ CDBEnv::VerifyResult r = bitdb.Verify(walletFile, recoverFunc, backup_filename);
if (r == CDBEnv::RECOVER_OK)
{
warningStr = strprintf(_("Warning: Wallet file corrupt, data salvaged!"
" Original %s saved as %s in %s; if"
" your balance or transactions are incorrect you should"
" restore from a backup."),
- walletFile, "wallet.{timestamp}.bak", dataDir);
+ walletFile, backup_filename, dataDir);
}
if (r == CDBEnv::RECOVER_FAIL)
{
@@ -361,7 +360,6 @@ void CDBEnv::CheckpointLSN(const std::string& strFile)
CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb(NULL), activeTxn(NULL)
{
- int ret;
fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
fFlushOnClose = fFlushOnCloseIn;
env = dbw.env;
@@ -384,6 +382,7 @@ CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb
++env->mapFileUseCount[strFile];
pdb = env->mapDb[strFile];
if (pdb == NULL) {
+ int ret;
pdb = new Db(env->dbenv, 0);
bool fMockDb = env->IsMock();
@@ -434,6 +433,11 @@ void CDB::Flush()
env->dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", DEFAULT_WALLET_DBLOGSIZE) * 1024 : 0, nMinutes, 0);
}
+void CWalletDBWrapper::IncrementUpdateCounter()
+{
+ ++nUpdateCounter;
+}
+
void CDB::Close()
{
if (!pdb)
diff --git a/src/wallet/db.h b/src/wallet/db.h
index 3c6870d169..7cccc65660 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -13,6 +13,7 @@
#include "sync.h"
#include "version.h"
+#include <atomic>
#include <map>
#include <string>
#include <vector>
@@ -55,7 +56,8 @@ public:
enum VerifyResult { VERIFY_OK,
RECOVER_OK,
RECOVER_FAIL };
- VerifyResult Verify(const std::string& strFile, bool (*recoverFunc)(const std::string& strFile));
+ typedef bool (*recoverFunc_type)(const std::string& strFile, std::string& out_backup_filename);
+ VerifyResult Verify(const std::string& strFile, recoverFunc_type recoverFunc, std::string& out_backup_filename);
/**
* Salvage data from a file that Verify says is bad.
* fAggressive sets the DB_AGGRESSIVE flag (see berkeley DB->verify() method documentation).
@@ -93,13 +95,13 @@ class CWalletDBWrapper
friend class CDB;
public:
/** Create dummy DB handle */
- CWalletDBWrapper(): env(nullptr)
+ CWalletDBWrapper() : nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(nullptr)
{
}
/** Create DB handle to real database */
- CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in):
- env(env_in), strFile(strFile_in)
+ CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in) :
+ nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(env_in), strFile(strFile_in)
{
}
@@ -119,6 +121,13 @@ public:
*/
void Flush(bool shutdown);
+ void IncrementUpdateCounter();
+
+ std::atomic<unsigned int> nUpdateCounter;
+ unsigned int nLastSeen;
+ unsigned int nLastFlushed;
+ int64_t nLastWalletUpdate;
+
private:
/** BerkeleyDB specific */
CDBEnv *env;
@@ -149,7 +158,7 @@ public:
void Flush();
void Close();
- static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue));
+ static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename);
/* flush the wallet passively (TRY_LOCK)
ideal to be called periodically */
@@ -157,7 +166,7 @@ public:
/* verifies the database environment */
static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr);
/* verifies the database file */
- static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, bool (*recoverFunc)(const std::string& strFile));
+ static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc);
private:
CDB(const CDB&);
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index c10a9eccd9..46ef87b7b1 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -66,7 +66,7 @@ bool CFeeBumper::preconditionChecks(const CWallet *pWallet, const CWalletTx& wtx
return true;
}
-CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, int newConfirmTarget, bool specifiedConfirmTarget, CAmount totalFee, bool newTxReplaceable)
+CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, int newConfirmTarget, bool ignoreGlobalPayTxFee, CAmount totalFee, bool newTxReplaceable)
:
txid(std::move(txidIn)),
nOldFee(0),
@@ -165,15 +165,7 @@ CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, int newConf
nNewFee = totalFee;
nNewFeeRate = CFeeRate(totalFee, maxNewTxSize);
} else {
- // if user specified a confirm target then don't consider any global payTxFee
- if (specifiedConfirmTarget) {
- nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, ::feeEstimator, true);
- }
- // otherwise use the regular wallet logic to select payTxFee or default confirm target
- else {
- nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, ::feeEstimator);
- }
-
+ nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, ::feeEstimator, ignoreGlobalPayTxFee);
nNewFeeRate = CFeeRate(nNewFee, maxNewTxSize);
// New fee rate must be at least old rate + minimum incremental relay rate
@@ -255,7 +247,7 @@ bool CFeeBumper::commit(CWallet *pWallet)
}
CWalletTx& oldWtx = pWallet->mapWallet[txid];
- // make sure the transaction still has no descendants and hasen't been mined in the meantime
+ // make sure the transaction still has no descendants and hasn't been mined in the meantime
if (!preconditionChecks(pWallet, oldWtx)) {
return false;
}
diff --git a/src/wallet/feebumper.h b/src/wallet/feebumper.h
index f40d05da28..fc32316704 100644
--- a/src/wallet/feebumper.h
+++ b/src/wallet/feebumper.h
@@ -24,7 +24,7 @@ enum class BumpFeeResult
class CFeeBumper
{
public:
- CFeeBumper(const CWallet *pWalletIn, const uint256 txidIn, int newConfirmTarget, bool specifiedConfirmTarget, CAmount totalFee, bool newTxReplaceable);
+ CFeeBumper(const CWallet *pWalletIn, const uint256 txidIn, int newConfirmTarget, bool ignoreGlobalPayTxFee, CAmount totalFee, bool newTxReplaceable);
BumpFeeResult getResult() const { return currentResult; }
const std::vector<std::string>& getErrors() const { return vErrors; }
CAmount getOldFee() const { return nOldFee; }
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index d46cf69efb..3c25364648 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -26,7 +26,6 @@
#include <univalue.h>
-#include <boost/assign/list_of.hpp>
#include <boost/foreach.hpp>
std::string static EncodeDumpTime(int64_t nTime) {
@@ -48,7 +47,7 @@ int64_t static DecodeDumpTime(const std::string &str) {
std::string static EncodeDumpString(const std::string &str) {
std::stringstream ret;
- BOOST_FOREACH(unsigned char c, str) {
+ for (unsigned char c : str) {
if (c <= 32 || c >= 128 || c == '%') {
ret << '%' << HexStr(&c, &c + 1);
} else {
@@ -357,7 +356,7 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
"removeprunedfunds \"txid\"\n"
- "\nDeletes the specified transaction from the wallet. Meant for use with pruned wallets and as a companion to importprunedfunds. This will effect wallet balances.\n"
+ "\nDeletes the specified transaction from the wallet. Meant for use with pruned wallets and as a companion to importprunedfunds. This will affect wallet balances.\n"
"\nArguments:\n"
"1. \"txid\" (string, required) The hex-encoded id of the transaction you are deleting\n"
"\nExamples:\n"
@@ -603,7 +602,11 @@ UniValue dumpwallet(const JSONRPCRequest& request)
"dumpwallet \"filename\"\n"
"\nDumps all wallet keys in a human-readable format.\n"
"\nArguments:\n"
- "1. \"filename\" (string, required) The filename\n"
+ "1. \"filename\" (string, required) The filename with path (either absolute or relative to bitcoind)\n"
+ "\nResult:\n"
+ "{ (json object)\n"
+ " \"filename\" : { (string) The filename with full absolute path\n"
+ "}\n"
"\nExamples:\n"
+ HelpExampleCli("dumpwallet", "\"test\"")
+ HelpExampleRpc("dumpwallet", "\"test\"")
@@ -614,7 +617,9 @@ UniValue dumpwallet(const JSONRPCRequest& request)
EnsureWalletIsUnlocked(pwallet);
std::ofstream file;
- file.open(request.params[0].get_str().c_str());
+ boost::filesystem::path filepath = request.params[0].get_str();
+ filepath = boost::filesystem::absolute(filepath);
+ file.open(filepath.string().c_str());
if (!file.is_open())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
@@ -679,7 +684,11 @@ UniValue dumpwallet(const JSONRPCRequest& request)
file << "\n";
file << "# End of dump\n";
file.close();
- return NullUniValue;
+
+ UniValue reply(UniValue::VOBJ);
+ reply.push_back(Pair("filename", filepath.string()));
+
+ return reply;
}
@@ -1060,7 +1069,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
// clang-format on
- RPCTypeCheck(mainRequest.params, boost::assign::list_of(UniValue::VARR)(UniValue::VOBJ));
+ RPCTypeCheck(mainRequest.params, {UniValue::VARR, UniValue::VOBJ});
const UniValue& requests = mainRequest.params[0];
@@ -1096,7 +1105,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
UniValue response(UniValue::VARR);
- BOOST_FOREACH (const UniValue& data, requests.getValues()) {
+ for (const UniValue& data : requests.getValues()) {
const int64_t timestamp = std::max(GetImportTimestamp(data, now), minimumTimestamp);
const UniValue result = ProcessImport(pwallet, data, timestamp);
response.push_back(result);
@@ -1118,13 +1127,13 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
if (fRescan && fRunScan && requests.size()) {
CBlockIndex* pindex = nLowestTimestamp > minimumTimestamp ? chainActive.FindEarliestAtLeast(std::max<int64_t>(nLowestTimestamp - TIMESTAMP_WINDOW, 0)) : chainActive.Genesis();
- CBlockIndex* scannedRange = nullptr;
+ CBlockIndex* scanFailed = nullptr;
if (pindex) {
- scannedRange = pwallet->ScanForWalletTransactions(pindex, true);
+ scanFailed = pwallet->ScanForWalletTransactions(pindex, true);
pwallet->ReacceptWalletTransactions();
}
- if (!scannedRange || scannedRange->nHeight > pindex->nHeight) {
+ if (scanFailed) {
std::vector<UniValue> results = response.getValues();
response.clear();
response.setArray();
@@ -1134,12 +1143,23 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
// range, or if the import result already has an error set, let
// the result stand unmodified. Otherwise replace the result
// with an error message.
- if (GetImportTimestamp(request, now) - TIMESTAMP_WINDOW >= scannedRange->GetBlockTimeMax() || results.at(i).exists("error")) {
+ if (GetImportTimestamp(request, now) - TIMESTAMP_WINDOW > scanFailed->GetBlockTimeMax() || results.at(i).exists("error")) {
response.push_back(results.at(i));
} else {
UniValue result = UniValue(UniValue::VOBJ);
result.pushKV("success", UniValue(false));
- result.pushKV("error", JSONRPCError(RPC_MISC_ERROR, strprintf("Failed to rescan before time %d, transactions may be missing.", scannedRange->GetBlockTimeMax())));
+ result.pushKV(
+ "error",
+ JSONRPCError(
+ RPC_MISC_ERROR,
+ strprintf("Rescan failed for key with creation timestamp %d. There was an error reading a "
+ "block from time %d, which is after or within %d seconds of key creation, and "
+ "could contain transactions pertaining to the key. As a result, transactions "
+ "and coins using this key may not appear in the wallet. This error could be "
+ "caused by pruning or data corruption (see bitcoind log for details) and could "
+ "be dealt with by downloading and rescanning the relevant blocks (see -reindex "
+ "and -rescan options).",
+ GetImportTimestamp(request, now), scanFailed->GetBlockTimeMax(), TIMESTAMP_WINDOW)));
response.push_back(std::move(result));
}
++i;
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index ae4f4f37cb..2e4105a569 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -9,7 +9,6 @@
#include "consensus/validation.h"
#include "core_io.h"
#include "init.h"
-#include "wallet/coincontrol.h"
#include "validation.h"
#include "net.h"
#include "policy/feerate.h"
@@ -21,19 +20,19 @@
#include "timedata.h"
#include "util.h"
#include "utilmoneystr.h"
+#include "wallet/coincontrol.h"
#include "wallet/feebumper.h"
#include "wallet/wallet.h"
#include "wallet/walletdb.h"
#include <stdint.h>
-#include <boost/assign/list_of.hpp>
-
#include <univalue.h>
CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
{
- return pwalletMain;
+ // TODO: Some way to access secondary wallets
+ return vpwallets.empty() ? nullptr : vpwallets[0];
}
std::string HelpRequiringPassphrase(CWallet * const pwallet)
@@ -78,7 +77,7 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
uint256 hash = wtx.GetHash();
entry.push_back(Pair("txid", hash.GetHex()));
UniValue conflicts(UniValue::VARR);
- BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
+ for (const uint256& conflict : wtx.GetConflicts())
conflicts.push_back(conflict.GetHex());
entry.push_back(Pair("walletconflicts", conflicts));
entry.push_back(Pair("time", wtx.GetTxTime()));
@@ -96,7 +95,7 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
}
entry.push_back(Pair("bip125-replaceable", rbfStatus));
- BOOST_FOREACH(const PAIRTYPE(std::string, std::string)& item, wtx.mapValue)
+ for (const std::pair<std::string, std::string>& item : wtx.mapValue)
entry.push_back(Pair(item.first, item.second));
}
@@ -490,7 +489,7 @@ UniValue listaddressgroupings(const JSONRPCRequest& request)
std::map<CTxDestination, CAmount> balances = pwallet->GetAddressBalances();
for (std::set<CTxDestination> grouping : pwallet->GetAddressGroupings()) {
UniValue jsonGrouping(UniValue::VARR);
- BOOST_FOREACH(CTxDestination address, grouping)
+ for (CTxDestination address : grouping)
{
UniValue addressInfo(UniValue::VARR);
addressInfo.push_back(CBitcoinAddress(address).ToString());
@@ -616,7 +615,7 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request)
if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
continue;
- BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
+ for (const CTxOut& txout : wtx.tx->vout)
if (txout.scriptPubKey == scriptPubKey)
if (wtx.GetDepthInMainChain() >= nMinDepth)
nAmount += txout.nValue;
@@ -671,7 +670,7 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
continue;
- BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
+ for (const CTxOut& txout : wtx.tx->vout)
{
CTxDestination address;
if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwallet, address) && setAddress.count(address)) {
@@ -950,7 +949,7 @@ UniValue sendmany(const JSONRPCRequest& request)
CAmount totalAmount = 0;
std::vector<std::string> keys = sendTo.getKeys();
- BOOST_FOREACH(const std::string& name_, keys)
+ for (const std::string& name_ : keys)
{
CBitcoinAddress address(name_);
if (!address.IsValid())
@@ -1191,7 +1190,7 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA
if (nDepth < nMinDepth)
continue;
- BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
+ for (const CTxOut& txout : wtx.tx->vout)
{
CTxDestination address;
if (!ExtractDestination(txout.scriptPubKey, address))
@@ -1251,7 +1250,7 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA
UniValue transactions(UniValue::VARR);
if (it != mapTally.end())
{
- BOOST_FOREACH(const uint256& _item, (*it).second.txids)
+ for (const uint256& _item : (*it).second.txids)
{
transactions.push_back(_item.GetHex());
}
@@ -1385,7 +1384,7 @@ void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, const std::s
// Sent
if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
{
- BOOST_FOREACH(const COutputEntry& s, listSent)
+ for (const COutputEntry& s : listSent)
{
UniValue entry(UniValue::VOBJ);
if (involvesWatchonly || (::IsMine(*pwallet, s.destination) & ISMINE_WATCH_ONLY)) {
@@ -1410,7 +1409,7 @@ void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, const std::s
// Received
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
{
- BOOST_FOREACH(const COutputEntry& r, listReceived)
+ for (const COutputEntry& r : listReceived)
{
std::string account;
if (pwallet->mapAddressBook.count(r.destination)) {
@@ -1655,11 +1654,11 @@ UniValue listaccounts(const JSONRPCRequest& request)
continue;
wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
mapAccountBalances[strSentAccount] -= nFee;
- BOOST_FOREACH(const COutputEntry& s, listSent)
+ for (const COutputEntry& s : listSent)
mapAccountBalances[strSentAccount] -= s.amount;
if (nDepth >= nMinDepth)
{
- BOOST_FOREACH(const COutputEntry& r, listReceived)
+ for (const COutputEntry& r : listReceived)
if (pwallet->mapAddressBook.count(r.destination)) {
mapAccountBalances[pwallet->mapAddressBook[r.destination].name] += r.amount;
}
@@ -1669,11 +1668,11 @@ UniValue listaccounts(const JSONRPCRequest& request)
}
const std::list<CAccountingEntry>& acentries = pwallet->laccentries;
- BOOST_FOREACH(const CAccountingEntry& entry, acentries)
+ for (const CAccountingEntry& entry : acentries)
mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
UniValue ret(UniValue::VOBJ);
- BOOST_FOREACH(const PAIRTYPE(std::string, CAmount)& accountBalance, mapAccountBalances) {
+ for (const std::pair<std::string, CAmount>& accountBalance : mapAccountBalances) {
ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
}
return ret;
@@ -2254,9 +2253,9 @@ UniValue lockunspent(const JSONRPCRequest& request)
LOCK2(cs_main, pwallet->cs_wallet);
if (request.params.size() == 1)
- RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VBOOL));
+ RPCTypeCheck(request.params, {UniValue::VBOOL});
else
- RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VBOOL)(UniValue::VARR));
+ RPCTypeCheck(request.params, {UniValue::VBOOL, UniValue::VARR});
bool fUnlock = request.params[0].get_bool();
@@ -2338,7 +2337,7 @@ UniValue listlockunspent(const JSONRPCRequest& request)
UniValue ret(UniValue::VARR);
- BOOST_FOREACH(COutPoint &outpt, vOutpts) {
+ for (COutPoint &outpt : vOutpts) {
UniValue o(UniValue::VOBJ);
o.push_back(Pair("txid", outpt.hash.GetHex()));
@@ -2456,7 +2455,7 @@ UniValue resendwallettransactions(const JSONRPCRequest& request)
std::vector<uint256> txids = pwallet->ResendWalletTransactionsBefore(GetTime(), g_connman.get());
UniValue result(UniValue::VARR);
- BOOST_FOREACH(const uint256& txid, txids)
+ for (const uint256& txid : txids)
{
result.push_back(txid.ToString());
}
@@ -2581,7 +2580,7 @@ UniValue listunspent(const JSONRPCRequest& request)
LOCK2(cs_main, pwallet->cs_wallet);
pwallet->AvailableCoins(vecOutputs, !include_unsafe, NULL, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth);
- BOOST_FOREACH(const COutput& out, vecOutputs) {
+ for (const COutput& out : vecOutputs) {
CTxDestination address;
const CScript& scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey;
bool fValidAddress = ExtractDestination(scriptPubKey, address);
@@ -2628,7 +2627,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
return NullUniValue;
}
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
+ if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
"fundrawtransaction \"hexstring\" ( options )\n"
"\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
@@ -2657,6 +2656,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
" Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
" If no outputs are specified here, the sender pays the fee.\n"
" [vout_index,...]\n"
+ " \"optIntoRbf\" (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees\n"
" }\n"
" for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n"
"\nResult:\n"
@@ -2676,25 +2676,26 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
+ HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
);
- RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR));
+ RPCTypeCheck(request.params, {UniValue::VSTR});
- CTxDestination changeAddress = CNoDestination();
+ CCoinControl coinControl;
+ coinControl.destChange = CNoDestination();
int changePosition = -1;
- bool includeWatching = false;
+ coinControl.fAllowWatchOnly = false; // include watching
bool lockUnspents = false;
bool reserveChangeKey = true;
- CFeeRate feeRate = CFeeRate(0);
- bool overrideEstimatedFeerate = false;
+ coinControl.nFeeRate = CFeeRate(0);
+ coinControl.fOverrideFeeRate = false;
UniValue subtractFeeFromOutputs;
std::set<int> setSubtractFeeFromOutputs;
if (request.params.size() > 1) {
if (request.params[1].type() == UniValue::VBOOL) {
// backward compatibility bool only fallback
- includeWatching = request.params[1].get_bool();
+ coinControl.fAllowWatchOnly = request.params[1].get_bool();
}
else {
- RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ));
+ RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ});
UniValue options = request.params[1];
@@ -2707,6 +2708,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
{"reserveChangeKey", UniValueType(UniValue::VBOOL)},
{"feeRate", UniValueType()}, // will be checked below
{"subtractFeeFromOutputs", UniValueType(UniValue::VARR)},
+ {"optIntoRbf", UniValueType(UniValue::VBOOL)},
},
true, true);
@@ -2716,14 +2718,14 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "changeAddress must be a valid bitcoin address");
- changeAddress = address.Get();
+ coinControl.destChange = address.Get();
}
if (options.exists("changePosition"))
changePosition = options["changePosition"].get_int();
if (options.exists("includeWatching"))
- includeWatching = options["includeWatching"].get_bool();
+ coinControl.fAllowWatchOnly = options["includeWatching"].get_bool();
if (options.exists("lockUnspents"))
lockUnspents = options["lockUnspents"].get_bool();
@@ -2733,12 +2735,16 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
if (options.exists("feeRate"))
{
- feeRate = CFeeRate(AmountFromValue(options["feeRate"]));
- overrideEstimatedFeerate = true;
+ coinControl.nFeeRate = CFeeRate(AmountFromValue(options["feeRate"]));
+ coinControl.fOverrideFeeRate = true;
}
if (options.exists("subtractFeeFromOutputs"))
subtractFeeFromOutputs = options["subtractFeeFromOutputs"].get_array();
+
+ if (options.exists("optIntoRbf")) {
+ coinControl.signalRbf = options["optIntoRbf"].get_bool();
+ }
}
}
@@ -2767,7 +2773,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
CAmount nFeeOut;
std::string strFailReason;
- if (!pwallet->FundTransaction(tx, nFeeOut, overrideEstimatedFeerate, feeRate, changePosition, strFailReason, includeWatching, lockUnspents, setSubtractFeeFromOutputs, reserveChangeKey, changeAddress)) {
+ if (!pwallet->FundTransaction(tx, nFeeOut, changePosition, strFailReason, lockUnspents, setSubtractFeeFromOutputs, coinControl, reserveChangeKey)) {
throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
}
@@ -2829,12 +2835,12 @@ UniValue bumpfee(const JSONRPCRequest& request)
HelpExampleCli("bumpfee", "<txid>"));
}
- RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ));
+ RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ});
uint256 hash;
hash.SetHex(request.params[0].get_str());
// optional parameters
- bool specifiedConfirmTarget = false;
+ bool ignoreGlobalPayTxFee = false;
int newConfirmTarget = nTxConfirmTarget;
CAmount totalFee = 0;
bool replaceable = true;
@@ -2851,7 +2857,10 @@ UniValue bumpfee(const JSONRPCRequest& request)
if (options.exists("confTarget") && options.exists("totalFee")) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "confTarget and totalFee options should not both be set. Please provide either a confirmation target for fee estimation or an explicit total fee for the transaction.");
} else if (options.exists("confTarget")) {
- specifiedConfirmTarget = true;
+ // If the user has explicitly set a confTarget in this rpc call,
+ // then override the default logic that uses the global payTxFee
+ // instead of the confirmation target.
+ ignoreGlobalPayTxFee = true;
newConfirmTarget = options["confTarget"].get_int();
if (newConfirmTarget <= 0) { // upper-bound will be checked by estimatefee/smartfee
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid confTarget (cannot be <= 0)");
@@ -2871,7 +2880,7 @@ UniValue bumpfee(const JSONRPCRequest& request)
LOCK2(cs_main, pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
- CFeeBumper feeBump(pwallet, hash, newConfirmTarget, specifiedConfirmTarget, totalFee, replaceable);
+ CFeeBumper feeBump(pwallet, hash, newConfirmTarget, ignoreGlobalPayTxFee, totalFee, replaceable);
BumpFeeResult res = feeBump.getResult();
if (res != BumpFeeResult::OK)
{
@@ -2909,7 +2918,7 @@ UniValue bumpfee(const JSONRPCRequest& request)
UniValue errors(UniValue::VARR);
for (const std::string& err: feeBump.getErrors())
errors.push_back(err);
- result.push_back(errors);
+ result.push_back(Pair("errors", errors));
return result;
}
diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp
index 1fe633f2e5..12d9f2e995 100644
--- a/src/wallet/test/accounting_tests.cpp
+++ b/src/wallet/test/accounting_tests.cpp
@@ -23,7 +23,7 @@ GetResults(std::map<CAmount, CAccountingEntry>& results)
results.clear();
BOOST_CHECK(pwalletMain->ReorderTransactions() == DB_LOAD_OK);
pwalletMain->ListAccountCreditDebit("", aes);
- BOOST_FOREACH(CAccountingEntry& ae, aes)
+ for (CAccountingEntry& ae : aes)
{
results[ae.nOrderPos] = ae;
}
diff --git a/src/wallet/test/crypto_tests.cpp b/src/wallet/test/crypto_tests.cpp
index 0d012dacad..524a72c303 100644
--- a/src/wallet/test/crypto_tests.cpp
+++ b/src/wallet/test/crypto_tests.cpp
@@ -2,9 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "test/test_random.h"
-#include "utilstrencodings.h"
#include "test/test_bitcoin.h"
+#include "utilstrencodings.h"
#include "wallet/crypter.h"
#include <vector>
@@ -193,7 +192,7 @@ BOOST_AUTO_TEST_CASE(passphrase) {
std::string hash(GetRandHash().ToString());
std::vector<unsigned char> vchSalt(8);
GetRandBytes(&vchSalt[0], vchSalt.size());
- uint32_t rounds = insecure_rand();
+ uint32_t rounds = InsecureRand32();
if (rounds > 30000)
rounds = 30000;
TestCrypter::TestPassphrase(vchSalt, SecureString(hash.begin(), hash.end()), rounds);
diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp
index 1989bf8d9b..922fcc8e89 100644
--- a/src/wallet/test/wallet_test_fixture.cpp
+++ b/src/wallet/test/wallet_test_fixture.cpp
@@ -8,6 +8,8 @@
#include "wallet/db.h"
#include "wallet/wallet.h"
+CWallet *pwalletMain;
+
WalletTestingSetup::WalletTestingSetup(const std::string& chainName):
TestingSetup(chainName)
{
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 5c7359fdce..96a1b14b60 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -15,10 +15,11 @@
#include "validation.h"
#include "wallet/test/wallet_test_fixture.h"
-#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
#include <univalue.h>
+extern CWallet* pwalletMain;
+
extern UniValue importmulti(const JSONRPCRequest& request);
extern UniValue dumpwallet(const JSONRPCRequest& request);
extern UniValue importwallet(const JSONRPCRequest& request);
@@ -367,6 +368,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
LOCK(cs_main);
// Cap last block file size, and mine new block in a new block file.
+ CBlockIndex* const nullBlock = nullptr;
CBlockIndex* oldTip = chainActive.Tip();
GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE;
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
@@ -378,7 +380,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
CWallet wallet;
LOCK(wallet.cs_wallet);
wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
- BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip));
+ BOOST_CHECK_EQUAL(nullBlock, wallet.ScanForWalletTransactions(oldTip));
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 100 * COIN);
}
@@ -392,7 +394,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
CWallet wallet;
LOCK(wallet.cs_wallet);
wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
- BOOST_CHECK_EQUAL(newTip, wallet.ScanForWalletTransactions(oldTip));
+ BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip));
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 50 * COIN);
}
@@ -401,8 +403,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
// after.
{
CWallet wallet;
- CWallet *backup = ::pwalletMain;
- ::pwalletMain = &wallet;
+ vpwallets.insert(vpwallets.begin(), &wallet);
UniValue keys;
keys.setArray();
UniValue key;
@@ -416,7 +417,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
CKey futureKey;
futureKey.MakeNewKey(true);
key.pushKV("scriptPubKey", HexStr(GetScriptForRawPubKey(futureKey.GetPubKey())));
- key.pushKV("timestamp", newTip->GetBlockTimeMax() + TIMESTAMP_WINDOW);
+ key.pushKV("timestamp", newTip->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1);
key.pushKV("internal", UniValue(true));
keys.push_back(key);
JSONRPCRequest request;
@@ -424,19 +425,16 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
request.params.push_back(keys);
UniValue response = importmulti(request);
- BOOST_CHECK_EQUAL(response.write(), strprintf("[{\"success\":false,\"error\":{\"code\":-1,\"message\":\"Failed to rescan before time %d, transactions may be missing.\"}},{\"success\":true}]", newTip->GetBlockTimeMax()));
- ::pwalletMain = backup;
- }
-
- // Verify ScanForWalletTransactions does not return null when the scan is
- // elided due to the nTimeFirstKey optimization.
- {
- CWallet wallet;
- {
- LOCK(wallet.cs_wallet);
- wallet.UpdateTimeFirstKey(newTip->GetBlockTime() + 7200 + 1);
- }
- BOOST_CHECK_EQUAL(newTip, wallet.ScanForWalletTransactions(newTip));
+ BOOST_CHECK_EQUAL(response.write(),
+ strprintf("[{\"success\":false,\"error\":{\"code\":-1,\"message\":\"Rescan failed for key with creation "
+ "timestamp %d. There was an error reading a block from time %d, which is after or within %d "
+ "seconds of key creation, and could contain transactions pertaining to the key. As a result, "
+ "transactions and coins using this key may not appear in the wallet. This error could be caused "
+ "by pruning or data corruption (see bitcoind log for details) and could be dealt with by "
+ "downloading and rescanning the relevant blocks (see -reindex and -rescan "
+ "options).\"}},{\"success\":true}]",
+ 0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW));
+ vpwallets.erase(vpwallets.begin());
}
}
@@ -446,7 +444,6 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
// than or equal to key birthday.
BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
{
- CWallet *pwalletMainBackup = ::pwalletMain;
LOCK(cs_main);
// Create two blocks with same timestamp to verify that importwallet rescan
@@ -472,7 +469,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
JSONRPCRequest request;
request.params.setArray();
request.params.push_back("wallet.backup");
- ::pwalletMain = &wallet;
+ vpwallets.insert(vpwallets.begin(), &wallet);
::dumpwallet(request);
}
@@ -484,7 +481,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
JSONRPCRequest request;
request.params.setArray();
request.params.push_back("wallet.backup");
- ::pwalletMain = &wallet;
+ vpwallets[0] = &wallet;
::importwallet(request);
BOOST_CHECK_EQUAL(wallet.mapWallet.size(), 3);
@@ -497,7 +494,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
}
SetMockTime(0);
- ::pwalletMain = pwalletMainBackup;
+ vpwallets.erase(vpwallets.begin());
}
// Check that GetImmatureCredit() returns a newly calculated value instead of
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index bc98435249..02de3cceed 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -35,7 +35,7 @@
#include <boost/algorithm/string/replace.hpp>
#include <boost/thread.hpp>
-CWallet* pwalletMain = NULL;
+std::vector<CWalletRef> vpwallets;
/** Transaction fee set by the user */
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;
@@ -297,7 +297,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase)
{
LOCK(cs_wallet);
- BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
+ for (const MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
{
if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
return false;
@@ -320,7 +320,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
CCrypter crypter;
CKeyingMaterial _vMasterKey;
- BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
+ for (MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
{
if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
return false;
@@ -412,7 +412,7 @@ std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
- BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin)
+ for (const CTxIn& txin : wtx.tx->vin)
{
if (mapTxSpends.count(txin.prevout) <= 1)
continue; // No conflict if zero or one spends
@@ -440,30 +440,40 @@ bool CWallet::Verify()
if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET))
return true;
- uiInterface.InitMessage(_("Verifying wallet..."));
- std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
+ uiInterface.InitMessage(_("Verifying wallet(s)..."));
- std::string strError;
- if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError))
- return InitError(strError);
+ for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
+ if (boost::filesystem::path(walletFile).filename() != walletFile) {
+ 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"));
+ }
- if (GetBoolArg("-salvagewallet", false))
- {
- // Recover readable keypairs:
- CWallet dummyWallet;
- if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter))
+ std::string strError;
+ if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) {
+ return InitError(strError);
+ }
+
+ if (GetBoolArg("-salvagewallet", false)) {
+ // Recover readable keypairs:
+ CWallet dummyWallet;
+ std::string backup_filename;
+ if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter, backup_filename)) {
+ return false;
+ }
+ }
+
+ std::string strWarning;
+ bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError);
+ if (!strWarning.empty()) {
+ InitWarning(strWarning);
+ }
+ if (!dbV) {
+ InitError(strError);
return false;
+ }
}
- std::string strWarning;
- bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError);
- if (!strWarning.empty())
- InitWarning(strWarning);
- if (!dbV)
- {
- InitError(strError);
- return false;
- }
return true;
}
@@ -544,7 +554,7 @@ void CWallet::AddToSpends(const uint256& wtxid)
if (thisTx.IsCoinBase()) // Coinbases don't spend anything!
return;
- BOOST_FOREACH(const CTxIn& txin, thisTx.tx->vin)
+ for (const CTxIn& txin : thisTx.tx->vin)
AddToSpends(txin.prevout, wtxid);
}
@@ -659,7 +669,7 @@ DBErrors CWallet::ReorderTransactions()
}
std::list<CAccountingEntry> acentries;
walletdb.ListAccountCreditDebit("", acentries);
- BOOST_FOREACH(CAccountingEntry& entry, acentries)
+ for (CAccountingEntry& entry : acentries)
{
txByTime.insert(std::make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
}
@@ -689,7 +699,7 @@ DBErrors CWallet::ReorderTransactions()
else
{
int64_t nOrderPosOff = 0;
- BOOST_FOREACH(const int64_t& nOffsetStart, nOrderPosOffsets)
+ for (const int64_t& nOffsetStart : nOrderPosOffsets)
{
if (nOrderPos >= nOffsetStart)
++nOrderPosOff;
@@ -778,7 +788,7 @@ bool CWallet::GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bFo
for (std::map<uint256, CWalletTx>::iterator it = mapWallet.begin();
it != mapWallet.end() && account.vchPubKey.IsValid();
++it)
- BOOST_FOREACH(const CTxOut& txout, (*it).second.tx->vout)
+ for (const CTxOut& txout : (*it).second.tx->vout)
if (txout.scriptPubKey == scriptPubKey) {
bForceNew = true;
break;
@@ -804,7 +814,7 @@ void CWallet::MarkDirty()
{
{
LOCK(cs_wallet);
- BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
+ for (std::pair<const uint256, CWalletTx>& item : mapWallet)
item.second.MarkDirty();
}
}
@@ -922,7 +932,7 @@ bool CWallet::LoadToWallet(const CWalletTx& wtxIn)
wtx.BindWallet(this);
wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0)));
AddToSpends(hash);
- BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin) {
+ for (const CTxIn& txin : wtx.tx->vin) {
if (mapWallet.count(txin.prevout.hash)) {
CWalletTx& prevtx = mapWallet[txin.prevout.hash];
if (prevtx.nIndex == -1 && !prevtx.hashUnset()) {
@@ -954,7 +964,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockI
AssertLockHeld(cs_wallet);
if (pIndex != NULL) {
- BOOST_FOREACH(const CTxIn& txin, tx.vin) {
+ for (const CTxIn& txin : tx.vin) {
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.prevout);
while (range.first != range.second) {
if (range.first->second != tx.GetHash()) {
@@ -1035,7 +1045,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
}
// If a transaction changes 'conflicted' state, that changes the balance
// available of the outputs it spends. So force those to be recomputed
- BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin)
+ for (const CTxIn& txin : wtx.tx->vin)
{
if (mapWallet.count(txin.prevout.hash))
mapWallet[txin.prevout.hash].MarkDirty();
@@ -1096,7 +1106,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
}
// If a transaction changes 'conflicted' state, that changes the balance
// available of the outputs it spends. So force those to be recomputed
- BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin)
+ for (const CTxIn& txin : wtx.tx->vin)
{
if (mapWallet.count(txin.prevout.hash))
mapWallet[txin.prevout.hash].MarkDirty();
@@ -1114,7 +1124,7 @@ void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pin
// If a transaction changes 'conflicted' state, that changes the balance
// available of the outputs it spends. So force those to be
// recomputed, also:
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ for (const CTxIn& txin : tx.vin)
{
if (mapWallet.count(txin.prevout.hash))
mapWallet[txin.prevout.hash].MarkDirty();
@@ -1230,7 +1240,7 @@ CAmount CWallet::GetChange(const CTxOut& txout) const
bool CWallet::IsMine(const CTransaction& tx) const
{
- BOOST_FOREACH(const CTxOut& txout, tx.vout)
+ for (const CTxOut& txout : tx.vout)
if (IsMine(txout))
return true;
return false;
@@ -1244,7 +1254,7 @@ bool CWallet::IsFromMe(const CTransaction& tx) const
CAmount CWallet::GetDebit(const CTransaction& tx, const isminefilter& filter) const
{
CAmount nDebit = 0;
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ for (const CTxIn& txin : tx.vin)
{
nDebit += GetDebit(txin, filter);
if (!MoneyRange(nDebit))
@@ -1257,7 +1267,7 @@ bool CWallet::IsAllFromMe(const CTransaction& tx, const isminefilter& filter) co
{
LOCK(cs_wallet);
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ for (const CTxIn& txin : tx.vin)
{
auto mi = mapWallet.find(txin.prevout.hash);
if (mi == mapWallet.end())
@@ -1277,7 +1287,7 @@ bool CWallet::IsAllFromMe(const CTransaction& tx, const isminefilter& filter) co
CAmount CWallet::GetCredit(const CTransaction& tx, const isminefilter& filter) const
{
CAmount nCredit = 0;
- BOOST_FOREACH(const CTxOut& txout, tx.vout)
+ for (const CTxOut& txout : tx.vout)
{
nCredit += GetCredit(txout, filter);
if (!MoneyRange(nCredit))
@@ -1289,7 +1299,7 @@ CAmount CWallet::GetCredit(const CTransaction& tx, const isminefilter& filter) c
CAmount CWallet::GetChange(const CTransaction& tx) const
{
CAmount nChange = 0;
- BOOST_FOREACH(const CTxOut& txout, tx.vout)
+ for (const CTxOut& txout : tx.vout)
{
nChange += GetChange(txout);
if (!MoneyRange(nChange))
@@ -1463,10 +1473,9 @@ void CWalletTx::GetAmounts(std::list<COutputEntry>& listReceived,
* from or to us. If fUpdate is true, found transactions that already
* exist in the wallet will be updated.
*
- * Returns pointer to the first block in the last contiguous range that was
- * successfully scanned or elided (elided if pIndexStart points at a block
- * before CWallet::nTimeFirstKey). Returns null if there is no such range, or
- * the range doesn't include chainActive.Tip().
+ * Returns null if scan was successful. Otherwise, if a complete rescan was not
+ * possible (due to pruning or corruption), returns pointer to the most recent
+ * block that could not be scanned.
*/
CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
{
@@ -1474,7 +1483,7 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f
const CChainParams& chainParams = Params();
CBlockIndex* pindex = pindexStart;
- CBlockIndex* ret = pindexStart;
+ CBlockIndex* ret = nullptr;
{
LOCK2(cs_main, cs_wallet);
fAbortRescan = false;
@@ -1502,11 +1511,8 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f
for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
AddToWalletIfInvolvingMe(block.vtx[posInBlock], pindex, posInBlock, fUpdate);
}
- if (!ret) {
- ret = pindex;
- }
} else {
- ret = nullptr;
+ ret = pindex;
}
pindex = chainActive.Next(pindex);
}
@@ -1529,7 +1535,7 @@ void CWallet::ReacceptWalletTransactions()
std::map<int64_t, CWalletTx*> mapSorted;
// Sort pending wallet transactions based on their initial wallet insertion order
- BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
+ for (std::pair<const uint256, CWalletTx>& item : mapWallet)
{
const uint256& wtxid = item.first;
CWalletTx& wtx = item.second;
@@ -1543,7 +1549,7 @@ void CWallet::ReacceptWalletTransactions()
}
// Try to add wallet transactions to memory pool
- BOOST_FOREACH(PAIRTYPE(const int64_t, CWalletTx*)& item, mapSorted)
+ for (std::pair<const int64_t, CWalletTx*>& item : mapSorted)
{
CWalletTx& wtx = *(item.second);
@@ -1771,7 +1777,7 @@ bool CWalletTx::IsTrusted() const
return false;
// Trusted if all inputs are from us and are in the mempool:
- BOOST_FOREACH(const CTxIn& txin, tx->vin)
+ for (const CTxIn& txin : tx->vin)
{
// Transactions not sent by us: not trusted
const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash);
@@ -1800,7 +1806,7 @@ std::vector<uint256> CWallet::ResendWalletTransactionsBefore(int64_t nTime, CCon
LOCK(cs_wallet);
// Sort them in chronological order
std::multimap<unsigned int, CWalletTx*> mapSorted;
- BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
+ for (std::pair<const uint256, CWalletTx>& item : mapWallet)
{
CWalletTx& wtx = item.second;
// Don't rebroadcast if newer than nTime:
@@ -1808,7 +1814,7 @@ std::vector<uint256> CWallet::ResendWalletTransactionsBefore(int64_t nTime, CCon
continue;
mapSorted.insert(std::make_pair(wtx.nTimeReceived, &wtx));
}
- BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
+ for (std::pair<const unsigned int, CWalletTx*>& item : mapSorted)
{
CWalletTx& wtx = *item.second;
if (wtx.RelayWalletTransaction(connman))
@@ -2232,7 +2238,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin
random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
- BOOST_FOREACH(const COutput &output, vCoins)
+ for (const COutput &output : vCoins)
{
if (!output.fSpendable)
continue;
@@ -2332,7 +2338,7 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
// coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs)
{
- BOOST_FOREACH(const COutput& out, vCoins)
+ for (const COutput& out : vCoins)
{
if (!out.fSpendable)
continue;
@@ -2349,7 +2355,7 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
std::vector<COutPoint> vPresetInputs;
if (coinControl)
coinControl->ListSelected(vPresetInputs);
- BOOST_FOREACH(const COutPoint& outpoint, vPresetInputs)
+ for (const COutPoint& outpoint : vPresetInputs)
{
std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash);
if (it != mapWallet.end())
@@ -2418,7 +2424,7 @@ bool CWallet::SignTransaction(CMutableTransaction &tx)
return true;
}
-bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool overrideEstimatedFeeRate, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, bool keepReserveKey, const CTxDestination& destChange)
+bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl coinControl, bool keepReserveKey)
{
std::vector<CRecipient> vecSend;
@@ -2430,14 +2436,9 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool ov
vecSend.push_back(recipient);
}
- CCoinControl coinControl;
- coinControl.destChange = destChange;
coinControl.fAllowOtherInputs = true;
- coinControl.fAllowWatchOnly = includeWatching;
- coinControl.fOverrideFeeRate = overrideEstimatedFeeRate;
- coinControl.nFeeRate = specificFeeRate;
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ for (const CTxIn& txin : tx.vin)
coinControl.Select(txin.prevout);
CReserveKey reservekey(this);
@@ -2453,7 +2454,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool ov
tx.vout[idx].nValue = wtx.tx->vout[idx].nValue;
// Add new txins (keeping original txin scriptSig/order)
- BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin)
+ for (const CTxIn& txin : wtx.tx->vin)
{
if (!coinControl.IsSelected(txin.prevout))
{
@@ -2694,9 +2695,10 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
// and in the spirit of "smallest possible change from prior
// behavior."
bool rbf = coinControl ? coinControl->signalRbf : fWalletRbf;
+ const uint32_t nSequence = rbf ? MAX_BIP125_RBF_SEQUENCE : (std::numeric_limits<unsigned int>::max() - 1);
for (const auto& coin : setCoins)
txNew.vin.push_back(CTxIn(coin.outpoint,CScript(),
- std::numeric_limits<unsigned int>::max() - (rbf ? 2 : 1)));
+ nSequence));
// Fill in dummy signatures for fee calculation.
if (!DummySignTx(txNew, setCoins)) {
@@ -2836,7 +2838,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon
AddToWallet(wtxNew);
// Notify that old coins are spent
- BOOST_FOREACH(const CTxIn& txin, wtxNew.tx->vin)
+ for (const CTxIn& txin : wtxNew.tx->vin)
{
CWalletTx &coin = mapWallet[txin.prevout.hash];
coin.BindWallet(this);
@@ -2875,8 +2877,9 @@ bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry)
bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB *pwalletdb)
{
- if (!pwalletdb->WriteAccountingEntry_Backend(acentry))
+ if (!pwalletdb->WriteAccountingEntry(++nAccountingEntryNumber, acentry)) {
return false;
+ }
laccentries.push_back(acentry);
CAccountingEntry & entry = laccentries.back();
@@ -2890,12 +2893,12 @@ CAmount CWallet::GetRequiredFee(unsigned int nTxBytes)
return std::max(minTxFee.GetFee(nTxBytes), ::minRelayTxFee.GetFee(nTxBytes));
}
-CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, bool ignoreUserSetFee)
+CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, bool ignoreGlobalPayTxFee)
{
// payTxFee is the user-set global for desired feerate
CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes);
// User didn't set: use -txconfirmtarget to estimate...
- if (nFeeNeeded == 0 || ignoreUserSetFee) {
+ if (nFeeNeeded == 0 || ignoreGlobalPayTxFee) {
int estimateFoundTarget = nConfirmTarget;
nFeeNeeded = estimator.estimateSmartFee(nConfirmTarget, &estimateFoundTarget, pool).GetFee(nTxBytes);
// ... unless we don't have enough mempool data for estimatefee, then use fallbackFee
@@ -3014,7 +3017,7 @@ bool CWallet::DelAddressBook(const CTxDestination& address)
// Delete destdata tuples associated with address
std::string strAddress = CBitcoinAddress(address).ToString();
- BOOST_FOREACH(const PAIRTYPE(std::string, std::string) &item, mapAddressBook[address].destdata)
+ for (const std::pair<std::string, std::string> &item : mapAddressBook[address].destdata)
{
CWalletDB(*dbw).EraseDestData(strAddress, item.first);
}
@@ -3059,7 +3062,7 @@ bool CWallet::NewKeyPool()
{
LOCK(cs_wallet);
CWalletDB walletdb(*dbw);
- BOOST_FOREACH(int64_t nIndex, setKeyPool)
+ for (int64_t nIndex : setKeyPool)
walletdb.ErasePool(nIndex);
setKeyPool.clear();
@@ -3196,10 +3199,10 @@ void CWallet::ReturnKey(int64_t nIndex)
bool CWallet::GetKeyFromPool(CPubKey& result, bool internal)
{
- int64_t nIndex = 0;
CKeyPool keypool;
{
LOCK(cs_wallet);
+ int64_t nIndex = 0;
ReserveKeyFromKeyPool(nIndex, keypool, internal);
if (nIndex == -1)
{
@@ -3261,9 +3264,9 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
{
LOCK(cs_wallet);
- BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
+ for (const auto& walletEntry : mapWallet)
{
- CWalletTx *pcoin = &walletEntry.second;
+ const CWalletTx *pcoin = &walletEntry.second;
if (!pcoin->IsTrusted())
continue;
@@ -3301,15 +3304,15 @@ std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
std::set< std::set<CTxDestination> > groupings;
std::set<CTxDestination> grouping;
- BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
+ for (const auto& walletEntry : mapWallet)
{
- CWalletTx *pcoin = &walletEntry.second;
+ const CWalletTx *pcoin = &walletEntry.second;
if (pcoin->tx->vin.size() > 0)
{
bool any_mine = false;
// group all input addresses with each other
- BOOST_FOREACH(CTxIn txin, pcoin->tx->vin)
+ for (CTxIn txin : pcoin->tx->vin)
{
CTxDestination address;
if(!IsMine(txin)) /* If this input isn't mine, ignore it */
@@ -3323,7 +3326,7 @@ std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
// group change with input addresses
if (any_mine)
{
- BOOST_FOREACH(CTxOut txout, pcoin->tx->vout)
+ for (CTxOut txout : pcoin->tx->vout)
if (IsChange(txout))
{
CTxDestination txoutAddr;
@@ -3354,18 +3357,18 @@ std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
std::set< std::set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
std::map< CTxDestination, std::set<CTxDestination>* > setmap; // map addresses to the unique group containing it
- BOOST_FOREACH(std::set<CTxDestination> _grouping, groupings)
+ for (std::set<CTxDestination> _grouping : groupings)
{
// make a set of all the groups hit by this new group
std::set< std::set<CTxDestination>* > hits;
std::map< CTxDestination, std::set<CTxDestination>* >::iterator it;
- BOOST_FOREACH(CTxDestination address, _grouping)
+ for (CTxDestination address : _grouping)
if ((it = setmap.find(address)) != setmap.end())
hits.insert((*it).second);
// merge all hit groups into a new single group and delete old groups
std::set<CTxDestination>* merged = new std::set<CTxDestination>(_grouping);
- BOOST_FOREACH(std::set<CTxDestination>* hit, hits)
+ for (std::set<CTxDestination>* hit : hits)
{
merged->insert(hit->begin(), hit->end());
uniqueGroupings.erase(hit);
@@ -3374,12 +3377,12 @@ std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
uniqueGroupings.insert(merged);
// update setmap
- BOOST_FOREACH(CTxDestination element, *merged)
+ for (CTxDestination element : *merged)
setmap[element] = merged;
}
std::set< std::set<CTxDestination> > ret;
- BOOST_FOREACH(std::set<CTxDestination>* uniqueGrouping, uniqueGroupings)
+ for (std::set<CTxDestination>* uniqueGrouping : uniqueGroupings)
{
ret.insert(*uniqueGrouping);
delete uniqueGrouping;
@@ -3392,7 +3395,7 @@ std::set<CTxDestination> CWallet::GetAccountAddresses(const std::string& strAcco
{
LOCK(cs_wallet);
std::set<CTxDestination> result;
- BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook)
+ for (const std::pair<CTxDestination, CAddressBookData>& item : mapAddressBook)
{
const CTxDestination& address = item.first;
const std::string& strName = item.second.name;
@@ -3442,7 +3445,7 @@ void CWallet::GetAllReserveKeys(std::set<CKeyID>& setAddress) const
CWalletDB walletdb(*dbw);
LOCK2(cs_main, cs_wallet);
- BOOST_FOREACH(const int64_t& id, setKeyPool)
+ for (const int64_t& id : setKeyPool)
{
CKeyPool keypool;
if (!walletdb.ReadPool(id, keypool))
@@ -3517,7 +3520,7 @@ public:
std::vector<CTxDestination> vDest;
int nRequired;
if (ExtractDestinations(script, type, vDest, nRequired)) {
- BOOST_FOREACH(const CTxDestination &dest, vDest)
+ for (const CTxDestination &dest : vDest)
boost::apply_visitor(*this, dest);
}
}
@@ -3552,7 +3555,7 @@ void CWallet::GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) c
std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
std::set<CKeyID> setKeys;
GetKeys(setKeys);
- BOOST_FOREACH(const CKeyID &keyid, setKeys) {
+ for (const CKeyID &keyid : setKeys) {
if (mapKeyBirth.count(keyid) == 0)
mapKeyFirstBlock[keyid] = pindexMax;
}
@@ -3571,10 +3574,10 @@ void CWallet::GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) c
if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) {
// ... which are already in a block
int nHeight = blit->second->nHeight;
- BOOST_FOREACH(const CTxOut &txout, wtx.tx->vout) {
+ for (const CTxOut &txout : wtx.tx->vout) {
// iterate over all their outputs
CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey);
- BOOST_FOREACH(const CKeyID &keyid, vAffected) {
+ for (const CKeyID &keyid : vAffected) {
// ... and all their affected keys
std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
@@ -3888,14 +3891,14 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
walletInstance->ScanForWalletTransactions(pindexRescan, true);
LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
walletInstance->SetBestChain(chainActive.GetLocator());
- CWalletDB::IncrementUpdateCounter();
+ walletInstance->dbw->IncrementUpdateCounter();
// Restore wallet transaction metadata after -zapwallettxes=1
if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")
{
CWalletDB walletdb(*walletInstance->dbw);
- BOOST_FOREACH(const CWalletTx& wtxOld, vWtx)
+ for (const CWalletTx& wtxOld : vWtx)
{
uint256 hash = wtxOld.GetHash();
std::map<uint256, CWalletTx>::iterator mi = walletInstance->mapWallet.find(hash);
@@ -3930,24 +3933,17 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
bool CWallet::InitLoadWallet()
{
if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
- pwalletMain = NULL;
LogPrintf("Wallet disabled!\n");
return true;
}
- std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
-
- if (boost::filesystem::path(walletFile).filename() != walletFile) {
- 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;
+ for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
+ CWallet * const pwallet = CreateWalletFromFile(walletFile);
+ if (!pwallet) {
+ return false;
+ }
+ vpwallets.push_back(pwallet);
}
- pwalletMain = pwallet;
return true;
}
@@ -3968,6 +3964,9 @@ void CWallet::postInitProcess(CScheduler& scheduler)
bool CWallet::ParameterInteraction()
{
+ SoftSetArg("-wallet", DEFAULT_WALLET_DAT);
+ const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1;
+
if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET))
return true;
@@ -3976,15 +3975,27 @@ bool CWallet::ParameterInteraction()
}
if (GetBoolArg("-salvagewallet", false) && SoftSetBoolArg("-rescan", true)) {
+ if (is_multiwallet) {
+ return InitError(strprintf("%s is only allowed with a single wallet file", "-salvagewallet"));
+ }
// Rewrite just private keys: rescan to find transactions
LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__);
}
// -zapwallettx implies a rescan
if (GetBoolArg("-zapwallettxes", false) && SoftSetBoolArg("-rescan", true)) {
+ if (is_multiwallet) {
+ return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes"));
+ }
LogPrintf("%s: parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1\n", __func__);
}
+ if (is_multiwallet) {
+ if (GetBoolArg("-upgradewallet", false)) {
+ return InitError(strprintf("%s is only allowed with a single wallet file", "-upgradewallet"));
+ }
+ }
+
if (GetBoolArg("-sysperms", false))
return InitError("-sysperms is not allowed in combination with enabled wallet functionality");
if (GetArg("-prune", 0) && GetBoolArg("-rescan", false))
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 11b2f7a663..6c6eb69180 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -29,7 +29,8 @@
#include <utility>
#include <vector>
-extern CWallet* pwalletMain;
+typedef CWallet* CWalletRef;
+extern std::vector<CWalletRef> vpwallets;
/**
* Settings
@@ -136,10 +137,7 @@ public:
std::string name;
std::string purpose;
- CAddressBookData()
- {
- purpose = "unknown";
- }
+ CAddressBookData() : purpose("unknown") {}
typedef std::map<std::string, std::string> StringMap;
StringMap destdata;
@@ -785,6 +783,7 @@ public:
nMasterKeyMaxID = 0;
pwalletdbEncryption = NULL;
nOrderPosNext = 0;
+ nAccountingEntryNumber = 0;
nNextResend = 0;
nLastResend = 0;
nTimeFirstKey = 0;
@@ -802,6 +801,7 @@ public:
TxItems wtxOrdered;
int64_t nOrderPosNext;
+ uint64_t nAccountingEntryNumber;
std::map<uint256, int> mapRequestCount;
std::map<CTxDestination, CAddressBookData> mapAddressBook;
@@ -935,7 +935,7 @@ public:
* Insert additional inputs into the transaction by
* calling CreateTransaction();
*/
- bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool overrideEstimatedFeeRate, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, bool keepReserveKey = true, const CTxDestination& destChange = CNoDestination());
+ bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl, bool keepReserveKey = true);
bool SignTransaction(CMutableTransaction& tx);
/**
@@ -959,7 +959,7 @@ public:
* Estimate the minimum fee considering user set parameters
* and the required fee
*/
- static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, bool ignoreUserSetFee = false);
+ static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, bool ignoreGlobalPayTxFee = false);
/**
* Return the minimum required fee taking into account the
* floating relay fee and user set minimum transaction fee
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 342c797dd3..eca6706c06 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -18,63 +18,50 @@
#include <atomic>
-#include <boost/version.hpp>
#include <boost/foreach.hpp>
#include <boost/thread.hpp>
-static uint64_t nAccountingEntryNumber = 0;
-
-static std::atomic<unsigned int> nWalletDBUpdateCounter;
-
//
// CWalletDB
//
bool CWalletDB::WriteName(const std::string& strAddress, const std::string& strName)
{
- nWalletDBUpdateCounter++;
- return batch.Write(std::make_pair(std::string("name"), strAddress), strName);
+ return WriteIC(std::make_pair(std::string("name"), strAddress), strName);
}
bool CWalletDB::EraseName(const std::string& strAddress)
{
// This should only be used for sending addresses, never for receiving addresses,
// receiving addresses must always have an address book entry if they're not change return.
- nWalletDBUpdateCounter++;
- return batch.Erase(std::make_pair(std::string("name"), strAddress));
+ return EraseIC(std::make_pair(std::string("name"), strAddress));
}
bool CWalletDB::WritePurpose(const std::string& strAddress, const std::string& strPurpose)
{
- nWalletDBUpdateCounter++;
- return batch.Write(std::make_pair(std::string("purpose"), strAddress), strPurpose);
+ return WriteIC(std::make_pair(std::string("purpose"), strAddress), strPurpose);
}
bool CWalletDB::ErasePurpose(const std::string& strPurpose)
{
- nWalletDBUpdateCounter++;
- return batch.Erase(std::make_pair(std::string("purpose"), strPurpose));
+ return EraseIC(std::make_pair(std::string("purpose"), strPurpose));
}
bool CWalletDB::WriteTx(const CWalletTx& wtx)
{
- nWalletDBUpdateCounter++;
- return batch.Write(std::make_pair(std::string("tx"), wtx.GetHash()), wtx);
+ return WriteIC(std::make_pair(std::string("tx"), wtx.GetHash()), wtx);
}
bool CWalletDB::EraseTx(uint256 hash)
{
- nWalletDBUpdateCounter++;
- return batch.Erase(std::make_pair(std::string("tx"), hash));
+ return EraseIC(std::make_pair(std::string("tx"), hash));
}
bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
{
- nWalletDBUpdateCounter++;
-
- if (!batch.Write(std::make_pair(std::string("keymeta"), vchPubKey),
- keyMeta, false))
+ if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta, false)) {
return false;
+ }
// hash pubkey/privkey to accelerate wallet load
std::vector<unsigned char> vchKey;
@@ -82,7 +69,7 @@ bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, c
vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
- return batch.Write(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false);
+ return WriteIC(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false);
}
bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,
@@ -90,55 +77,53 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,
const CKeyMetadata &keyMeta)
{
const bool fEraseUnencryptedKey = true;
- nWalletDBUpdateCounter++;
- if (!batch.Write(std::make_pair(std::string("keymeta"), vchPubKey),
- keyMeta))
+ if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) {
return false;
+ }
- if (!batch.Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false))
+ if (!WriteIC(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) {
return false;
+ }
if (fEraseUnencryptedKey)
{
- batch.Erase(std::make_pair(std::string("key"), vchPubKey));
- batch.Erase(std::make_pair(std::string("wkey"), vchPubKey));
+ EraseIC(std::make_pair(std::string("key"), vchPubKey));
+ EraseIC(std::make_pair(std::string("wkey"), vchPubKey));
}
+
return true;
}
bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
{
- nWalletDBUpdateCounter++;
- return batch.Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
+ return WriteIC(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
}
bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript)
{
- nWalletDBUpdateCounter++;
- return batch.Write(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false);
+ return WriteIC(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false);
}
bool CWalletDB::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta)
{
- nWalletDBUpdateCounter++;
- if (!batch.Write(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta))
+ if (!WriteIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta)) {
return false;
- return batch.Write(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1');
+ }
+ return WriteIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1');
}
bool CWalletDB::EraseWatchOnly(const CScript &dest)
{
- nWalletDBUpdateCounter++;
- if (!batch.Erase(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest))))
+ if (!EraseIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)))) {
return false;
- return batch.Erase(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)));
+ }
+ return EraseIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)));
}
bool CWalletDB::WriteBestBlock(const CBlockLocator& locator)
{
- nWalletDBUpdateCounter++;
- batch.Write(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
- return batch.Write(std::string("bestblock_nomerkle"), locator);
+ WriteIC(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
+ return WriteIC(std::string("bestblock_nomerkle"), locator);
}
bool CWalletDB::ReadBestBlock(CBlockLocator& locator)
@@ -149,14 +134,12 @@ bool CWalletDB::ReadBestBlock(CBlockLocator& locator)
bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext)
{
- nWalletDBUpdateCounter++;
- return batch.Write(std::string("orderposnext"), nOrderPosNext);
+ return WriteIC(std::string("orderposnext"), nOrderPosNext);
}
bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey)
{
- nWalletDBUpdateCounter++;
- return batch.Write(std::string("defaultkey"), vchPubKey);
+ return WriteIC(std::string("defaultkey"), vchPubKey);
}
bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool)
@@ -166,19 +149,17 @@ bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool)
bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool)
{
- nWalletDBUpdateCounter++;
- return batch.Write(std::make_pair(std::string("pool"), nPool), keypool);
+ return WriteIC(std::make_pair(std::string("pool"), nPool), keypool);
}
bool CWalletDB::ErasePool(int64_t nPool)
{
- nWalletDBUpdateCounter++;
- return batch.Erase(std::make_pair(std::string("pool"), nPool));
+ return EraseIC(std::make_pair(std::string("pool"), nPool));
}
bool CWalletDB::WriteMinVersion(int nVersion)
{
- return batch.Write(std::string("minversion"), nVersion);
+ return WriteIC(std::string("minversion"), nVersion);
}
bool CWalletDB::ReadAccount(const std::string& strAccount, CAccount& account)
@@ -189,17 +170,12 @@ bool CWalletDB::ReadAccount(const std::string& strAccount, CAccount& account)
bool CWalletDB::WriteAccount(const std::string& strAccount, const CAccount& account)
{
- return batch.Write(std::make_pair(std::string("acc"), strAccount), account);
+ return WriteIC(std::make_pair(std::string("acc"), strAccount), account);
}
bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry)
{
- return batch.Write(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry);
-}
-
-bool CWalletDB::WriteAccountingEntry_Backend(const CAccountingEntry& acentry)
-{
- return WriteAccountingEntry(++nAccountingEntryNumber, acentry);
+ return WriteIC(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry);
}
CAmount CWalletDB::GetAccountCreditDebit(const std::string& strAccount)
@@ -208,7 +184,7 @@ CAmount CWalletDB::GetAccountCreditDebit(const std::string& strAccount)
ListAccountCreditDebit(strAccount, entries);
CAmount nCreditDebit = 0;
- BOOST_FOREACH (const CAccountingEntry& entry, entries)
+ for (const CAccountingEntry& entry : entries)
nCreditDebit += entry.nCreditDebit;
return nCreditDebit;
@@ -338,8 +314,9 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
ssKey >> strAccount;
uint64_t nNumber;
ssKey >> nNumber;
- if (nNumber > nAccountingEntryNumber)
- nAccountingEntryNumber = nNumber;
+ if (nNumber > pwallet->nAccountingEntryNumber) {
+ pwallet->nAccountingEntryNumber = nNumber;
+ }
if (!wss.fAnyUnordered)
{
@@ -635,7 +612,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
if ((wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta)
pwallet->UpdateTimeFirstKey(1);
- BOOST_FOREACH(uint256 hash, wss.vWalletUpgrade)
+ for (uint256 hash : wss.vWalletUpgrade)
WriteTx(pwallet->mapWallet[hash]);
// Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
@@ -650,7 +627,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
pwallet->laccentries.clear();
ListAccountCreditDebit("*", pwallet->laccentries);
- BOOST_FOREACH(CAccountingEntry& entry, pwallet->laccentries) {
+ for (CAccountingEntry& entry : pwallet->laccentries) {
pwallet->wtxOrdered.insert(make_pair(entry.nOrderPos, CWallet::TxPair((CWalletTx*)0, &entry)));
}
@@ -736,7 +713,7 @@ DBErrors CWalletDB::ZapSelectTx(std::vector<uint256>& vTxHashIn, std::vector<uin
// erase each matching wallet TX
bool delerror = false;
std::vector<uint256>::iterator it = vTxHashIn.begin();
- BOOST_FOREACH (uint256 hash, vTxHash) {
+ for (uint256 hash : vTxHash) {
while (it < vTxHashIn.end() && (*it) < hash) {
it++;
}
@@ -767,7 +744,7 @@ DBErrors CWalletDB::ZapWalletTx(std::vector<CWalletTx>& vWtx)
return err;
// erase each wallet TX
- BOOST_FOREACH (uint256& hash, vTxHash) {
+ for (uint256& hash : vTxHash) {
if (!EraseTx(hash))
return DB_CORRUPT;
}
@@ -785,38 +762,39 @@ void MaybeCompactWalletDB()
return;
}
- static unsigned int nLastSeen = CWalletDB::GetUpdateCounter();
- static unsigned int nLastFlushed = CWalletDB::GetUpdateCounter();
- static int64_t nLastWalletUpdate = GetTime();
+ for (CWalletRef pwallet : vpwallets) {
+ CWalletDBWrapper& dbh = pwallet->GetDBHandle();
- if (nLastSeen != CWalletDB::GetUpdateCounter())
- {
- nLastSeen = CWalletDB::GetUpdateCounter();
- nLastWalletUpdate = GetTime();
- }
+ unsigned int nUpdateCounter = dbh.nUpdateCounter;
- if (nLastFlushed != CWalletDB::GetUpdateCounter() && GetTime() - nLastWalletUpdate >= 2)
- {
- if (CDB::PeriodicFlush(pwalletMain->GetDBHandle())) {
- nLastFlushed = CWalletDB::GetUpdateCounter();
+ if (dbh.nLastSeen != nUpdateCounter) {
+ dbh.nLastSeen = nUpdateCounter;
+ dbh.nLastWalletUpdate = GetTime();
+ }
+
+ if (dbh.nLastFlushed != nUpdateCounter && GetTime() - dbh.nLastWalletUpdate >= 2) {
+ if (CDB::PeriodicFlush(dbh)) {
+ dbh.nLastFlushed = nUpdateCounter;
+ }
}
}
+
fOneThread = false;
}
//
// Try to (very carefully!) recover wallet file if there is a problem.
//
-bool CWalletDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue))
+bool CWalletDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename)
{
- return CDB::Recover(filename, callbackDataIn, recoverKVcallback);
+ return CDB::Recover(filename, callbackDataIn, recoverKVcallback, out_backup_filename);
}
-bool CWalletDB::Recover(const std::string& filename)
+bool CWalletDB::Recover(const std::string& filename, std::string& out_backup_filename)
{
// recover without a key filter callback
// results in recovering all record types
- return CWalletDB::Recover(filename, NULL, NULL);
+ return CWalletDB::Recover(filename, NULL, NULL, out_backup_filename);
}
bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue)
@@ -849,36 +827,23 @@ bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const fs::path&
bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr)
{
- return CDB::VerifyDatabaseFile(walletFile, dataDir, errorStr, warningStr, CWalletDB::Recover);
+ return CDB::VerifyDatabaseFile(walletFile, dataDir, warningStr, errorStr, CWalletDB::Recover);
}
bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
{
- nWalletDBUpdateCounter++;
- return batch.Write(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
+ return WriteIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
}
bool CWalletDB::EraseDestData(const std::string &address, const std::string &key)
{
- nWalletDBUpdateCounter++;
- return batch.Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
+ return EraseIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
}
bool CWalletDB::WriteHDChain(const CHDChain& chain)
{
- nWalletDBUpdateCounter++;
- return batch.Write(std::string("hdchain"), chain);
-}
-
-void CWalletDB::IncrementUpdateCounter()
-{
- nWalletDBUpdateCounter++;
-}
-
-unsigned int CWalletDB::GetUpdateCounter()
-{
- return nWalletDBUpdateCounter;
+ return WriteIC(std::string("hdchain"), chain);
}
bool CWalletDB::TxnBegin()
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index cd9fe279c5..d78f143ebd 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -140,9 +140,31 @@ public:
*/
class CWalletDB
{
+private:
+ template <typename K, typename T>
+ bool WriteIC(const K& key, const T& value, bool fOverwrite = true)
+ {
+ if (!batch.Write(key, value, fOverwrite)) {
+ return false;
+ }
+ m_dbw.IncrementUpdateCounter();
+ return true;
+ }
+
+ template <typename K>
+ bool EraseIC(const K& key)
+ {
+ if (!batch.Erase(key)) {
+ return false;
+ }
+ m_dbw.IncrementUpdateCounter();
+ return true;
+ }
+
public:
CWalletDB(CWalletDBWrapper& dbw, const char* pszMode = "r+", bool _fFlushOnClose = true) :
- batch(dbw, pszMode, _fFlushOnClose)
+ batch(dbw, pszMode, _fFlushOnClose),
+ m_dbw(dbw)
{
}
@@ -180,7 +202,6 @@ public:
/// This writes directly to the database, and will not update the CWallet's cached accounting entries!
/// Use wallet.AddAccountingEntry instead, to write *and* update its caches.
bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry);
- bool WriteAccountingEntry_Backend(const CAccountingEntry& acentry);
bool ReadAccount(const std::string& strAccount, CAccount& account);
bool WriteAccount(const std::string& strAccount, const CAccount& account);
@@ -197,9 +218,9 @@ public:
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut);
/* Try to (very carefully!) recover wallet database (with a possible key type filter) */
- static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue));
+ static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename);
/* Recover convenience-function to bypass the key filter callback, called when verify fails, recovers everything */
- static bool Recover(const std::string& filename);
+ static bool Recover(const std::string& filename, std::string& out_backup_filename);
/* Recover filter (used as callback), will only let keys (cryptographical keys) as KV/key-type pass through */
static bool RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue);
/* Function to determine if a certain KV/key-type is a key (cryptographical key) type */
@@ -212,9 +233,6 @@ public:
//! write the hdchain model (external chain child index counter)
bool WriteHDChain(const CHDChain& chain);
- static void IncrementUpdateCounter();
- static unsigned int GetUpdateCounter();
-
//! Begin a new transaction
bool TxnBegin();
//! Commit current transaction
@@ -227,6 +245,7 @@ public:
bool WriteVersion(int nVersion);
private:
CDB batch;
+ CWalletDBWrapper& m_dbw;
CWalletDB(const CWalletDB&);
void operator=(const CWalletDB&);