Skip to content

Commit

Permalink
validation: add randomness to periodic write interval
Browse files Browse the repository at this point in the history
Co-Authored-By: Pieter Wuille <[email protected]>
Co-Authored-By: l0rinc <[email protected]>
  • Loading branch information
3 people committed Dec 12, 2024
1 parent 6a78f10 commit 5326e68
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 7 deletions.
8 changes: 4 additions & 4 deletions src/test/chainstate_write_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,18 @@ BOOST_FIXTURE_TEST_CASE(chainstate_write_interval, TestingSetup)
auto& chainstate{Assert(m_node.chainman)->ActiveChainstate()};
BlockValidationState state_dummy{};

// The first periodic flush sets m_last_write and does not flush
// The first periodic flush sets m_next_write and does not flush
chainstate.FlushStateToDisk(state_dummy, FlushStateMode::PERIODIC);
m_node.validation_signals->SyncWithValidationInterfaceQueue();
BOOST_CHECK(!sub->m_did_flush);

// The periodic flush interval is 1 hour
SetMockTime(GetTime<std::chrono::minutes>() + 59min);
// The periodic flush interval is between 50 and 70 minutes (inclusive)
SetMockTime(GetTime<std::chrono::minutes>() + 49min);
chainstate.FlushStateToDisk(state_dummy, FlushStateMode::PERIODIC);
m_node.validation_signals->SyncWithValidationInterfaceQueue();
BOOST_CHECK(!sub->m_did_flush);

SetMockTime(GetTime<std::chrono::minutes>() + 1h);
SetMockTime(GetTime<std::chrono::minutes>() + 70min);
chainstate.FlushStateToDisk(state_dummy, FlushStateMode::PERIODIC);
m_node.validation_signals->SyncWithValidationInterfaceQueue();
BOOST_CHECK(sub->m_did_flush);
Expand Down
11 changes: 8 additions & 3 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,12 @@ using node::CBlockIndexHeightOnlyComparator;
using node::CBlockIndexWorkComparator;
using node::SnapshotMetadata;

/** Time to wait between writing blocks/block index and chainstate to disk. */
static constexpr std::chrono::hours DATABASE_WRITE_INTERVAL{1};
/** Time window to wait between writing blocks/block index and chainstate to disk.
* Randomize writing time inside the window to prevent a situation where the
* network over time settles into a few cohorts of synchronized writers.
*/
static constexpr auto DATABASE_WRITE_INTERVAL_MIN{50min};
static constexpr auto DATABASE_WRITE_INTERVAL_MAX{70min};
/** Maximum age of our tip for us to be considered current for fee estimation */
static constexpr std::chrono::hours MAX_FEE_ESTIMATION_TIP_AGE{3};
const std::vector<std::string> CHECKLEVEL_DOC {
Expand Down Expand Up @@ -2884,7 +2888,8 @@ bool Chainstate::FlushStateToDisk(
bool should_write = (mode == FlushStateMode::ALWAYS) || fCacheLarge || fCacheCritical || fPeriodicWrite || fFlushForPrune;

if (should_write || m_next_write == NodeClock::time_point::max()) {
m_next_write = nNow + DATABASE_WRITE_INTERVAL;
constexpr auto range{DATABASE_WRITE_INTERVAL_MAX - DATABASE_WRITE_INTERVAL_MIN + 1min};
m_next_write = FastRandomContext().rand_uniform_delay(nNow + DATABASE_WRITE_INTERVAL_MIN, range);
}

// Write blocks, block index and best chain related state to disk.
Expand Down

0 comments on commit 5326e68

Please sign in to comment.