diff --git a/Builds/VisualStudio2015/RippleD.vcxproj b/Builds/VisualStudio2015/RippleD.vcxproj
index 97deae1369..34a50db41f 100644
--- a/Builds/VisualStudio2015/RippleD.vcxproj
+++ b/Builds/VisualStudio2015/RippleD.vcxproj
@@ -1001,6 +1001,12 @@
True
True
+
+ True
+ True
+
+
+
True
True
diff --git a/Builds/VisualStudio2015/RippleD.vcxproj.filters b/Builds/VisualStudio2015/RippleD.vcxproj.filters
index c215923e99..8c90529468 100644
--- a/Builds/VisualStudio2015/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2015/RippleD.vcxproj.filters
@@ -1482,6 +1482,12 @@
ripple\app\paths\cursor
+
+ ripple\app\paths\cursor
+
+
+ ripple\app\paths\cursor
+
ripple\app\paths\cursor
diff --git a/src/ripple/app/misc/NetworkOPs.cpp b/src/ripple/app/misc/NetworkOPs.cpp
index e32edc923e..55822e1e91 100644
--- a/src/ripple/app/misc/NetworkOPs.cpp
+++ b/src/ripple/app/misc/NetworkOPs.cpp
@@ -65,6 +65,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -2851,7 +2852,7 @@ void NetworkOPsImp::getBookPage (
unsigned int uBookEntry;
STAmount saDirRate;
- auto uTransferRate = rippleTransferRate(view, book.out.account);
+ auto const rate = transferRate(view, book.out.account);
auto viewJ = app_.journal ("View");
unsigned int left (iLimit == 0 ? 300 : iLimit);
@@ -2948,12 +2949,11 @@ void NetworkOPsImp::getBookPage (
Json::Value jvOffer = sleOffer->getJson (0);
- STAmount saTakerGetsFunded;
- STAmount saOwnerFundsLimit;
- std::uint32_t uOfferRate;
+ STAmount saTakerGetsFunded;
+ STAmount saOwnerFundsLimit = saOwnerFunds;
+ Rate offerRate = parityRate;
-
- if (uTransferRate != QUALITY_ONE
+ if (rate != parityRate
// Have a tranfer fee.
&& uTakerID != book.out.account
// Not taking offers of own IOUs.
@@ -2961,16 +2961,9 @@ void NetworkOPsImp::getBookPage (
// Offer owner not issuing ownfunds
{
// Need to charge a transfer fee to offer owner.
- uOfferRate = uTransferRate;
- saOwnerFundsLimit = divide (
- saOwnerFunds,
- amountFromRate (uOfferRate),
- saOwnerFunds.issue ());
- }
- else
- {
- uOfferRate = QUALITY_ONE;
- saOwnerFundsLimit = saOwnerFunds;
+ offerRate = rate;
+ saOwnerFundsLimit = divide (
+ saOwnerFunds, offerRate);
}
if (saOwnerFundsLimit >= saTakerGets)
@@ -2982,7 +2975,7 @@ void NetworkOPsImp::getBookPage (
{
// Only provide, if not fully funded.
- saTakerGetsFunded = saOwnerFundsLimit;
+ saTakerGetsFunded = saOwnerFundsLimit;
saTakerGetsFunded.setJson (jvOffer[jss::taker_gets_funded]);
std::min (
@@ -2991,14 +2984,11 @@ void NetworkOPsImp::getBookPage (
(jvOffer[jss::taker_pays_funded]);
}
- STAmount saOwnerPays = (QUALITY_ONE == uOfferRate)
+ STAmount saOwnerPays = (parityRate == offerRate)
? saTakerGetsFunded
: std::min (
saOwnerFunds,
- multiply (
- saTakerGetsFunded,
- amountFromRate (uOfferRate),
- saTakerGetsFunded.issue ()));
+ multiply (saTakerGetsFunded, offerRate));
umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
@@ -3055,7 +3045,7 @@ void NetworkOPsImp::getBookPage (
MetaView lesActive (lpLedger, tapNONE, true);
OrderBookIterator obIterator (lesActive, book);
- auto uTransferRate = rippleTransferRate (lesActive, book.out.account);
+ auto const rate = transferRate(lesActive, book.out.account);
const bool bGlobalFreeze = lesActive.isGlobalFrozen (book.out.account) ||
lesActive.isGlobalFrozen (book.in.account);
@@ -3115,12 +3105,11 @@ void NetworkOPsImp::getBookPage (
Json::Value jvOffer = sleOffer->getJson (0);
- STAmount saTakerGetsFunded;
- STAmount saOwnerFundsLimit;
- std::uint32_t uOfferRate;
+ STAmount saTakerGetsFunded;
+ STAmount saOwnerFundsLimit = saOwnerFunds;
+ Rate offerRate = parityRate;
-
- if (uTransferRate != QUALITY_ONE
+ if (rate != parityRate
// Have a tranfer fee.
&& uTakerID != book.out.account
// Not taking offers of own IOUs.
@@ -3128,14 +3117,8 @@ void NetworkOPsImp::getBookPage (
// Offer owner not issuing ownfunds
{
// Need to charge a transfer fee to offer owner.
- uOfferRate = uTransferRate;
- saOwnerFundsLimit = divide (saOwnerFunds,
- amountFromRate (uOfferRate));
- }
- else
- {
- uOfferRate = QUALITY_ONE;
- saOwnerFundsLimit = saOwnerFunds;
+ offerRate = rate;
+ saOwnerFundsLimit = divide (saOwnerFunds, offerRate);
}
if (saOwnerFundsLimit >= saTakerGets)
@@ -3157,11 +3140,11 @@ void NetworkOPsImp::getBookPage (
jvOffer[jss::taker_pays_funded]);
}
- STAmount saOwnerPays = (uOfferRate == QUALITY_ONE)
+ STAmount saOwnerPays = (parityRate == offerRate)
? saTakerGetsFunded
: std::min (
saOwnerFunds,
- multiply (saTakerGetsFunded, amountFromRate (uOfferRate)));
+ multiply (saTakerGetsFunded, offerRate));
umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
diff --git a/src/ripple/app/paths/Node.h b/src/ripple/app/paths/Node.h
index efd32de808..2c56420f7a 100644
--- a/src/ripple/app/paths/Node.h
+++ b/src/ripple/app/paths/Node.h
@@ -22,7 +22,9 @@
#include
#include
+#include
#include
+#include
namespace ripple {
namespace path {
@@ -42,12 +44,12 @@ struct Node
std::uint16_t uFlags; // --> From path.
- AccountID account_; // --> Accounts: Receiving/sending account.
+ AccountID account_; // --> Accounts: Receiving/sending account.
Issue issue_; // --> Accounts: Receive and send, Offers: send.
// --- For offer's next has currency out.
- STAmount transferRate_; // Transfer rate for issuer.
+ boost::optional transferRate_; // Transfer rate for issuer.
// Computed by Reverse.
STAmount saRevRedeem; // <-- Amount to redeem to next.
@@ -65,8 +67,7 @@ struct Node
// fee.
// For offers:
-
- STAmount saRateMax;
+ boost::optional rateMax;
// The nodes are partitioned into a buckets called "directories".
//
diff --git a/src/ripple/app/paths/PathState.cpp b/src/ripple/app/paths/PathState.cpp
index 2bcb32d259..f42f1f5c24 100644
--- a/src/ripple/app/paths/PathState.cpp
+++ b/src/ripple/app/paths/PathState.cpp
@@ -366,7 +366,6 @@ TER PathState::pushNode (
else
node.issue_.account = backNode.issue_.account;
- node.saRateMax = STAmount::saZero;
node.saRevDeliver = STAmount (node.issue_);
node.saFwdDeliver = node.saRevDeliver;
diff --git a/src/ripple/app/paths/RippleCalc.cpp b/src/ripple/app/paths/RippleCalc.cpp
index 8e5b26cade..98646629e8 100644
--- a/src/ripple/app/paths/RippleCalc.cpp
+++ b/src/ripple/app/paths/RippleCalc.cpp
@@ -366,7 +366,7 @@ TER RippleCalc::rippleCalculate (detail::FlowDebugInfo* flowDebugInfo)
<< "rippleCalc: AFTER:"
<< " mIndex=" << pathState->index()
<< " uQuality=" << pathState->quality()
- << " rate=" << amountFromRate (pathState->quality());
+ << " rate=" << amountFromQuality (pathState->quality());
if (flowDebugInfo)
flowDebugInfo->pushLiquiditySrc (
@@ -399,7 +399,7 @@ TER RippleCalc::rippleCalculate (detail::FlowDebugInfo* flowDebugInfo)
JLOG (j_.debug())
<< "rippleCalc: better:"
<< " uQuality="
- << amountFromRate (pathState->quality())
+ << amountFromQuality (pathState->quality())
<< " inPass()=" << pathState->inPass()
<< " saOutPass=" << pathState->outPass();
}
@@ -427,7 +427,7 @@ TER RippleCalc::rippleCalculate (detail::FlowDebugInfo* flowDebugInfo)
<< " mIndex=" << pathState->index()
<< " uQuality=" << pathState->quality()
<< " rate="
- << amountFromRate (pathState->quality())
+ << amountFromQuality (pathState->quality())
<< " inPass()=" << pathState->inPass()
<< " saOutPass=" << pathState->outPass();
@@ -452,7 +452,7 @@ TER RippleCalc::rippleCalculate (detail::FlowDebugInfo* flowDebugInfo)
<< "rippleCalc: "
<< "Summary: " << pathState->index()
<< " rate: "
- << amountFromRate (pathState->quality())
+ << amountFromQuality (pathState->quality())
<< " quality:" << pathState->quality()
<< " best: " << (iBest == pathState->index ());
}
@@ -470,7 +470,7 @@ TER RippleCalc::rippleCalculate (detail::FlowDebugInfo* flowDebugInfo)
JLOG (j_.debug ())
<< "rippleCalc: best:"
- << " uQuality=" << amountFromRate (pathState->quality ())
+ << " uQuality=" << amountFromQuality (pathState->quality ())
<< " inPass()=" << pathState->inPass ()
<< " saOutPass=" << pathState->outPass () << " iBest=" << iBest;
@@ -490,7 +490,7 @@ TER RippleCalc::rippleCalculate (detail::FlowDebugInfo* flowDebugInfo)
JLOG (j_.trace())
<< "rippleCalc: best:"
<< " uQuality="
- << amountFromRate (pathState->quality())
+ << amountFromQuality (pathState->quality())
<< " inPass()=" << pathState->inPass()
<< " saOutPass=" << pathState->outPass()
<< " actualIn=" << actualAmountIn_
diff --git a/src/ripple/app/paths/RippleState.cpp b/src/ripple/app/paths/RippleState.cpp
index d6d2eaf0eb..562569fc2b 100644
--- a/src/ripple/app/paths/RippleState.cpp
+++ b/src/ripple/app/paths/RippleState.cpp
@@ -41,21 +41,18 @@ RippleState::makeItem (
RippleState::RippleState (
std::shared_ptr&& sle,
AccountID const& viewAccount)
- : mLedgerEntry (std::move(sle))
- , mLowLimit (mLedgerEntry->getFieldAmount (sfLowLimit))
- , mHighLimit (mLedgerEntry->getFieldAmount (sfHighLimit))
+ : sle_ (std::move(sle))
+ , mFlags (sle_->getFieldU32 (sfFlags))
+ , mLowLimit (sle_->getFieldAmount (sfLowLimit))
+ , mHighLimit (sle_->getFieldAmount (sfHighLimit))
, mLowID (mLowLimit.getIssuer ())
, mHighID (mHighLimit.getIssuer ())
- , mBalance (mLedgerEntry->getFieldAmount (sfBalance))
+ , lowQualityIn_ (sle_->getFieldU32 (sfLowQualityIn))
+ , lowQualityOut_ (sle_->getFieldU32 (sfLowQualityOut))
+ , highQualityIn_ (sle_->getFieldU32 (sfHighQualityIn))
+ , highQualityOut_ (sle_->getFieldU32 (sfHighQualityOut))
+ , mBalance (sle_->getFieldAmount (sfBalance))
{
- mFlags = mLedgerEntry->getFieldU32 (sfFlags);
-
- mLowQualityIn = mLedgerEntry->getFieldU32 (sfLowQualityIn);
- mLowQualityOut = mLedgerEntry->getFieldU32 (sfLowQualityOut);
-
- mHighQualityIn = mLedgerEntry->getFieldU32 (sfHighQualityIn);
- mHighQualityOut = mLedgerEntry->getFieldU32 (sfHighQualityOut);
-
mViewLowest = (mLowID == viewAccount);
if (!mViewLowest)
diff --git a/src/ripple/app/paths/RippleState.h b/src/ripple/app/paths/RippleState.h
index ec83aa6bdb..1166485402 100644
--- a/src/ripple/app/paths/RippleState.h
+++ b/src/ripple/app/paths/RippleState.h
@@ -21,6 +21,7 @@
#define RIPPLE_APP_PATHS_RIPPLESTATE_H_INCLUDED
#include
+#include
#include
#include
#include
@@ -58,7 +59,7 @@ public:
uint256
key() const
{
- return mLedgerEntry->getIndex();
+ return sle_->getIndex();
}
// VFALCO Take off the "get" from each function name
@@ -121,20 +122,22 @@ public:
return !mViewLowest ? mLowLimit : mHighLimit;
}
- std::uint32_t getQualityIn () const
+ Rate const&
+ getQualityIn () const
{
- return ((std::uint32_t) (mViewLowest ? mLowQualityIn : mHighQualityIn));
+ return mViewLowest ? lowQualityIn_ : highQualityIn_;
}
- std::uint32_t getQualityOut () const
+ Rate const&
+ getQualityOut () const
{
- return ((std::uint32_t) (mViewLowest ? mLowQualityOut : mHighQualityOut));
+ return mViewLowest ? lowQualityOut_ : highQualityOut_;
}
Json::Value getJson (int);
private:
- std::shared_ptr mLedgerEntry;
+ std::shared_ptr sle_;
bool mViewLowest;
@@ -146,10 +149,10 @@ private:
AccountID const& mLowID;
AccountID const& mHighID;
- std::uint64_t mLowQualityIn;
- std::uint64_t mLowQualityOut;
- std::uint64_t mHighQualityIn;
- std::uint64_t mHighQualityOut;
+ Rate lowQualityIn_;
+ Rate lowQualityOut_;
+ Rate highQualityIn_;
+ Rate highQualityOut_;
STAmount mBalance;
};
diff --git a/src/ripple/app/paths/cursor/DeliverNodeForward.cpp b/src/ripple/app/paths/cursor/DeliverNodeForward.cpp
index 7e0c16f413..9a69610103 100644
--- a/src/ripple/app/paths/cursor/DeliverNodeForward.cpp
+++ b/src/ripple/app/paths/cursor/DeliverNodeForward.cpp
@@ -18,6 +18,7 @@
//==============================================================================
#include
+#include
#include
#include
@@ -82,14 +83,11 @@ TER PathCursor::deliverNodeForward (
}
else if (resultCode == tesSUCCESS)
{
- // Doesn't charge input. Input funds are in limbo.
- // There's no fee if we're transferring XRP, if the sender is the
- // issuer, or if the receiver is the issuer.
- bool noFee = isXRP (previousNode().issue_)
- || uInAccountID == previousNode().issue_.account
- || node().offerOwnerAccount_ == previousNode().issue_.account;
- const STAmount saInFeeRate = noFee ? STAmount::saOne
- : previousNode().transferRate_; // Transfer rate of issuer.
+ auto const xferRate = effectiveRate (
+ previousNode().issue_,
+ uInAccountID,
+ node().offerOwnerAccount_,
+ previousNode().transferRate_);
// First calculate assuming no output fees: saInPassAct,
// saInPassFees, saOutPassAct.
@@ -111,8 +109,8 @@ TER PathCursor::deliverNodeForward (
true);
// Offer maximum in with fees.
- auto saInTotal = mulRound (saInFunded, saInFeeRate,
- saInFunded.issue (), true);
+ auto saInTotal = multiplyRound (
+ saInFunded, xferRate, true);
auto saInRemaining = saInReq - saInAct - saInFees;
if (saInRemaining < zero)
@@ -123,8 +121,8 @@ TER PathCursor::deliverNodeForward (
// In without fees.
auto saInPassAct = std::min (
- node().saTakerPays, divRound (
- saInSum, saInFeeRate, saInSum.issue (), true));
+ node().saTakerPays,
+ divideRound (saInSum, xferRate, true));
// Out limited by in remaining.
auto outPass = divRound (
@@ -247,8 +245,8 @@ TER PathCursor::deliverNodeForward (
auto inPassAct = mulRound (
saOutPassAct, node().saOfrRate, saInReq.issue (), true);
saInPassAct = std::min (node().saTakerPays, inPassAct);
- auto inPassFees = mulRound (
- saInPassAct, saInFeeRate, saInPassAct.issue (), true);
+ auto inPassFees = multiplyRound (
+ saInPassAct, xferRate, true);
saInPassFees = std::min (saInPassFeesMax, inPassFees);
}
diff --git a/src/ripple/app/paths/cursor/DeliverNodeReverse.cpp b/src/ripple/app/paths/cursor/DeliverNodeReverse.cpp
index 4420db9f8a..efb67a639c 100644
--- a/src/ripple/app/paths/cursor/DeliverNodeReverse.cpp
+++ b/src/ripple/app/paths/cursor/DeliverNodeReverse.cpp
@@ -18,6 +18,7 @@
//==============================================================================
#include
+#include
#include
#include
@@ -81,66 +82,58 @@ TER PathCursor::deliverNodeReverseImpl (
// Error or out of offers.
break;
- auto const hasFee = node().offerOwnerAccount_ == node().issue_.account
- || uOutAccountID == node().issue_.account;
- // Issuer sending or receiving.
-
- const STAmount saOutFeeRate = hasFee
- ? STAmount::saOne // No fee.
- : node().transferRate_; // Transfer rate of issuer.
+ auto const xferRate = effectiveRate (
+ node().issue_,
+ uOutAccountID,
+ node().offerOwnerAccount_,
+ node().transferRate_);
JLOG (j_.trace())
<< "deliverNodeReverse:"
- << " offerOwnerAccount_="
- << node().offerOwnerAccount_
- << " uOutAccountID="
- << uOutAccountID
- << " node().issue_.account="
- << node().issue_.account
- << " node().transferRate_=" << node().transferRate_
- << " saOutFeeRate=" << saOutFeeRate;
+ << " offerOwnerAccount_=" << node().offerOwnerAccount_
+ << " uOutAccountID=" << uOutAccountID
+ << " node().issue_.account=" << node().issue_.account
+ << " xferRate=" << xferRate;
- if (multiQuality_)
+ // Only use rate when not in multi-quality mode
+ if (!multiQuality_)
{
- // In multi-quality mode, ignore rate.
- }
- else if (!node().saRateMax)
- {
- // Set initial rate.
- node().saRateMax = saOutFeeRate;
+ if (!node().rateMax)
+ {
+ // Set initial rate.
+ JLOG (j_.trace())
+ << "Set initial rate";
- JLOG (j_.trace())
- << "deliverNodeReverse: Set initial rate:"
- << " node().saRateMax=" << node().saRateMax
- << " saOutFeeRate=" << saOutFeeRate;
- }
- else if (saOutFeeRate > node().saRateMax)
- {
- // Offer exceeds initial rate.
- JLOG (j_.trace())
- << "deliverNodeReverse: Offer exceeds initial rate:"
- << " node().saRateMax=" << node().saRateMax
- << " saOutFeeRate=" << saOutFeeRate;
+ node().rateMax = xferRate;
+ }
+ else if (xferRate > node().rateMax)
+ {
+ // Offer exceeds initial rate.
+ JLOG (j_.trace())
+ << "Offer exceeds initial rate: " << *node().rateMax;
- break; // Done. Don't bother looking for smaller transferRates.
- }
- else if (saOutFeeRate < node().saRateMax)
- {
- // Reducing rate. Additional offers will only considered for this
- // increment if they are at least this good.
- //
- // At this point, the overall rate is reducing, while the overall
- // rate is not saOutFeeRate, it would be wrong to add anything with
- // a rate above saOutFeeRate.
- //
- // The rate would be reduced if the current offer was from the
- // issuer and the previous offer wasn't.
+ break; // Done. Don't bother looking for smaller transferRates.
+ }
+ else if (xferRate < node().rateMax)
+ {
+ // Reducing rate. Additional offers will only
+ // be considered for this increment if they
+ // are at least this good.
+ //
+ // At this point, the overall rate is reducing,
+ // while the overall rate is not xferRate, it
+ // would be wrong to add anything with a rate
+ // above xferRate.
+ //
+ // The rate would be reduced if the current
+ // offer was from the issuer and the previous
+ // offer wasn't.
- node().saRateMax = saOutFeeRate;
+ JLOG (j_.trace())
+ << "Reducing rate: " << *node().rateMax;
- JLOG (j_.trace())
- << "deliverNodeReverse: Reducing rate:"
- << " node().saRateMax=" << node().saRateMax;
+ node().rateMax = xferRate;
+ }
}
// Amount that goes to the taker.
@@ -157,8 +150,8 @@ TER PathCursor::deliverNodeReverseImpl (
// as a cost to taker.
//
// Round down: prefer liquidity rather than microscopic fees.
- STAmount saOutPlusFees = mulRound (
- saOutPassAct, saOutFeeRate, saOutPassAct.issue (), false);
+ STAmount saOutPlusFees = multiplyRound (
+ saOutPassAct, xferRate, false);
// Offer out with fees.
@@ -180,8 +173,7 @@ TER PathCursor::deliverNodeReverseImpl (
// Round up: prefer liquidity rather than microscopic fees. But,
// limit by requested.
- auto fee = divRound (saOutPlusFees, saOutFeeRate,
- saOutPlusFees.issue (), true);
+ auto fee = divideRound (saOutPlusFees, xferRate, true);
saOutPassAct = std::min (saOutPassReq, fee);
JLOG (j_.trace())
@@ -280,8 +272,7 @@ TER PathCursor::deliverNodeReverseImpl (
auto outputRequirements = divRound (saInPassAct, node ().saOfrRate,
node ().saTakerGets.issue (), true);
saOutPassAct = std::min (saOutPassReq, outputRequirements);
- auto outputFees = mulRound (saOutPassAct, saOutFeeRate,
- saOutPassAct.issue (), true);
+ auto outputFees = multiplyRound (saOutPassAct, xferRate, true);
saOutPlusFees = std::min (node().saOfferFunds, outputFees);
JLOG (j_.trace())
diff --git a/src/ripple/app/paths/cursor/EffectiveRate.cpp b/src/ripple/app/paths/cursor/EffectiveRate.cpp
new file mode 100644
index 0000000000..9f527c1690
--- /dev/null
+++ b/src/ripple/app/paths/cursor/EffectiveRate.cpp
@@ -0,0 +1,49 @@
+//------------------------------------------------------------------------------
+/*
+ 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
+#include
+
+namespace ripple {
+namespace path {
+
+Rate
+effectiveRate(
+ Issue const& issue,
+ AccountID const& account1,
+ AccountID const& account2,
+ boost::optional const& rate)
+{
+ // 1:1 transfer rate for XRP
+ if (isXRP (issue))
+ return parityRate;
+
+ if (!rate)
+ LogicError ("No transfer rate set for node.");
+
+ // 1:1 transfer rate if either of the accounts is the issuer
+ if (issue.account == account1 || issue.account == account2)
+ return parityRate;
+
+ return rate.get();
+}
+
+} // path
+} // ripple
diff --git a/src/ripple/app/paths/cursor/EffectiveRate.h b/src/ripple/app/paths/cursor/EffectiveRate.h
new file mode 100644
index 0000000000..21f4ef2fba
--- /dev/null
+++ b/src/ripple/app/paths/cursor/EffectiveRate.h
@@ -0,0 +1,41 @@
+//------------------------------------------------------------------------------
+/*
+ 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_PATHS_CURSOR_EFFECTIVERATE_H_INCLUDED
+#define RIPPLE_APP_PATHS_CURSOR_EFFECTIVERATE_H_INCLUDED
+
+#include
+#include
+#include
+#include
+
+namespace ripple {
+namespace path {
+
+Rate
+effectiveRate(
+ Issue const& issue,
+ AccountID const& account1,
+ AccountID const& account2,
+ boost::optional const& rate);
+
+} // path
+} // ripple
+
+#endif
diff --git a/src/ripple/app/paths/cursor/ForwardLiquidityForAccount.cpp b/src/ripple/app/paths/cursor/ForwardLiquidityForAccount.cpp
index d6cd5017fe..3225f1c8f5 100644
--- a/src/ripple/app/paths/cursor/ForwardLiquidityForAccount.cpp
+++ b/src/ripple/app/paths/cursor/ForwardLiquidityForAccount.cpp
@@ -55,18 +55,19 @@ TER PathCursor::forwardLiquidityForAccount () const
AccountID const& nextAccountID =
nextNode().isAccount() ? nextNode().account_ : node().account_;
- std::uint32_t uQualityIn = nodeIndex_
+ auto const qualityIn = nodeIndex_
? quality_in (view(),
node().account_,
previousAccountID,
node().issue_.currency)
- : QUALITY_ONE;
- std::uint32_t uQualityOut = (nodeIndex_ == lastNodeIndex)
+ : parityRate;
+
+ auto const qualityOut = (nodeIndex_ == lastNodeIndex)
? quality_out (view(),
node().account_,
nextAccountID,
node().issue_.currency)
- : QUALITY_ONE;
+ : parityRate;
// When looking backward (prv) for req we care about what we just
// calculated: use fwd.
@@ -153,12 +154,11 @@ TER PathCursor::forwardLiquidityForAccount () const
// Last node. Accept all funds. Calculate amount actually to credit.
auto& saCurReceive = pathState_.outPass();
- STAmount saIssueCrd = uQualityIn >= QUALITY_ONE
+ STAmount saIssueCrd = qualityIn >= parityRate
? previousNode().saFwdIssue // No fee.
- : mulRound (
+ : multiplyRound (
previousNode().saFwdIssue,
- amountFromRate (uQualityIn),
- previousNode().saFwdIssue.issue (),
+ qualityIn,
true); // Amount to credit.
// Amount to credit. Credit for less than received as a surcharge.
@@ -196,8 +196,8 @@ TER PathCursor::forwardLiquidityForAccount () const
// Rate : 1.0 : quality out
rippleLiquidity (
rippleCalc_,
- QUALITY_ONE,
- uQualityOut,
+ parityRate,
+ qualityOut,
previousNode().saFwdRedeem,
node().saRevRedeem,
saPrvRedeemAct,
@@ -214,8 +214,8 @@ TER PathCursor::forwardLiquidityForAccount () const
// Rate: quality in : quality out
rippleLiquidity (
rippleCalc_,
- uQualityIn,
- uQualityOut,
+ qualityIn,
+ qualityOut,
previousNode().saFwdIssue,
node().saRevRedeem,
saPrvIssueAct,
@@ -234,8 +234,8 @@ TER PathCursor::forwardLiquidityForAccount () const
// Rate : 1.0 : transfer_rate
rippleLiquidity (
rippleCalc_,
- QUALITY_ONE,
- rippleTransferRate (view(), node().account_),
+ parityRate,
+ transferRate (view(), node().account_),
previousNode().saFwdRedeem,
node().saRevIssue,
saPrvRedeemAct,
@@ -254,8 +254,8 @@ TER PathCursor::forwardLiquidityForAccount () const
// Rate: quality in : 1.0
rippleLiquidity (
rippleCalc_,
- uQualityIn,
- QUALITY_ONE,
+ qualityIn,
+ parityRate,
previousNode().saFwdIssue,
node().saRevIssue,
saPrvIssueAct,
@@ -303,8 +303,8 @@ TER PathCursor::forwardLiquidityForAccount () const
// XXX Is having the transfer rate here correct?
rippleLiquidity (
rippleCalc_,
- QUALITY_ONE,
- rippleTransferRate (view(), node().account_),
+ parityRate,
+ transferRate (view(), node().account_),
previousNode().saFwdRedeem,
node().saRevDeliver,
saPrvRedeemAct,
@@ -321,8 +321,8 @@ TER PathCursor::forwardLiquidityForAccount () const
// Rate: quality in : 1.0
rippleLiquidity (
rippleCalc_,
- uQualityIn,
- QUALITY_ONE,
+ qualityIn,
+ parityRate,
previousNode().saFwdIssue,
node().saRevDeliver,
saPrvIssueAct,
@@ -428,8 +428,8 @@ TER PathCursor::forwardLiquidityForAccount () const
// Rate : 1.0 : quality out
rippleLiquidity (
rippleCalc_,
- QUALITY_ONE,
- uQualityOut,
+ parityRate,
+ qualityOut,
previousNode().saFwdDeliver,
node().saRevRedeem,
saPrvDeliverAct,
@@ -449,8 +449,8 @@ TER PathCursor::forwardLiquidityForAccount () const
// Rate : 1.0 : transfer_rate
rippleLiquidity (
rippleCalc_,
- QUALITY_ONE,
- rippleTransferRate (view(), node().account_),
+ parityRate,
+ transferRate (view(), node().account_),
previousNode().saFwdDeliver,
node().saRevIssue,
saPrvDeliverAct,
@@ -480,8 +480,8 @@ TER PathCursor::forwardLiquidityForAccount () const
// Rate : 1.0 : transfer_rate
rippleLiquidity (
rippleCalc_,
- QUALITY_ONE,
- rippleTransferRate (view(), node().account_),
+ parityRate,
+ transferRate (view(), node().account_),
previousNode().saFwdDeliver,
node().saRevDeliver,
saPrvDeliverAct,
diff --git a/src/ripple/app/paths/cursor/Liquidity.cpp b/src/ripple/app/paths/cursor/Liquidity.cpp
index d8a7638edf..ee8176a394 100644
--- a/src/ripple/app/paths/cursor/Liquidity.cpp
+++ b/src/ripple/app/paths/cursor/Liquidity.cpp
@@ -39,14 +39,17 @@ TER PathCursor::liquidity () const
<< " nodeIndex=" << pc.nodeIndex_
<< ".issue_.account=" << to_string (pc.node().issue_.account);
- resultCode = pc.reverseLiquidity();
+ resultCode = pc.reverseLiquidity();
+
+ if (!pc.node().transferRate_)
+ return tefINTERNAL;
JLOG (j_.trace())
<< "reverseLiquidity< "
<< "nodeIndex=" << pc.nodeIndex_
<< " resultCode=" << transToken (resultCode)
- << " transferRate_=" << pc.node().transferRate_
- << "/" << resultCode;
+ << " transferRate_=" << *pc.node().transferRate_
+ << ": " << resultCode;
if (resultCode != tesSUCCESS)
break;
diff --git a/src/ripple/app/paths/cursor/ReverseLiquidity.cpp b/src/ripple/app/paths/cursor/ReverseLiquidity.cpp
index ad190de08d..f34f1c1cb7 100644
--- a/src/ripple/app/paths/cursor/ReverseLiquidity.cpp
+++ b/src/ripple/app/paths/cursor/ReverseLiquidity.cpp
@@ -55,9 +55,8 @@ TER PathCursor::reverseLiquidity () const
// TOMOVE: The account charges
// a fee when third parties transfer that account's own issuances.
- // node.transferRate_ caches the output transfer rate for this node.
- node().transferRate_ = amountFromRate (
- rippleTransferRate (view(), node().issue_.account));
+ // Cache the output transfer rate for this node.
+ node().transferRate_ = transferRate (view(), node().issue_.account);
if (node().isAccount ())
return reverseLiquidityForAccount ();
diff --git a/src/ripple/app/paths/cursor/ReverseLiquidityForAccount.cpp b/src/ripple/app/paths/cursor/ReverseLiquidityForAccount.cpp
index be6da3fa95..1af3cdb315 100644
--- a/src/ripple/app/paths/cursor/ReverseLiquidityForAccount.cpp
+++ b/src/ripple/app/paths/cursor/ReverseLiquidityForAccount.cpp
@@ -49,8 +49,8 @@ TER PathCursor::reverseLiquidityForAccount () const
auto const isFinalNode = (nodeIndex_ == lastNodeIndex);
// 0 quality means none has yet been determined.
- std::uint64_t uRateMax = 0
-;
+ std::uint64_t uRateMax = 0;
+
// Current is allowed to redeem to next.
const bool previousNodeIsAccount = !nodeIndex_ ||
previousNode().isAccount();
@@ -63,22 +63,22 @@ TER PathCursor::reverseLiquidityForAccount () const
: node().account_; // Offers are always issue.
// This is the quality from from the previous node to this one.
- const std::uint32_t uQualityIn
+ auto const qualityIn
= (nodeIndex_ != 0)
? quality_in (view(),
node().account_,
previousAccountID,
node().issue_.currency)
- : QUALITY_ONE;
+ : parityRate;
// And this is the quality from the next one to this one.
- const std::uint32_t uQualityOut
+ auto const qualityOut
= (nodeIndex_ != lastNodeIndex)
? quality_out (view(),
node().account_,
nextAccountID,
node().issue_.currency)
- : QUALITY_ONE;
+ : parityRate;
// For previousNodeIsAccount:
// Previous account is already owed.
@@ -112,8 +112,8 @@ TER PathCursor::reverseLiquidityForAccount () const
<< " node.account_=" << node().account_
<< " nextAccountID=" << nextAccountID
<< " currency=" << node().issue_.currency
- << " uQualityIn=" << uQualityIn
- << " uQualityOut=" << uQualityOut
+ << " qualityIn=" << qualityIn
+ << " qualityOut=" << qualityOut
<< " saPrvOwed=" << saPrvOwed
<< " saPrvLimit=" << saPrvLimit;
@@ -208,7 +208,7 @@ TER PathCursor::reverseLiquidityForAccount () const
<< " (available) previousNode.saRevRedeem="
<< previousNode().saRevRedeem
<< " uRateMax="
- << amountFromRate (uRateMax).getText ();
+ << amountFromQuality (uRateMax).getText ();
}
else
{
@@ -227,8 +227,8 @@ TER PathCursor::reverseLiquidityForAccount () const
// won't be included the current increment.
rippleLiquidity (
rippleCalc_,
- uQualityIn,
- QUALITY_ONE,
+ qualityIn,
+ parityRate,
saPrvIssueReq,
saCurWantedReq,
previousNode().saRevIssue,
@@ -266,8 +266,8 @@ TER PathCursor::reverseLiquidityForAccount () const
// as 1:1.
rippleLiquidity (
rippleCalc_,
- QUALITY_ONE,
- uQualityOut,
+ parityRate,
+ qualityOut,
saPrvRedeemReq,
node().saRevRedeem,
previousNode().saRevRedeem,
@@ -290,8 +290,8 @@ TER PathCursor::reverseLiquidityForAccount () const
// Rate: quality in : quality out
rippleLiquidity (
rippleCalc_,
- uQualityIn,
- uQualityOut,
+ qualityIn,
+ qualityOut,
saPrvIssueReq,
node().saRevRedeem,
previousNode().saRevIssue,
@@ -316,8 +316,8 @@ TER PathCursor::reverseLiquidityForAccount () const
// Rate : 1.0 : transfer_rate
rippleLiquidity (
rippleCalc_,
- QUALITY_ONE,
- rippleTransferRate (view(), node().account_),
+ parityRate,
+ transferRate (view(), node().account_),
saPrvRedeemReq,
node().saRevIssue,
previousNode().saRevRedeem,
@@ -344,8 +344,8 @@ TER PathCursor::reverseLiquidityForAccount () const
// Rate: quality in : 1.0
rippleLiquidity (
rippleCalc_,
- uQualityIn,
- QUALITY_ONE,
+ qualityIn,
+ parityRate,
saPrvIssueReq,
node().saRevIssue,
previousNode().saRevIssue,
@@ -402,8 +402,8 @@ TER PathCursor::reverseLiquidityForAccount () const
// Rate : 1.0 : transfer_rate
rippleLiquidity (
rippleCalc_,
- QUALITY_ONE,
- rippleTransferRate (view(), node().account_),
+ parityRate,
+ transferRate (view(), node().account_),
saPrvRedeemReq,
node().saRevDeliver,
previousNode().saRevRedeem,
@@ -419,8 +419,8 @@ TER PathCursor::reverseLiquidityForAccount () const
// Rate: quality in : 1.0
rippleLiquidity (
rippleCalc_,
- uQualityIn,
- QUALITY_ONE,
+ qualityIn,
+ parityRate,
saPrvIssueReq,
node().saRevDeliver,
previousNode().saRevIssue,
@@ -483,8 +483,8 @@ TER PathCursor::reverseLiquidityForAccount () const
// Rate: quality in : 1.0
rippleLiquidity (
rippleCalc_,
- uQualityIn,
- QUALITY_ONE,
+ qualityIn,
+ parityRate,
saPrvDeliverReq,
saCurWantedReq,
previousNode().saRevDeliver,
@@ -527,8 +527,8 @@ TER PathCursor::reverseLiquidityForAccount () const
// Rate : 1.0 : quality out
rippleLiquidity (
rippleCalc_,
- QUALITY_ONE,
- uQualityOut,
+ parityRate,
+ qualityOut,
saPrvDeliverReq,
node().saRevRedeem,
previousNode().saRevDeliver,
@@ -545,8 +545,8 @@ TER PathCursor::reverseLiquidityForAccount () const
// Rate : 1.0 : transfer_rate
rippleLiquidity (
rippleCalc_,
- QUALITY_ONE,
- rippleTransferRate (view(), node().account_),
+ parityRate,
+ transferRate (view(), node().account_),
saPrvDeliverReq,
node().saRevIssue,
previousNode().saRevDeliver,
@@ -578,8 +578,8 @@ TER PathCursor::reverseLiquidityForAccount () const
// Rate : 1.0 : transfer_rate
rippleLiquidity (
rippleCalc_,
- QUALITY_ONE,
- rippleTransferRate (view(), node().account_),
+ parityRate,
+ transferRate (view(), node().account_),
saPrvDeliverReq,
node().saRevDeliver,
previousNode().saRevDeliver,
diff --git a/src/ripple/app/paths/cursor/RippleLiquidity.cpp b/src/ripple/app/paths/cursor/RippleLiquidity.cpp
index 997bdc84b9..1e71e68d60 100644
--- a/src/ripple/app/paths/cursor/RippleLiquidity.cpp
+++ b/src/ripple/app/paths/cursor/RippleLiquidity.cpp
@@ -49,8 +49,8 @@ namespace path {
void rippleLiquidity (
RippleCalc& rippleCalc,
- std::uint32_t const uQualityIn,
- std::uint32_t const uQualityOut,
+ Rate const& qualityIn,
+ Rate const& qualityOut,
STAmount const& saPrvReq, // --> in limit including fees, <0 = unlimited
STAmount const& saCurReq, // --> out limit
STAmount& saPrvAct, // <-> in limit including achieved so far: <-- <= -->
@@ -59,8 +59,8 @@ void rippleLiquidity (
{
JLOG (rippleCalc.j_.trace())
<< "rippleLiquidity>"
- << " uQualityIn=" << uQualityIn
- << " uQualityOut=" << uQualityOut
+ << " qualityIn=" << qualityIn
+ << " qualityOut=" << qualityOut
<< " saPrvReq=" << saPrvReq
<< " saCurReq=" << saCurReq
<< " saPrvAct=" << saPrvAct
@@ -94,7 +94,7 @@ void rippleLiquidity (
if (saPrv == zero || saCur == zero)
return;
- if (uQualityIn >= uQualityOut)
+ if (qualityIn >= qualityOut)
{
// You're getting better quality than you asked for, so no fee.
JLOG (rippleCalc.j_.trace()) << "rippleLiquidity: No fees";
@@ -129,22 +129,18 @@ void rippleLiquidity (
// If the quality is worse than the previous
JLOG (rippleCalc.j_.trace()) << "rippleLiquidity: Fee";
- std::uint64_t uRate = getRate (
- STAmount (uQualityOut), STAmount (uQualityIn));
+ std::uint64_t const uRate = getRate (
+ STAmount (qualityOut.value),
+ STAmount (qualityIn.value));
// If the next rate is at least as good as the current rate, process.
if (!uRateMax || uRate <= uRateMax)
{
- auto currency = saCur.getCurrency ();
- auto uCurIssuerID = saCur.getIssuer ();
-
// current actual = current request * (quality out / quality in).
- auto numerator = mulRound (
- saCur, uQualityOut, {currency, uCurIssuerID}, true);
+ auto numerator = multiplyRound (saCur, qualityOut, true);
// True means "round up" to get best flow.
- STAmount saCurIn = divRound (
- numerator, uQualityIn, {currency, uCurIssuerID}, true);
+ STAmount saCurIn = divideRound (numerator, qualityIn, true);
JLOG (rippleCalc.j_.trace())
<< "rippleLiquidity:"
@@ -170,13 +166,12 @@ void rippleLiquidity (
// * (quality in / quality out).
// This is inverted compared to the code above because we're
// going the other way
-
- Issue issue{currency, uCurIssuerID};
- auto numerator = mulRound (saPrv, uQualityIn, issue, true);
+ auto numerator = multiplyRound (saPrv,
+ qualityIn, saCur.issue(), true);
// A part of current. All of previous. (Cur is the driver
// variable.)
- STAmount saCurOut = divRound (
- numerator, uQualityOut, issue, true);
+ STAmount saCurOut = divideRound (numerator,
+ qualityOut, saCur.issue(), true);
JLOG (rippleCalc.j_.trace())
<< "rippleLiquidity:4: saCurReq=" << saCurReq;
@@ -191,8 +186,8 @@ void rippleLiquidity (
JLOG (rippleCalc.j_.trace())
<< "rippleLiquidity<"
- << " uQualityIn=" << uQualityIn
- << " uQualityOut=" << uQualityOut
+ << " qualityIn=" << qualityIn
+ << " qualityOut=" << qualityOut
<< " saPrvReq=" << saPrvReq
<< " saCurReq=" << saCurReq
<< " saPrvAct=" << saPrvAct
@@ -200,7 +195,7 @@ void rippleLiquidity (
}
static
-std::uint32_t
+Rate
rippleQuality (
ReadView const& view,
AccountID const& destination,
@@ -209,32 +204,28 @@ rippleQuality (
SField const& sfLow,
SField const& sfHigh)
{
- std::uint32_t uQuality (QUALITY_ONE);
+ if (destination == source)
+ return parityRate;
- if (destination != source)
- {
- auto const sleRippleState = view.read(
- keylet::line(destination, source, currency));
+ auto const& sfField = destination < source ? sfLow : sfHigh;
- // we should be able to assert(sleRippleState) here
+ auto const sle = view.read(
+ keylet::line(destination, source, currency));
- if (sleRippleState)
- {
- auto const& sfField = destination < source ? sfLow : sfHigh;
+ if (!sle || !sle->isFieldPresent (sfField))
+ return parityRate;
- uQuality = sleRippleState->isFieldPresent (sfField)
- ? sleRippleState->getFieldU32 (sfField)
- : QUALITY_ONE;
+ auto quality = sle->getFieldU32 (sfField);
- if (!uQuality)
- uQuality = 1; // Avoid divide by zero.
- }
- }
+ // Avoid divide by zero. NIKB CHECKME: if we
+ // allow zero qualities now, then we shouldn't.
+ if (quality == 0)
+ quality = 1;
- return uQuality;
+ return Rate{ quality };
}
-std::uint32_t
+Rate
quality_in (
ReadView const& view,
AccountID const& uToAccountID,
@@ -245,7 +236,7 @@ quality_in (
sfLowQualityIn, sfHighQualityIn);
}
-std::uint32_t
+Rate
quality_out (
ReadView const& view,
AccountID const& uToAccountID,
diff --git a/src/ripple/app/paths/cursor/RippleLiquidity.h b/src/ripple/app/paths/cursor/RippleLiquidity.h
index 51ddf6b3c1..767c248deb 100644
--- a/src/ripple/app/paths/cursor/RippleLiquidity.h
+++ b/src/ripple/app/paths/cursor/RippleLiquidity.h
@@ -24,28 +24,29 @@
#include
#include
#include
+#include
namespace ripple {
namespace path {
void rippleLiquidity (
RippleCalc&,
- const std::uint32_t uQualityIn,
- const std::uint32_t uQualityOut,
+ Rate const& qualityIn,
+ Rate const& qualityOut,
STAmount const& saPrvReq,
STAmount const& saCurReq,
STAmount& saPrvAct,
STAmount& saCurAct,
std::uint64_t& uRateMax);
-std::uint32_t
+Rate
quality_in (
ReadView const& view,
AccountID const& uToAccountID,
AccountID const& uFromAccountID,
Currency const& currency);
-std::uint32_t
+Rate
quality_out (
ReadView const& view,
AccountID const& uToAccountID,
diff --git a/src/ripple/app/paths/impl/BookStep.cpp b/src/ripple/app/paths/impl/BookStep.cpp
index 2ee6143112..4ad559855c 100644
--- a/src/ripple/app/paths/impl/BookStep.cpp
+++ b/src/ripple/app/paths/impl/BookStep.cpp
@@ -256,18 +256,20 @@ forEachOffer (
// Charge a fee even if the owner is the same as the issuer
// (the old code does not charge a fee)
// Calculate amount that goes to the taker and the amount charged the offer owner
- auto transferRate = [&](AccountID const& id)->std::uint32_t
+ auto rate = [&](AccountID const& id)->std::uint32_t
{
if (isXRP (id) || id == dst)
return QUALITY_ONE;
- return rippleTransferRate (sb, id);
+ return transferRate (sb, id).value;
};
- std::uint32_t const trIn =
- prevStepRedeems ? transferRate (book.in.account) : QUALITY_ONE;
+ std::uint32_t const trIn = prevStepRedeems
+ ? rate (book.in.account)
+ : QUALITY_ONE;
// Always charge the transfer fee, even if the owner is the issuer
- std::uint32_t const trOut =
- ownerPaysTransferFee ? transferRate (book.out.account) : QUALITY_ONE;
+ std::uint32_t const trOut = ownerPaysTransferFee
+ ? rate (book.out.account)
+ : QUALITY_ONE;
typename FlowOfferStream::StepCounter counter (limit, j);
FlowOfferStream offers (
diff --git a/src/ripple/app/paths/impl/DirectStep.cpp b/src/ripple/app/paths/impl/DirectStep.cpp
index 106a8d6da4..a46d5a553e 100644
--- a/src/ripple/app/paths/impl/DirectStep.cpp
+++ b/src/ripple/app/paths/impl/DirectStep.cpp
@@ -546,8 +546,9 @@ DirectStepI::qualities (
{
// Charge a transfer rate when issuing and previous step redeems
auto const prevStepRedeems = prevStep_ && prevStep_->redeems (sb, fwd);
- std::uint32_t const srcQOut =
- prevStepRedeems ? rippleTransferRate (sb, src_) : QUALITY_ONE;
+ std::uint32_t const srcQOut = prevStepRedeems
+ ? transferRate (sb, src_).value
+ : QUALITY_ONE;
return std::make_pair(
srcQOut,
quality ( // dst quality in
diff --git a/src/ripple/app/tests/Taker.test.cpp b/src/ripple/app/tests/Taker.test.cpp
index 3a270f1e47..25cb97f611 100644
--- a/src/ripple/app/tests/Taker.test.cpp
+++ b/src/ripple/app/tests/Taker.test.cpp
@@ -37,10 +37,21 @@ class Taker_test : public beast::unit_test::suite
public:
TestTaker (
- CrossType cross_type, Amounts const& amount, Quality const& quality,
- STAmount const& funds, std::uint32_t flags, std::uint32_t rate_in,
- std::uint32_t rate_out)
- : BasicTaker (cross_type, AccountID(0x4701), amount, quality, flags, rate_in, rate_out)
+ CrossType cross_type,
+ Amounts const& amount,
+ Quality const& quality,
+ STAmount const& funds,
+ std::uint32_t flags,
+ Rate const& rate_in,
+ Rate const& rate_out)
+ : BasicTaker (
+ cross_type,
+ AccountID(0x4701),
+ amount,
+ quality,
+ flags,
+ rate_in,
+ rate_out)
, funds_ (funds)
{
}
@@ -178,8 +189,8 @@ private:
cross_attempt_offer const flow,
Issue const& issue_in,
Issue const& issue_out,
- std::uint32_t rate_in = QUALITY_ONE,
- std::uint32_t rate_out = QUALITY_ONE)
+ Rate rate_in = parityRate,
+ Rate rate_out = parityRate)
{
Amounts taker_offer (parse_amounts (
offer.in, issue_in,
@@ -333,7 +344,7 @@ public:
Quality q1 = get_quality ("1", "1");
// Highly exaggerated 50% transfer rate for the input and output:
- std::uint32_t rate = QUALITY_ONE + (QUALITY_ONE / 2);
+ Rate const rate { parityRate.value + (parityRate.value / 2) };
// TAKER OWNER
// QUAL OFFER FUNDS QUAL OFFER FUNDS EXPECTED
diff --git a/src/ripple/app/tx/impl/Taker.cpp b/src/ripple/app/tx/impl/Taker.cpp
index b8cabc447e..daee7f6b07 100644
--- a/src/ripple/app/tx/impl/Taker.cpp
+++ b/src/ripple/app/tx/impl/Taker.cpp
@@ -34,28 +34,10 @@ format_amount (STAmount const& amount)
return txt;
}
-STAmount
-BasicTaker::Rate::divide (STAmount const& amount) const
-{
- if (quality_ == QUALITY_ONE)
- return amount;
-
- return ripple::divide (amount, rate_, amount.issue ());
-}
-
-STAmount
-BasicTaker::Rate::multiply (STAmount const& amount) const
-{
- if (quality_ == QUALITY_ONE)
- return amount;
-
- return ripple::multiply (amount, rate_, amount.issue ());
-}
-
BasicTaker::BasicTaker (
CrossType cross_type, AccountID const& account, Amounts const& amount,
- Quality const& quality, std::uint32_t flags, std::uint32_t rate_in,
- std::uint32_t rate_out, beast::Journal journal)
+ Quality const& quality, std::uint32_t flags, Rate const& rate_in,
+ Rate const& rate_out, beast::Journal journal)
: account_ (account)
, quality_ (quality)
, threshold_ (quality_)
@@ -72,8 +54,8 @@ BasicTaker::BasicTaker (
assert (remaining_.in > zero);
assert (remaining_.out > zero);
- assert (m_rate_in != 0);
- assert (m_rate_out != 0);
+ assert (m_rate_in.value != 0);
+ assert (m_rate_out.value != 0);
// If we are dealing with a particular flavor, make sure that it's the
// flavor we expect:
@@ -92,24 +74,23 @@ BasicTaker::BasicTaker (
++threshold_;
}
-BasicTaker::Rate
+Rate
BasicTaker::effective_rate (
- std::uint32_t rate, Issue const &issue,
+ Rate const& rate, Issue const &issue,
AccountID const& from, AccountID const& to)
{
- assert (rate != 0);
-
- if (rate != QUALITY_ONE)
+ // If there's a transfer rate, the issuer is not involved
+ // and the sender isn't the same as the recipient, return
+ // the actual transfer rate.
+ if (rate != parityRate &&
+ from != to &&
+ from != issue.account &&
+ to != issue.account)
{
- // We ignore the transfer if the sender is also the recipient since no
- // actual transfer takes place in that case. We also ignore if either
- // the sender or the receiver is the issuer.
-
- if (from != to && from != issue.account && to != issue.account)
- return Rate (rate);
+ return rate;
}
- return Rate (QUALITY_ONE);
+ return parityRate;
}
bool
@@ -232,7 +213,7 @@ BasicTaker::flow_xrp_to_iou (
{
Flow f;
f.order = order;
- f.issuers.out = rate_out.multiply (f.order.out);
+ f.issuers.out = multiply (f.order.out, rate_out);
log_flow ("flow_xrp_to_iou", f);
@@ -240,7 +221,7 @@ BasicTaker::flow_xrp_to_iou (
if (owner_funds < f.issuers.out)
{
f.issuers.out = owner_funds;
- f.order.out = rate_out.divide (f.issuers.out);
+ f.order.out = divide (f.issuers.out, rate_out);
f.order.in = qual_mul (f.order.out, quality, f.order.in);
log_flow ("(clamped on owner balance)", f);
}
@@ -250,7 +231,7 @@ BasicTaker::flow_xrp_to_iou (
{
f.order.out = remaining_.out;
f.order.in = qual_mul (f.order.out, quality, f.order.in);
- f.issuers.out = rate_out.multiply (f.order.out);
+ f.issuers.out = multiply (f.order.out, rate_out);
log_flow ("(clamped on taker output)", f);
}
@@ -259,7 +240,7 @@ BasicTaker::flow_xrp_to_iou (
{
f.order.in = taker_funds;
f.order.out = qual_div (f.order.in, quality, f.order.out);
- f.issuers.out = rate_out.multiply (f.order.out);
+ f.issuers.out = multiply (f.order.out, rate_out);
log_flow ("(clamped on taker funds)", f);
}
@@ -269,7 +250,7 @@ BasicTaker::flow_xrp_to_iou (
{
f.order.in = remaining_.in;
f.order.out = qual_div (f.order.in, quality, f.order.out);
- f.issuers.out = rate_out.multiply (f.order.out);
+ f.issuers.out = multiply (f.order.out, rate_out);
log_flow ("(clamped on taker input)", f);
}
@@ -284,7 +265,7 @@ BasicTaker::flow_iou_to_xrp (
{
Flow f;
f.order = order;
- f.issuers.in = rate_in.multiply (f.order.in);
+ f.issuers.in = multiply (f.order.in, rate_in);
log_flow ("flow_iou_to_xrp", f);
@@ -293,7 +274,7 @@ BasicTaker::flow_iou_to_xrp (
{
f.order.out = owner_funds;
f.order.in = qual_mul (f.order.out, quality, f.order.in);
- f.issuers.in = rate_in.multiply (f.order.in);
+ f.issuers.in = multiply (f.order.in, rate_in);
log_flow ("(clamped on owner funds)", f);
}
@@ -305,7 +286,7 @@ BasicTaker::flow_iou_to_xrp (
{
f.order.out = remaining_.out;
f.order.in = qual_mul (f.order.out, quality, f.order.in);
- f.issuers.in = rate_in.multiply (f.order.in);
+ f.issuers.in = multiply (f.order.in, rate_in);
log_flow ("(clamped on taker output)", f);
}
}
@@ -314,7 +295,7 @@ BasicTaker::flow_iou_to_xrp (
if (remaining_.in < f.order.in)
{
f.order.in = remaining_.in;
- f.issuers.in = rate_in.multiply (f.order.in);
+ f.issuers.in = multiply (f.order.in, rate_in);
f.order.out = qual_div (f.order.in, quality, f.order.out);
log_flow ("(clamped on taker input)", f);
}
@@ -323,7 +304,7 @@ BasicTaker::flow_iou_to_xrp (
if (taker_funds < f.issuers.in)
{
f.issuers.in = taker_funds;
- f.order.in = rate_in.divide (f.issuers.in);
+ f.order.in = divide (f.issuers.in, rate_in);
f.order.out = qual_div (f.order.in, quality, f.order.out);
log_flow ("(clamped on taker funds)", f);
}
@@ -339,8 +320,8 @@ BasicTaker::flow_iou_to_iou (
{
Flow f;
f.order = order;
- f.issuers.in = rate_in.multiply (f.order.in);
- f.issuers.out = rate_out.multiply (f.order.out);
+ f.issuers.in = multiply (f.order.in, rate_in);
+ f.issuers.out = multiply (f.order.out, rate_out);
log_flow ("flow_iou_to_iou", f);
@@ -348,9 +329,9 @@ BasicTaker::flow_iou_to_iou (
if (owner_funds < f.issuers.out)
{
f.issuers.out = owner_funds;
- f.order.out = rate_out.divide (f.issuers.out);
+ f.order.out = divide (f.issuers.out, rate_out);
f.order.in = qual_mul (f.order.out, quality, f.order.in);
- f.issuers.in = rate_in.multiply (f.order.in);
+ f.issuers.in = multiply (f.order.in, rate_in);
log_flow ("(clamped on owner funds)", f);
}
@@ -359,8 +340,8 @@ BasicTaker::flow_iou_to_iou (
{
f.order.out = remaining_.out;
f.order.in = qual_mul (f.order.out, quality, f.order.in);
- f.issuers.out = rate_out.multiply (f.order.out);
- f.issuers.in = rate_in.multiply (f.order.in);
+ f.issuers.out = multiply (f.order.out, rate_out);
+ f.issuers.in = multiply (f.order.in, rate_in);
log_flow ("(clamped on taker output)", f);
}
@@ -368,9 +349,9 @@ BasicTaker::flow_iou_to_iou (
if (remaining_.in < f.order.in)
{
f.order.in = remaining_.in;
- f.issuers.in = rate_in.multiply (f.order.in);
+ f.issuers.in = multiply (f.order.in, rate_in);
f.order.out = qual_div (f.order.in, quality, f.order.out);
- f.issuers.out = rate_out.multiply (f.order.out);
+ f.issuers.out = multiply (f.order.out, rate_out);
log_flow ("(clamped on taker input)", f);
}
@@ -378,9 +359,9 @@ BasicTaker::flow_iou_to_iou (
if (taker_funds < f.issuers.in)
{
f.issuers.in = taker_funds;
- f.order.in = rate_in.divide (f.issuers.in);
+ f.order.in = divide (f.issuers.in, rate_in);
f.order.out = qual_div (f.order.in, quality, f.order.out);
- f.issuers.out = rate_out.multiply (f.order.out);
+ f.issuers.out = multiply (f.order.out, rate_out);
log_flow ("(clamped on taker funds)", f);
}
@@ -503,7 +484,7 @@ BasicTaker::do_cross (
// Adjust the second leg of the offer down:
flow2.order.in = flow1.order.out;
flow2.order.out = qual_div (flow2.order.in, quality2, flow2.order.out);
- flow2.issuers.out = leg2_rate.multiply (flow2.order.out);
+ flow2.issuers.out = multiply (flow2.order.out, leg2_rate);
log_flow ("Balancing: adjusted second leg down", flow2);
}
else if (flow1.order.out > flow2.order.in)
@@ -511,7 +492,7 @@ BasicTaker::do_cross (
// Adjust the first leg of the offer down:
flow1.order.out = flow2.order.in;
flow1.order.in = qual_mul (flow1.order.out, quality1, flow1.order.in);
- flow1.issuers.in = leg1_rate.multiply (flow1.order.in);
+ flow1.issuers.in = multiply (flow1.order.in, leg1_rate);
log_flow ("Balancing: adjusted first leg down", flow2);
}
@@ -779,15 +760,15 @@ Taker::cross (Offer& leg1, Offer& leg2)
return fill (ret.first, leg1, ret.second, leg2);
}
-std::uint32_t
+Rate
Taker::calculateRate (
ApplyView const& view,
AccountID const& issuer,
AccountID const& account)
{
return isXRP (issuer) || (account == issuer)
- ? QUALITY_ONE
- : rippleTransferRate (view, issuer);
+ ? parityRate
+ : transferRate (view, issuer);
}
} // ripple
diff --git a/src/ripple/app/tx/impl/Taker.h b/src/ripple/app/tx/impl/Taker.h
index 7fbdfef85e..ee1706813b 100644
--- a/src/ripple/app/tx/impl/Taker.h
+++ b/src/ripple/app/tx/impl/Taker.h
@@ -24,6 +24,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -42,28 +43,6 @@ enum class CrossType
/** State for the active party during order book or payment operations. */
class BasicTaker
{
-private:
- class Rate
- {
- private:
- std::uint32_t quality_;
- STAmount rate_;
-
- public:
- Rate (std::uint32_t quality)
- : quality_ (quality)
- {
- assert (quality_ != 0);
- rate_ = amountFromRate (quality_);
- }
-
- STAmount
- divide (STAmount const& amount) const;
-
- STAmount
- multiply (STAmount const& amount) const;
- };
-
private:
AccountID account_;
Quality quality_;
@@ -82,9 +61,9 @@ private:
Issue const& issue_out_;
// The rates that will be paid when the input and output currencies are
- // transfer when the currency issuer isn't involved:
- std::uint32_t const m_rate_in;
- std::uint32_t const m_rate_out;
+ // transfered and the currency issuer isn't involved:
+ Rate const m_rate_in;
+ Rate const m_rate_out;
// The type of crossing that we are performing
CrossType cross_type_;
@@ -132,7 +111,7 @@ private:
// flows for a particular issue between two accounts.
static
Rate
- effective_rate (std::uint32_t rate, Issue const &issue,
+ effective_rate (Rate const& rate, Issue const &issue,
AccountID const& from, AccountID const& to);
// The transfer rate for the input currency between the given accounts
@@ -155,8 +134,8 @@ public:
BasicTaker (
CrossType cross_type, AccountID const& account, Amounts const& amount,
- Quality const& quality, std::uint32_t flags, std::uint32_t rate_in,
- std::uint32_t rate_out, beast::Journal journal = beast::Journal ());
+ Quality const& quality, std::uint32_t flags, Rate const& rate_in,
+ Rate const& rate_out, beast::Journal journal = beast::Journal ());
virtual ~BasicTaker () = default;
@@ -291,7 +270,7 @@ public:
private:
static
- std::uint32_t
+ Rate
calculateRate (ApplyView const& view,
AccountID const& issuer,
AccountID const& account);
diff --git a/src/ripple/ledger/View.h b/src/ripple/ledger/View.h
index 78f02c1b96..7e225f4880 100644
--- a/src/ripple/ledger/View.h
+++ b/src/ripple/ledger/View.h
@@ -25,6 +25,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -90,16 +91,10 @@ forEachItemAfter (ReadView const& view, AccountID const& id,
unsigned int limit, std::function<
bool (std::shared_ptr const&)> f);
-std::uint32_t
-rippleTransferRate (ReadView const& view,
+Rate
+transferRate (ReadView const& view,
AccountID const& issuer);
-std::uint32_t
-rippleTransferRate (ReadView const& view,
- AccountID const& uSenderID,
- AccountID const& uReceiverID,
- AccountID const& issuer);
-
/** Returns `true` if the directory is empty
@param key The key of the directory
*/
diff --git a/src/ripple/ledger/impl/View.cpp b/src/ripple/ledger/impl/View.cpp
index 1c19449ac4..3cbea894a5 100644
--- a/src/ripple/ledger/impl/View.cpp
+++ b/src/ripple/ledger/impl/View.cpp
@@ -328,31 +328,16 @@ forEachItemAfter (ReadView const& view, AccountID const& id,
}
}
-std::uint32_t
-rippleTransferRate (ReadView const& view,
+Rate
+transferRate (ReadView const& view,
AccountID const& issuer)
{
auto const sle = view.read(keylet::account(issuer));
- std::uint32_t quality;
- if (sle && sle->isFieldPresent (sfTransferRate))
- quality = sle->getFieldU32 (sfTransferRate);
- else
- quality = QUALITY_ONE;
- return quality;
-}
-std::uint32_t
-rippleTransferRate (ReadView const& view,
- AccountID const& uSenderID,
- AccountID const& uReceiverID,
- AccountID const& issuer)
-{
- // If calculating the transfer rate from
- // or to the issuer of the currency no
- // fees are assessed.
- return (uSenderID == issuer || uReceiverID == issuer)
- ? QUALITY_ONE
- : rippleTransferRate(view, issuer);
+ if (sle && sle->isFieldPresent (sfTransferRate))
+ return Rate{ sle->getFieldU32 (sfTransferRate) };
+
+ return parityRate;
}
bool
@@ -1367,27 +1352,26 @@ rippleTransferFee (ReadView const& view,
AccountID const& from,
AccountID const& to,
AccountID const& issuer,
- STAmount const& saAmount,
+ STAmount const& amount,
beast::Journal j)
{
if (from != issuer && to != issuer)
{
- std::uint32_t uTransitRate = rippleTransferRate (view, issuer);
+ Rate const rate = transferRate (view, issuer);
- if (QUALITY_ONE != uTransitRate)
+ if (parityRate != rate)
{
- STAmount saTransferTotal = multiply (
- saAmount, amountFromRate (uTransitRate), saAmount.issue ());
- STAmount saTransferFee = saTransferTotal - saAmount;
+ auto const fee = multiply (amount, rate) - amount;
JLOG (j.debug()) << "rippleTransferFee:" <<
- " saTransferFee=" << saTransferFee.getFullText ();
+ " amount=" << amount.getFullText () <<
+ " fee=" << fee.getFullText ();
- return saTransferFee;
+ return fee;
}
}
- return saAmount.zeroed();
+ return amount.zeroed();
}
// Send regardless of limits.
@@ -1426,12 +1410,8 @@ rippleSend (ApplyView& view,
}
else
{
- auto const rate = rippleTransferRate (view, issuer);
- if (QUALITY_ONE == rate)
- saActual = saAmount;
- else
- saActual =
- multiply (saAmount, amountFromRate (rate), saAmount.issue ());
+ saActual = multiply (saAmount,
+ transferRate (view, issuer));
}
JLOG (j.debug()) << "rippleSend> " <<
diff --git a/src/ripple/ledger/tests/View_test.cpp b/src/ripple/ledger/tests/View_test.cpp
index 88744f54b9..151d08fcf0 100644
--- a/src/ripple/ledger/tests/View_test.cpp
+++ b/src/ripple/ledger/tests/View_test.cpp
@@ -646,27 +646,20 @@ class View_test
using namespace jtx;
Env env(*this);
- auto const alice = Account("alice");
- auto const bob = Account("bob");
auto const gw1 = Account("gw1");
- env.fund(XRP(10000), alice, bob, gw1);
+ env.fund(XRP(10000), gw1);
env.close();
auto rdView = env.closed();
// Test with no rate set on gw1.
- expect (rippleTransferRate (*rdView, alice, bob, gw1) == 1000000000);
- expect (rippleTransferRate (*rdView, gw1, alice, gw1) == 1000000000);
- expect (rippleTransferRate (*rdView, alice, gw1, gw1) == 1000000000);
+ expect (transferRate (*rdView, gw1) == parityRate);
env(rate(gw1, 1.02));
env.close();
rdView = env.closed();
- // Test with a non-unity rate set on gw1.
- expect (rippleTransferRate (*rdView, alice, bob, gw1) == 1020000000);
- expect (rippleTransferRate (*rdView, gw1, alice, gw1) == 1000000000);
- expect (rippleTransferRate (*rdView, alice, gw1, gw1) == 1000000000);
+ expect (transferRate (*rdView, gw1) == Rate{ 1020000000 });
}
void
diff --git a/src/ripple/protocol/Rate.h b/src/ripple/protocol/Rate.h
index b7268d6979..cbb4894ab7 100644
--- a/src/ripple/protocol/Rate.h
+++ b/src/ripple/protocol/Rate.h
@@ -30,20 +30,21 @@ namespace ripple {
/** Represents a transfer rate
- Transfer rates are specified as fractions of 1 billion. For example, a
- transfer rate of 1% is represented as 1010000000.
+ Transfer rates are specified as fractions of 1 billion.
+ For example, a transfer rate of 1% is represented as
+ 1,010,000,000.
*/
struct Rate
: private boost::totally_ordered
{
std::uint32_t value;
- Rate () = default;
+ Rate () = delete;
+ explicit
Rate (std::uint32_t rate)
: value (rate)
{
- assert (rate != 0);
}
};
@@ -69,6 +70,42 @@ operator<< (std::ostream& os, Rate const& rate)
return os;
}
+STAmount
+multiply (
+ STAmount const& amount,
+ Rate const& rate);
+
+STAmount
+multiplyRound (
+ STAmount const& amount,
+ Rate const& rate,
+ bool roundUp);
+
+STAmount
+multiplyRound (
+ STAmount const& amount,
+ Rate const& rate,
+ Issue const& issue,
+ bool roundUp);
+
+STAmount
+divide (
+ STAmount const& amount,
+ Rate const& rate);
+
+STAmount
+divideRound (
+ STAmount const& amount,
+ Rate const& rate,
+ bool roundUp);
+
+STAmount
+divideRound (
+ STAmount const& amount,
+ Rate const& rate,
+ Issue const& issue,
+ bool roundUp);
+
/** A transfer rate signifying a 1:1 exchange */
extern Rate const parityRate;
diff --git a/src/ripple/protocol/STAmount.h b/src/ripple/protocol/STAmount.h
index 4338316f64..4330c0cac4 100644
--- a/src/ripple/protocol/STAmount.h
+++ b/src/ripple/protocol/STAmount.h
@@ -75,9 +75,6 @@ public:
static std::uint64_t const uRateOne;
- static STAmount const saZero;
- static STAmount const saOne;
-
//--------------------------------------------------------------------------
STAmount(SerialIter& sit, SField const& name);
@@ -294,9 +291,6 @@ public:
//
//------------------------------------------------------------------------------
-STAmount
-amountFromRate (std::uint64_t uRate);
-
// VFALCO TODO The parameter type should be Quality not uint64_t
STAmount
amountFromQuality (std::uint64_t rate);
diff --git a/src/ripple/protocol/XRPAmount.h b/src/ripple/protocol/XRPAmount.h
index 93bc3df7ea..2a45ecf78a 100644
--- a/src/ripple/protocol/XRPAmount.h
+++ b/src/ripple/protocol/XRPAmount.h
@@ -149,8 +149,6 @@ mulRatio (
if (!den)
Throw ("division by zero");
- int128_t const den128 (den);
- int128_t const num128 (num);
int128_t const amt128 (amt.drops ());
auto const neg = amt.drops () < 0;
auto const m = amt128 * num;
diff --git a/src/ripple/protocol/impl/Rate2.cpp b/src/ripple/protocol/impl/Rate2.cpp
index 0d44d6ad1c..67702b994a 100644
--- a/src/ripple/protocol/impl/Rate2.cpp
+++ b/src/ripple/protocol/impl/Rate2.cpp
@@ -25,4 +25,121 @@ namespace ripple {
Rate const parityRate (QUALITY_ONE);
+namespace detail {
+
+STAmount as_amount (Rate const& rate)
+{
+ return { noIssue(), rate.value, -9, false };
+}
+
+}
+
+STAmount
+multiply (
+ STAmount const& amount,
+ Rate const& rate)
+{
+ assert (rate.value != 0);
+
+ if (rate == parityRate)
+ return amount;
+
+ return multiply (
+ amount,
+ detail::as_amount(rate),
+ amount.issue());
+}
+
+STAmount
+multiplyRound (
+ STAmount const& amount,
+ Rate const& rate,
+ bool roundUp)
+{
+ assert (rate.value != 0);
+
+ if (rate == parityRate)
+ return amount;
+
+ return mulRound (
+ amount,
+ detail::as_amount(rate),
+ amount.issue(),
+ roundUp);
+}
+
+STAmount
+multiplyRound (
+ STAmount const& amount,
+ Rate const& rate,
+ Issue const& issue,
+ bool roundUp)
+{
+ assert (rate.value != 0);
+
+ if (rate == parityRate)
+ {
+ return amount;
+ }
+
+ return mulRound (
+ amount,
+ detail::as_amount(rate),
+ issue,
+ roundUp);
+}
+
+STAmount
+divide (
+ STAmount const& amount,
+ Rate const& rate)
+{
+ assert (rate.value != 0);
+
+ if (rate == parityRate)
+ return amount;
+
+ return divide (
+ amount,
+ detail::as_amount(rate),
+ amount.issue());
+}
+
+STAmount
+divideRound (
+ STAmount const& amount,
+ Rate const& rate,
+ bool roundUp)
+{
+ assert (rate.value != 0);
+
+ if (rate == parityRate)
+ return amount;
+
+ return divRound (
+ amount,
+ detail::as_amount(rate),
+ amount.issue(),
+ roundUp);
+}
+
+STAmount
+divideRound (
+ STAmount const& amount,
+ Rate const& rate,
+ Issue const& issue,
+ bool roundUp)
+{
+ assert (rate.value != 0);
+
+ if (rate == parityRate)
+ return amount;
+
+ return divRound (
+ amount,
+ detail::as_amount(rate),
+ issue,
+ roundUp);
+}
+
}
diff --git a/src/ripple/protocol/impl/STAmount.cpp b/src/ripple/protocol/impl/STAmount.cpp
index 40914ffd93..1170416f6e 100644
--- a/src/ripple/protocol/impl/STAmount.cpp
+++ b/src/ripple/protocol/impl/STAmount.cpp
@@ -406,9 +406,6 @@ STAmount operator- (STAmount const& v1, STAmount const& v2)
std::uint64_t const STAmount::uRateOne = getRate (STAmount (1), STAmount (1));
-STAmount const STAmount::saZero (noIssue (), 0u);
-STAmount const STAmount::saOne (noIssue (), 1u);
-
void
STAmount::setIssue (Issue const& issue)
{
@@ -721,12 +718,6 @@ void STAmount::set (std::int64_t v)
//------------------------------------------------------------------------------
-STAmount
-amountFromRate (std::uint64_t uRate)
-{
- return { noIssue(), uRate, -9, false };
-}
-
STAmount
amountFromQuality (std::uint64_t rate)
{
diff --git a/src/ripple/protocol/impl/TER.cpp b/src/ripple/protocol/impl/TER.cpp
index 02c6642bcb..8a5b2c42ba 100644
--- a/src/ripple/protocol/impl/TER.cpp
+++ b/src/ripple/protocol/impl/TER.cpp
@@ -133,7 +133,7 @@ bool transResultInfo (TER code, std::string& token, std::string& text)
{ terNO_LINE, { "terNO_LINE", "No such line." } },
{ terPRE_SEQ, { "terPRE_SEQ", "Missing/inapplicable prior transaction." } },
{ terOWNERS, { "terOWNERS", "Non-zero owner count." } },
- { terQUEUED, { "terQUEUED", "Held until escalated fee drops." } },
+ { terQUEUED, { "terQUEUED", "Held until escalated fee drops." } },
{ tesSUCCESS, { "tesSUCCESS", "The transaction was applied. Only final in a validated ledger." } },
};
diff --git a/src/ripple/rpc/handlers/AccountLines.cpp b/src/ripple/rpc/handlers/AccountLines.cpp
index 58213faf6c..ff78502136 100644
--- a/src/ripple/rpc/handlers/AccountLines.cpp
+++ b/src/ripple/rpc/handlers/AccountLines.cpp
@@ -56,10 +56,8 @@ void addLine (Json::Value& jsonLines, RippleState const& line)
jPeer[jss::currency] = to_string (saBalance.issue ().currency);
jPeer[jss::limit] = saLimit.getText ();
jPeer[jss::limit_peer] = saLimitPeer.getText ();
- jPeer[jss::quality_in]
- = static_cast (line.getQualityIn ());
- jPeer[jss::quality_out]
- = static_cast (line.getQualityOut ());
+ jPeer[jss::quality_in] = line.getQualityIn ().value;
+ jPeer[jss::quality_out] = line.getQualityOut ().value;
if (line.getAuth ())
jPeer[jss::authorized] = true;
if (line.getAuthPeer ())
diff --git a/src/ripple/unity/app_paths.cpp b/src/ripple/unity/app_paths.cpp
index da78056027..e48209eb56 100644
--- a/src/ripple/unity/app_paths.cpp
+++ b/src/ripple/unity/app_paths.cpp
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
#include
#include
#include