@@ -1229,16 +1229,69 @@ HerderImpl::setupTriggerNextLedger()
12291229 // bootstrap with a pessimistic estimate of when
12301230 // the ballot protocol started last
12311231 auto now = mApp .getClock ().now ();
1232- auto lastBallotStart = now - milliseconds;
1233- auto lastStart = mHerderSCPDriver .getPrepareStart (lastIndex);
1234- if (lastStart)
1232+ auto lastLedgerStatingPoint = now - milliseconds;
1233+
1234+ #ifdef BUILD_TESTS
1235+ if (mApp .getConfig ().EXPERIMENTAL_TRIGGER_TIMER &&
1236+ mApp .getClock ().getMode () == VirtualClock::REAL_TIME)
1237+ {
1238+ auto consensusCloseTime = trackingConsensusCloseTime ();
1239+
1240+ // Bootstrap to pessimistic estimate on startup
1241+ if (consensusCloseTime == 0 )
1242+ {
1243+ CLOG_WARNING (
1244+ Herder,
1245+ " Consensus close time is 0, using pessimistic estimate" );
1246+ // Keep the existing lastLedgerStatingPoint
1247+ }
1248+ else
1249+ {
1250+ // The externalized close time is a unix timestamp. We convert it to
1251+ // steady_clock time by:
1252+ // 1. Converting unix timestamp to system_clock::time_point (wall
1253+ // clock time)
1254+ // 2. Calculating how long ago that was from current system time
1255+ // 3. Subtracting that duration from current steady_clock time
1256+ auto externalizedSystemTime =
1257+ VirtualClock::from_time_t (consensusCloseTime);
1258+ auto currentSystemTime = mApp .getClock ().system_now ();
1259+
1260+ // Handle clock drift: if externalized time is in the future,
1261+ // fall back to pessimistic estimate
1262+ if (externalizedSystemTime >= currentSystemTime)
1263+ {
1264+ CLOG_WARNING (Herder,
1265+ " Externalized closeTime {} is in the future "
1266+ " (current time {}), "
1267+ " using pessimistic estimate" ,
1268+ consensusCloseTime,
1269+ VirtualClock::to_time_t (currentSystemTime));
1270+ // Keep the existing lastLedgerStatingPoint which is already set
1271+ // to the pessimistic estimate (now - milliseconds)
1272+ }
1273+ else
1274+ {
1275+ // Calculate how long ago the externalized closeTime was
1276+ auto timeSinceExternalized =
1277+ currentSystemTime - externalizedSystemTime;
1278+ lastLedgerStatingPoint = now - timeSinceExternalized;
1279+ }
1280+ }
1281+ }
1282+ else
1283+ #endif
12351284 {
1236- lastBallotStart = *lastStart;
1285+ auto lastStart = mHerderSCPDriver .getPrepareStart (lastIndex);
1286+ if (lastStart)
1287+ {
1288+ lastLedgerStatingPoint = *lastStart;
1289+ }
12371290 }
12381291
12391292 // Adjust trigger time in case node's clock has drifted.
12401293 // This ensures that next value to nominate is valid
1241- auto triggerTime = lastBallotStart + milliseconds;
1294+ auto triggerTime = lastLedgerStatingPoint + milliseconds;
12421295
12431296 if (triggerTime < now)
12441297 {
0 commit comments