diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj index 6bda41cf5..8c8805f58 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj +++ b/Builds/VisualStudio2013/RippleD.vcxproj @@ -1397,10 +1397,6 @@ - - True - True - True True @@ -1425,8 +1421,6 @@ - - True True @@ -2287,8 +2281,6 @@ - - diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters index d014f8942..830934dd3 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters @@ -2136,9 +2136,6 @@ ripple\app\ledger\impl - - ripple\app\ledger\impl - ripple\app\ledger\impl @@ -2163,9 +2160,6 @@ ripple\app\ledger - - ripple\app\ledger - ripple\app\ledger @@ -2997,9 +2991,6 @@ ripple\ledger - - ripple\ledger - ripple\net diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index f8efc7049..69440639c 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -91,6 +91,8 @@ Ledger::Ledger (RippleAddress const& masterPublicKey, getApp().family(), deprecatedLogs().journal("SHAMap"))) , stateMap_ (std::make_shared (SHAMapType::STATE, getApp().family(), deprecatedLogs().journal("SHAMap"))) + // VFALCO Needs audit + , fees_(getFees(*this, getConfig())) { auto sle = makeGenesisAccount( calcAccountID(masterPublicKey), @@ -126,6 +128,8 @@ Ledger::Ledger (uint256 const& parentHash, deprecatedLogs().journal("SHAMap"))) , stateMap_ (std::make_shared (SHAMapType::STATE, accountHash, getApp().family(), deprecatedLogs().journal("SHAMap"))) + // VFALCO Needs audit + , fees_(getFees(*this, getConfig())) { updateHash (); loaded = true; @@ -164,6 +168,8 @@ Ledger::Ledger (Ledger const& ledger, , mImmutable (!isMutable) , txMap_ (ledger.txMap_->snapShot (isMutable)) , stateMap_ (ledger.stateMap_->snapShot (isMutable)) + // VFALCO Needs audit + , fees_(getFees(*this, getConfig())) { updateHash (); } @@ -180,6 +186,8 @@ Ledger::Ledger (bool /* dummy */, , txMap_ (std::make_shared (SHAMapType::TRANSACTION, getApp().family(), deprecatedLogs().journal("SHAMap"))) , stateMap_ (prevLedger.stateMap_->snapShot (true)) + // VFALCO Needs audit + , fees_(getFees(*this, getConfig())) { prevLedger.updateHash (); @@ -207,6 +215,7 @@ Ledger::Ledger (void const* data, { SerialIter sit (data, size); setRaw (sit, hasPrefix); + fees_ = getFees(*this, getConfig()); } Ledger::Ledger (std::uint32_t ledgerSeq, std::uint32_t closeTime) @@ -223,6 +232,8 @@ Ledger::Ledger (std::uint32_t ledgerSeq, std::uint32_t closeTime) , stateMap_ (std::make_shared ( SHAMapType::STATE, getApp().family(), deprecatedLogs().journal("SHAMap"))) + // VFALCO Needs audit + , fees_(getFees(*this, getConfig())) { } @@ -341,48 +352,6 @@ bool Ledger::addSLE (SLE const& sle) return stateMap_->addItem(item, false, false); } -bool -addTransaction (Ledger& ledger, - uint256 const& txID, const Serializer& txn) -{ - // low-level - just add to table - auto item = std::make_shared< - SHAMapItem const> (txID, txn.peekData ()); - - if (! ledger.txMap().addGiveItem (std::move(item), true, false)) - { - WriteLog (lsWARNING, Ledger) - << "Attempt to add transaction to ledger that already had it"; - return false; - } - - // VFALCO TODO We could touch only the txMap - ledger.touch(); - return true; -} - -bool addTransaction (Ledger& ledger, - uint256 const& txID, const Serializer& txn, const Serializer& md) -{ - // low-level - just add to table - Serializer s (txn.getDataLength () + md.getDataLength () + 16); - s.addVL (txn.peekData ()); - s.addVL (md.peekData ()); - auto item = std::make_shared< - SHAMapItem const> (txID, std::move(s)); - - if (! ledger.txMap().addGiveItem (std::move(item), true, true)) - { - WriteLog (lsFATAL, Ledger) - << "Attempt to add transaction+MD to ledger that already had it"; - return false; - } - - // VFALCO TODO We could touch only the txMap - ledger.touch(); - return true; -} - Transaction::pointer getTransaction (Ledger const& ledger, uint256 const& transID, TransactionMaster& cache) @@ -1000,6 +969,68 @@ Ledger::unchecked_replace( auto const ours = std::move(sle); } +bool +Ledger::txExists (uint256 const& key) const +{ + return txMap().hasItem (key); +} + +bool +Ledger::txInsert (uint256 const& key, + std::shared_ptr const& txn, + std::shared_ptr const& metaData) +{ + if (metaData) + { + // low-level - just add to table + Serializer s (txn->getDataLength () + metaData->getDataLength () + 16); + s.addVL (txn->peekData ()); + s.addVL (metaData->peekData ()); + auto item = std::make_shared< + SHAMapItem const> (key, std::move(s)); + + // VFALCO Should just terminate the app + // with a fatal error here. + + if (! txMap().addGiveItem (std::move(item), true, true)) + { + WriteLog (lsFATAL, Ledger) + << "Attempt to add transaction+MD to ledger that already had it"; + return false; + } + + auto const temp = std::move(*metaData); + } + else + { + // low-level - just add to table + auto item = std::make_shared< + SHAMapItem const> (key, txn->peekData ()); + + if (! txMap().addGiveItem (std::move(item), true, false)) + { + WriteLog (lsWARNING, Ledger) + << "Attempt to add transaction to ledger that already had it"; + return false; + } + } + + // VFALCO TODO We could touch only the txMap + touch(); + return true; +} + +std::vector +Ledger::txList() const +{ + std::vector list; + for (auto const& item : *txMap_) + { + list.push_back(item->key()); + } + return list; +} + std::shared_ptr Ledger::peek (Keylet const& k) const { @@ -1486,31 +1517,4 @@ getMetaHex (Ledger const& ledger, return true; } -static -Ledger const* -ledgerFromView(BasicView const* view) -{ - do - { - auto const ledger = - dynamic_cast(view); - if (ledger) - return ledger; - view = view->parent(); - } - while (view != nullptr); - return nullptr; -} - -// This hack traverses the View chain until -// it finds the underlying ledger then extracts -// the parent close time. -// -std::uint32_t -getParentCloseTimeNC (BasicView const& view) -{ - auto const& ledger = *ledgerFromView(&view); - return ledger.getParentCloseTimeNC(); -} - } // ripple diff --git a/src/ripple/app/ledger/Ledger.h b/src/ripple/app/ledger/Ledger.h index 212044d22..882abdf63 100644 --- a/src/ripple/app/ledger/Ledger.h +++ b/src/ripple/app/ledger/Ledger.h @@ -118,6 +118,24 @@ public: // //-------------------------------------------------------------------------- + Fees const& + fees() const override + { + return fees_; + } + + LedgerIndex + seq() const override + { + return seq_; + } + + std::uint32_t + time() const override + { + return mParentCloseTime; + } + bool exists (Keylet const& k) const override; @@ -137,12 +155,24 @@ public: void unchecked_replace (std::shared_ptr&& sle) override; - BasicView const* - parent() const override + void + destroyCoins (std::uint64_t feeDrops) override { - return nullptr; + mTotCoins -= feeDrops; } + bool + txExists (uint256 const& key) const override; + + bool + txInsert (uint256 const& key, + std::shared_ptr const& txn, std::shared_ptr< + Serializer const> const& metaData) override; + + std::vector + txList() const override; + //-------------------------------------------------------------------------- /** Hint that the contents have changed. @@ -231,11 +261,6 @@ public: return mTotCoins; } - void destroyCoins (std::uint64_t fee) - { - mTotCoins -= fee; - } - void setTotalCoins (std::uint64_t totCoins) { mTotCoins = totCoins; @@ -251,12 +276,6 @@ public: return mParentCloseTime; } - LedgerIndex - seq() const - { - return seq_; - } - // DEPRECATED std::uint32_t getLedgerSeq () const { @@ -450,6 +469,8 @@ private: // Protects fee variables std::mutex mutable mutex_; + Fees fees_; + // Ripple cost of the reference transaction std::uint64_t mutable mBaseFee = 0; @@ -531,20 +552,6 @@ injectSLE (Json::Value& jv, //------------------------------------------------------------------------------ -// VFALCO Should this take Slice? Should id be called key or hash? Or txhash? -bool addTransaction (Ledger& ledger, - uint256 const& id, Serializer const& txn); - -bool addTransaction (Ledger& ledger, - uint256 const& id, Serializer const& txn, Serializer const& metaData); - -inline -bool hasTransaction (Ledger const& ledger, - uint256 const& TransID) -{ - return ledger.txMap().hasItem (TransID); -} - // VFALCO NOTE This is called from only one place Transaction::pointer getTransaction (Ledger const& ledger, @@ -578,11 +585,6 @@ qualityDirDescriber ( Currency const& uTakerGetsCurrency, AccountID const& uTakerGetsIssuer, const std::uint64_t & uRate); -//------------------------------------------------------------------------------ - -std::uint32_t -getParentCloseTimeNC (BasicView const& view); - } // ripple #endif diff --git a/src/ripple/app/ledger/LedgerFees.h b/src/ripple/app/ledger/LedgerFees.h deleted file mode 100644 index be2aebc37..000000000 --- a/src/ripple/app/ledger/LedgerFees.h +++ /dev/null @@ -1,40 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef RIPPLE_APP_FEES_H_INCLUDED -#define RIPPLE_APP_FEES_H_INCLUDED - -#include -#include - -namespace ripple { - -// VFALCO Replace std::uint64_t with a real type, maybe Amount? -// Converts a fee in fee units to a fee in drops -std::uint64_t -scaleFeeBase (LoadFeeTrack& track, - Ledger const& ledger, std::uint64_t fee); - -std::uint64_t -scaleFeeLoad (LoadFeeTrack& track, - Ledger const& ledger, std::uint64_t fee, bool admin); - -} - -#endif diff --git a/src/ripple/app/ledger/MetaView.h b/src/ripple/app/ledger/MetaView.h index 2319e2f2f..f91518729 100644 --- a/src/ripple/app/ledger/MetaView.h +++ b/src/ripple/app/ledger/MetaView.h @@ -20,39 +20,21 @@ #ifndef RIPPLE_LEDGER_METAVIEW_H_INCLUDED #define RIPPLE_LEDGER_METAVIEW_H_INCLUDED -#include +#include +#include #include -#include +#include #include +#include #include #include #include +#include +#include #include namespace ripple { -// VFALCO Does this belong here? Is it correctly named? - -enum TransactionEngineParams -{ - tapNONE = 0x00, - - // Signature already checked - tapNO_CHECK_SIGN = 0x01, - - // Transaction is running against an open ledger - // true = failures are not forwarded, check transaction fee - // false = debit ledger for consumed funds - tapOPEN_LEDGER = 0x10, - - // This is not the transaction's last pass - // Transaction can be retried, soft failures allowed - tapRETRY = 0x20, - - // Transaction came from a privileged source - tapADMIN = 0x400, -}; - /** A MetaView can produce tx metadata and is attached to a parent. It's a view into a ledger used while a transaction is processing. @@ -78,36 +60,134 @@ private: using Mods = hash_map>; - using list_type = std::map; + // The SLEs and Serializers in here are + // shared between copy-constructed instances + using item_list = std::map; + using tx_list = hardened_hash_map< + uint256, std::pair, std::shared_ptr< + Serializer const>>>; - BasicView* parent_; - list_type items_; - TransactionMetaSet mSet; - TransactionEngineParams mParams = tapNONE; + // Note that this class needs to be + // somewhat light-weight copy constructible. + BasicView const* parent_; + ViewFlags flags_ = tapNONE; + LedgerIndex seq_; + std::uint32_t time_; // should be Clock::time_point + tx_list txs_; + item_list items_; + TransactionMetaSet meta_; + std::uint32_t destroyedCoins_ = 0; public: + MetaView() = delete; MetaView& operator= (MetaView const&) = delete; - MetaView (Ledger::ref ledger, - uint256 const& transactionID, - std::uint32_t ledgerID, - TransactionEngineParams params); + /** Create a shallow copy of a MetaView. - MetaView (BasicView& parent, - bool openLedger); + The SLEs and Serializers in the created copy + are shared with the other view. - // DEPRECATED - MetaView (Ledger::ref ledger, - TransactionEngineParams tep); + It is only safe to use the BasicView modification + functions. Using View modification functions will + break invariants. - MetaView (MetaView& parent); + The seq, time, and flags are copied from `other`. + + @note This is used to apply new transactions to + the open MetaView. + */ + // VFALCO Refactor to disallow at compile time, + // breaking invariants on a shallow copy. + // + MetaView (MetaView const& other) = default; + + /** Create a MetaView with a BasicView as its parent. + + Effects: + The sequence number and time are set + from the passed parameters. + + It is only safe to use the BasicView modification + functions. Using View modification functions will + break invariants. + + @note This is for converting a closed ledger + into an open ledger. + + @note A pointer is used to prevent confusion + with copy construction. + */ + // VFALCO Refactor to disallow at compile time, + // breaking invariants on a shallow copy. + // + MetaView (BasicView const* parent, + LedgerIndex seq, std::uint32_t time, + ViewFlags flags); + + /** Create a MetaView with a BasicView as its parent. + + Effects: + The sequence number and time are inherited + from the parent. + + The MetaSet is prepared to produce metadata + for a transaction with the specified key. + + @note This is for applying a particular transaction + and computing its metadata, or for applying + a transaction without extracting metadata. For + example, to calculate changes in a sandbox + and then throw the sandbox away. + + @note A pointer is used to prevent confusion + with copy construction. + */ + MetaView (BasicView const* parent, + ViewFlags flags, + boost::optional const& key = boost::none); + + /** Create a MetaView with a View as its parent. + + Effects: + The sequence number, time, and flags + are inherited from the parent. + + @note This is for stacking view for the purpose of + performing calculations or applying to an + underlying MetaView associated with a particular + transation. + + @note A pointer is used to prevent confusion + with copy construction. + */ + MetaView (View const* parent); //-------------------------------------------------------------------------- // - // View + // BasicView // //-------------------------------------------------------------------------- + Fees const& + fees() const override + { + return parent_->fees(); + } + + LedgerIndex + seq() const override + { + return seq_; + } + + std::uint32_t + time() const override + { + return time_; + } + bool exists (Keylet const& k) const override; @@ -130,13 +210,32 @@ public: unchecked_replace( std::shared_ptr&& sle) override; - BasicView const* - parent() const override + void + destroyCoins (std::uint64_t feeDrops) override; + + bool + txExists (uint256 const& key) const override; + + bool + txInsert (uint256 const& key, + std::shared_ptr const& txn, std::shared_ptr< + Serializer const> const& metaData) override; + + std::vector + txList() const override; + + //-------------------------------------------------------------------------- + // + // view + // + //-------------------------------------------------------------------------- + + ViewFlags + flags() const override { - return parent_; + return flags_; } - - //--------------------------------------------- std::shared_ptr peek (Keylet const& k) override; @@ -150,14 +249,19 @@ public: void update (std::shared_ptr const& sle) override; - bool - openLedger() const override; - //-------------------------------------------------------------------------- - /** Apply changes to the parent View */ + /** Apply changes to the parent View. + + `to` must contain contents identical to the parent + view passed upon construction, else undefined + behavior will result. + + After a call to apply(), the only valid operation that + may be performed on this is a call to the destructor. + */ void - apply(); + apply (BasicView& to); // For diagnostics Json::Value getJson (int) const; @@ -166,7 +270,7 @@ public: void setDeliveredAmount (STAmount const& amt) { - mSet.setDeliveredAmount (amt); + meta_.setDeliveredAmount (amt); } private: diff --git a/src/ripple/app/ledger/impl/LedgerConsensusImp.cpp b/src/ripple/app/ledger/impl/LedgerConsensusImp.cpp index b77204c80..76aa1694d 100644 --- a/src/ripple/app/ledger/impl/LedgerConsensusImp.cpp +++ b/src/ripple/app/ledger/impl/LedgerConsensusImp.cpp @@ -1375,7 +1375,7 @@ void LedgerConsensusImp::takeInitialPosition (Ledger& initialLedger) for (auto& it : mDisputes) { - it.second->setOurVote (hasTransaction (initialLedger, it.first)); + it.second->setOurVote (initialLedger.txExists(it.first)); } // if any peers have taken a contrary position, process disputes @@ -1722,22 +1722,22 @@ make_LedgerConsensus (ConsensusImp& consensus, int previousProposers, static int applyTransaction ( TransactionEngine& engine, - STTx::ref txn, + std::shared_ptr const& txn, bool openLedger, bool retryAssured) { // Returns false if the transaction has need not be retried. - TransactionEngineParams parms = openLedger ? tapOPEN_LEDGER : tapNONE; + ViewFlags parms = openLedger ? tapOPEN_LEDGER : tapNONE; if (retryAssured) { - parms = static_cast (parms | tapRETRY); + parms = static_cast (parms | tapRETRY); } if ((getApp().getHashRouter ().getFlags (txn->getTransactionID ()) & SF_SIGGOOD) == SF_SIGGOOD) { - parms = static_cast + parms = static_cast (parms | tapNO_CHECK_SIGN); } WriteLog (lsDEBUG, LedgerConsensus) << "TXN " @@ -1790,7 +1790,7 @@ void applyTransactions ( { for (auto const item : *set) { - if (hasTransaction (*checkLedger, item->getTag ())) + if (checkLedger->txExists (item->key())) continue; // The transaction isn't in the check ledger, try to apply it diff --git a/src/ripple/app/ledger/impl/LedgerFees.cpp b/src/ripple/app/ledger/impl/LedgerFees.cpp deleted file mode 100644 index 32da76eca..000000000 --- a/src/ripple/app/ledger/impl/LedgerFees.cpp +++ /dev/null @@ -1,42 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#include -#include - -namespace ripple { - -std::uint64_t -scaleFeeBase (LoadFeeTrack& track, - Ledger const& ledger, std::uint64_t fee) -{ - return track.scaleFeeBase (fee, - ledger.getBaseFee(), ledger.getReferenceFeeUnits()); -} - -std::uint64_t -scaleFeeLoad (LoadFeeTrack& track, - Ledger const& ledger, std::uint64_t fee, bool admin) -{ - return track.scaleFeeLoad (fee, - ledger.getBaseFee(), ledger.getReferenceFeeUnits(), - admin); -} - -} // ripple diff --git a/src/ripple/app/ledger/impl/LedgerMaster.cpp b/src/ripple/app/ledger/impl/LedgerMaster.cpp index 03e82b510..c894aaf8b 100644 --- a/src/ripple/app/ledger/impl/LedgerMaster.cpp +++ b/src/ripple/app/ledger/impl/LedgerMaster.cpp @@ -350,7 +350,9 @@ public: ScopedLockType sl (m_mutex); // Start with a mutable snapshot of the open ledger - TransactionEngine engine (mCurrentLedger.getMutable ()); + auto const ledger = + mCurrentLedger.getMutable(); + TransactionEngine engine (ledger); int recovers = 0; @@ -358,10 +360,10 @@ public: { try { - TransactionEngineParams tepFlags = tapOPEN_LEDGER; + ViewFlags tepFlags = tapOPEN_LEDGER; if (getApp().getHashRouter ().addSuppressionFlags (it.first.getTXID (), SF_SIGGOOD)) - tepFlags = static_cast (tepFlags | tapNO_CHECK_SIGN); + tepFlags = static_cast (tepFlags | tapNO_CHECK_SIGN); auto ret = engine.applyTransaction (*it.second, tepFlags); @@ -382,8 +384,8 @@ public: CondLog (recovers != 0, lsINFO, LedgerMaster) << "Recovered " << recovers << " held transactions"; // VFALCO TODO recreate the CanonicalTxSet object instead of resetting it - mHeldTransactions.reset (engine.getLedger()->getHash ()); - mCurrentLedger.set (engine.getLedger ()); + mHeldTransactions.reset (ledger->getHash ()); + mCurrentLedger.set (ledger); } LedgerIndex getBuildingLedger () diff --git a/src/ripple/app/ledger/impl/MetaView.cpp b/src/ripple/app/ledger/impl/MetaView.cpp index 0422df189..d72eeef81 100644 --- a/src/ripple/app/ledger/impl/MetaView.cpp +++ b/src/ripple/app/ledger/impl/MetaView.cpp @@ -42,34 +42,34 @@ namespace ripple { #define DIR_NODE_MAX 32 #endif -MetaView::MetaView(Ledger::ref ledger, - uint256 const& transactionID, - std::uint32_t ledgerID, - TransactionEngineParams params) - : parent_(&*ledger) - , mParams(params) -{ - mSet.init (transactionID, ledgerID); -} - -MetaView::MetaView (BasicView& parent, - bool openLedger) - : parent_ (&parent) - , mParams (openLedger - ? tapOPEN_LEDGER : tapNONE) +MetaView::MetaView (BasicView const* parent, + LedgerIndex seq, std::uint32_t time, + ViewFlags flags) + : parent_ (parent) + , flags_ (flags) + , seq_ (parent->seq()) + , time_ (parent->time()) { } -MetaView::MetaView (Ledger::ref ledger, - TransactionEngineParams tep) - : parent_(&*ledger) - , mParams (tep) +MetaView::MetaView (BasicView const* parent, + ViewFlags flags, boost::optional< + uint256> const& key) + : parent_ (parent) + , flags_ (flags) + , seq_ (parent->seq()) + , time_ (parent->time()) { + // VFALCO This needs to be refactored + if (key) + meta_.init (*key, seq_); } -MetaView::MetaView (MetaView& parent) - : parent_(&parent) - , mParams(parent.mParams) +MetaView::MetaView (View const* parent) + : parent_ (parent) + , flags_ (parent->flags()) + , seq_ (parent->seq()) + , time_ (parent->time()) { } @@ -98,7 +98,7 @@ MetaView::succ (uint256 const& key, boost::optional last) const { boost::optional next = key; - list_type::const_iterator iter; + item_list::const_iterator iter; // Find parent successor that is // not also deleted in our list do @@ -249,6 +249,47 @@ MetaView::unchecked_replace (std::shared_ptr&& sle) iter->second.second = std::move(sle); } +void +MetaView::destroyCoins (std::uint64_t feeDrops) +{ + destroyedCoins_ += feeDrops; +} + +bool +MetaView::txExists (uint256 const& key) const +{ + if (txs_.count(key) > 0) + return true; + return parent_->txExists(key); +} + +bool +MetaView::txInsert (uint256 const& key, + std::shared_ptr const& txn, + std::shared_ptr const& metaData) +{ + bool already = txs_.count(key); + if (! already) + already = parent_->txExists(key); + if (already) + return false; + txs_.emplace(std::piecewise_construct, + std::forward_as_tuple(key), + std::forward_as_tuple( + txn, metaData)); + return true; +} + +std::vector +MetaView::txList() const +{ + std::vector list; + list.reserve(txs_.size()); + for (auto const& e : txs_) + list.push_back(e.first); + return list; +} + std::shared_ptr MetaView::peek (Keylet const& k) { @@ -361,17 +402,11 @@ MetaView::update (std::shared_ptr const& sle) iter->second.first = taaMODIFY; } -bool -MetaView::openLedger() const -{ - return mParams & tapOPEN_LEDGER; -} - //------------------------------------------------------------------------------ -void MetaView::apply() +void MetaView::apply (BasicView& to) { - + assert(&to == parent_); // Write back the account states for (auto& item : items_) { @@ -382,7 +417,7 @@ void MetaView::apply() switch (item.second.first) { case taaCACHED: - assert(parent_->exists( + assert(to.exists( Keylet(sle->getType(), item.first))); break; @@ -390,28 +425,32 @@ void MetaView::apply() // VFALCO Is this logging necessary anymore? WriteLog (lsDEBUG, View) << "applyTransaction: taaCREATE: " << sle->getText (); - parent_->unchecked_insert(std::move(sle)); + to.unchecked_insert(std::move(sle)); break; case taaMODIFY: { WriteLog (lsDEBUG, View) << "applyTransaction: taaMODIFY: " << sle->getText (); - parent_->unchecked_replace(std::move(sle)); + to.unchecked_replace(std::move(sle)); break; } case taaDELETE: WriteLog (lsDEBUG, View) << "applyTransaction: taaDELETE: " << sle->getText (); - parent_->unchecked_erase(sle->key()); + to.unchecked_erase(sle->key()); break; } } - // Safety precaution since we moved the - // entries out, apply() cannot be called twice. - items_.clear(); + // Write the transactions + for (auto& tx : txs_) + to.txInsert(tx.first, + tx.second.first, + tx.second.second); + + to.destroyCoins(destroyedCoins_); } Json::Value MetaView::getJson (int) const @@ -482,7 +521,7 @@ Json::Value MetaView::getJson (int) const ret[jss::nodes] = nodes; - ret[jss::metaData] = mSet.getJson (0); + ret[jss::metaData] = meta_.getJson (0); return ret; } @@ -555,12 +594,12 @@ MetaView::threadTx( { uint256 prevTxID; std::uint32_t prevLgrID; - if (! to->thread(mSet.getTxID(), - mSet.getLgrSeq(), prevTxID, prevLgrID)) + if (! to->thread(meta_.getTxID(), + meta_.getLgrSeq(), prevTxID, prevLgrID)) return false; if (prevTxID.isZero () || TransactionMetaSet::thread( - mSet.getAffectedNode(to, + meta_.getAffectedNode(to, sfModifiedNode), prevTxID, prevLgrID)) return true; @@ -650,7 +689,7 @@ MetaView::calcRawMeta (Serializer& s, ? curNode->getFieldU16 (sfLedgerEntryType) : origNode->getFieldU16 (sfLedgerEntryType); - mSet.setAffectedNode (it.first, *type, nodeType); + meta_.setAffectedNode (it.first, *type, nodeType); if (type == &sfDeletedNode) { @@ -666,7 +705,7 @@ MetaView::calcRawMeta (Serializer& s, } if (!prevs.empty ()) - mSet.getAffectedNode (it.first).emplace_back (std::move(prevs)); + meta_.getAffectedNode (it.first).emplace_back (std::move(prevs)); STObject finals (sfFinalFields); for (auto const& obj : *curNode) @@ -677,7 +716,7 @@ MetaView::calcRawMeta (Serializer& s, } if (!finals.empty ()) - mSet.getAffectedNode (it.first).emplace_back (std::move(finals)); + meta_.getAffectedNode (it.first).emplace_back (std::move(finals)); } else if (type == &sfModifiedNode) { @@ -695,7 +734,7 @@ MetaView::calcRawMeta (Serializer& s, } if (!prevs.empty ()) - mSet.getAffectedNode (it.first).emplace_back (std::move(prevs)); + meta_.getAffectedNode (it.first).emplace_back (std::move(prevs)); STObject finals (sfFinalFields); for (auto const& obj : *curNode) @@ -706,7 +745,7 @@ MetaView::calcRawMeta (Serializer& s, } if (!finals.empty ()) - mSet.getAffectedNode (it.first).emplace_back (std::move(finals)); + meta_.getAffectedNode (it.first).emplace_back (std::move(finals)); } else if (type == &sfCreatedNode) // if created, thread to owner(s) { @@ -725,7 +764,7 @@ MetaView::calcRawMeta (Serializer& s, } if (!news.empty ()) - mSet.getAffectedNode (it.first).emplace_back (std::move(news)); + meta_.getAffectedNode (it.first).emplace_back (std::move(news)); } else assert (false); } @@ -734,8 +773,8 @@ MetaView::calcRawMeta (Serializer& s, for (auto& it : newMod) update (it.second); - mSet.addRaw (s, result, index); - WriteLog (lsTRACE, View) << "Metadata:" << mSet.getJson (0); + meta_.addRaw (s, result, index); + WriteLog (lsTRACE, View) << "Metadata:" << meta_.getJson (0); } } // ripple diff --git a/src/ripple/app/ledger/tests/MetaView_test.cpp b/src/ripple/app/ledger/tests/MetaView_test.cpp index 9b68caa5f..8810a77c7 100644 --- a/src/ripple/app/ledger/tests/MetaView_test.cpp +++ b/src/ripple/app/ledger/tests/MetaView_test.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include // namespace ripple { @@ -151,7 +152,7 @@ class MetaView_test using namespace jtx; Env env(*this); wipe(*env.ledger); - MetaView v(*env.ledger, false); + MetaView v(env.ledger.get(), tapNONE); succ(v, 0, boost::none); v.insert(sle(1)); expect(v.exists(k(1))); @@ -188,7 +189,7 @@ class MetaView_test v0.unchecked_insert(sle(4)); v0.unchecked_insert(sle(7)); { - MetaView v1(v0, false); + MetaView v1(&v0, tapNONE); v1.insert(sle(3)); v1.insert(sle(5)); v1.insert(sle(6)); @@ -224,7 +225,7 @@ class MetaView_test // v0: 12----7 // v1: --3-5-- - v1.apply(); + v1.apply(v0); } // v0: 123-5-7 @@ -251,7 +252,7 @@ class MetaView_test v0.unchecked_insert(sle(4, 4)); { - MetaView v1(v0, true); + MetaView v1(&v0, tapNONE); v1.erase(v1.peek(k(2))); v1.insert(sle(3, 3)); auto s = v1.peek(k(4)); @@ -262,7 +263,7 @@ class MetaView_test expect(seq(v1.read(k(3))) == 3); expect(seq(v1.read(k(4))) == 5); { - MetaView v2(v1, true); + MetaView v2(&v1); auto s = v2.peek(k(3)); seq(s, 6); v2.update(s); @@ -279,7 +280,7 @@ class MetaView_test expect(seq(v1.read(k(4))) == 5); { - MetaView v2(v1, true); + MetaView v2(&v1); auto s = v2.peek(k(3)); seq(s, 6); v2.update(s); @@ -288,13 +289,13 @@ class MetaView_test expect(! v2.exists(k(2))); expect(seq(v2.read(k(3))) == 6); expect(! v2.exists(k(4))); - v2.apply(); + v2.apply(v1); } expect(seq(v1.read(k(1))) == 1); expect(! v1.exists(k(2))); expect(seq(v1.read(k(3))) == 6); expect(! v1.exists(k(4))); - v1.apply(); + v1.apply(v0); } expect(seq(v0.read(k(1))) == 1); expect(! v0.exists(k(2))); @@ -302,25 +303,70 @@ class MetaView_test expect(! v0.exists(k(4))); } - // Regression test: - // Create a ledger with 1 item, put a - // MetaView on that, then another MetaView, - // erase the item, apply. + // Verify contextual information void - testStackRegress() + testContext() { using namespace jtx; - Env env(*this); - wipe(*env.ledger); - BasicView& v0 = *env.ledger; - v0.unchecked_insert(sle(1)); - MetaView v1(v0, true); { - MetaView v2(v1, true); - v2.erase(v2.peek(k(1))); - v2.apply(); + Env env(*this); + wipe(*env.ledger); + MetaView v0(env.ledger.get(), tapNONE); + expect(v0.seq() != 98); + expect(v0.seq() == env.ledger->seq()); + expect(v0.time() != 99); + expect(v0.time() == env.ledger->time()); + expect(v0.flags() == tapNONE); + { + // Shallow copy + MetaView v1(v0); + expect (v1.seq() == v0.seq()); + expect (v1.time() == v1.time()); + expect (v1.flags() == tapNONE); + + MetaView v2(&v1, tapNO_CHECK_SIGN); + expect(v2.time() == v1.time()); + expect(v2.seq() == v1.seq()); + expect(v2.flags() == tapNO_CHECK_SIGN); + MetaView v3(&v2); + expect(v3.seq() == v2.seq()); + expect(v3.time() == v2.time()); + expect(v3.flags() == v2.flags()); + } + { + PaymentView v1(&v0, tapNO_CHECK_SIGN); + expect(v1.seq() == v0.seq()); + expect(v1.time() == v0.time()); + expect(v1.flags() == tapNO_CHECK_SIGN); + PaymentView v2(&v1); + expect(v2.seq() == v1.seq()); + expect(v2.time() == v1.time()); + expect(v2.flags() == v1.flags()); + } + } + } + + void + testRegressions() + { + using namespace jtx; + + // Create a ledger with 1 item, put a + // MetaView on that, then another MetaView, + // erase the item, apply. + { + Env env(*this); + wipe(*env.ledger); + BasicView& v0 = *env.ledger; + v0.unchecked_insert(sle(1)); + MetaView v1(&v0, tapNONE); + { + MetaView v2(&v1); + v2.erase(v2.peek(k(1))); + v2.apply(v1); + } + expect(! v1.exists(k(1))); } - expect(! v1.exists(k(1))); } void run() @@ -332,7 +378,9 @@ class MetaView_test testMeta(); testMetaSucc(); testStacked(); - testStackRegress(); + testContext(); + + testRegressions(); } }; diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index 6e06b817d..65bfaa176 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -1337,7 +1337,9 @@ bool ApplicationImp::loadOldLedger ( txn->getJson(0); Serializer s; txn->getSTransaction()->add(s); - if (! addTransaction(*cur, item->getTag(), s)) + if (! cur->txInsert(item->getTag(), + std::make_shared(std::move(s)), + nullptr)) if (m_journal.warning) m_journal.warning << "Unable to add transaction " << item->getTag(); getApp().getHashRouter().setFlag (item->getTag(), SF_SIGGOOD); diff --git a/src/ripple/app/misc/CanonicalTXSet.cpp b/src/ripple/app/misc/CanonicalTXSet.cpp index 8fcce4d9c..e7f7f9db0 100644 --- a/src/ripple/app/misc/CanonicalTXSet.cpp +++ b/src/ripple/app/misc/CanonicalTXSet.cpp @@ -74,7 +74,7 @@ bool CanonicalTXSet::Key::operator>= (Key const& rhs)const return mTXid >= rhs.mTXid; } -void CanonicalTXSet::push_back (STTx::ref txn) +void CanonicalTXSet::push_back (std::shared_ptr const& txn) { uint256 effectiveAccount = mSetHash; diff --git a/src/ripple/app/misc/CanonicalTXSet.h b/src/ripple/app/misc/CanonicalTXSet.h index 9ae7cf079..4c9a9e816 100644 --- a/src/ripple/app/misc/CanonicalTXSet.h +++ b/src/ripple/app/misc/CanonicalTXSet.h @@ -71,8 +71,8 @@ public: std::uint32_t mSeq; }; - using iterator = std::map ::iterator; - using const_iterator = std::map ::const_iterator; + using iterator = std::map >::iterator; + using const_iterator = std::map >::const_iterator; public: explicit CanonicalTXSet (LedgerHash const& lastClosedLedgerHash) @@ -80,7 +80,7 @@ public: { } - void push_back (STTx::ref txn); + void push_back (std::shared_ptr const& txn); // VFALCO TODO remove this function void reset (LedgerHash const& newLastClosedLedgerHash) @@ -121,7 +121,7 @@ private: // Used to salt the accounts so people can't mine for low account numbers uint256 mSetHash; - std::map mMap; + std::map > mMap; }; } // ripple diff --git a/src/ripple/app/paths/PathRequest.cpp b/src/ripple/app/paths/PathRequest.cpp index 4b6ff9723..521408e67 100644 --- a/src/ripple/app/paths/PathRequest.cpp +++ b/src/ripple/app/paths/PathRequest.cpp @@ -525,7 +525,8 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast) if (valid) { boost::optional sandbox; - sandbox.emplace(cache->getLedger(), tapNONE); + sandbox.emplace(cache->getLedger().get(), + tapOPEN_LEDGER); auto& sourceAccount = !isXRP (currIssuer.account) ? currIssuer.account @@ -551,7 +552,8 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast) m_journal.debug << iIdentifier << " Trying with an extra path element"; spsPaths.push_back (fullLiquidityPath); - sandbox.emplace(cache->getLedger (), tapNONE); + sandbox.emplace(cache->getLedger().get(), + tapOPEN_LEDGER); rc = path::RippleCalc::rippleCalculate ( *sandbox, saMaxAmount, diff --git a/src/ripple/app/paths/PathRequest.h b/src/ripple/app/paths/PathRequest.h index 1f111462d..057341be8 100644 --- a/src/ripple/app/paths/PathRequest.h +++ b/src/ripple/app/paths/PathRequest.h @@ -20,6 +20,7 @@ #ifndef RIPPLE_APP_PATHS_PATHREQUEST_H_INCLUDED #define RIPPLE_APP_PATHS_PATHREQUEST_H_INCLUDED +#include #include #include #include diff --git a/src/ripple/app/paths/PathState.h b/src/ripple/app/paths/PathState.h index fe820845b..d66791533 100644 --- a/src/ripple/app/paths/PathState.h +++ b/src/ripple/app/paths/PathState.h @@ -36,7 +36,7 @@ class PathState : public CountedObject using Ptr = std::shared_ptr; using List = std::vector; - PathState (PaymentView& parent, + PathState (PaymentView const& parent, STAmount const& saSend, STAmount const& saSendMax) : mIndex (0) @@ -110,7 +110,7 @@ class PathState : public CountedObject return *view_; } - void resetView (PaymentView& view) + void resetView (PaymentView const& view) { view_.emplace(&view); } diff --git a/src/ripple/app/paths/Pathfinder.cpp b/src/ripple/app/paths/Pathfinder.cpp index bbe2fa780..2201e5e68 100644 --- a/src/ripple/app/paths/Pathfinder.cpp +++ b/src/ripple/app/paths/Pathfinder.cpp @@ -378,7 +378,7 @@ TER Pathfinder::getPathLiquidity ( path::RippleCalc::Input rcInput; rcInput.defaultPathsAllowed = false; - PaymentView sandbox (mLedger, tapNONE); + PaymentView sandbox (mLedger.get(), tapOPEN_LEDGER); try { @@ -443,7 +443,7 @@ void Pathfinder::computePathRanks (int maxPaths) // Must subtract liquidity in default path from remaining amount. try { - PaymentView sandbox (mLedger, tapNONE); + PaymentView sandbox (mLedger.get(), tapOPEN_LEDGER); path::RippleCalc::Input rcInput; rcInput.partialPaymentAllowed = true; diff --git a/src/ripple/app/paths/Pathfinder.h b/src/ripple/app/paths/Pathfinder.h index c03de02a1..c63896015 100644 --- a/src/ripple/app/paths/Pathfinder.h +++ b/src/ripple/app/paths/Pathfinder.h @@ -20,6 +20,7 @@ #ifndef RIPPLE_APP_PATHS_PATHFINDER_H_INCLUDED #define RIPPLE_APP_PATHS_PATHFINDER_H_INCLUDED +#include #include #include #include diff --git a/src/ripple/app/paths/RippleCalc.cpp b/src/ripple/app/paths/RippleCalc.cpp index f88e6f3ad..f2cc7049f 100644 --- a/src/ripple/app/paths/RippleCalc.cpp +++ b/src/ripple/app/paths/RippleCalc.cpp @@ -329,7 +329,7 @@ TER RippleCalc::rippleCalculate () pathState->unfundedOffers().end ()); // Apply best pass' view - pathState->view().apply(); + pathState->view().apply(view); actualAmountIn_ += pathState->inPass(); actualAmountOut_ += pathState->outPass(); diff --git a/src/ripple/app/paths/RippleLineCache.h b/src/ripple/app/paths/RippleLineCache.h index c606ac809..8fb03531a 100644 --- a/src/ripple/app/paths/RippleLineCache.h +++ b/src/ripple/app/paths/RippleLineCache.h @@ -20,6 +20,7 @@ #ifndef RIPPLE_APP_PATHS_RIPPLELINECACHE_H_INCLUDED #define RIPPLE_APP_PATHS_RIPPLELINECACHE_H_INCLUDED +#include #include #include #include diff --git a/src/ripple/app/paths/RippleState.h b/src/ripple/app/paths/RippleState.h index 2ce0a3c47..fe9ba608c 100644 --- a/src/ripple/app/paths/RippleState.h +++ b/src/ripple/app/paths/RippleState.h @@ -20,6 +20,7 @@ #ifndef RIPPLE_APP_PATHS_RIPPLESTATE_H_INCLUDED #define RIPPLE_APP_PATHS_RIPPLESTATE_H_INCLUDED +#include #include #include #include diff --git a/src/ripple/app/paths/cursor/AdvanceNode.cpp b/src/ripple/app/paths/cursor/AdvanceNode.cpp index 0d2309555..3e8f17277 100644 --- a/src/ripple/app/paths/cursor/AdvanceNode.cpp +++ b/src/ripple/app/paths/cursor/AdvanceNode.cpp @@ -212,7 +212,7 @@ TER PathCursor::advanceNode (bool const bReverse) const if (node().sleOffer->isFieldPresent (sfExpiration) && (node().sleOffer->getFieldU32 (sfExpiration) <= - getParentCloseTimeNC(view()))) + view().time())) { // Offer is expired. WriteLog (lsTRACE, RippleCalc) diff --git a/src/ripple/app/paths/impl/PaymentView.cpp b/src/ripple/app/paths/impl/PaymentView.cpp index bdc2f2479..5939c76c8 100644 --- a/src/ripple/app/paths/impl/PaymentView.cpp +++ b/src/ripple/app/paths/impl/PaymentView.cpp @@ -19,6 +19,7 @@ #include #include +#include namespace ripple { @@ -40,11 +41,18 @@ PaymentView::creditHook (AccountID const& from, } void -PaymentView::apply() +PaymentView::apply (BasicView& to) { - view_.apply(); - if (pv_) - pv_->tab_.apply(tab_); + assert(! pv_); + view_.apply(to); +} + +void +PaymentView::apply (PaymentView& to) +{ + assert(pv_ == &to); + view_.apply(to); + tab_.apply(to.tab_); } } // ripple diff --git a/src/ripple/app/paths/impl/PaymentView.h b/src/ripple/app/paths/impl/PaymentView.h index 4999ecf7b..0a652c778 100644 --- a/src/ripple/app/paths/impl/PaymentView.h +++ b/src/ripple/app/paths/impl/PaymentView.h @@ -23,8 +23,8 @@ #include #include #include -#include #include +#include // #include namespace ripple { @@ -39,12 +39,11 @@ namespace ripple { will change via the balanceHook and creditHook overrides of PaymentView. */ -class PaymentView : public View +class PaymentView : public ViewWrapper { private: - MetaView view_; DeferredCredits tab_; - PaymentView* pv_ = nullptr; + PaymentView const* pv_ = nullptr; public: PaymentView (PaymentView const&) = delete; @@ -54,7 +53,7 @@ public: template explicit PaymentView (Args&&... args) - : view_ (std::forward(args)...) + : ViewWrapper (std::forward(args)...) { } @@ -68,95 +67,24 @@ public: @note A pointer is used to prevent confusion with copy construction. */ + // VFALCO If we are constructing on top of a PaymentView, + // or a PaymentView-derived class, we MUST go through + // one of these constructors or invariants will be broken. + /** @{ */ explicit - PaymentView (PaymentView* parent) - : view_ (*parent, - parent->openLedger()) + PaymentView (PaymentView const* parent) + : ViewWrapper (parent) , pv_ (parent) { } - bool - exists (Keylet const& k) const override + explicit + PaymentView (PaymentView* parent) + : ViewWrapper (parent) + , pv_ (parent) { - return view_.exists(k); } - - boost::optional - succ (uint256 const& key, - boost::optional last = - boost::none) const override - { - return view_.succ(key, last); - } - - std::shared_ptr - read (Keylet const& k) const override - { - return view_.read(k); - } - - bool - unchecked_erase (uint256 const& key) override - { - return view_.unchecked_erase(key); - } - - void - unchecked_insert( - std::shared_ptr&& sle) override - { - view_.unchecked_insert( - std::move(sle)); - } - - void - unchecked_replace ( - std::shared_ptr&& sle) override - { - view_.unchecked_replace( - std::move(sle)); - } - - BasicView const* - parent() const override - { - return &view_; - } - - //--------------------------------------------- - - std::shared_ptr - peek (Keylet const& k) override - { - return view_.peek(k); - } - - void - erase (std::shared_ptr const& sle) override - { - return view_.erase(sle); - } - - void - insert (std::shared_ptr const& sle) override - { - return view_.insert(sle); - } - - void - update (std::shared_ptr const& sle) override - { - return view_.update(sle); - } - - bool - openLedger() const override - { - return view_.openLedger(); - } - - //-------------------------------------------------------------------------- + /** @} */ STAmount balanceHook (AccountID const& account, @@ -168,8 +96,22 @@ public: AccountID const& to, STAmount const& amount) override; + /** Apply changes to the parent View. + + `to` must contain contents identical to the parent + view passed upon construction, else undefined + behavior will result. + + After a call to apply(), the only valid operation that + may be performed on this is a call to the destructor. + */ + /** @{ */ void - apply(); + apply (BasicView& to); + + void + apply (PaymentView& to); + /** @} */ }; } // ripple diff --git a/src/ripple/app/tx/TransactionEngine.h b/src/ripple/app/tx/TransactionEngine.h index ef8dddf0b..03e2a98bb 100644 --- a/src/ripple/app/tx/TransactionEngine.h +++ b/src/ripple/app/tx/TransactionEngine.h @@ -27,31 +27,12 @@ namespace ripple { -// A TransactionEngine applies serialized transactions to a ledger -// It can also, verify signatures, verify fees, and give rejection reasons - -struct tx_enable_test_t { tx_enable_test_t() { } }; -static tx_enable_test_t const tx_enable_test; +// tx_enable_test // One instance per ledger. // Only one transaction applied at a time. class TransactionEngine { -private: - bool enableMultiSign_ = -#if RIPPLE_ENABLE_MULTI_SIGN - true; -#else - false; -#endif - - bool enableTickets_ = -#if RIPPLE_ENABLE_TICKETS - true; -#else - false; -#endif - boost::optional mNodes; void txnWrite(); @@ -70,36 +51,14 @@ public: assert (mLedger); } - TransactionEngine (Ledger::ref ledger, - tx_enable_test_t) - : enableMultiSign_(true) - , enableTickets_(true) - , mLedger (ledger) - { - assert (mLedger); - } - - bool - enableMultiSign() const - { - return enableMultiSign_; - } - - bool - enableTickets() const - { - return enableTickets_; - } - - // VFALCO TODO Change to return `View&` - MetaView& + View& view () { return *mNodes; } Ledger::ref - getLedger () + getLedger() { return mLedger; } @@ -119,20 +78,20 @@ public: } std::pair - applyTransaction (STTx const&, TransactionEngineParams); + applyTransaction (STTx const&, ViewFlags); bool - checkInvariants (TER result, STTx const& txn, TransactionEngineParams params); + checkInvariants (TER result, STTx const& txn, ViewFlags params); }; -inline TransactionEngineParams operator| (const TransactionEngineParams& l1, const TransactionEngineParams& l2) +inline ViewFlags operator| (const ViewFlags& l1, const ViewFlags& l2) { - return static_cast (static_cast (l1) | static_cast (l2)); + return static_cast (static_cast (l1) | static_cast (l2)); } -inline TransactionEngineParams operator& (const TransactionEngineParams& l1, const TransactionEngineParams& l2) +inline ViewFlags operator& (const ViewFlags& l1, const ViewFlags& l2) { - return static_cast (static_cast (l1) & static_cast (l2)); + return static_cast (static_cast (l1) & static_cast (l2)); } } // ripple diff --git a/src/ripple/app/tx/impl/CancelOffer.cpp b/src/ripple/app/tx/impl/CancelOffer.cpp index 230a9a797..cbace411e 100644 --- a/src/ripple/app/tx/impl/CancelOffer.cpp +++ b/src/ripple/app/tx/impl/CancelOffer.cpp @@ -31,7 +31,7 @@ class CancelOffer public: CancelOffer ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) : Transactor ( txn, @@ -95,7 +95,7 @@ public: TER transact_CancelOffer ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) { return CancelOffer (txn, params, engine).apply (); diff --git a/src/ripple/app/tx/impl/CancelTicket.cpp b/src/ripple/app/tx/impl/CancelTicket.cpp index 5fdc61266..8f03f4ccb 100644 --- a/src/ripple/app/tx/impl/CancelTicket.cpp +++ b/src/ripple/app/tx/impl/CancelTicket.cpp @@ -30,7 +30,7 @@ class CancelTicket public: CancelTicket ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) : Transactor ( txn, @@ -69,7 +69,7 @@ public: { std::uint32_t const expiration = sleTicket->getFieldU32 (sfExpiration); - if (mEngine->getLedger ()->getParentCloseTimeNC () >= expiration) + if (mEngine->view().time() >= expiration) authorized = true; } @@ -92,11 +92,13 @@ public: TER transact_CancelTicket ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) { - if (! engine->enableTickets()) +#if ! RIPPLE_ENABLE_TICKETS + if (! (engine->view().flags() & tapENABLE_TESTING)) return temDISABLED; +#endif return CancelTicket (txn, params, engine).apply(); } diff --git a/src/ripple/app/tx/impl/Change.cpp b/src/ripple/app/tx/impl/Change.cpp index 70c0a6801..9f1d64188 100644 --- a/src/ripple/app/tx/impl/Change.cpp +++ b/src/ripple/app/tx/impl/Change.cpp @@ -33,7 +33,7 @@ class Change public: Change ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) : Transactor ( txn, @@ -192,7 +192,7 @@ private: TER transact_Change ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) { return Change (txn, params, engine).apply (); diff --git a/src/ripple/app/tx/impl/CreateOffer.cpp b/src/ripple/app/tx/impl/CreateOffer.cpp index 5c7822fbe..204e506b1 100644 --- a/src/ripple/app/tx/impl/CreateOffer.cpp +++ b/src/ripple/app/tx/impl/CreateOffer.cpp @@ -391,8 +391,8 @@ private: View& cancel_view, Amounts const& taker_amount) { - Clock::time_point const when ( - mEngine->getLedger ()->getParentCloseTimeNC ()); + Clock::time_point const when = + mEngine->view().time(); beast::WrappedSink takerSink (m_journal, "Taker "); @@ -432,7 +432,7 @@ public: CreateOffer ( CrossType cross_type, STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) : Transactor ( txn, @@ -448,7 +448,7 @@ public: STAmount getAccountReserve (SLE::pointer account) { - return STAmount (mEngine->getLedger ()->getReserve ( + return STAmount (mEngine->view().fees().accountReserve( account->getFieldU32 (sfOwnerCount) + 1)); } @@ -641,7 +641,7 @@ public: // because we definitively know the time that it closed but we do not // know the closing time of the ledger that is under construction. if (bHaveExpiration && - (mEngine->getLedger ()->getParentCloseTimeNC () >= uExpiration)) + (mEngine->view().time() >= uExpiration)) { return { tesSUCCESS, true }; } @@ -835,18 +835,17 @@ public: TER doApply() override { - bool const openLedger = mParams & tapOPEN_LEDGER; // This is the ledger view that we work against. Transactions are applied // as we go on processing transactions. - MetaView view (mEngine->view(), openLedger); + MetaView view (&mEngine->view()); // This is a checkpoint with just the fees paid. If something goes wrong // with this transaction, we roll back to this ledger. - MetaView viewCancel (mEngine->view(), openLedger); + MetaView viewCancel (&mEngine->view()); auto const result = applyGuts(view, viewCancel); if (result.second) - view.apply(); + view.apply(mEngine->view()); else - viewCancel.apply(); + viewCancel.apply(mEngine->view()); return result.first; } }; @@ -854,7 +853,7 @@ public: TER transact_CreateOffer ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) { CrossType cross_type = CrossType::IouToIou; diff --git a/src/ripple/app/tx/impl/CreateTicket.cpp b/src/ripple/app/tx/impl/CreateTicket.cpp index c5658f3dc..5ec7a017a 100644 --- a/src/ripple/app/tx/impl/CreateTicket.cpp +++ b/src/ripple/app/tx/impl/CreateTicket.cpp @@ -30,7 +30,7 @@ class CreateTicket public: CreateTicket ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) : Transactor ( txn, @@ -61,7 +61,7 @@ public: STAmount getAccountReserve (SLE::pointer account) { - return STAmount (mEngine->getLedger ()->getReserve ( + return STAmount (mEngine->view().fees().accountReserve( account->getFieldU32 (sfOwnerCount) + 1)); } @@ -81,7 +81,7 @@ public: { expiration = mTxn.getFieldU32 (sfExpiration); - if (mEngine->getLedger ()->getParentCloseTimeNC () >= expiration) + if (mEngine->view().time() >= expiration) return tesSUCCESS; } @@ -141,11 +141,13 @@ public: TER transact_CreateTicket ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) { - if (! engine->enableTickets()) +#if ! RIPPLE_ENABLE_TICKETS + if (! (engine->view().flags() & tapENABLE_TESTING)) return temDISABLED; +#endif return CreateTicket (txn, params, engine).apply (); } diff --git a/src/ripple/app/tx/impl/LocalTxs.cpp b/src/ripple/app/tx/impl/LocalTxs.cpp index 663c8f9d4..68aa27080 100644 --- a/src/ripple/app/tx/impl/LocalTxs.cpp +++ b/src/ripple/app/tx/impl/LocalTxs.cpp @@ -124,7 +124,7 @@ public: { if (txn.isExpired (ledger->getLedgerSeq ())) return true; - if (hasTransaction (*ledger, txn.getID ())) + if (ledger->txExists(txn.getID())) return true; auto const sle = cachedRead(*ledger, keylet::account(txn.getAccount()).key, diff --git a/src/ripple/app/tx/impl/Payment.cpp b/src/ripple/app/tx/impl/Payment.cpp index 871a756f9..b520200d7 100644 --- a/src/ripple/app/tx/impl/Payment.cpp +++ b/src/ripple/app/tx/impl/Payment.cpp @@ -39,7 +39,7 @@ class Payment public: Payment ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) : Transactor ( txn, @@ -218,7 +218,7 @@ public: // transaction would succeed. return telNO_DST_PARTIAL; } - else if (saDstAmount < STAmount (mEngine->getLedger ()->getReserve (0))) + else if (saDstAmount < STAmount (mEngine->view().fees().accountReserve(0))) { // getReserve() is the minimum amount that an account can have. // Reserve is not scaled by load. @@ -294,7 +294,7 @@ public: { path::RippleCalc::Output rc; { - PaymentView view (mEngine->view()); + PaymentView view (&mEngine->view()); rc = path::RippleCalc::rippleCalculate ( view, maxSourceAmount, @@ -306,7 +306,7 @@ public: // VFALCO NOTE We might not need to apply, depending // on the TER. But always applying *should* // be safe. - view.apply(); + view.apply(mEngine->view()); } // TODO: is this right? If the amount is the correct amount, was @@ -339,8 +339,8 @@ public: auto const uOwnerCount = mTxnAccount->getFieldU32 (sfOwnerCount); // This is the total reserve in drops. - std::uint64_t const uReserve = - mEngine->getLedger ()->getReserve (uOwnerCount); + auto const uReserve = + mEngine->view().fees().accountReserve(uOwnerCount); // mPriorBalance is the balance on the sending account BEFORE the // fees were charged. We want to make sure we have enough reserve @@ -396,7 +396,7 @@ public: TER transact_Payment ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) { return Payment(txn, params, engine).apply (); diff --git a/src/ripple/app/tx/impl/SetAccount.cpp b/src/ripple/app/tx/impl/SetAccount.cpp index e98ef73c8..2cd8a5ce0 100644 --- a/src/ripple/app/tx/impl/SetAccount.cpp +++ b/src/ripple/app/tx/impl/SetAccount.cpp @@ -36,7 +36,7 @@ class SetAccount public: SetAccount ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) : Transactor ( txn, @@ -387,7 +387,7 @@ public: TER transact_SetAccount ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) { return SetAccount(txn, params, engine).apply (); diff --git a/src/ripple/app/tx/impl/SetRegularKey.cpp b/src/ripple/app/tx/impl/SetRegularKey.cpp index 286b8a0dc..fa78bf7cc 100644 --- a/src/ripple/app/tx/impl/SetRegularKey.cpp +++ b/src/ripple/app/tx/impl/SetRegularKey.cpp @@ -44,7 +44,7 @@ class SetRegularKey public: SetRegularKey ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) : Transactor ( txn, @@ -94,7 +94,7 @@ public: TER transact_SetRegularKey ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) { return SetRegularKey(txn, params, engine).apply (); diff --git a/src/ripple/app/tx/impl/SetSignerList.cpp b/src/ripple/app/tx/impl/SetSignerList.cpp index 9a458e40e..2ad9d1600 100644 --- a/src/ripple/app/tx/impl/SetSignerList.cpp +++ b/src/ripple/app/tx/impl/SetSignerList.cpp @@ -48,7 +48,7 @@ private: public: SetSignerList ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) : Transactor ( txn, @@ -224,8 +224,9 @@ SetSignerList::replaceSignerList (uint256 const& index) std::uint32_t const oldOwnerCount = mTxnAccount->getFieldU32 (sfOwnerCount); std::uint32_t const addedOwnerCount = ownerCountDelta (signers_.size ()); - std::uint64_t const newReserve = - mEngine->getLedger ()->getReserve (oldOwnerCount + addedOwnerCount); + auto const newReserve = + mEngine->view().fees().accountReserve( + oldOwnerCount + addedOwnerCount); // We check the reserve against the starting balance because we want to // allow dipping into the reserve to pay fees. This behavior is consistent @@ -359,11 +360,13 @@ SetSignerList::ownerCountDelta (std::size_t entryCount) TER transact_SetSignerList ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) { - if (! engine->enableMultiSign()) +#if ! RIPPLE_ENABLE_MULTI_SIGN + if (! (engine->view().flags() & tapENABLE_TESTING)) return temDISABLED; +#endif return SetSignerList (txn, params, engine).apply (); } diff --git a/src/ripple/app/tx/impl/SetTrust.cpp b/src/ripple/app/tx/impl/SetTrust.cpp index 9622efa1a..83ee89243 100644 --- a/src/ripple/app/tx/impl/SetTrust.cpp +++ b/src/ripple/app/tx/impl/SetTrust.cpp @@ -32,7 +32,7 @@ class SetTrust public: SetTrust ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) : Transactor ( txn, @@ -123,7 +123,7 @@ public: STAmount const reserveCreate ((uOwnerCount < 2) ? 0 - : mEngine->getLedger ()->getReserve (uOwnerCount + 1)); + : mEngine->view().fees().accountReserve(uOwnerCount + 1)); std::uint32_t uQualityIn (bQualityIn ? mTxn.getFieldU32 (sfQualityIn) : 0); std::uint32_t uQualityOut (bQualityOut ? mTxn.getFieldU32 (sfQualityOut) : 0); @@ -451,7 +451,7 @@ public: TER transact_SetTrust ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) { return SetTrust (txn, params, engine).apply (); diff --git a/src/ripple/app/tx/impl/TransactionEngine.cpp b/src/ripple/app/tx/impl/TransactionEngine.cpp index 7e3e34522..19abf5e13 100644 --- a/src/ripple/app/tx/impl/TransactionEngine.cpp +++ b/src/ripple/app/tx/impl/TransactionEngine.cpp @@ -34,7 +34,7 @@ namespace ripple { std::pair TransactionEngine::applyTransaction ( STTx const& txn, - TransactionEngineParams params) + ViewFlags flags) { assert (mLedger); @@ -49,8 +49,7 @@ TransactionEngine::applyTransaction ( return std::make_pair(temINVALID_FLAG, false); } - mNodes.emplace(mLedger, txID, - mLedger->getLedgerSeq(), params); + mNodes.emplace(mLedger.get(), flags, txID); #ifdef BEAST_DEBUG if (1) @@ -71,7 +70,7 @@ TransactionEngine::applyTransaction ( } #endif - TER terResult = Transactor::transact (txn, params, this); + TER terResult = Transactor::transact (txn, flags, this); if (terResult == temUNKNOWN) { @@ -95,13 +94,12 @@ TransactionEngine::applyTransaction ( bool didApply = isTesSuccess (terResult); - if (isTecClaim (terResult) && !(params & tapRETRY)) + if (isTecClaim (terResult) && !(flags & tapRETRY)) { // only claim the transaction fee WriteLog (lsDEBUG, TransactionEngine) << "Reprocessing tx " << txID << " to only claim fee"; - mNodes.emplace(mLedger, txID, - mLedger->getLedgerSeq(), params); + mNodes.emplace(mLedger.get(), flags, txID); SLE::pointer txnAcct = view().peek( keylet::account(txn.getAccountID(sfAccount))); @@ -126,7 +124,7 @@ TransactionEngine::applyTransaction ( // balance is zero or we're applying against an open // ledger and the balance is less than the fee if ((balance == zero) || - ((params & tapOPEN_LEDGER) && (balance < fee))) + ((flags & tapOPEN_LEDGER) && (balance < fee))) { // Account has no funds or ledger is open terResult = terINSUF_FEE_B; @@ -148,7 +146,7 @@ TransactionEngine::applyTransaction ( WriteLog (lsDEBUG, TransactionEngine) << "Not applying transaction " << txID; } - if (didApply && !checkInvariants (terResult, txn, params)) + if (didApply && !checkInvariants (terResult, txn, flags)) { WriteLog (lsFATAL, TransactionEngine) << "Transaction violates invariants"; @@ -169,14 +167,17 @@ TransactionEngine::applyTransaction ( Serializer m; mNodes->calcRawMeta (m, terResult, mTxnSeq++); - mNodes->apply(); + mNodes->apply(*mLedger); Serializer s; txn.add (s); - if (params & tapOPEN_LEDGER) + if (flags & tapOPEN_LEDGER) { - if (! addTransaction (*mLedger, txID, s)) + if (! mLedger->txInsert(txID, + std::make_shared< + Serializer const>(std::move(s)), + nullptr)) { WriteLog (lsFATAL, TransactionEngine) << "Duplicate transaction applied"; @@ -186,7 +187,9 @@ TransactionEngine::applyTransaction ( } else { - if (! addTransaction (*mLedger, txID, s, m)) + if (! mLedger->txInsert(txID, + std::make_shared(std::move(s)), + std::make_shared(std::move(m)))) { WriteLog (lsFATAL, TransactionEngine) << "Duplicate transaction applied to closed ledger"; @@ -210,7 +213,7 @@ TransactionEngine::applyTransaction ( mNodes = boost::none; - if (!(params & tapOPEN_LEDGER) && isTemMalformed (terResult)) + if (!(flags & tapOPEN_LEDGER) && isTemMalformed (terResult)) { // XXX Malformed or failed transaction in closed ledger must bow out. } @@ -222,7 +225,7 @@ bool TransactionEngine::checkInvariants ( TER result, STTx const& txn, - TransactionEngineParams params) + ViewFlags flags) { // VFALCO I deleted a bunch of code that was wrapped in #if 0. // If you need it, check the commit log. diff --git a/src/ripple/app/tx/impl/Transactor.cpp b/src/ripple/app/tx/impl/Transactor.cpp index 5e22b990d..77643fb0a 100644 --- a/src/ripple/app/tx/impl/Transactor.cpp +++ b/src/ripple/app/tx/impl/Transactor.cpp @@ -18,31 +18,31 @@ //============================================================================== #include -#include #include #include #include #include +#include #include #include namespace ripple { -TER transact_Payment (STTx const& txn, TransactionEngineParams params, TransactionEngine* engine); -TER transact_SetAccount (STTx const& txn, TransactionEngineParams params, TransactionEngine* engine); -TER transact_SetRegularKey (STTx const& txn, TransactionEngineParams params, TransactionEngine* engine); -TER transact_SetTrust (STTx const& txn, TransactionEngineParams params, TransactionEngine* engine); -TER transact_CreateOffer (STTx const& txn, TransactionEngineParams params, TransactionEngine* engine); -TER transact_CancelOffer (STTx const& txn, TransactionEngineParams params, TransactionEngine* engine); -TER transact_Change (STTx const& txn, TransactionEngineParams params, TransactionEngine* engine); -TER transact_CreateTicket (STTx const& txn, TransactionEngineParams params, TransactionEngine* engine); -TER transact_CancelTicket (STTx const& txn, TransactionEngineParams params, TransactionEngine* engine); -TER transact_SetSignerList (STTx const& txn, TransactionEngineParams params, TransactionEngine* engine); +TER transact_Payment (STTx const& txn, ViewFlags params, TransactionEngine* engine); +TER transact_SetAccount (STTx const& txn, ViewFlags params, TransactionEngine* engine); +TER transact_SetRegularKey (STTx const& txn, ViewFlags params, TransactionEngine* engine); +TER transact_SetTrust (STTx const& txn, ViewFlags params, TransactionEngine* engine); +TER transact_CreateOffer (STTx const& txn, ViewFlags params, TransactionEngine* engine); +TER transact_CancelOffer (STTx const& txn, ViewFlags params, TransactionEngine* engine); +TER transact_Change (STTx const& txn, ViewFlags params, TransactionEngine* engine); +TER transact_CreateTicket (STTx const& txn, ViewFlags params, TransactionEngine* engine); +TER transact_CancelTicket (STTx const& txn, ViewFlags params, TransactionEngine* engine); +TER transact_SetSignerList (STTx const& txn, ViewFlags params, TransactionEngine* engine); TER Transactor::transact ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine) { switch (txn.getTxnType ()) @@ -85,22 +85,24 @@ Transactor::transact ( Transactor::Transactor ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine, beast::Journal journal) : mTxn (txn) , mEngine (engine) - , mParams (params) + , mParams (mEngine->view().flags()) , mHasAuthKey (false) , mSigMaster (false) , m_journal (journal) { + assert(mEngine->view().flags() == params); } void Transactor::calculateFee () { - mFeeDue = STAmount (scaleFeeLoad (getApp().getFeeTrack(), - *mEngine->getLedger(), calculateBaseFee (), mParams & tapADMIN)); + mFeeDue = STAmount (getApp().getFeeTrack().scaleFeeLoad( + calculateBaseFee(), mEngine->view().fees().base, + mEngine->view().fees().units, mParams & tapADMIN)); } std::uint64_t Transactor::calculateBaseFee () @@ -172,7 +174,7 @@ TER Transactor::checkSeq () return terPRE_SEQ; } - if (hasTransaction (*mEngine->getLedger (), mTxn.getTransactionID ())) + if (mEngine->view().txExists(mTxn.getTransactionID ())) return tefALREADY; m_journal.trace << "applyTransaction: has past sequence number " << @@ -233,7 +235,14 @@ TER Transactor::preCheckSigningKey () if (!mTxn.isKnownGood ()) { if (mTxn.isKnownBad () || - (!(mParams & tapNO_CHECK_SIGN) && !mTxn.checkSign(mEngine->enableMultiSign()))) + (!(mParams & tapNO_CHECK_SIGN) && !mTxn.checkSign( + ( +#if RIPPLE_ENABLE_MULTI_SIGN + true +#else + mEngine->view().flags() & tapENABLE_TESTING +#endif + )))) { mTxn.setBad (); m_journal.debug << "apply: Invalid transaction (bad signature)"; @@ -303,7 +312,10 @@ TER Transactor::apply () TER Transactor::checkSign () { - if(mEngine->enableMultiSign()) +#if RIPPLE_ENABLE_MULTI_SIGN +#else + if(mEngine->view().flags() & tapENABLE_TESTING) +#endif { // If the mSigningPubKey is empty, then we must be multi-signing. if (mSigningPubKey.getAccountPublic ().empty ()) diff --git a/src/ripple/app/tx/impl/Transactor.h b/src/ripple/app/tx/impl/Transactor.h index ba6714212..972dac7a4 100644 --- a/src/ripple/app/tx/impl/Transactor.h +++ b/src/ripple/app/tx/impl/Transactor.h @@ -31,7 +31,7 @@ public: TER transact ( STTx const& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine); TER @@ -40,7 +40,7 @@ public: protected: STTx const& mTxn; TransactionEngine* mEngine; - TransactionEngineParams mParams; + ViewFlags const mParams; AccountID mTxnAccountID; STAmount mFeeDue; @@ -72,7 +72,7 @@ protected: Transactor ( const STTx& txn, - TransactionEngineParams params, + ViewFlags params, TransactionEngine* engine, beast::Journal journal = beast::Journal ()); diff --git a/src/ripple/app/tx/tests/common_transactor.cpp b/src/ripple/app/tx/tests/common_transactor.cpp index 7156a5c04..343246deb 100644 --- a/src/ripple/app/tx/tests/common_transactor.cpp +++ b/src/ripple/app/tx/tests/common_transactor.cpp @@ -107,7 +107,7 @@ std::pair TestLedger::applyTransaction (STTx const& tx, bool check) // Check for the transaction in the closed ledger. bool const foundTx = - hasTransaction(*lastClosedLedger, tx.getTransactionID()); + lastClosedLedger->txExists(tx.getTransactionID()); suite_.expect (r.second == foundTx); return {r.first, r.second && foundTx}; diff --git a/src/ripple/ledger/CachedView.h b/src/ripple/ledger/CachedView.h index 5cbae2429..1b568e477 100644 --- a/src/ripple/ledger/CachedView.h +++ b/src/ripple/ledger/CachedView.h @@ -26,10 +26,9 @@ namespace ripple { /** Cache-aware view to a ledger */ -class CachedView : public BasicView +class CachedView : public BasicViewWrapper { private: - Ledger& ledger_; SLECache& cache_; public: @@ -39,56 +38,15 @@ public: /** Wrap a ledger with a cache. @note Only ledgers may be wrapped with a cache. */ - CachedView(Ledger& ledger, + CachedView (Ledger& ledger, SLECache& cache) - : ledger_(ledger) + : BasicViewWrapper(ledger) , cache_(cache) { } - bool - exists (Keylet const& k) const override - { - return ledger_.exists(k); - } - - boost::optional - succ (uint256 const& key, boost::optional< - uint256> last = boost::none) const override - { - return ledger_.succ(key, last); - } - - BasicView const* - parent() const override - { - return &ledger_; - } - std::shared_ptr read (Keylet const& k) const override; - - bool - unchecked_erase (uint256 const& key) override - { - return ledger_.unchecked_erase(key); - } - - void - unchecked_insert( - std::shared_ptr&& sle) override - { - ledger_.unchecked_insert( - std::move(sle)); - } - - void - unchecked_replace ( - std::shared_ptr&& sle) override - { - ledger_.unchecked_replace( - std::move(sle)); - } }; } // ripple diff --git a/src/ripple/ledger/DeferredCredits.h b/src/ripple/ledger/DeferredCredits.h index e4560513d..6d1b15e60 100644 --- a/src/ripple/ledger/DeferredCredits.h +++ b/src/ripple/ledger/DeferredCredits.h @@ -58,15 +58,11 @@ public: AccountID const& receiver, STAmount const& amount); - void apply (DeferredCredits const& child); + void apply (DeferredCredits& to); // VFALCO Is this needed? // DEPRECATED void clear (); - // DEPRECATED - 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/View.h b/src/ripple/ledger/View.h index 83c675585..2d2a96635 100644 --- a/src/ripple/ledger/View.h +++ b/src/ripple/ledger/View.h @@ -20,16 +20,51 @@ #ifndef RIPPLE_LEDGER_VIEW_H_INCLUDED #define RIPPLE_LEDGER_VIEW_H_INCLUDED +#include +#include #include #include #include #include -#include -#include #include +#include +#include +#include + +#include namespace ripple { +/** Reflects the fee settings for a particular ledger. + + The fees are always the same for any transactions applied + to a ledger. Changes to fees occur in between ledgers. +*/ +struct Fees +{ + std::uint64_t base = 0; // Reference tx cost (drops) + std::uint32_t units = 0; // Reference fee units + std::uint32_t reserve = 0; // Reserve base (drops) + std::uint32_t increment = 0; // Reserve increment (drops) + + Fees() = default; + Fees (Fees const&) = default; + Fees& operator= (Fees const&) = default; + + /** Returns the account reserve given the owner count, in drops. + + The reserve is calculated as the reserve base plus + the reserve increment times the number of increments. + */ + std::uint64_t + accountReserve (std::size_t ownerCount) const + { + return reserve + ownerCount * increment; + } +}; + +//------------------------------------------------------------------------------ + /** A view into a ledger's state items. The interface provides raw access for state item @@ -43,11 +78,26 @@ public: using mapped_type = std::shared_ptr; - BasicView() = default; - BasicView(BasicView const&) = delete; - BasicView& operator=(BasicView const&) = delete; virtual ~BasicView() = default; + /** Returns the fees for the base ledger. */ + virtual + Fees const& + fees() const = 0; + + /** Returns the sequence number of the base ledger. */ + virtual + LedgerIndex + seq() const = 0; + + /** Return the last known close time. + + The epoch is based on the Ripple network clock. + */ + virtual + std::uint32_t + time() const = 0; + /** Determine if a state item exists. @note This can be more efficient than calling read. @@ -146,16 +196,34 @@ public: void unchecked_replace (std::shared_ptr&& sle) = 0; - /** Return the parent view or nullptr. - @note Changing views with children breaks invariants. + /** Destroy XRP. + + This is used to pay for transaction fees. */ - // VFALCO This is a bit of a hack used to walk the parent - // list to gain access to the underlying ledger. - // Its an alternative to exposing things like the - // previous ledger close time. virtual - BasicView const* - parent() const = 0; + void + destroyCoins (std::uint64_t feeDrops) = 0; + + /** Returns `true` if a tx exists in the tx map. */ + virtual + bool + txExists (uint256 const& key) const = 0; + + /** Add a transaction to the tx map. + + @param metaData Optional metadata (may be nullptr) + */ + virtual + bool + txInsert (uint256 const& key, + std::shared_ptr const& txn, + std::shared_ptr const& metaData) = 0; + + // DEBUG ROUTINE + // Return a list of transaction keys in the tx map. + virtual + std::vector + txList() const = 0; //-------------------------------------------------------------------------- @@ -174,6 +242,32 @@ public: //------------------------------------------------------------------------------ +enum ViewFlags +{ + tapNONE = 0x00, + + // Signature already checked + tapNO_CHECK_SIGN = 0x01, + + // Enable supressed features for testing. + // This lets unit tests exercise code that + // is not turned on for production. + // + tapENABLE_TESTING = 0x02, + + // Transaction is running against an open ledger + // true = failures are not forwarded, check transaction fee + // false = debit ledger for consumed funds + tapOPEN_LEDGER = 0x10, + + // This is not the transaction's last pass + // Transaction can be retried, soft failures allowed + tapRETRY = 0x20, + + // Transaction came from a privileged source + tapADMIN = 0x400, +}; + /** A contextual view into a ledger's state items. This refinement of BasicView provides an interface where @@ -183,6 +277,8 @@ public: to calculate the results of transaction processing, including the metadata if the view is later applied to the parent (using an interface in the derived class). + The context info also includes values from the base + ledger such as sequence number and the network time. This allows the MetaView implementation to journal changes made to the state items in a ledger, with the @@ -214,11 +310,20 @@ public: class View : public BasicView { public: - View() = default; - View(BasicView const&) = delete; - View& operator=(BasicView const&) = delete; virtual ~View() = default; + /** Returns the contextual tx processing flags. + + Transactions may process differently depending on + information in the context. For example, transactions + applied to an open ledger generate "local" failures, + while transactions applied to the consensus ledger + produce hard failures (and claim a fee). + */ + virtual + ViewFlags + flags() const = 0; + /** Prepare to modify the SLE associated with key. Effects: @@ -287,17 +392,6 @@ public: //-------------------------------------------------------------------------- - /** Returns `true` if the context is an open ledger. - - Open ledgers have different rules for what TER - codes are returned when a transaction fails. - */ - virtual - bool - openLedger() const = 0; - - //-------------------------------------------------------------------------- - // Called when a credit is made to an account // This is required to support PaymentView virtual @@ -309,37 +403,280 @@ public: } }; +//------------------------------------------------------------------------------ + +// Wrapper to facilitate subclasses, +// forwards all non-overriden virtuals. +// +template +class BasicViewWrapper : public BasicView +{ +protected: + Member view_; + +public: + template + explicit + BasicViewWrapper (Args&&... args) + : view_(std::forward(args)...) + { + } + + Fees const& + fees() const override + { + return view_.fees(); + } + + LedgerIndex + seq() const override + { + return view_.seq(); + } + + std::uint32_t + time() const override + { + return view_.time(); + } + + bool + exists (Keylet const& k) const override + { + return view_.exists(k); + } + + boost::optional + succ (uint256 const& key, boost::optional< + uint256> last = boost::none) const override + { + return view_.succ(key, last); + } + + std::shared_ptr + read (Keylet const& k) const override + { + return view_.read(k); + } + + bool + unchecked_erase( + uint256 const& key) override + { + return view_.unchecked_erase(key); + } + + void + unchecked_insert( + std::shared_ptr&& sle) override + { + return view_.unchecked_insert( + std::move(sle)); + } + + void + unchecked_replace( + std::shared_ptr&& sle) override + { + return view_.unchecked_replace( + std::move(sle)); + } + + void + destroyCoins (std::uint64_t feeDrops) override + { + return view_.destroyCoins(feeDrops); + } + + bool + txExists (uint256 const& key) const override + { + return view_.txExists(key); + } + + bool + txInsert (uint256 const& key, + std::shared_ptr const& txn, std::shared_ptr< + Serializer const> const& metaData) override + { + return view_.txInsert( + key, txn, metaData); + } + + std::vector + txList() const override + { + return view_.txList(); + } +}; + +// Wrapper to facilitate subclasses, +// forwards all non-overriden virtuals. +// +template +class ViewWrapper : public View +{ +protected: + Member view_; + +public: + template + explicit + ViewWrapper (Args&&... args) + : view_(std::forward(args)...) + { + } + + Fees const& + fees() const override + { + return view_.fees(); + } + + LedgerIndex + seq() const override + { + return view_.seq(); + } + + std::uint32_t + time() const override + { + return view_.time(); + } + + bool + exists (Keylet const& k) const override + { + return view_.exists(k); + } + + boost::optional + succ (uint256 const& key, boost::optional< + uint256> last = boost::none) const override + { + return view_.succ(key, last); + } + + std::shared_ptr + read (Keylet const& k) const override + { + return view_.read(k); + } + + bool + unchecked_erase( + uint256 const& key) override + { + return view_.unchecked_erase(key); + } + + void + unchecked_insert( + std::shared_ptr&& sle) override + { + return view_.unchecked_insert( + std::move(sle)); + } + + void + unchecked_replace( + std::shared_ptr&& sle) override + { + return view_.unchecked_replace( + std::move(sle)); + } + + void + destroyCoins (std::uint64_t feeDrops) override + { + return view_.destroyCoins(feeDrops); + } + + bool + txExists (uint256 const& key) const override + { + return view_.txExists(key); + } + + bool + txInsert (uint256 const& key, + std::shared_ptr const& txn, std::shared_ptr< + Serializer const> const& metaData) override + { + return view_.txInsert( + key, txn, metaData); + } + + std::vector + txList() const override + { + return view_.txList(); + } + + //----- + + ViewFlags + flags() const override + { + return view_.flags(); + } + + std::shared_ptr + peek (Keylet const& k) override + { + return view_.peek(k); + } + + void + erase (std::shared_ptr< + SLE> const& sle) override + { + return view_.erase(sle); + } + + void + insert (std::shared_ptr< + SLE> const& sle) override + { + return view_.insert(sle); + } + + void + update (std::shared_ptr< + SLE> const& sle) override + { + return view_.update(sle); + } + + void + creditHook (AccountID const& from, + AccountID const& to, + STAmount const& amount) override + { + return view_.creditHook (from, to, amount); + } +}; + //------------------------------------------------------------------------------ // // Observers // //------------------------------------------------------------------------------ -/** Reflects the fee settings for a particular ledger. */ -class Fees +/** Controls the treatment of frozen account balances */ +enum FreezeHandling { -private: - std::uint64_t base_; // Reference tx cost (drops) - std::uint32_t units_; // Reference fee units - std::uint32_t reserve_; // Reserve base (drops) - std::uint32_t increment_; // Reserve increment (drops) - -public: - Fees (BasicView const& view, - Config const& config); - - /** Returns the account reserve given the owner count, in drops. - - The reserve is calculated as the reserve base plus - the reserve increment times the number of increments. - */ - std::uint64_t - reserve (std::size_t ownerCount) const - { - return reserve_ + ownerCount * increment_; - } + fhIGNORE_FREEZE, + fhZERO_IF_FROZEN }; +Fees +getFees (BasicView const& view, + Config const& config); + bool isGlobalFrozen (BasicView const& view, AccountID const& issuer); diff --git a/src/ripple/ledger/ViewAPIBasics.h b/src/ripple/ledger/ViewAPIBasics.h deleted file mode 100644 index 77ecacad1..000000000 --- a/src/ripple/ledger/ViewAPIBasics.h +++ /dev/null @@ -1,33 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef RIPPLE_LEDGER_VIEWAPIBASICS_H_INCLUDED -#define RIPPLE_LEDGER_VIEWAPIBASICS_H_INCLUDED - -namespace ripple { - -enum FreezeHandling -{ - fhIGNORE_FREEZE, - fhZERO_IF_FROZEN -}; - -} // ripple - -#endif diff --git a/src/ripple/ledger/impl/CachedView.cpp b/src/ripple/ledger/impl/CachedView.cpp index 5dcd7c1f3..d3f0e412e 100644 --- a/src/ripple/ledger/impl/CachedView.cpp +++ b/src/ripple/ledger/impl/CachedView.cpp @@ -29,7 +29,7 @@ CachedView::read (Keylet const& k) const uint256 hash; // get hash since SLECache needs to know auto const item = - ledger_.stateMap().peekItem(k.key, hash); + view_.stateMap().peekItem(k.key, hash); if (! item) return nullptr; if (auto sle = cache_.fetch(hash)) diff --git a/src/ripple/ledger/impl/DeferredCredits.cpp b/src/ripple/ledger/impl/DeferredCredits.cpp index 3da5799ec..7f4e822cd 100644 --- a/src/ripple/ledger/impl/DeferredCredits.cpp +++ b/src/ripple/ledger/impl/DeferredCredits.cpp @@ -143,12 +143,12 @@ STAmount DeferredCredits::adjustedBalance (AccountID const& main, } void DeferredCredits::apply( - DeferredCredits const& child) + DeferredCredits& to) { - for (auto& p : child.map_) + for (auto& p : map_) { auto r = - map_.emplace(p); + to.map_.emplace(p); if (! r.second) { using std::get; @@ -163,16 +163,5 @@ 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 diff --git a/src/ripple/ledger/impl/View.cpp b/src/ripple/ledger/impl/View.cpp index 012380d17..f34fcb461 100644 --- a/src/ripple/ledger/impl/View.cpp +++ b/src/ripple/ledger/impl/View.cpp @@ -39,28 +39,34 @@ namespace ripple { // //------------------------------------------------------------------------------ -Fees::Fees (BasicView const& view, Config const& config) - : base_(config.FEE_DEFAULT) - , units_(config.TRANSACTION_FEE_BASE) - , reserve_(config.FEE_ACCOUNT_RESERVE) - , increment_(config.FEE_OWNER_RESERVE) +Fees +getFees (BasicView const& view, + Config const& config) { - auto const sle = view.read(keylet::fees()); + Fees f; + f.base = config.FEE_DEFAULT; + f.units = config.TRANSACTION_FEE_BASE; + f.reserve = config.FEE_ACCOUNT_RESERVE; + f.increment = config.FEE_OWNER_RESERVE; + auto const sle = + view.read(keylet::fees()); if (sle) { // VFALCO NOTE Why getFieldIndex and not isFieldPresent? + if (sle->getFieldIndex (sfBaseFee) != -1) - base_ = sle->getFieldU64 (sfBaseFee); + f.base = sle->getFieldU64 (sfBaseFee); if (sle->getFieldIndex (sfReferenceFeeUnits) != -1) - units_ = sle->getFieldU32 (sfReferenceFeeUnits); + f.units = sle->getFieldU32 (sfReferenceFeeUnits); if (sle->getFieldIndex (sfReserveBase) != -1) - reserve_ = sle->getFieldU32 (sfReserveBase); + f.reserve = sle->getFieldU32 (sfReserveBase); if (sle->getFieldIndex (sfReserveIncrement) != -1) - increment_ = sle->getFieldU32 (sfReserveIncrement); + f.increment = sle->getFieldU32 (sfReserveIncrement); } + return f; } //------------------------------------------------------------------------------ @@ -114,12 +120,12 @@ accountHolds (BasicView const& view, STAmount amount; if (isXRP(currency)) { - Fees const fees{view, config}; // XRP: return balance minus reserve auto const sle = view.read( keylet::account(account)); - auto const reserve = STAmount{fees.reserve( - sle->getFieldU32(sfOwnerCount))}; + auto const reserve = + STAmount{view.fees().accountReserve( + sle->getFieldU32(sfOwnerCount))}; auto const balance = sle->getFieldAmount(sfBalance); if (balance < reserve) @@ -1234,7 +1240,7 @@ accountSend (View& view, { // VFALCO Its laborious to have to mutate the // TER based on params everywhere - terResult = view.openLedger() + terResult = (view.flags() & tapOPEN_LEDGER) ? telFAILED_PROCESSING : tecFAILED_PROCESSING; } @@ -1491,7 +1497,7 @@ transferXRP (View& view, // VFALCO Its unfortunate we have to keep // mutating these TER everywhere // FIXME: this logic should be moved to callers maybe? - return view.openLedger() + return (view.flags() & tapOPEN_LEDGER) ? telFAILED_PROCESSING : tecFAILED_PROCESSING; } diff --git a/src/ripple/rpc/handlers/NoRippleCheck.cpp b/src/ripple/rpc/handlers/NoRippleCheck.cpp index 967e9031c..96dd5b32d 100644 --- a/src/ripple/rpc/handlers/NoRippleCheck.cpp +++ b/src/ripple/rpc/handlers/NoRippleCheck.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -35,8 +34,10 @@ static void fillTransaction ( { txArray["Sequence"] = Json::UInt (sequence++); txArray["Account"] = getApp().accountIDCache().toBase58 (accountID); - txArray["Fee"] = Json::UInt (scaleFeeLoad ( - getApp().getFeeTrack(), *ledger, 10, false)); + // VFALCO Needs audit + // Why are we hard-coding 10? + txArray["Fee"] = Json::UInt (getApp().getFeeTrack().scaleFeeLoad( + 10, ledger->fees().base, ledger->fees().units, false)); } // { diff --git a/src/ripple/rpc/handlers/RipplePathFind.cpp b/src/ripple/rpc/handlers/RipplePathFind.cpp index 07d6ed389..ef4362c80 100644 --- a/src/ripple/rpc/handlers/RipplePathFind.cpp +++ b/src/ripple/rpc/handlers/RipplePathFind.cpp @@ -304,7 +304,7 @@ ripplePathFind (RippleLineCache::pointer const& cache, saMaxAmount.negate(); boost::optional sandbox; - sandbox.emplace(lpLedger, tapNONE); + sandbox.emplace(lpLedger.get(), tapOPEN_LEDGER); auto rc = path::RippleCalc::rippleCalculate( *sandbox, @@ -329,7 +329,7 @@ ripplePathFind (RippleLineCache::pointer const& cache, << "Trying with an extra path element"; spsComputed.push_back(fullLiquidityPath); - sandbox.emplace(lpLedger, tapNONE); + sandbox.emplace(lpLedger.get(), tapOPEN_LEDGER); rc = path::RippleCalc::rippleCalculate( *sandbox, saMaxAmount, // --> Amount to send is unlimited diff --git a/src/ripple/rpc/impl/TransactionSign.cpp b/src/ripple/rpc/impl/TransactionSign.cpp index 3653336b2..59bd462e4 100644 --- a/src/ripple/rpc/impl/TransactionSign.cpp +++ b/src/ripple/rpc/impl/TransactionSign.cpp @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -176,8 +175,9 @@ std::uint64_t TxnSignApiFacade::scaleFeeBase (std::uint64_t fee) const if (!ledger_) // Unit testing. return fee; - return ripple::scaleFeeBase( - getApp().getFeeTrack(), *ledger_, fee); + // VFALCO Audit + return getApp().getFeeTrack().scaleFeeBase( + fee, ledger_->fees().base, ledger_->fees().units); } std::uint64_t @@ -186,9 +186,10 @@ TxnSignApiFacade::scaleFeeLoad (std::uint64_t fee, bool bAdmin) const if (!ledger_) // Unit testing. return fee; - return ripple::scaleFeeLoad ( - getApp().getFeeTrack(), - *ledger_, fee, bAdmin); + // VFALCO Audit + return getApp().getFeeTrack().scaleFeeLoad( + fee, ledger_->fees().base, ledger_->fees().units, + bAdmin); } bool TxnSignApiFacade::hasAccountRoot () const diff --git a/src/ripple/test/jtx/impl/Env.cpp b/src/ripple/test/jtx/impl/Env.cpp index e121d6b6b..7d34f7588 100644 --- a/src/ripple/test/jtx/impl/Env.cpp +++ b/src/ripple/test/jtx/impl/Env.cpp @@ -197,11 +197,12 @@ Env::submit (JTx const& jt) bool didApply; if (stx) { - TransactionEngine txe (ledger, - tx_enable_test); - std::tie(ter, didApply) = txe.applyTransaction( - *stx, tapOPEN_LEDGER | - (true ? tapNONE : tapNO_CHECK_SIGN)); + ViewFlags flags = tapNONE; + flags = flags | tapOPEN_LEDGER; + flags = flags | tapENABLE_TESTING; + TransactionEngine txe (ledger); + std::tie(ter, didApply) = + txe.applyTransaction(*stx, flags); } else { diff --git a/src/ripple/unity/app_ledger.cpp b/src/ripple/unity/app_ledger.cpp index 632f5475e..b3eec1cd3 100644 --- a/src/ripple/unity/app_ledger.cpp +++ b/src/ripple/unity/app_ledger.cpp @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include