Refine View interfaces:

This shores up the View interface support for contextual
transaction processing by putting params in the View, and
provides support for replacing the open ledger with the
open MetaView.

Transaction metadata is now part of the View interface.
Stacked MetaViews correctly apply their transaction
metadata to the parent.

* Add lastCloseTime to View
* Add insertTx to View, implement in MetaView
* Add View::txExists for transaction checking
* Add Fees to View, cache fees in Ledger and MetaView
* Use ViewFlags in View
* Use tapENABLE_TESTING flag for features
* Use cached Fees in View
* Rename to ViewFlags
* Move FreezeHandling to View.h, remove ViewAPIBasics.h
* Remove BasicView::parent hack
* Remove calls to getLedger in Transactors
This commit is contained in:
Vinnie Falco
2015-06-25 12:29:48 -07:00
committed by Nik Bougalis
parent 2fc8d70655
commit 57689c4e66
53 changed files with 1046 additions and 753 deletions

View File

@@ -1397,10 +1397,6 @@
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\impl\LedgerConsensusImp.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerFees.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerMaster.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -1425,8 +1421,6 @@
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerConsensus.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerFees.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\LedgerHistory.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -2287,8 +2281,6 @@
</ClInclude>
<ClInclude Include="..\..\src\ripple\ledger\View.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\ledger\ViewAPIBasics.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\net\HTTPClient.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\net\HTTPRequest.h">

View File

@@ -2136,9 +2136,6 @@
<ClInclude Include="..\..\src\ripple\app\ledger\impl\LedgerConsensusImp.h">
<Filter>ripple\app\ledger\impl</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerFees.cpp">
<Filter>ripple\app\ledger\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\LedgerMaster.cpp">
<Filter>ripple\app\ledger\impl</Filter>
</ClCompile>
@@ -2163,9 +2160,6 @@
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerConsensus.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\ledger\LedgerFees.h">
<Filter>ripple\app\ledger</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\LedgerHistory.cpp">
<Filter>ripple\app\ledger</Filter>
</ClCompile>
@@ -2997,9 +2991,6 @@
<ClInclude Include="..\..\src\ripple\ledger\View.h">
<Filter>ripple\ledger</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\ledger\ViewAPIBasics.h">
<Filter>ripple\ledger</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\net\HTTPClient.h">
<Filter>ripple\net</Filter>
</ClInclude>

View File

@@ -91,6 +91,8 @@ Ledger::Ledger (RippleAddress const& masterPublicKey,
getApp().family(), deprecatedLogs().journal("SHAMap")))
, stateMap_ (std::make_shared <SHAMap> (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 <SHAMap> (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 <SHAMap> (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 <SHAMap> (
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<Serializer const> const& txn,
std::shared_ptr<Serializer const> 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<uint256>
Ledger::txList() const
{
std::vector<uint256> list;
for (auto const& item : *txMap_)
{
list.push_back(item->key());
}
return list;
}
std::shared_ptr<SLE>
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<Ledger const*>(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

View File

@@ -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>&& 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<Serializer const
> const& txn, std::shared_ptr<
Serializer const> const& metaData) override;
std::vector<uint256>
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

View File

@@ -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 <ripple/app/ledger/Ledger.h>
#include <ripple/core/LoadFeeTrack.h>
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

View File

@@ -20,39 +20,21 @@
#ifndef RIPPLE_LEDGER_METAVIEW_H_INCLUDED
#define RIPPLE_LEDGER_METAVIEW_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/tx/TransactionMeta.h>
#include <ripple/ledger/View.h>
#include <ripple/basics/CountedObject.h>
#include <ripple/ledger/ViewAPIBasics.h>
#include <ripple/basics/UnorderedContainers.h>
#include <ripple/protocol/Keylet.h>
#include <ripple/protocol/Serializer.h>
#include <ripple/protocol/STLedgerEntry.h>
#include <beast/utility/noexcept.h>
#include <boost/optional.hpp>
#include <list>
#include <tuple>
#include <utility>
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<uint256,
std::shared_ptr<SLE>>;
using list_type = std::map<uint256, Item>;
// The SLEs and Serializers in here are
// shared between copy-constructed instances
using item_list = std::map<uint256, Item>;
using tx_list = hardened_hash_map<
uint256, std::pair<std::shared_ptr<
Serializer const>, 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<uint256
> 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>&& sle) override;
BasicView const*
parent() const override
{
return parent_;
}
void
destroyCoins (std::uint64_t feeDrops) override;
//---------------------------------------------
bool
txExists (uint256 const& key) const override;
bool
txInsert (uint256 const& key,
std::shared_ptr<Serializer const
> const& txn, std::shared_ptr<
Serializer const> const& metaData) override;
std::vector<uint256>
txList() const override;
//--------------------------------------------------------------------------
//
// view
//
//--------------------------------------------------------------------------
ViewFlags
flags() const override
{
return flags_;
}
std::shared_ptr<SLE>
peek (Keylet const& k) override;
@@ -150,14 +249,19 @@ public:
void
update (std::shared_ptr<SLE> 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:

View File

@@ -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<STTx const> 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<TransactionEngineParams> (parms | tapRETRY);
parms = static_cast<ViewFlags> (parms | tapRETRY);
}
if ((getApp().getHashRouter ().getFlags (txn->getTransactionID ())
& SF_SIGGOOD) == SF_SIGGOOD)
{
parms = static_cast<TransactionEngineParams>
parms = static_cast<ViewFlags>
(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

View File

@@ -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 <BeastConfig.h>
#include <ripple/app/ledger/LedgerFees.h>
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

View File

@@ -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<TransactionEngineParams> (tepFlags | tapNO_CHECK_SIGN);
tepFlags = static_cast<ViewFlags> (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 ()

View File

@@ -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<uint256> last) const
{
boost::optional<uint256> 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>&& 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<Serializer const> const& txn,
std::shared_ptr<Serializer const> 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<uint256>
MetaView::txList() const
{
std::vector<uint256> list;
list.reserve(txs_.size());
for (auto const& e : txs_)
list.push_back(e.first);
return list;
}
std::shared_ptr<SLE>
MetaView::peek (Keylet const& k)
{
@@ -361,17 +402,11 @@ MetaView::update (std::shared_ptr<SLE> 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

View File

@@ -21,6 +21,7 @@
#include <ripple/test/jtx.h>
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/ledger/MetaView.h>
#include <ripple/app/paths/impl/PaymentView.h>
#include <beast/cxx14/type_traits.h> // <type_traits>
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,26 +303,71 @@ class MetaView_test
expect(! v0.exists(k(4)));
}
// Regression test:
// Verify contextual information
void
testContext()
{
using namespace jtx;
{
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.
void
testStackRegress()
{
using namespace jtx;
Env env(*this);
wipe(*env.ledger);
BasicView& v0 = *env.ledger;
v0.unchecked_insert(sle(1));
MetaView v1(v0, true);
MetaView v1(&v0, tapNONE);
{
MetaView v2(v1, true);
MetaView v2(&v1);
v2.erase(v2.peek(k(1)));
v2.apply();
v2.apply(v1);
}
expect(! v1.exists(k(1)));
}
}
void run()
{
@@ -332,7 +378,9 @@ class MetaView_test
testMeta();
testMetaSucc();
testStacked();
testStackRegress();
testContext();
testRegressions();
}
};

View File

@@ -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<Serializer const>(std::move(s)),
nullptr))
if (m_journal.warning) m_journal.warning <<
"Unable to add transaction " << item->getTag();
getApp().getHashRouter().setFlag (item->getTag(), SF_SIGGOOD);

View File

@@ -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<STTx const> const& txn)
{
uint256 effectiveAccount = mSetHash;

View File

@@ -71,8 +71,8 @@ public:
std::uint32_t mSeq;
};
using iterator = std::map <Key, STTx::pointer>::iterator;
using const_iterator = std::map <Key, STTx::pointer>::const_iterator;
using iterator = std::map <Key, std::shared_ptr<STTx const>>::iterator;
using const_iterator = std::map <Key, std::shared_ptr<STTx const>>::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<STTx const> 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 <Key, STTx::pointer> mMap;
std::map <Key, std::shared_ptr<STTx const>> mMap;
};
} // ripple

View File

@@ -525,7 +525,8 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
if (valid)
{
boost::optional<PaymentView> 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,

View File

@@ -20,6 +20,7 @@
#ifndef RIPPLE_APP_PATHS_PATHREQUEST_H_INCLUDED
#define RIPPLE_APP_PATHS_PATHREQUEST_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/paths/RippleLineCache.h>
#include <ripple/json/json_value.h>
#include <ripple/net/InfoSub.h>

View File

@@ -36,7 +36,7 @@ class PathState : public CountedObject <PathState>
using Ptr = std::shared_ptr<PathState>;
using List = std::vector<Ptr>;
PathState (PaymentView& parent,
PathState (PaymentView const& parent,
STAmount const& saSend,
STAmount const& saSendMax)
: mIndex (0)
@@ -110,7 +110,7 @@ class PathState : public CountedObject <PathState>
return *view_;
}
void resetView (PaymentView& view)
void resetView (PaymentView const& view)
{
view_.emplace(&view);
}

View File

@@ -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;

View File

@@ -20,6 +20,7 @@
#ifndef RIPPLE_APP_PATHS_PATHFINDER_H_INCLUDED
#define RIPPLE_APP_PATHS_PATHFINDER_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/paths/RippleLineCache.h>
#include <ripple/core/LoadEvent.h>
#include <ripple/protocol/STAmount.h>

View File

@@ -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();

View File

@@ -20,6 +20,7 @@
#ifndef RIPPLE_APP_PATHS_RIPPLELINECACHE_H_INCLUDED
#define RIPPLE_APP_PATHS_RIPPLELINECACHE_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/paths/RippleState.h>
#include <ripple/basics/hardened_hash.h>
#include <cstddef>

View File

@@ -20,6 +20,7 @@
#ifndef RIPPLE_APP_PATHS_RIPPLESTATE_H_INCLUDED
#define RIPPLE_APP_PATHS_RIPPLESTATE_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/ledger/MetaView.h>
#include <ripple/protocol/STAmount.h>
#include <ripple/protocol/STLedgerEntry.h>

View File

@@ -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)

View File

@@ -19,6 +19,7 @@
#include <BeastConfig.h>
#include <ripple/app/paths/impl/PaymentView.h>
#include <cassert>
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

View File

@@ -23,8 +23,8 @@
#include <ripple/core/Config.h>
#include <ripple/app/ledger/MetaView.h>
#include <ripple/ledger/View.h>
#include <ripple/ledger/ViewAPIBasics.h>
#include <ripple/ledger/DeferredCredits.h>
#include <beast/cxx14/type_traits.h> // <type_traits>
#include <utility>
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<MetaView>
{
private:
MetaView view_;
DeferredCredits tab_;
PaymentView* pv_ = nullptr;
PaymentView const* pv_ = nullptr;
public:
PaymentView (PaymentView const&) = delete;
@@ -54,7 +53,7 @@ public:
template <class... Args>
explicit
PaymentView (Args&&... args)
: view_ (std::forward<Args>(args)...)
: ViewWrapper (std::forward<Args>(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<uint256>
succ (uint256 const& key,
boost::optional<uint256> last =
boost::none) const override
{
return view_.succ(key, last);
}
std::shared_ptr<SLE const>
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>&& sle) override
{
view_.unchecked_insert(
std::move(sle));
}
void
unchecked_replace (
std::shared_ptr<SLE>&& sle) override
{
view_.unchecked_replace(
std::move(sle));
}
BasicView const*
parent() const override
{
return &view_;
}
//---------------------------------------------
std::shared_ptr<SLE>
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);
}
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

View File

@@ -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<MetaView> 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<TER, bool>
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<TransactionEngineParams> (static_cast<int> (l1) | static_cast<int> (l2));
return static_cast<ViewFlags> (static_cast<int> (l1) | static_cast<int> (l2));
}
inline TransactionEngineParams operator& (const TransactionEngineParams& l1, const TransactionEngineParams& l2)
inline ViewFlags operator& (const ViewFlags& l1, const ViewFlags& l2)
{
return static_cast<TransactionEngineParams> (static_cast<int> (l1) & static_cast<int> (l2));
return static_cast<ViewFlags> (static_cast<int> (l1) & static_cast<int> (l2));
}
} // ripple

View File

@@ -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 ();

View File

@@ -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();
}

View File

@@ -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 ();

View File

@@ -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;

View File

@@ -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 ();
}

View File

@@ -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,

View File

@@ -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 ();

View File

@@ -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 ();

View File

@@ -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 ();

View File

@@ -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 ();
}

View File

@@ -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 ();

View File

@@ -34,7 +34,7 @@ namespace ripple {
std::pair<TER, bool>
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<Serializer const>(std::move(s)),
std::make_shared<Serializer const>(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.

View File

@@ -18,31 +18,31 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/ledger/LedgerFees.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/tx/impl/Transactor.h>
#include <ripple/app/tx/impl/SignerEntries.h>
#include <ripple/core/Config.h>
#include <ripple/core/LoadFeeTrack.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/protocol/types.h>
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 ())

View File

@@ -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 ());

View File

@@ -107,7 +107,7 @@ std::pair<TER, bool> 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};

View File

@@ -26,10 +26,9 @@
namespace ripple {
/** Cache-aware view to a ledger */
class CachedView : public BasicView
class CachedView : public BasicViewWrapper<Ledger&>
{
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<uint256>
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<SLE const>
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>&& sle) override
{
ledger_.unchecked_insert(
std::move(sle));
}
void
unchecked_replace (
std::shared_ptr<SLE>&& sle) override
{
ledger_.unchecked_replace(
std::move(sle));
}
};
} // ripple

View File

@@ -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<Key, Value>::iterator begin() { return map_.begin(); }
std::map<Key, Value>::iterator end() { return map_.end(); }
void merge (std::pair <Key, Value> const& p);
};
} // ripple

View File

@@ -20,16 +20,51 @@
#ifndef RIPPLE_LEDGER_VIEW_H_INCLUDED
#define RIPPLE_LEDGER_VIEW_H_INCLUDED
#include <ripple/protocol/Protocol.h>
#include <ripple/protocol/Serializer.h>
#include <ripple/protocol/STLedgerEntry.h>
#include <ripple/protocol/TER.h>
#include <ripple/core/Config.h>
#include <ripple/ledger/View.h>
#include <ripple/ledger/ViewAPIBasics.h>
#include <functional>
#include <boost/optional.hpp>
#include <functional>
#include <memory>
#include <utility>
#include <vector>
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<SLE const>;
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>&& 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<Serializer const> const& txn,
std::shared_ptr<Serializer const> const& metaData) = 0;
// DEBUG ROUTINE
// Return a list of transaction keys in the tx map.
virtual
std::vector<uint256>
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 Member>
class BasicViewWrapper : public BasicView
{
protected:
Member view_;
public:
template <class... Args>
explicit
BasicViewWrapper (Args&&... args)
: view_(std::forward<Args>(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<uint256>
succ (uint256 const& key, boost::optional<
uint256> last = boost::none) const override
{
return view_.succ(key, last);
}
std::shared_ptr<SLE const>
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>&& sle) override
{
return view_.unchecked_insert(
std::move(sle));
}
void
unchecked_replace(
std::shared_ptr<SLE>&& 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<Serializer const
> const& txn, std::shared_ptr<
Serializer const> const& metaData) override
{
return view_.txInsert(
key, txn, metaData);
}
std::vector<uint256>
txList() const override
{
return view_.txList();
}
};
// Wrapper to facilitate subclasses,
// forwards all non-overriden virtuals.
//
template <class Member>
class ViewWrapper : public View
{
protected:
Member view_;
public:
template <class... Args>
explicit
ViewWrapper (Args&&... args)
: view_(std::forward<Args>(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<uint256>
succ (uint256 const& key, boost::optional<
uint256> last = boost::none) const override
{
return view_.succ(key, last);
}
std::shared_ptr<SLE const>
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>&& sle) override
{
return view_.unchecked_insert(
std::move(sle));
}
void
unchecked_replace(
std::shared_ptr<SLE>&& 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<Serializer const
> const& txn, std::shared_ptr<
Serializer const> const& metaData) override
{
return view_.txInsert(
key, txn, metaData);
}
std::vector<uint256>
txList() const override
{
return view_.txList();
}
//-----
ViewFlags
flags() const override
{
return view_.flags();
}
std::shared_ptr<SLE>
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);

View File

@@ -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

View File

@@ -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))

View File

@@ -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 <Key, Value> 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

View File

@@ -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,11 +120,11 @@ 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(
auto const reserve =
STAmount{view.fees().accountReserve(
sle->getFieldU32(sfOwnerCount))};
auto const balance =
sle->getFieldAmount(sfBalance);
@@ -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;
}

View File

@@ -20,7 +20,6 @@
#include <BeastConfig.h>
#include <ripple/app/main/Application.h>
#include <ripple/rpc/impl/Tuning.h>
#include <ripple/app/ledger/LedgerFees.h>
#include <ripple/ledger/CachedView.h>
#include <ripple/app/paths/RippleState.h>
#include <ripple/protocol/TxFlags.h>
@@ -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));
}
// {

View File

@@ -304,7 +304,7 @@ ripplePathFind (RippleLineCache::pointer const& cache,
saMaxAmount.negate();
boost::optional<PaymentView> 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

View File

@@ -19,7 +19,6 @@
#include <BeastConfig.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/ledger/LedgerFees.h>
#include <ripple/rpc/impl/TransactionSign.h>
#include <ripple/rpc/impl/KeypairForSignature.h>
#include <ripple/app/paths/FindPaths.h>
@@ -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

View File

@@ -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
{

View File

@@ -36,7 +36,6 @@
#include <ripple/app/ledger/impl/InboundLedgers.cpp>
#include <ripple/app/ledger/impl/LedgerCleaner.cpp>
#include <ripple/app/ledger/impl/LedgerConsensusImp.cpp>
#include <ripple/app/ledger/impl/LedgerFees.cpp>
#include <ripple/app/ledger/impl/LedgerMaster.cpp>
#include <ripple/app/ledger/impl/LedgerTiming.cpp>
#include <ripple/app/ledger/impl/MetaView.cpp>