Beispiel #1
0
void OrderBookDB::addOrderBook(Book const& book)
{
    bool toXDV = isXDV (book.out);
    ScopedLockType sl (mLock);

    if (toXDV)
    {
        // We don't want to search through all the to-XDV or from-XDV order
        // books!
        for (auto ob: mSourceMap[book.in])
        {
            if (isXDV (ob->getCurrencyOut ())) // also to XDV
                return;
        }
    }
    else
    {
        for (auto ob: mDestMap[book.out])
        {
            if (ob->getCurrencyIn() == book.in.currency &&
                ob->getIssuerIn() == book.in.account)
            {
                return;
            }
        }
    }
    uint256 index = getBookBase(book);
    auto orderBook = std::make_shared<OrderBook> (index, book);

    mSourceMap[book.in].push_back (orderBook);
    mDestMap[book.out].push_back (orderBook);
    if (toXDV)
        mXDVBooks.insert(book.in);
}
Beispiel #2
0
static void updateHelper (SLE::ref entry,
    hash_set< uint256 >& seen,
    OrderBookDB::IssueToOrderBook& destMap,
    OrderBookDB::IssueToOrderBook& sourceMap,
    hash_set< Issue >& XDVBooks,
    int& books)
{
    if (entry->getType () == ltDIR_NODE &&
        entry->isFieldPresent (sfExchangeRate) &&
        entry->getFieldH256 (sfRootIndex) == entry->getIndex())
    {
        Book book;
        book.in.currency.copyFrom (entry->getFieldH160 (sfTakerPaysCurrency));
        book.in.account.copyFrom (entry->getFieldH160 (sfTakerPaysIssuer));
        book.out.account.copyFrom (entry->getFieldH160 (sfTakerGetsIssuer));
        book.out.currency.copyFrom (entry->getFieldH160 (sfTakerGetsCurrency));

        uint256 index = getBookBase (book);
        if (seen.insert (index).second)
        {
            auto orderBook = std::make_shared<OrderBook> (index, book);
            sourceMap[book.in].push_back (orderBook);
            destMap[book.out].push_back (orderBook);
            if (isXDV(book.out))
                XDVBooks.insert(book.in);
            ++books;
        }
    }
}
Beispiel #3
0
std::vector<RippleAddress>
STTx::getMentionedAccounts () const
{
    std::vector<RippleAddress> accounts;

    for (auto const& it : peekData ())
    {
        if (auto sa = dynamic_cast<STAccount const*> (&it))
        {
            auto const na = sa->getValueNCA ();

            if (std::find (accounts.cbegin (), accounts.cend (), na) == accounts.cend ())
                accounts.push_back (na);
        }
        else if (auto sa = dynamic_cast<STAmount const*> (&it))
        {
            auto const& issuer = sa->getIssuer ();

            if (isXDV (issuer))
                continue;

            RippleAddress na;
            na.setAccountID (issuer);

            if (std::find (accounts.cbegin (), accounts.cend (), na) == accounts.cend ())
                accounts.push_back (na);
        }
    }

    return accounts;
}
Beispiel #4
0
Json::Value
trust (Account const& account,
    STAmount const& amount)
{
    if (isXDV(amount))
        throw std::runtime_error(
            "trust() requires IOU");
    Json::Value jv;
    jv[jss::Account] = account.human();
    jv[jss::LimitAmount] = amount.getJson(0);
    jv[jss::TransactionType] = "TrustSet";
    jv[jss::Flags] = 0;    // tfClearNoDivvy;
    return jv;
}
Beispiel #5
0
Json::Value doBookOffers (RPC::Context& context)
{
    // VFALCO TODO Here is a terrible place for this kind of business
    //             logic. It needs to be moved elsewhere and documented,
    //             and encapsulated into a function.
    if (getApp().getJobQueue ().getJobCountGE (jtCLIENT) > 200)
        return rpcError (rpcTOO_BUSY);

    Ledger::pointer lpLedger;
    Json::Value jvResult (
        RPC::lookupLedger (context.params, lpLedger, context.netOps));

    if (!lpLedger)
        return jvResult;

    if (!context.params.isMember (jss::taker_pays))
        return RPC::missing_field_error (jss::taker_pays);

    if (!context.params.isMember (jss::taker_gets))
        return RPC::missing_field_error (jss::taker_gets);

    if (!context.params[jss::taker_pays].isObject ())
        return RPC::object_field_error (jss::taker_pays);

    if (!context.params[jss::taker_gets].isObject ())
        return RPC::object_field_error (jss::taker_gets);

    Json::Value const& taker_pays (context.params[jss::taker_pays]);

    if (!taker_pays.isMember (jss::currency))
        return RPC::missing_field_error ("taker_pays.currency");

    if (! taker_pays [jss::currency].isString ())
        return RPC::expected_field_error ("taker_pays.currency", "string");

    Json::Value const& taker_gets = context.params[jss::taker_gets];

    if (! taker_gets.isMember (jss::currency))
        return RPC::missing_field_error ("taker_gets.currency");

    if (! taker_gets [jss::currency].isString ())
        return RPC::expected_field_error ("taker_gets.currency", "string");

    Currency pay_currency;

    if (!to_currency (pay_currency, taker_pays [jss::currency].asString ()))
    {
        WriteLog (lsINFO, RPCHandler) << "Bad taker_pays currency.";
        return RPC::make_error (rpcSRC_CUR_MALFORMED,
            "Invalid field 'taker_pays.currency', bad currency.");
    }

    Currency get_currency;

    if (!to_currency (get_currency, taker_gets [jss::currency].asString ()))
    {
        WriteLog (lsINFO, RPCHandler) << "Bad taker_gets currency.";
        return RPC::make_error (rpcDST_AMT_MALFORMED,
            "Invalid field 'taker_gets.currency', bad currency.");
    }

    AccountID pay_issuer;

    if (taker_pays.isMember (jss::issuer))
    {
        if (! taker_pays [jss::issuer].isString())
            return RPC::expected_field_error ("taker_pays.issuer", "string");

        if (!to_issuer(
            pay_issuer, taker_pays [jss::issuer].asString ()))
            return RPC::make_error (rpcSRC_ISR_MALFORMED,
                "Invalid field 'taker_pays.issuer', bad issuer.");

        if (pay_issuer == noAccount ())
            return RPC::make_error (rpcSRC_ISR_MALFORMED,
                "Invalid field 'taker_pays.issuer', bad issuer account one.");
    }
    else
    {
        pay_issuer = xdvAccount ();
    }

    if (isXDV (pay_currency) && ! isXDV (pay_issuer))
        return RPC::make_error (
            rpcSRC_ISR_MALFORMED, "Unneeded field 'taker_pays.issuer' for "
            "XDV currency specification.");

    if (!isXDV (pay_currency) && isXDV (pay_issuer))
        return RPC::make_error (rpcSRC_ISR_MALFORMED,
            "Invalid field 'taker_pays.issuer', expected non-XDV issuer.");

    AccountID get_issuer;

    if (taker_gets.isMember (jss::issuer))
    {
        if (! taker_gets [jss::issuer].isString())
            return RPC::expected_field_error ("taker_gets.issuer", "string");

        if (! to_issuer (
            get_issuer, taker_gets [jss::issuer].asString ()))
            return RPC::make_error (rpcDST_ISR_MALFORMED,
                "Invalid field 'taker_gets.issuer', bad issuer.");

        if (get_issuer == noAccount ())
            return RPC::make_error (rpcDST_ISR_MALFORMED,
                "Invalid field 'taker_gets.issuer', bad issuer account one.");
    }
    else
    {
        get_issuer = xdvAccount ();
    }


    if (isXDV (get_currency) && ! isXDV (get_issuer))
        return RPC::make_error (rpcDST_ISR_MALFORMED,
            "Unneeded field 'taker_gets.issuer' for "
                               "XDV currency specification.");

    if (!isXDV (get_currency) && isXDV (get_issuer))
        return RPC::make_error (rpcDST_ISR_MALFORMED,
            "Invalid field 'taker_gets.issuer', expected non-XDV issuer.");

    DivvyAddress raTakerID;

    if (context.params.isMember (jss::taker))
    {
        if (! context.params [jss::taker].isString ())
            return RPC::expected_field_error (jss::taker, "string");

        if (! raTakerID.setAccountID (context.params [jss::taker].asString ()))
            return RPC::invalid_field_error (jss::taker);
    }
    else
    {
        raTakerID.setAccountID (noAccount());
    }

    if (pay_currency == get_currency && pay_issuer == get_issuer)
    {
        WriteLog (lsINFO, RPCHandler) << "taker_gets same as taker_pays.";
        return RPC::make_error (rpcBAD_MARKET);
    }

    unsigned int iLimit;
    if (context.params.isMember (jss::limit))
    {
        auto const& jvLimit (context.params[jss::limit]);

        if (! jvLimit.isIntegral ())
            return RPC::expected_field_error (jss::limit, "unsigned integer");

        iLimit = jvLimit.isUInt () ? jvLimit.asUInt () :
            std::max (0, jvLimit.asInt ());
    }
    else
    {
        iLimit = 0;
    }

    bool const bProof (context.params.isMember (jss::proof));

    Json::Value const jvMarker (context.params.isMember (jss::marker)
        ? context.params[jss::marker]
        : Json::Value (Json::nullValue));

    context.netOps.getBookPage (
        context.role == Role::ADMIN,
        lpLedger,
        {{pay_currency, pay_issuer}, {get_currency, get_issuer}},
        raTakerID.getAccountID (), bProof, iLimit, jvMarker, jvResult);

    context.loadType = Resource::feeMediumBurdenRPC;

    return jvResult;
}