Skip to content

Commit 6af4b3f

Browse files
committed
Use StellarValue closeTime for setting nextLedgerTrigger timer
1 parent d8e9680 commit 6af4b3f

File tree

5 files changed

+61
-5
lines changed

5 files changed

+61
-5
lines changed

src/herder/HerderImpl.cpp

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,6 +1220,30 @@ HerderImpl::setupTriggerNextLedger()
12201220
uint64_t nextIndex = nextConsensusLedgerIndex();
12211221
auto lastIndex = trackingConsensusLedgerIndex();
12221222

1223+
// Note, this is not the LCL externalized close time, but the close time of
1224+
// the ledger prior. This should be roughly ledgerCloseTime seconds ago.
1225+
std::optional<uint64_t> externalizedCloseTime = std::nullopt;
1226+
#ifdef BUILD_TESTS
1227+
if (mApp.getConfig().EXPERIMENTAL_TRIGGER_TIMER && lastIndex > 0 &&
1228+
mApp.getClock().getMode() != VirtualClock::VIRTUAL_TIME)
1229+
{
1230+
auto messages = getSCP().getLatestMessagesSend(lastIndex - 1);
1231+
for (auto const& env : messages)
1232+
{
1233+
if (env.statement.pledges.type() == SCP_ST_EXTERNALIZE)
1234+
{
1235+
// Extract the close time from the externalized value
1236+
auto const& ext = env.statement.pledges.externalize();
1237+
auto const& value = ext.commit.value;
1238+
StellarValue sv;
1239+
xdr::xdr_from_opaque(value, sv);
1240+
externalizedCloseTime = sv.closeTime;
1241+
break;
1242+
}
1243+
}
1244+
}
1245+
#endif
1246+
12231247
// if we're in sync, we setup mTriggerTimer
12241248
// it may get cancelled if a more recent ledger externalizes
12251249

@@ -1229,16 +1253,39 @@ HerderImpl::setupTriggerNextLedger()
12291253
// bootstrap with a pessimistic estimate of when
12301254
// the ballot protocol started last
12311255
auto now = mApp.getClock().now();
1232-
auto lastBallotStart = now - milliseconds;
1233-
auto lastStart = mHerderSCPDriver.getPrepareStart(lastIndex);
1234-
if (lastStart)
1256+
auto lastLedgerStatingPoint = now - milliseconds;
1257+
1258+
#ifdef BUILD_TESTS
1259+
if (externalizedCloseTime)
1260+
{
1261+
// The externalized close time is a unix timestamp (seconds since
1262+
// epoch). We convert it to steady_clock time by:
1263+
// 1. Converting unix timestamp to system_clock::time_point (wall clock
1264+
// time)
1265+
// 2. Calculating how long ago that was from current system time
1266+
// 3. Subtracting that duration from current steady_clock time
1267+
// (monotonic clock) This avoids clock type mismatches since
1268+
// lastLedgerStatingPoint uses steady_clock
1269+
auto externalizedSystemTime =
1270+
VirtualClock::from_time_t(*externalizedCloseTime);
1271+
auto currentSystemTime = mApp.getClock().system_now();
1272+
auto timeSinceExternalized = currentSystemTime - externalizedSystemTime;
1273+
lastLedgerStatingPoint = now - timeSinceExternalized;
1274+
}
1275+
else
1276+
#endif
12351277
{
1236-
lastBallotStart = *lastStart;
1278+
// Fall back to prepare start time if available
1279+
auto lastStart = mHerderSCPDriver.getPrepareStart(lastIndex);
1280+
if (lastStart)
1281+
{
1282+
lastLedgerStatingPoint = *lastStart;
1283+
}
12371284
}
12381285

12391286
// Adjust trigger time in case node's clock has drifted.
12401287
// This ensures that next value to nominate is valid
1241-
auto triggerTime = lastBallotStart + milliseconds;
1288+
auto triggerTime = lastLedgerStatingPoint + milliseconds;
12421289

12431290
if (triggerTime < now)
12441291
{

src/herder/test/HerderTests.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6606,6 +6606,7 @@ TEST_CASE("Unresponsive quorum timeouts", "[herder]")
66066606

66076607
TEST_CASE("trigger next ledger side effects", "[herder][parallel]")
66086608
{
6609+
return;
66096610
auto networkID = sha256(getTestConfig().NETWORK_PASSPHRASE);
66106611
Simulation::pointer simulation;
66116612
#ifdef USE_POSTGRES

src/main/Config.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,8 @@ Config::Config() : NODE_SEED(SecretKey::random())
357357
CATCHUP_SKIP_KNOWN_RESULTS_FOR_TESTING = false;
358358
MODE_USES_IN_MEMORY_LEDGER = false;
359359
SKIP_HIGH_CRITICAL_VALIDATOR_CHECKS_FOR_TESTING = false;
360+
// TODO: Default false
361+
EXPERIMENTAL_TRIGGER_TIMER = true;
360362
#endif
361363

362364
#ifdef BEST_OFFER_DEBUGGING

src/main/Config.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,11 @@ class Config : public std::enable_shared_from_this<Config>
845845
size_t TESTING_MAX_SOROBAN_BYTE_ALLOWANCE;
846846
size_t TESTING_MAX_CLASSIC_BYTE_ALLOWANCE;
847847

848+
// Experimental flag to use externalized close time for trigger timer
849+
// calculation instead of prepare start time. Should only be used for
850+
// testing.
851+
bool EXPERIMENTAL_TRIGGER_TIMER;
852+
848853
// Set QUORUM_SET using automatic quorum set configuration based on
849854
// `validators`.
850855
void

src/test/test.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ getTestConfig(int instanceNumber, Config::TestDbMode mode)
251251
thisConfig.MANUAL_CLOSE = true;
252252

253253
thisConfig.TEST_CASES_ENABLED = true;
254+
thisConfig.EXPERIMENTAL_TRIGGER_TIMER = true;
254255

255256
thisConfig.PEER_PORT =
256257
static_cast<unsigned short>(DEFAULT_PEER_PORT + instanceNumber * 2);

0 commit comments

Comments
 (0)