예제 #1
0
// Note: This function is currently only used in AllowTrustOpFrame, which means
// the asset parameter will never satisfy asset.type() == ASSET_TYPE_NATIVE. As
// a consequence, I have not implemented that possibility so this function
// throws in that case.
std::vector<LedgerEntry>
LedgerStateRoot::Impl::loadOffersByAccountAndAsset(AccountID const& accountID,
                                                   Asset const& asset) const
{
    std::string sql = "SELECT sellerid, offerid, "
                      "sellingassettype, sellingassetcode, sellingissuer, "
                      "buyingassettype, buyingassetcode, buyingissuer, "
                      "amount, pricen, priced, flags, lastmodified "
                      "FROM offers ";
    sql += " WHERE sellerid = :acc"
           " AND ((sellingassetcode = :code AND sellingissuer = :iss)"
           " OR   (buyingassetcode = :code AND buyingissuer = :iss))";

    std::string accountStr = KeyUtils::toStrKey(accountID);

    std::string assetCode;
    std::string assetIssuer;
    if (asset.type() == ASSET_TYPE_CREDIT_ALPHANUM4)
    {
        assetCodeToStr(asset.alphaNum4().assetCode, assetCode);
        assetIssuer = KeyUtils::toStrKey(asset.alphaNum4().issuer);
    }
    else if (asset.type() == ASSET_TYPE_CREDIT_ALPHANUM12)
    {
        assetCodeToStr(asset.alphaNum12().assetCode, assetCode);
        assetIssuer = KeyUtils::toStrKey(asset.alphaNum12().issuer);
    }
    else
    {
        throw std::runtime_error("Invalid asset type");
    }

    auto prep = mDatabase.getPreparedStatement(sql);
    auto& st = prep.statement();
    st.exchange(soci::use(accountStr, "acc"));
    st.exchange(soci::use(assetCode, "code"));
    st.exchange(soci::use(assetIssuer, "iss"));

    std::vector<LedgerEntry> offers;
    {
        auto timer = mDatabase.getSelectTimer("offer");
        offers = loadOffers(prep);
    }
    return offers;
}
예제 #2
0
파일: OfferFrame.cpp 프로젝트: tctx/network
void
OfferFrame::storeUpdateHelper(LedgerDelta& delta, Database& db, bool insert)
{
    touch(delta);

    if (!isValid())
    {
        throw std::runtime_error("Invalid asset");
    }

    std::string actIDStrKey = PubKeyUtils::toStrKey(mOffer.sellerID);

    unsigned int sellingType = mOffer.selling.type();
    unsigned int buyingType = mOffer.buying.type();
    std::string sellingIssuerStrKey, buyingIssuerStrKey;
    std::string sellingAssetCode, buyingAssetCode;
    soci::indicator selling_ind = soci::i_null, buying_ind = soci::i_null;

    if (sellingType == ASSET_TYPE_CREDIT_ALPHANUM4)
    {
        sellingIssuerStrKey =
            PubKeyUtils::toStrKey(mOffer.selling.alphaNum4().issuer);
        assetCodeToStr(mOffer.selling.alphaNum4().assetCode, sellingAssetCode);
        selling_ind = soci::i_ok;
    }
    else if (sellingType == ASSET_TYPE_CREDIT_ALPHANUM12)
    {
        sellingIssuerStrKey =
            PubKeyUtils::toStrKey(mOffer.selling.alphaNum12().issuer);
        assetCodeToStr(mOffer.selling.alphaNum12().assetCode, sellingAssetCode);
        selling_ind = soci::i_ok;
    }

    if (buyingType == ASSET_TYPE_CREDIT_ALPHANUM4)
    {
        buyingIssuerStrKey =
            PubKeyUtils::toStrKey(mOffer.buying.alphaNum4().issuer);
        assetCodeToStr(mOffer.buying.alphaNum4().assetCode, buyingAssetCode);
        buying_ind = soci::i_ok;
    }
    else if (buyingType == ASSET_TYPE_CREDIT_ALPHANUM12)
    {
        buyingIssuerStrKey =
            PubKeyUtils::toStrKey(mOffer.buying.alphaNum12().issuer);
        assetCodeToStr(mOffer.buying.alphaNum12().assetCode, buyingAssetCode);
        buying_ind = soci::i_ok;
    }

    string sql;

    if (insert)
    {
        sql = "INSERT INTO offers (sellerid,offerid,"
              "sellingassettype,sellingassetcode,sellingissuer,"
              "buyingassettype,buyingassetcode,buyingissuer,"
              "amount,pricen,priced,price,flags,lastmodified) VALUES "
              "(:sid,:oid,:sat,:sac,:si,:bat,:bac,:bi,:a,:pn,:pd,:p,:f,:l)";
    }
    else
    {
        sql = "UPDATE offers SET sellingassettype=:sat "
              ",sellingassetcode=:sac,sellingissuer=:si,"
              "buyingassettype=:bat,buyingassetcode=:bac,buyingissuer=:bi,"
              "amount=:a,pricen=:pn,priced=:pd,price=:p,flags=:f,"
              "lastmodified=:l WHERE offerid=:oid";
    }

    auto prep = db.getPreparedStatement(sql);
    auto& st = prep.statement();

    if (insert)
    {
        st.exchange(use(actIDStrKey, "sid"));
    }
    st.exchange(use(mOffer.offerID, "oid"));
    st.exchange(use(sellingType, "sat"));
    st.exchange(use(sellingAssetCode, selling_ind, "sac"));
    st.exchange(use(sellingIssuerStrKey, selling_ind, "si"));
    st.exchange(use(buyingType, "bat"));
    st.exchange(use(buyingAssetCode, buying_ind, "bac"));
    st.exchange(use(buyingIssuerStrKey, buying_ind, "bi"));
    st.exchange(use(mOffer.amount, "a"));
    st.exchange(use(mOffer.price.n, "pn"));
    st.exchange(use(mOffer.price.d, "pd"));
    auto price = computePrice();
    st.exchange(use(price, "p"));
    st.exchange(use(mOffer.flags, "f"));
    st.exchange(use(getLastModified(), "l"));
    st.define_and_bind();

    auto timer =
        insert ? db.getInsertTimer("offer") : db.getUpdateTimer("offer");
    st.execute(true);

    if (st.get_affected_rows() != 1)
    {
        throw std::runtime_error("could not update SQL");
    }

    if (insert)
    {
        delta.addEntry(*this);
    }
    else
    {
        delta.modEntry(*this);
    }
}
예제 #3
0
파일: OfferFrame.cpp 프로젝트: tctx/network
void
OfferFrame::loadBestOffers(size_t numOffers, size_t offset,
                           Asset const& selling, Asset const& buying,
                           vector<OfferFrame::pointer>& retOffers, Database& db)
{
    std::string sql = offerColumnSelector;

    std::string sellingAssetCode, sellingIssuerStrKey;
    std::string buyingAssetCode, buyingIssuerStrKey;

    bool useSellingAsset = false;
    bool useBuyingAsset = false;

    if (selling.type() == ASSET_TYPE_NATIVE)
    {
        sql += " WHERE sellingassettype = 0";
    }
    else
    {
        if (selling.type() == ASSET_TYPE_CREDIT_ALPHANUM4)
        {
            assetCodeToStr(selling.alphaNum4().assetCode, sellingAssetCode);
            sellingIssuerStrKey =
                PubKeyUtils::toStrKey(selling.alphaNum4().issuer);
        }
        else if (selling.type() == ASSET_TYPE_CREDIT_ALPHANUM12)
        {
            assetCodeToStr(selling.alphaNum12().assetCode, sellingAssetCode);
            sellingIssuerStrKey =
                PubKeyUtils::toStrKey(selling.alphaNum12().issuer);
        }
        else
        {
            throw std::runtime_error("unknown asset type");
        }

        useSellingAsset = true;
        sql += " WHERE sellingassetcode = :pcur AND sellingissuer = :pi";
    }

    if (buying.type() == ASSET_TYPE_NATIVE)
    {
        sql += " AND buyingassettype = 0";
    }
    else
    {
        if (buying.type() == ASSET_TYPE_CREDIT_ALPHANUM4)
        {
            assetCodeToStr(buying.alphaNum4().assetCode, buyingAssetCode);
            buyingIssuerStrKey =
                PubKeyUtils::toStrKey(buying.alphaNum4().issuer);
        }
        else if (buying.type() == ASSET_TYPE_CREDIT_ALPHANUM12)
        {
            assetCodeToStr(buying.alphaNum12().assetCode, buyingAssetCode);
            buyingIssuerStrKey =
                PubKeyUtils::toStrKey(buying.alphaNum12().issuer);
        }
        else
        {
            throw std::runtime_error("unknown asset type");
        }

        useBuyingAsset = true;
        sql += " AND buyingassetcode = :gcur AND buyingissuer = :gi";
    }

    // price is an approximation of the actual n/d (truncated math, 15 digits)
    // ordering by offerid gives precendence to older offers for fairness
    sql += " ORDER BY price, offerid LIMIT :n OFFSET :o";

    auto prep = db.getPreparedStatement(sql);
    auto& st = prep.statement();

    if (useSellingAsset)
    {
        st.exchange(use(sellingAssetCode));
        st.exchange(use(sellingIssuerStrKey));
    }

    if (useBuyingAsset)
    {
        st.exchange(use(buyingAssetCode));
        st.exchange(use(buyingIssuerStrKey));
    }

    st.exchange(use(numOffers));
    st.exchange(use(offset));

    auto timer = db.getSelectTimer("offer");
    loadOffers(prep, [&retOffers](LedgerEntry const& of)
               {
                   retOffers.emplace_back(make_shared<OfferFrame>(of));
               });
}
예제 #4
0
std::list<LedgerEntry>::const_iterator
LedgerStateRoot::Impl::loadBestOffers(std::list<LedgerEntry>& offers,
                                      Asset const& buying, Asset const& selling,
                                      size_t numOffers, size_t offset) const
{
    std::string sql = "SELECT sellerid, offerid, "
                      "sellingassettype, sellingassetcode, sellingissuer, "
                      "buyingassettype, buyingassetcode, buyingissuer, "
                      "amount, pricen, priced, flags, lastmodified "
                      "FROM offers ";

    std::string sellingAssetCode, sellingIssuerStrKey;
    if (selling.type() == ASSET_TYPE_NATIVE)
    {
        sql += " WHERE sellingassettype = 0 AND sellingissuer IS NULL";
    }
    else
    {
        if (selling.type() == ASSET_TYPE_CREDIT_ALPHANUM4)
        {
            assetCodeToStr(selling.alphaNum4().assetCode, sellingAssetCode);
            sellingIssuerStrKey =
                KeyUtils::toStrKey(selling.alphaNum4().issuer);
        }
        else if (selling.type() == ASSET_TYPE_CREDIT_ALPHANUM12)
        {
            assetCodeToStr(selling.alphaNum12().assetCode, sellingAssetCode);
            sellingIssuerStrKey =
                KeyUtils::toStrKey(selling.alphaNum12().issuer);
        }
        else
        {
            throw std::runtime_error("unknown asset type");
        }
        sql += " WHERE sellingassetcode = :sac AND sellingissuer = :si";
    }

    std::string buyingAssetCode, buyingIssuerStrKey;
    if (buying.type() == ASSET_TYPE_NATIVE)
    {
        sql += " AND buyingassettype = 0 AND buyingissuer IS NULL";
    }
    else
    {
        if (buying.type() == ASSET_TYPE_CREDIT_ALPHANUM4)
        {
            assetCodeToStr(buying.alphaNum4().assetCode, buyingAssetCode);
            buyingIssuerStrKey = KeyUtils::toStrKey(buying.alphaNum4().issuer);
        }
        else if (buying.type() == ASSET_TYPE_CREDIT_ALPHANUM12)
        {
            assetCodeToStr(buying.alphaNum12().assetCode, buyingAssetCode);
            buyingIssuerStrKey = KeyUtils::toStrKey(buying.alphaNum12().issuer);
        }
        else
        {
            throw std::runtime_error("unknown asset type");
        }
        sql += " AND buyingassetcode = :bac AND buyingissuer = :bi";
    }

    // price is an approximation of the actual n/d (truncated math, 15 digits)
    // ordering by offerid gives precendence to older offers for fairness
    sql += " ORDER BY price, offerid LIMIT :n OFFSET :o";

    auto prep = mDatabase.getPreparedStatement(sql);
    auto& st = prep.statement();
    if (selling.type() != ASSET_TYPE_NATIVE)
    {
        st.exchange(soci::use(sellingAssetCode, "sac"));
        st.exchange(soci::use(sellingIssuerStrKey, "si"));
    }
    if (buying.type() != ASSET_TYPE_NATIVE)
    {
        st.exchange(soci::use(buyingAssetCode, "bac"));
        st.exchange(soci::use(buyingIssuerStrKey, "bi"));
    }
    st.exchange(soci::use(numOffers, "n"));
    st.exchange(soci::use(offset, "o"));

    {
        auto timer = mDatabase.getSelectTimer("offer");
        return loadOffers(prep, offers);
    }
}
예제 #5
0
void
LedgerStateRoot::Impl::insertOrUpdateOffer(LedgerEntry const& entry,
                                           bool isInsert)
{
    auto const& offer = entry.data.offer();
    std::string actIDStrKey = KeyUtils::toStrKey(offer.sellerID);

    unsigned int sellingType = offer.selling.type();
    unsigned int buyingType = offer.buying.type();
    std::string sellingIssuerStrKey, buyingIssuerStrKey;
    std::string sellingAssetCode, buyingAssetCode;
    soci::indicator selling_ind = soci::i_null, buying_ind = soci::i_null;
    double price = double(offer.price.n) / double(offer.price.d);

    if (sellingType == ASSET_TYPE_CREDIT_ALPHANUM4)
    {
        sellingIssuerStrKey =
            KeyUtils::toStrKey(offer.selling.alphaNum4().issuer);
        assetCodeToStr(offer.selling.alphaNum4().assetCode, sellingAssetCode);
        selling_ind = soci::i_ok;
    }
    else if (sellingType == ASSET_TYPE_CREDIT_ALPHANUM12)
    {
        sellingIssuerStrKey =
            KeyUtils::toStrKey(offer.selling.alphaNum12().issuer);
        assetCodeToStr(offer.selling.alphaNum12().assetCode, sellingAssetCode);
        selling_ind = soci::i_ok;
    }

    if (buyingType == ASSET_TYPE_CREDIT_ALPHANUM4)
    {
        buyingIssuerStrKey =
            KeyUtils::toStrKey(offer.buying.alphaNum4().issuer);
        assetCodeToStr(offer.buying.alphaNum4().assetCode, buyingAssetCode);
        buying_ind = soci::i_ok;
    }
    else if (buyingType == ASSET_TYPE_CREDIT_ALPHANUM12)
    {
        buyingIssuerStrKey =
            KeyUtils::toStrKey(offer.buying.alphaNum12().issuer);
        assetCodeToStr(offer.buying.alphaNum12().assetCode, buyingAssetCode);
        buying_ind = soci::i_ok;
    }

    std::string sql;
    if (isInsert)
    {
        sql = "INSERT INTO offers (sellerid,offerid,"
              "sellingassettype,sellingassetcode,sellingissuer,"
              "buyingassettype,buyingassetcode,buyingissuer,"
              "amount,pricen,priced,price,flags,lastmodified) VALUES "
              "(:sid,:oid,:sat,:sac,:si,:bat,:bac,:bi,:a,:pn,:pd,:p,:f,:l)";
    }
    else
    {
        sql = "UPDATE offers SET sellingassettype=:sat,"
              "sellingassetcode=:sac,sellingissuer=:si,"
              "buyingassettype=:bat,buyingassetcode=:bac,buyingissuer=:bi,"
              "amount=:a,pricen=:pn,priced=:pd,price=:p,flags=:f,"
              "lastmodified=:l WHERE offerid=:oid";
    }

    auto prep = mDatabase.getPreparedStatement(sql);
    auto& st = prep.statement();
    if (isInsert)
    {
        st.exchange(soci::use(actIDStrKey, "sid"));
    }
    st.exchange(soci::use(offer.offerID, "oid"));
    st.exchange(soci::use(sellingType, "sat"));
    st.exchange(soci::use(sellingAssetCode, selling_ind, "sac"));
    st.exchange(soci::use(sellingIssuerStrKey, selling_ind, "si"));
    st.exchange(soci::use(buyingType, "bat"));
    st.exchange(soci::use(buyingAssetCode, buying_ind, "bac"));
    st.exchange(soci::use(buyingIssuerStrKey, buying_ind, "bi"));
    st.exchange(soci::use(offer.amount, "a"));
    st.exchange(soci::use(offer.price.n, "pn"));
    st.exchange(soci::use(offer.price.d, "pd"));
    st.exchange(soci::use(price, "p"));
    st.exchange(soci::use(offer.flags, "f"));
    st.exchange(soci::use(entry.lastModifiedLedgerSeq, "l"));
    st.define_and_bind();
    {
        auto timer = isInsert ? mDatabase.getInsertTimer("offer")
                              : mDatabase.getUpdateTimer("offer");
        st.execute(true);
    }
    if (st.get_affected_rows() != 1)
    {
        throw std::runtime_error("could not update SQL");
    }
}
예제 #6
0
void
OfferFrame::storeAdd(LedgerDelta& delta, Database& db) const
{
    std::string actIDStrKey = PubKeyUtils::toStrKey(mOffer.sellerID);

    soci::statement st(db.getSession().prepare << "select 1");

    auto timer = db.getInsertTimer("offer");

    unsigned int sellingType = mOffer.selling.type();
    unsigned int buyingType = mOffer.buying.type();
    std::string sellingIssuerStrKey, buyingIssuerStrKey;
    std::string sellingAssetCode, buyingAssetCode;

    if(sellingType == ASSET_TYPE_CREDIT_ALPHANUM4)
    {
        sellingIssuerStrKey =
            PubKeyUtils::toStrKey(mOffer.selling.alphaNum4().issuer); 
        assetCodeToStr(mOffer.selling.alphaNum4().assetCode,
            sellingAssetCode);
       
    } else if(sellingType == ASSET_TYPE_CREDIT_ALPHANUM12)
    {
        sellingIssuerStrKey =
            PubKeyUtils::toStrKey(mOffer.selling.alphaNum12().issuer);
        assetCodeToStr(mOffer.selling.alphaNum12().assetCode,
            sellingAssetCode);
    }

    if(buyingType == ASSET_TYPE_CREDIT_ALPHANUM4)
    {
        buyingIssuerStrKey =
            PubKeyUtils::toStrKey(mOffer.buying.alphaNum4().issuer);
        assetCodeToStr(mOffer.buying.alphaNum4().assetCode,
            buyingAssetCode);

    } else if(buyingType == ASSET_TYPE_CREDIT_ALPHANUM12)
    {
        buyingIssuerStrKey =
            PubKeyUtils::toStrKey(mOffer.buying.alphaNum12().issuer);
        assetCodeToStr(mOffer.buying.alphaNum12().assetCode,
            buyingAssetCode);
    }
    
   
    
    st = (db.getSession().prepare
        << "INSERT INTO offers (sellerid,offerid,"
        "sellingassettype,sellingassetcode,sellingissuer,"
        "buyingassettype,buyingassetcode,buyingissuer,"
        "amount,pricen,priced,price,flags) VALUES "
        "(:v1,:v2,:v3,:v4,:v5,:v6,:v7,:v8,:v9,:v10,:v11,:v12,:v13)",
        use(actIDStrKey), use(mOffer.offerID), use(sellingType), 
        use(sellingAssetCode),
        use(sellingIssuerStrKey), use(buyingType), use(buyingAssetCode),
        use(buyingIssuerStrKey), use(mOffer.amount), use(mOffer.price.n),
        use(mOffer.price.d), use(computePrice()), use(mOffer.flags));
    st.execute(true);
    

    if (st.get_affected_rows() != 1)
    {
        throw std::runtime_error("could not update SQL");
    }

    delta.addEntry(*this);
}
예제 #7
0
void
OfferFrame::loadBestOffers(size_t numOffers, size_t offset,
                           Asset const& selling, Asset const& buying,
                           vector<OfferFrame::pointer>& retOffers, Database& db)
{
    soci::session& session = db.getSession();

    soci::details::prepare_temp_type sql =
        (session.prepare << offerColumnSelector);

    std::string sellingAssetCode, sellingIssuerStrKey;
    std::string buyingAssetCode, buyingIssuerStrKey;

    if (selling.type() == ASSET_TYPE_NATIVE)
    {
        sql << " WHERE sellingassettype=0";
    }
    else
    {
        if(selling.type() == ASSET_TYPE_CREDIT_ALPHANUM4)
        {
            assetCodeToStr(selling.alphaNum4().assetCode, sellingAssetCode);
            sellingIssuerStrKey = PubKeyUtils::toStrKey(selling.alphaNum4().issuer);
        } else if(selling.type() == ASSET_TYPE_CREDIT_ALPHANUM12)
        {
            assetCodeToStr(selling.alphaNum12().assetCode, sellingAssetCode);
            sellingIssuerStrKey = PubKeyUtils::toStrKey(selling.alphaNum12().issuer);
        }else throw std::runtime_error("unknown asset type");

        sql << " WHERE sellingassetcode=:pcur AND sellingissuer = :pi",
            use(sellingAssetCode), use(sellingIssuerStrKey);
    }

    if (buying.type() == ASSET_TYPE_NATIVE)
    {
        sql << " AND buyingassettype=0";
    }
    else
    {
        if(buying.type() == ASSET_TYPE_CREDIT_ALPHANUM4)
        {
            assetCodeToStr(buying.alphaNum4().assetCode, buyingAssetCode);
            buyingIssuerStrKey = PubKeyUtils::toStrKey(buying.alphaNum4().issuer);
        } else if(buying.type() == ASSET_TYPE_CREDIT_ALPHANUM12)
        {
            assetCodeToStr(buying.alphaNum12().assetCode, buyingAssetCode);
            buyingIssuerStrKey = PubKeyUtils::toStrKey(buying.alphaNum12().issuer);
        }else throw std::runtime_error("unknown asset type");

        sql << " AND buyingassetcode=:gcur AND buyingissuer = :gi",
            use(buyingAssetCode), use(buyingIssuerStrKey);
    }
    sql << " ORDER BY price,offerid LIMIT :n OFFSET :o", use(numOffers),
        use(offset);

    auto timer = db.getSelectTimer("offer");
    loadOffers(sql, [&retOffers](LedgerEntry const& of)
               {
                   retOffers.emplace_back(make_shared<OfferFrame>(of));
               });
}