wallet: take note heights from the wallet's depth, not tx_height()
For minDepth > 1, GetFilteredNotes located each wallet tx's block with tx_height(), which calls GetTransaction and re-reads the tx from disk through the txindex. It did this once per wallet tx, transparent ones included, while holding LOCK2. z_listunspent and z_listreceivedbyaddress did it once more per returned note. Without -txindex, GetTransaction can only find a tx that still has unspent transparent outputs. tx_height() then returned 0 for every fully shielded tx, and the tx was skipped. So on a -txindex=0 node, sweep and consolidation (minDepth 11) and any minconf >= 2 call never saw those notes. The wallet already has the depth, and for an active-chain tx GetDepthInMainChain is chainActive.Height() - height + 1. The new HeightFromDepth() inverts that (0 when unconfirmed or off the active chain) and replaces tx_height() at all three sites. The height only feeds the == 0 skip and hush_dpowconfs. Both sides hold cs_main for the whole call, so the tip can't move between the walk and the RPC tail. On a -txindex node the results are identical: the txindex block and wtx.hashBlock are the same block. The extended equivalence test now also covers minDepth 2/11/12/22. On -txindex=0 nodes, fully shielded notes now show up for minDepth > 1. With -zsweep or -consolidation enabled, those notes will now be swept and consolidated, so init logs that once. MinDepthAboveOneUsesWalletHeight pins the new behaviour and shows that the old path returned nothing without a txindex. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+11
-2
@@ -76,7 +76,6 @@ bool fPayAtLeastCustomFee = true;
|
||||
CBlockIndex *hush_chainactive(int32_t height);
|
||||
extern int32_t HUSH_LOADINGBLOCKS;
|
||||
int32_t hush_dpowconfs(int32_t height,int32_t numconfs);
|
||||
int tx_height( const uint256 &hash );
|
||||
bool fTxDeleteEnabled = false;
|
||||
bool fTxConflictDeleteEnabled = false;
|
||||
int fDeleteInterval = DEFAULT_TX_DELETE_INTERVAL;
|
||||
@@ -5715,6 +5714,16 @@ bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
|
||||
return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectAbsurdFee);
|
||||
}
|
||||
|
||||
// Replaces tx_height() on the wallet's note paths. tx_height() re-read the tx from disk through
|
||||
// GetTransaction, once per wallet tx (or per returned note) under LOCK2, and on a -txindex=0 node it
|
||||
// never found a fully shielded tx, so those notes were silently skipped. The depth already locates
|
||||
// the block: GetDepthInMainChain is chainActive.Height() - height + 1 for an active-chain tx.
|
||||
int HeightFromDepth(int nDepth)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
return nDepth > 0 ? chainActive.Height() - nDepth + 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find notes in the wallet filtered by payment address, min depth and ability to spend.
|
||||
* These notes are decrypted and added to the output parameter vector, outEntries.
|
||||
@@ -5773,7 +5782,7 @@ void CWallet::GetFilteredNotes(
|
||||
// cs_main is held, so the depth can't change during the walk.
|
||||
const int nDepth = wtx.GetDepthInMainChain();
|
||||
if (minDepth > 1) {
|
||||
int nHeight = tx_height(wtx.GetHash());
|
||||
int nHeight = HeightFromDepth(nDepth);
|
||||
if ( nHeight == 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user