@@ -301,11 +301,8 @@ bool WalletBatch::EraseLockedUTXO(const COutPoint& output)
301
301
class CWalletScanState {
302
302
public:
303
303
unsigned int m_unknown_records{0 };
304
- bool fAnyUnordered {false };
305
- std::vector<uint256> vWalletUpgrade;
306
304
std::map<OutputType, uint256> m_active_external_spks;
307
305
std::map<OutputType, uint256> m_active_internal_spks;
308
- bool tx_corrupt{false };
309
306
310
307
CWalletScanState () = default ;
311
308
};
@@ -473,51 +470,6 @@ ReadKeyValue(CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue,
473
470
if (strType == DBKeys::NAME) {
474
471
} else if (strType == DBKeys::PURPOSE) {
475
472
} else if (strType == DBKeys::TX) {
476
- uint256 hash;
477
- ssKey >> hash;
478
- // LoadToWallet call below creates a new CWalletTx that fill_wtx
479
- // callback fills with transaction metadata.
480
- auto fill_wtx = [&](CWalletTx& wtx, bool new_tx) {
481
- if (!new_tx) {
482
- // There's some corruption here since the tx we just tried to load was already in the wallet.
483
- // We don't consider this type of corruption critical, and can fix it by removing tx data and
484
- // rescanning.
485
- wss.tx_corrupt = true ;
486
- return false ;
487
- }
488
- ssValue >> wtx;
489
- if (wtx.GetHash () != hash)
490
- return false ;
491
-
492
- // Undo serialize changes in 31600
493
- if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703 )
494
- {
495
- if (!ssValue.empty ())
496
- {
497
- uint8_t fTmp ;
498
- uint8_t fUnused ;
499
- std::string unused_string;
500
- ssValue >> fTmp >> fUnused >> unused_string;
501
- strErr = strprintf (" LoadWallet() upgrading tx ver=%d %d %s" ,
502
- wtx.fTimeReceivedIsTxTime , fTmp , hash.ToString ());
503
- wtx.fTimeReceivedIsTxTime = fTmp ;
504
- }
505
- else
506
- {
507
- strErr = strprintf (" LoadWallet() repairing tx ver=%d %s" , wtx.fTimeReceivedIsTxTime , hash.ToString ());
508
- wtx.fTimeReceivedIsTxTime = 0 ;
509
- }
510
- wss.vWalletUpgrade .push_back (hash);
511
- }
512
-
513
- if (wtx.nOrderPos == -1 )
514
- wss.fAnyUnordered = true ;
515
-
516
- return true ;
517
- };
518
- if (!pwallet->LoadToWallet (hash, fill_wtx)) {
519
- return false ;
520
- }
521
473
} else if (strType == DBKeys::WATCHS) {
522
474
} else if (strType == DBKeys::KEY) {
523
475
} else if (strType == DBKeys::MASTER_KEY) {
@@ -537,7 +489,6 @@ ReadKeyValue(CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue,
537
489
} else if (strType == DBKeys::POOL) {
538
490
} else if (strType == DBKeys::CSCRIPT) {
539
491
} else if (strType == DBKeys::ORDERPOSNEXT) {
540
- ssValue >> pwallet->nOrderPosNext ;
541
492
} else if (strType == DBKeys::DESTDATA) {
542
493
} else if (strType == DBKeys::HDCHAIN) {
543
494
} else if (strType == DBKeys::OLD_KEY) {
@@ -562,11 +513,6 @@ ReadKeyValue(CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue,
562
513
} else if (strType == DBKeys::WALLETDESCRIPTORKEY) {
563
514
} else if (strType == DBKeys::WALLETDESCRIPTORCKEY) {
564
515
} else if (strType == DBKeys::LOCKED_UTXO) {
565
- uint256 hash;
566
- uint32_t n;
567
- ssKey >> hash;
568
- ssKey >> n;
569
- pwallet->LockCoin (COutPoint (hash, n));
570
516
} else if (strType != DBKeys::BESTBLOCK && strType != DBKeys::BESTBLOCK_NOMERKLE &&
571
517
strType != DBKeys::MINVERSION && strType != DBKeys::ACENTRY &&
572
518
strType != DBKeys::VERSION && strType != DBKeys::SETTINGS &&
@@ -1112,12 +1058,101 @@ static DBErrors LoadAddressBookRecords(CWallet* pwallet, DatabaseBatch& batch) E
1112
1058
return result;
1113
1059
}
1114
1060
1061
+ static DBErrors LoadTxRecords (CWallet* pwallet, DatabaseBatch& batch, std::vector<uint256>& upgraded_txs, bool & any_unordered) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
1062
+ {
1063
+ AssertLockHeld (pwallet->cs_wallet );
1064
+ DBErrors result = DBErrors::LOAD_OK;
1065
+
1066
+ // Load tx record
1067
+ any_unordered = false ;
1068
+ LoadResult tx_res = LoadRecords (pwallet, batch, DBKeys::TX,
1069
+ [&any_unordered, &upgraded_txs] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) EXCLUSIVE_LOCKS_REQUIRED (pwallet->cs_wallet ) {
1070
+ DBErrors result = DBErrors::LOAD_OK;
1071
+ uint256 hash;
1072
+ key >> hash;
1073
+ // LoadToWallet call below creates a new CWalletTx that fill_wtx
1074
+ // callback fills with transaction metadata.
1075
+ auto fill_wtx = [&](CWalletTx& wtx, bool new_tx) {
1076
+ if (!new_tx) {
1077
+ // There's some corruption here since the tx we just tried to load was already in the wallet.
1078
+ err = " Error: Corrupt transaction found. This can be fixed by removing transactions from wallet and rescanning." ;
1079
+ result = DBErrors::CORRUPT;
1080
+ return false ;
1081
+ }
1082
+ value >> wtx;
1083
+ if (wtx.GetHash () != hash)
1084
+ return false ;
1085
+
1086
+ // Undo serialize changes in 31600
1087
+ if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703 )
1088
+ {
1089
+ if (!value.empty ())
1090
+ {
1091
+ uint8_t fTmp ;
1092
+ uint8_t fUnused ;
1093
+ std::string unused_string;
1094
+ value >> fTmp >> fUnused >> unused_string;
1095
+ pwallet->WalletLogPrintf (" LoadWallet() upgrading tx ver=%d %d %s\n " ,
1096
+ wtx.fTimeReceivedIsTxTime , fTmp , hash.ToString ());
1097
+ wtx.fTimeReceivedIsTxTime = fTmp ;
1098
+ }
1099
+ else
1100
+ {
1101
+ pwallet->WalletLogPrintf (" LoadWallet() repairing tx ver=%d %s\n " , wtx.fTimeReceivedIsTxTime , hash.ToString ());
1102
+ wtx.fTimeReceivedIsTxTime = 0 ;
1103
+ }
1104
+ upgraded_txs.push_back (hash);
1105
+ }
1106
+
1107
+ if (wtx.nOrderPos == -1 )
1108
+ any_unordered = true ;
1109
+
1110
+ return true ;
1111
+ };
1112
+ if (!pwallet->LoadToWallet (hash, fill_wtx)) {
1113
+ // Use std::max as fill_wtx may have already set result to CORRUPT
1114
+ result = std::max (result, DBErrors::NEED_RESCAN);
1115
+ }
1116
+ return result;
1117
+ });
1118
+ result = std::max (result, tx_res.m_result );
1119
+
1120
+ // Load locked utxo record
1121
+ LoadResult locked_utxo_res = LoadRecords (pwallet, batch, DBKeys::LOCKED_UTXO,
1122
+ [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) EXCLUSIVE_LOCKS_REQUIRED (pwallet->cs_wallet ) {
1123
+ uint256 hash;
1124
+ uint32_t n;
1125
+ key >> hash;
1126
+ key >> n;
1127
+ pwallet->LockCoin (COutPoint (hash, n));
1128
+ return DBErrors::LOAD_OK;
1129
+ });
1130
+ result = std::max (result, locked_utxo_res.m_result );
1131
+
1132
+ // Load orderposnext record
1133
+ // Note: There should only be one ORDERPOSNEXT record with nothing trailing the type
1134
+ LoadResult order_pos_res = LoadRecords (pwallet, batch, DBKeys::ORDERPOSNEXT,
1135
+ [] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) EXCLUSIVE_LOCKS_REQUIRED (pwallet->cs_wallet ) {
1136
+ try {
1137
+ value >> pwallet->nOrderPosNext ;
1138
+ } catch (const std::exception& e) {
1139
+ err = e.what ();
1140
+ return DBErrors::NONCRITICAL_ERROR;
1141
+ }
1142
+ return DBErrors::LOAD_OK;
1143
+ });
1144
+ result = std::max (result, order_pos_res.m_result );
1145
+
1146
+ return result;
1147
+ }
1148
+
1115
1149
DBErrors WalletBatch::LoadWallet (CWallet* pwallet)
1116
1150
{
1117
1151
CWalletScanState wss;
1118
1152
bool fNoncriticalErrors = false ;
1119
- bool rescan_required = false ;
1120
1153
DBErrors result = DBErrors::LOAD_OK;
1154
+ bool any_unordered = false ;
1155
+ std::vector<uint256> upgraded_txs;
1121
1156
1122
1157
LOCK (pwallet->cs_wallet );
1123
1158
@@ -1153,6 +1188,9 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
1153
1188
// Load address book
1154
1189
result = std::max (LoadAddressBookRecords (pwallet, *m_batch), result);
1155
1190
1191
+ // Load tx records
1192
+ result = std::max (LoadTxRecords (pwallet, *m_batch, upgraded_txs, any_unordered), result);
1193
+
1156
1194
// Get cursor
1157
1195
std::unique_ptr<DatabaseCursor> cursor = m_batch->GetNewCursor ();
1158
1196
if (!cursor)
@@ -1184,17 +1222,9 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
1184
1222
if (strType == DBKeys::MASTER_KEY ||
1185
1223
strType == DBKeys::DEFAULTKEY) {
1186
1224
result = DBErrors::CORRUPT;
1187
- } else if (wss.tx_corrupt ) {
1188
- pwallet->WalletLogPrintf (" Error: Corrupt transaction found. This can be fixed by removing transactions from wallet and rescanning.\n " );
1189
- // Set tx_corrupt back to false so that the error is only printed once (per corrupt tx)
1190
- wss.tx_corrupt = false ;
1191
- result = DBErrors::CORRUPT;
1192
1225
} else {
1193
1226
// Leave other errors alone, if we try to fix them we might make things worse.
1194
1227
fNoncriticalErrors = true ; // ... but do warn the user there is something wrong.
1195
- if (strType == DBKeys::TX)
1196
- // Rescan if there is a bad transaction record:
1197
- rescan_required = true ;
1198
1228
}
1199
1229
}
1200
1230
if (!strErr.empty ())
@@ -1214,9 +1244,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
1214
1244
pwallet->LoadActiveScriptPubKeyMan (spk_man_pair.second , spk_man_pair.first , /* internal=*/ true );
1215
1245
}
1216
1246
1217
- if (rescan_required && result == DBErrors::LOAD_OK) {
1218
- result = DBErrors::NEED_RESCAN;
1219
- } else if (fNoncriticalErrors && result == DBErrors::LOAD_OK) {
1247
+ if (fNoncriticalErrors && result == DBErrors::LOAD_OK) {
1220
1248
result = DBErrors::NONCRITICAL_ERROR;
1221
1249
}
1222
1250
@@ -1225,13 +1253,13 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
1225
1253
if (result != DBErrors::LOAD_OK)
1226
1254
return result;
1227
1255
1228
- for (const uint256& hash : wss. vWalletUpgrade )
1256
+ for (const uint256& hash : upgraded_txs )
1229
1257
WriteTx (pwallet->mapWallet .at (hash));
1230
1258
1231
1259
if (!has_last_client || last_client != CLIENT_VERSION) // Update
1232
1260
m_batch->Write (DBKeys::VERSION, CLIENT_VERSION);
1233
1261
1234
- if (wss. fAnyUnordered )
1262
+ if (any_unordered )
1235
1263
result = pwallet->ReorderTransactions ();
1236
1264
1237
1265
// Upgrade all of the wallet keymetadata to have the hd master key id
0 commit comments