Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/interfaces/chain.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,12 +326,18 @@ class Chain
};

//! Register handler for notifications.
//! Some notifications are asynchronous and may still execute after the handler is disconnected.
//! Use waitForNotifications() after the handler is disconnected to ensure all pending notifications
//! have been processed.
virtual std::unique_ptr<Handler> handleNotifications(std::shared_ptr<Notifications> notifications) = 0;

//! Wait for pending notifications to be processed unless block hash points to the current
//! chain tip.
virtual void waitForNotificationsIfTipChanged(const uint256& old_tip) = 0;

//! Wait for all pending notifications up to this point to be processed
virtual void waitForNotifications() = 0;

//! Register handler for RPC. Command is not copied, so reference
//! needs to remain valid until Handler is disconnected.
virtual std::unique_ptr<Handler> handleRpc(const CRPCCommand& command) = 0;
Expand Down
4 changes: 4 additions & 0 deletions src/node/interfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,10 @@ class ChainImpl : public Chain
if (!old_tip.IsNull() && old_tip == WITH_LOCK(::cs_main, return chainman().ActiveChain().Tip()->GetBlockHash())) return;
validation_signals().SyncWithValidationInterfaceQueue();
}
void waitForNotifications() override
{
validation_signals().SyncWithValidationInterfaceQueue();
}
std::unique_ptr<Handler> handleRpc(const CRPCCommand& command) override
{
return std::make_unique<RpcHandlerImpl>(command);
Expand Down
16 changes: 13 additions & 3 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ bool RemoveWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet
WITH_LOCK(wallet->cs_wallet, wallet->WriteBestBlock());

// Unregister with the validation interface which also drops shared pointers.
wallet->m_chain_notifications_handler.reset();
wallet->DisconnectChainNotifications();
{
LOCK(context.wallets_mutex);
std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(context.wallets.begin(), context.wallets.end(), wallet);
Expand Down Expand Up @@ -3117,7 +3117,7 @@ std::shared_ptr<CWallet> CWallet::CreateNew(WalletContext& context, const std::s
walletInstance->TopUpKeyPool();

if (chain && !AttachChain(walletInstance, *chain, /*rescan_required=*/false, error, warnings)) {
walletInstance->m_chain_notifications_handler.reset(); // Reset this pointer so that the wallet will actually be unloaded
walletInstance->DisconnectChainNotifications();
return nullptr;
}

Expand Down Expand Up @@ -3158,7 +3158,7 @@ std::shared_ptr<CWallet> CWallet::LoadExisting(WalletContext& context, const std
walletInstance->TopUpKeyPool();

if (chain && !AttachChain(walletInstance, *chain, rescan_required, error, warnings)) {
walletInstance->m_chain_notifications_handler.reset(); // Reset this pointer so that the wallet will actually be unloaded
walletInstance->DisconnectChainNotifications();
return nullptr;
}

Expand Down Expand Up @@ -4577,4 +4577,14 @@ std::optional<WalletTXO> CWallet::GetTXO(const COutPoint& outpoint) const
}
return it->second;
}

void CWallet::DisconnectChainNotifications()
{
if (m_chain_notifications_handler) {
m_chain_notifications_handler->disconnect();
chain().waitForNotifications();
m_chain_notifications_handler.reset();
}
}

} // namespace wallet
3 changes: 3 additions & 0 deletions src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,9 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
//! Find the private key for the given key id from the wallet's descriptors, if available
//! Returns nullopt when no descriptor has the key or if the wallet is locked.
std::optional<CKey> GetKey(const CKeyID& keyid) const;

//! Disconnect chain notifications and wait for all notifications to be processed
void DisconnectChainNotifications();
};

/**
Expand Down
Loading