Skip to content

Commit 598db38

Browse files
committed
Merge #13106: Simplify semantics of ChainStateFlushed callback
9cb6cdc Simplify semantics of ChainStateFlushed callback (Matt Corallo) 50b6533 scripted-diff: Rename SetBestChain callback ChainStateFlushed (Matt Corallo) Pull request description: Previously, ChainStateFlushed would fire either if a full flush completed (which can happen due to memory limits, forced flush, or on its own DATABASE_WRITE_INTERVAL timer) *or* on a ChainStateFlushed-specific DATABASE_WRITE_INTERVAL timer. This is both less clear for clients (as there are no guarantees about a flush having actually happened prior to the call), and reults in extra flushes not clearly intended by the code. We drop the second case, providing a strong guarantee without removing the periodit timer-based flushing. This is a follow-up to discussion in #11857. Tree-SHA512: 22ba3a0954d265d28413dbf87040790ca5b439820ee7bbadab14028295ec190de82ce5cd664426c82e58b706dc84278868026fa8d066702eb6e6962c9ace1f8e
2 parents 0bc980b + 9cb6cdc commit 598db38

File tree

7 files changed

+33
-26
lines changed

7 files changed

+33
-26
lines changed

src/index/txindex.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ void TxIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const C
192192
}
193193
}
194194

195-
void TxIndex::SetBestChain(const CBlockLocator& locator)
195+
void TxIndex::ChainStateFlushed(const CBlockLocator& locator)
196196
{
197197
if (!m_synced) {
198198
return;
@@ -211,7 +211,7 @@ void TxIndex::SetBestChain(const CBlockLocator& locator)
211211
return;
212212
}
213213

214-
// This checks that SetBestChain callbacks are received after BlockConnected. The check may fail
214+
// This checks that ChainStateFlushed callbacks are received after BlockConnected. The check may fail
215215
// immediately after the the sync thread catches up and sets m_synced. Consider the case where
216216
// there is a reorg and the blocks on the stale branch are in the ValidationInterface queue
217217
// backlog even after the sync thread has caught up to the new chain tip. In this unlikely

src/index/txindex.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class TxIndex final : public CValidationInterface
5555
void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex,
5656
const std::vector<CTransactionRef>& txn_conflicted) override;
5757

58-
void SetBestChain(const CBlockLocator& locator) override;
58+
void ChainStateFlushed(const CBlockLocator& locator) override;
5959

6060
public:
6161
/// Constructs the TxIndex, which becomes available to be queried.

src/validation.cpp

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2066,13 +2066,12 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
20662066
LOCK(cs_main);
20672067
static int64_t nLastWrite = 0;
20682068
static int64_t nLastFlush = 0;
2069-
static int64_t nLastSetChain = 0;
20702069
std::set<int> setFilesToPrune;
2071-
bool fFlushForPrune = false;
2072-
bool fDoFullFlush = false;
2073-
int64_t nNow = 0;
2070+
bool full_flush_completed = false;
20742071
try {
20752072
{
2073+
bool fFlushForPrune = false;
2074+
bool fDoFullFlush = false;
20762075
LOCK(cs_LastBlockFile);
20772076
if (fPruneMode && (fCheckForPruning || nManualPruneHeight > 0) && !fReindex) {
20782077
if (nManualPruneHeight > 0) {
@@ -2089,17 +2088,14 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
20892088
}
20902089
}
20912090
}
2092-
nNow = GetTimeMicros();
2091+
int64_t nNow = GetTimeMicros();
20932092
// Avoid writing/flushing immediately after startup.
20942093
if (nLastWrite == 0) {
20952094
nLastWrite = nNow;
20962095
}
20972096
if (nLastFlush == 0) {
20982097
nLastFlush = nNow;
20992098
}
2100-
if (nLastSetChain == 0) {
2101-
nLastSetChain = nNow;
2102-
}
21032099
int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
21042100
int64_t cacheSize = pcoinsTip->DynamicMemoryUsage();
21052101
int64_t nTotalSpace = nCoinCacheUsage + std::max<int64_t>(nMempoolSizeMax - nMempoolUsage, 0);
@@ -2156,12 +2152,12 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
21562152
if (!pcoinsTip->Flush())
21572153
return AbortNode(state, "Failed to write to coin database");
21582154
nLastFlush = nNow;
2155+
full_flush_completed = true;
21592156
}
21602157
}
2161-
if (fDoFullFlush || ((mode == FlushStateMode::ALWAYS || mode == FlushStateMode::PERIODIC) && nNow > nLastSetChain + (int64_t)DATABASE_WRITE_INTERVAL * 1000000)) {
2158+
if (full_flush_completed) {
21622159
// Update best block in wallet (so we can detect restored wallets).
2163-
GetMainSignals().SetBestChain(chainActive.GetLocator());
2164-
nLastSetChain = nNow;
2160+
GetMainSignals().ChainStateFlushed(chainActive.GetLocator());
21652161
}
21662162
} catch (const std::runtime_error& e) {
21672163
return AbortNode(state, std::string("System error while flushing: ") + e.what());

src/validationinterface.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct MainSignalsInstance {
2525
boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::vector<CTransactionRef>&)> BlockConnected;
2626
boost::signals2::signal<void (const std::shared_ptr<const CBlock> &)> BlockDisconnected;
2727
boost::signals2::signal<void (const CTransactionRef &)> TransactionRemovedFromMempool;
28-
boost::signals2::signal<void (const CBlockLocator &)> SetBestChain;
28+
boost::signals2::signal<void (const CBlockLocator &)> ChainStateFlushed;
2929
boost::signals2::signal<void (const uint256 &)> Inventory;
3030
boost::signals2::signal<void (int64_t nBestBlockTime, CConnman* connman)> Broadcast;
3131
boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
@@ -80,7 +80,7 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) {
8080
g_signals.m_internals->BlockConnected.connect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3));
8181
g_signals.m_internals->BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1));
8282
g_signals.m_internals->TransactionRemovedFromMempool.connect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, _1));
83-
g_signals.m_internals->SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
83+
g_signals.m_internals->ChainStateFlushed.connect(boost::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, _1));
8484
g_signals.m_internals->Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
8585
g_signals.m_internals->Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2));
8686
g_signals.m_internals->BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
@@ -91,7 +91,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
9191
g_signals.m_internals->BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
9292
g_signals.m_internals->Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2));
9393
g_signals.m_internals->Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
94-
g_signals.m_internals->SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
94+
g_signals.m_internals->ChainStateFlushed.disconnect(boost::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, _1));
9595
g_signals.m_internals->TransactionAddedToMempool.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1));
9696
g_signals.m_internals->BlockConnected.disconnect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3));
9797
g_signals.m_internals->BlockDisconnected.disconnect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1));
@@ -107,7 +107,7 @@ void UnregisterAllValidationInterfaces() {
107107
g_signals.m_internals->BlockChecked.disconnect_all_slots();
108108
g_signals.m_internals->Broadcast.disconnect_all_slots();
109109
g_signals.m_internals->Inventory.disconnect_all_slots();
110-
g_signals.m_internals->SetBestChain.disconnect_all_slots();
110+
g_signals.m_internals->ChainStateFlushed.disconnect_all_slots();
111111
g_signals.m_internals->TransactionAddedToMempool.disconnect_all_slots();
112112
g_signals.m_internals->BlockConnected.disconnect_all_slots();
113113
g_signals.m_internals->BlockDisconnected.disconnect_all_slots();
@@ -166,9 +166,9 @@ void CMainSignals::BlockDisconnected(const std::shared_ptr<const CBlock> &pblock
166166
});
167167
}
168168

169-
void CMainSignals::SetBestChain(const CBlockLocator &locator) {
169+
void CMainSignals::ChainStateFlushed(const CBlockLocator &locator) {
170170
m_internals->m_schedulerClient.AddToProcessQueue([locator, this] {
171-
m_internals->SetBestChain(locator);
171+
m_internals->ChainStateFlushed(locator);
172172
});
173173
}
174174

src/validationinterface.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,20 @@ class CValidationInterface {
9999
/**
100100
* Notifies listeners of the new active block chain on-disk.
101101
*
102+
* Prior to this callback, any updates are not guaranteed to persist on disk
103+
* (ie clients need to handle shutdown/restart safety by being able to
104+
* understand when some updates were lost due to unclean shutdown).
105+
*
106+
* When this callback is invoked, the validation changes done by any prior
107+
* callback are guaranteed to exist on disk and survive a restart, including
108+
* an unclean shutdown.
109+
*
110+
* Provides a locator describing the best chain, which is likely useful for
111+
* storing current state on disk in client DBs.
112+
*
102113
* Called on a background thread.
103114
*/
104-
virtual void SetBestChain(const CBlockLocator &locator) {}
115+
virtual void ChainStateFlushed(const CBlockLocator &locator) {}
105116
/**
106117
* Notifies listeners about an inventory item being seen on the network.
107118
*
@@ -157,7 +168,7 @@ class CMainSignals {
157168
void TransactionAddedToMempool(const CTransactionRef &);
158169
void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>> &);
159170
void BlockDisconnected(const std::shared_ptr<const CBlock> &);
160-
void SetBestChain(const CBlockLocator &);
171+
void ChainStateFlushed(const CBlockLocator &);
161172
void Inventory(const uint256 &);
162173
void Broadcast(int64_t nBestBlockTime, CConnman* connman);
163174
void BlockChecked(const CBlock&, const CValidationState&);

src/wallet/wallet.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
453453
return false;
454454
}
455455

456-
void CWallet::SetBestChain(const CBlockLocator& loc)
456+
void CWallet::ChainStateFlushed(const CBlockLocator& loc)
457457
{
458458
WalletBatch batch(*database);
459459
batch.WriteBestBlock(loc);
@@ -4038,7 +4038,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
40384038
return nullptr;
40394039
}
40404040

4041-
walletInstance->SetBestChain(chainActive.GetLocator());
4041+
walletInstance->ChainStateFlushed(chainActive.GetLocator());
40424042
} else if (gArgs.IsArgSet("-usehd")) {
40434043
bool useHD = gArgs.GetBoolArg("-usehd", true);
40444044
if (walletInstance->IsHDEnabled() && !useHD) {
@@ -4180,7 +4180,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
41804180
walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, reserver, true);
41814181
}
41824182
LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
4183-
walletInstance->SetBestChain(chainActive.GetLocator());
4183+
walletInstance->ChainStateFlushed(chainActive.GetLocator());
41844184
walletInstance->database->IncrementUpdateCounter();
41854185

41864186
// Restore wallet transaction metadata after -zapwallettxes=1

src/wallet/wallet.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
10131013
bool IsAllFromMe(const CTransaction& tx, const isminefilter& filter) const;
10141014
CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const;
10151015
CAmount GetChange(const CTransaction& tx) const;
1016-
void SetBestChain(const CBlockLocator& loc) override;
1016+
void ChainStateFlushed(const CBlockLocator& loc) override;
10171017

10181018
DBErrors LoadWallet(bool& fFirstRunRet);
10191019
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);

0 commit comments

Comments
 (0)