From 57441faffb02f4f2eea37d31b29728de25f18bef Mon Sep 17 00:00:00 2001 From: mtg0001 <106211915+mtg0001@users.noreply.github.com> Date: Mon, 3 Aug 2026 10:43:42 -0300 Subject: Add wallet recovery balance audit (#117) Co-authored-by: Gilcimar Duarte --- src/main.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 1b09a1a..75647ba 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3660,6 +3660,93 @@ bool BitcoinMiner(int nThreadId) // +WalletRecoveryAudit GetWalletRecoveryAudit() +{ + WalletRecoveryAudit audit; + set > setDerivedPubKeys; + + CRITICAL_BLOCK(cs_keyPool) + { + audit.fHaveSeed = HaveHDSeed(); + audit.nDerivedKnown = nHDNext; + if (audit.fHaveSeed) + { + string strError; + for (unsigned int i = 0; i < nHDNext; i++) + { + CKey key; + if (!DeriveHDKey(i, key, strError)) + { + audit.fDeriveComplete = false; + audit.strDeriveError = strprintf("derivation failed at index %u: %s", + i, strError.c_str()); + break; + } + setDerivedPubKeys.insert(key.GetPubKey()); + } + } + } + + CRITICAL_BLOCK(cs_mapWallet) + { + for (map::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + CWalletTx& wtx = (*it).second; + if (!wtx.IsFinal() || wtx.fSpent) + continue; + bool fImmature = wtx.IsCoinBase() && wtx.GetBlocksToMaturity() > 0; + + bool fTxRecoverable = false; + bool fTxLegacy = false; + for (int i = 0; i < (int)wtx.vout.size(); i++) + { + const CTxOut& txout = wtx.vout[i]; + if (!txout.IsMine()) + continue; + + vector vchPubKey; + bool fRecoverable = false; + if (audit.fHaveSeed && ExtractPubKey(txout.scriptPubKey, true, vchPubKey)) + fRecoverable = setDerivedPubKeys.count(vchPubKey) > 0; + + if (fRecoverable) + { + if (fImmature) + audit.nRecoverableImmatureCredit += txout.nValue; + else + audit.nRecoverableCredit += txout.nValue; + fTxRecoverable = true; + } + else + { + if (fImmature) + audit.nLegacyImmatureCredit += txout.nValue; + else + audit.nLegacyCredit += txout.nValue; + fTxLegacy = true; + } + } + + if (fTxRecoverable) + { + if (fImmature) + audit.nRecoverableImmatureTx++; + else + audit.nRecoverableTx++; + } + if (fTxLegacy) + { + if (fImmature) + audit.nLegacyImmatureTx++; + else + audit.nLegacyTx++; + } + } + } + + return audit; +} + int64 GetBalance() { int64 nStart, nEnd; -- cgit v1.2.3