From 1798262d7ad673d93b550ef96f30ae658d9fa2b9 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Mon, 5 Oct 2026 18:15:02 +0000 Subject: [PATCH] refactor: Use LedgerHashesEntry everywhere (#8369) --- .../xrpl/ledger/entries/LedgerHashesEntry.h | 31 +++++++++++++++++++ src/libxrpl/ledger/View.cpp | 18 +++++------ src/xrpld/app/consensus/RCLValidations.cpp | 4 +-- .../app/ledger/detail/SkipListAcquire.cpp | 3 +- src/xrpld/app/misc/NegativeUNLVote.cpp | 4 +-- 5 files changed, 45 insertions(+), 15 deletions(-) diff --git a/include/xrpl/ledger/entries/LedgerHashesEntry.h b/include/xrpl/ledger/entries/LedgerHashesEntry.h index ab54d820a1..8a18008545 100644 --- a/include/xrpl/ledger/entries/LedgerHashesEntry.h +++ b/include/xrpl/ledger/entries/LedgerHashesEntry.h @@ -1,11 +1,17 @@ #pragma once +#include #include #include #include #include #include #include +#include +#include + +#include +#include namespace xrpl { @@ -25,6 +31,31 @@ public: : Base(keylet::skip(), view, j) { } + + /** + * Looks up a hash `diff` slots back from the most recent entry in the + * sfHashes vector (diff == 0 is the most recent entry). + * + * Callers decide which skip list entry to read and how to translate a + * target ledger sequence into `diff`; this only does the bounds check + * and vector indexing shared by both the recent (stride 1) and distant + * (stride 256) skip lists. + * + * @param diff how many slots back from the most recent hash to look up; + * 0 is the most recent hash. + * @return the hash at that slot, or std::nullopt if the entry does not + * exist or `diff` is out of range. + */ + [[nodiscard]] std::optional + hashAt(std::size_t diff) const + { + if (!this->exists()) + return std::nullopt; + STVector256 const vec = (*this)->getFieldV256(sfHashes); + if (vec.size() > diff) + return vec[vec.size() - diff - 1]; + return std::nullopt; + } }; using LedgerHashesEntryR = LedgerHashesEntry; diff --git a/src/libxrpl/ledger/View.cpp b/src/libxrpl/ledger/View.cpp index 26e3d42353..81e960ca78 100644 --- a/src/libxrpl/ledger/View.cpp +++ b/src/libxrpl/ledger/View.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -361,17 +362,16 @@ hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal) if (int const diff = ledger.seq() - seq; diff <= 256) { // Within 256... - auto const hashIndex = ledger.read(keylet::skip()); + LedgerHashesEntryR const hashIndex(ledger, journal); if (hashIndex) { XRPL_ASSERT( hashIndex->getFieldU32(sfLastLedgerSequence) == (ledger.seq() - 1), "xrpl::hashOfSeq : matching ledger sequence"); - STVector256 vec = hashIndex->getFieldV256(sfHashes); - if (vec.size() >= diff) - return vec[vec.size() - diff]; + if (auto const hash = hashIndex.hashAt(diff - 1)) + return hash; JLOG(journal.warn()) << "Ledger " << ledger.seq() << " missing hash for " << seq << " (" - << vec.size() << "," << diff << ")"; + << hashIndex->getFieldV256(sfHashes).size() << "," << diff << ")"; } else { @@ -387,16 +387,14 @@ hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal) } // in skiplist - auto const hashIndex = ledger.read(keylet::skip(seq)); + LedgerHashesEntryR const hashIndex(keylet::skip(seq), ledger, journal); if (hashIndex) { auto const lastSeq = hashIndex->getFieldU32(sfLastLedgerSequence); XRPL_ASSERT(lastSeq >= seq, "xrpl::hashOfSeq : minimum last ledger"); XRPL_ASSERT((lastSeq & 0xff) == 0, "xrpl::hashOfSeq : valid last ledger"); - auto const diff = (lastSeq - seq) >> 8; - STVector256 vec = hashIndex->getFieldV256(sfHashes); - if (vec.size() > diff) - return vec[vec.size() - diff - 1]; + if (auto const hash = hashIndex.hashAt((lastSeq - seq) >> 8)) + return hash; } JLOG(journal.warn()) << "Can't get seq " << seq << " from " << ledger.seq() << " error"; return std::nullopt; diff --git a/src/xrpld/app/consensus/RCLValidations.cpp b/src/xrpld/app/consensus/RCLValidations.cpp index c587a04cf0..9d19a2405e 100644 --- a/src/xrpld/app/consensus/RCLValidations.cpp +++ b/src/xrpld/app/consensus/RCLValidations.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -36,7 +36,7 @@ RCLValidatedLedger::RCLValidatedLedger( beast::Journal j) : ledgerID_{ledger->header().hash}, ledgerSeq_{ledger->seq()}, j_{j} { - auto const hashIndex = ledger->read(keylet::skip()); + LedgerHashesEntryR const hashIndex(*ledger, j_); if (hashIndex) { XRPL_ASSERT( diff --git a/src/xrpld/app/ledger/detail/SkipListAcquire.cpp b/src/xrpld/app/ledger/detail/SkipListAcquire.cpp index 66b5f4f526..b075718657 100644 --- a/src/xrpld/app/ledger/detail/SkipListAcquire.cpp +++ b/src/xrpld/app/ledger/detail/SkipListAcquire.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -183,7 +184,7 @@ SkipListAcquire::getData() const void SkipListAcquire::retrieveSkipList(std::shared_ptr const& ledger, ScopedLockType& sl) { - if (auto const hashIndex = ledger->read(keylet::skip()); + if (LedgerHashesEntryR const hashIndex(*ledger, journal_); hashIndex && hashIndex->isFieldPresent(sfHashes)) { auto const& slist = hashIndex->getFieldV256(sfHashes).value(); diff --git a/src/xrpld/app/misc/NegativeUNLVote.cpp b/src/xrpld/app/misc/NegativeUNLVote.cpp index ab401dcfeb..18dc47d3df 100644 --- a/src/xrpld/app/misc/NegativeUNLVote.cpp +++ b/src/xrpld/app/misc/NegativeUNLVote.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -170,7 +170,7 @@ NegativeUNLVote::buildScoreTable( validations.setSeqToKeep(seq - 1, seq + kFlagLedgerInterval); // Find FLAG_LEDGER_INTERVAL (i.e. 256) previous ledger hashes - auto const hashIndex = prevLedger->read(keylet::skip()); + LedgerHashesEntryR const hashIndex(*prevLedger, j_); if (!hashIndex || !hashIndex->isFieldPresent(sfHashes)) { JLOG(j_.debug()) << "N-UNL: ledger " << seq << " no history.";