// Calculates the direct flow through the specified offer BasicTaker::Flow BasicTaker::do_cross (Amounts offer, Quality quality, AccountID const& owner) { assert (!done ()); auto const owner_funds = get_funds (owner, offer.out); auto const taker_funds = get_funds (account (), offer.in); Flow result; if (cross_type_ == CrossType::XrpToIou) { result = flow_xrp_to_iou (offer, quality, owner_funds, taker_funds, out_rate (owner, account ())); } else if (cross_type_ == CrossType::IouToXrp) { result = flow_iou_to_xrp (offer, quality, owner_funds, taker_funds, in_rate (owner, account ())); } else { result = flow_iou_to_iou (offer, quality, owner_funds, taker_funds, in_rate (owner, account ()), out_rate (owner, account ())); } if (!result.sanity_check ()) Throw<std::logic_error> ("Computed flow fails sanity check."); remaining_.out -= result.order.out; remaining_.in -= result.order.in; assert (remaining_.in >= zero); return result; }
void print_transitions(FILE *fpout) { FILE *fp; int ixtto; int srcnum,destnum; transition_info_type *tto; transition_info_type *ttoovf; tto = &trantos[0]; ttoovf = &trantos[tranto_knt]; for (ixtto=0;tto < ttoovf;++ixtto,++tto){ srcnum = (*tto).start_statenum; destnum = (*tto).dest_statenum; if (states[srcnum].coll_comments){ fp = fpout; if ((fp != ((FILE *) NULL)) && (states[srcnum].coll_comments)){ fprintf(fp,"%5d(* %s *),%5d(* %s *) = ", (int) srcnum, states[srcnum].coll_comments, (int) destnum, states[destnum].coll_comments); out_rate(fp,(*tto).rate,1,1); fprintf(fp,"\n");}}} }
// Calculates the bridged flow through the specified offers std::pair<BasicTaker::Flow, BasicTaker::Flow> BasicTaker::do_cross ( Amounts offer1, Quality quality1, AccountID const& owner1, Amounts offer2, Quality quality2, AccountID const& owner2) { assert (!done ()); assert (!offer1.in.native ()); assert (offer1.out.native ()); assert (offer2.in.native ()); assert (!offer2.out.native ()); // If the taker owns the first leg of the offer, then the taker's available // funds aren't the limiting factor for the input - the offer itself is. auto leg1_in_funds = get_funds (account (), offer1.in); if (account () == owner1) { journal_.trace << "The taker owns the first leg of a bridge."; leg1_in_funds = std::max (leg1_in_funds, offer1.in); } // If the taker owns the second leg of the offer, then the taker's available // funds are not the limiting factor for the output - the offer itself is. auto leg2_out_funds = get_funds (owner2, offer2.out); if (account () == owner2) { journal_.trace << "The taker owns the second leg of a bridge."; leg2_out_funds = std::max (leg2_out_funds, offer2.out); } // The amount available to flow via XRP is the amount that the owner of the // first leg of the bridge has, up to the first leg's output. // // But, when both legs of a bridge are owned by the same person, the amount // of XRP that can flow between the two legs is, essentially, infinite // since all the owner is doing is taking out XRP of his left pocket // and putting it in his right pocket. In that case, we set the available // XRP to the largest of the two offers. auto xrp_funds = get_funds (owner1, offer1.out); if (owner1 == owner2) { journal_.trace << "The bridge endpoints are owneb by the same account."; xrp_funds = std::max (offer1.out, offer2.in); } if (journal_.debug) { journal_.debug << "Available bridge funds:"; journal_.debug << " leg1 in: " << format_amount (leg1_in_funds); journal_.debug << " leg2 out: " << format_amount (leg2_out_funds); journal_.debug << " xrp: " << format_amount (xrp_funds); } auto const leg1_rate = in_rate (owner1, account ()); auto const leg2_rate = out_rate (owner2, account ()); // Attempt to determine the maximal flow that can be achieved across each // leg independent of the other. auto flow1 = flow_iou_to_xrp (offer1, quality1, xrp_funds, leg1_in_funds, leg1_rate); if (!flow1.sanity_check ()) Throw<std::logic_error> ("Computed flow1 fails sanity check."); auto flow2 = flow_xrp_to_iou (offer2, quality2, leg2_out_funds, xrp_funds, leg2_rate); if (!flow2.sanity_check ()) Throw<std::logic_error> ("Computed flow2 fails sanity check."); // We now have the maximal flows across each leg individually. We need to // equalize them, so that the amount of XRP that flows out of the first leg // is the same as the amount of XRP that flows into the second leg. We take // the side which is the limiting factor (if any) and adjust the other. if (flow1.order.out < flow2.order.in) { // 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); log_flow ("Balancing: adjusted second leg down", flow2); } else if (flow1.order.out > flow2.order.in) { // 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); log_flow ("Balancing: adjusted first leg down", flow2); } if (flow1.order.out != flow2.order.in) Throw<std::logic_error> ("Bridged flow is out of balance."); remaining_.out -= flow2.order.out; remaining_.in -= flow1.order.in; return std::make_pair (flow1, flow2); }