From d21171b21eed11bf61f2b80e35f517392da3e271 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Tue, 9 Jun 2015 10:37:13 -0400 Subject: [PATCH] Refactor LedgerEntrySet: * Remove duplicate: This changes behavior to fix an apparent bug. The copy will now correctly inherit mParams instead of reverting to tapNONE * Tidy up LedgerEntrySet declarations * Tidy up TransactionEngine * Tidy PathCursor declarations * Add LedgerEntrySet::apply * Add LedgerEntrySet ctor * Add Keylet, keylet namespace * Add defaulted copy members * Use optional in TransactionEngine * Use optional in PathState * Return shared_ptr in Ledger::fetch * Don't call entryCache with zero * Deprecate invalidate * Remove default constructor * Remove unused container API * Remove CountedObject base class * Remove insert, clear * Remove entryCreate overload * Remove unused and tidy up STLedgerEntry * Make getEntry private and tidy * Replace members with adjustOwnerCount free function * Replace accountFunds with funds free function --- src/ripple/app/ledger/AcceptedLedgerTx.cpp | 3 +- src/ripple/app/ledger/Ledger.cpp | 21 +- src/ripple/app/ledger/Ledger.h | 9 +- src/ripple/app/ledger/LedgerEntrySet.cpp | 352 +++++++++---------- src/ripple/app/ledger/LedgerEntrySet.h | 219 ++++++------ src/ripple/app/main/Application.cpp | 2 + src/ripple/app/misc/NetworkOPs.cpp | 14 +- src/ripple/app/paths/PathRequest.cpp | 7 +- src/ripple/app/paths/PathState.cpp | 20 +- src/ripple/app/paths/PathState.h | 37 +- src/ripple/app/paths/RippleCalc.cpp | 9 +- src/ripple/app/paths/cursor/AdvanceNode.cpp | 4 +- src/ripple/app/paths/cursor/Liquidity.cpp | 8 +- src/ripple/app/paths/cursor/PathCursor.h | 13 +- src/ripple/app/tests/Env.h | 2 +- src/ripple/app/tx/TransactionEngine.h | 14 +- src/ripple/app/tx/impl/CancelTicket.cpp | 9 +- src/ripple/app/tx/impl/Change.cpp | 19 +- src/ripple/app/tx/impl/CreateOffer.cpp | 27 +- src/ripple/app/tx/impl/CreateTicket.cpp | 7 +- src/ripple/app/tx/impl/LocalTxs.cpp | 6 +- src/ripple/app/tx/impl/OfferStream.cpp | 6 +- src/ripple/app/tx/impl/Payment.cpp | 5 +- src/ripple/app/tx/impl/SetSignerList.cpp | 13 +- src/ripple/app/tx/impl/SetTrust.cpp | 12 +- src/ripple/app/tx/impl/Taker.cpp | 4 +- src/ripple/app/tx/impl/TransactionEngine.cpp | 66 +--- src/ripple/protocol/Indexes.h | 133 +++++++ src/ripple/protocol/STLedgerEntry.h | 61 +++- src/ripple/protocol/impl/Indexes.cpp | 115 ++++++ src/ripple/protocol/impl/STLedgerEntry.cpp | 53 ++- src/ripple/rpc/handlers/RipplePathFind.cpp | 2 +- 32 files changed, 746 insertions(+), 526 deletions(-) diff --git a/src/ripple/app/ledger/AcceptedLedgerTx.cpp b/src/ripple/app/ledger/AcceptedLedgerTx.cpp index 5e0e7b6f80..43916a7214 100644 --- a/src/ripple/app/ledger/AcceptedLedgerTx.cpp +++ b/src/ripple/app/ledger/AcceptedLedgerTx.cpp @@ -99,7 +99,8 @@ void AcceptedLedgerTx::buildJson () if (account != amount.issue ().account) { LedgerEntrySet les (mLedger, tapNONE, true); - auto const ownerFunds (les.accountFunds (account, amount, fhIGNORE_FREEZE)); + auto const ownerFunds (funds( + les, account, amount, fhIGNORE_FREEZE)); mJson[jss::transaction][jss::owner_funds] = ownerFunds.getText (); } diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index fdba43afc1..567b221f6b 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -984,20 +984,19 @@ Ledger::insert (SLE const& sle) assert(success); } -boost::optional +std::shared_ptr Ledger::fetch (uint256 const& key, boost::optional type) const { auto const item = mAccountStateMap->peekItem(key); if (! item) - return boost::none; - boost::optional result; - result.emplace(item->peekSerializer(), - item->getTag()); - if (type && result->getType() != type) - return {}; - return result; + return nullptr; + auto const sle = std::make_shared( + item->peekSerializer(), item->getTag()); + if (type && sle->getType() != type) + return nullptr; + return sle; } void @@ -1171,7 +1170,8 @@ void Ledger::updateSkipList () bool created; if (! sle) { - sle.emplace(ltLEDGER_HASHES, key); + sle = std::make_shared( + ltLEDGER_HASHES, key); created = true; } else @@ -1198,7 +1198,8 @@ void Ledger::updateSkipList () bool created; if (! sle) { - sle.emplace(ltLEDGER_HASHES, key); + sle = std::make_shared( + ltLEDGER_HASHES, key); created = true; } else diff --git a/src/ripple/app/ledger/Ledger.h b/src/ripple/app/ledger/Ledger.h index fce2b6f816..a722e1c01c 100644 --- a/src/ripple/app/ledger/Ledger.h +++ b/src/ripple/app/ledger/Ledger.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -138,10 +139,16 @@ public: then boost::none is returned. @return `empty` if the key is not present */ - boost::optional + std::shared_ptr fetch (uint256 const& key, boost::optional< LedgerEntryType> type = boost::none) const; + std::shared_ptr + fetch (Keylet const& k) const + { + return fetch(k.key, k.type); + } + // DEPRECATED // Retrieve immutable ledger entry SLE::pointer getSLEi (uint256 const& uHash) const; diff --git a/src/ripple/app/ledger/LedgerEntrySet.cpp b/src/ripple/app/ledger/LedgerEntrySet.cpp index b595fd71fd..dfdf54f578 100644 --- a/src/ripple/app/ledger/LedgerEntrySet.cpp +++ b/src/ripple/app/ledger/LedgerEntrySet.cpp @@ -34,31 +34,76 @@ namespace ripple { // VFALCO TODO Replace this macro with a documented language constant // NOTE Is this part of the protocol? // -#define DIR_NODE_MAX 32 +#define DIR_NODE_MAX 32 -void LedgerEntrySet::init (Ledger::ref ledger, uint256 const& transactionID, - std::uint32_t ledgerID, TransactionEngineParams params) +LedgerEntrySet::LedgerEntrySet (LedgerEntrySet const& other) + : mLedger(other.mLedger) + , mEntries(other.mEntries) + , 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) +{ +} + +LedgerEntrySet::LedgerEntrySet(Ledger::ref ledger, + uint256 const& transactionID, + std::uint32_t ledgerID, + TransactionEngineParams params) + : mLedger(ledger) + , mParams(params) { - mEntries.clear (); - if (mDeferredCredits) - mDeferredCredits->clear (); - mLedger = ledger; mSet.init (transactionID, ledgerID); - mParams = params; - mSeq = 0; } -void LedgerEntrySet::clear () +LedgerEntrySet::LedgerEntrySet (Ledger::ref ledger, + TransactionEngineParams tep, bool immutable) + : mLedger (ledger) + , mParams (tep) + , mImmutable (immutable) { - mEntries.clear (); - mSet.clear (); - if (mDeferredCredits) - mDeferredCredits->clear (); } -LedgerEntrySet LedgerEntrySet::duplicate () const +void LedgerEntrySet::apply() { - return LedgerEntrySet (mLedger, mEntries, mSet, mSeq + 1, mDeferredCredits); + // Write back the account states + for (auto const& item : mEntries) + { + // VFALCO TODO rvalue move the mEntry, make + // sure the mNodes is not used after + // this function is called. + auto sle = item.second.mEntry; + switch (item.second.mAction) + { + case taaNONE: + assert (false); + break; + + case taaCACHED: + break; + + case taaCREATE: + // VFALCO Is this logging necessary anymore? + WriteLog (lsDEBUG, LedgerEntrySet) << + "applyTransaction: taaCREATE: " << sle->getText (); + mLedger->insert(*sle); + break; + + case taaMODIFY: + WriteLog (lsDEBUG, LedgerEntrySet) << + "applyTransaction: taaMODIFY: " << sle->getText (); + mLedger->replace(*sle); + break; + + case taaDELETE: + WriteLog (lsDEBUG, LedgerEntrySet) << + "applyTransaction: taaDELETE: " << sle->getText (); + mLedger->erase(item.first); + break; + } + } } void LedgerEntrySet::swapWith (LedgerEntrySet& e) @@ -74,7 +119,7 @@ void LedgerEntrySet::swapWith (LedgerEntrySet& e) // Find an entry in the set. If it has the wrong sequence number, copy it and update the sequence number. // This is basically: copy-on-read. -SLE::pointer LedgerEntrySet::getEntry (uint256 const& index, LedgerEntryAction& action) +SLE::pointer LedgerEntrySet::getEntry (uint256 const& index, Action& action) { auto it = mEntries.find (index); @@ -87,7 +132,7 @@ SLE::pointer LedgerEntrySet::getEntry (uint256 const& index, LedgerEntryAction& if (it->second.mSeq != mSeq) { assert (it->second.mSeq < mSeq); - it->second.mEntry = std::make_shared (*it->second.mEntry); + it->second.mEntry = std::make_shared (*it->second.mEntry); it->second.mSeq = mSeq; } @@ -95,26 +140,15 @@ SLE::pointer LedgerEntrySet::getEntry (uint256 const& index, LedgerEntryAction& return it->second.mEntry; } -SLE::pointer LedgerEntrySet::entryCreate (LedgerEntryType letType, uint256 const& index) -{ - assert (index.isNonZero ()); - SLE::pointer sleNew = std::make_shared (letType, index); - entryCreate (sleNew); - return sleNew; -} - SLE::pointer LedgerEntrySet::entryCache (LedgerEntryType letType, uint256 const& key) { + assert(key.isNonZero ()); assert (mLedger); SLE::pointer sle; - // VFALCO Shouldn't be calling this with invalid keys, - // but apparently its happening. Need to track it down. - //assert(key.isNonZero ()); - if (key.isNonZero ()) { - LedgerEntryAction action; + Action action; sle = getEntry (key, action); if (! sle) @@ -128,10 +162,7 @@ SLE::pointer LedgerEntrySet::entryCache (LedgerEntryType letType, uint256 const& } else { - auto maybe_sle = mLedger->fetch(key, letType); - if (maybe_sle) - sle = std::make_shared( - std::move(*maybe_sle)); + sle = mLedger->fetch(key, letType); } if (sle) @@ -160,7 +191,7 @@ void LedgerEntrySet::entryCache (SLE::ref sle) if (it == mEntries.end ()) { - mEntries.insert (std::make_pair (sle->getIndex (), LedgerEntrySetEntry (sle, taaCACHED, mSeq))); + mEntries.insert (std::make_pair (sle->getIndex (), Item (sle, taaCACHED, mSeq))); return; } @@ -185,7 +216,7 @@ void LedgerEntrySet::entryCreate (SLE::ref sle) if (it == mEntries.end ()) { - mEntries.insert (std::make_pair (sle->getIndex (), LedgerEntrySetEntry (sle, taaCREATE, mSeq))); + mEntries.insert (std::make_pair (sle->getIndex (), Item (sle, taaCREATE, mSeq))); return; } @@ -223,7 +254,7 @@ void LedgerEntrySet::entryModify (SLE::ref sle) if (it == mEntries.end ()) { - mEntries.insert (std::make_pair (sle->getIndex (), LedgerEntrySetEntry (sle, taaMODIFY, mSeq))); + mEntries.insert (std::make_pair (sle->getIndex (), Item (sle, taaMODIFY, mSeq))); return; } @@ -260,7 +291,7 @@ void LedgerEntrySet::entryDelete (SLE::ref sle) if (it == mEntries.end ()) { assert (false); // deleting an entry not cached? - mEntries.insert (std::make_pair (sle->getIndex (), LedgerEntrySetEntry (sle, taaDELETE, mSeq))); + mEntries.insert (std::make_pair (sle->getIndex (), Item (sle, taaDELETE, mSeq))); return; } @@ -379,7 +410,8 @@ SLE::pointer LedgerEntrySet::getForMod (uint256 const& node, Ledger::ref ledger, if (it->second.mSeq != mSeq) { - it->second.mEntry = std::make_shared (*it->second.mEntry); + it->second.mEntry = + std::make_shared (*it->second.mEntry); it->second.mSeq = mSeq; } @@ -395,15 +427,10 @@ SLE::pointer LedgerEntrySet::getForMod (uint256 const& node, Ledger::ref ledger, } auto sle = ledger->fetch(node); - if (sle) - { - auto p = std::make_shared( - std::move(*sle)); - newMods.insert (std::make_pair (node, p)); - return p; - } - - return {}; + if (! sle) + return nullptr; + newMods.insert (std::make_pair (node, sle)); + return sle; } bool LedgerEntrySet::threadTx (RippleAddress const& threadTo, Ledger::ref ledger, @@ -611,36 +638,6 @@ void LedgerEntrySet::calcRawMeta (Serializer& s, TER result, std::uint32_t index WriteLog (lsTRACE, LedgerEntrySet) << "Metadata:" << mSet.getJson (0); } -TER LedgerEntrySet::dirCount (uint256 const& uRootIndex, std::uint32_t& uCount) -{ - std::uint64_t uNodeDir = 0; - - uCount = 0; - - do - { - SLE::pointer sleNode = entryCache (ltDIR_NODE, getDirNodeIndex (uRootIndex, uNodeDir)); - - if (sleNode) - { - uCount += sleNode->getFieldV256 (sfIndexes).size (); - - uNodeDir = sleNode->getFieldU64 (sfIndexNext); // Get next node. - } - else if (uNodeDir) - { - WriteLog (lsWARNING, LedgerEntrySet) << "dirCount: no such node"; - - assert (false); - - return tefBAD_LEDGER; - } - } - while (uNodeDir); - - return tesSUCCESS; -} - bool LedgerEntrySet::dirIsEmpty (uint256 const& uRootIndex) { std::uint64_t uNodeDir = 0; @@ -679,10 +676,10 @@ TER LedgerEntrySet::dirAdd ( if (!sleRoot) { // No root, make it. - sleRoot = entryCreate (ltDIR_NODE, uRootIndex); + sleRoot = std::make_shared(ltDIR_NODE, uRootIndex); sleRoot->setFieldH256 (sfRootIndex, uRootIndex); + entryCreate (sleRoot); fDescriber (sleRoot, true); - sleNode = sleRoot; uNodeDir = 0; } @@ -726,8 +723,10 @@ TER LedgerEntrySet::dirAdd ( entryModify (sleRoot); // Create the new node. - sleNode = entryCreate (ltDIR_NODE, getDirNodeIndex (uRootIndex, uNodeDir)); + sleNode = std::make_shared( + ltDIR_NODE, getDirNodeIndex(uRootIndex, uNodeDir)); sleNode->setFieldH256 (sfRootIndex, uRootIndex); + entryCreate (sleNode); if (uNodeDir != 1) sleNode->setFieldU64 (sfIndexPrevious, uNodeDir - 1); @@ -1080,7 +1079,7 @@ uint256 LedgerEntrySet::getNextLedgerIndex (uint256 const& uHash) { // find next node in ledger that isn't deleted by LES uint256 ledgerNext = uHash; - std::map::const_iterator it; + std::map::const_iterator it; do { @@ -1113,69 +1112,6 @@ uint256 LedgerEntrySet::getNextLedgerIndex ( return next; } -void LedgerEntrySet::incrementOwnerCount (SLE::ref sleAccount) -{ - increaseOwnerCount (sleAccount, 1); -} - -void LedgerEntrySet::incrementOwnerCount (Account const& owner) -{ - increaseOwnerCount( - entryCache (ltACCOUNT_ROOT, getAccountRootIndex (owner)), 1); -} - -void -LedgerEntrySet::increaseOwnerCount (SLE::ref sleAccount, std::uint32_t howMuch) -{ - assert (sleAccount); - - std::uint32_t const current_count = sleAccount->getFieldU32 (sfOwnerCount); - std::uint32_t new_count = current_count + howMuch; - - // Check for integer overflow -- well defined behavior on unsigned. - if (new_count < current_count) - { - WriteLog (lsFATAL, LedgerEntrySet) << - "Account " << sleAccount->getFieldAccount160 (sfAccount) << - " owner count exceeds max!"; - new_count = std::numeric_limits::max (); - } - sleAccount->setFieldU32 (sfOwnerCount, new_count); - entryModify (sleAccount); -} - -void LedgerEntrySet::decrementOwnerCount (SLE::ref sleAccount) -{ - decreaseOwnerCount (sleAccount, 1); -} - -void LedgerEntrySet::decrementOwnerCount (Account const& owner) -{ - decreaseOwnerCount( - entryCache (ltACCOUNT_ROOT, getAccountRootIndex (owner)), 1); -} - -void -LedgerEntrySet::decreaseOwnerCount (SLE::ref sleAccount, std::uint32_t howMuch) -{ - assert (sleAccount); - - std::uint32_t const current_count = sleAccount->getFieldU32 (sfOwnerCount); - std::uint32_t new_count = current_count - howMuch; - - // Check for integer underflow -- well defined behavior on unsigned. - if (new_count > current_count) - { - WriteLog (lsFATAL, LedgerEntrySet) << - "Account " << sleAccount->getFieldAccount160 (sfAccount) << - " owner count set below 0!"; - new_count = 0; - assert (false); // "This is a dangerous place." Stop in a debug build. - } - sleAccount->setFieldU32 (sfOwnerCount, new_count); - entryModify (sleAccount); -} - TER LedgerEntrySet::offerDelete (SLE::pointer sleOffer) { if (!sleOffer) @@ -1197,7 +1133,8 @@ TER LedgerEntrySet::offerDelete (SLE::pointer sleOffer) false, uBookNode, uDirectory, offerIndex, true, false); if (tesSUCCESS == terResult) - decrementOwnerCount (owner); + adjustOwnerCount(*this, entryCache(ltACCOUNT_ROOT, + getAccountRootIndex(owner)), -1); entryDelete (sleOffer); @@ -1333,43 +1270,6 @@ bool LedgerEntrySet::isFrozen( return false; } -// Returns the funds available for account for a currency/issuer. -// Use when you need a default for rippling account's currency. -// XXX Should take into account quality? -// --> saDefault/currency/issuer -// <-- saFunds: Funds available. May be negative. -// -// If the issuer is the same as account, funds are unlimited, use result is -// saDefault. -STAmount LedgerEntrySet::accountFunds ( - Account const& account, STAmount const& saDefault, FreezeHandling zeroIfFrozen) -{ - STAmount saFunds; - - if (!saDefault.native () && saDefault.getIssuer () == account) - { - saFunds = saDefault; - - WriteLog (lsTRACE, LedgerEntrySet) << "accountFunds:" << - " account=" << to_string (account) << - " saDefault=" << saDefault.getFullText () << - " SELF-FUNDED"; - } - else - { - saFunds = accountHolds ( - account, saDefault.getCurrency (), saDefault.getIssuer (), - zeroIfFrozen); - - WriteLog (lsTRACE, LedgerEntrySet) << "accountFunds:" << - " account=" << to_string (account) << - " saDefault=" << saDefault.getFullText () << - " saFunds=" << saFunds.getFullText (); - } - - return saFunds; -} - TER LedgerEntrySet::trustCreate ( const bool bSrcHigh, Account const& uSrcAccountID, @@ -1393,7 +1293,9 @@ TER LedgerEntrySet::trustCreate ( auto const& uLowAccountID = !bSrcHigh ? uSrcAccountID : uDstAccountID; auto const& uHighAccountID = bSrcHigh ? uSrcAccountID : uDstAccountID; - SLE::pointer sleRippleState = entryCreate (ltRIPPLE_STATE, uIndex); + auto sleRippleState = std::make_shared( + ltRIPPLE_STATE, uIndex); + entryCreate (sleRippleState); std::uint64_t uLowNode; std::uint64_t uHighNode; @@ -1469,7 +1371,7 @@ TER LedgerEntrySet::trustCreate ( } sleRippleState->setFieldU32 (sfFlags, uFlags); - incrementOwnerCount (sleAccount); + adjustOwnerCount(*this, sleAccount, 1); // ONLY: Create ripple balance. sleRippleState->setFieldAmount (sfBalance, bSetHigh ? -saBalance : saBalance); @@ -1659,7 +1561,8 @@ TER LedgerEntrySet::rippleCredit ( // Sender quality out is 0. { // Clear the reserve of the sender, possibly delete the line! - decrementOwnerCount (uSenderID); + adjustOwnerCount(*this, entryCache(ltACCOUNT_ROOT, + getAccountRootIndex(uSenderID)), -1); // Clear reserve flag. sleRippleState->setFieldU32 ( @@ -1881,9 +1784,9 @@ bool LedgerEntrySet::checkState ( { std::uint32_t const flags (state->getFieldU32 (sfFlags)); - auto sender_account = entryCache (ltACCOUNT_ROOT, + auto sle = entryCache (ltACCOUNT_ROOT, getAccountRootIndex (sender)); - assert (sender_account); + assert (sle); // YYY Could skip this if rippling in reverse. if (before > zero @@ -1893,7 +1796,7 @@ bool LedgerEntrySet::checkState ( && (flags & (!bSenderHigh ? lsfLowReserve : lsfHighReserve)) // Sender reserve is set. && static_cast (flags & (!bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple)) != - static_cast (sender_account->getFlags() & lsfDefaultRipple) + static_cast (sle->getFlags() & lsfDefaultRipple) && !(flags & (!bSenderHigh ? lsfLowFreeze : lsfHighFreeze)) && !state->getFieldAmount ( !bSenderHigh ? sfLowLimit : sfHighLimit) @@ -1905,8 +1808,9 @@ bool LedgerEntrySet::checkState ( !bSenderHigh ? sfLowQualityOut : sfHighQualityOut)) // Sender quality out is 0. { + // VFALCO Where is the line being deleted? // Clear the reserve of the sender, possibly delete the line! - decrementOwnerCount (sender_account); + adjustOwnerCount(*this, sle, -1); // Clear reserve flag. state->setFieldU32 (sfFlags, @@ -2146,4 +2050,70 @@ ScopedDeferCredits::~ScopedDeferCredits () } } +//------------------------------------------------------------------------------ + +void +adjustOwnerCount (LedgerEntrySet& view, + std::shared_ptr const& sle, int amount) +{ + assert(amount != 0); + auto const current = + sle->getFieldU32 (sfOwnerCount); + auto adjusted = current + amount; + if (amount > 0) + { + // Overflow is well defined on unsigned + if (adjusted < current) + { + WriteLog (lsFATAL, LedgerEntrySet) << + "Account " << sle->getFieldAccount160(sfAccount) << + " owner count exceeds max!"; + adjusted = + std::numeric_limits::max (); + } + } + else + { + // Underflow is well defined on unsigned + if (adjusted > current) + { + WriteLog (lsFATAL, LedgerEntrySet) << + "Account " << sle->getFieldAccount160 (sfAccount) << + " owner count set below 0!"; + adjusted = 0; + assert(false); + } + } + sle->setFieldU32 (sfOwnerCount, adjusted); + view.entryModify (sle); +} + +STAmount +funds (LedgerEntrySet& view, Account const& id, + STAmount const& saDefault, FreezeHandling freezeHandling) +{ + STAmount saFunds; + + if (!saDefault.native () && + saDefault.getIssuer () == id) + { + saFunds = saDefault; + WriteLog (lsTRACE, LedgerEntrySet) << "accountFunds:" << + " account=" << to_string (id) << + " saDefault=" << saDefault.getFullText () << + " SELF-FUNDED"; + } + else + { + saFunds = view.accountHolds(id, + saDefault.getCurrency(), saDefault.getIssuer(), + freezeHandling); + WriteLog (lsTRACE, LedgerEntrySet) << "accountFunds:" << + " account=" << to_string (id) << + " saDefault=" << saDefault.getFullText () << + " saFunds=" << saFunds.getFullText (); + } + return saFunds; +} + } // ripple diff --git a/src/ripple/app/ledger/LedgerEntrySet.h b/src/ripple/app/ledger/LedgerEntrySet.h index 1b2c500532..6a5804c4bf 100644 --- a/src/ripple/app/ledger/LedgerEntrySet.h +++ b/src/ripple/app/ledger/LedgerEntrySet.h @@ -24,7 +24,9 @@ #include #include #include +#include #include +#include namespace ripple { @@ -50,39 +52,12 @@ enum TransactionEngineParams tapADMIN = 0x400, }; -enum LedgerEntryAction -{ - taaNONE, - taaCACHED, // Unmodified. - taaMODIFY, // Modifed, must have previously been taaCACHED. - taaDELETE, // Delete, must have previously been taaDELETE or taaMODIFY. - taaCREATE, // Newly created. -}; - enum FreezeHandling { fhIGNORE_FREEZE, fhZERO_IF_FROZEN }; -class LedgerEntrySetEntry - : public CountedObject -{ -public: - static char const* getCountedObjectName () { return "LedgerEntrySetEntry"; } - - SLE::pointer mEntry; - LedgerEntryAction mAction; - int mSeq; - - LedgerEntrySetEntry (SLE::ref e, LedgerEntryAction a, int s) - : mEntry (e) - , mAction (a) - , mSeq (s) - { - } -}; - /** An LES is a LedgerEntrySet. It's a view into a ledger used while a transaction is processing. @@ -91,30 +66,73 @@ public: transaction finishes, the LES is committed into the ledger to make the modifications. The transaction metadata is built from the LES too. */ -/** @{ */ class LedgerEntrySet - : public CountedObject { +private: + using NodeToLedgerEntry = + hash_map; + + enum Action + { + taaNONE, + taaCACHED, // Unmodified. + taaMODIFY, // Modifed, must have previously been taaCACHED. + taaDELETE, // Delete, must have previously been taaDELETE or taaMODIFY. + taaCREATE, // Newly created. + }; + + class Item + { + public: + int mSeq; + Action mAction; + std::shared_ptr mEntry; + + Item (SLE::ref e, Action a, int s) + : mSeq (s) + , mAction (a) + , mEntry (e) + { + } + }; + + Ledger::pointer mLedger; + // Implementation requires an ordered container + std::map mEntries; + boost::optional mDeferredCredits; + TransactionMetaSet mSet; + TransactionEngineParams mParams = tapNONE; + int mSeq = 0; + bool mImmutable = false; + public: - static char const* getCountedObjectName () { return "LedgerEntrySet"; } + LedgerEntrySet& operator= (LedgerEntrySet const&) = delete; - LedgerEntrySet ( - Ledger::ref ledger, TransactionEngineParams tep, bool immutable = false) - : mLedger (ledger), mParams (tep), mSeq (0), mImmutable (immutable) - { - } + /** Construct a copy. + Effects: + The copy is identical except that + the sequence number is one higher. + */ + LedgerEntrySet (LedgerEntrySet const&); - LedgerEntrySet () : mParams (tapNONE), mSeq (0), mImmutable (false) - { - } + LedgerEntrySet (Ledger::ref ledger, + uint256 const& transactionID, + std::uint32_t ledgerID, + TransactionEngineParams params); - // Make a duplicate of this set. - LedgerEntrySet duplicate () const; + LedgerEntrySet (Ledger::ref ledger, + TransactionEngineParams tep, + bool immutable = false); + + /** Apply changes to the backing ledger. */ + void + apply(); // Swap the contents of two sets void swapWith (LedgerEntrySet&); - void invalidate () + // VFALCO Only called from RippleCalc.cpp + void deprecatedInvalidate() { mLedger.reset (); mDeferredCredits.reset (); @@ -135,26 +153,17 @@ public: ++mSeq; } - void init (Ledger::ref ledger, uint256 const& transactionID, - std::uint32_t ledgerID, TransactionEngineParams params); - - void clear (); - Ledger::pointer& getLedger () { return mLedger; } - // basic entry functions - SLE::pointer getEntry (uint256 const& index, LedgerEntryAction&); - void entryCache (SLE::ref); // Add this entry to the cache void entryCreate (SLE::ref); // This entry will be created void entryDelete (SLE::ref); // This entry will be deleted void entryModify (SLE::ref); // This entry will be modified // higher-level ledger functions - SLE::pointer entryCreate (LedgerEntryType letType, uint256 const& uIndex); SLE::pointer entryCache (LedgerEntryType letType, uint256 const& key); std::shared_ptr @@ -177,35 +186,24 @@ public: bool dirFirst (uint256 const& uRootIndex, SLE::pointer& sleNode, unsigned int & uDirEntry, uint256 & uEntryIndex); + bool dirFirst (uint256 const& uRootIndex, std::shared_ptr& sleNode, unsigned int & uDirEntry, uint256 & uEntryIndex); bool dirNext (uint256 const& uRootIndex, SLE::pointer& sleNode, unsigned int & uDirEntry, uint256 & uEntryIndex); + bool dirNext (uint256 const& uRootIndex, std::shared_ptr& sleNode, unsigned int & uDirEntry, uint256 & uEntryIndex); bool dirIsEmpty (uint256 const& uDirIndex); - TER dirCount (uint256 const& uDirIndex, std::uint32_t & uCount); - uint256 getNextLedgerIndex (uint256 const& uHash); uint256 getNextLedgerIndex (uint256 const& uHash, uint256 const& uEnd); - /** @{ */ - void incrementOwnerCount (SLE::ref sleAccount); - void incrementOwnerCount (Account const& owner); - void increaseOwnerCount (SLE::ref sleAccount, std::uint32_t howMuch); - /** @} */ - - /** @{ */ - void decrementOwnerCount (SLE::ref sleAccount); - void decrementOwnerCount (Account const& owner); - void decreaseOwnerCount (SLE::ref sleAccount, std::uint32_t howMuch); - /** @} */ - // Offer functions. TER offerDelete (SLE::pointer); + TER offerDelete (uint256 const& offerIndex) { return offerDelete( entryCache (ltOFFER, offerIndex)); @@ -220,6 +218,7 @@ public: bool isGlobalFrozen (Account const& issuer); void enableDeferredCredits (bool enable=true); + bool areCreditsDeferred () const; TER rippleCredit ( @@ -229,8 +228,7 @@ public: STAmount accountHolds ( Account const& account, Currency const& currency, Account const& issuer, FreezeHandling freezeHandling); - STAmount accountFunds ( - Account const& account, const STAmount & saDefault, FreezeHandling freezeHandling); + TER accountSend ( Account const& uSenderID, Account const& uReceiverID, const STAmount & saAmount); @@ -248,46 +246,15 @@ public: STAmount const& saSrcLimit, const std::uint32_t uSrcQualityIn = 0, const std::uint32_t uSrcQualityOut = 0); + TER trustDelete ( SLE::ref sleRippleState, Account const& uLowAccountID, Account const& uHighAccountID); Json::Value getJson (int) const; + void calcRawMeta (Serializer&, TER result, std::uint32_t index); - // iterator functions - using iterator = std::map::iterator; - using const_iterator = std::map::const_iterator; - - bool empty () const - { - return mEntries.empty (); - } - const_iterator cbegin () const - { - return mEntries.cbegin (); - } - const_iterator cend () const - { - return mEntries.cend (); - } - const_iterator begin () const - { - return mEntries.cbegin (); - } - const_iterator end () const - { - return mEntries.cend (); - } - iterator begin () - { - return mEntries.begin (); - } - iterator end () - { - return mEntries.end (); - } - void setDeliveredAmount (STAmount const& amt) { mSet.setDeliveredAmount (amt); @@ -302,24 +269,7 @@ public: TER transfer_xrp (Account const& from, Account const& to, STAmount const& amount); private: - Ledger::pointer mLedger; - std::map mEntries; // cannot be unordered! - // Defers credits made to accounts until later - boost::optional mDeferredCredits; - - using NodeToLedgerEntry = hash_map; - - TransactionMetaSet mSet; - TransactionEngineParams mParams; - int mSeq; - bool mImmutable; - - LedgerEntrySet ( - Ledger::ref ledger, const std::map& e, - const TransactionMetaSet & s, int m, boost::optional const& ft) : - mLedger (ledger), mEntries (e), mDeferredCredits (ft), mSet (s), mParams (tapNONE), - mSeq (m), mImmutable (false) - {} + SLE::pointer getEntry (uint256 const& index, Action&); SLE::pointer getForMod ( uint256 const& node, Ledger::ref ledger, @@ -359,8 +309,17 @@ private: STAmount const& amount); }; +template +inline +void +reconstruct (LedgerEntrySet& v, Args&&... args) noexcept +{ + v.~LedgerEntrySet(); + new(&v) LedgerEntrySet( + std::forward(args)...); +} + using LedgerView = LedgerEntrySet; -/** @} */ //------------------------------------------------------------------------------ @@ -382,6 +341,30 @@ std::uint32_t rippleTransferRate (LedgerEntrySet& ledger, Account const& uSenderID, Account const& uReceiverID, Account const& issuer); +//------------------------------------------------------------------------------ +// +// API +// +//------------------------------------------------------------------------------ + +/** Adjust the owner count up or down. */ +void +adjustOwnerCount (LedgerEntrySet& view, + std::shared_ptr const& sle, int amount); + +// Returns the funds available for account for a currency/issuer. +// Use when you need a default for rippling account's currency. +// XXX Should take into account quality? +// --> saDefault/currency/issuer +// <-- saFunds: Funds available. May be negative. +// +// If the issuer is the same as account, funds are unlimited, use result is +// saDefault. +STAmount +funds (LedgerEntrySet& view, Account const& id, + STAmount const& saDefault, + FreezeHandling freezeHandling); + } // ripple #endif diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index 0189ffb794..cccea90624 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -1193,6 +1193,8 @@ bool ApplicationImp::loadOldLedger ( if (stp.object && (uIndex.isNonZero())) { + // VFALCO TODO This is the only place that + // constructor is used, try to remove it STLedgerEntry sle (*stp.object, uIndex); bool ok = loadLedger->addSLE (sle); if (!ok) diff --git a/src/ripple/app/misc/NetworkOPs.cpp b/src/ripple/app/misc/NetworkOPs.cpp index 7a8d08bd6a..d1b2c65b05 100644 --- a/src/ripple/app/misc/NetworkOPs.cpp +++ b/src/ripple/app/misc/NetworkOPs.cpp @@ -2496,9 +2496,10 @@ Json::Value NetworkOPsImp::transJson( // If the offer create is not self funded then add the owner balance if (account != amount.issue ().account) { + // VFALCO Why are we doing this hack? LedgerEntrySet les (lpCurrent, tapNONE, true); - auto const ownerFunds (les.accountFunds (account, amount, fhIGNORE_FREEZE)); - + auto const ownerFunds = funds( + les,account, amount, fhIGNORE_FREEZE); jvObj[jss::transaction][jss::owner_funds] = ownerFunds.getText (); } } @@ -2947,8 +2948,13 @@ void NetworkOPsImp::getBookPage ( m_journal.trace << "getBookPage: bDirectAdvance"; - sleOfferDir = lesActive.entryCache ( - ltDIR_NODE, lpLedger->getNextLedgerIndex (uTipIndex, uBookEnd)); + uint256 const ledgerIndex = + lpLedger->getNextLedgerIndex (uTipIndex, uBookEnd); + if (ledgerIndex.isNonZero()) + sleOfferDir = lesActive.entryCache ( + ltDIR_NODE, ledgerIndex); + else + sleOfferDir.reset(); if (!sleOfferDir) { diff --git a/src/ripple/app/paths/PathRequest.cpp b/src/ripple/app/paths/PathRequest.cpp index 933a05feb3..adf500ed21 100644 --- a/src/ripple/app/paths/PathRequest.cpp +++ b/src/ripple/app/paths/PathRequest.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include namespace ripple { @@ -480,7 +480,8 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast) if (valid) { - LedgerEntrySet lesSandbox (cache->getLedger (), tapNONE); + LedgerEntrySet lesSandbox( + cache->getLedger(), tapNONE); auto& sourceAccount = !isXRP (currIssuer.account) ? currIssuer.account : isXRP (currIssuer.currency) @@ -505,7 +506,7 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast) m_journal.debug << iIdentifier << " Trying with an extra path element"; spsPaths.push_back (fullLiquidityPath); - lesSandbox.clear(); + reconstruct(lesSandbox, cache->getLedger (), tapNONE); rc = path::RippleCalc::rippleCalculate ( lesSandbox, saMaxAmount, diff --git a/src/ripple/app/paths/PathState.cpp b/src/ripple/app/paths/PathState.cpp index 09d456c5d7..cab0e2d308 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 = lesEntries.entryCache ( + auto sleRippleState = lesEntries_->entryCache ( ltRIPPLE_STATE, getRippleStateIndex ( backNode.account_, @@ -295,7 +295,7 @@ TER PathState::pushNode ( << backNode.account_ << " and " << node.account_ << " for " << node.issue_.currency << "." ; - auto sleBck = lesEntries.entryCache ( + auto sleBck = lesEntries_->entryCache ( ltACCOUNT_ROOT, getAccountRootIndex (backNode.account_)); // Is the source account the highest numbered account ID? @@ -323,13 +323,13 @@ TER PathState::pushNode ( if (resultCode == tesSUCCESS) { - STAmount saOwed = creditBalance (lesEntries, + STAmount saOwed = creditBalance (*lesEntries_, node.account_, backNode.account_, node.issue_.currency); STAmount saLimit; if (saOwed <= zero) { - saLimit = creditLimit (lesEntries, + saLimit = creditLimit (*lesEntries_, node.account_, backNode.account_, node.issue_.currency); @@ -437,7 +437,7 @@ TER PathState::expandPath ( WriteLog (lsTRACE, RippleCalc) << "expandPath> " << spSourcePath.getJson (0); - lesEntries = lesSource.duplicate (); + lesEntries_.emplace(lesSource); terStatus = tesSUCCESS; @@ -632,7 +632,7 @@ void PathState::checkFreeze() // Check each order book for a global freeze if (nodes_[i].uFlags & STPathElement::typeIssuer) { - sle = lesEntries.entryCache (ltACCOUNT_ROOT, + sle = lesEntries_->entryCache (ltACCOUNT_ROOT, getAccountRootIndex (nodes_[i].issue_.account)); if (sle && sle->isFlag (lsfGlobalFreeze)) @@ -651,7 +651,7 @@ void PathState::checkFreeze() if (inAccount != outAccount) { - sle = lesEntries.entryCache (ltACCOUNT_ROOT, + sle = lesEntries_->entryCache (ltACCOUNT_ROOT, getAccountRootIndex (outAccount)); if (sle && sle->isFlag (lsfGlobalFreeze)) @@ -660,7 +660,7 @@ void PathState::checkFreeze() return; } - sle = lesEntries.entryCache (ltRIPPLE_STATE, + sle = lesEntries_->entryCache (ltRIPPLE_STATE, getRippleStateIndex (inAccount, outAccount, currencyID)); @@ -688,9 +688,9 @@ TER PathState::checkNoRipple ( Currency const& currency) { // fetch the ripple lines into and out of this node - SLE::pointer sleIn = lesEntries.entryCache (ltRIPPLE_STATE, + SLE::pointer sleIn = lesEntries_->entryCache (ltRIPPLE_STATE, getRippleStateIndex (firstAccount, secondAccount, currency)); - SLE::pointer sleOut = lesEntries.entryCache (ltRIPPLE_STATE, + SLE::pointer sleOut = lesEntries_->entryCache (ltRIPPLE_STATE, getRippleStateIndex (secondAccount, thirdAccount, currency)); if (!sleIn || !sleOut) diff --git a/src/ripple/app/paths/PathState.h b/src/ripple/app/paths/PathState.h index d6f516d706..8e336f11de 100644 --- a/src/ripple/app/paths/PathState.h +++ b/src/ripple/app/paths/PathState.h @@ -23,6 +23,7 @@ #include #include #include +#include namespace ripple { @@ -102,20 +103,37 @@ class PathState : public CountedObject static bool lessPriority (PathState const& lhs, PathState const& rhs); - LedgerEntrySet& ledgerEntries() { return lesEntries; } + // VFALCO Remove or rename to view, + LedgerEntrySet& ledgerEntries() + { + return *lesEntries_; + } bool isDry() const { return !(saInPass && saOutPass); } - private: +private: TER checkNoRipple ( Account const&, Account const&, Account const&, Currency const&); /** Clear path structures, and clear each node. */ void clear(); + TER pushNode ( + int const iType, + Account const& account, + Currency const& currency, + Account const& issuer); + + TER pushImpliedNodes ( + Account const& account, + Currency const& currency, + Account const& issuer); + + Json::Value getJson () const; + TER terStatus; path::Node::List nodes_; @@ -132,7 +150,7 @@ class PathState : public CountedObject // Source may only be used there if not mentioned by an account. AccountIssueToNodeIndex umReverse; - LedgerEntrySet lesEntries; + boost::optional lesEntries_; int mIndex; // Index/rank amoung siblings. std::uint64_t uQuality; // 0 = no quality/liquity left. @@ -147,19 +165,6 @@ class PathState : public CountedObject // If true, all liquidity on this path has been consumed. bool allLiquidityConsumed_ = false; - - TER pushNode ( - int const iType, - Account const& account, - Currency const& currency, - Account const& issuer); - - TER pushImpliedNodes ( - Account const& account, - Currency const& currency, - Account const& issuer); - - Json::Value getJson () const; }; } // ripple diff --git a/src/ripple/app/paths/RippleCalc.cpp b/src/ripple/app/paths/RippleCalc.cpp index c47600982c..2f3e8be7a7 100644 --- a/src/ripple/app/paths/RippleCalc.cpp +++ b/src/ripple/app/paths/RippleCalc.cpp @@ -288,7 +288,9 @@ TER RippleCalc::rippleCalculate () assert (mActiveLedger.isValid ()); mActiveLedger.swapWith (pathState->ledgerEntries()); // For the path, save ledger state. - mActiveLedger.invalidate (); + + // VFALCO Can this be done without the function call? + mActiveLedger.deprecatedInvalidate(); iBest = pathState->index (); } @@ -339,7 +341,10 @@ TER RippleCalc::rippleCalculate () // return. assert (pathState->ledgerEntries().isValid ()); mActiveLedger.swapWith (pathState->ledgerEntries()); - pathState->ledgerEntries().invalidate (); + + // VFALCO Why is this needed? Can it be done + // without the function call? + pathState->ledgerEntries().deprecatedInvalidate(); actualAmountIn_ += pathState->inPass(); actualAmountOut_ += pathState->outPass(); diff --git a/src/ripple/app/paths/cursor/AdvanceNode.cpp b/src/ripple/app/paths/cursor/AdvanceNode.cpp index df6e82449e..af20c4acfa 100644 --- a/src/ripple/app/paths/cursor/AdvanceNode.cpp +++ b/src/ripple/app/paths/cursor/AdvanceNode.cpp @@ -128,7 +128,7 @@ TER PathCursor::advanceNode (bool const bReverse) const = node().sleOffer->getFieldAmount (sfTakerGets); // Funds left. - node().saOfferFunds = ledger().accountFunds ( + node().saOfferFunds = funds (ledger(), node().offerOwnerAccount_, node().saTakerGets, fhZERO_IF_FROZEN); @@ -329,7 +329,7 @@ TER PathCursor::advanceNode (bool const bReverse) const // Only the current node is allowed to use the source. - node().saOfferFunds = ledger().accountFunds ( + node().saOfferFunds = funds(ledger(), node().offerOwnerAccount_, node().saTakerGets, fhZERO_IF_FROZEN); diff --git a/src/ripple/app/paths/cursor/Liquidity.cpp b/src/ripple/app/paths/cursor/Liquidity.cpp index d20a0331f5..ff8077a4e0 100644 --- a/src/ripple/app/paths/cursor/Liquidity.cpp +++ b/src/ripple/app/paths/cursor/Liquidity.cpp @@ -30,7 +30,9 @@ TER PathCursor::liquidity (LedgerEntrySet const& lesCheckpoint) const TER resultCode = tecPATH_DRY; PathCursor pc = *this; - ledger() = lesCheckpoint.duplicate (); + // duplicate + reconstruct(rippleCalc_.mActiveLedger, lesCheckpoint); + for (pc.nodeIndex_ = pc.nodeSize(); pc.nodeIndex_--; ) { WriteLog (lsTRACE, RippleCalc) @@ -59,7 +61,9 @@ TER PathCursor::liquidity (LedgerEntrySet const& lesCheckpoint) const return resultCode; // Do forward. - ledger() = lesCheckpoint.duplicate (); + // duplicate + reconstruct(rippleCalc_.mActiveLedger, lesCheckpoint); + for (pc.nodeIndex_ = 0; pc.nodeIndex_ < pc.nodeSize(); ++pc.nodeIndex_) { WriteLog (lsTRACE, RippleCalc) diff --git a/src/ripple/app/paths/cursor/PathCursor.h b/src/ripple/app/paths/cursor/PathCursor.h index c35dd6ce89..06a208197f 100644 --- a/src/ripple/app/paths/cursor/PathCursor.h +++ b/src/ripple/app/paths/cursor/PathCursor.h @@ -55,7 +55,8 @@ public: private: PathCursor(PathCursor const&) = default; - PathCursor increment(int delta = 1) const { + PathCursor increment(int delta = 1) const + { return {rippleCalc_, pathState_, multiQuality_, nodeIndex_ + delta}; } @@ -90,11 +91,6 @@ private: STAmount& saInAct, STAmount& saInFees) const; - RippleCalc& rippleCalc_; - PathState& pathState_; - bool multiQuality_; - NodeIndex nodeIndex_; - LedgerEntrySet& ledger() const { return rippleCalc_.mActiveLedger; @@ -129,6 +125,11 @@ private: { return node (restrict (nodeIndex_ + 1)); } + + RippleCalc& rippleCalc_; + PathState& pathState_; + bool multiQuality_; + NodeIndex nodeIndex_; }; } // path diff --git a/src/ripple/app/tests/Env.h b/src/ripple/app/tests/Env.h index 810c25c599..17a300aa18 100644 --- a/src/ripple/app/tests/Env.h +++ b/src/ripple/app/tests/Env.h @@ -46,7 +46,7 @@ class AccountInfo private: Account account_; std::shared_ptr ledger_; - boost::optional root_; + std::shared_ptr root_; public: AccountInfo(Account const& account, diff --git a/src/ripple/app/tx/TransactionEngine.h b/src/ripple/app/tx/TransactionEngine.h index 3a6104fef1..20b879eb0c 100644 --- a/src/ripple/app/tx/TransactionEngine.h +++ b/src/ripple/app/tx/TransactionEngine.h @@ -22,6 +22,7 @@ #include #include +#include #include namespace ripple { @@ -35,11 +36,7 @@ static multisign_t const multisign; // One instance per ledger. // Only one transaction applied at a time. class TransactionEngine - : public CountedObject { -public: - static char const* getCountedObjectName () { return "TransactionEngine"; } - private: bool enableMultiSign_ = #if RIPPLE_ENABLE_MULTI_SIGN @@ -48,17 +45,16 @@ private: false; #endif - LedgerEntrySet mNodes; - - void txnWrite (); + boost::optional mNodes; protected: Ledger::pointer mLedger; int mTxnSeq = 0; public: - TransactionEngine () = default; + TransactionEngine() = default; + explicit TransactionEngine (Ledger::ref ledger) : mLedger (ledger) { @@ -81,7 +77,7 @@ public: LedgerEntrySet& view () { - return mNodes; + return *mNodes; } Ledger::ref diff --git a/src/ripple/app/tx/impl/CancelTicket.cpp b/src/ripple/app/tx/impl/CancelTicket.cpp index d270a10706..255e2af837 100644 --- a/src/ripple/app/tx/impl/CancelTicket.cpp +++ b/src/ripple/app/tx/impl/CancelTicket.cpp @@ -52,9 +52,11 @@ public: if (!sleTicket) return tecNO_ENTRY; - Account const ticket_owner (sleTicket->getFieldAccount160 (sfAccount)); + auto const ticket_owner = + sleTicket->getFieldAccount160 (sfAccount); - bool authorized (mTxnAccountID == ticket_owner); + bool authorized = + mTxnAccountID == ticket_owner; // The target can also always remove a ticket if (!authorized && sleTicket->isFieldPresent (sfTarget)) @@ -77,7 +79,8 @@ public: TER const result = mEngine->view ().dirDelete (false, hint, getOwnerDirIndex (ticket_owner), ticketId, false, (hint == 0)); - mEngine->view ().decrementOwnerCount (ticket_owner); + adjustOwnerCount(mEngine->view(), mEngine->view().entryCache( + ltACCOUNT_ROOT, getAccountRootIndex(ticket_owner)), -1); mEngine->view ().entryDelete (sleTicket); return result; diff --git a/src/ripple/app/tx/impl/Change.cpp b/src/ripple/app/tx/impl/Change.cpp index 17507ba87c..13e2b3bd76 100644 --- a/src/ripple/app/tx/impl/Change.cpp +++ b/src/ripple/app/tx/impl/Change.cpp @@ -122,15 +122,18 @@ private: SLE::pointer amendmentObject (mEngine->view().entryCache (ltAMENDMENTS, index)); if (!amendmentObject) - amendmentObject = mEngine->view().entryCreate(ltAMENDMENTS, index); + { + amendmentObject = std::make_shared( + ltAMENDMENTS, index); + mEngine->view().entryCreate(amendmentObject); + } - STVector256 amendments (amendmentObject->getFieldV256 (sfAmendments)); + STVector256 amendments = + amendmentObject->getFieldV256(sfAmendments); if (std::find (amendments.begin(), amendments.end(), - amendment) != amendments.end ()) - { + amendment) != amendments.end ()) return tefALREADY; - } amendments.push_back (amendment); amendmentObject->setFieldV256 (sfAmendments, amendments); @@ -151,7 +154,11 @@ private: SLE::pointer feeObject = mEngine->view().entryCache (ltFEE_SETTINGS, index); if (!feeObject) - feeObject = mEngine->view().entryCreate (ltFEE_SETTINGS, index); + { + feeObject = std::make_shared( + ltFEE_SETTINGS, index); + mEngine->view().entryCreate(feeObject); + } // VFALCO-FIXME this generates errors // m_journal.trace << diff --git a/src/ripple/app/tx/impl/CreateOffer.cpp b/src/ripple/app/tx/impl/CreateOffer.cpp index cafefecbbe..8fa8c74c40 100644 --- a/src/ripple/app/tx/impl/CreateOffer.cpp +++ b/src/ripple/app/tx/impl/CreateOffer.cpp @@ -101,11 +101,9 @@ private: { if (offer.fully_consumed ()) return true; - - auto const funds (view.accountFunds (offer.owner(), - offer.amount().out, fhZERO_IF_FROZEN)); - - return (funds <= zero); + auto const amount = funds(view, offer.owner(), + offer.amount().out, fhZERO_IF_FROZEN); + return (amount <= zero); } static @@ -202,7 +200,7 @@ private: m_journal.debug << " in: " << offers_direct.tip ().amount().in; m_journal.debug << " out: " << offers_direct.tip ().amount ().out; m_journal.debug << " owner: " << offers_direct.tip ().owner (); - m_journal.debug << " funds: " << view.accountFunds ( + m_journal.debug << " funds: " << funds(view, offers_direct.tip ().owner (), offers_direct.tip ().amount ().out, fhIGNORE_FREEZE); @@ -222,12 +220,12 @@ private: { if (m_journal.debug) { - auto const owner1_funds_before = view.accountFunds ( + auto const owner1_funds_before = funds(view, offers_leg1.tip ().owner (), offers_leg1.tip ().amount ().out, fhIGNORE_FREEZE); - auto const owner2_funds_before = view.accountFunds ( + auto const owner2_funds_before = funds(view, offers_leg2.tip ().owner (), offers_leg2.tip ().amount ().out, fhIGNORE_FREEZE); @@ -321,7 +319,7 @@ private: m_journal.debug << " in: " << offer.amount ().in; m_journal.debug << " out: " << offer.amount ().out; m_journal.debug << " owner: " << offer.owner (); - m_journal.debug << " funds: " << view.accountFunds ( + m_journal.debug << " funds: " << funds(view, offer.owner (), offer.amount ().out, fhIGNORE_FREEZE); } @@ -604,7 +602,7 @@ public: result = tecFROZEN; } - else if (view.accountFunds ( + else if (funds(view, mTxnAccountID, saTakerGets, fhZERO_IF_FROZEN) <= zero) { if (m_journal.debug) m_journal.debug << @@ -795,7 +793,7 @@ public: if (result == tesSUCCESS) { // Update owner count. - view.incrementOwnerCount (sleCreator); + adjustOwnerCount(view, sleCreator, 1); if (m_journal.trace) m_journal.trace << "adding to book: " << to_string (saTakerPays.issue ()) << @@ -818,8 +816,7 @@ public: if (result == tesSUCCESS) { - SLE::pointer sleOffer (mEngine->view().entryCreate (ltOFFER, offer_index)); - + auto sleOffer = std::make_shared(ltOFFER, offer_index); sleOffer->setFieldAccount (sfAccount, mTxnAccountID); sleOffer->setFieldU32 (sfSequence, uSequence); sleOffer->setFieldH256 (sfBookDirectory, uDirectory); @@ -827,15 +824,13 @@ public: sleOffer->setFieldAmount (sfTakerGets, saTakerGets); sleOffer->setFieldU64 (sfOwnerNode, uOwnerNode); sleOffer->setFieldU64 (sfBookNode, uBookNode); - if (uExpiration) sleOffer->setFieldU32 (sfExpiration, uExpiration); - if (bPassive) sleOffer->setFlag (lsfPassive); - if (bSell) sleOffer->setFlag (lsfSell); + mEngine->view().entryCreate(sleOffer); } if (result != tesSUCCESS) diff --git a/src/ripple/app/tx/impl/CreateTicket.cpp b/src/ripple/app/tx/impl/CreateTicket.cpp index c76ead5cff..d1dbf548d4 100644 --- a/src/ripple/app/tx/impl/CreateTicket.cpp +++ b/src/ripple/app/tx/impl/CreateTicket.cpp @@ -85,14 +85,13 @@ public: return tesSUCCESS; } - SLE::pointer sleTicket = mEngine->view().entryCreate (ltTICKET, + SLE::pointer sleTicket = std::make_shared(ltTICKET, getTicketIndex (mTxnAccountID, mTxn.getSequence ())); - sleTicket->setFieldAccount (sfAccount, mTxnAccountID); sleTicket->setFieldU32 (sfSequence, mTxn.getSequence ()); - if (expiration != 0) sleTicket->setFieldU32 (sfExpiration, expiration); + mEngine->view().entryCreate (sleTicket); if (mTxn.isFieldPresent (sfTarget)) { @@ -134,7 +133,7 @@ public: sleTicket->setFieldU64(sfOwnerNode, hint); // If we succeeded, the new entry counts agains the creator's reserve. - mEngine->view ().incrementOwnerCount (mTxnAccount); + adjustOwnerCount(mEngine->view(), mTxnAccount, 1); return result; } diff --git a/src/ripple/app/tx/impl/LocalTxs.cpp b/src/ripple/app/tx/impl/LocalTxs.cpp index e17c96a719..81208e0a6a 100644 --- a/src/ripple/app/tx/impl/LocalTxs.cpp +++ b/src/ripple/app/tx/impl/LocalTxs.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -125,8 +126,9 @@ public: return true; if (ledger->hasTransaction (txn.getID ())) return true; - auto const sle = ledger->fetch( - getAccountRootIndex(txn.getAccount())); + auto const sle = fetch(*ledger, + getAccountRootIndex(txn.getAccount().getAccountID()), + getApp().getSLECache()); if (! sle) return false; if (sle->getFieldU32 (sfSequence) > txn.getSeq ()) diff --git a/src/ripple/app/tx/impl/OfferStream.cpp b/src/ripple/app/tx/impl/OfferStream.cpp index 66094c7c82..4a9ccfd480 100644 --- a/src/ripple/app/tx/impl/OfferStream.cpp +++ b/src/ripple/app/tx/impl/OfferStream.cpp @@ -122,8 +122,8 @@ OfferStream::step () // Calculate owner funds // NIKB NOTE The calling code also checks the funds, how expensive is // looking up the funds twice? - STAmount const owner_funds (view().accountFunds ( - m_offer.owner(), amount.out, fhZERO_IF_FROZEN)); + auto const owner_funds = funds(view(), + m_offer.owner(), amount.out, fhZERO_IF_FROZEN); // Check for unfunded offer if (owner_funds <= zero) @@ -131,7 +131,7 @@ OfferStream::step () // If the owner's balance in the pristine view is the same, // we haven't modified the balance and therefore the // offer is "found unfunded" versus "became unfunded" - auto const original_funds = view_cancel().accountFunds ( + auto const original_funds = funds(view_cancel(), m_offer.owner(), amount.out, fhZERO_IF_FROZEN); if (original_funds == owner_funds) diff --git a/src/ripple/app/tx/impl/Payment.cpp b/src/ripple/app/tx/impl/Payment.cpp index bbeef99654..db83c45d11 100644 --- a/src/ripple/app/tx/impl/Payment.cpp +++ b/src/ripple/app/tx/impl/Payment.cpp @@ -233,10 +233,11 @@ public: } // Create the account. - auto const newIndex = getAccountRootIndex (uDstAccountID); - sleDst = mEngine->view().entryCreate (ltACCOUNT_ROOT, newIndex); + sleDst = std::make_shared(ltACCOUNT_ROOT, + getAccountRootIndex (uDstAccountID)); sleDst->setFieldAccount (sfAccount, uDstAccountID); sleDst->setFieldU32 (sfSequence, 1); + mEngine->view().entryCreate(sleDst); } else if ((sleDst->getFlags () & lsfRequireDestTag) && !mTxn.isFieldPresent (sfDestinationTag)) diff --git a/src/ripple/app/tx/impl/SetSignerList.cpp b/src/ripple/app/tx/impl/SetSignerList.cpp index 6ce7124047..0af8ca5386 100644 --- a/src/ripple/app/tx/impl/SetSignerList.cpp +++ b/src/ripple/app/tx/impl/SetSignerList.cpp @@ -234,8 +234,8 @@ SetSignerList::replaceSignerList (uint256 const& index) return tecINSUFFICIENT_RESERVE; // Everything's ducky. Add the ltSIGNER_LIST to the ledger. - SLE::pointer signerList ( - mEngine->view().entryCreate (ltSIGNER_LIST, index)); + auto signerList = std::make_shared(ltSIGNER_LIST, index); + mEngine->view().entryCreate (signerList); writeSignersToLedger (signerList); // Lambda for call to dirAdd. @@ -259,7 +259,8 @@ SetSignerList::replaceSignerList (uint256 const& index) signerList->setFieldU64 (sfOwnerNode, hint); // If we succeeded, the new entry counts against the creator's reserve. - mEngine->view ().increaseOwnerCount (mTxnAccount, addedOwnerCount); + adjustOwnerCount(mEngine->view(), + mTxnAccount, addedOwnerCount); return result; } @@ -295,13 +296,17 @@ SetSignerList::destroySignerList (uint256 const& index) getOwnerDirIndex (mTxnAccountID), index, false, (hint == 0)); if (result == tesSUCCESS) - mEngine->view ().decreaseOwnerCount (mTxnAccount, removeFromOwnerCount); + adjustOwnerCount(mEngine->view(), + mTxnAccount, removeFromOwnerCount); mEngine->view ().entryDelete (signerList); return result; } +// VFALCO NOTE This name is misleading, the signers +// are not written to the ledger they are +// added to the SLE. void SetSignerList::writeSignersToLedger (SLE::pointer ledgerEntry) { diff --git a/src/ripple/app/tx/impl/SetTrust.cpp b/src/ripple/app/tx/impl/SetTrust.cpp index 7c688345d6..0af6d18a8f 100644 --- a/src/ripple/app/tx/impl/SetTrust.cpp +++ b/src/ripple/app/tx/impl/SetTrust.cpp @@ -339,7 +339,8 @@ public: if (bLowReserveSet && !bLowReserved) { // Set reserve for low account. - mEngine->view ().incrementOwnerCount (sleLowAccount); + adjustOwnerCount(mEngine->view(), + sleLowAccount, 1); uFlagsOut |= lsfLowReserve; if (!bHigh) @@ -349,14 +350,16 @@ public: if (bLowReserveClear && bLowReserved) { // Clear reserve for low account. - mEngine->view ().decrementOwnerCount (sleLowAccount); + adjustOwnerCount(mEngine->view(), + sleLowAccount, -1); uFlagsOut &= ~lsfLowReserve; } if (bHighReserveSet && !bHighReserved) { // Set reserve for high account. - mEngine->view ().incrementOwnerCount (sleHighAccount); + adjustOwnerCount(mEngine->view(), + sleHighAccount, 1); uFlagsOut |= lsfHighReserve; if (bHigh) @@ -366,7 +369,8 @@ public: if (bHighReserveClear && bHighReserved) { // Clear reserve for high account. - mEngine->view ().decrementOwnerCount (sleHighAccount); + adjustOwnerCount(mEngine->view(), + sleHighAccount, -1); uFlagsOut &= ~lsfHighReserve; } diff --git a/src/ripple/app/tx/impl/Taker.cpp b/src/ripple/app/tx/impl/Taker.cpp index ef7a8e1e02..48e6526570 100644 --- a/src/ripple/app/tx/impl/Taker.cpp +++ b/src/ripple/app/tx/impl/Taker.cpp @@ -581,9 +581,9 @@ Taker::consume_offer (Offer const& offer, Amounts const& order) } STAmount -Taker::get_funds (Account const& account, STAmount const& funds) const +Taker::get_funds (Account const& account, STAmount const& amount) const { - return view_.accountFunds (account, funds, fhZERO_IF_FROZEN); + return funds(view_, account, amount, fhZERO_IF_FROZEN); } TER Taker::transfer_xrp ( diff --git a/src/ripple/app/tx/impl/TransactionEngine.cpp b/src/ripple/app/tx/impl/TransactionEngine.cpp index 6bf40d6b95..ae16c348b0 100644 --- a/src/ripple/app/tx/impl/TransactionEngine.cpp +++ b/src/ripple/app/tx/impl/TransactionEngine.cpp @@ -31,53 +31,6 @@ namespace ripple { // XXX Make sure all fields are recognized in transactions. // -void TransactionEngine::txnWrite () -{ - // Write back the account states - for (auto& it : mNodes) - { - // VFALCO TODO rvalue move the mEntry, make - // sure the mNodes is not used after - // this function is called. - SLE::ref sleEntry = it.second.mEntry; - - switch (it.second.mAction) - { - case taaNONE: - assert (false); - break; - - case taaCACHED: - break; - - case taaCREATE: - { - // VFALCO Is this logging necessary anymore? - WriteLog (lsDEBUG, TransactionEngine) << - "applyTransaction: taaCREATE: " << sleEntry->getText (); - mLedger->insert(*sleEntry); - } - break; - - case taaMODIFY: - { - WriteLog (lsDEBUG, TransactionEngine) << - "applyTransaction: taaMODIFY: " << sleEntry->getText (); - mLedger->replace(*sleEntry); - } - break; - - case taaDELETE: - { - WriteLog (lsDEBUG, TransactionEngine) << - "applyTransaction: taaDELETE: " << sleEntry->getText (); - mLedger->erase(it.first); - } - break; - } - } -} - std::pair TransactionEngine::applyTransaction ( STTx const& txn, @@ -96,7 +49,8 @@ TransactionEngine::applyTransaction ( return std::make_pair(temINVALID_FLAG, false); } - mNodes.init (mLedger, txID, mLedger->getLedgerSeq (), params); + mNodes.emplace(mLedger, txID, + mLedger->getLedgerSeq(), params); #ifdef BEAST_DEBUG if (1) @@ -146,9 +100,10 @@ TransactionEngine::applyTransaction ( // only claim the transaction fee WriteLog (lsDEBUG, TransactionEngine) << "Reprocessing tx " << txID << " to only claim fee"; - mNodes.clear (); + mNodes.emplace(mLedger, txID, + mLedger->getLedgerSeq(), params); - SLE::pointer txnAcct = mNodes.entryCache (ltACCOUNT_ROOT, + SLE::pointer txnAcct = mNodes->entryCache (ltACCOUNT_ROOT, getAccountRootIndex (txn.getSourceAccount ())); if (!txnAcct) @@ -182,7 +137,7 @@ TransactionEngine::applyTransaction ( fee = balance; txnAcct->setFieldAmount (sfBalance, balance - fee); txnAcct->setFieldU32 (sfSequence, t_seq + 1); - mNodes.entryModify (txnAcct); + mNodes->entryModify (txnAcct); didApply = true; } } @@ -202,7 +157,7 @@ TransactionEngine::applyTransaction ( WriteLog (lsFATAL, TransactionEngine) << transToken (terResult) << ": " << transHuman (terResult); WriteLog (lsFATAL, TransactionEngine) << - mNodes.getJson (0); + mNodes->getJson (0); didApply = false; terResult = tefINTERNAL; } @@ -212,9 +167,10 @@ TransactionEngine::applyTransaction ( // Transaction succeeded fully or (retries are not allowed and the // transaction could claim a fee) Serializer m; - mNodes.calcRawMeta (m, terResult, mTxnSeq++); + mNodes->calcRawMeta (m, terResult, mTxnSeq++); - txnWrite (); + assert(mLedger == mNodes->getLedger()); + mNodes->apply(); Serializer s; txn.add (s); @@ -253,7 +209,7 @@ TransactionEngine::applyTransaction ( } } - mNodes.clear (); + mNodes = boost::none; if (!(params & tapOPEN_LEDGER) && isTemMalformed (terResult)) { diff --git a/src/ripple/protocol/Indexes.h b/src/ripple/protocol/Indexes.h index cb962f68b1..19d6f26a8a 100644 --- a/src/ripple/protocol/Indexes.h +++ b/src/ripple/protocol/Indexes.h @@ -21,11 +21,13 @@ #define RIPPLE_PROTOCOL_INDEXES_H_INCLUDED #include +#include #include #include #include #include #include +#include namespace ripple { @@ -89,6 +91,137 @@ getRippleStateIndex (Account const& a, Issue const& issue); uint256 getSignerListIndex (Account const& account); + +//------------------------------------------------------------------------------ + +/** A pair of SHAMap key and LedgerEntryType. + + A Keylet identifies both a key in the state map + and its ledger entry type. +*/ +struct Keylet +{ + LedgerEntryType type; + uint256 key; + + Keylet (LedgerEntryType type_, + uint256 const& key_) + : type(type_) + , key(key_) + { + } +}; + +/** Keylet computation funclets. */ +namespace keylet { + +/** Account root */ +struct account_t +{ + Keylet operator()(Account const& id) const; + + // DEPRECATED + Keylet operator()(RippleAddress const& ra) const; +}; +static account_t const account {}; + +/** OWner directory */ +struct owndir_t +{ + Keylet operator()(Account const& id) const; +}; +static owndir_t const ownerDir {}; + +/** Skip list */ +struct skip_t +{ + Keylet operator()() const; + + Keylet operator()(LedgerIndex ledger) const; +}; +static skip_t const skip {}; + +/** The amendment table */ +struct amendments_t +{ + Keylet operator()() const; +}; +static amendments_t const amendments {}; + +/** The ledger fees */ +struct fee_t +{ + Keylet operator()() const; +}; +static fee_t const fee {}; + +/** The beginning of an order book */ +struct book_t +{ + Keylet operator()(Book const& b) const; +}; +static book_t const book {}; + +/** An offer from an account */ +struct offer_t +{ + Keylet operator()(Account const& id, + std::uint32_t seq) const; +}; +static offer_t const offer {}; + +/** An item in a directory */ +struct item_t +{ + Keylet operator()(Keylet const& k, + std::uint64_t index, + LedgerEntryType type) const; +}; +static item_t const item {}; + +/** The directory for a specific quality */ +struct quality_t +{ + Keylet operator()(Keylet const& k, + std::uint64_t q) const; +}; +static quality_t const quality {}; + +/** The directry for the next lower quality */ +struct next_t +{ + Keylet operator()(Keylet const& k) const; +}; +static next_t const next {}; + +/** A ticket belonging to an account */ +struct ticket_t +{ + Keylet operator()(Account const& id, + std::uint32_t seq) const; +}; +static ticket_t const ticket {}; + +/** A trust line */ +struct trust_t +{ + Keylet operator()(Account const& id0, + Account const& id1, Currency const& currency) const; + + Keylet operator()(Account const& id, + Issue const& issue) const; +}; +static trust_t const trust {}; + +/** A SignerList */ +struct signers_t +{ + Keylet operator()(Account const& id) const; +}; +static signers_t const signers {}; + +} // keylet + } #endif diff --git a/src/ripple/protocol/STLedgerEntry.h b/src/ripple/protocol/STLedgerEntry.h index 707efed584..a9cc604d96 100644 --- a/src/ripple/protocol/STLedgerEntry.h +++ b/src/ripple/protocol/STLedgerEntry.h @@ -20,7 +20,7 @@ #ifndef RIPPLE_PROTOCOL_STLEDGERENTRY_H_INCLUDED #define RIPPLE_PROTOCOL_STLEDGERENTRY_H_INCLUDED -#include +#include #include namespace ripple { @@ -35,10 +35,21 @@ public: using pointer = std::shared_ptr; using ref = const std::shared_ptr&; -public: + /** Create an empty object with the given key and type. */ + explicit + STLedgerEntry (Keylet const& k); + + STLedgerEntry (LedgerEntryType type, + uint256 const& key) + : STLedgerEntry(Keylet(type, key)) + { + } + STLedgerEntry (const Serializer & s, uint256 const& index); + STLedgerEntry (SerialIter & sit, uint256 const& index); - STLedgerEntry (LedgerEntryType type, uint256 const& index); + + STLedgerEntry (const STObject & object, uint256 const& index); STBase* @@ -57,69 +68,81 @@ public: { return STI_LEDGERENTRY; } + std::string getFullText () const override; + std::string getText () const override; + Json::Value getJson (int options) const override; /** Returns the 'key' (or 'index') of this item. The key identifies this entry's position in the SHAMap associative container. */ + uint256 const& + key() const + { + return key_; + } + + // DEPRECATED uint256 const& getIndex () const { - return mIndex; - } - void setIndex (uint256 const& i) - { - mIndex = i; + return key_; } void setImmutable () { mMutable = false; } + bool isMutable () { return mMutable; } - STLedgerEntry::pointer getMutable () const; LedgerEntryType getType () const { - return mType; + return type_; } + std::uint16_t getVersion () const { return getFieldU16 (sfLedgerEntryType); } - LedgerFormats::Item const* getFormat () - { - return mFormat; - } - + bool isThreadedType() const; // is this a ledger entry that can be threaded + bool isThreaded () const; // is this ledger entry actually threaded + bool hasOneOwner () const; // This node has one other node that owns it + bool hasTwoOwners () const; // This node has two nodes that own it (like ripple balance) + RippleAddress getOwner () const; + RippleAddress getFirstOwner () const; + RippleAddress getSecondOwner () const; + uint256 getThreadedTransaction () const; + std::uint32_t getThreadedLedger () const; + bool thread (uint256 const& txID, std::uint32_t ledgerSeq, uint256 & prevTxID, std::uint32_t & prevLedgerID); private: - /** Make STObject comply with the template for this SLE type + /* Make STObject comply with the template for this SLE type Can throw */ void setSLEType (); private: - uint256 mIndex; - LedgerEntryType mType; + uint256 key_; + LedgerEntryType type_; LedgerFormats::Item const* mFormat; - bool mMutable; + bool mMutable; }; using SLE = STLedgerEntry; diff --git a/src/ripple/protocol/impl/Indexes.cpp b/src/ripple/protocol/impl/Indexes.cpp index 83643a30dc..ef2acbbd48 100644 --- a/src/ripple/protocol/impl/Indexes.cpp +++ b/src/ripple/protocol/impl/Indexes.cpp @@ -21,6 +21,7 @@ #include #include #include +#include namespace ripple { @@ -192,4 +193,118 @@ getSignerListIndex (Account const& account) account); } +//------------------------------------------------------------------------------ + +namespace keylet { + +Keylet account_t::operator()( + Account const& id) const +{ + return { ltACCOUNT_ROOT, + getAccountRootIndex(id) }; +} + +Keylet account_t::operator()( + RippleAddress const& ra) const +{ + return { ltACCOUNT_ROOT, + getAccountRootIndex(ra.getAccountID()) }; +} + +Keylet owndir_t::operator()( + Account const& id) const +{ + return { ltDIR_NODE, + getOwnerDirIndex(id) }; +} + +Keylet skip_t::operator()() const +{ + return { ltLEDGER_HASHES, + getLedgerHashIndex() }; +} + +Keylet skip_t::operator()(LedgerIndex ledger) const +{ + return { ltLEDGER_HASHES, + getLedgerHashIndex(ledger) }; +} + +Keylet amendments_t::operator()() const +{ + return { ltAMENDMENTS, + getLedgerAmendmentIndex() }; +} + +Keylet fee_t::operator()() const +{ + return { ltFEE_SETTINGS, + getLedgerFeeIndex() }; +} + +Keylet book_t::operator()(Book const& b) const +{ + return { ltDIR_NODE, + getBookBase(b) }; +} + +Keylet offer_t::operator()(Account const& id, + std::uint32_t seq) const +{ + return { ltOFFER, + getOfferIndex(id, seq) }; +} + +Keylet item_t::operator()(Keylet const& k, + std::uint64_t index, + LedgerEntryType type) const +{ + return { type, + getDirNodeIndex(k.key, index) }; +} + +Keylet quality_t::operator()(Keylet const& k, + std::uint64_t q) const +{ + assert(k.type == ltDIR_NODE); + return { ltDIR_NODE, + getQualityIndex(k.key, q) }; +} + +Keylet next_t::operator()(Keylet const& k) const +{ + assert(k.type == ltDIR_NODE); + return { ltDIR_NODE, + getQualityNext(k.key) }; +} + +Keylet ticket_t::operator()(Account const& id, + std::uint32_t seq) const +{ + return { ltTICKET, + getTicketIndex(id, seq) }; +} + +Keylet trust_t::operator()(Account const& id0, + Account const& id1, Currency const& currency) const +{ + return { ltRIPPLE_STATE, + getRippleStateIndex(id0, id1, currency) }; +} + +Keylet trust_t::operator()(Account const& id, + Issue const& issue) const +{ + return { ltRIPPLE_STATE, + getRippleStateIndex(id, issue) }; +} + +Keylet signers_t::operator()(Account const& id) const +{ + return { ltSIGNER_LIST, + getSignerListIndex(id) }; +} + +} // keylet + } // ripple diff --git a/src/ripple/protocol/impl/STLedgerEntry.cpp b/src/ripple/protocol/impl/STLedgerEntry.cpp index 987e07519c..cf2e864e36 100644 --- a/src/ripple/protocol/impl/STLedgerEntry.cpp +++ b/src/ripple/protocol/impl/STLedgerEntry.cpp @@ -28,9 +28,24 @@ namespace ripple { +STLedgerEntry::STLedgerEntry (Keylet const& k) + : STObject(sfLedgerEntry) + , key_ (k.key) + , type_ (k.type) + , mMutable (true) +{ + mFormat = + LedgerFormats::getInstance().findByType (type_); + if (mFormat == nullptr) + throw std::runtime_error ("invalid ledger entry type"); + set (mFormat->elements); + setFieldU16 (sfLedgerEntryType, + static_cast (mFormat->getType ())); +} + STLedgerEntry::STLedgerEntry ( SerialIter& sit, uint256 const& index) - : STObject (sfLedgerEntry), mIndex (index), mMutable (true) + : STObject (sfLedgerEntry), key_ (index), mMutable (true) { set (sit); setSLEType (); @@ -38,7 +53,7 @@ STLedgerEntry::STLedgerEntry ( STLedgerEntry::STLedgerEntry ( const Serializer& s, uint256 const& index) - : STObject (sfLedgerEntry), mIndex (index), mMutable (true) + : STObject (sfLedgerEntry), key_ (index), mMutable (true) { SerialIter sit (s.slice()); set (sit); @@ -47,7 +62,7 @@ STLedgerEntry::STLedgerEntry ( STLedgerEntry::STLedgerEntry ( const STObject & object, uint256 const& index) - : STObject (object), mIndex(index), mMutable (true) + : STObject (object), key_(index), mMutable (true) { setSLEType (); } @@ -60,7 +75,7 @@ void STLedgerEntry::setSLEType () if (mFormat == nullptr) throw std::runtime_error ("invalid ledger entry type"); - mType = mFormat->getType (); + type_ = mFormat->getType (); if (!setType (mFormat->elements)) { WriteLog (lsWARNING, SerializedLedger) @@ -70,30 +85,10 @@ void STLedgerEntry::setSLEType () } } -STLedgerEntry::STLedgerEntry (LedgerEntryType type, uint256 const& index) : - STObject (sfLedgerEntry), mIndex (index), mType (type), mMutable (true) -{ - mFormat = LedgerFormats::getInstance().findByType (type); - - if (mFormat == nullptr) - throw std::runtime_error ("invalid ledger entry type"); - - set (mFormat->elements); - setFieldU16 (sfLedgerEntryType, - static_cast (mFormat->getType ())); -} - -STLedgerEntry::pointer STLedgerEntry::getMutable () const -{ - STLedgerEntry::pointer ret = std::make_shared (std::cref (*this)); - ret->mMutable = true; - return ret; -} - std::string STLedgerEntry::getFullText () const { std::string ret = "\""; - ret += to_string (mIndex); + ret += to_string (key_); ret += "\" = { "; ret += mFormat->getName (); ret += ", "; @@ -105,7 +100,7 @@ std::string STLedgerEntry::getFullText () const std::string STLedgerEntry::getText () const { return str (boost::format ("{ %s, %s }") - % to_string (mIndex) + % to_string (key_) % STObject::getText ()); } @@ -113,7 +108,7 @@ Json::Value STLedgerEntry::getJson (int options) const { Json::Value ret (STObject::getJson (options)); - ret[jss::index] = to_string (mIndex); + ret[jss::index] = to_string (key_); return ret; } @@ -130,12 +125,12 @@ bool STLedgerEntry::isThreaded () const bool STLedgerEntry::hasOneOwner () const { - return (mType != ltACCOUNT_ROOT) && (getFieldIndex (sfAccount) != -1); + return (type_ != ltACCOUNT_ROOT) && (getFieldIndex (sfAccount) != -1); } bool STLedgerEntry::hasTwoOwners () const { - return mType == ltRIPPLE_STATE; + return type_ == ltRIPPLE_STATE; } RippleAddress STLedgerEntry::getOwner () const diff --git a/src/ripple/rpc/handlers/RipplePathFind.cpp b/src/ripple/rpc/handlers/RipplePathFind.cpp index 7c526f4899..0f015c08cd 100644 --- a/src/ripple/rpc/handlers/RipplePathFind.cpp +++ b/src/ripple/rpc/handlers/RipplePathFind.cpp @@ -306,7 +306,7 @@ ripplePathFind(RippleLineCache::pointer const& cache, << "Trying with an extra path element"; spsComputed.push_back(fullLiquidityPath); - lesSandbox.clear(); + reconstruct(lesSandbox, lpLedger, tapNONE); rc = path::RippleCalc::rippleCalculate( lesSandbox, saMaxAmount, // --> Amount to send is unlimited