@@ -3322,6 +3322,18 @@ TEST_CASE("SCP checkpoint", "[catchup][herder]")
33223322 simulation->getExpectedLedgerCloseTime (),
33233323 false );
33243324
3325+ // An out of sync node should buffer every ledger from the checkpoint up to
3326+ // the main node's latest. The main node applies ledgers asynchronously
3327+ // after externalizing them and the out of sync node hears about them
3328+ // asynchronously, so this only holds at moments where the two line up.
3329+ auto hasBufferedCheckpointToLcl = [&](LedgerApplyManagerImpl const & lam) {
3330+ auto const & buffered = lam.getBufferedLedgers ();
3331+ return !buffered.empty () &&
3332+ buffered.begin ()->first == firstCheckpoint &&
3333+ buffered.crbegin ()->first ==
3334+ mainNode->getLedgerManager ().getLastClosedLedgerNum ();
3335+ };
3336+
33253337 SECTION (" GC old checkpoints" )
33263338 {
33273339 HerderImpl& herder = static_cast <HerderImpl&>(mainNode->getHerder ());
@@ -3362,14 +3374,13 @@ TEST_CASE("SCP checkpoint", "[catchup][herder]")
33623374
33633375 // Crank until outOfSync node has received checkpoint ledger and started
33643376 // catchup
3365- simulation->crankUntil ([&]() { return lam.isCatchupInitialized (); },
3366- 2 * Herder::SEND_LATEST_CHECKPOINT_DELAY , false );
3367-
3368- auto const & bufferedLedgers = lam.getBufferedLedgers ();
3369- REQUIRE (!bufferedLedgers.empty ());
3370- REQUIRE (bufferedLedgers.begin ()->first == firstCheckpoint);
3371- REQUIRE (bufferedLedgers.crbegin ()->first ==
3372- mainNode->getLedgerManager ().getLastClosedLedgerNum ());
3377+ simulation->crankUntil (
3378+ [&]() {
3379+ return lam.isCatchupInitialized () &&
3380+ hasBufferedCheckpointToLcl (lam);
3381+ },
3382+ 2 * Herder::SEND_LATEST_CHECKPOINT_DELAY , false );
3383+ REQUIRE (hasBufferedCheckpointToLcl (lam));
33733384 }
33743385
33753386 SECTION (" Two out of sync nodes receive checkpoint" )
@@ -3391,20 +3402,14 @@ TEST_CASE("SCP checkpoint", "[catchup][herder]")
33913402 // catchup
33923403 simulation->crankUntil (
33933404 [&]() {
3394- return cm1.isCatchupInitialized () && cm2.isCatchupInitialized ();
3405+ return cm1.isCatchupInitialized () &&
3406+ cm2.isCatchupInitialized () &&
3407+ hasBufferedCheckpointToLcl (cm1) &&
3408+ hasBufferedCheckpointToLcl (cm2);
33953409 },
33963410 2 * Herder::SEND_LATEST_CHECKPOINT_DELAY , false );
3397-
3398- auto const & bufferedLedgers1 = cm1.getBufferedLedgers ();
3399- REQUIRE (!bufferedLedgers1.empty ());
3400- REQUIRE (bufferedLedgers1.begin ()->first == firstCheckpoint);
3401- REQUIRE (bufferedLedgers1.crbegin ()->first ==
3402- mainNode->getLedgerManager ().getLastClosedLedgerNum ());
3403- auto const & bufferedLedgers2 = cm2.getBufferedLedgers ();
3404- REQUIRE (!bufferedLedgers2.empty ());
3405- REQUIRE (bufferedLedgers2.begin ()->first == firstCheckpoint);
3406- REQUIRE (bufferedLedgers2.crbegin ()->first ==
3407- mainNode->getLedgerManager ().getLastClosedLedgerNum ());
3411+ REQUIRE (hasBufferedCheckpointToLcl (cm1));
3412+ REQUIRE (hasBufferedCheckpointToLcl (cm2));
34083413 }
34093414}
34103415
@@ -4023,7 +4028,16 @@ TEST_CASE("SCP message capture from previous ledger", "[herder]")
40234028{
40244029 // Initialize simulation
40254030 auto networkID = sha256 (getTestConfig ().NETWORK_PASSPHRASE );
4026- auto simulation = std::make_shared<Simulation>(networkID);
4031+ // A and B keep closing ledgers in real time while C is fed slot 2 by
4032+ // hand. Use a longer close time so that C's slot-2 EXTERNALIZE reaches
4033+ // A and B before they close ledger 3.
4034+ auto confGen = [](int i) {
4035+ auto cfg = getTestConfig (i);
4036+ cfg.ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING = true ;
4037+ cfg.ARTIFICIALLY_SET_CLOSE_TIME_FOR_TESTING = 5 ;
4038+ return cfg;
4039+ };
4040+ auto simulation = std::make_shared<Simulation>(networkID, confGen);
40274041
40284042 // Create three validators: A, B, and C
40294043 auto validatorAKey = SecretKey::fromSeed (sha256 (" validator-A" ));
0 commit comments