diff options
author | W. J. van der Laan <laanwj@protonmail.com> | 2021-10-01 10:30:26 +0200 |
---|---|---|
committer | W. J. van der Laan <laanwj@protonmail.com> | 2021-10-01 10:32:10 +0200 |
commit | 46b4937bc16cbccabaf27ca9c1d605646bdea67e (patch) | |
tree | 6de43c39c746a9f451d852c736c343a28a15df48 /src/wallet | |
parent | 29b030bca31d1246e94b3396b0a01a17dadc96a8 (diff) | |
parent | 0ab4c3b27265401c59e40adc494041927dc9dbe3 (diff) |
Merge bitcoin/bitcoin#23142: Return false on corrupt tx rather than asserting
0ab4c3b27265401c59e40adc494041927dc9dbe3 Return false on corrupt tx rather than asserting (Samuel Dobson)
Pull request description:
Takes up #19793
Rather than asserting, we log an error and return CORRUPT so that the user is informed. This type of error isn't critical so it isn't worth `assert`ing.
ACKs for top commit:
achow101:
ACK 0ab4c3b27265401c59e40adc494041927dc9dbe3
laanwj:
Code review ACK 0ab4c3b27265401c59e40adc494041927dc9dbe3
ryanofsky:
Code review ACK 0ab4c3b27265401c59e40adc494041927dc9dbe3. There may be room for more improvements later like better error messages or easier recovery options, but changing from an assert to an error seems like a clear improvement, and this seems to avoid all the pitfalls of the last PR that tried this.
Tree-SHA512: 4a1a412e7c473d176c4e09123b85f390a6b0ea195e78d28ebd50b13814b7852f8225a172511a2efb6affb555b11bd4e667c19eb8c78b060c5444b62f0fae5f7a
Diffstat (limited to 'src/wallet')
-rw-r--r-- | src/wallet/walletdb.cpp | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 528f77b14c..8ff09a0878 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -311,6 +311,7 @@ public: std::map<std::pair<uint256, CKeyID>, CKey> m_descriptor_keys; std::map<std::pair<uint256, CKeyID>, std::pair<CPubKey, std::vector<unsigned char>>> m_descriptor_crypt_keys; std::map<uint160, CHDChain> m_hd_chains; + bool tx_corrupt{false}; CWalletScanState() { } @@ -345,7 +346,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, // LoadToWallet call below creates a new CWalletTx that fill_wtx // callback fills with transaction metadata. auto fill_wtx = [&](CWalletTx& wtx, bool new_tx) { - assert(new_tx); + if(!new_tx) { + // There's some corruption here since the tx we just tried to load was already in the wallet. + // We don't consider this type of corruption critical, and can fix it by removing tx data and + // rescanning. + wss.tx_corrupt = true; + return false; + } ssValue >> wtx; if (wtx.GetHash() != hash) return false; @@ -819,6 +826,11 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet) } else if (strType == DBKeys::FLAGS) { // reading the wallet flags can only fail if unknown flags are present result = DBErrors::TOO_NEW; + } else if (wss.tx_corrupt) { + pwallet->WalletLogPrintf("Error: Corrupt transaction found. This can be fixed by removing transactions from wallet and rescanning.\n"); + // Set tx_corrupt back to false so that the error is only printed once (per corrupt tx) + wss.tx_corrupt = false; + result = DBErrors::CORRUPT; } else { // Leave other errors alone, if we try to fix them we might make things worse. fNoncriticalErrors = true; // ... but do warn the user there is something wrong. |