diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index 93b65b3d94..12d331507e 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -240,7 +240,15 @@ Ledger::Ledger (uint256 const& parentHash, txMap_->setImmutable (); stateMap_->setImmutable (); - setup(config); + + if (! setup(config)) + loaded = false; + + if (! loaded) + { + updateHash (); + getApp().family().missing_node (info_.hash); + } } // Create a new ledger that's a snapshot of this one @@ -682,31 +690,61 @@ Ledger::rawTxInsert (uint256 const& key, } } -void +bool Ledger::setup (Config const& config) { + bool ret = true; + fees_.base = config.FEE_DEFAULT; fees_.units = config.TRANSACTION_FEE_BASE; fees_.reserve = config.FEE_ACCOUNT_RESERVE; fees_.increment = config.FEE_OWNER_RESERVE; - auto const sle = read(keylet::fees()); - if (sle) + + try { - // VFALCO NOTE Why getFieldIndex and not isFieldPresent? + auto const sle = read(keylet::fees()); - if (sle->getFieldIndex (sfBaseFee) != -1) - fees_.base = sle->getFieldU64 (sfBaseFee); + if (sle) + { + // VFALCO NOTE Why getFieldIndex and not isFieldPresent? - if (sle->getFieldIndex (sfReferenceFeeUnits) != -1) - fees_.units = sle->getFieldU32 (sfReferenceFeeUnits); + if (sle->getFieldIndex (sfBaseFee) != -1) + fees_.base = sle->getFieldU64 (sfBaseFee); - if (sle->getFieldIndex (sfReserveBase) != -1) - fees_.reserve = sle->getFieldU32 (sfReserveBase); + if (sle->getFieldIndex (sfReferenceFeeUnits) != -1) + fees_.units = sle->getFieldU32 (sfReferenceFeeUnits); - if (sle->getFieldIndex (sfReserveIncrement) != -1) - fees_.increment = sle->getFieldU32 (sfReserveIncrement); + if (sle->getFieldIndex (sfReserveBase) != -1) + fees_.reserve = sle->getFieldU32 (sfReserveBase); + + if (sle->getFieldIndex (sfReserveIncrement) != -1) + fees_.increment = sle->getFieldU32 (sfReserveIncrement); + } } - rules_ = Rules(*this); + catch (SHAMapMissingNode &) + { + ret = false; + } + catch (...) + { + throw; + } + + + try + { + rules_ = Rules(*this); + } + catch (SHAMapMissingNode &) + { + ret = false; + } + catch (...) + { + throw; + } + + return ret; } std::shared_ptr diff --git a/src/ripple/app/ledger/Ledger.h b/src/ripple/app/ledger/Ledger.h index d35fed7e64..17a55ee05f 100644 --- a/src/ripple/app/ledger/Ledger.h +++ b/src/ripple/app/ledger/Ledger.h @@ -367,7 +367,9 @@ private: class sles_iter_impl; class txs_iter_impl; - void + bool saveValidatedLedger (bool current); + + bool setup (Config const& config); std::shared_ptr diff --git a/src/ripple/app/ledger/LedgerConsensus.h b/src/ripple/app/ledger/LedgerConsensus.h index da45a4189c..0f6f0205c4 100644 --- a/src/ripple/app/ledger/LedgerConsensus.h +++ b/src/ripple/app/ledger/LedgerConsensus.h @@ -95,6 +95,7 @@ void applyTransactions ( @return resultSuccess, resultFail or resultRetry */ int applyTransaction ( + Application& app, OpenView& view, std::shared_ptr const& txn, bool retryAssured, diff --git a/src/ripple/app/ledger/impl/LedgerConsensusImp.cpp b/src/ripple/app/ledger/impl/LedgerConsensusImp.cpp index 9b1796bad9..d604a88256 100644 --- a/src/ripple/app/ledger/impl/LedgerConsensusImp.cpp +++ b/src/ripple/app/ledger/impl/LedgerConsensusImp.cpp @@ -1035,7 +1035,7 @@ void LedgerConsensusImp::accept (std::shared_ptr set) { // Special case, we are replaying a ledger close for (auto& tx : replay->txns_) - applyTransaction (accum, tx.second, false, tapNO_CHECK_SIGN); + applyTransaction (app_, accum, tx.second, false, tapNO_CHECK_SIGN); } else { diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index efed23e8ee..8ffc90d6d7 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -118,6 +118,10 @@ private: FullBelowCache fullbelow_; NodeStore::Database& db_; + // missing node handler + std::uint32_t maxSeq = 0; + std::mutex maxSeqLock; + public: AppFamily (AppFamily const&) = delete; AppFamily& operator= (AppFamily const&) = delete; @@ -173,18 +177,48 @@ public: void missing_node (std::uint32_t seq) override { - uint256 const hash = app_.getLedgerMaster ().getHashBySeq (seq); - if (hash.isZero()) - app_.getInboundLedgers ().acquire ( - hash, seq, InboundLedger::fcGENERIC); + WriteLog (lsERROR, Ledger) << "Missing node in " << seq; + + // prevent recursive invocation + std::unique_lock lock (maxSeqLock); + + if (maxSeq == 0) + { + maxSeq = seq; + + do + { + // Try to acquire the most recent missing ledger + seq = maxSeq; + + lock.unlock(); + + // This can invoke the missing node handler + uint256 hash = app_.getLedgerMaster().getHashBySeq (seq); + + if (hash.isNonZero()) + app_.getInboundLedgers().acquire ( + hash, seq, InboundLedger::fcGENERIC); + + lock.lock(); + } + while (maxSeq != seq); + } + else if (maxSeq < seq) + { + // We found a more recent ledger with a missing node + maxSeq = seq; + } } - virtual void missing_node (uint256 const& hash) override { if (hash.isNonZero()) { + WriteLog (lsERROR, Ledger) << "Missing node in " + << to_string (hash); + app_.getInboundLedgers ().acquire ( hash, 0, InboundLedger::fcGENERIC); } @@ -1239,6 +1273,8 @@ bool ApplicationImp::loadOldLedger ( } loadLedger->setClosed (); + loadLedger->stateMap().flushDirty + (hotACCOUNT_NODE, loadLedger->info().seq); loadLedger->setAccepted (closeTime, closeTimeResolution, ! closeTimeEstimated); } diff --git a/src/ripple/shamap/Family.h b/src/ripple/shamap/Family.h index 354ee0c0ac..af112a5f73 100644 --- a/src/ripple/shamap/Family.h +++ b/src/ripple/shamap/Family.h @@ -62,7 +62,7 @@ public: virtual void - missing_node (uint256 const& hash) = 0; + missing_node (uint256 const& refHash) = 0; }; } // ripple diff --git a/src/ripple/shamap/tests/common.h b/src/ripple/shamap/tests/common.h index 8e48b35d6b..92d50bca97 100644 --- a/src/ripple/shamap/tests/common.h +++ b/src/ripple/shamap/tests/common.h @@ -104,9 +104,9 @@ public: { throw std::runtime_error("missing node"); } - + void - missing_node (uint256 const& hash) override + missing_node (uint256 const& refHash) override { throw std::runtime_error("missing node"); }