@@ -3362,6 +3362,64 @@ TEST_CASE("SCP Driver", "[herder][acceptance]")
33623362 }
33633363}
33643364
3365+ // Test combineCandidates handling of candidates where
3366+ // previousLedgerHash != LCL.hash
3367+ TEST_CASE (" combineCandidates with mismatched previousLedgerHash candidate" ,
3368+ " [herder][bug]" )
3369+ {
3370+ Config cfg (getTestConfig ());
3371+
3372+ VirtualClock clock;
3373+ auto app = createTestApplication (clock, cfg);
3374+ auto & herder = dynamic_cast <HerderImpl&>(app->getHerder ());
3375+ auto & pe = herder.getPendingEnvelopes ();
3376+ auto & driver = herder.getHerderSCPDriver ();
3377+
3378+ auto const & lcl = app->getLedgerManager ().getLastClosedLedgerHeader ();
3379+ uint32_t const ver = lcl.header .ledgerVersion ;
3380+ uint64_t const closeTime = lcl.header .scpValue .closeTime + 1 ;
3381+ uint64_t const slotIndex = lcl.header .ledgerSeq + 1 ;
3382+
3383+ // Two structurally-valid empty tx sets that differ only in
3384+ // previousLedgerHash.
3385+ auto goodTxSet = TxSetXDRFrame::makeEmpty (lcl.hash , ver); // matches LCL
3386+ auto badTxSet = TxSetXDRFrame::makeEmpty (sha256 (" not the LCL hash" ),
3387+ ver); // mismatched
3388+
3389+ ValueWrapperPtrSet candidates;
3390+ // Register the tx set so combineCandidates' getTxSet() returns it, then add
3391+ // a candidate value referencing it.
3392+ auto addCandidate = [&](TxSetXDRFrameConstPtr const & txSet) {
3393+ pe.addTxSet (txSet->getContentsHash (), slotIndex, txSet);
3394+ StellarValue sv =
3395+ herder.makeStellarValue (txSet->getContentsHash (), closeTime,
3396+ emptyUpgradeSteps, cfg.NODE_SEED );
3397+ candidates.emplace (driver.wrapValue (xdr::xdr_to_opaque (sv)));
3398+ };
3399+ auto combinedTxSetHash = [&]() {
3400+ ValueWrapperPtr result =
3401+ driver.combineCandidates (slotIndex, candidates);
3402+ StellarValue sv;
3403+ xdr::xdr_from_opaque (result->getValue (), sv);
3404+ return sv.txSetHash ;
3405+ };
3406+
3407+ SECTION (" prefer applicable candidate over mismatched candidate" )
3408+ {
3409+ addCandidate (goodTxSet);
3410+ addCandidate (badTxSet);
3411+ REQUIRE (combinedTxSetHash () == goodTxSet->getContentsHash ());
3412+ }
3413+
3414+ SECTION (" all candidates have mismatched previousLedgerHash" )
3415+ {
3416+ // If the *only* option is a candidate with a mismatched
3417+ // previousLedgerHash, choose it.
3418+ addCandidate (badTxSet);
3419+ REQUIRE (combinedTxSetHash () == badTxSet->getContentsHash ());
3420+ }
3421+ }
3422+
33653423TEST_CASE (" SCP State" , " [herder]" )
33663424{
33673425 SecretKey nodeKeys[3 ];
0 commit comments