mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 01:07:57 +00:00
Use enums for some parameters in payments:
* Use enums for StrandDirection, DebtDirection, and QualityDirection
This commit is contained in:
@@ -110,10 +110,11 @@ public:
|
||||
return EitherAmount (cache_->out);
|
||||
}
|
||||
|
||||
bool
|
||||
redeems (ReadView const& sb, bool fwd) const override
|
||||
DebtDirection
|
||||
debtDirection(ReadView const& sb, StrandDirection dir) const override
|
||||
{
|
||||
return !ownerPaysTransferFee_;
|
||||
return ownerPaysTransferFee_ ? DebtDirection::issues
|
||||
: DebtDirection::redeems;
|
||||
}
|
||||
|
||||
boost::optional<Book>
|
||||
@@ -123,7 +124,7 @@ public:
|
||||
}
|
||||
|
||||
boost::optional<Quality>
|
||||
qualityUpperBound(ReadView const& v, bool& redeems) const override;
|
||||
qualityUpperBound(ReadView const& v, DebtDirection& dir) const override;
|
||||
|
||||
std::pair<TIn, TOut>
|
||||
revImp (
|
||||
@@ -188,7 +189,7 @@ private:
|
||||
forEachOffer (
|
||||
PaymentSandbox& sb,
|
||||
ApplyView& afView,
|
||||
bool prevStepRedeems,
|
||||
DebtDirection prevStepDebtDir,
|
||||
Callback& callback) const;
|
||||
|
||||
void consumeOffer (PaymentSandbox& sb,
|
||||
@@ -248,7 +249,7 @@ public:
|
||||
Quality
|
||||
qualityUpperBound(ReadView const& v,
|
||||
Quality const& ofrQ,
|
||||
bool prevStepRedeems) const
|
||||
DebtDirection prevStepDir) const
|
||||
{
|
||||
// Charge the offer owner, not the sender
|
||||
// Charge a fee even if the owner is the same as the issuer
|
||||
@@ -262,7 +263,7 @@ public:
|
||||
};
|
||||
|
||||
auto const trIn =
|
||||
prevStepRedeems ? rate(this->book_.in.account) : parityRate;
|
||||
redeems(prevStepDir) ? rate(this->book_.in.account) : parityRate;
|
||||
// Always charge the transfer fee, even if the owner is the issuer
|
||||
auto const trOut =
|
||||
this->ownerPaysTransferFee_
|
||||
@@ -393,7 +394,7 @@ public:
|
||||
Quality
|
||||
qualityUpperBound(ReadView const& v,
|
||||
Quality const& ofrQ,
|
||||
bool prevStepRedeems) const
|
||||
DebtDirection prevStepDir) const
|
||||
{
|
||||
// Offer x-ing does not charge a transfer fee when the offer's owner
|
||||
// is the same as the strand dst. It is important that `qualityUpperBound`
|
||||
@@ -427,10 +428,10 @@ bool BookStep<TIn, TOut, TDerived>::equal (Step const& rhs) const
|
||||
template <class TIn, class TOut, class TDerived>
|
||||
boost::optional<Quality>
|
||||
BookStep<TIn, TOut, TDerived>::qualityUpperBound(
|
||||
ReadView const& v, bool& redeems) const
|
||||
ReadView const& v, DebtDirection& dir) const
|
||||
{
|
||||
auto const prevStepRedeems = redeems;
|
||||
redeems = this->redeems(v, true);
|
||||
auto const prevStepDir = dir;
|
||||
dir = this->debtDirection(v, StrandDirection::forward);
|
||||
|
||||
// This can be simplified (and sped up) if directories are never empty.
|
||||
Sandbox sb(&v, tapNONE);
|
||||
@@ -439,7 +440,7 @@ BookStep<TIn, TOut, TDerived>::qualityUpperBound(
|
||||
return boost::none;
|
||||
|
||||
return static_cast<TDerived const*>(this)->qualityUpperBound(
|
||||
v, bt.quality(), prevStepRedeems);
|
||||
v, bt.quality(), prevStepDir);
|
||||
}
|
||||
|
||||
// Adjust the offer amount and step amount subject to the given input limit
|
||||
@@ -493,7 +494,7 @@ std::pair<boost::container::flat_set<uint256>, std::uint32_t>
|
||||
BookStep<TIn, TOut, TDerived>::forEachOffer (
|
||||
PaymentSandbox& sb,
|
||||
ApplyView& afView,
|
||||
bool prevStepRedeems,
|
||||
DebtDirection prevStepDir,
|
||||
Callback& callback) const
|
||||
{
|
||||
// Charge the offer owner, not the sender
|
||||
@@ -507,9 +508,8 @@ BookStep<TIn, TOut, TDerived>::forEachOffer (
|
||||
return transferRate (sb, id).value;
|
||||
};
|
||||
|
||||
std::uint32_t const trIn = prevStepRedeems
|
||||
? rate (book_.in.account)
|
||||
: QUALITY_ONE;
|
||||
std::uint32_t const trIn =
|
||||
redeems(prevStepDir) ? rate(book_.in.account) : QUALITY_ONE;
|
||||
// Always charge the transfer fee, even if the owner is the issuer
|
||||
std::uint32_t const trOut = ownerPaysTransferFee_
|
||||
? rate (book_.out.account)
|
||||
@@ -726,8 +726,12 @@ BookStep<TIn, TOut, TDerived>::revImp (
|
||||
};
|
||||
|
||||
{
|
||||
auto const prevStepRedeems = prevStep_ && prevStep_->redeems (sb, false);
|
||||
auto const r = forEachOffer (sb, afView, prevStepRedeems, eachOffer);
|
||||
auto const prevStepDebtDir = [&]{
|
||||
if (prevStep_)
|
||||
return prevStep_->debtDirection (sb, StrandDirection::reverse);
|
||||
return DebtDirection::issues;
|
||||
}();
|
||||
auto const r = forEachOffer (sb, afView, prevStepDebtDir, eachOffer);
|
||||
boost::container::flat_set<uint256> toRm = std::move(std::get<0>(r));
|
||||
std::uint32_t const offersConsumed = std::get<1>(r);
|
||||
SetUnion(ofrsToRm, toRm);
|
||||
@@ -887,8 +891,12 @@ BookStep<TIn, TOut, TDerived>::fwdImp (
|
||||
};
|
||||
|
||||
{
|
||||
auto const prevStepRedeems = prevStep_ && prevStep_->redeems (sb, true);
|
||||
auto const r = forEachOffer (sb, afView, prevStepRedeems, eachOffer);
|
||||
auto const prevStepDebtDir = [&] {
|
||||
if (prevStep_)
|
||||
return prevStep_->debtDirection(sb, StrandDirection::forward);
|
||||
return DebtDirection::issues;
|
||||
}();
|
||||
auto const r = forEachOffer(sb, afView, prevStepDebtDir, eachOffer);
|
||||
boost::container::flat_set<uint256> toRm = std::move(std::get<0>(r));
|
||||
std::uint32_t const offersConsumed = std::get<1>(r);
|
||||
SetUnion(ofrsToRm, toRm);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <ripple/protocol/Quality.h>
|
||||
|
||||
#include <boost/container/flat_set.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
@@ -50,17 +51,17 @@ protected:
|
||||
IOUAmount in;
|
||||
IOUAmount srcToDst;
|
||||
IOUAmount out;
|
||||
bool srcRedeems;
|
||||
DebtDirection srcDebtDir;
|
||||
|
||||
Cache (
|
||||
IOUAmount const& in_,
|
||||
IOUAmount const& srcToDst_,
|
||||
IOUAmount const& out_,
|
||||
bool srcRedeems_)
|
||||
DebtDirection srcDebtDir_)
|
||||
: in(in_)
|
||||
, srcToDst(srcToDst_)
|
||||
, out(out_)
|
||||
, srcRedeems(srcRedeems_)
|
||||
, srcDebtDir(srcDebtDir_)
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -69,17 +70,28 @@ protected:
|
||||
// Compute the maximum value that can flow from src->dst at
|
||||
// the best available quality.
|
||||
// return: first element is max amount that can flow,
|
||||
// second is true if dst holds an iou from src.
|
||||
std::pair<IOUAmount, bool>
|
||||
// second is the debt direction of the source w.r.t. the dst
|
||||
std::pair<IOUAmount, DebtDirection>
|
||||
maxPaymentFlow (
|
||||
ReadView const& sb) const;
|
||||
|
||||
// Compute srcQOut and dstQIn when the source redeems.
|
||||
std::pair<std::uint32_t, std::uint32_t>
|
||||
qualitiesSrcRedeems(
|
||||
ReadView const& sb) const;
|
||||
|
||||
// Compute srcQOut and dstQIn when the source issues.
|
||||
std::pair<std::uint32_t, std::uint32_t>
|
||||
qualitiesSrcIssues(
|
||||
ReadView const& sb,
|
||||
DebtDirection prevStepDebtDirection) const;
|
||||
|
||||
// Returns srcQOut, dstQIn
|
||||
std::pair <std::uint32_t, std::uint32_t>
|
||||
qualities (
|
||||
ReadView const& sb,
|
||||
bool srcRedeems,
|
||||
bool fwd) const;
|
||||
DebtDirection srcDebtDir,
|
||||
StrandDirection strandDir) const;
|
||||
|
||||
public:
|
||||
DirectStepI (
|
||||
@@ -135,14 +147,14 @@ public:
|
||||
return std::make_pair(src_, dst_);
|
||||
}
|
||||
|
||||
bool
|
||||
redeems (ReadView const& sb, bool fwd) const override;
|
||||
DebtDirection
|
||||
debtDirection (ReadView const& sb, StrandDirection dir) const override;
|
||||
|
||||
std::uint32_t
|
||||
lineQualityIn (ReadView const& v) const override;
|
||||
|
||||
boost::optional<Quality>
|
||||
qualityUpperBound(ReadView const& v, bool& redeems) const override;
|
||||
qualityUpperBound(ReadView const& v, DebtDirection& dir) const override;
|
||||
|
||||
std::pair<IOUAmount, IOUAmount>
|
||||
revImp (
|
||||
@@ -172,7 +184,7 @@ public:
|
||||
IOUAmount const& fwdIn,
|
||||
IOUAmount const& fwdSrcToDst,
|
||||
IOUAmount const& fwdOut,
|
||||
bool srcRedeems);
|
||||
DebtDirection srcDebtDir);
|
||||
|
||||
friend bool operator==(DirectStepI const& lhs, DirectStepI const& rhs)
|
||||
{
|
||||
@@ -223,7 +235,7 @@ public:
|
||||
using DirectStepI<DirectIPaymentStep>::DirectStepI;
|
||||
using DirectStepI<DirectIPaymentStep>::check;
|
||||
|
||||
bool verifyPrevStepRedeems (bool) const
|
||||
bool verifyPrevStepDebtDirection (DebtDirection) const
|
||||
{
|
||||
// A payment doesn't care whether or not prevStepRedeems.
|
||||
return true;
|
||||
@@ -237,14 +249,13 @@ public:
|
||||
|
||||
std::uint32_t
|
||||
quality (ReadView const& sb,
|
||||
// set true for quality in, false for quality out
|
||||
bool qin) const;
|
||||
QualityDirection qDir) const;
|
||||
|
||||
// Compute the maximum value that can flow from src->dst at
|
||||
// the best available quality.
|
||||
// return: first element is max amount that can flow,
|
||||
// second is true if dst holds an iou from src.
|
||||
std::pair<IOUAmount, bool>
|
||||
// second is the debt direction w.r.t. the source account
|
||||
std::pair<IOUAmount, DebtDirection>
|
||||
maxFlow (ReadView const& sb, IOUAmount const& desired) const;
|
||||
|
||||
// Verify the consistency of the step. These checks are specific to
|
||||
@@ -266,15 +277,15 @@ public:
|
||||
using DirectStepI<DirectIOfferCrossingStep>::DirectStepI;
|
||||
using DirectStepI<DirectIOfferCrossingStep>::check;
|
||||
|
||||
bool verifyPrevStepRedeems (bool prevStepRedeems) const
|
||||
bool verifyPrevStepDebtDirection (DebtDirection prevStepDir) const
|
||||
{
|
||||
// During offer crossing we rely on the fact that prevStepRedeems
|
||||
// will *always* be false. That's because:
|
||||
// will *always* issue. That's because:
|
||||
// o If there's a prevStep_, it will always be a BookStep.
|
||||
// o BookStep::redeems() aways returns false when offer crossing.
|
||||
// o BookStep::debtDirection() aways returns `issues` when offer crossing.
|
||||
// An assert based on this return value will tell us if that
|
||||
// behavior changes.
|
||||
return !prevStepRedeems;
|
||||
return issues(prevStepDir);
|
||||
}
|
||||
|
||||
bool verifyDstQualityIn (std::uint32_t dstQIn) const
|
||||
@@ -286,14 +297,13 @@ public:
|
||||
|
||||
std::uint32_t
|
||||
quality (ReadView const& sb,
|
||||
// set true for quality in, false for quality out
|
||||
bool qin) const;
|
||||
QualityDirection qDir) const;
|
||||
|
||||
// Compute the maximum value that can flow from src->dst at
|
||||
// the best available quality.
|
||||
// return: first element is max amount that can flow,
|
||||
// second is true if dst holds an iou from src.
|
||||
std::pair<IOUAmount, bool>
|
||||
// second is the debt direction w.r.t the source
|
||||
std::pair<IOUAmount, DebtDirection>
|
||||
maxFlow (ReadView const& sb, IOUAmount const& desired) const;
|
||||
|
||||
// Verify the consistency of the step. These checks are specific to
|
||||
@@ -313,8 +323,7 @@ public:
|
||||
|
||||
std::uint32_t
|
||||
DirectIPaymentStep::quality (ReadView const& sb,
|
||||
// set true for quality in, false for quality out
|
||||
bool qin) const
|
||||
QualityDirection qDir) const
|
||||
{
|
||||
if (src_ == dst_)
|
||||
return QUALITY_ONE;
|
||||
@@ -324,9 +333,9 @@ DirectIPaymentStep::quality (ReadView const& sb,
|
||||
if (!sle)
|
||||
return QUALITY_ONE;
|
||||
|
||||
auto const& field = [this, qin]() -> SF_U32 const&
|
||||
auto const& field = [this, qDir]() -> SF_U32 const&
|
||||
{
|
||||
if (qin)
|
||||
if (qDir == QualityDirection::in)
|
||||
{
|
||||
// compute dst quality in
|
||||
if (this->dst_ < this->src_)
|
||||
@@ -355,21 +364,20 @@ DirectIPaymentStep::quality (ReadView const& sb,
|
||||
|
||||
std::uint32_t
|
||||
DirectIOfferCrossingStep::quality (ReadView const&,
|
||||
// set true for quality in, false for quality out
|
||||
bool) const
|
||||
QualityDirection qDir) const
|
||||
{
|
||||
// If offer crossing then ignore trust line Quality fields. This
|
||||
// preserves a long-standing tradition.
|
||||
return QUALITY_ONE;
|
||||
}
|
||||
|
||||
std::pair<IOUAmount, bool>
|
||||
std::pair<IOUAmount, DebtDirection>
|
||||
DirectIPaymentStep::maxFlow (ReadView const& sb, IOUAmount const&) const
|
||||
{
|
||||
return maxPaymentFlow (sb);
|
||||
}
|
||||
|
||||
std::pair<IOUAmount, bool>
|
||||
std::pair<IOUAmount, DebtDirection>
|
||||
DirectIOfferCrossingStep::maxFlow (
|
||||
ReadView const& sb, IOUAmount const& desired) const
|
||||
{
|
||||
@@ -386,7 +394,7 @@ DirectIOfferCrossingStep::maxFlow (
|
||||
// "dstQIn" is always QUALITY_ONE for offer crossing.
|
||||
|
||||
if (isLast_)
|
||||
return {desired, false};
|
||||
return {desired, DebtDirection::issues};
|
||||
|
||||
return maxPaymentFlow (sb);
|
||||
}
|
||||
@@ -460,29 +468,31 @@ DirectIOfferCrossingStep::check (
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class TDerived>
|
||||
std::pair<IOUAmount, bool>
|
||||
std::pair<IOUAmount, DebtDirection>
|
||||
DirectStepI<TDerived>::maxPaymentFlow (ReadView const& sb) const
|
||||
{
|
||||
auto const srcOwed = toAmount<IOUAmount> (
|
||||
accountHolds (sb, src_, currency_, dst_, fhIGNORE_FREEZE, j_));
|
||||
|
||||
if (srcOwed.signum () > 0)
|
||||
return {srcOwed, true};
|
||||
return {srcOwed, DebtDirection::redeems};
|
||||
|
||||
// srcOwed is negative or zero
|
||||
return {creditLimit2 (sb, dst_, src_, currency_) + srcOwed, false};
|
||||
return {creditLimit2 (sb, dst_, src_, currency_) + srcOwed, DebtDirection::issues};
|
||||
}
|
||||
|
||||
template <class TDerived>
|
||||
bool
|
||||
DirectStepI<TDerived>::redeems (ReadView const& sb, bool fwd) const
|
||||
DebtDirection
|
||||
DirectStepI<TDerived>::debtDirection(ReadView const& sb, StrandDirection dir)
|
||||
const
|
||||
{
|
||||
if (fwd && cache_)
|
||||
return cache_->srcRedeems;
|
||||
if (dir == StrandDirection::forward && cache_)
|
||||
return cache_->srcDebtDir;
|
||||
|
||||
auto const srcOwed = accountHolds (
|
||||
sb, src_, currency_, dst_, fhIGNORE_FREEZE, j_);
|
||||
return srcOwed.signum () > 0;
|
||||
auto const srcOwed =
|
||||
accountHolds(sb, src_, currency_, dst_, fhIGNORE_FREEZE, j_);
|
||||
return srcOwed.signum() > 0 ? DebtDirection::redeems
|
||||
: DebtDirection::issues;
|
||||
}
|
||||
|
||||
template <class TDerived>
|
||||
@@ -495,21 +505,22 @@ DirectStepI<TDerived>::revImp (
|
||||
{
|
||||
cache_.reset ();
|
||||
|
||||
bool srcRedeems;
|
||||
DebtDirection srcDebtDir;
|
||||
IOUAmount maxSrcToDst;
|
||||
|
||||
std::tie (maxSrcToDst, srcRedeems) =
|
||||
std::tie (maxSrcToDst, srcDebtDir) =
|
||||
static_cast<TDerived const*>(this)->maxFlow (sb, out);
|
||||
|
||||
std::uint32_t srcQOut, dstQIn;
|
||||
std::tie (srcQOut, dstQIn) = qualities (sb, srcRedeems, false);
|
||||
std::tie (srcQOut, dstQIn) = qualities (sb, srcDebtDir, StrandDirection::reverse);
|
||||
assert (static_cast<TDerived const*>(this)->verifyDstQualityIn (dstQIn));
|
||||
|
||||
Issue const srcToDstIss (currency_, srcRedeems ? dst_ : src_);
|
||||
Issue const srcToDstIss(
|
||||
currency_, redeems(srcDebtDir) ? dst_ : src_);
|
||||
|
||||
JLOG (j_.trace()) <<
|
||||
"DirectStepI::rev" <<
|
||||
" srcRedeems: " << srcRedeems <<
|
||||
" srcRedeems: " << redeems(srcDebtDir) <<
|
||||
" outReq: " << to_string (out) <<
|
||||
" maxSrcToDst: " << to_string (maxSrcToDst) <<
|
||||
" srcQOut: " << srcQOut <<
|
||||
@@ -522,7 +533,7 @@ DirectStepI<TDerived>::revImp (
|
||||
IOUAmount (beast::zero),
|
||||
IOUAmount (beast::zero),
|
||||
IOUAmount (beast::zero),
|
||||
srcRedeems);
|
||||
srcDebtDir);
|
||||
return {beast::zero, beast::zero};
|
||||
}
|
||||
|
||||
@@ -533,13 +544,13 @@ DirectStepI<TDerived>::revImp (
|
||||
{
|
||||
IOUAmount const in = mulRatio (
|
||||
srcToDst, srcQOut, QUALITY_ONE, /*roundUp*/ true);
|
||||
cache_.emplace (in, srcToDst, out, srcRedeems);
|
||||
cache_.emplace (in, srcToDst, out, srcDebtDir);
|
||||
rippleCredit (sb,
|
||||
src_, dst_, toSTAmount (srcToDst, srcToDstIss),
|
||||
/*checkIssuer*/ true, j_);
|
||||
JLOG (j_.trace()) <<
|
||||
"DirectStepI::rev: Non-limiting" <<
|
||||
" srcRedeems: " << srcRedeems <<
|
||||
" srcRedeems: " << redeems(srcDebtDir) <<
|
||||
" in: " << to_string (in) <<
|
||||
" srcToDst: " << to_string (srcToDst) <<
|
||||
" out: " << to_string (out);
|
||||
@@ -551,13 +562,13 @@ DirectStepI<TDerived>::revImp (
|
||||
maxSrcToDst, srcQOut, QUALITY_ONE, /*roundUp*/ true);
|
||||
IOUAmount const actualOut = mulRatio (
|
||||
maxSrcToDst, dstQIn, QUALITY_ONE, /*roundUp*/ false);
|
||||
cache_.emplace (in, maxSrcToDst, actualOut, srcRedeems);
|
||||
cache_.emplace (in, maxSrcToDst, actualOut, srcDebtDir);
|
||||
rippleCredit (sb,
|
||||
src_, dst_, toSTAmount (maxSrcToDst, srcToDstIss),
|
||||
/*checkIssuer*/ true, j_);
|
||||
JLOG (j_.trace()) <<
|
||||
"DirectStepI::rev: Limiting" <<
|
||||
" srcRedeems: " << srcRedeems <<
|
||||
" srcRedeems: " << redeems(srcDebtDir) <<
|
||||
" in: " << to_string (in) <<
|
||||
" srcToDst: " << to_string (maxSrcToDst) <<
|
||||
" out: " << to_string (out);
|
||||
@@ -574,7 +585,7 @@ DirectStepI<TDerived>::setCacheLimiting (
|
||||
IOUAmount const& fwdIn,
|
||||
IOUAmount const& fwdSrcToDst,
|
||||
IOUAmount const& fwdOut,
|
||||
bool srcRedeems)
|
||||
DebtDirection srcDebtDir)
|
||||
{
|
||||
if (cache_->in < fwdIn)
|
||||
{
|
||||
@@ -596,7 +607,7 @@ DirectStepI<TDerived>::setCacheLimiting (
|
||||
<< " cacheSrcToDst: " << to_string (cache_->srcToDst)
|
||||
<< " fwdOut: " << to_string (fwdOut)
|
||||
<< " cacheOut: " << to_string (cache_->out);
|
||||
cache_.emplace (fwdIn, fwdSrcToDst, fwdOut, srcRedeems);
|
||||
cache_.emplace (fwdIn, fwdSrcToDst, fwdOut, srcDebtDir);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -606,7 +617,7 @@ DirectStepI<TDerived>::setCacheLimiting (
|
||||
cache_->srcToDst = fwdSrcToDst;
|
||||
if (fwdOut < cache_->out)
|
||||
cache_->out = fwdOut;
|
||||
cache_->srcRedeems = srcRedeems;
|
||||
cache_->srcDebtDir = srcDebtDir;
|
||||
};
|
||||
|
||||
template <class TDerived>
|
||||
@@ -619,19 +630,19 @@ DirectStepI<TDerived>::fwdImp (
|
||||
{
|
||||
assert (cache_);
|
||||
|
||||
bool srcRedeems;
|
||||
DebtDirection srcDebtDir;
|
||||
IOUAmount maxSrcToDst;
|
||||
std::tie (maxSrcToDst, srcRedeems) =
|
||||
std::tie (maxSrcToDst, srcDebtDir) =
|
||||
static_cast<TDerived const*>(this)->maxFlow (sb, cache_->srcToDst);
|
||||
|
||||
std::uint32_t srcQOut, dstQIn;
|
||||
std::tie (srcQOut, dstQIn) = qualities (sb, srcRedeems, true);
|
||||
std::tie (srcQOut, dstQIn) = qualities (sb, srcDebtDir, StrandDirection::forward);
|
||||
|
||||
Issue const srcToDstIss (currency_, srcRedeems ? dst_ : src_);
|
||||
Issue const srcToDstIss (currency_, redeems(srcDebtDir) ? dst_ : src_);
|
||||
|
||||
JLOG (j_.trace()) <<
|
||||
"DirectStepI::fwd" <<
|
||||
" srcRedeems: " << srcRedeems <<
|
||||
" srcRedeems: " << redeems(srcDebtDir) <<
|
||||
" inReq: " << to_string (in) <<
|
||||
" maxSrcToDst: " << to_string (maxSrcToDst) <<
|
||||
" srcQOut: " << srcQOut <<
|
||||
@@ -644,7 +655,7 @@ DirectStepI<TDerived>::fwdImp (
|
||||
IOUAmount (beast::zero),
|
||||
IOUAmount (beast::zero),
|
||||
IOUAmount (beast::zero),
|
||||
srcRedeems);
|
||||
srcDebtDir);
|
||||
return {beast::zero, beast::zero};
|
||||
}
|
||||
|
||||
@@ -655,13 +666,13 @@ DirectStepI<TDerived>::fwdImp (
|
||||
{
|
||||
IOUAmount const out = mulRatio (
|
||||
srcToDst, dstQIn, QUALITY_ONE, /*roundUp*/ false);
|
||||
setCacheLimiting (in, srcToDst, out, srcRedeems);
|
||||
setCacheLimiting (in, srcToDst, out, srcDebtDir);
|
||||
rippleCredit (sb,
|
||||
src_, dst_, toSTAmount (cache_->srcToDst, srcToDstIss),
|
||||
/*checkIssuer*/ true, j_);
|
||||
JLOG (j_.trace()) <<
|
||||
"DirectStepI::fwd: Non-limiting" <<
|
||||
" srcRedeems: " << srcRedeems <<
|
||||
" srcRedeems: " << redeems(srcDebtDir) <<
|
||||
" in: " << to_string (in) <<
|
||||
" srcToDst: " << to_string (srcToDst) <<
|
||||
" out: " << to_string (out);
|
||||
@@ -673,13 +684,13 @@ DirectStepI<TDerived>::fwdImp (
|
||||
maxSrcToDst, srcQOut, QUALITY_ONE, /*roundUp*/ true);
|
||||
IOUAmount const out = mulRatio (
|
||||
maxSrcToDst, dstQIn, QUALITY_ONE, /*roundUp*/ false);
|
||||
setCacheLimiting (actualIn, maxSrcToDst, out, srcRedeems);
|
||||
setCacheLimiting (actualIn, maxSrcToDst, out, srcDebtDir);
|
||||
rippleCredit (sb,
|
||||
src_, dst_, toSTAmount (cache_->srcToDst, srcToDstIss),
|
||||
/*checkIssuer*/ true, j_);
|
||||
JLOG (j_.trace()) <<
|
||||
"DirectStepI::rev: Limiting" <<
|
||||
" srcRedeems: " << srcRedeems <<
|
||||
" srcRedeems: " << redeems(srcDebtDir) <<
|
||||
" in: " << to_string (actualIn) <<
|
||||
" srcToDst: " << to_string (srcToDst) <<
|
||||
" out: " << to_string (out);
|
||||
@@ -705,9 +716,9 @@ DirectStepI<TDerived>::validFwd (
|
||||
|
||||
assert (!in.native);
|
||||
|
||||
bool srcRedeems;
|
||||
DebtDirection srcDebtDir;
|
||||
IOUAmount maxSrcToDst;
|
||||
std::tie (maxSrcToDst, srcRedeems) =
|
||||
std::tie (maxSrcToDst, srcDebtDir) =
|
||||
static_cast<TDerived const*>(this)->maxFlow (sb, cache_->srcToDst);
|
||||
|
||||
try
|
||||
@@ -747,40 +758,65 @@ DirectStepI<TDerived>::validFwd (
|
||||
// Returns srcQOut, dstQIn
|
||||
template <class TDerived>
|
||||
std::pair<std::uint32_t, std::uint32_t>
|
||||
DirectStepI<TDerived>::qualities (
|
||||
ReadView const& sb,
|
||||
bool srcRedeems,
|
||||
bool fwd) const
|
||||
{
|
||||
if (srcRedeems)
|
||||
DirectStepI<TDerived>::qualitiesSrcRedeems(
|
||||
ReadView const& sb) const
|
||||
{
|
||||
if (!prevStep_)
|
||||
return {QUALITY_ONE, QUALITY_ONE};
|
||||
|
||||
auto const prevStepQIn = prevStep_->lineQualityIn(sb);
|
||||
auto srcQOut = static_cast<TDerived const*>(this)->quality (
|
||||
sb, /* src quality out */ false);
|
||||
auto srcQOut =
|
||||
static_cast<TDerived const*>(this)->quality(sb, QualityDirection::out);
|
||||
|
||||
if (prevStepQIn > srcQOut)
|
||||
srcQOut = prevStepQIn;
|
||||
return {srcQOut, QUALITY_ONE};
|
||||
}
|
||||
else
|
||||
|
||||
// Returns srcQOut, dstQIn
|
||||
template <class TDerived>
|
||||
std::pair<std::uint32_t, std::uint32_t>
|
||||
DirectStepI<TDerived>::qualitiesSrcIssues(
|
||||
ReadView const& sb,
|
||||
DebtDirection prevStepDebtDirection) const
|
||||
{
|
||||
// Charge a transfer rate when issuing and previous step redeems
|
||||
auto const prevStepRedeems = prevStep_ && prevStep_->redeems (sb, fwd);
|
||||
assert (static_cast<TDerived const*>(this)->verifyPrevStepRedeems (
|
||||
prevStepRedeems));
|
||||
|
||||
std::uint32_t const srcQOut =
|
||||
prevStepRedeems ? transferRate (sb, src_).value : QUALITY_ONE;
|
||||
assert(static_cast<TDerived const*>(this)->verifyPrevStepDebtDirection(
|
||||
prevStepDebtDirection));
|
||||
|
||||
std::uint32_t const srcQOut = redeems(prevStepDebtDirection)
|
||||
? transferRate(sb, src_).value
|
||||
: QUALITY_ONE;
|
||||
auto dstQIn = static_cast<TDerived const*>(this)->quality(
|
||||
sb, /* dst quality in */ true);
|
||||
sb, QualityDirection::in);
|
||||
|
||||
if (isLast_ && dstQIn > QUALITY_ONE)
|
||||
dstQIn = QUALITY_ONE;
|
||||
return {srcQOut, dstQIn};
|
||||
}
|
||||
|
||||
// Returns srcQOut, dstQIn
|
||||
template <class TDerived>
|
||||
std::pair<std::uint32_t, std::uint32_t>
|
||||
DirectStepI<TDerived>::qualities(
|
||||
ReadView const& sb,
|
||||
DebtDirection srcDebtDir,
|
||||
StrandDirection strandDir) const
|
||||
{
|
||||
if (redeems(srcDebtDir))
|
||||
{
|
||||
return qualitiesSrcRedeems(sb);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const prevStepDebtDirection = [&] {
|
||||
if (prevStep_)
|
||||
return prevStep_->debtDirection(sb, strandDir);
|
||||
return DebtDirection::issues;
|
||||
}();
|
||||
return qualitiesSrcIssues(sb, prevStepDebtDirection);
|
||||
}
|
||||
}
|
||||
|
||||
template <class TDerived>
|
||||
@@ -789,19 +825,23 @@ DirectStepI<TDerived>::lineQualityIn (ReadView const& v) const
|
||||
{
|
||||
// dst quality in
|
||||
return static_cast<TDerived const*>(this)->quality (
|
||||
v, /* dst quality in */ true);
|
||||
v, QualityDirection::in);
|
||||
}
|
||||
|
||||
template <class TDerived>
|
||||
boost::optional<Quality>
|
||||
DirectStepI<TDerived>::qualityUpperBound(ReadView const& v, bool& redeems) const
|
||||
DirectStepI<TDerived>::qualityUpperBound(ReadView const& v, DebtDirection& dir)
|
||||
const
|
||||
{
|
||||
auto const prevRedeems = redeems;
|
||||
redeems = this->redeems(v, true);
|
||||
std::uint32_t const srcQOut =
|
||||
(prevRedeems && !redeems) ? transferRate(v, src_).value : QUALITY_ONE;
|
||||
auto dstQIn = static_cast<TDerived const*>(this)->quality (
|
||||
v, /* dst quality in */ true);
|
||||
auto const prevStepDebtDir = dir;
|
||||
dir = this->debtDirection(v, StrandDirection::forward);
|
||||
std::uint32_t const srcQOut = [&]() -> std::uint32_t {
|
||||
if (redeems(prevStepDebtDir) && issues(dir))
|
||||
return transferRate(v, src_).value;
|
||||
return QUALITY_ONE;
|
||||
}();
|
||||
auto dstQIn =
|
||||
static_cast<TDerived const*>(this)->quality(v, QualityDirection::in);
|
||||
|
||||
if (isLast_ && dstQIn > QUALITY_ONE)
|
||||
dstQIn = QUALITY_ONE;
|
||||
|
||||
@@ -34,6 +34,24 @@ class PaymentSandbox;
|
||||
class ReadView;
|
||||
class ApplyView;
|
||||
|
||||
enum class DebtDirection { issues, redeems };
|
||||
enum class QualityDirection { in, out };
|
||||
enum class StrandDirection { forward, reverse };
|
||||
|
||||
inline
|
||||
bool
|
||||
redeems(DebtDirection dir)
|
||||
{
|
||||
return dir == DebtDirection::redeems;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
issues(DebtDirection dir)
|
||||
{
|
||||
return dir == DebtDirection::issues;
|
||||
}
|
||||
|
||||
/**
|
||||
A step in a payment path
|
||||
|
||||
@@ -63,7 +81,6 @@ class ApplyView;
|
||||
class Step
|
||||
{
|
||||
public:
|
||||
/** Step destructor. */
|
||||
virtual ~Step() = default;
|
||||
|
||||
/**
|
||||
@@ -145,13 +162,10 @@ public:
|
||||
otherwise return true.
|
||||
|
||||
@param sb view with the strand's state of balances and offers
|
||||
@param fwd false -> called from rev(); true -> called from fwd().
|
||||
@param dir reverse -> called from rev(); forward -> called from fwd().
|
||||
*/
|
||||
virtual bool
|
||||
redeems (ReadView const& sb, bool fwd) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual DebtDirection
|
||||
debtDirection (ReadView const& sb, StrandDirection dir) const = 0;
|
||||
|
||||
/**
|
||||
If this step is a DirectStepI, return the quality in of the dst account.
|
||||
@@ -166,14 +180,14 @@ public:
|
||||
Find an upper bound of quality for the step
|
||||
|
||||
@param v view to query the ledger state from
|
||||
@param redeems in/out param. Set to true if the previous step redeems.
|
||||
Will be set to true if this step redeems; Will be set to false if this
|
||||
step does not redeem.
|
||||
@param dir in/out param. Set to DebtDirection::redeems if the previous step redeems.
|
||||
Will be set to DebtDirection::redeems if this step redeems; Will be set to DebtDirection::issues if this
|
||||
step does not redeem
|
||||
@return The upper bound of quality for the step, or boost::none if the
|
||||
step is dry.
|
||||
*/
|
||||
virtual boost::optional<Quality>
|
||||
qualityUpperBound(ReadView const& v, bool& redeems) const = 0;
|
||||
qualityUpperBound(ReadView const& v, DebtDirection& dir) const = 0;
|
||||
|
||||
/**
|
||||
If this step is a BookStep, return the book.
|
||||
|
||||
@@ -401,10 +401,10 @@ boost::optional<Quality>
|
||||
qualityUpperBound(ReadView const& v, Strand const& strand)
|
||||
{
|
||||
Quality q{STAmount::uRateOne};
|
||||
bool redeems = false;
|
||||
DebtDirection dir = DebtDirection::issues;
|
||||
for (auto const& step : strand)
|
||||
{
|
||||
if (auto const stepQ = step->qualityUpperBound(v, redeems))
|
||||
if (auto const stepQ = step->qualityUpperBound(v, dir))
|
||||
q = composed_quality(q, *stepQ);
|
||||
else
|
||||
return boost::none;
|
||||
|
||||
@@ -89,8 +89,14 @@ public:
|
||||
return cached ();
|
||||
}
|
||||
|
||||
DebtDirection
|
||||
debtDirection(ReadView const& sb, StrandDirection dir) const override
|
||||
{
|
||||
return DebtDirection::issues;
|
||||
}
|
||||
|
||||
boost::optional<Quality>
|
||||
qualityUpperBound(ReadView const& v, bool& redeems) const override;
|
||||
qualityUpperBound(ReadView const& v, DebtDirection& dir) const override;
|
||||
|
||||
std::pair<XRPAmount, XRPAmount>
|
||||
revImp (
|
||||
@@ -237,9 +243,9 @@ inline bool operator==(XRPEndpointStep<TDerived> const& lhs,
|
||||
template <class TDerived>
|
||||
boost::optional<Quality>
|
||||
XRPEndpointStep<TDerived>::qualityUpperBound(
|
||||
ReadView const& v, bool& redeems) const
|
||||
ReadView const& v, DebtDirection& dir) const
|
||||
{
|
||||
redeems = this->redeems(v, true);
|
||||
dir = this->debtDirection(v, StrandDirection::forward);
|
||||
return Quality{STAmount::uRateOne};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user