Skip to content

Commit 91868e6

Browse files
committed
Remove use CValidationInterface in wallet code
This commit does not change behavior.
1 parent d8a62db commit 91868e6

File tree

6 files changed

+107
-25
lines changed

6 files changed

+107
-25
lines changed

src/interfaces/chain.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <chain.h>
88
#include <chainparams.h>
9+
#include <interfaces/handler.h>
910
#include <interfaces/wallet.h>
1011
#include <net.h>
1112
#include <policy/fees.h>
@@ -22,6 +23,7 @@
2223
#include <uint256.h>
2324
#include <util/system.h>
2425
#include <validation.h>
26+
#include <validationinterface.h>
2527

2628
#include <memory>
2729
#include <utility>
@@ -161,6 +163,55 @@ class LockingStateImpl : public LockImpl, public UniqueLock<CCriticalSection>
161163
using UniqueLock::UniqueLock;
162164
};
163165

166+
class NotificationsHandlerImpl : public Handler, CValidationInterface
167+
{
168+
public:
169+
explicit NotificationsHandlerImpl(Chain& chain, Chain::Notifications& notifications)
170+
: m_chain(chain), m_notifications(&notifications)
171+
{
172+
RegisterValidationInterface(this);
173+
}
174+
~NotificationsHandlerImpl() override { disconnect(); }
175+
void disconnect() override
176+
{
177+
if (m_notifications) {
178+
m_notifications = nullptr;
179+
UnregisterValidationInterface(this);
180+
}
181+
}
182+
void TransactionAddedToMempool(const CTransactionRef& tx) override
183+
{
184+
m_notifications->TransactionAddedToMempool(tx);
185+
}
186+
void TransactionRemovedFromMempool(const CTransactionRef& tx) override
187+
{
188+
m_notifications->TransactionRemovedFromMempool(tx);
189+
}
190+
void BlockConnected(const std::shared_ptr<const CBlock>& block,
191+
const CBlockIndex* index,
192+
const std::vector<CTransactionRef>& tx_conflicted) override
193+
{
194+
m_notifications->BlockConnected(*block, tx_conflicted);
195+
}
196+
void BlockDisconnected(const std::shared_ptr<const CBlock>& block) override
197+
{
198+
m_notifications->BlockDisconnected(*block);
199+
}
200+
void ChainStateFlushed(const CBlockLocator& locator) override { m_notifications->ChainStateFlushed(locator); }
201+
void ResendWalletTransactions(int64_t best_block_time, CConnman*) override
202+
{
203+
// `cs_main` is always held when this method is called, so it is safe to
204+
// call `assumeLocked`. This is awkward, and the `assumeLocked` method
205+
// should be able to be removed entirely if `ResendWalletTransactions`
206+
// is replaced by a wallet timer as suggested in
207+
// https://github.com/bitcoin/bitcoin/issues/15619
208+
auto locked_chain = m_chain.assumeLocked();
209+
m_notifications->ResendWalletTransactions(*locked_chain, best_block_time);
210+
}
211+
Chain& m_chain;
212+
Chain::Notifications* m_notifications;
213+
};
214+
164215
class ChainImpl : public Chain
165216
{
166217
public:
@@ -254,6 +305,11 @@ class ChainImpl : public Chain
254305
void initWarning(const std::string& message) override { InitWarning(message); }
255306
void initError(const std::string& message) override { InitError(message); }
256307
void loadWallet(std::unique_ptr<Wallet> wallet) override { ::uiInterface.LoadWallet(wallet); }
308+
std::unique_ptr<Handler> handleNotifications(Notifications& notifications) override
309+
{
310+
return MakeUnique<NotificationsHandlerImpl>(*this, notifications);
311+
}
312+
void waitForNotifications() override { SyncWithValidationInterfaceQueue(); }
257313
};
258314

259315
} // namespace

src/interfaces/chain.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ struct FeeCalculation;
2525

2626
namespace interfaces {
2727

28+
class Handler;
2829
class Wallet;
2930

3031
//! Interface giving clients (wallet processes, maybe other analysis tools in
@@ -40,6 +41,12 @@ class Wallet;
4041
//! asynchronously
4142
//! (https://github.com/bitcoin/bitcoin/pull/10973#issuecomment-380101269).
4243
//!
44+
//! * The isPotentialTip() and waitForNotifications() methods are too low-level
45+
//! and should be replaced with a higher level
46+
//! waitForNotificationsUpTo(block_hash) method that the wallet can call
47+
//! instead
48+
//! (https://github.com/bitcoin/bitcoin/pull/10973#discussion_r266995234).
49+
//!
4350
//! * The relayTransactions() and submitToMemoryPool() methods could be replaced
4451
//! with a higher-level broadcastTransaction method
4552
//! (https://github.com/bitcoin/bitcoin/pull/14978#issuecomment-459373984).
@@ -217,6 +224,25 @@ class Chain
217224

218225
//! Send wallet load notification to the GUI.
219226
virtual void loadWallet(std::unique_ptr<Wallet> wallet) = 0;
227+
228+
//! Chain notifications.
229+
class Notifications
230+
{
231+
public:
232+
virtual ~Notifications() {}
233+
virtual void TransactionAddedToMempool(const CTransactionRef& tx) {}
234+
virtual void TransactionRemovedFromMempool(const CTransactionRef& ptx) {}
235+
virtual void BlockConnected(const CBlock& block, const std::vector<CTransactionRef>& tx_conflicted) {}
236+
virtual void BlockDisconnected(const CBlock& block) {}
237+
virtual void ChainStateFlushed(const CBlockLocator& locator) {}
238+
virtual void ResendWalletTransactions(Lock& locked_chain, int64_t best_block_time) {}
239+
};
240+
241+
//! Register handler for notifications.
242+
virtual std::unique_ptr<Handler> handleNotifications(Notifications& notifications) = 0;
243+
244+
//! Wait for pending notifications to be handled.
245+
virtual void waitForNotifications() = 0;
220246
};
221247

222248
//! Interface to let node manage chain clients (wallets, or maybe tools for

src/wallet/test/wallet_test_fixture.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,7 @@ WalletTestingSetup::WalletTestingSetup(const std::string& chainName):
1313
{
1414
bool fFirstRun;
1515
m_wallet.LoadWallet(fFirstRun);
16-
RegisterValidationInterface(&m_wallet);
16+
m_wallet.m_chain_notifications_handler = m_chain->handleNotifications(m_wallet);
1717

1818
RegisterWalletRPCCommands(tableRPC);
1919
}
20-
21-
WalletTestingSetup::~WalletTestingSetup()
22-
{
23-
UnregisterValidationInterface(&m_wallet);
24-
}

src/wallet/test/wallet_test_fixture.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
*/
1818
struct WalletTestingSetup: public TestingSetup {
1919
explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
20-
~WalletTestingSetup();
2120

2221
std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain();
2322
CWallet m_wallet;

src/wallet/wallet.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ static void ReleaseWallet(CWallet* wallet)
9696
wallet->WalletLogPrintf("Releasing wallet\n");
9797
wallet->BlockUntilSyncedToCurrentChain();
9898
wallet->Flush();
99-
UnregisterValidationInterface(wallet);
99+
wallet->m_chain_notifications_handler.reset();
100100
delete wallet;
101101
// Wallet is now released, notify UnloadWallet, if any.
102102
{
@@ -1243,7 +1243,8 @@ void CWallet::TransactionRemovedFromMempool(const CTransactionRef &ptx) {
12431243
}
12441244
}
12451245

1246-
void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) {
1246+
void CWallet::BlockConnected(const CBlock& block, const std::vector<CTransactionRef>& vtxConflicted) {
1247+
const uint256& block_hash = block.GetHash();
12471248
auto locked_chain = chain().lock();
12481249
LOCK(cs_wallet);
12491250
// TODO: Temporarily ensure that mempool removals are notified before
@@ -1258,19 +1259,19 @@ void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const
12581259
SyncTransaction(ptx, {} /* block hash */, 0 /* position in block */);
12591260
TransactionRemovedFromMempool(ptx);
12601261
}
1261-
for (size_t i = 0; i < pblock->vtx.size(); i++) {
1262-
SyncTransaction(pblock->vtx[i], pindex->GetBlockHash(), i);
1263-
TransactionRemovedFromMempool(pblock->vtx[i]);
1262+
for (size_t i = 0; i < block.vtx.size(); i++) {
1263+
SyncTransaction(block.vtx[i], block_hash, i);
1264+
TransactionRemovedFromMempool(block.vtx[i]);
12641265
}
12651266

1266-
m_last_block_processed = pindex->GetBlockHash();
1267+
m_last_block_processed = block_hash;
12671268
}
12681269

1269-
void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) {
1270+
void CWallet::BlockDisconnected(const CBlock& block) {
12701271
auto locked_chain = chain().lock();
12711272
LOCK(cs_wallet);
12721273

1273-
for (const CTransactionRef& ptx : pblock->vtx) {
1274+
for (const CTransactionRef& ptx : block.vtx) {
12741275
SyncTransaction(ptx, {} /* block hash */, 0 /* position in block */);
12751276
}
12761277
}
@@ -1297,7 +1298,7 @@ void CWallet::BlockUntilSyncedToCurrentChain() {
12971298
// ...otherwise put a callback in the validation interface queue and wait
12981299
// for the queue to drain enough to execute it (indicating we are caught up
12991300
// at least with the time we entered this function).
1300-
SyncWithValidationInterfaceQueue();
1301+
chain().waitForNotifications();
13011302
}
13021303

13031304

@@ -2137,7 +2138,7 @@ std::vector<uint256> CWallet::ResendWalletTransactionsBefore(interfaces::Chain::
21372138
return result;
21382139
}
21392140

2140-
void CWallet::ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman)
2141+
void CWallet::ResendWalletTransactions(interfaces::Chain::Lock& locked_chain, int64_t nBestBlockTime)
21412142
{
21422143
// Do this infrequently and randomly to avoid giving away
21432144
// that these are our transactions.
@@ -2155,8 +2156,7 @@ void CWallet::ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman
21552156

21562157
// Rebroadcast unconfirmed txes older than 5 minutes before the last
21572158
// block was found:
2158-
auto locked_chain = chain().assumeLocked(); // Temporary. Removed in upcoming lock cleanup
2159-
std::vector<uint256> relayed = ResendWalletTransactionsBefore(*locked_chain, nBestBlockTime-5*60);
2159+
std::vector<uint256> relayed = ResendWalletTransactionsBefore(locked_chain, nBestBlockTime-5*60);
21602160
if (!relayed.empty())
21612161
WalletLogPrintf("%s: rebroadcast %u unconfirmed transactions\n", __func__, relayed.size());
21622162
}
@@ -4385,8 +4385,8 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
43854385

43864386
chain.loadWallet(interfaces::MakeWallet(walletInstance));
43874387

4388-
// Register with the validation interface. It's ok to do this after rescan since we're still holding cs_main.
4389-
RegisterValidationInterface(walletInstance.get());
4388+
// Register with the validation interface. It's ok to do this after rescan since we're still holding locked_chain.
4389+
walletInstance->m_chain_notifications_handler = chain.handleNotifications(*walletInstance);
43904390

43914391
walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
43924392

src/wallet/wallet.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <amount.h>
1010
#include <interfaces/chain.h>
11+
#include <interfaces/handler.h>
1112
#include <outputtype.h>
1213
#include <policy/feerate.h>
1314
#include <streams.h>
@@ -637,7 +638,7 @@ class WalletRescanReserver; //forward declarations for ScanForWalletTransactions
637638
* A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
638639
* and provides the ability to create new transactions.
639640
*/
640-
class CWallet final : public CCryptoKeyStore, public CValidationInterface
641+
class CWallet final : public CCryptoKeyStore, private interfaces::Chain::Notifications
641642
{
642643
private:
643644
std::atomic<bool> fAbortRescan{false};
@@ -808,6 +809,9 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
808809

809810
std::set<COutPoint> setLockedCoins GUARDED_BY(cs_wallet);
810811

812+
/** Registered interfaces::Chain::Notifications handler. */
813+
std::unique_ptr<interfaces::Handler> m_chain_notifications_handler;
814+
811815
/** Interface for accessing chain state. */
812816
interfaces::Chain& chain() const { return m_chain; }
813817

@@ -920,8 +924,8 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
920924
bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true);
921925
void LoadToWallet(const CWalletTx& wtxIn) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
922926
void TransactionAddedToMempool(const CTransactionRef& tx) override;
923-
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) override;
924-
void BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) override;
927+
void BlockConnected(const CBlock& block, const std::vector<CTransactionRef>& vtxConflicted) override;
928+
void BlockDisconnected(const CBlock& block) override;
925929
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update);
926930

927931
struct ScanResult {
@@ -942,7 +946,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
942946
ScanResult ScanForWalletTransactions(const uint256& first_block, const uint256& last_block, const WalletRescanReserver& reserver, bool fUpdate);
943947
void TransactionRemovedFromMempool(const CTransactionRef &ptx) override;
944948
void ReacceptWalletTransactions();
945-
void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override EXCLUSIVE_LOCKS_REQUIRED(cs_main);
949+
void ResendWalletTransactions(interfaces::Chain::Lock& locked_chain, int64_t nBestBlockTime) override;
946950
// ResendWalletTransactionsBefore may only be called if fBroadcastTransactions!
947951
std::vector<uint256> ResendWalletTransactionsBefore(interfaces::Chain::Lock& locked_chain, int64_t nTime);
948952
CAmount GetBalance(const isminefilter& filter=ISMINE_SPENDABLE, const int min_depth=0) const;
@@ -1220,6 +1224,8 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
12201224

12211225
/** Add a KeyOriginInfo to the wallet */
12221226
bool AddKeyOrigin(const CPubKey& pubkey, const KeyOriginInfo& info);
1227+
1228+
friend struct WalletTestingSetup;
12231229
};
12241230

12251231
/** A key allocated from the key pool. */

0 commit comments

Comments
 (0)