diff options
Diffstat (limited to 'src/wallet/wallet.cpp')
-rw-r--r-- | src/wallet/wallet.cpp | 240 |
1 files changed, 125 insertions, 115 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 74deb2dddc..ddeff8ba09 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -935,19 +935,19 @@ void CWallet::LoadToWallet(const CWalletTx& wtxIn) } } -bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate) +bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const uint256& block_hash, int posInBlock, bool fUpdate) { const CTransaction& tx = *ptx; { AssertLockHeld(cs_wallet); - if (pIndex != nullptr) { + if (!block_hash.IsNull()) { 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()) { - WalletLogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), pIndex->GetBlockHash().ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n); - MarkConflicted(pIndex->GetBlockHash(), range.first->second); + WalletLogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), block_hash.ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n); + MarkConflicted(block_hash, range.first->second); } range.first++; } @@ -983,8 +983,8 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockI CWalletTx wtx(this, ptx); // Get merkle branch if transaction was found in a block - if (pIndex != nullptr) - wtx.SetMerkleBranch(pIndex, posInBlock); + if (!block_hash.IsNull()) + wtx.SetMerkleBranch(block_hash, posInBlock); return AddToWallet(wtx, false); } @@ -1071,11 +1071,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) auto locked_chain = chain().lock(); LOCK(cs_wallet); - int conflictconfirms = 0; - CBlockIndex* pindex = LookupBlockIndex(hashBlock); - if (pindex && chainActive.Contains(pindex)) { - conflictconfirms = -(chainActive.Height() - pindex->nHeight + 1); - } + int conflictconfirms = -locked_chain->getBlockDepth(hashBlock); // If number of conflict confirms cannot be determined, this means // that the block is still unknown or not yet part of the main chain, // for example when loading the wallet during a reindex. Do nothing in that @@ -1121,8 +1117,8 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) } } -void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pindex, int posInBlock, bool update_tx) { - if (!AddToWalletIfInvolvingMe(ptx, pindex, posInBlock, update_tx)) +void CWallet::SyncTransaction(const CTransactionRef& ptx, const uint256& block_hash, int posInBlock, bool update_tx) { + if (!AddToWalletIfInvolvingMe(ptx, block_hash, posInBlock, update_tx)) return; // Not one of ours // If a transaction changes 'conflicted' state, that changes the balance @@ -1134,7 +1130,7 @@ void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pin void CWallet::TransactionAddedToMempool(const CTransactionRef& ptx) { auto locked_chain = chain().lock(); LOCK(cs_wallet); - SyncTransaction(ptx); + SyncTransaction(ptx, {} /* block hash */, 0 /* position in block */); auto it = mapWallet.find(ptx->GetHash()); if (it != mapWallet.end()) { @@ -1162,15 +1158,15 @@ void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const // the notification that the conflicted transaction was evicted. for (const CTransactionRef& ptx : vtxConflicted) { - SyncTransaction(ptx); + SyncTransaction(ptx, {} /* block hash */, 0 /* position in block */); TransactionRemovedFromMempool(ptx); } for (size_t i = 0; i < pblock->vtx.size(); i++) { - SyncTransaction(pblock->vtx[i], pindex, i); + SyncTransaction(pblock->vtx[i], pindex->GetBlockHash(), i); TransactionRemovedFromMempool(pblock->vtx[i]); } - m_last_block_processed = pindex; + m_last_block_processed = pindex->GetBlockHash(); } void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) { @@ -1178,7 +1174,7 @@ void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) { LOCK(cs_wallet); for (const CTransactionRef& ptx : pblock->vtx) { - SyncTransaction(ptx); + SyncTransaction(ptx, {} /* block hash */, 0 /* position in block */); } } @@ -1195,9 +1191,8 @@ void CWallet::BlockUntilSyncedToCurrentChain() { // protected by cs_wallet instead of cs_main, but as long as we need // cs_main here anyway, it's easier to just call it cs_main-protected. auto locked_chain = chain().lock(); - const CBlockIndex* initialChainTip = chainActive.Tip(); - if (m_last_block_processed && m_last_block_processed->GetAncestor(initialChainTip->nHeight) == initialChainTip) { + if (!m_last_block_processed.IsNull() && locked_chain->isPotentialTip(m_last_block_processed)) { return; } } @@ -1591,132 +1586,143 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r // Find starting block. May be null if nCreateTime is greater than the // highest blockchain timestamp, in which case there is nothing that needs // to be scanned. - CBlockIndex* startBlock = nullptr; + uint256 start_block; { auto locked_chain = chain().lock(); - startBlock = chainActive.FindEarliestAtLeast(startTime - TIMESTAMP_WINDOW); - WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, startBlock ? chainActive.Height() - startBlock->nHeight + 1 : 0); + const Optional<int> start_height = locked_chain->findFirstBlockWithTime(startTime - TIMESTAMP_WINDOW, &start_block); + const Optional<int> tip_height = locked_chain->getHeight(); + WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, tip_height && start_height ? *tip_height - *start_height + 1 : 0); } - if (startBlock) { - const CBlockIndex *failedBlock, *stop_block; + if (!start_block.IsNull()) { // TODO: this should take into account failure by ScanResult::USER_ABORT - if (ScanResult::FAILURE == ScanForWalletTransactions(startBlock, nullptr, reserver, failedBlock, stop_block, update)) { - return failedBlock->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1; + ScanResult result = ScanForWalletTransactions(start_block, {} /* stop_block */, reserver, update); + if (result.status == ScanResult::FAILURE) { + int64_t time_max; + if (!chain().findBlock(result.failed_block, nullptr /* block */, nullptr /* time */, &time_max)) { + throw std::logic_error("ScanForWalletTransactions returned invalid block hash"); + } + return time_max + TIMESTAMP_WINDOW + 1; } } return startTime; } /** - * Scan the block chain (starting in pindexStart) for transactions + * Scan the block chain (starting in start_block) for transactions * from or to us. If fUpdate is true, found transactions that already * exist in the wallet will be updated. * - * @param[in] pindexStop if not a nullptr, the scan will stop at this block-index - * @param[out] failed_block if FAILURE is returned, the most recent block - * that could not be scanned, otherwise nullptr - * @param[out] stop_block the most recent block that could be scanned, - * otherwise nullptr if no block could be scanned + * @param[in] start_block if not null, the scan will start at this block instead + * of the genesis block + * @param[in] stop_block if not null, the scan will stop at this block instead + * of the chain tip * * @return ScanResult indicating success or failure of the scan. SUCCESS if * scan was successful. FAILURE if a complete rescan was not possible (due to * pruning or corruption). USER_ABORT if the rescan was aborted before it * could complete. * - * @pre Caller needs to make sure pindexStop (and the optional pindexStart) are on + * @pre Caller needs to make sure start_block (and the optional stop_block) are on * the main chain after to the addition of any new keys you want to detect * transactions for. */ -CWallet::ScanResult CWallet::ScanForWalletTransactions(const CBlockIndex* const pindexStart, const CBlockIndex* const pindexStop, const WalletRescanReserver& reserver, const CBlockIndex*& failed_block, const CBlockIndex*& stop_block, bool fUpdate) +CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, const uint256& stop_block, const WalletRescanReserver& reserver, bool fUpdate) { int64_t nNow = GetTime(); - const CChainParams& chainParams = Params(); assert(reserver.isReserved()); - if (pindexStop) { - assert(pindexStop->nHeight >= pindexStart->nHeight); - } - const CBlockIndex* pindex = pindexStart; - failed_block = nullptr; - stop_block = nullptr; + uint256 block_hash = start_block; + ScanResult result; - if (pindex) WalletLogPrintf("Rescan started from block %d...\n", pindex->nHeight); + WalletLogPrintf("Rescan started from block %s...\n", start_block.ToString()); { fAbortRescan = false; ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup - CBlockIndex* tip = nullptr; + uint256 tip_hash; + Optional<int> block_height; double progress_begin; double progress_end; { auto locked_chain = chain().lock(); - progress_begin = GuessVerificationProgress(chainParams.TxData(), pindex); - if (pindexStop == nullptr) { - tip = chainActive.Tip(); - progress_end = GuessVerificationProgress(chainParams.TxData(), tip); - } else { - progress_end = GuessVerificationProgress(chainParams.TxData(), pindexStop); + if (Optional<int> tip_height = locked_chain->getHeight()) { + tip_hash = locked_chain->getBlockHash(*tip_height); } + block_height = locked_chain->getBlockHeight(block_hash); + progress_begin = chain().guessVerificationProgress(block_hash); + progress_end = chain().guessVerificationProgress(stop_block.IsNull() ? tip_hash : stop_block); } double progress_current = progress_begin; - while (pindex && !fAbortRescan && !ShutdownRequested()) { - if (pindex->nHeight % 100 == 0 && progress_end - progress_begin > 0.0) { + while (block_height && !fAbortRescan && !ShutdownRequested()) { + if (*block_height % 100 == 0 && progress_end - progress_begin > 0.0) { ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), std::max(1, std::min(99, (int)((progress_current - progress_begin) / (progress_end - progress_begin) * 100)))); } if (GetTime() >= nNow + 60) { nNow = GetTime(); - WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, progress_current); + WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", *block_height, progress_current); } CBlock block; - if (ReadBlockFromDisk(block, pindex, Params().GetConsensus())) { + if (chain().findBlock(block_hash, &block) && !block.IsNull()) { auto locked_chain = chain().lock(); LOCK(cs_wallet); - if (pindex && !chainActive.Contains(pindex)) { + if (!locked_chain->getBlockHeight(block_hash)) { // Abort scan if current block is no longer active, to prevent // marking transactions as coming from the wrong block. - failed_block = pindex; + // TODO: This should return success instead of failure, see + // https://github.com/bitcoin/bitcoin/pull/14711#issuecomment-458342518 + result.failed_block = block_hash; + result.status = ScanResult::FAILURE; break; } for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) { - SyncTransaction(block.vtx[posInBlock], pindex, posInBlock, fUpdate); + SyncTransaction(block.vtx[posInBlock], block_hash, posInBlock, fUpdate); } // scan succeeded, record block as most recent successfully scanned - stop_block = pindex; + result.stop_block = block_hash; + result.stop_height = *block_height; } else { // could not scan block, keep scanning but record this block as the most recent failure - failed_block = pindex; + result.failed_block = block_hash; + result.status = ScanResult::FAILURE; } - if (pindex == pindexStop) { + if (block_hash == stop_block) { break; } { auto locked_chain = chain().lock(); - pindex = chainActive.Next(pindex); - progress_current = GuessVerificationProgress(chainParams.TxData(), pindex); - if (pindexStop == nullptr && tip != chainActive.Tip()) { - tip = chainActive.Tip(); + Optional<int> tip_height = locked_chain->getHeight(); + if (!tip_height || *tip_height <= block_height || !locked_chain->getBlockHeight(block_hash)) { + // break successfully when rescan has reached the tip, or + // previous block is no longer on the chain due to a reorg + break; + } + + // increment block and verification progress + block_hash = locked_chain->getBlockHash(++*block_height); + progress_current = chain().guessVerificationProgress(block_hash); + + // handle updated tip hash + const uint256 prev_tip_hash = tip_hash; + tip_hash = locked_chain->getBlockHash(*tip_height); + if (stop_block.IsNull() && prev_tip_hash != tip_hash) { // in case the tip has changed, update progress max - progress_end = GuessVerificationProgress(chainParams.TxData(), tip); + progress_end = chain().guessVerificationProgress(tip_hash); } } } ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), 100); // hide progress dialog in GUI - if (pindex && fAbortRescan) { - WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, progress_current); - return ScanResult::USER_ABORT; - } else if (pindex && ShutdownRequested()) { - WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", pindex->nHeight, progress_current); - return ScanResult::USER_ABORT; + if (block_height && fAbortRescan) { + WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", block_height.value_or(0), progress_current); + result.status = ScanResult::USER_ABORT; + } else if (block_height && ShutdownRequested()) { + WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height.value_or(0), progress_current); + result.status = ScanResult::USER_ABORT; } } - if (failed_block) { - return ScanResult::FAILURE; - } else { - return ScanResult::SUCCESS; - } + return result; } void CWallet::ReacceptWalletTransactions() @@ -2573,6 +2579,7 @@ static bool IsCurrentForAntiFeeSniping(interfaces::Chain::Lock& locked_chain) */ static uint32_t GetLocktimeForNewTransaction(interfaces::Chain::Lock& locked_chain) { + uint32_t const height = locked_chain.getHeight().value_or(-1); uint32_t locktime; // Discourage fee sniping. // @@ -2595,7 +2602,7 @@ static uint32_t GetLocktimeForNewTransaction(interfaces::Chain::Lock& locked_cha // now we ensure code won't be written that makes assumptions about // nLockTime that preclude a fix later. if (IsCurrentForAntiFeeSniping(locked_chain)) { - locktime = chainActive.Height(); + locktime = height; // Secondly occasionally randomly pick a nLockTime even further back, so // that transactions that are delayed after signing for whatever reason, @@ -2609,7 +2616,7 @@ static uint32_t GetLocktimeForNewTransaction(interfaces::Chain::Lock& locked_cha // unique "nLockTime fingerprint", set nLockTime to a constant. locktime = 0; } - assert(locktime <= (unsigned int)chainActive.Height()); + assert(locktime <= height); assert(locktime < LOCKTIME_THRESHOLD); return locktime; } @@ -3718,11 +3725,12 @@ void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<C } // map in which we'll infer heights of other keys - CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganized; use a 144-block safety margin - std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock; + const Optional<int> tip_height = locked_chain.getHeight(); + const int max_height = tip_height && *tip_height > 144 ? *tip_height - 144 : 0; // the tip can be reorganized; use a 144-block safety margin + std::map<CKeyID, int> mapKeyFirstBlock; for (const CKeyID &keyid : GetKeys()) { if (mapKeyBirth.count(keyid) == 0) - mapKeyFirstBlock[keyid] = pindexMax; + mapKeyFirstBlock[keyid] = max_height; } // if there are no such keys, we're done @@ -3733,17 +3741,15 @@ void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<C for (const auto& entry : mapWallet) { // iterate over all wallet transactions... const CWalletTx &wtx = entry.second; - CBlockIndex* pindex = LookupBlockIndex(wtx.hashBlock); - if (pindex && chainActive.Contains(pindex)) { + if (Optional<int> height = locked_chain.getBlockHeight(wtx.hashBlock)) { // ... which are already in a block - int nHeight = pindex->nHeight; for (const CTxOut &txout : wtx.tx->vout) { // iterate over all their outputs for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *this)) { // ... and all their affected keys - std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid); - if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight) - rit->second = pindex; + std::map<CKeyID, int>::iterator rit = mapKeyFirstBlock.find(keyid); + if (rit != mapKeyFirstBlock.end() && *height < rit->second) + rit->second = *height; } } } @@ -3751,7 +3757,7 @@ void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<C // Extract block timestamps for those keys for (const auto& entry : mapKeyFirstBlock) - mapKeyBirth[entry.first] = entry.second->GetBlockTime() - TIMESTAMP_WINDOW; // block times can be 2h off + mapKeyBirth[entry.first] = locked_chain.getBlockTime(entry.second) - TIMESTAMP_WINDOW; // block times can be 2h off } /** @@ -3779,7 +3785,8 @@ unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const { unsigned int nTimeSmart = wtx.nTimeReceived; if (!wtx.hashUnset()) { - if (const CBlockIndex* pindex = LookupBlockIndex(wtx.hashBlock)) { + int64_t blocktime; + if (chain().findBlock(wtx.hashBlock, nullptr /* block */, &blocktime)) { int64_t latestNow = wtx.nTimeReceived; int64_t latestEntry = 0; @@ -3805,7 +3812,6 @@ unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const } } - int64_t blocktime = pindex->GetBlockTime(); nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow)); } else { WalletLogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), wtx.hashBlock.ToString()); @@ -4067,7 +4073,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, } auto locked_chain = chain.assumeLocked(); // Temporary. Removed in upcoming lock cleanup - walletInstance->ChainStateFlushed(chainActive.GetLocator()); + walletInstance->ChainStateFlushed(locked_chain->getLocator()); } else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) { // Make it impossible to disable private keys after creation InitError(strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile)); @@ -4154,58 +4160,67 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, // Try to top up keypool. No-op if the wallet is locked. walletInstance->TopUpKeyPool(); - LockAnnotation lock(::cs_main); // Temporary, for FindForkInGlobalIndex below. Removed in upcoming commit. auto locked_chain = chain.lock(); LOCK(walletInstance->cs_wallet); - CBlockIndex *pindexRescan = chainActive.Genesis(); + int rescan_height = 0; if (!gArgs.GetBoolArg("-rescan", false)) { WalletBatch batch(*walletInstance->database); CBlockLocator locator; - if (batch.ReadBestBlock(locator)) - pindexRescan = FindForkInGlobalIndex(chainActive, locator); + if (batch.ReadBestBlock(locator)) { + if (const Optional<int> fork_height = locked_chain->findLocatorFork(locator)) { + rescan_height = *fork_height; + } + } } - walletInstance->m_last_block_processed = chainActive.Tip(); + const Optional<int> tip_height = locked_chain->getHeight(); + if (tip_height) { + walletInstance->m_last_block_processed = locked_chain->getBlockHash(*tip_height); + } else { + walletInstance->m_last_block_processed.SetNull(); + } - if (chainActive.Tip() && chainActive.Tip() != pindexRescan) + if (tip_height && *tip_height != rescan_height) { //We can't rescan beyond non-pruned blocks, stop and throw an error //this might happen if a user uses an old wallet within a pruned node // or if he ran -disablewallet for a longer time, then decided to re-enable if (fPruneMode) { - CBlockIndex *block = chainActive.Tip(); - while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA) && block->pprev->nTx > 0 && pindexRescan != block) - block = block->pprev; + int block_height = *tip_height; + while (block_height > 0 && locked_chain->haveBlockOnDisk(block_height - 1) && rescan_height != block_height) { + --block_height; + } - if (pindexRescan != block) { + if (rescan_height != block_height) { InitError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)")); return nullptr; } } uiInterface.InitMessage(_("Rescanning...")); - walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight); + walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height); // No need to read and scan block if block was created before // our wallet birthday (as adjusted for block time variability) - while (pindexRescan && walletInstance->nTimeFirstKey && (pindexRescan->GetBlockTime() < (walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW))) { - pindexRescan = chainActive.Next(pindexRescan); + if (walletInstance->nTimeFirstKey) { + if (Optional<int> first_block = locked_chain->findFirstBlockWithTimeAndHeight(walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW, rescan_height)) { + rescan_height = *first_block; + } } nStart = GetTimeMillis(); { WalletRescanReserver reserver(walletInstance.get()); - const CBlockIndex *stop_block, *failed_block; - if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, reserver, failed_block, stop_block, true))) { + if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(locked_chain->getBlockHash(rescan_height), {} /* stop block */, reserver, true /* update */).status)) { InitError(_("Failed to rescan the wallet during initialization")); return nullptr; } } walletInstance->WalletLogPrintf("Rescan completed in %15dms\n", GetTimeMillis() - nStart); - walletInstance->ChainStateFlushed(chainActive.GetLocator()); + walletInstance->ChainStateFlushed(locked_chain->getLocator()); walletInstance->database->IncrementUpdateCounter(); // Restore wallet transaction metadata after -zapwallettxes=1 @@ -4282,10 +4297,10 @@ CWalletKey::CWalletKey(int64_t nExpires) nTimeExpires = nExpires; } -void CMerkleTx::SetMerkleBranch(const CBlockIndex* pindex, int posInBlock) +void CMerkleTx::SetMerkleBranch(const uint256& block_hash, int posInBlock) { // Update the tx's hashBlock - hashBlock = pindex->GetBlockHash(); + hashBlock = block_hash; // set the position of the transaction in the block nIndex = posInBlock; @@ -4298,12 +4313,7 @@ int CMerkleTx::GetDepthInMainChain(interfaces::Chain::Lock& locked_chain) const AssertLockHeld(cs_main); - // Find the block it claims to be in - CBlockIndex* pindex = LookupBlockIndex(hashBlock); - if (!pindex || !chainActive.Contains(pindex)) - return 0; - - return ((nIndex == -1) ? (-1) : 1) * (chainActive.Height() - pindex->nHeight + 1); + return locked_chain.getBlockDepth(hashBlock) * (nIndex == -1 ? -1 : 1); } int CMerkleTx::GetBlocksToMaturity(interfaces::Chain::Lock& locked_chain) const |