diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index 40702fdd43..4383cbee6b 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -1049,34 +1049,6 @@ bool pendSaveValidated ( return true; } -void -ownerDirDescriber (SLE::ref sle, bool, AccountID const& owner) -{ - sle->setAccountID (sfOwner, owner); -} - -void -qualityDirDescriber ( - SLE::ref sle, bool isNew, - Currency const& uTakerPaysCurrency, AccountID const& uTakerPaysIssuer, - Currency const& uTakerGetsCurrency, AccountID const& uTakerGetsIssuer, - const std::uint64_t& uRate, - Application& app) -{ - sle->setFieldH160 (sfTakerPaysCurrency, uTakerPaysCurrency); - sle->setFieldH160 (sfTakerPaysIssuer, uTakerPaysIssuer); - sle->setFieldH160 (sfTakerGetsCurrency, uTakerGetsCurrency); - sle->setFieldH160 (sfTakerGetsIssuer, uTakerGetsIssuer); - sle->setFieldU64 (sfExchangeRate, uRate); - if (isNew) - { - // VFALCO NO! This shouldn't be done here! - app.getOrderBookDB().addOrderBook( - {{uTakerPaysCurrency, uTakerPaysIssuer}, - {uTakerGetsCurrency, uTakerGetsIssuer}}); - } -} - void Ledger::make_v2() { diff --git a/src/ripple/app/ledger/Ledger.h b/src/ripple/app/ledger/Ledger.h index 17e6e20726..b44d0619c8 100644 --- a/src/ripple/app/ledger/Ledger.h +++ b/src/ripple/app/ledger/Ledger.h @@ -404,19 +404,6 @@ cachedRead (ReadView const& ledger, uint256 const& key, return ledger.read(keylet::unchecked(key)); } -//------------------------------------------------------------------------------ - -void -ownerDirDescriber (SLE::ref, bool, AccountID const& owner); - -// VFALCO NOTE This is referenced from only one place -void -qualityDirDescriber ( - SLE::ref, bool, - Currency const& uTakerPaysCurrency, AccountID const& uTakerPaysIssuer, - Currency const& uTakerGetsCurrency, AccountID const& uTakerGetsIssuer, - const std::uint64_t & uRate, Application& app); - } // ripple #endif diff --git a/src/ripple/app/tx/impl/CreateOffer.cpp b/src/ripple/app/tx/impl/CreateOffer.cpp index f59ff7638c..29ab6d6e32 100644 --- a/src/ripple/app/tx/impl/CreateOffer.cpp +++ b/src/ripple/app/tx/impl/CreateOffer.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -666,10 +667,6 @@ CreateOffer::applyGuts (ApplyView& view, ApplyView& view_cancel) auto saTakerPays = ctx_.tx[sfTakerPays]; auto saTakerGets = ctx_.tx[sfTakerGets]; - auto const& uPaysIssuerID = saTakerPays.getIssuer (); - - auto const& uGetsIssuerID = saTakerGets.getIssuer (); - auto const cancelSequence = ctx_.tx[~sfOfferSequence]; // FIXME understand why we use SequenceNext instead of current transaction @@ -720,8 +717,7 @@ CreateOffer::applyGuts (ApplyView& view, ApplyView& view_cancel) return{ tesSUCCESS, true }; } - bool const bOpenLedger = - ctx_.view().open(); + bool const bOpenLedger = ctx_.view().open(); bool crossed = false; if (result == tesSUCCESS) @@ -854,15 +850,11 @@ CreateOffer::applyGuts (ApplyView& view, ApplyView& view_cancel) auto const offer_index = getOfferIndex (account_, uSequence); std::uint64_t uOwnerNode; - std::uint64_t uBookNode; - uint256 uDirectory; // Add offer to owner's directory. - result = dirAdd(view, uOwnerNode, - getOwnerDirIndex (account_), offer_index, - std::bind ( - &ownerDirDescriber, std::placeholders::_1, - std::placeholders::_2, account_), viewJ); + std::tie(result, std::ignore) = dirAdd(view, uOwnerNode, + keylet::ownerDir (account_), offer_index, + describeOwnerDir (account_), viewJ); if (result == tesSUCCESS) { @@ -873,39 +865,49 @@ CreateOffer::applyGuts (ApplyView& view, ApplyView& view_cancel) "adding to book: " << to_string (saTakerPays.issue ()) << " : " << to_string (saTakerGets.issue ()); - uint256 const book_base (getBookBase ( - { saTakerPays.issue (), saTakerGets.issue () })); + Book const book { saTakerPays.issue(), saTakerGets.issue() }; + std::uint64_t uBookNode; + bool isNewBook; - // We use the original rate to place the offer. - uDirectory = getQualityIndex (book_base, uRate); + // Add offer to order book, using the original rate + // before any crossing occured. + auto dir = keylet::quality (keylet::book (book), uRate); - // Add offer to order book. - result = dirAdd (view, uBookNode, uDirectory, offer_index, - std::bind ( - &qualityDirDescriber, std::placeholders::_1, - std::placeholders::_2, saTakerPays.getCurrency (), - uPaysIssuerID, saTakerGets.getCurrency (), - uGetsIssuerID, uRate, std::ref(ctx_.app)), - viewJ); - } + std::tie(result, isNewBook) = dirAdd (view, uBookNode, + dir, offer_index, [&](SLE::ref sle) + { + sle->setFieldH160 (sfTakerPaysCurrency, + saTakerPays.issue().currency); + sle->setFieldH160 (sfTakerPaysIssuer, + saTakerPays.issue().account); + sle->setFieldH160 (sfTakerGetsCurrency, + saTakerGets.issue().currency); + sle->setFieldH160 (sfTakerGetsIssuer, + saTakerGets.issue().account); + sle->setFieldU64 (sfExchangeRate, uRate); + }, viewJ); - if (result == tesSUCCESS) - { - auto sleOffer = std::make_shared(ltOFFER, offer_index); - sleOffer->setAccountID (sfAccount, account_); - sleOffer->setFieldU32 (sfSequence, uSequence); - sleOffer->setFieldH256 (sfBookDirectory, uDirectory); - sleOffer->setFieldAmount (sfTakerPays, saTakerPays); - sleOffer->setFieldAmount (sfTakerGets, saTakerGets); - sleOffer->setFieldU64 (sfOwnerNode, uOwnerNode); - sleOffer->setFieldU64 (sfBookNode, uBookNode); - if (expiration) - sleOffer->setFieldU32 (sfExpiration, *expiration); - if (bPassive) - sleOffer->setFlag (lsfPassive); - if (bSell) - sleOffer->setFlag (lsfSell); - view.insert(sleOffer); + if (result == tesSUCCESS) + { + auto sleOffer = std::make_shared(ltOFFER, offer_index); + sleOffer->setAccountID (sfAccount, account_); + sleOffer->setFieldU32 (sfSequence, uSequence); + sleOffer->setFieldH256 (sfBookDirectory, dir.key); + sleOffer->setFieldAmount (sfTakerPays, saTakerPays); + sleOffer->setFieldAmount (sfTakerGets, saTakerGets); + sleOffer->setFieldU64 (sfOwnerNode, uOwnerNode); + sleOffer->setFieldU64 (sfBookNode, uBookNode); + if (expiration) + sleOffer->setFieldU32 (sfExpiration, *expiration); + if (bPassive) + sleOffer->setFlag (lsfPassive); + if (bSell) + sleOffer->setFlag (lsfSell); + view.insert(sleOffer); + + if (isNewBook) + ctx_.app.getOrderBookDB().addOrderBook(book); + } } if (result != tesSUCCESS) diff --git a/src/ripple/app/tx/impl/CreateTicket.cpp b/src/ripple/app/tx/impl/CreateTicket.cpp index 6120a37619..118b5d7404 100644 --- a/src/ripple/app/tx/impl/CreateTicket.cpp +++ b/src/ripple/app/tx/impl/CreateTicket.cpp @@ -102,32 +102,25 @@ CreateTicket::doApply () std::uint64_t hint; - auto describer = [&](SLE::pointer p, bool b) - { - ownerDirDescriber(p, b, account_); - }; - auto viewJ = ctx_.app.journal ("View"); - TER result = dirAdd(view(), - hint, - getOwnerDirIndex (account_), - sleTicket->getIndex (), - describer, - viewJ); + + auto result = dirAdd(view(), hint, keylet::ownerDir (account_), + sleTicket->getIndex (), describeOwnerDir (account_), viewJ); JLOG(j_.trace()) << "Creating ticket " << to_string (sleTicket->getIndex ()) << - ": " << transHuman (result); + ": " << transHuman (result.first); - if (result != tesSUCCESS) - return result; + if (result.first == tesSUCCESS) + { + sleTicket->setFieldU64(sfOwnerNode, hint); - sleTicket->setFieldU64(sfOwnerNode, hint); + // If we succeeded, the new entry counts agains the + // creator's reserve. + adjustOwnerCount(view(), sle, 1, viewJ); + } - // If we succeeded, the new entry counts agains the creator's reserve. - adjustOwnerCount(view(), sle, 1, viewJ); - - return result; + return result.first; } } diff --git a/src/ripple/app/tx/impl/SetSignerList.cpp b/src/ripple/app/tx/impl/SetSignerList.cpp index 326f5d629f..9d17d51125 100644 --- a/src/ripple/app/tx/impl/SetSignerList.cpp +++ b/src/ripple/app/tx/impl/SetSignerList.cpp @@ -238,21 +238,23 @@ SetSignerList::replaceSignerList () auto viewJ = ctx_.app.journal ("View"); // Add the signer list to the account's directory. std::uint64_t hint; - TER result = dirAdd(ctx_.view (), hint, ownerDirKeylet.key, + + auto result = dirAdd(ctx_.view (), hint, ownerDirKeylet, signerListKeylet.key, describeOwnerDir (account_), viewJ); JLOG(j_.trace()) << "Create signer list for account " << - toBase58(account_) << ": " << transHuman (result); + toBase58(account_) << ": " << transHuman (result.first); - if (result != tesSUCCESS) - return result; + if (result.first == tesSUCCESS) + { + signerList->setFieldU64 (sfOwnerNode, hint); - signerList->setFieldU64 (sfOwnerNode, hint); + // If we succeeded, the new entry counts against the + // creator's reserve. + adjustOwnerCount(view(), sle, addedOwnerCount, viewJ); + } - // If we succeeded, the new entry counts against the creator's reserve. - adjustOwnerCount(view(), sle, addedOwnerCount, viewJ); - - return result; + return result.first; } TER diff --git a/src/ripple/app/tx/impl/SusPay.cpp b/src/ripple/app/tx/impl/SusPay.cpp index b4d63086d2..8f8a198032 100644 --- a/src/ripple/app/tx/impl/SusPay.cpp +++ b/src/ripple/app/tx/impl/SusPay.cpp @@ -235,11 +235,11 @@ SusPayCreate::doApply() // Add SusPay to owner directory { uint64_t page; - TER ter = dirAdd(ctx_.view(), page, - keylet::ownerDir(account).key, - slep->key(), describeOwnerDir(account), ctx_.app.journal ("View")); - if (! isTesSuccess(ter)) - return ter; + auto result = dirAdd(ctx_.view(), page, + keylet::ownerDir(account), slep->key(), + describeOwnerDir(account), ctx_.app.journal ("View")); + if (! isTesSuccess(result.first)) + return result.first; (*slep)[sfOwnerNode] = page; } diff --git a/src/ripple/ledger/View.h b/src/ripple/ledger/View.h index ac0d4a2ce1..16b45317bd 100644 --- a/src/ripple/ledger/View.h +++ b/src/ripple/ledger/View.h @@ -215,7 +215,7 @@ dirNext (ApplyView& view, uint256& uEntryIndex, // <-- The entry, if available. Otherwise, zero. beast::Journal j); -std::function +std::function describeOwnerDir(AccountID const& account); // <-- uNodeDir: For deletion, present to make dirDelete efficient. @@ -223,12 +223,24 @@ describeOwnerDir(AccountID const& account); // --> uLedgerIndex: Value to add to directory. // Only append. This allow for things that watch append only structure to just monitor from the last node on ward. // Within a node with no deletions order of elements is sequential. Otherwise, order of elements is random. -TER + +/** Add an entry to directory, creating the directory if necessary + + @param uNodeDir node of entry - makes deletion efficient + @param uRootIndex The index of the base of the directory. + Nodes are based off of this. + @param uLedgerIndex Value to add to directory. + + @return a pair containing a code indicating success or + failure, and if successful, a boolean indicating + whether the directory was just created. +*/ +std::pair dirAdd (ApplyView& view, std::uint64_t& uNodeDir, // Node of entry. - uint256 const& uRootIndex, + Keylet const& uRootIndex, uint256 const& uLedgerIndex, - std::function fDescriber, + std::function fDescriber, beast::Journal j); TER diff --git a/src/ripple/ledger/impl/View.cpp b/src/ripple/ledger/impl/View.cpp index d56faf4864..0739a8aa7e 100644 --- a/src/ripple/ledger/impl/View.cpp +++ b/src/ripple/ledger/impl/View.cpp @@ -692,107 +692,114 @@ dirNext (ApplyView& view, return true; } -std::function +std::function describeOwnerDir(AccountID const& account) { - return [account](std::shared_ptr const& sle, bool) + return [&account](std::shared_ptr const& sle) { (*sle)[sfOwner] = account; }; } -TER +std::pair dirAdd (ApplyView& view, std::uint64_t& uNodeDir, - uint256 const& uRootIndex, // VFALCO Should be Keylet + Keylet const& dir, uint256 const& uLedgerIndex, - std::function fDescriber, + std::function fDescriber, beast::Journal j) { JLOG (j.trace()) << "dirAdd:" << - " uRootIndex=" << to_string (uRootIndex) << + " dir=" << to_string (dir.key) << " uLedgerIndex=" << to_string (uLedgerIndex); - SLE::pointer sleNode; - STVector256 svIndexes; - auto const k = keylet::page(uRootIndex); - auto sleRoot = view.peek(k); + auto sleRoot = view.peek(dir); if (! sleRoot) { // No root, make it. - sleRoot = std::make_shared(k); - sleRoot->setFieldH256 (sfRootIndex, uRootIndex); + sleRoot = std::make_shared(dir); + sleRoot->setFieldH256 (sfRootIndex, dir.key); view.insert (sleRoot); - fDescriber (sleRoot, true); - sleNode = sleRoot; - uNodeDir = 0; + fDescriber (sleRoot); + + STVector256 v; + v.push_back (uLedgerIndex); + sleRoot->setFieldV256 (sfIndexes, v); + + JLOG (j.trace()) << + "dirAdd: created root " << to_string (dir.key) << + " for entry " << to_string (uLedgerIndex); + + uNodeDir = 0; + + return { tesSUCCESS, true }; + } + + SLE::pointer sleNode; + STVector256 svIndexes; + + uNodeDir = sleRoot->getFieldU64 (sfIndexPrevious); // Get index to last directory node. + + if (uNodeDir) + { + // Try adding to last node. + sleNode = view.peek (keylet::page(dir, uNodeDir)); + assert (sleNode); } else { - uNodeDir = sleRoot->getFieldU64 (sfIndexPrevious); // Get index to last directory node. + // Try adding to root. Didn't have a previous set to the last node. + sleNode = sleRoot; + } - if (uNodeDir) - { - // Try adding to last node. - sleNode = view.peek (keylet::page(uRootIndex, uNodeDir)); + svIndexes = sleNode->getFieldV256 (sfIndexes); - assert (sleNode); - } - else - { - // Try adding to root. Didn't have a previous set to the last node. - sleNode = sleRoot; - } + if (DIR_NODE_MAX != svIndexes.size ()) + { + // Add to current node. + view.update(sleNode); + } + // Add to new node. + else if (!++uNodeDir) + { + return { tecDIR_FULL, false }; + } + else + { + // Have old last point to new node + sleNode->setFieldU64 (sfIndexNext, uNodeDir); + view.update(sleNode); - svIndexes = sleNode->getFieldV256 (sfIndexes); + // Have root point to new node. + sleRoot->setFieldU64 (sfIndexPrevious, uNodeDir); + view.update (sleRoot); - if (DIR_NODE_MAX != svIndexes.size ()) - { - // Add to current node. - view.update(sleNode); - } - // Add to new node. - else if (!++uNodeDir) - { - return tecDIR_FULL; - } - else - { - // Have old last point to new node - sleNode->setFieldU64 (sfIndexNext, uNodeDir); - view.update(sleNode); + // Create the new node. + sleNode = std::make_shared( + keylet::page(dir, uNodeDir)); + sleNode->setFieldH256 (sfRootIndex, dir.key); + view.insert (sleNode); - // Have root point to new node. - sleRoot->setFieldU64 (sfIndexPrevious, uNodeDir); - view.update (sleRoot); + if (uNodeDir != 1) + sleNode->setFieldU64 (sfIndexPrevious, uNodeDir - 1); - // Create the new node. - sleNode = std::make_shared( - keylet::page(uRootIndex, uNodeDir)); - sleNode->setFieldH256 (sfRootIndex, uRootIndex); - view.insert (sleNode); + fDescriber (sleNode); - if (uNodeDir != 1) - sleNode->setFieldU64 (sfIndexPrevious, uNodeDir - 1); - - fDescriber (sleNode, false); - - svIndexes = STVector256 (); - } + svIndexes = STVector256 (); } svIndexes.push_back (uLedgerIndex); // Append entry. sleNode->setFieldV256 (sfIndexes, svIndexes); // Save entry. JLOG (j.trace()) << - "dirAdd: creating: root: " << to_string (uRootIndex); + "dirAdd: creating: root: " << to_string (dir.key); JLOG (j.trace()) << "dirAdd: appending: Entry: " << to_string (uLedgerIndex); JLOG (j.trace()) << "dirAdd: appending: Node: " << strHex (uNodeDir); - return tesSUCCESS; + return { tesSUCCESS, false }; } // Ledger must be in a state for this to work. @@ -1016,27 +1023,19 @@ trustCreate (ApplyView& view, std::uint64_t uLowNode; std::uint64_t uHighNode; - TER terResult = dirAdd (view, - uLowNode, - getOwnerDirIndex (uLowAccountID), + TER terResult; + + std::tie (terResult, std::ignore) = dirAdd (view, + uLowNode, keylet::ownerDir (uLowAccountID), sleRippleState->getIndex (), - [uLowAccountID](std::shared_ptr const& sle, bool) - { - sle->setAccountID (sfOwner, uLowAccountID); - }, - j); + describeOwnerDir (uLowAccountID), j); if (tesSUCCESS == terResult) { - terResult = dirAdd (view, - uHighNode, - getOwnerDirIndex (uHighAccountID), + std::tie (terResult, std::ignore) = dirAdd (view, + uHighNode, keylet::ownerDir (uHighAccountID), sleRippleState->getIndex (), - [uHighAccountID](std::shared_ptr const& sle, bool) - { - sle->setAccountID (sfOwner, uHighAccountID); - }, - j); + describeOwnerDir (uHighAccountID), j); } if (tesSUCCESS == terResult)