@@ -663,6 +663,22 @@ void CWallet::chainStateFlushed(ChainstateRole role, const CBlockLocator& loc)
663
663
batch.WriteBestBlock (loc);
664
664
}
665
665
666
+ void CWallet::SetLastBlockProcessedInMem (int block_height, uint256 block_hash)
667
+ {
668
+ AssertLockHeld (cs_wallet);
669
+
670
+ m_last_block_processed = block_hash;
671
+ m_last_block_processed_height = block_height;
672
+ }
673
+
674
+ void CWallet::SetLastBlockProcessed (int block_height, uint256 block_hash)
675
+ {
676
+ AssertLockHeld (cs_wallet);
677
+
678
+ SetLastBlockProcessedInMem (block_height, block_hash);
679
+ WriteBestBlock ();
680
+ }
681
+
666
682
void CWallet::SetMinVersion (enum WalletFeature nVersion, WalletBatch* batch_in)
667
683
{
668
684
LOCK (cs_wallet);
@@ -1378,15 +1394,16 @@ void CWallet::RecursiveUpdateTxState(WalletBatch* batch, const uint256& tx_hash,
1378
1394
}
1379
1395
}
1380
1396
1381
- void CWallet::SyncTransaction (const CTransactionRef& ptx, const SyncTxState& state, bool update_tx, bool rescanning_old_block)
1397
+ bool CWallet::SyncTransaction (const CTransactionRef& ptx, const SyncTxState& state, bool update_tx, bool rescanning_old_block)
1382
1398
{
1383
1399
if (!AddToWalletIfInvolvingMe (ptx, state, update_tx, rescanning_old_block))
1384
- return ; // Not one of ours
1400
+ return false ; // Not one of ours
1385
1401
1386
1402
// If a transaction changes 'conflicted' state, that changes the balance
1387
1403
// available of the outputs it spends. So force those to be
1388
1404
// recomputed, also:
1389
1405
MarkInputsDirty (ptx);
1406
+ return true ;
1390
1407
}
1391
1408
1392
1409
void CWallet::transactionAddedToMempool (const CTransactionRef& tx) {
@@ -1473,18 +1490,25 @@ void CWallet::blockConnected(ChainstateRole role, const interfaces::BlockInfo& b
1473
1490
assert (block.data );
1474
1491
LOCK (cs_wallet);
1475
1492
1476
- m_last_block_processed_height = block.height ;
1477
- m_last_block_processed = block.hash ;
1493
+ // Update the best block in memory first. This will set the best block's height, which is
1494
+ // needed by MarkConflicted.
1495
+ SetLastBlockProcessedInMem (block.height , block.hash );
1478
1496
1479
1497
// No need to scan block if it was created before the wallet birthday.
1480
1498
// Uses chain max time and twice the grace period to adjust time for block time variability.
1481
1499
if (block.chain_time_max < m_birth_time.load () - (TIMESTAMP_WINDOW * 2 )) return ;
1482
1500
1483
1501
// Scan block
1502
+ bool wallet_updated = false ;
1484
1503
for (size_t index = 0 ; index < block.data ->vtx .size (); index++) {
1485
- SyncTransaction (block.data ->vtx [index], TxStateConfirmed{block.hash , block.height , static_cast <int >(index)});
1504
+ wallet_updated |= SyncTransaction (block.data ->vtx [index], TxStateConfirmed{block.hash , block.height , static_cast <int >(index)});
1486
1505
transactionRemovedFromMempool (block.data ->vtx [index], MemPoolRemovalReason::BLOCK);
1487
1506
}
1507
+
1508
+ // Update on disk if this block resulted in us updating a tx, or periodically every 144 blocks (~1 day)
1509
+ if (wallet_updated || block.height % 144 == 0 ) {
1510
+ WriteBestBlock ();
1511
+ }
1488
1512
}
1489
1513
1490
1514
void CWallet::blockDisconnected (const interfaces::BlockInfo& block)
@@ -1496,9 +1520,6 @@ void CWallet::blockDisconnected(const interfaces::BlockInfo& block)
1496
1520
// be unconfirmed, whether or not the transaction is added back to the mempool.
1497
1521
// User may have to call abandontransaction again. It may be addressed in the
1498
1522
// future with a stickier abandoned state or even removing abandontransaction call.
1499
- m_last_block_processed_height = block.height - 1 ;
1500
- m_last_block_processed = *Assert (block.prev_hash );
1501
-
1502
1523
int disconnect_height = block.height ;
1503
1524
1504
1525
for (size_t index = 0 ; index < block.data ->vtx .size (); index++) {
@@ -1532,6 +1553,9 @@ void CWallet::blockDisconnected(const interfaces::BlockInfo& block)
1532
1553
}
1533
1554
}
1534
1555
}
1556
+
1557
+ // Update the best block
1558
+ SetLastBlockProcessed (block.height - 1 , *Assert (block.prev_hash ));
1535
1559
}
1536
1560
1537
1561
void CWallet::updatedBlockTip ()
@@ -3264,14 +3288,7 @@ void CWallet::postInitProcess()
3264
3288
3265
3289
bool CWallet::BackupWallet (const std::string& strDest) const
3266
3290
{
3267
- if (m_chain) {
3268
- CBlockLocator loc;
3269
- WITH_LOCK (cs_wallet, chain ().findBlock (m_last_block_processed, FoundBlock ().locator (loc)));
3270
- if (!loc.IsNull ()) {
3271
- WalletBatch batch (GetDatabase ());
3272
- batch.WriteBestBlock (loc);
3273
- }
3274
- }
3291
+ WITH_LOCK (cs_wallet, WriteBestBlock ());
3275
3292
return GetDatabase ().Backup (strDest);
3276
3293
}
3277
3294
@@ -4453,4 +4470,17 @@ std::optional<CKey> CWallet::GetKey(const CKeyID& keyid) const
4453
4470
}
4454
4471
return std::nullopt;
4455
4472
}
4473
+
4474
+ void CWallet::WriteBestBlock () const
4475
+ {
4476
+ AssertLockHeld (cs_wallet);
4477
+
4478
+ if (!m_last_block_processed.IsNull ()) {
4479
+ CBlockLocator loc;
4480
+ chain ().findBlock (m_last_block_processed, FoundBlock ().locator (loc));
4481
+
4482
+ WalletBatch batch (GetDatabase ());
4483
+ batch.WriteBestBlock (loc);
4484
+ }
4485
+ }
4456
4486
} // namespace wallet
0 commit comments