mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin
This commit is contained in:
@@ -1598,21 +1598,21 @@ void NetworkOPs::unsubAccount(uint64 uSeq, const boost::unordered_set<RippleAddr
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkOPs::subBook(InfoSub::ref isrListener, const uint160& currencyIn, const uint160& currencyOut,
|
||||
const uint160& issuerIn, const uint160& issuerOut)
|
||||
bool NetworkOPs::subBook(InfoSub::ref isrListener, const uint160& currencyPays, const uint160& currencyGets,
|
||||
const uint160& issuerPays, const uint160& issuerGets)
|
||||
{
|
||||
BookListeners::pointer listeners =
|
||||
theApp->getOrderBookDB().makeBookListeners(currencyIn, currencyOut, issuerIn, issuerOut);
|
||||
theApp->getOrderBookDB().makeBookListeners(currencyPays, currencyGets, issuerPays, issuerGets);
|
||||
if (listeners)
|
||||
listeners->addSubscriber(isrListener);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetworkOPs::unsubBook(uint64 uSeq,
|
||||
const uint160& currencyIn, const uint160& currencyOut, const uint160& issuerIn, const uint160& issuerOut)
|
||||
const uint160& currencyPays, const uint160& currencyGets, const uint160& issuerPays, const uint160& issuerGets)
|
||||
{
|
||||
BookListeners::pointer listeners =
|
||||
theApp->getOrderBookDB().getBookListeners(currencyIn, currencyOut, issuerIn, issuerOut);
|
||||
theApp->getOrderBookDB().getBookListeners(currencyPays, currencyGets, issuerPays, issuerGets);
|
||||
if (listeners)
|
||||
listeners->removeSubscriber(uSeq);
|
||||
return true;
|
||||
|
||||
@@ -322,10 +322,10 @@ public:
|
||||
bool subServer(InfoSub::ref ispListener, Json::Value& jvResult);
|
||||
bool unsubServer(uint64 uListener);
|
||||
|
||||
bool subBook(InfoSub::ref ispListener, const uint160& currencyIn, const uint160& currencyOut,
|
||||
const uint160& issuerIn, const uint160& issuerOut);
|
||||
bool unsubBook(uint64 uListener, const uint160& currencyIn, const uint160& currencyOut,
|
||||
const uint160& issuerIn, const uint160& issuerOut);
|
||||
bool subBook(InfoSub::ref ispListener, const uint160& currencyPays, const uint160& currencyGets,
|
||||
const uint160& issuerPays, const uint160& issuerGets);
|
||||
bool unsubBook(uint64 uListener, const uint160& currencyPays, const uint160& currencyGets,
|
||||
const uint160& issuerPays, const uint160& issuerGets);
|
||||
|
||||
bool subTransactions(InfoSub::ref ispListener);
|
||||
bool unsubTransactions(uint64 uListener);
|
||||
|
||||
@@ -93,40 +93,40 @@ void OrderBookDB::getBooks(const uint160& issuerID, const uint160& currencyID, s
|
||||
}
|
||||
}
|
||||
|
||||
BookListeners::pointer OrderBookDB::makeBookListeners(const uint160& currencyIn, const uint160& currencyOut,
|
||||
const uint160& issuerIn, const uint160& issuerOut)
|
||||
BookListeners::pointer OrderBookDB::makeBookListeners(const uint160& currencyPays, const uint160& currencyGets,
|
||||
const uint160& issuerPays, const uint160& issuerGets)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
BookListeners::pointer ret = getBookListeners(currencyIn, currencyOut, issuerIn, issuerOut);
|
||||
BookListeners::pointer ret = getBookListeners(currencyPays, currencyGets, issuerPays, issuerGets);
|
||||
if (!ret)
|
||||
{
|
||||
ret = boost::make_shared<BookListeners>();
|
||||
mListeners[issuerIn][issuerOut][currencyIn][currencyOut] = ret;
|
||||
mListeners[issuerPays][issuerGets][currencyPays][currencyGets] = ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
BookListeners::pointer OrderBookDB::getBookListeners(const uint160& currencyIn, const uint160& currencyOut,
|
||||
const uint160& issuerIn, const uint160& issuerOut)
|
||||
BookListeners::pointer OrderBookDB::getBookListeners(const uint160& currencyPays, const uint160& currencyGets,
|
||||
const uint160& issuerPays, const uint160& issuerGets)
|
||||
{
|
||||
BookListeners::pointer ret;
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
std::map<uint160, std::map<uint160, std::map<uint160, std::map<uint160, BookListeners::pointer> > > >::iterator
|
||||
it0 = mListeners.find(issuerIn);
|
||||
it0 = mListeners.find(issuerPays);
|
||||
if(it0 == mListeners.end())
|
||||
return ret;
|
||||
|
||||
std::map<uint160, std::map<uint160, std::map<uint160, BookListeners::pointer> > >::iterator
|
||||
it1 = (*it0).second.find(issuerOut);
|
||||
it1 = (*it0).second.find(issuerGets);
|
||||
if(it1 == (*it0).second.end())
|
||||
return ret;
|
||||
|
||||
std::map<uint160, std::map<uint160, BookListeners::pointer> >::iterator it2 = (*it1).second.find(currencyIn);
|
||||
std::map<uint160, std::map<uint160, BookListeners::pointer> >::iterator it2 = (*it1).second.find(currencyPays);
|
||||
if(it2 == (*it1).second.end())
|
||||
return ret;
|
||||
|
||||
std::map<uint160, BookListeners::pointer>::iterator it3 = (*it2).second.find(currencyOut);
|
||||
std::map<uint160, BookListeners::pointer>::iterator it3 = (*it2).second.find(currencyGets);
|
||||
if(it3 == (*it2).second.end())
|
||||
return ret;
|
||||
|
||||
@@ -216,16 +216,16 @@ void OrderBookDB::processTxn(Ledger::ref ledger, const ALTransaction& alTx, Json
|
||||
if (data)
|
||||
{
|
||||
STAmount takerGets = data->getFieldAmount(sfTakerGets);
|
||||
uint160 currencyOut = takerGets.getCurrency();
|
||||
uint160 issuerOut = takerGets.getIssuer();
|
||||
uint160 currencyGets = takerGets.getCurrency();
|
||||
uint160 issuerGets = takerGets.getIssuer();
|
||||
|
||||
STAmount takerPays = data->getFieldAmount(sfTakerPays);
|
||||
uint160 currencyIn = takerPays.getCurrency();
|
||||
uint160 issuerIn = takerPays.getIssuer();
|
||||
uint160 currencyPays = takerPays.getCurrency();
|
||||
uint160 issuerPays = takerPays.getIssuer();
|
||||
|
||||
// determine the OrderBook
|
||||
BookListeners::pointer book =
|
||||
getBookListeners(currencyIn, currencyOut, issuerIn, issuerOut);
|
||||
getBookListeners(currencyPays, currencyGets, issuerPays, issuerGets);
|
||||
if (book)
|
||||
book->publish(jvObj);
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@ class OrderBookDB
|
||||
boost::unordered_map<uint160, std::vector<OrderBook::pointer> > mIssuerMap;
|
||||
//std::vector<OrderBook::pointer> mAllOrderBooks;
|
||||
|
||||
// issuerIn, issuerOut, currencyIn, currencyOut
|
||||
std::map<uint160, std::map<uint160, std::map<uint160, std::map<uint160, BookListeners::pointer> > > > mListeners;
|
||||
// issuerPays, issuerGets, currencyPays, currencyGets
|
||||
std::map<uint160, std::map<uint160, std::map<uint160, std::map<uint160, BookListeners::pointer> > > > mListeners;
|
||||
|
||||
uint32 mSeq;
|
||||
boost::recursive_mutex mLock;
|
||||
@@ -56,13 +56,13 @@ public:
|
||||
void getBooks(const uint160& issuerID, const uint160& currencyID, std::vector<OrderBook::pointer>& bookRet);
|
||||
|
||||
// returns the best rate we can find
|
||||
float getPrice(uint160& currencyIn,uint160& currencyOut);
|
||||
float getPrice(uint160& currencyPays,uint160& currencyGets);
|
||||
|
||||
|
||||
BookListeners::pointer getBookListeners(const uint160& currencyIn, const uint160& currencyOut,
|
||||
const uint160& issuerIn, const uint160& issuerOut);
|
||||
BookListeners::pointer makeBookListeners(const uint160& currencyIn, const uint160& currencyOut,
|
||||
const uint160& issuerIn, const uint160& issuerOut);
|
||||
BookListeners::pointer getBookListeners(const uint160& currencyPays, const uint160& currencyGets,
|
||||
const uint160& issuerPays, const uint160& issuerGets);
|
||||
BookListeners::pointer makeBookListeners(const uint160& currencyPays, const uint160& currencyGets,
|
||||
const uint160& issuerPays, const uint160& issuerGets);
|
||||
|
||||
// see if this txn effects any orderbook
|
||||
void processTxn(Ledger::ref ledger, const ALTransaction& alTx, Json::Value& jvObj);
|
||||
|
||||
@@ -2754,34 +2754,90 @@ Json::Value RPCHandler::doSubscribe(Json::Value jvRequest, int& cost)
|
||||
{ // FIXME: This can crash the server if the parameters to things like getBookPage are invalid
|
||||
for (Json::Value::iterator it = jvRequest["books"].begin(); it != jvRequest["books"].end(); it++)
|
||||
{
|
||||
uint160 currencyOut;
|
||||
STAmount::currencyFromString(currencyOut,(*it)["CurrencyOut"].asString());
|
||||
uint160 issuerOut,issuerIn;
|
||||
if(currencyOut.isNonZero())
|
||||
STAmount::issuerFromString(issuerOut,(*it)["IssuerOut"].asString());
|
||||
uint160 currencyIn;
|
||||
STAmount::currencyFromString(currencyIn,(*it)["CurrencyIn"].asString());
|
||||
if(currencyIn.isNonZero())
|
||||
STAmount::issuerFromString(issuerIn,(*it)["IssuerIn"].asString());
|
||||
uint160 uTakerPaysCurrencyID;
|
||||
uint160 uTakerPaysIssuerID;
|
||||
Json::Value jvTakerPays = (*it)["taker_pays"];
|
||||
|
||||
bool bothSides=false;
|
||||
if((*it).isMember("BothSides") && (*it)["BothSides"].asBool()) bothSides=true;
|
||||
// Parse mandatory currency.
|
||||
if (!jvTakerPays.isMember("currency")
|
||||
|| !STAmount::currencyFromString(uTakerPaysCurrencyID, jvTakerPays["currency"].asString()))
|
||||
{
|
||||
cLog(lsINFO) << "Bad taker_pays currency.";
|
||||
|
||||
mNetOps->subBook(ispSub, currencyIn, currencyOut, issuerIn, issuerOut);
|
||||
if(bothSides) mNetOps->subBook(ispSub, currencyOut, currencyIn, issuerOut, issuerIn);
|
||||
if((*it)["StateNow"].asBool())
|
||||
return rpcError(rpcSRC_CUR_MALFORMED);
|
||||
}
|
||||
// Parse optional issuer.
|
||||
else if (((jvTakerPays.isMember("issuer"))
|
||||
&& (!jvTakerPays["issuer"].isString()
|
||||
|| !STAmount::issuerFromString(uTakerPaysIssuerID, jvTakerPays["issuer"].asString())))
|
||||
// Don't allow illegal issuers.
|
||||
|| (!uTakerPaysCurrencyID != !uTakerPaysIssuerID)
|
||||
|| ACCOUNT_ONE == uTakerPaysIssuerID)
|
||||
{
|
||||
cLog(lsINFO) << "Bad taker_pays issuer.";
|
||||
|
||||
return rpcError(rpcSRC_ISR_MALFORMED);
|
||||
}
|
||||
|
||||
uint160 uTakerGetsCurrencyID;
|
||||
uint160 uTakerGetsIssuerID;
|
||||
Json::Value jvTakerGets = (*it)["taker_gets"];
|
||||
|
||||
// Parse mandatory currency.
|
||||
if (!jvTakerGets.isMember("currency")
|
||||
|| !STAmount::currencyFromString(uTakerGetsCurrencyID, jvTakerGets["currency"].asString()))
|
||||
{
|
||||
cLog(lsINFO) << "Bad taker_pays currency.";
|
||||
|
||||
return rpcError(rpcSRC_CUR_MALFORMED);
|
||||
}
|
||||
// Parse optional issuer.
|
||||
else if (((jvTakerGets.isMember("issuer"))
|
||||
&& (!jvTakerGets["issuer"].isString()
|
||||
|| !STAmount::issuerFromString(uTakerGetsIssuerID, jvTakerGets["issuer"].asString())))
|
||||
// Don't allow illegal issuers.
|
||||
|| (!uTakerGetsCurrencyID != !uTakerGetsIssuerID)
|
||||
|| ACCOUNT_ONE == uTakerGetsIssuerID)
|
||||
{
|
||||
cLog(lsINFO) << "Bad taker_gets issuer.";
|
||||
|
||||
return rpcError(rpcDST_ISR_MALFORMED);
|
||||
}
|
||||
|
||||
if (uTakerPaysCurrencyID == uTakerGetsCurrencyID
|
||||
&& uTakerPaysIssuerID == uTakerGetsIssuerID)
|
||||
{
|
||||
cLog(lsINFO) << "taker_gets same as taker_pays.";
|
||||
|
||||
return rpcError(rpcBAD_MARKET);
|
||||
}
|
||||
|
||||
RippleAddress raTakerID;
|
||||
|
||||
if (!(*it).isMember("taker"))
|
||||
{
|
||||
raTakerID.setAccountID(ACCOUNT_ONE);
|
||||
}
|
||||
else if (!raTakerID.setAccountID((*it)["taker"].asString()))
|
||||
{
|
||||
return rpcError(rpcBAD_ISSUER);
|
||||
}
|
||||
|
||||
bool bothSides = (*it)["both_sides"].asBool();
|
||||
|
||||
mNetOps->subBook(ispSub, uTakerPaysCurrencyID, uTakerGetsCurrencyID, uTakerPaysIssuerID, uTakerGetsIssuerID);
|
||||
if (bothSides) mNetOps->subBook(ispSub, uTakerGetsCurrencyID, uTakerPaysCurrencyID, uTakerGetsIssuerID, uTakerPaysIssuerID);
|
||||
if ((*it)["state_now"].asBool())
|
||||
{
|
||||
Ledger::pointer ledger= theApp->getLedgerMaster().getClosedLedger();
|
||||
RippleAddress raTakerID;
|
||||
raTakerID.setAccountID(ACCOUNT_ONE);
|
||||
const Json::Value jvMarker = Json::Value(Json::nullValue);
|
||||
mNetOps->getBookPage(ledger, currencyOut, issuerOut, currencyIn, issuerIn, raTakerID.getAccountID(), false, 0, jvMarker, jvResult);
|
||||
if(bothSides)
|
||||
mNetOps->getBookPage(ledger, uTakerPaysCurrencyID, uTakerPaysIssuerID, uTakerGetsCurrencyID, uTakerGetsIssuerID, raTakerID.getAccountID(), false, 0, jvMarker, jvResult);
|
||||
if (bothSides)
|
||||
{
|
||||
Json::Value tempJson(Json::objectValue);
|
||||
if(jvResult.isMember("offers")) jvResult["bids"]=jvResult["offers"];
|
||||
mNetOps->getBookPage(ledger, currencyIn, issuerIn, currencyOut, issuerOut, raTakerID.getAccountID(), false, 0, jvMarker, tempJson);
|
||||
if(tempJson.isMember("offers")) jvResult["asks"]=tempJson["offers"];
|
||||
if (jvResult.isMember("offers")) jvResult["bids"]=jvResult["offers"];
|
||||
mNetOps->getBookPage(ledger, uTakerGetsCurrencyID, uTakerGetsIssuerID, uTakerPaysCurrencyID, uTakerPaysIssuerID, raTakerID.getAccountID(), false, 0, jvMarker, tempJson);
|
||||
if (tempJson.isMember("offers")) jvResult["asks"]=tempJson["offers"];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2886,14 +2942,68 @@ Json::Value RPCHandler::doUnsubscribe(Json::Value jvRequest, int& cost)
|
||||
{
|
||||
for (Json::Value::iterator it = jvRequest["books"].begin(); it != jvRequest["books"].end(); it++)
|
||||
{
|
||||
uint160 currencyOut;
|
||||
STAmount::issuerFromString(currencyOut,(*it)["CurrencyOut"].asString());
|
||||
uint160 issuerOut = RippleAddress::createNodePublic( (*it)["IssuerOut"].asString() ).getAccountID();
|
||||
uint160 currencyIn;
|
||||
STAmount::issuerFromString(currencyOut,(*it)["CurrencyIn"].asString());
|
||||
uint160 issuerIn = RippleAddress::createNodePublic( (*it)["IssuerIn"].asString() ).getAccountID();
|
||||
uint160 uTakerPaysCurrencyID;
|
||||
uint160 uTakerPaysIssuerID;
|
||||
Json::Value jvTakerPays = (*it)["taker_pays"];
|
||||
|
||||
mNetOps->unsubBook(ispSub->getSeq(), currencyIn, currencyOut, issuerIn, issuerOut);
|
||||
// Parse mandatory currency.
|
||||
if (!jvTakerPays.isMember("currency")
|
||||
|| !STAmount::currencyFromString(uTakerPaysCurrencyID, jvTakerPays["currency"].asString()))
|
||||
{
|
||||
cLog(lsINFO) << "Bad taker_pays currency.";
|
||||
|
||||
return rpcError(rpcSRC_CUR_MALFORMED);
|
||||
}
|
||||
// Parse optional issuer.
|
||||
else if (((jvTakerPays.isMember("issuer"))
|
||||
&& (!jvTakerPays["issuer"].isString()
|
||||
|| !STAmount::issuerFromString(uTakerPaysIssuerID, jvTakerPays["issuer"].asString())))
|
||||
// Don't allow illegal issuers.
|
||||
|| (!uTakerPaysCurrencyID != !uTakerPaysIssuerID)
|
||||
|| ACCOUNT_ONE == uTakerPaysIssuerID)
|
||||
{
|
||||
cLog(lsINFO) << "Bad taker_pays issuer.";
|
||||
|
||||
return rpcError(rpcSRC_ISR_MALFORMED);
|
||||
}
|
||||
|
||||
uint160 uTakerGetsCurrencyID;
|
||||
uint160 uTakerGetsIssuerID;
|
||||
Json::Value jvTakerGets = (*it)["taker_gets"];
|
||||
|
||||
// Parse mandatory currency.
|
||||
if (!jvTakerGets.isMember("currency")
|
||||
|| !STAmount::currencyFromString(uTakerGetsCurrencyID, jvTakerGets["currency"].asString()))
|
||||
{
|
||||
cLog(lsINFO) << "Bad taker_pays currency.";
|
||||
|
||||
return rpcError(rpcSRC_CUR_MALFORMED);
|
||||
}
|
||||
// Parse optional issuer.
|
||||
else if (((jvTakerGets.isMember("issuer"))
|
||||
&& (!jvTakerGets["issuer"].isString()
|
||||
|| !STAmount::issuerFromString(uTakerGetsIssuerID, jvTakerGets["issuer"].asString())))
|
||||
// Don't allow illegal issuers.
|
||||
|| (!uTakerGetsCurrencyID != !uTakerGetsIssuerID)
|
||||
|| ACCOUNT_ONE == uTakerGetsIssuerID)
|
||||
{
|
||||
cLog(lsINFO) << "Bad taker_gets issuer.";
|
||||
|
||||
return rpcError(rpcDST_ISR_MALFORMED);
|
||||
}
|
||||
|
||||
if (uTakerPaysCurrencyID == uTakerGetsCurrencyID
|
||||
&& uTakerPaysIssuerID == uTakerGetsIssuerID)
|
||||
{
|
||||
cLog(lsINFO) << "taker_gets same as taker_pays.";
|
||||
|
||||
return rpcError(rpcBAD_MARKET);
|
||||
}
|
||||
|
||||
bool bothSides = (*it)["both_sides"].asBool();
|
||||
|
||||
mNetOps->unsubBook(ispSub->getSeq(), uTakerPaysCurrencyID, uTakerGetsCurrencyID, uTakerPaysIssuerID, uTakerGetsIssuerID);
|
||||
if (bothSides) mNetOps->unsubBook(ispSub->getSeq(), uTakerGetsCurrencyID, uTakerPaysCurrencyID, uTakerGetsIssuerID, uTakerPaysIssuerID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user