mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
More PFRequest work. Advanced features.
This commit is contained in:
@@ -4,6 +4,9 @@
|
||||
#include "RPCErr.h"
|
||||
#include "Ledger.h"
|
||||
#include "Application.h"
|
||||
#include "Pathfinder.h"
|
||||
#include "RippleCalc.h"
|
||||
#include "LedgerFormats.h"
|
||||
|
||||
boost::recursive_mutex PFRequest::sLock;
|
||||
std::set<PFRequest::wptr> PFRequest::sRequests;
|
||||
@@ -35,8 +38,10 @@ bool PFRequest::isValid(Ledger::ref lrLedger)
|
||||
else
|
||||
{
|
||||
AccountState::pointer asDst = theApp->getOPs().getAccountState(lrLedger, raDstAccount);
|
||||
Json::Value jvDestCur;
|
||||
if (!asDst)
|
||||
{ // no destination account
|
||||
jvDestCur.append(Json::Value("XRP"));
|
||||
if(!saDstAmount.isNative())
|
||||
{ // only XRP can be send to a non-existent account
|
||||
bValid = false;
|
||||
@@ -48,21 +53,41 @@ bool PFRequest::isValid(Ledger::ref lrLedger)
|
||||
jvStatus = rpcError(rpcDST_AMT_MALFORMED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::unordered_set<uint160> usDestCurrID = usAccountDestCurrencies(raDstAccount, lrLedger, true);
|
||||
BOOST_FOREACH(const uint160& uCurrency, usDestCurrID)
|
||||
jvDestCur.append(STAmount::createHumanCurrency(uCurrency));
|
||||
jvStatus["destination_tag"] = (asDst->peekSLE().getFlags() & lsfRequireDestTag) != 0;
|
||||
}
|
||||
jvStatus["destination_currencies"] = jvDestCur;
|
||||
}
|
||||
}
|
||||
jvStatus["ledger_hash"] = lrLedger->getHash().GetHex();
|
||||
jvStatus["ledger_index"] = lrLedger->getLedgerSeq();
|
||||
return bValid;
|
||||
}
|
||||
|
||||
Json::Value PFRequest::doCreate(Ledger::ref lrLedger, const Json::Value& value)
|
||||
{
|
||||
assert(lrLedger->isClosed());
|
||||
|
||||
Json::Value status;
|
||||
bool mValid;
|
||||
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
parseJson(value, true);
|
||||
status = jvStatus;
|
||||
mValid = isValid(lrLedger);
|
||||
if (parseJson(value, true) != PFR_PJ_INVALID)
|
||||
{
|
||||
mValid = isValid(lrLedger);
|
||||
if (mValid)
|
||||
{
|
||||
RLCache::pointer cache = boost::make_shared<RLCache>(lrLedger);
|
||||
doUpdate(cache, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
mValid = false;
|
||||
}
|
||||
|
||||
if (mValid)
|
||||
@@ -167,4 +192,60 @@ Json::Value PFRequest::doStatus(const Json::Value&)
|
||||
return jvStatus;
|
||||
}
|
||||
|
||||
bool PFRequest::doUpdate(RLCache::ref cache, bool fast)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
jvStatus = Json::objectValue;
|
||||
if (!isValid(cache->getLedger()))
|
||||
return false;
|
||||
|
||||
std::set<currIssuer_t> sourceCurrencies(sciSourceCurrencies);
|
||||
if (sourceCurrencies.empty())
|
||||
{
|
||||
boost::unordered_set<uint160> usCurrencies =
|
||||
usAccountSourceCurrencies(raSrcAccount, cache->getLedger(), true);
|
||||
bool sameAccount = raSrcAccount == raDstAccount;
|
||||
BOOST_FOREACH(const uint160& c, usCurrencies)
|
||||
{
|
||||
if (!sameAccount || (c != saDstAmount.getCurrency()))
|
||||
sourceCurrencies.insert(std::make_pair(c, ACCOUNT_XRP));
|
||||
}
|
||||
}
|
||||
|
||||
jvStatus["source_account"] = raSrcAccount.humanAccountID();
|
||||
jvStatus["destination_account"] = raDstAccount.humanAccountID();
|
||||
|
||||
Json::Value jvArray = Json::arrayValue;
|
||||
|
||||
BOOST_FOREACH(const currIssuer_t& currIssuer, sourceCurrencies)
|
||||
{
|
||||
bool valid;
|
||||
STPathSet spsPaths;
|
||||
Pathfinder pf(cache, raSrcAccount, raDstAccount,
|
||||
currIssuer.first, currIssuer.second, saDstAmount, valid);
|
||||
if (valid && pf.findPaths(theConfig.PATH_SEARCH_SIZE - (fast ? 0 : 1), 3, spsPaths))
|
||||
{
|
||||
LedgerEntrySet lesSandbox(cache->getLedger(), tapNONE);
|
||||
std::vector<PathState::pointer> vpsExpanded;
|
||||
STAmount saMaxAmountAct;
|
||||
STAmount saDstAmountAct;
|
||||
STAmount saMaxAmount(currIssuer.first,
|
||||
currIssuer.second.isNonZero() ? currIssuer.second :
|
||||
(currIssuer.first.isZero() ? ACCOUNT_XRP : raSrcAccount.getAccountID()), 1);
|
||||
TER terResult = RippleCalc::rippleCalc(lesSandbox, saMaxAmountAct, saDstAmountAct,
|
||||
vpsExpanded, saMaxAmount, saDstAmount, raDstAccount.getAccountID(), raSrcAccount.getAccountID(),
|
||||
spsPaths, false, false, false, true);
|
||||
if (terResult == tesSUCCESS)
|
||||
{
|
||||
Json::Value jvEntry(Json::objectValue);
|
||||
jvEntry["source_amount"] = saMaxAmountAct.getJson(0);
|
||||
jvEntry["paths_computed"] = spsPaths.getJson(0);
|
||||
jvArray.append(jvEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
jvStatus["alternatives"] = jvArray;
|
||||
return true;
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "uint256.h"
|
||||
#include "RippleAddress.h"
|
||||
#include "SerializedTypes.h"
|
||||
#include "Pathfinder.h"
|
||||
|
||||
// A pathfinding request submitted by a client
|
||||
// The request issuer must maintain a strong pointer
|
||||
@@ -21,6 +22,7 @@
|
||||
class Ledger;
|
||||
class InfoSub;
|
||||
class STAmount;
|
||||
class RLCache;
|
||||
|
||||
// Return values from parseJson <0 = invalid, >0 = valid
|
||||
#define PFR_PJ_INVALID -1
|
||||
@@ -69,8 +71,7 @@ public:
|
||||
Json::Value doClose(const Json::Value&);
|
||||
Json::Value doStatus(const Json::Value&);
|
||||
|
||||
void doUpdate(); // do an update
|
||||
void trigger(); // schedule an update
|
||||
bool doUpdate(const boost::shared_ptr<RLCache>&, bool fast); // update jvStatus
|
||||
|
||||
static void updateAll(const boost::shared_ptr<Ledger> &);
|
||||
};
|
||||
|
||||
@@ -138,7 +138,7 @@ static int getEffectiveLength(const STPath& spPath)
|
||||
return length;
|
||||
}
|
||||
|
||||
Pathfinder::Pathfinder(Ledger::ref ledger, RLCache::ref cache,
|
||||
Pathfinder::Pathfinder(RLCache::ref cache,
|
||||
const RippleAddress& uSrcAccountID, const RippleAddress& uDstAccountID,
|
||||
const uint160& uSrcCurrencyID, const uint160& uSrcIssuerID, const STAmount& saDstAmount, bool& bValid)
|
||||
: mSrcAccountID(uSrcAccountID.getAccountID()),
|
||||
@@ -147,7 +147,7 @@ Pathfinder::Pathfinder(Ledger::ref ledger, RLCache::ref cache,
|
||||
mSrcCurrencyID(uSrcCurrencyID),
|
||||
mSrcIssuerID(uSrcIssuerID),
|
||||
mSrcAmount(uSrcCurrencyID, uSrcIssuerID, 1u, 0, true),
|
||||
mLedger(ledger), mRLCache(cache)
|
||||
mLedger(cache->getLedger()), mRLCache(cache)
|
||||
{
|
||||
|
||||
if (((mSrcAccountID == mDstAccountID) && (mSrcCurrencyID == mDstAmount.getCurrency())) || mDstAmount.isZero())
|
||||
|
||||
@@ -47,7 +47,9 @@ public:
|
||||
typedef const pointer& ref;
|
||||
|
||||
RLCache(Ledger::ref l) : mLedger(l) { ; }
|
||||
AccountItems& getRippleLines(const uint160& accountID);
|
||||
Ledger::ref getLedger() { return mLedger; }
|
||||
|
||||
AccountItems& getRippleLines(const uint160& accountID);
|
||||
};
|
||||
|
||||
class Pathfinder
|
||||
@@ -83,7 +85,7 @@ class Pathfinder
|
||||
bool isAuthRequired, bool isDestCurrency, const uint160& dest);
|
||||
|
||||
public:
|
||||
Pathfinder(Ledger::ref ledger, RLCache::ref cache,
|
||||
Pathfinder(RLCache::ref cache,
|
||||
const RippleAddress& srcAccountID, const RippleAddress& dstAccountID,
|
||||
const uint160& srcCurrencyID, const uint160& srcIssuerID, const STAmount& dstAmount, bool& bValid);
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ Json::Value RPCHandler::transactionSign(Json::Value jvRequest, bool bSubmit)
|
||||
ScopedUnlock su(theApp->getMasterLock());
|
||||
bool bValid;
|
||||
RLCache::pointer cache = boost::make_shared<RLCache>(lSnapshot);
|
||||
Pathfinder pf(lSnapshot, cache, raSrcAddressID, dstAccountID,
|
||||
Pathfinder pf(cache, raSrcAddressID, dstAccountID,
|
||||
saSendMax.getCurrency(), saSendMax.getIssuer(), saSend, bValid);
|
||||
|
||||
if (!bValid || !pf.findPaths(theConfig.PATH_SEARCH_SIZE, 3, spsPaths))
|
||||
@@ -1173,13 +1173,17 @@ Json::Value RPCHandler::doPathFind(Json::Value jvRequest, int& cost, ScopedLock&
|
||||
{
|
||||
if (!jvRequest.isMember("subcommand") || !jvRequest["subcommand"].isString())
|
||||
return rpcError(rpcINVALID_PARAMS);
|
||||
|
||||
if (!mInfoSub)
|
||||
return rpcError(rpcNO_EVENTS);
|
||||
|
||||
std::string sSubCommand = jvRequest["subcommand"].asString();
|
||||
|
||||
if (sSubCommand == "create")
|
||||
{
|
||||
mInfoSub->clearPFRequest();
|
||||
PFRequest::pointer request = boost::make_shared<PFRequest>(mInfoSub);
|
||||
Json::Value result = request->doCreate(mNetOps->getCurrentLedger(), jvRequest);
|
||||
Json::Value result = request->doCreate(mNetOps->getClosedLedger(), jvRequest);
|
||||
if (request->isValid())
|
||||
mInfoSub->setPFRequest(request);
|
||||
return result;
|
||||
@@ -1342,7 +1346,7 @@ Json::Value RPCHandler::doRipplePathFind(Json::Value jvRequest, int& cost, Scope
|
||||
|
||||
STPathSet spsComputed;
|
||||
bool bValid;
|
||||
Pathfinder pf(lSnapShot, cache, raSrc, raDst, uSrcCurrencyID, uSrcIssuerID, saDstAmount, bValid);
|
||||
Pathfinder pf(cache, raSrc, raDst, uSrcCurrencyID, uSrcIssuerID, saDstAmount, bValid);
|
||||
|
||||
if (!bValid || !pf.findPaths(theConfig.PATH_SEARCH_SIZE, 3, spsComputed))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user