Skip to content

Commit 5aacc3e

Browse files
author
Antoine Riard
committed
Add m_last_block_processed_height field in CWallet
At BlockConnected/BlockDisconnected, we rely on height of block itself to know current height of wallet
1 parent 10b4729 commit 5aacc3e

File tree

4 files changed

+54
-5
lines changed

4 files changed

+54
-5
lines changed

src/qt/test/wallettests.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,12 @@ void TestGUI(interfaces::Node& node)
139139
wallet->LoadWallet(firstRun);
140140
{
141141
auto spk_man = wallet->GetLegacyScriptPubKeyMan();
142+
auto locked_chain = wallet->chain().lock();
142143
LOCK(wallet->cs_wallet);
143144
AssertLockHeld(spk_man->cs_wallet);
144145
wallet->SetAddressBook(GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet->m_default_address_type), "", "receive");
145146
spk_man->AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
147+
wallet->SetLastBlockProcessed(105, ::ChainActive().Tip()->GetBlockHash());
146148
}
147149
{
148150
auto locked_chain = wallet->chain().lock();

src/wallet/test/wallet_tests.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
5050
// Verify ScanForWalletTransactions accommodates a null start block.
5151
{
5252
CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
53+
{
54+
LOCK(wallet.cs_wallet);
55+
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
56+
}
5357
AddKey(wallet, coinbaseKey);
5458
WalletRescanReserver reserver(&wallet);
5559
reserver.reserve();
@@ -65,6 +69,10 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
6569
// and new block files.
6670
{
6771
CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
72+
{
73+
LOCK(wallet.cs_wallet);
74+
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
75+
}
6876
AddKey(wallet, coinbaseKey);
6977
WalletRescanReserver reserver(&wallet);
7078
reserver.reserve();
@@ -84,6 +92,10 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
8492
// file.
8593
{
8694
CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
95+
{
96+
LOCK(wallet.cs_wallet);
97+
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
98+
}
8799
AddKey(wallet, coinbaseKey);
88100
WalletRescanReserver reserver(&wallet);
89101
reserver.reserve();
@@ -102,6 +114,10 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
102114
// Verify ScanForWalletTransactions scans no blocks.
103115
{
104116
CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
117+
{
118+
LOCK(wallet.cs_wallet);
119+
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
120+
}
105121
AddKey(wallet, coinbaseKey);
106122
WalletRescanReserver reserver(&wallet);
107123
reserver.reserve();
@@ -258,6 +274,7 @@ BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
258274
LockAssertion lock(::cs_main);
259275
LOCK(wallet.cs_wallet);
260276
AssertLockHeld(spk_man->cs_wallet);
277+
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
261278

262279
wtx.SetConf(CWalletTx::Status::CONFIRMED, ::ChainActive().Tip()->GetBlockHash(), 0);
263280

@@ -435,6 +452,10 @@ class ListCoinsTestingSetup : public TestChain100Setup
435452
{
436453
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
437454
wallet = MakeUnique<CWallet>(m_chain.get(), WalletLocation(), WalletDatabase::CreateMock());
455+
{
456+
LOCK(wallet->cs_wallet);
457+
wallet->SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
458+
}
438459
bool firstRun;
439460
wallet->LoadWallet(firstRun);
440461
AddKey(*wallet, coinbaseKey);
@@ -473,6 +494,7 @@ class ListCoinsTestingSetup : public TestChain100Setup
473494

474495
LOCK(cs_main);
475496
LOCK(wallet->cs_wallet);
497+
wallet->SetLastBlockProcessed(wallet->GetLastBlockHeight() + 1, ::ChainActive().Tip()->GetBlockHash());
476498
auto it = wallet->mapWallet.find(tx->GetHash());
477499
BOOST_CHECK(it != wallet->mapWallet.end());
478500
it->second.SetConf(CWalletTx::Status::CONFIRMED, ::ChainActive().Tip()->GetBlockHash(), 1);

src/wallet/wallet.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,15 +1058,15 @@ void CWallet::BlockConnected(const CBlock& block, const std::vector<CTransaction
10581058
auto locked_chain = chain().lock();
10591059
LOCK(cs_wallet);
10601060

1061+
m_last_block_processed_height = height;
1062+
m_last_block_processed = block_hash;
10611063
for (size_t i = 0; i < block.vtx.size(); i++) {
10621064
SyncTransaction(block.vtx[i], CWalletTx::Status::CONFIRMED, block_hash, i);
10631065
TransactionRemovedFromMempool(block.vtx[i]);
10641066
}
10651067
for (const CTransactionRef& ptx : vtxConflicted) {
10661068
TransactionRemovedFromMempool(ptx);
10671069
}
1068-
1069-
m_last_block_processed = block_hash;
10701070
}
10711071

10721072
void CWallet::BlockDisconnected(const CBlock& block, int height)
@@ -1078,6 +1078,8 @@ void CWallet::BlockDisconnected(const CBlock& block, int height)
10781078
// be unconfirmed, whether or not the transaction is added back to the mempool.
10791079
// User may have to call abandontransaction again. It may be addressed in the
10801080
// future with a stickier abandoned state or even removing abandontransaction call.
1081+
m_last_block_processed_height = height - 1;
1082+
m_last_block_processed = block.hashPrevBlock;
10811083
for (const CTransactionRef& ptx : block.vtx) {
10821084
SyncTransaction(ptx, CWalletTx::Status::UNCONFIRMED, {} /* block hash */, 0 /* position in block */);
10831085
}
@@ -3785,8 +3787,10 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
37853787
const Optional<int> tip_height = locked_chain->getHeight();
37863788
if (tip_height) {
37873789
walletInstance->m_last_block_processed = locked_chain->getBlockHash(*tip_height);
3790+
walletInstance->m_last_block_processed_height = *tip_height;
37883791
} else {
37893792
walletInstance->m_last_block_processed.SetNull();
3793+
walletInstance->m_last_block_processed_height = -1;
37903794
}
37913795

37923796
if (tip_height && *tip_height != rescan_height)

src/wallet/wallet.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -679,12 +679,18 @@ class CWallet final : public WalletStorage, private interfaces::Chain::Notificat
679679
* The following is used to keep track of how far behind the wallet is
680680
* from the chain sync, and to allow clients to block on us being caught up.
681681
*
682-
* Note that this is *not* how far we've processed, we may need some rescan
683-
* to have seen all transactions in the chain, but is only used to track
684-
* live BlockConnected callbacks.
682+
* Processed hash is a pointer on node's tip and doesn't imply that the wallet
683+
* has scanned sequentially all blocks up to this one.
685684
*/
686685
uint256 m_last_block_processed GUARDED_BY(cs_wallet);
687686

687+
/* Height of last block processed is used by wallet to know depth of transactions
688+
* without relying on Chain interface beyond asynchronous updates. For safety, we
689+
* initialize it to -1. Height is a pointer on node's tip and doesn't imply
690+
* that the wallet has scanned sequentially all blocks up to this one.
691+
*/
692+
int m_last_block_processed_height GUARDED_BY(cs_wallet) = -1;
693+
688694
public:
689695
/*
690696
* Main wallet lock.
@@ -1129,6 +1135,21 @@ class CWallet final : public WalletStorage, private interfaces::Chain::Notificat
11291135
LegacyScriptPubKeyMan::WatchKeyMap& mapWatchKeys GUARDED_BY(cs_KeyStore) = m_spk_man->mapWatchKeys;
11301136
WalletBatch*& encrypted_batch GUARDED_BY(cs_wallet) = m_spk_man->encrypted_batch;
11311137
using CryptedKeyMap = LegacyScriptPubKeyMan::CryptedKeyMap;
1138+
1139+
/** Get last block processed height */
1140+
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
1141+
{
1142+
AssertLockHeld(cs_wallet);
1143+
assert(m_last_block_processed_height >= 0);
1144+
return m_last_block_processed_height;
1145+
};
1146+
/** Set last block processed height, currently only use in unit test */
1147+
void SetLastBlockProcessed(int block_height, uint256 block_hash) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
1148+
{
1149+
AssertLockHeld(cs_wallet);
1150+
m_last_block_processed_height = block_height;
1151+
m_last_block_processed = block_hash;
1152+
};
11321153
};
11331154

11341155
/**

0 commit comments

Comments
 (0)