Esempio n. 1
0
// 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;
}
Esempio n. 2
0
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");}}}
}
Esempio n. 3
0
// 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);
}