Merge pull request #5809 from str4d/5805-fix-thread-notify-wallets-init
wallet: Initialise ThreadNotifyWallets with wallets best block
This commit is contained in:
commit
98c848fd20
24
src/init.cpp
24
src/init.cpp
|
@ -1707,15 +1707,33 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||
// Start the thread that notifies listeners of transactions that have been
|
||||
// recently added to the mempool, or have been added to or removed from the
|
||||
// chain. We perform this before step 10 (import blocks) so that the
|
||||
// original value of chainActive.Tip(), which corresponds with the wallet's
|
||||
// view of the chaintip, is passed to ThreadNotifyWallets before the chain
|
||||
// tip changes again.
|
||||
// original value of chainActive.Tip() can be passed to ThreadNotifyWallets
|
||||
// before the chain tip changes again.
|
||||
{
|
||||
CBlockIndex *pindexLastTip;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
pindexLastTip = chainActive.Tip();
|
||||
}
|
||||
|
||||
// However, if a wallet is enabled, we actually want to start notifying
|
||||
// from the block which corresponds with the wallet's view of the chain
|
||||
// tip. In particular, we want to handle the case where the node shuts
|
||||
// down uncleanly, and on restart the chain's tip is potentially up to
|
||||
// an hour of chain sync older than the wallet's tip. We assume here
|
||||
// that there is only a single wallet connected to the validation
|
||||
// interface, which is currently true.
|
||||
#ifdef ENABLE_WALLET
|
||||
if (pwalletMain)
|
||||
{
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
const auto walletBestBlock = pwalletMain->GetPersistedBestBlock();
|
||||
if (walletBestBlock != nullptr) {
|
||||
pindexLastTip = walletBestBlock;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
boost::function<void()> threadnotifywallets = boost::bind(&ThreadNotifyWallets, pindexLastTip);
|
||||
threadGroup.create_thread(
|
||||
boost::bind(&TraceThread<boost::function<void()>>, "txnotify", threadnotifywallets)
|
||||
|
|
|
@ -93,6 +93,31 @@ void ThreadNotifyWallets(CBlockIndex *pindexLastTip)
|
|||
MilliSleep(50);
|
||||
}
|
||||
|
||||
// We cannot progress with wallet notification until the chain tip is no
|
||||
// more than 100 blocks behind pindexLastTip. This can occur if the node
|
||||
// shuts down abruptly without being able to write out chainActive; the
|
||||
// node writes chain data out roughly hourly, while the wallet writes it
|
||||
// every 10 minutes. We need to wait for ThreadImport to catch up.
|
||||
while (true) {
|
||||
boost::this_thread::interruption_point();
|
||||
|
||||
{
|
||||
LOCK(cs_main);
|
||||
|
||||
const CBlockIndex *pindexFork = chainActive.FindFork(pindexLastTip);
|
||||
// We know we have the genesis block.
|
||||
assert(pindexFork != nullptr);
|
||||
|
||||
if (pindexLastTip->nHeight < pindexFork->nHeight ||
|
||||
pindexLastTip->nHeight - pindexFork->nHeight < 100)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MilliSleep(50);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
// Run the notifier on an integer second in the steady clock.
|
||||
auto now = std::chrono::steady_clock::now().time_since_epoch();
|
||||
|
|
|
@ -1501,6 +1501,27 @@ void CWallet::SetBestChain(const CBlockLocator& loc)
|
|||
SetBestChainINTERNAL(walletdb, loc);
|
||||
}
|
||||
|
||||
CBlockIndex* CWallet::GetPersistedBestBlock()
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
AssertLockHeld(cs_wallet);
|
||||
|
||||
CWalletDB walletdb(strWalletFile);
|
||||
CBlockLocator locator;
|
||||
if (walletdb.ReadBestBlock(locator)) {
|
||||
if (!locator.vHave.empty()) {
|
||||
BlockMap::iterator mi = mapBlockIndex.find(locator.vHave[0]);
|
||||
if (mi != mapBlockIndex.end()) {
|
||||
return (*mi).second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The wallet's best block is not known to the node. This can occur when a
|
||||
// wallet file is transplanted between disparate nodes.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::set<std::pair<libzcash::SproutPaymentAddress, uint256>> CWallet::GetSproutNullifiers(
|
||||
const std::set<libzcash::SproutPaymentAddress>& addresses) {
|
||||
std::set<std::pair<libzcash::SproutPaymentAddress, uint256>> nullifierSet;
|
||||
|
|
|
@ -1811,6 +1811,16 @@ public:
|
|||
void AddPendingSaplingMigrationTx(const CTransaction& tx);
|
||||
/** Saves witness caches and best block locator to disk. */
|
||||
void SetBestChain(const CBlockLocator& loc);
|
||||
/**
|
||||
* Returns the block index corresponding to the wallet's most recently
|
||||
* persisted best block. This is the state to which the wallet will revert
|
||||
* if restarted immediately, and does not necessarily match the current
|
||||
* in-memory state.
|
||||
*
|
||||
* Returns nullptr if the wallet's best block is not known to this node
|
||||
* (e.g. if the wallet was transplanted from another node).
|
||||
*/
|
||||
CBlockIndex* GetPersistedBestBlock();
|
||||
|
||||
std::set<std::pair<libzcash::SproutPaymentAddress, uint256>> GetSproutNullifiers(
|
||||
const std::set<libzcash::SproutPaymentAddress>& addresses);
|
||||
|
|
Loading…
Reference in New Issue