diff options
Diffstat (limited to 'src/wallet/wallet.cpp')
-rw-r--r-- | src/wallet/wallet.cpp | 61 |
1 files changed, 31 insertions, 30 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 65b54f39b4..918946f9e7 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -52,7 +52,7 @@ const std::map<uint64_t,std::string> WALLET_FLAG_CAVEATS{ static const size_t OUTPUT_GROUP_MAX_ENTRIES = 10; -static RecursiveMutex cs_wallets; +RecursiveMutex cs_wallets; static std::vector<std::shared_ptr<CWallet>> vpwallets GUARDED_BY(cs_wallets); static std::list<LoadWalletFn> g_load_wallet_fns GUARDED_BY(cs_wallets); @@ -85,9 +85,9 @@ static void UpdateWalletSetting(interfaces::Chain& chain, std::vector<bilingual_str>& warnings) { if (load_on_startup == nullopt) return; - if (load_on_startup.get() && !AddWalletSetting(chain, wallet_name)) { + if (load_on_startup.value() && !AddWalletSetting(chain, wallet_name)) { warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup.")); - } else if (!load_on_startup.get() && !RemoveWalletSetting(chain, wallet_name)) { + } else if (!load_on_startup.value() && !RemoveWalletSetting(chain, wallet_name)) { warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup.")); } } @@ -570,7 +570,7 @@ void CWallet::AddToSpends(const uint256& wtxid) { auto it = mapWallet.find(wtxid); assert(it != mapWallet.end()); - CWalletTx& thisTx = it->second; + const CWalletTx& thisTx = it->second; if (thisTx.IsCoinBase()) // Coinbases don't spend anything! return; @@ -946,11 +946,12 @@ bool CWallet::LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx } // If wallet doesn't have a chain (e.g wallet-tool), don't bother to update txn. if (HaveChain()) { - Optional<int> block_height = chain().getBlockHeight(wtx.m_confirm.hashBlock); - if (block_height) { + bool active; + int height; + if (chain().findBlock(wtx.m_confirm.hashBlock, FoundBlock().inActiveChain(active).height(height)) && active) { // Update cached block height variable since it not stored in the // serialized transaction. - wtx.m_confirm.block_height = *block_height; + wtx.m_confirm.block_height = height; } else if (wtx.isConflicted() || wtx.isConfirmed()) { // If tx block (or conflicting block) was reorged out of chain // while the wallet was shutdown, change tx status to UNCONFIRMED @@ -1053,7 +1054,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx) // Can't mark abandoned if confirmed or in mempool auto it = mapWallet.find(hashTx); assert(it != mapWallet.end()); - CWalletTx& origtx = it->second; + const CWalletTx& origtx = it->second; if (origtx.GetDepthInMainChain() != 0 || origtx.InMempool()) { return false; } @@ -1177,9 +1178,8 @@ void CWallet::transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRe // Handle transactions that were removed from the mempool because they // conflict with transactions in a newly connected block. if (reason == MemPoolRemovalReason::CONFLICT) { - // Call SyncNotifications, so external -walletnotify notifications will - // be triggered for these transactions. Set Status::UNCONFIRMED instead - // of Status::CONFLICTED for a few reasons: + // Trigger external -walletnotify notifications for these transactions. + // Set Status::UNCONFIRMED instead of Status::CONFLICTED for a few reasons: // // 1. The transactionRemovedFromMempool callback does not currently // provide the conflicting block's hash and height, and for backwards @@ -1771,18 +1771,22 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", block_height, progress_current); } + // Read block data CBlock block; - bool next_block; + chain().findBlock(block_hash, FoundBlock().data(block)); + + // Find next block separately from reading data above, because reading + // is slow and there might be a reorg while it is read. + bool block_still_active = false; + bool next_block = false; uint256 next_block_hash; - bool reorg = false; - if (chain().findBlock(block_hash, FoundBlock().data(block)) && !block.IsNull()) { + chain().findBlock(block_hash, FoundBlock().inActiveChain(block_still_active).nextBlock(FoundBlock().inActiveChain(next_block).hash(next_block_hash))); + + if (!block.IsNull()) { LOCK(cs_wallet); - next_block = chain().findNextBlock(block_hash, block_height, FoundBlock().hash(next_block_hash), &reorg); - if (reorg) { + if (!block_still_active) { // Abort scan if current block is no longer active, to prevent // marking transactions as coming from the wrong block. - // TODO: This should return success instead of failure, see - // https://github.com/bitcoin/bitcoin/pull/14711#issuecomment-458342518 result.last_failed_block = block_hash; result.status = ScanResult::FAILURE; break; @@ -1797,13 +1801,12 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc // could not scan block, keep scanning but record this block as the most recent failure result.last_failed_block = block_hash; result.status = ScanResult::FAILURE; - next_block = chain().findNextBlock(block_hash, block_height, FoundBlock().hash(next_block_hash), &reorg); } if (max_height && block_height >= *max_height) { break; } { - if (!next_block || reorg) { + if (!next_block) { // break successfully when rescan has reached the tip, or // previous block is no longer on the chain due to a reorg break; @@ -2706,7 +2709,7 @@ static uint32_t GetLocktimeForNewTransaction(interfaces::Chain& chain, const uin return locktime; } -OutputType CWallet::TransactionChangeType(const Optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend) +OutputType CWallet::TransactionChangeType(const Optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend) const { // If -changetype is specified, always use that change type. if (change_type) { @@ -2786,7 +2789,7 @@ bool CWallet::CreateTransactionInternal( CScript scriptChange; // coin control: send change to custom address - if (!boost::get<CNoDestination>(&coin_control.destChange)) { + if (!std::get_if<CNoDestination>(&coin_control.destChange)) { scriptChange = GetScriptForDestination(coin_control.destChange); } else { // no coin control: send change to newly generated address // Note: We use a new key here to keep it from being obvious which side is the change. @@ -3048,7 +3051,7 @@ bool CWallet::CreateTransactionInternal( // to avoid conflicting with other possible uses of nSequence, // and in the spirit of "smallest possible change from prior // behavior." - const uint32_t nSequence = coin_control.m_signal_bip125_rbf.get_value_or(m_signal_rbf) ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1); + const uint32_t nSequence = coin_control.m_signal_bip125_rbf.value_or(m_signal_rbf) ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1); for (const auto& coin : selected_coins) { txNew.vin.push_back(CTxIn(coin.outpoint, CScript(), nSequence)); } @@ -3109,13 +3112,14 @@ bool CWallet::CreateTransaction( bool sign) { int nChangePosIn = nChangePosInOut; - CTransactionRef tx2 = tx; + Assert(!tx); // tx is an out-param. TODO change the return type from bool to tx (or nullptr) bool res = CreateTransactionInternal(vecSend, tx, nFeeRet, nChangePosInOut, error, coin_control, fee_calc_out, sign); // try with avoidpartialspends unless it's enabled already if (res && nFeeRet > 0 /* 0 means non-functional fee rate estimation */ && m_max_aps_fee > -1 && !coin_control.m_avoid_partial_spends) { CCoinControl tmp_cc = coin_control; tmp_cc.m_avoid_partial_spends = true; CAmount nFeeRet2; + CTransactionRef tx2; int nChangePosInOut2 = nChangePosIn; bilingual_str error2; // fired and forgotten; if an error occurs, we discard the results if (CreateTransactionInternal(vecSend, tx2, nFeeRet2, nChangePosInOut2, error2, tmp_cc, fee_calc_out, sign)) { @@ -3720,7 +3724,7 @@ unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const bool CWallet::AddDestData(WalletBatch& batch, const CTxDestination &dest, const std::string &key, const std::string &value) { - if (boost::get<CNoDestination>(&dest)) + if (std::get_if<CNoDestination>(&dest)) return false; m_address_book[dest].destdata.insert(std::make_pair(key, value)); @@ -4051,16 +4055,13 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st // No need to read and scan block if block was created before // our wallet birthday (as adjusted for block time variability) - // The way the 'time_first_key' is initialized is just a workaround for the gcc bug #47679 since version 4.6.0. - Optional<int64_t> time_first_key = MakeOptional(false, int64_t());; + Optional<int64_t> time_first_key; for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) { int64_t time = spk_man->GetTimeFirstKey(); if (!time_first_key || time < *time_first_key) time_first_key = time; } if (time_first_key) { - if (Optional<int> first_block = chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, nullptr)) { - rescan_height = *first_block; - } + chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, FoundBlock().height(rescan_height)); } { |