diff --git a/src/ripple/app/ledger/MetaView.h b/src/ripple/app/ledger/MetaView.h index 0265b21051..f4f5a44891 100644 --- a/src/ripple/app/ledger/MetaView.h +++ b/src/ripple/app/ledger/MetaView.h @@ -94,6 +94,7 @@ private: using list_type = std::map; BasicView* parent_; + MetaView* mParent_ = NULL; list_type items_; boost::optional mDeferredCredits; TransactionMetaSet mSet; @@ -115,13 +116,9 @@ public: MetaView (Ledger::ref ledger, TransactionEngineParams tep); - /** Construct a copy. - Effects: - The copy is identical except that - the sequence number is one higher. + /** Construct a nested view. */ - // DEPRECATED - MetaView (MetaView const&); + MetaView (MetaView&); //-------------------------------------------------------------------------- // diff --git a/src/ripple/app/ledger/impl/MetaView.cpp b/src/ripple/app/ledger/impl/MetaView.cpp index 8f95e4395a..e1a2b8ffbe 100644 --- a/src/ripple/app/ledger/impl/MetaView.cpp +++ b/src/ripple/app/ledger/impl/MetaView.cpp @@ -69,16 +69,18 @@ MetaView::MetaView (Ledger::ref ledger, { } -MetaView::MetaView (MetaView const& other) - : parent_(other.parent_) +MetaView::MetaView (MetaView& other) + : parent_(&other) + , mParent_(&other) , items_(other.items_) - , mDeferredCredits(other.mDeferredCredits) , mSet(other.mSet) // VFALCO NOTE This is a change in behavior, // previous version set tapNONE , mParams(other.mParams) , mSeq(other.mSeq + 1) { + if (other.mDeferredCredits) + mDeferredCredits.emplace(); } //------------------------------------------------------------------------------ @@ -279,8 +281,23 @@ MetaView::deprecatedBalance( STAmount const& amount) const { if (mDeferredCredits) + { + if (mParent_) + { + assert (mParent_->mDeferredCredits); + return mDeferredCredits->adjustedBalance( + account, issuer, mParent_->deprecatedBalance(account, issuer, amount)); + } + return mDeferredCredits->adjustedBalance( account, issuer, amount); + } + else if (mParent_ && mParent_->mDeferredCredits) + { + return mParent_->mDeferredCredits->adjustedBalance( + account, issuer, amount); + } + return amount; } @@ -422,6 +439,7 @@ MetaView::deprecatedCreditHint( void MetaView::apply() { + // Write back the account states for (auto& item : items_) { @@ -433,7 +451,7 @@ void MetaView::apply() { case taaCACHED: assert(parent_->exists( - keylet::child(item.first))); + Keylet(sle->getType(), item.first))); break; case taaCREATE: @@ -458,6 +476,20 @@ void MetaView::apply() break; } } + + if (mDeferredCredits) + { + assert (mParent_ != NULL); + if (mParent_->areCreditsDeferred()) + { + for (auto& credit : *mDeferredCredits) + { + // This will go away soon + mParent_->mDeferredCredits->merge (credit); + } + } + } + // Safety precaution since we moved the // entries out, apply() cannot be called twice. items_.clear(); diff --git a/src/ripple/app/paths/PathState.cpp b/src/ripple/app/paths/PathState.cpp index ab9937b884..fb9e51a582 100644 --- a/src/ripple/app/paths/PathState.cpp +++ b/src/ripple/app/paths/PathState.cpp @@ -268,7 +268,7 @@ TER PathState::pushNode ( auto const& backNode = nodes_.back (); if (backNode.isAccount()) { - auto sleRippleState = metaView_->peek( + auto sleRippleState = metaView_.peek( keylet::line(backNode.account_, node.account_, backNode.issue_.currency)); // A "RippleState" means a balance betweeen two accounts for a @@ -291,7 +291,7 @@ TER PathState::pushNode ( << backNode.account_ << " and " << node.account_ << " for " << node.issue_.currency << "." ; - auto sleBck = metaView_->peek ( + auto sleBck = metaView_.peek ( keylet::account(backNode.account_)); // Is the source account the highest numbered account ID? bool bHigh = backNode.account_ > node.account_; @@ -318,13 +318,13 @@ TER PathState::pushNode ( if (resultCode == tesSUCCESS) { - STAmount saOwed = creditBalance (*metaView_, + STAmount saOwed = creditBalance (metaView_, node.account_, backNode.account_, node.issue_.currency); STAmount saLimit; if (saOwed <= zero) { - saLimit = creditLimit (*metaView_, + saLimit = creditLimit (metaView_, node.account_, backNode.account_, node.issue_.currency); @@ -413,7 +413,6 @@ TER PathState::pushNode ( // terStatus = tesSUCCESS, temBAD_PATH, terNO_LINE, terNO_ACCOUNT, terNO_AUTH, // or temBAD_PATH_LOOP TER PathState::expandPath ( - MetaView const& viewSource, STPath const& spSourcePath, AccountID const& uReceiverID, AccountID const& uSenderID) @@ -432,8 +431,6 @@ TER PathState::expandPath ( WriteLog (lsTRACE, RippleCalc) << "expandPath> " << spSourcePath.getJson (0); - metaView_.emplace(viewSource); - terStatus = tesSUCCESS; // XRP with issuer is malformed. @@ -627,7 +624,7 @@ void PathState::checkFreeze() // Check each order book for a global freeze if (nodes_[i].uFlags & STPathElement::typeIssuer) { - sle = metaView_->peek (keylet::account(nodes_[i].issue_.account)); + sle = metaView_.peek (keylet::account(nodes_[i].issue_.account)); if (sle && sle->isFlag (lsfGlobalFreeze)) { @@ -645,7 +642,7 @@ void PathState::checkFreeze() if (inAccount != outAccount) { - sle = metaView_->peek (keylet::account(outAccount)); + sle = metaView_.peek (keylet::account(outAccount)); if (sle && sle->isFlag (lsfGlobalFreeze)) { @@ -653,7 +650,7 @@ void PathState::checkFreeze() return; } - sle = metaView_->peek (keylet::line(inAccount, + sle = metaView_.peek (keylet::line(inAccount, outAccount, currencyID)); if (sle && sle->isFlag ( @@ -680,9 +677,9 @@ TER PathState::checkNoRipple ( Currency const& currency) { // fetch the ripple lines into and out of this node - SLE::pointer sleIn = metaView_->peek ( + SLE::pointer sleIn = metaView_.peek ( keylet::line(firstAccount, secondAccount, currency)); - SLE::pointer sleOut = metaView_->peek ( + SLE::pointer sleOut = metaView_.peek ( keylet::line(secondAccount, thirdAccount, currency)); if (!sleIn || !sleOut) diff --git a/src/ripple/app/paths/PathState.h b/src/ripple/app/paths/PathState.h index b5285d63b3..a05b659f92 100644 --- a/src/ripple/app/paths/PathState.h +++ b/src/ripple/app/paths/PathState.h @@ -35,20 +35,18 @@ class PathState : public CountedObject using Ptr = std::shared_ptr; using List = std::vector; - PathState (STAmount const& saSend, STAmount const& saSendMax) - : mIndex (0) + PathState (MetaView& view, STAmount const& saSend, STAmount const& saSendMax) + : metaView_ (view) + , mIndex (0) , uQuality (0) , saInReq (saSendMax) , saOutReq (saSend) { } - explicit PathState (const PathState& psSrc) = default; - void reset(STAmount const& in, STAmount const& out); TER expandPath ( - MetaView const& viewSource, STPath const& spSourcePath, AccountID const& uReceiverID, AccountID const& uSenderID @@ -105,7 +103,12 @@ class PathState : public CountedObject MetaView& metaView() { - return *metaView_; + return metaView_; + } + + void resetView (MetaView& view) + { + reconstruct (metaView_, view); } bool isDry() const @@ -149,7 +152,7 @@ private: // Source may only be used there if not mentioned by an account. AccountIssueToNodeIndex umReverse; - boost::optional metaView_; + MetaView metaView_; int mIndex; // Index/rank amoung siblings. std::uint64_t uQuality; // 0 = no quality/liquity left. diff --git a/src/ripple/app/paths/RippleCalc.cpp b/src/ripple/app/paths/RippleCalc.cpp index b2d2fb661e..299aba701b 100644 --- a/src/ripple/app/paths/RippleCalc.cpp +++ b/src/ripple/app/paths/RippleCalc.cpp @@ -94,7 +94,7 @@ RippleCalc::Output RippleCalc::rippleCalculate ( bool RippleCalc::addPathState(STPath const& path, TER& resultCode) { auto pathState = std::make_shared ( - saDstAmountReq_, saMaxAmountReq_); + metaView, saDstAmountReq_, saMaxAmountReq_); if (!pathState) { @@ -103,7 +103,6 @@ bool RippleCalc::addPathState(STPath const& path, TER& resultCode) } pathState->expandPath ( - metaView, path, uDstAccountID_, uSrcAccountID_); @@ -208,7 +207,6 @@ TER RippleCalc::rippleCalculate () while (resultCode == temUNCERTAIN) { int iBest = -1; - MetaView lesCheckpoint = metaView; int iDry = 0; // True, if ever computed multi-quality. @@ -228,7 +226,7 @@ TER RippleCalc::rippleCalculate () // Error if done, output met. PathCursor pc(*this, *pathState, multiQuality); - pc.nextIncrement (lesCheckpoint); + pc.nextIncrement (); // Compute increment. WriteLog (lsDEBUG, RippleCalc) @@ -287,13 +285,6 @@ TER RippleCalc::rippleCalculate () << " inPass()=" << pathState->inPass() << " saOutPass=" << pathState->outPass(); - assert (metaView.isValid ()); - metaView.swapWith (pathState->metaView()); - // For the path, save ledger state. - - // VFALCO Can this be done without the function call? - metaView.deprecatedInvalidate(); - iBest = pathState->index (); } } @@ -339,14 +330,9 @@ TER RippleCalc::rippleCalculate () pathState->unfundedOffers().begin (), pathState->unfundedOffers().end ()); - // Record best pass' MetaView to build off of and potentially - // return. + // Apply best pass' MetaView assert (pathState->metaView().isValid ()); - metaView.swapWith (pathState->metaView()); - - // VFALCO Why is this needed? Can it be done - // without the function call? - pathState->metaView().deprecatedInvalidate(); + pathState->metaView().apply(); actualAmountIn_ += pathState->inPass(); actualAmountOut_ += pathState->outPass(); @@ -421,10 +407,7 @@ TER RippleCalc::rippleCalculate () } else { - // We must restore the activeLedger from lesCheckpoint in the case - // when iBest is -1 and just before the result is set to tesSUCCESS. - - metaView.swapWith (lesCheckpoint); + // Don't apply any payment increments resultCode = tesSUCCESS; } } diff --git a/src/ripple/app/paths/RippleCalc.h b/src/ripple/app/paths/RippleCalc.h index 7e9b7e257e..7b23206092 100644 --- a/src/ripple/app/paths/RippleCalc.h +++ b/src/ripple/app/paths/RippleCalc.h @@ -98,11 +98,10 @@ public: STPathSet const& spsPaths, Input const* const pInputs = nullptr); - /** The active ledger. */ - // VFALCO TODO Fix this comment its not the ledger - // VFALCO TODO Rename this to view + // The view we are currently working on MetaView& metaView; + // If the transaction fails to meet some constraint, still need to delete // unfunded offers. // diff --git a/src/ripple/app/paths/cursor/Liquidity.cpp b/src/ripple/app/paths/cursor/Liquidity.cpp index 52a580c984..91bb25f125 100644 --- a/src/ripple/app/paths/cursor/Liquidity.cpp +++ b/src/ripple/app/paths/cursor/Liquidity.cpp @@ -25,13 +25,12 @@ namespace ripple { namespace path { -TER PathCursor::liquidity (MetaView const& lesCheckpoint) const +TER PathCursor::liquidity () const { TER resultCode = tecPATH_DRY; PathCursor pc = *this; - // duplicate - reconstruct(rippleCalc_.metaView, lesCheckpoint); + pathState_.resetView (rippleCalc_.metaView); for (pc.nodeIndex_ = pc.nodeSize(); pc.nodeIndex_--; ) { @@ -60,9 +59,7 @@ TER PathCursor::liquidity (MetaView const& lesCheckpoint) const if (resultCode != tesSUCCESS) return resultCode; - // Do forward. - // duplicate - reconstruct(rippleCalc_.metaView, lesCheckpoint); + pathState_.resetView (rippleCalc_.metaView); for (pc.nodeIndex_ = 0; pc.nodeIndex_ < pc.nodeSize(); ++pc.nodeIndex_) { diff --git a/src/ripple/app/paths/cursor/NextIncrement.cpp b/src/ripple/app/paths/cursor/NextIncrement.cpp index 09e6ca51ab..6140fcde33 100644 --- a/src/ripple/app/paths/cursor/NextIncrement.cpp +++ b/src/ripple/app/paths/cursor/NextIncrement.cpp @@ -34,7 +34,7 @@ namespace path { // This is the wrapper that restores a checkpointed version of the ledger so we // can write all over it without consequence. -void PathCursor::nextIncrement (MetaView const& lesCheckpoint) const +void PathCursor::nextIncrement () const { // The next state is what is available in preference order. // This is calculated when referenced accounts changed. @@ -42,7 +42,7 @@ void PathCursor::nextIncrement (MetaView const& lesCheckpoint) const // WriteLog (lsTRACE, RippleCalc) // << "nextIncrement: Path In: " << pathState_.getJson (); - auto status = liquidity(lesCheckpoint); + auto status = liquidity(); if (status == tesSUCCESS) { diff --git a/src/ripple/app/paths/cursor/PathCursor.h b/src/ripple/app/paths/cursor/PathCursor.h index c66ae9ab62..5bfdf4842a 100644 --- a/src/ripple/app/paths/cursor/PathCursor.h +++ b/src/ripple/app/paths/cursor/PathCursor.h @@ -50,7 +50,7 @@ public: { } - void nextIncrement(MetaView const& checkpoint) const; + void nextIncrement() const; private: PathCursor(PathCursor const&) = default; @@ -60,7 +60,7 @@ private: return {rippleCalc_, pathState_, multiQuality_, nodeIndex_ + delta}; } - TER liquidity(MetaView const& lesCheckpoint) const; + TER liquidity() const; TER reverseLiquidity () const; TER forwardLiquidity () const; @@ -95,7 +95,8 @@ private: MetaView& ledger() const { // VFALCO Rename metaView to view - return rippleCalc_.metaView; + //return rippleCalc_.metaView; + return pathState_.metaView(); } NodeIndex nodeSize() const diff --git a/src/ripple/ledger/DeferredCredits.h b/src/ripple/ledger/DeferredCredits.h index 376313190c..c8d2c4a247 100644 --- a/src/ripple/ledger/DeferredCredits.h +++ b/src/ripple/ledger/DeferredCredits.h @@ -59,6 +59,10 @@ public: STAmount const& amount); void clear (); + + std::map::iterator begin() { return map_.begin(); } + std::map::iterator end() { return map_.end(); } + void merge (std::pair const& p); }; } // ripple diff --git a/src/ripple/ledger/impl/DeferredCredits.cpp b/src/ripple/ledger/impl/DeferredCredits.cpp index 577dbe0631..a4e8ed34c2 100644 --- a/src/ripple/ledger/impl/DeferredCredits.cpp +++ b/src/ripple/ledger/impl/DeferredCredits.cpp @@ -147,5 +147,16 @@ void DeferredCredits::clear () map_.clear (); } +void DeferredCredits::merge (std::pair const& p) +{ + using std::get; + auto r = map_.emplace(p); + if (!r.second) + { + get<0>(r.first->second) += get<0>(p.second); + get<1>(r.first->second) += get<1>(p.second); + } +} + } // ripple