diff --git a/src/cpp/ripple/Ledger.cpp b/src/cpp/ripple/Ledger.cpp index 15d03084b4..56a7a008ac 100644 --- a/src/cpp/ripple/Ledger.cpp +++ b/src/cpp/ripple/Ledger.cpp @@ -529,6 +529,53 @@ Ledger::pointer Ledger::getSQL(const std::string& sql) return ret; } +uint256 Ledger::getHashByIndex(uint32 ledgerIndex) +{ + uint256 ret; + + std::string sql="SELECT LedgerHash FROM Ledgers WHERE LedgerSeq='"; + sql.append(boost::lexical_cast(ledgerIndex)); + sql.append("';"); + + std::string hash; + { + Database *db = theApp->getLedgerDB()->getDB(); + ScopedLock sl(theApp->getLedgerDB()->getDBLock()); + if (!db->executeSQL(sql) || !db->startIterRows()) + return ret; + db->getStr("LedgerHash", hash); + db->endIterRows(); + } + + ret.SetHex(hash); + return ret; +} + +bool Ledger::getHashesByIndex(uint32 ledgerIndex, uint256& ledgerHash, uint256& parentHash) +{ + std::string sql="SELECT LedgerHash,PrevHash FROM Ledgers WHERE LedgerSeq='"; + sql.append(boost::lexical_cast(ledgerIndex)); + sql.append("';"); + + std::string hash, prevHash; + { + Database *db = theApp->getLedgerDB()->getDB(); + ScopedLock sl(theApp->getLedgerDB()->getDBLock()); + if (!db->executeSQL(sql) || !db->startIterRows()) + return false; + db->getStr("LedgerHash", hash); + db->getStr("PrevHash", prevHash); + db->endIterRows(); + } + + ledgerHash.SetHex(hash); + parentHash.SetHex(prevHash); + + assert(ledgerHash.isNonZero() && ((ledgerIndex == 0) || parentHash.isNonZero())); + + return true; +} + Ledger::pointer Ledger::loadByIndex(uint32 ledgerIndex) { // This is a low-level function with no caching std::string sql="SELECT * from Ledgers WHERE LedgerSeq='"; diff --git a/src/cpp/ripple/Ledger.h b/src/cpp/ripple/Ledger.h index 27fad106c1..4ca92acc40 100644 --- a/src/cpp/ripple/Ledger.h +++ b/src/cpp/ripple/Ledger.h @@ -178,9 +178,11 @@ public: SLE::pointer getAccountRoot(const RippleAddress& naAccountID); void updateSkipList(); - // database functions + // database functions (low-level) static Ledger::pointer loadByIndex(uint32 ledgerIndex); static Ledger::pointer loadByHash(const uint256& ledgerHash); + static uint256 getHashByIndex(uint32 index); + static bool getHashesByIndex(uint32 index, uint256& ledgerHash, uint256& parentHash); void pendSave(bool fromConsensus); // next/prev function diff --git a/src/cpp/ripple/LedgerMaster.cpp b/src/cpp/ripple/LedgerMaster.cpp index 3c9fed8e3f..76cc44dcf2 100644 --- a/src/cpp/ripple/LedgerMaster.cpp +++ b/src/cpp/ripple/LedgerMaster.cpp @@ -134,19 +134,25 @@ bool LedgerMaster::haveLedgerRange(uint32 from, uint32 to) void LedgerMaster::asyncAccept(Ledger::pointer ledger) { - do + uint32 seq = ledger->getLedgerSeq(); + uint256 prevHash = ledger->getParentHash(); + + while (seq > 0) { { boost::recursive_mutex::scoped_lock ml(mLock); - mCompleteLedgers.setValue(ledger->getLedgerSeq()); - if ((ledger->getLedgerSeq() == 0) || mCompleteLedgers.hasValue(ledger->getLedgerSeq() - 1)) + mCompleteLedgers.setValue(seq); + --seq; + if (mCompleteLedgers.hasValue(seq)) break; } - Ledger::pointer prevLedger = mLedgerHistory.getLedgerBySeq(ledger->getLedgerSeq() - 1); // FIXME - if (!prevLedger || (prevLedger->getHash() != ledger->getParentHash())) + + uint256 tHash, pHash; + if (!Ledger::getHashesByIndex(seq, tHash, pHash) || (tHash != prevHash)) break; - ledger = prevLedger; - } while(1); + prevHash = pHash; + } + resumeAcquiring(); } @@ -156,7 +162,7 @@ bool LedgerMaster::acquireMissingLedger(const uint256& ledgerHash, uint32 ledger return true; Ledger::pointer ledger = mLedgerHistory.getLedgerBySeq(ledgerSeq); - if (ledger && (ledger->getHash() == ledgerHash)) + if (Ledger::getHashByIndex(ledgerSeq) == ledgerHash) { cLog(lsDEBUG) << "Ledger hash found in database"; mTooFast = true;