fix: Report no ledger from a failed acquisition

InboundLedger::getLedger() now reports nothing once the acquisition has
failed, since a failed acquisition can still hold a partially built
ledger that must never be used. The guard sits at the one accessor rather
than relying on every caller to check isFailed() first; the pointer itself
is kept, since getJson() still reports on the partial maps of a failed
acquire.
This commit is contained in:
Bart
2026-08-22 22:47:24 -04:00
parent 838f6c0459
commit 0f0ff0d699
2 changed files with 16 additions and 2 deletions

View File

@@ -542,6 +542,9 @@ struct InboundLedger_test : public beast::unit_test::Suite
BEAST_EXPECT(acquire->isFailed());
BEAST_EXPECT(!acquire->isComplete());
// A failed acquisition must not hand back the partial ledger it built.
BEAST_EXPECT(acquire->getLedger() == nullptr);
}
/**
@@ -705,7 +708,8 @@ struct InboundLedger_test : public beast::unit_test::Suite
BEAST_EXPECT(!acquire->isComplete());
BEAST_EXPECT(peerSetPtr->requests() > requestsFromInit);
// done() remembered the hash, which is what stops the next round asking again.
// A failed acquisition holds no ledger to hand back, and done() remembered the hash.
BEAST_EXPECT(acquire->getLedger() == nullptr);
BEAST_EXPECT(
waitFor([&] { return env.app().getInboundLedgers().isFailure(kUnknownLedger); }));
}

View File

@@ -102,10 +102,20 @@ public:
return failed_;
}
/**
* The acquired ledger, or nullptr if it is not yet available.
*
* Nullptr both before a header has been obtained, since there is
* nothing built yet to hand out, and once the acquisition has failed.
* A failed acquisition may still hold a partially built ledger, which
* must never be used, so failure reports nothing rather than rely on
* every caller to check isFailed() first. The pointer itself is kept,
* since getJson() reports on the partial maps of a failed acquire.
*/
std::shared_ptr<Ledger const>
getLedger() const
{
return ledger_;
return failed_ ? nullptr : ledger_;
}
std::uint32_t