20 #include <ripple/app/tx/impl/Taker.h>
21 #include <ripple/basics/contract.h>
22 #include <ripple/basics/Log.h>
42 , threshold_ (quality_)
46 , issue_in_ (remaining_.
in.issue ())
47 , issue_out_ (remaining_.
out.issue ())
49 , m_rate_out (rate_out)
50 , cross_type_ (cross_type)
101 JLOG(
journal_.
debug()) <<
"Unfunded: taker is out of funds.";
111 JLOG(
journal_.
debug()) <<
"Done: all the input currency has been consumed.";
119 JLOG(
journal_.
debug()) <<
"Done: the desired amount has been received.";
173 auto result =
divide (amount, quality.rate (), output.
issue ());
181 auto result =
multiply (amount, quality.rate (), output.
issue ());
192 stream << description;
209 Amounts
const& order, Quality quality,
211 Rate const& rate_out)
220 if (owner_funds < f.
issuers.out)
225 log_flow (
"(clamped on owner balance)", f);
234 log_flow (
"(clamped on taker output)", f);
238 if (taker_funds < f.
order.in)
240 f.
order.in = taker_funds;
243 log_flow (
"(clamped on taker funds)", f);
253 log_flow (
"(clamped on taker input)", f);
261 Amounts
const& order, Quality quality,
272 if (owner_funds < f.
order.out)
274 f.
order.out = owner_funds;
277 log_flow (
"(clamped on owner funds)", f);
289 log_flow (
"(clamped on taker output)", f);
299 log_flow (
"(clamped on taker input)", f);
303 if (taker_funds < f.
issuers.in)
308 log_flow (
"(clamped on taker funds)", f);
316 Amounts
const& order, Quality quality,
318 Rate const& rate_in,
Rate const& rate_out)
328 if (owner_funds < f.
issuers.out)
334 log_flow (
"(clamped on owner funds)", f);
344 log_flow (
"(clamped on taker output)", f);
354 log_flow (
"(clamped on taker input)", f);
358 if (taker_funds < f.
issuers.in)
364 log_flow (
"(clamped on taker funds)", f);
374 auto const owner_funds =
get_funds (owner, offer.out);
396 Throw<std::logic_error> (
"Computed flow fails sanity check.");
409 Amounts offer1, Quality quality1,
AccountID const& owner1,
410 Amounts offer2, Quality quality2,
AccountID const& owner2)
412 assert (!offer1.in.native ());
413 assert (offer1.out.native ());
414 assert (offer2.in.native ());
415 assert (!offer2.out.native ());
423 JLOG(
journal_.
trace()) <<
"The taker owns the first leg of a bridge.";
424 leg1_in_funds =
std::max (leg1_in_funds, offer1.in);
429 auto leg2_out_funds =
get_funds (owner2, offer2.out);
433 JLOG(
journal_.
trace()) <<
"The taker owns the second leg of a bridge.";
434 leg2_out_funds =
std::max (leg2_out_funds, offer2.out);
445 auto xrp_funds =
get_funds (owner1, offer1.out);
447 if (owner1 == owner2)
450 "The bridge endpoints are owned by the same account.";
451 xrp_funds =
std::max (offer1.out, offer2.in);
456 stream <<
"Available bridge funds:";
467 auto flow1 =
flow_iou_to_xrp (offer1, quality1, xrp_funds, leg1_in_funds, leg1_rate);
469 if (!flow1.sanity_check ())
470 Throw<std::logic_error> (
"Computed flow1 fails sanity check.");
472 auto flow2 =
flow_xrp_to_iou (offer2, quality2, leg2_out_funds, xrp_funds, leg2_rate);
474 if (!flow2.sanity_check ())
475 Throw<std::logic_error> (
"Computed flow2 fails sanity check.");
481 if (flow1.order.out < flow2.order.in)
484 flow2.order.in = flow1.order.out;
485 flow2.order.out =
qual_div (flow2.order.in, quality2, flow2.order.out);
486 flow2.issuers.out =
multiply (flow2.order.out, leg2_rate);
487 log_flow (
"Balancing: adjusted second leg down", flow2);
489 else if (flow1.order.out > flow2.order.in)
492 flow1.order.out = flow2.order.in;
493 flow1.order.in =
qual_mul (flow1.order.out, quality1, flow1.order.in);
494 flow1.issuers.in =
multiply (flow1.order.in, leg1_rate);
495 log_flow (
"Balancing: adjusted first leg down", flow2);
498 if (flow1.order.out != flow2.order.in)
499 Throw<std::logic_error> (
"Bridged flow is out of balance.");
510 AccountID const& account, Amounts
const& offer,
513 :
BasicTaker (cross_type, account, offer, Quality(offer), flags,
514 calculateRate(view, offer.
in.getIssuer(), account),
515 calculateRate(view, offer.
out.getIssuer(), account), journal)
518 , direct_crossings_ (0)
519 , bridge_crossings_ (0)
521 assert (
issue_in () == offer.in.issue ());
522 assert (
issue_out () == offer.out.issue ());
548 if (order.in < beast::zero)
549 Throw<std::logic_error> (
"flow with negative input.");
551 if (order.out < beast::zero)
552 Throw<std::logic_error> (
"flow with negative output.");
558 auto const& available = offer.amount ();
564 offer.consume (
view_, order);
579 Throw<std::logic_error> (
"Using transferXRP with IOU");
585 if (amount == beast::zero)
597 Throw<std::logic_error> (
"Using redeemIOU with XRP");
603 if (amount == beast::zero)
609 Throw<std::logic_error> (
"redeemIOU has no funds to redeem");
614 Throw<std::logic_error> (
"redeemIOU redeemed more funds than available");
625 Throw<std::logic_error> (
"Using issueIOU with XRP");
631 if (amount == beast::zero)
670 result =
redeemIOU (offer.owner (),
flow.issuers.out,
flow.issuers.out.issue ());
738 if (
isXRP (offer.amount ().in) &&
isXRP (offer.amount ().out))
742 offer.amount (), offer.quality (), offer.owner ());
744 return fill (amount, offer);
759 return fill (ret.first, leg1, ret.second, leg2);
STAmount get_funds(AccountID const &account, STAmount const &funds) const override
Rate transferRate(ReadView const &view, AccountID const &issuer)
A currency issued by an account.
Represents a transfer rate.
TER fill(BasicTaker::Flow const &flow, Offer &offer)
Stream trace() const
Severity stream access functions.
bool unfunded() const
Returns true if the taker has run out of funds.
Flow flow_iou_to_iou(Amounts const &offer, Quality quality, STAmount const &owner_funds, STAmount const &taker_funds, Rate const &rate_in, Rate const &rate_out)
static STAmount qual_div(STAmount const &amount, Quality const &quality, STAmount const &output)
BasicTaker::Flow do_cross(Amounts offer, Quality quality, AccountID const &owner)
Perform direct crossing through given offer.
static STAmount qual_mul(STAmount const &amount, Quality const &quality, STAmount const &output)
Amounts remaining_offer() const
Returns the amount remaining on the offer.
const std::uint32_t tfPassive
Rate in_rate(AccountID const &from, AccountID const &to) const
std::string getText() const override
std::uint32_t direct_crossings_
void log_flow(char const *description, Flow const &flow)
static std::string format_amount(STAmount const &amount)
Issue const & issue_in() const
Returns the Issue associated with the input of the offer.
Flow flow_xrp_to_iou(Amounts const &offer, Quality quality, STAmount const &owner_funds, STAmount const &taker_funds, Rate const &rate_out)
State for the active party during order book or payment operations.
std::string to_string(ListDisposition disposition)
CrossType cross_type() const
Returns the type of crossing that is being performed.
const beast::Journal journal_
const Rate parityRate(QUALITY_ONE)
A transfer rate signifying a 1:1 exchange.
Writeable view to a ledger, for applying a transaction.
TER redeemIOU(AccountID const &account, STAmount const &amount, Issue const &issue)
STAmount mulRound(STAmount const &v1, STAmount const &v2, Issue const &issue, bool roundUp)
const Quality quality() const noexcept
Returns the quality of the offer.
TAmounts< TIn, TOut > const & amount() const
Returns the in and out amounts.
Flow flow_iou_to_xrp(Amounts const &offer, Quality quality, STAmount const &owner_funds, STAmount const &taker_funds, Rate const &rate_in)
static Rate calculateRate(ApplyView const &view, AccountID const &issuer, AccountID const &account)
STAmount divide(STAmount const &amount, Rate const &rate)
Issue const & issue_out() const
Returns the Issue associated with the output of the offer.
CrossType
The flavor of an offer crossing.
STAmount divRound(STAmount const &num, STAmount const &den, Issue const &issue, bool roundUp)
TER issueIOU(AccountID const &account, STAmount const &amount, Issue const &issue)
AccountID const & owner() const
Returns the account id of the offer's owner.
Amounts const & original_offer() const
Returns the amount that the offer was originally placed at.
bool isXRP(AccountID const &c)
void consume_offer(Offer &offer, Amounts const &order)
A generic endpoint for log messages.
std::uint32_t bridge_crossings_
bool sanity_check() const
static Rate effective_rate(Rate const &rate, Issue const &issue, AccountID const &from, AccountID const &to)
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
TER transferXRP(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &amount, beast::Journal j)
STAmount multiply(STAmount const &amount, Rate const &rate)
virtual STAmount get_funds(AccountID const &account, STAmount const &funds) const =0
TER issueIOU(ApplyView &view, AccountID const &account, STAmount const &amount, Issue const &issue, beast::Journal j)
bool done() const
Returns true if order crossing should not continue.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
const std::uint32_t tfSell
TER redeemIOU(ApplyView &view, AccountID const &account, STAmount const &amount, Issue const &issue, beast::Journal j)
Issue const & issue() const
TER transferXRP(AccountID const &from, AccountID const &to, STAmount const &amount)
path::RippleCalc::Output flow(PaymentSandbox &view, STAmount const &deliver, AccountID const &src, AccountID const &dst, STPathSet const &paths, bool defaultPaths, bool partialPayment, bool ownerPaysTransferFee, bool offerCrossing, boost::optional< Quality > const &limitQuality, boost::optional< STAmount > const &sendMax, beast::Journal j, path::detail::FlowDebugInfo *flowDebugInfo=nullptr)
Make a payment from the src account to the dst account.
AccountID const & account() const noexcept
Returns the account identifier of the taker.
TER cross(Offer &offer)
Perform a direct or bridged offer crossing as appropriate.
Rate out_rate(AccountID const &from, AccountID const &to) const