From a6bcde3044e8a3ef7565df09fc069452a25dec8f Mon Sep 17 00:00:00 2001 From: Nicholas Dudfield Date: Thu, 16 Jul 2026 19:29:43 +0700 Subject: [PATCH] test(ledger): cover consensus entropy replay --- src/test/app/LedgerReplay_test.cpp | 71 +++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/src/test/app/LedgerReplay_test.cpp b/src/test/app/LedgerReplay_test.cpp index 20b7f1d52..51f10edfd 100644 --- a/src/test/app/LedgerReplay_test.cpp +++ b/src/test/app/LedgerReplay_test.cpp @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include @@ -40,7 +42,7 @@ namespace test { struct LedgerReplay_test : public beast::unit_test::suite { void - run() override + testReplay() { testcase("Replay ledger"); @@ -73,6 +75,73 @@ struct LedgerReplay_test : public beast::unit_test::suite BEAST_EXPECT(replayed->info().hash == lastClosed->info().hash); } + + void + testConsensusEntropyReplay() + { + testcase("Replay ledger with consensus entropy"); + + using namespace jtx; + + auto const alice = Account("alice"); + auto const bob = Account("bob"); + + Env env = [&] { + auto c = jtx::envconfig(); + auto& sectionNode = c->section(ConfigSection::nodeDatabase()); + sectionNode.set("type", "memory"); + c->overwrite(SECTION_RELATIONAL_DB, "backend", "sqlite"); + return jtx::Env( + *this, + std::move(c), + supported_amendments() | featureConsensusEntropy, + nullptr); + }(); + env.fund(XRP(100000), alice, bob); + env.close(); + + LedgerMaster& ledgerMaster = env.app().getLedgerMaster(); + auto const lastClosed = ledgerMaster.getClosedLedger(); + auto const lastClosedParent = + ledgerMaster.getLedgerByHash(lastClosed->info().parentHash); + + LedgerReplay const replayData(lastClosedParent, lastClosed); + auto const& orderedTxns = replayData.orderedTxns(); + BEAST_EXPECT(orderedTxns.size() > 1); + if (orderedTxns.empty()) + return; + + auto const& [index, entropyTx] = *orderedTxns.begin(); + BEAST_EXPECT(index == 0); + BEAST_EXPECT(entropyTx->getTxnType() == ttCONSENSUS_ENTROPY); + + auto const persisted = + lastClosed->txRead(entropyTx->getTransactionID()); + BEAST_EXPECT(persisted.first); + BEAST_EXPECT( + persisted.second && + persisted.second->getFieldU32(sfTransactionIndex) == index); + if (persisted.first) + { + Serializer persistedBytes; + persisted.first->add(persistedBytes); + Serializer replayBytes; + entropyTx->add(replayBytes); + BEAST_EXPECT(replayBytes.peekData() == persistedBytes.peekData()); + } + + auto const replayed = + buildLedger(replayData, tapNONE, env.app(), env.journal); + + BEAST_EXPECT(replayed->info().hash == lastClosed->info().hash); + } + + void + run() override + { + testReplay(); + testConsensusEntropyReplay(); + } }; enum class InboundLedgersBehavior {