diff --git a/src/cpp/ripple/PFRequest.cpp b/src/cpp/ripple/PFRequest.cpp index 54f9371c8d..a613cf1c3a 100644 --- a/src/cpp/ripple/PFRequest.cpp +++ b/src/cpp/ripple/PFRequest.cpp @@ -2,6 +2,8 @@ #include "NetworkOPs.h" #include "RPCErr.h" +#include "Ledger.h" +#include "Application.h" boost::recursive_mutex PFRequest::sLock; std::set PFRequest::sRequests; @@ -15,11 +17,43 @@ PFRequest::PFRequest(const boost::shared_ptr& subscriber) : bool PFRequest::isValid() { boost::recursive_mutex::scoped_lock sl(mLock); - bValid = raSrcAccount.isSet() && raDstAccount.isSet() && saDstAmount.isPositive(); return bValid; } -Json::Value PFRequest::doCreate(const Json::Value& value) +bool PFRequest::isValid(Ledger::ref lrLedger) +{ + boost::recursive_mutex::scoped_lock sl(mLock); + bValid = raSrcAccount.isSet() && raDstAccount.isSet() && saDstAmount.isPositive(); + if (bValid) + { + AccountState::pointer asSrc = theApp->getOPs().getAccountState(lrLedger, raSrcAccount); + if (!asSrc) + { // no source account + bValid = false; + jvStatus = rpcError(rpcSRC_ACT_NOT_FOUND); + } + else + { + AccountState::pointer asDst = theApp->getOPs().getAccountState(lrLedger, raDstAccount); + if (!asDst) + { // no destination account + if(!saDstAmount.isNative()) + { // only XRP can be send to a non-existent account + bValid = false; + jvStatus = rpcError(rpcACT_NOT_FOUND); + } + else if (saDstAmount < STAmount(lrLedger->getReserve(0))) + { // payment must meet reserve + bValid = false; + jvStatus = rpcError(rpcDST_AMT_MALFORMED); + } + } + } + } + return bValid; +} + +Json::Value PFRequest::doCreate(Ledger::ref lrLedger, const Json::Value& value) { Json::Value status; bool mValid; @@ -28,7 +62,7 @@ Json::Value PFRequest::doCreate(const Json::Value& value) boost::recursive_mutex::scoped_lock sl(mLock); parseJson(value, true); status = jvStatus; - mValid = isValid(); + mValid = isValid(lrLedger); } if (mValid) @@ -75,7 +109,7 @@ int PFRequest::parseJson(const Json::Value& jvParams, bool complete) if (jvParams.isMember("destination_amount")) { if (!saDstAmount.bSetJson(jvParams["destination_amount"]) || - (saDstAmount.getCurrency().isZero() != saDstAmount.getIssuer().isZero()) || + (saDstAmount.getCurrency().isZero() && saDstAmount.getIssuer().isNonZero()) || (saDstAmount.getCurrency() == CURRENCY_BAD)) { jvStatus = rpcError(rpcDST_AMT_MALFORMED); @@ -106,12 +140,16 @@ int PFRequest::parseJson(const Json::Value& jvParams, bool complete) jvStatus = rpcError(rpcSRC_CUR_MALFORMED); return PFR_PJ_INVALID; } - if (jvCur.isMember("issuer")) + if (jvCur.isMember("issuer") && !STAmount::issuerFromString(uIss, jvCur["issuer"].asString())) { - // parse issuer WRITEME + jvStatus = rpcError(rpcSRC_ISR_MALFORMED); } - // sanity check WRITEME - // insert in set WRIEME + if (uCur.isZero() && uIss.isNonZero()) + { + jvStatus = rpcError(rpcSRC_CUR_MALFORMED); + return PFR_PJ_INVALID; + } + sciSourceCurrencies.insert(currIssuer_t(uCur, uIss)); } } diff --git a/src/cpp/ripple/PFRequest.h b/src/cpp/ripple/PFRequest.h index 114fc5e343..30c40ff91b 100644 --- a/src/cpp/ripple/PFRequest.h +++ b/src/cpp/ripple/PFRequest.h @@ -61,10 +61,11 @@ public: PFRequest(const boost::shared_ptr& subscriber); + bool isValid(const boost::shared_ptr&); bool isValid(); Json::Value getStatus(); - Json::Value doCreate(const Json::Value&); + Json::Value doCreate(const boost::shared_ptr&, const Json::Value&); Json::Value doClose(const Json::Value&); Json::Value doStatus(const Json::Value&); diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp index 64e29bdfb1..b72ea21ddf 100644 --- a/src/cpp/ripple/RPCHandler.cpp +++ b/src/cpp/ripple/RPCHandler.cpp @@ -1177,7 +1177,7 @@ Json::Value RPCHandler::doPathFind(Json::Value jvRequest, int& cost, ScopedLock& { mInfoSub->clearPFRequest(); PFRequest::pointer request = boost::make_shared(mInfoSub); - Json::Value result = request->doCreate(jvRequest); + Json::Value result = request->doCreate(mNetOps->getCurrentLedger(), jvRequest); if (request->isValid()) mInfoSub->setPFRequest(request); return result;