diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/chainparams.cpp | 2 | ||||
-rw-r--r-- | src/index/txindex.cpp | 4 | ||||
-rw-r--r-- | src/index/txindex.h | 2 | ||||
-rw-r--r-- | src/init.cpp | 2 | ||||
-rw-r--r-- | src/net.cpp | 2 | ||||
-rw-r--r-- | src/net_processing.cpp | 4 | ||||
-rw-r--r-- | src/qt/addresstablemodel.cpp | 2 | ||||
-rw-r--r-- | src/qt/addresstablemodel.h | 6 | ||||
-rw-r--r-- | src/qt/paymentserver.cpp | 2 | ||||
-rw-r--r-- | src/qt/rpcconsole.cpp | 7 | ||||
-rw-r--r-- | src/qt/rpcconsole.h | 18 | ||||
-rw-r--r-- | src/rpc/blockchain.cpp | 2 | ||||
-rw-r--r-- | src/timedata.cpp | 4 | ||||
-rw-r--r-- | src/validation.cpp | 18 | ||||
-rw-r--r-- | src/validationinterface.cpp | 12 | ||||
-rw-r--r-- | src/validationinterface.h | 15 | ||||
-rw-r--r-- | src/wallet/coinselection.cpp | 4 | ||||
-rw-r--r-- | src/wallet/rpcwallet.cpp | 15 | ||||
-rw-r--r-- | src/wallet/wallet.cpp | 39 | ||||
-rw-r--r-- | src/wallet/wallet.h | 17 |
20 files changed, 92 insertions, 85 deletions
diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 121d95af90..71762158f0 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -173,7 +173,7 @@ public: // Data as of block 0000000000000000002d6cca6761c99b3c2e936f9a0e304b7c7651a993f461de (height 506081). 1516903077, // * UNIX timestamp of last known number of transactions 295363220, // * total number of transactions between genesis and that timestamp - // (the tx=... number in the SetBestChain debug.log lines) + // (the tx=... number in the ChainStateFlushed debug.log lines) 3.5 // * estimated number of transactions per second after that timestamp }; diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp index 2a661f0330..0bb553ee6a 100644 --- a/src/index/txindex.cpp +++ b/src/index/txindex.cpp @@ -192,7 +192,7 @@ void TxIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const C } } -void TxIndex::SetBestChain(const CBlockLocator& locator) +void TxIndex::ChainStateFlushed(const CBlockLocator& locator) { if (!m_synced) { return; @@ -211,7 +211,7 @@ void TxIndex::SetBestChain(const CBlockLocator& locator) return; } - // This checks that SetBestChain callbacks are received after BlockConnected. The check may fail + // This checks that ChainStateFlushed callbacks are received after BlockConnected. The check may fail // immediately after the the sync thread catches up and sets m_synced. Consider the case where // there is a reorg and the blocks on the stale branch are in the ValidationInterface queue // backlog even after the sync thread has caught up to the new chain tip. In this unlikely diff --git a/src/index/txindex.h b/src/index/txindex.h index ac746de05b..4937bd64e9 100644 --- a/src/index/txindex.h +++ b/src/index/txindex.h @@ -55,7 +55,7 @@ protected: void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex, const std::vector<CTransactionRef>& txn_conflicted) override; - void SetBestChain(const CBlockLocator& locator) override; + void ChainStateFlushed(const CBlockLocator& locator) override; public: /// Constructs the TxIndex, which becomes available to be queried. diff --git a/src/init.cpp b/src/init.cpp index 6423d87026..52b3ba19a5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -242,7 +242,7 @@ void Shutdown() fFeeEstimatesInitialized = false; } - // FlushStateToDisk generates a SetBestChain callback, which we should avoid missing + // FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing if (pcoinsTip != nullptr) { FlushStateToDisk(); } diff --git a/src/net.cpp b/src/net.cpp index cd076c1ce2..0a1e268822 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -395,7 +395,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo if (Lookup(pszDest, resolved, default_port, fNameLookup && !HaveNameProxy(), 256) && !resolved.empty()) { addrConnect = CAddress(resolved[GetRand(resolved.size())], NODE_NONE); if (!addrConnect.IsValid()) { - LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s", addrConnect.ToString(), pszDest); + LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s\n", addrConnect.ToString(), pszDest); return nullptr; } // It is possible that we already have a connection to the IP/port pszDest resolved to. diff --git a/src/net_processing.cpp b/src/net_processing.cpp index ee4e9e61bc..cc819a01c3 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -2059,7 +2059,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr const CBlockIndex* pindex = LookupBlockIndex(req.blockhash); if (!pindex || !(pindex->nStatus & BLOCK_HAVE_DATA)) { - LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block we don't have", pfrom->GetId()); + LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block we don't have\n", pfrom->GetId()); return true; } @@ -2071,7 +2071,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // might maliciously send lots of getblocktxn requests to trigger // expensive disk reads, because it will require the peer to // actually receive all the data read from disk over the network. - LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep", pfrom->GetId(), MAX_BLOCKTXN_DEPTH); + LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep\n", pfrom->GetId(), MAX_BLOCKTXN_DEPTH); CInv inv; inv.type = State(pfrom->GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK; inv.hash = req.blockhash; diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index f38e864b48..25b615e6f8 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -159,7 +159,7 @@ public: }; AddressTableModel::AddressTableModel(WalletModel *parent) : - QAbstractTableModel(parent),walletModel(parent),priv(0) + QAbstractTableModel(parent), walletModel(parent) { columns << tr("Label") << tr("Address"); priv = new AddressTablePriv(this); diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h index 979f861fea..6e1b53b049 100644 --- a/src/qt/addresstablemodel.h +++ b/src/qt/addresstablemodel.h @@ -83,10 +83,10 @@ public: OutputType GetDefaultAddressType() const; private: - WalletModel *walletModel; - AddressTablePriv *priv; + WalletModel* const walletModel; + AddressTablePriv *priv = nullptr; QStringList columns; - EditStatus editStatus; + EditStatus editStatus = OK; /** Look up address book data given an address string. */ bool getAddressData(const QString &address, std::string* name, std::string* purpose) const; diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 70cdb3361c..59bb5d5bb6 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -648,7 +648,7 @@ void PaymentServer::fetchPaymentACK(WalletModel* walletModel, const SendCoinsRec // use for change. Despite an actual payment and not change, this is a close match: // it's the output type we use subject to privacy issues, but not restricted by what // other software supports. - const OutputType change_type = walletModel->wallet().getDefaultChangeType() != OutputType::NONE ? walletModel->wallet().getDefaultChangeType() : walletModel->wallet().getDefaultAddressType(); + const OutputType change_type = walletModel->wallet().getDefaultChangeType() != OutputType::CHANGE_AUTO ? walletModel->wallet().getDefaultChangeType() : walletModel->wallet().getDefaultAddressType(); walletModel->wallet().learnRelatedScripts(newKey, change_type); CTxDestination dest = GetDestinationForKey(newKey, change_type); std::string label = tr("Refund from %1").arg(recipient.authenticatedMerchant).toStdString(); diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 5122bab36f..7924840d0b 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -455,12 +455,7 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty QWidget(parent), m_node(node), ui(new Ui::RPCConsole), - clientModel(0), - historyPtr(0), - platformStyle(_platformStyle), - peersTableContextMenu(0), - banTableContextMenu(0), - consoleFontSize(0) + platformStyle(_platformStyle) { ui->setupUi(this); QSettings settings; diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index a9a60d09f1..a53c4c24f9 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -145,18 +145,18 @@ private: }; interfaces::Node& m_node; - Ui::RPCConsole *ui; - ClientModel *clientModel; + Ui::RPCConsole* const ui; + ClientModel *clientModel = nullptr; QStringList history; - int historyPtr; + int historyPtr = 0; QString cmdBeforeBrowsing; QList<NodeId> cachedNodeids; - const PlatformStyle *platformStyle; - RPCTimerInterface *rpcTimerInterface; - QMenu *peersTableContextMenu; - QMenu *banTableContextMenu; - int consoleFontSize; - QCompleter *autoCompleter; + const PlatformStyle* const platformStyle; + RPCTimerInterface *rpcTimerInterface = nullptr; + QMenu *peersTableContextMenu = nullptr; + QMenu *banTableContextMenu = nullptr; + int consoleFontSize = 0; + QCompleter *autoCompleter = nullptr; QThread thread; QString m_last_wallet_id; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index c24a3de060..5593cc9acc 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -940,7 +940,7 @@ UniValue pruneblockchain(const JSONRPCRequest& request) else if (height > chainHeight) throw JSONRPCError(RPC_INVALID_PARAMETER, "Blockchain is shorter than the attempted prune height."); else if (height > chainHeight - MIN_BLOCKS_TO_KEEP) { - LogPrint(BCLog::RPC, "Attempt to prune blocks close to the tip. Retaining the minimum number of blocks."); + LogPrint(BCLog::RPC, "Attempt to prune blocks close to the tip. Retaining the minimum number of blocks.\n"); height = chainHeight - MIN_BLOCKS_TO_KEEP; } diff --git a/src/timedata.cpp b/src/timedata.cpp index a803b2fc87..27d08172f5 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -110,9 +110,9 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample) if (LogAcceptCategory(BCLog::NET)) { for (int64_t n : vSorted) { - LogPrint(BCLog::NET, "%+d ", n); + LogPrint(BCLog::NET, "%+d ", n); /* Continued */ } - LogPrint(BCLog::NET, "| "); + LogPrint(BCLog::NET, "| "); /* Continued */ LogPrint(BCLog::NET, "nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset/60); } diff --git a/src/validation.cpp b/src/validation.cpp index 14257d78f9..1b9e982753 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2066,13 +2066,12 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState & LOCK(cs_main); static int64_t nLastWrite = 0; static int64_t nLastFlush = 0; - static int64_t nLastSetChain = 0; std::set<int> setFilesToPrune; - bool fFlushForPrune = false; - bool fDoFullFlush = false; - int64_t nNow = 0; + bool full_flush_completed = false; try { { + bool fFlushForPrune = false; + bool fDoFullFlush = false; LOCK(cs_LastBlockFile); if (fPruneMode && (fCheckForPruning || nManualPruneHeight > 0) && !fReindex) { if (nManualPruneHeight > 0) { @@ -2089,7 +2088,7 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState & } } } - nNow = GetTimeMicros(); + int64_t nNow = GetTimeMicros(); // Avoid writing/flushing immediately after startup. if (nLastWrite == 0) { nLastWrite = nNow; @@ -2097,9 +2096,6 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState & if (nLastFlush == 0) { nLastFlush = nNow; } - if (nLastSetChain == 0) { - nLastSetChain = nNow; - } int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; int64_t cacheSize = pcoinsTip->DynamicMemoryUsage(); int64_t nTotalSpace = nCoinCacheUsage + std::max<int64_t>(nMempoolSizeMax - nMempoolUsage, 0); @@ -2156,12 +2152,12 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState & if (!pcoinsTip->Flush()) return AbortNode(state, "Failed to write to coin database"); nLastFlush = nNow; + full_flush_completed = true; } } - if (fDoFullFlush || ((mode == FlushStateMode::ALWAYS || mode == FlushStateMode::PERIODIC) && nNow > nLastSetChain + (int64_t)DATABASE_WRITE_INTERVAL * 1000000)) { + if (full_flush_completed) { // Update best block in wallet (so we can detect restored wallets). - GetMainSignals().SetBestChain(chainActive.GetLocator()); - nLastSetChain = nNow; + GetMainSignals().ChainStateFlushed(chainActive.GetLocator()); } } catch (const std::runtime_error& e) { return AbortNode(state, std::string("System error while flushing: ") + e.what()); diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 746263f113..f328d2d14b 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -25,7 +25,7 @@ struct MainSignalsInstance { boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::vector<CTransactionRef>&)> BlockConnected; boost::signals2::signal<void (const std::shared_ptr<const CBlock> &)> BlockDisconnected; boost::signals2::signal<void (const CTransactionRef &)> TransactionRemovedFromMempool; - boost::signals2::signal<void (const CBlockLocator &)> SetBestChain; + boost::signals2::signal<void (const CBlockLocator &)> ChainStateFlushed; boost::signals2::signal<void (const uint256 &)> Inventory; boost::signals2::signal<void (int64_t nBestBlockTime, CConnman* connman)> Broadcast; boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked; @@ -80,7 +80,7 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.m_internals->BlockConnected.connect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); g_signals.m_internals->BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); g_signals.m_internals->TransactionRemovedFromMempool.connect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, _1)); - g_signals.m_internals->SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); + g_signals.m_internals->ChainStateFlushed.connect(boost::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, _1)); g_signals.m_internals->Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); g_signals.m_internals->Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); g_signals.m_internals->BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); @@ -91,7 +91,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.m_internals->BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); g_signals.m_internals->Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); g_signals.m_internals->Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); - g_signals.m_internals->SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); + g_signals.m_internals->ChainStateFlushed.disconnect(boost::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, _1)); g_signals.m_internals->TransactionAddedToMempool.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); g_signals.m_internals->BlockConnected.disconnect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); g_signals.m_internals->BlockDisconnected.disconnect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); @@ -107,7 +107,7 @@ void UnregisterAllValidationInterfaces() { g_signals.m_internals->BlockChecked.disconnect_all_slots(); g_signals.m_internals->Broadcast.disconnect_all_slots(); g_signals.m_internals->Inventory.disconnect_all_slots(); - g_signals.m_internals->SetBestChain.disconnect_all_slots(); + g_signals.m_internals->ChainStateFlushed.disconnect_all_slots(); g_signals.m_internals->TransactionAddedToMempool.disconnect_all_slots(); g_signals.m_internals->BlockConnected.disconnect_all_slots(); g_signals.m_internals->BlockDisconnected.disconnect_all_slots(); @@ -166,9 +166,9 @@ void CMainSignals::BlockDisconnected(const std::shared_ptr<const CBlock> &pblock }); } -void CMainSignals::SetBestChain(const CBlockLocator &locator) { +void CMainSignals::ChainStateFlushed(const CBlockLocator &locator) { m_internals->m_schedulerClient.AddToProcessQueue([locator, this] { - m_internals->SetBestChain(locator); + m_internals->ChainStateFlushed(locator); }); } diff --git a/src/validationinterface.h b/src/validationinterface.h index 63097166af..3a5fed0106 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -99,9 +99,20 @@ protected: /** * Notifies listeners of the new active block chain on-disk. * + * Prior to this callback, any updates are not guaranteed to persist on disk + * (ie clients need to handle shutdown/restart safety by being able to + * understand when some updates were lost due to unclean shutdown). + * + * When this callback is invoked, the validation changes done by any prior + * callback are guaranteed to exist on disk and survive a restart, including + * an unclean shutdown. + * + * Provides a locator describing the best chain, which is likely useful for + * storing current state on disk in client DBs. + * * Called on a background thread. */ - virtual void SetBestChain(const CBlockLocator &locator) {} + virtual void ChainStateFlushed(const CBlockLocator &locator) {} /** * Notifies listeners about an inventory item being seen on the network. * @@ -157,7 +168,7 @@ public: void TransactionAddedToMempool(const CTransactionRef &); void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>> &); void BlockDisconnected(const std::shared_ptr<const CBlock> &); - void SetBestChain(const CBlockLocator &); + void ChainStateFlushed(const CBlockLocator &); void Inventory(const uint256 &); void Broadcast(int64_t nBestBlockTime, CConnman* connman); void BlockChecked(const CBlock&, const CValidationState&); diff --git a/src/wallet/coinselection.cpp b/src/wallet/coinselection.cpp index 8596ad2adc..a403411e5b 100644 --- a/src/wallet/coinselection.cpp +++ b/src/wallet/coinselection.cpp @@ -286,10 +286,10 @@ bool KnapsackSolver(const CAmount& nTargetValue, std::vector<CInputCoin>& vCoins } if (LogAcceptCategory(BCLog::SELECTCOINS)) { - LogPrint(BCLog::SELECTCOINS, "SelectCoins() best subset: "); + LogPrint(BCLog::SELECTCOINS, "SelectCoins() best subset: "); /* Continued */ for (unsigned int i = 0; i < vValue.size(); i++) { if (vfBest[i]) { - LogPrint(BCLog::SELECTCOINS, "%s ", FormatMoney(vValue[i].txout.nValue)); + LogPrint(BCLog::SELECTCOINS, "%s ", FormatMoney(vValue[i].txout.nValue)); /* Continued */ } } LogPrint(BCLog::SELECTCOINS, "total %s\n", FormatMoney(nBest)); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index a82f069490..bfd9840dfc 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -164,8 +164,7 @@ UniValue getnewaddress(const JSONRPCRequest& request) OutputType output_type = pwallet->m_default_address_type; if (!request.params[1].isNull()) { - output_type = ParseOutputType(request.params[1].get_str(), pwallet->m_default_address_type); - if (output_type == OutputType::NONE) { + if (!ParseOutputType(request.params[1].get_str(), output_type)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[1].get_str())); } } @@ -282,10 +281,9 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request) pwallet->TopUpKeyPool(); } - OutputType output_type = pwallet->m_default_change_type != OutputType::NONE ? pwallet->m_default_change_type : pwallet->m_default_address_type; + OutputType output_type = pwallet->m_default_change_type != OutputType::CHANGE_AUTO ? pwallet->m_default_change_type : pwallet->m_default_address_type; if (!request.params[0].isNull()) { - output_type = ParseOutputType(request.params[0].get_str(), output_type); - if (output_type == OutputType::NONE) { + if (!ParseOutputType(request.params[0].get_str(), output_type)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str())); } } @@ -1317,8 +1315,7 @@ UniValue addmultisigaddress(const JSONRPCRequest& request) OutputType output_type = pwallet->m_default_address_type; if (!request.params[3].isNull()) { - output_type = ParseOutputType(request.params[3].get_str(), output_type); - if (output_type == OutputType::NONE) { + if (!ParseOutputType(request.params[3].get_str(), output_type)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[3].get_str())); } } @@ -3317,8 +3314,8 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) if (options.exists("changeAddress")) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both changeAddress and address_type options"); } - coinControl.m_change_type = ParseOutputType(options["change_type"].get_str(), pwallet->m_default_change_type); - if (coinControl.m_change_type == OutputType::NONE) { + coinControl.m_change_type = pwallet->m_default_change_type; + if (!ParseOutputType(options["change_type"].get_str(), *coinControl.m_change_type)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown change type '%s'", options["change_type"].get_str())); } } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6e0f49f136..9533e6ff56 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -11,6 +11,7 @@ #include <consensus/consensus.h> #include <consensus/validation.h> #include <fs.h> +#include <init.h> #include <key.h> #include <key_io.h> #include <keystore.h> @@ -453,7 +454,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, return false; } -void CWallet::SetBestChain(const CBlockLocator& loc) +void CWallet::ChainStateFlushed(const CBlockLocator& loc) { WalletBatch batch(*database); batch.WriteBestBlock(loc); @@ -1753,7 +1754,7 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock dProgressTip = GuessVerificationProgress(chainParams.TxData(), tip); } double gvp = dProgressStart; - while (pindex && !fAbortRescan) + while (pindex && !fAbortRescan && !ShutdownRequested()) { if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0) { ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((gvp - dProgressStart) / (dProgressTip - dProgressStart) * 100)))); @@ -1794,6 +1795,8 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock } if (pindex && fAbortRescan) { LogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, gvp); + } else if (pindex && ShutdownRequested()) { + LogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", pindex->nHeight, gvp); } ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI } @@ -2671,7 +2674,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC OutputType CWallet::TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend) { // If -changetype is specified, always use that change type. - if (change_type != OutputType::NONE) { + if (change_type != OutputType::CHANGE_AUTO) { return change_type; } @@ -4038,7 +4041,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& return nullptr; } - walletInstance->SetBestChain(chainActive.GetLocator()); + walletInstance->ChainStateFlushed(chainActive.GetLocator()); } else if (gArgs.IsArgSet("-usehd")) { bool useHD = gArgs.GetBoolArg("-usehd", true); if (walletInstance->IsHDEnabled() && !useHD) { @@ -4051,16 +4054,12 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& } } - walletInstance->m_default_address_type = ParseOutputType(gArgs.GetArg("-addresstype", ""), DEFAULT_ADDRESS_TYPE); - if (walletInstance->m_default_address_type == OutputType::NONE) { + if (!gArgs.GetArg("-addresstype", "").empty() && !ParseOutputType(gArgs.GetArg("-addresstype", ""), walletInstance->m_default_address_type)) { InitError(strprintf("Unknown address type '%s'", gArgs.GetArg("-addresstype", ""))); return nullptr; } - // If changetype is set in config file or parameter, check that it's valid. - // Default to OutputType::NONE if not set. - walletInstance->m_default_change_type = ParseOutputType(gArgs.GetArg("-changetype", ""), OutputType::NONE); - if (walletInstance->m_default_change_type == OutputType::NONE && !gArgs.GetArg("-changetype", "").empty()) { + if (!gArgs.GetArg("-changetype", "").empty() && !ParseOutputType(gArgs.GetArg("-changetype", ""), walletInstance->m_default_change_type)) { InitError(strprintf("Unknown change type '%s'", gArgs.GetArg("-changetype", ""))); return nullptr; } @@ -4180,7 +4179,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, reserver, true); } LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); - walletInstance->SetBestChain(chainActive.GetLocator()); + walletInstance->ChainStateFlushed(chainActive.GetLocator()); walletInstance->database->IncrementUpdateCounter(); // Restore wallet transaction metadata after -zapwallettxes=1 @@ -4308,19 +4307,19 @@ static const std::string OUTPUT_TYPE_STRING_LEGACY = "legacy"; static const std::string OUTPUT_TYPE_STRING_P2SH_SEGWIT = "p2sh-segwit"; static const std::string OUTPUT_TYPE_STRING_BECH32 = "bech32"; -OutputType ParseOutputType(const std::string& type, OutputType default_type) +bool ParseOutputType(const std::string& type, OutputType& output_type) { - if (type.empty()) { - return default_type; - } else if (type == OUTPUT_TYPE_STRING_LEGACY) { - return OutputType::LEGACY; + if (type == OUTPUT_TYPE_STRING_LEGACY) { + output_type = OutputType::LEGACY; + return true; } else if (type == OUTPUT_TYPE_STRING_P2SH_SEGWIT) { - return OutputType::P2SH_SEGWIT; + output_type = OutputType::P2SH_SEGWIT; + return true; } else if (type == OUTPUT_TYPE_STRING_BECH32) { - return OutputType::BECH32; - } else { - return OutputType::NONE; + output_type = OutputType::BECH32; + return true; } + return false; } const std::string& FormatOutputType(OutputType type) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 780c82ac36..3208a20f0f 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -93,15 +93,24 @@ enum WalletFeature }; enum class OutputType { - NONE, LEGACY, P2SH_SEGWIT, BECH32, + + /** + * Special output type for change outputs only. Automatically choose type + * based on address type setting and the types other of non-change outputs + * (see -changetype option documentation and implementation in + * CWallet::TransactionChangeType for details). + */ + CHANGE_AUTO, }; //! Default for -addresstype constexpr OutputType DEFAULT_ADDRESS_TYPE{OutputType::P2SH_SEGWIT}; +//! Default for -changetype +constexpr OutputType DEFAULT_CHANGE_TYPE{OutputType::CHANGE_AUTO}; /** A key pool entry */ class CKeyPool @@ -973,7 +982,7 @@ public: CFeeRate m_fallback_fee{DEFAULT_FALLBACK_FEE}; CFeeRate m_discard_rate{DEFAULT_DISCARD_FEE}; OutputType m_default_address_type{DEFAULT_ADDRESS_TYPE}; - OutputType m_default_change_type{OutputType::NONE}; // Default to OutputType::NONE if not set by -changetype + OutputType m_default_change_type{DEFAULT_CHANGE_TYPE}; bool NewKeyPool(); size_t KeypoolCountExternalKeys(); @@ -1013,7 +1022,7 @@ public: bool IsAllFromMe(const CTransaction& tx, const isminefilter& filter) const; CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const; CAmount GetChange(const CTransaction& tx) const; - void SetBestChain(const CBlockLocator& loc) override; + void ChainStateFlushed(const CBlockLocator& loc) override; DBErrors LoadWallet(bool& fFirstRunRet); DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx); @@ -1218,7 +1227,7 @@ public: } }; -OutputType ParseOutputType(const std::string& str, OutputType default_type); +bool ParseOutputType(const std::string& str, OutputType& output_type); const std::string& FormatOutputType(OutputType type); /** |