From 28c31e797be81532fed07b7a7c729fdbf7505069 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Thu, 16 Aug 2012 14:05:21 -0700 Subject: [PATCH 1/5] Disable SNTPClient in standalone mode. --- src/Application.cpp | 3 ++- src/SNTPClient.cpp | 3 ++- src/SNTPClient.h | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Application.cpp b/src/Application.cpp index 2fe18c161f..dd94fb43b9 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -73,7 +73,8 @@ void Application::run() boost::thread auxThread(boost::bind(&boost::asio::io_service::run, &mAuxService)); auxThread.detach(); - mSNTPClient.init(theConfig.SNTP_SERVERS); + if (!theConfig.RUN_STANDALONE) + mSNTPClient.init(theConfig.SNTP_SERVERS); // // Construct databases. diff --git a/src/SNTPClient.cpp b/src/SNTPClient.cpp index 444b7b6c73..11a7915fae 100644 --- a/src/SNTPClient.cpp +++ b/src/SNTPClient.cpp @@ -47,7 +47,7 @@ SNTPClient::SNTPClient(boost::asio::io_service& service) : mSocket(service), mTi mSocket.async_receive_from(boost::asio::buffer(mReceiveBuffer, 256), mReceiveEndpoint, boost::bind(&SNTPClient::receivePacket, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); - + mTimer.expires_from_now(boost::posix_time::seconds(NTP_QUERY_FREQUENCY)); mTimer.async_wait(boost::bind(&SNTPClient::timerEntry, this, boost::asio::placeholders::error)); } @@ -247,3 +247,4 @@ bool SNTPClient::doQuery() #endif return true; } +// vim:ts=4 diff --git a/src/SNTPClient.h b/src/SNTPClient.h index 51adf3ceb2..c2bf75ec63 100644 --- a/src/SNTPClient.h +++ b/src/SNTPClient.h @@ -56,3 +56,4 @@ public: }; #endif +// vim:ts=4 From 9c66ae8ef0da6045a2c2c08b981b63512678c47d Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Thu, 16 Aug 2012 14:06:06 -0700 Subject: [PATCH 2/5] Fixes for ripple path expansion. --- src/TransactionEngine.cpp | 144 +++++++++++++++++++++++++++++--------- src/TransactionEngine.h | 6 +- 2 files changed, 116 insertions(+), 34 deletions(-) diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index c0c32519c5..a2ebca5f4c 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -113,13 +113,24 @@ STAmount TransactionEngine::rippleBalance(const uint160& uToAccountID, const uin STAmount saBalance; SLE::pointer sleRippleState = entryCache(ltRIPPLE_STATE, Ledger::getRippleStateIndex(uToAccountID, uFromAccountID, uCurrencyID)); - assert(sleRippleState); if (sleRippleState) { saBalance = sleRippleState->getIValueFieldAmount(sfBalance); if (uToAccountID < uFromAccountID) saBalance.negate(); } + else + { + Log(lsINFO) << "rippleBalance: No credit line between " + << NewcoinAddress::createHumanAccountID(uFromAccountID) + << " and " + << NewcoinAddress::createHumanAccountID(uToAccountID) + << " for " + << STAmount::createHumanCurrency(uCurrencyID) + << "." ; + + assert(false); + } return saBalance; @@ -164,7 +175,13 @@ uint32 TransactionEngine::rippleQualityIn(const uint160& uToAccountID, const uin if (sleRippleState) { - uQualityIn = sleRippleState->getIFieldU32(uToAccountID < uFromAccountID ? sfLowQualityIn : sfHighQualityIn); + SOE_Field sfField = uToAccountID < uFromAccountID ? sfLowQualityIn : sfHighQualityIn; + + uQualityIn = sleRippleState->getIFieldPresent(sfField) + ? sleRippleState->getIFieldU32(sfField) + : QUALITY_ONE; + if (!uQualityIn) + uQualityIn = 1; } else { @@ -190,6 +207,8 @@ uint32 TransactionEngine::rippleQualityOut(const uint160& uToAccountID, const ui if (sleRippleState) { uQualityOut = sleRippleState->getIFieldU32(uToAccountID < uFromAccountID ? sfLowQualityOut : sfHighQualityOut); + if (!uQualityOut) + uQualityOut = 1; } else { @@ -2517,6 +2536,7 @@ void TransactionEngine::calcNodeOffer( // actual send toward the reciver. // This routine works backwards as it calculates previous wants based on previous credit limits and current wants. // This routine works forwards as it calculates current deliver based on previous delivery limits and current wants. +// XXX Deal with uQualityIn or uQualityOut = 0 void TransactionEngine::calcNodeRipple( const uint32 uQualityIn, const uint32 uQualityOut, @@ -2525,8 +2545,18 @@ void TransactionEngine::calcNodeRipple( STAmount& saPrvAct, // <-> in limit including achieved STAmount& saCurAct) // <-> out limit achieved. { + Log(lsINFO) << str(boost::format("calcNodeRipple> uQualityIn=%d uQualityOut=%d saPrvReq=%s/%s saCurReq=%s/%s") + % uQualityIn + % uQualityOut + % saPrvReq.getText() + % saPrvReq.getHumanCurrency() + % saCurReq.getText() + % saCurReq.getHumanCurrency()); + + assert(saPrvReq.getCurrency() == saCurReq.getCurrency()); + bool bPrvUnlimited = saPrvReq.isNegative(); - STAmount saPrv = bPrvUnlimited ? saZero : saPrvReq-saPrvAct; + STAmount saPrv = bPrvUnlimited ? STAmount(saPrvReq) : saPrvReq-saPrvAct; STAmount saCur = saCurReq-saCurAct; if (uQualityIn >= uQualityOut) @@ -2573,8 +2603,8 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point bool bPrvRedeem = !!(prvPN.uFlags & STPathElement::typeRedeem); bool bIssue = !!(curPN.uFlags & STPathElement::typeIssue); bool bPrvIssue = !!(prvPN.uFlags & STPathElement::typeIssue); - bool bPrvAccount = !!(prvPN.uFlags & STPathElement::typeAccount); - bool bNxtAccount = !!(nxtPN.uFlags & STPathElement::typeAccount); + bool bPrvAccount = uIndex && !!(prvPN.uFlags & STPathElement::typeAccount); + bool bNxtAccount = uIndex != uLast && !!(nxtPN.uFlags & STPathElement::typeAccount); uint160& uPrvAccountID = prvPN.uAccountID; uint160& uCurAccountID = curPN.uAccountID; @@ -2582,17 +2612,17 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point uint160& uCurrencyID = curPN.uCurrencyID; - uint32 uQualityIn = rippleQualityIn(uCurAccountID, uPrvAccountID, uCurrencyID); - uint32 uQualityOut = rippleQualityOut(uCurAccountID, uNxtAccountID, uCurrencyID); + uint32 uQualityIn = uIndex ? rippleQualityIn(uCurAccountID, uPrvAccountID, uCurrencyID) : 0; + uint32 uQualityOut = uIndex != uLast ? rippleQualityOut(uCurAccountID, uNxtAccountID, uCurrencyID) : 0; // For bPrvAccount - STAmount saPrvBalance = bPrvAccount ? rippleBalance(uCurAccountID, uPrvAccountID, uCurrencyID) : saZero; - STAmount saPrvLimit = bPrvAccount ? rippleLimit(uCurAccountID, uPrvAccountID, uCurrencyID) : saZero; + STAmount saPrvBalance = bPrvAccount ? rippleBalance(uCurAccountID, uPrvAccountID, uCurrencyID) : STAmount(uCurrencyID); + STAmount saPrvLimit = bPrvAccount ? rippleLimit(uCurAccountID, uPrvAccountID, uCurrencyID) : STAmount(uCurrencyID); STAmount saPrvRedeemReq = bPrvRedeem && saPrvBalance.isNegative() ? -saPrvBalance : STAmount(uCurrencyID, 0); STAmount& saPrvRedeemAct = prvPN.saRevRedeem; - STAmount saPrvIssueReq = bPrvIssue && saPrvLimit - saPrvBalance; + STAmount saPrvIssueReq = bPrvIssue ? saPrvLimit - saPrvBalance : STAmount(uCurrencyID); STAmount& saPrvIssueAct = prvPN.saRevIssue; // For !bPrvAccount @@ -2601,19 +2631,25 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point // For bNxtAccount const STAmount& saCurRedeemReq = curPN.saRevRedeem; - STAmount saCurRedeemAct; + STAmount saCurRedeemAct(saCurRedeemReq.getCurrency()); const STAmount& saCurIssueReq = curPN.saRevIssue; - STAmount saCurIssueAct; // Track progress. + STAmount saCurIssueAct(saCurIssueReq.getCurrency()); // Track progress. // For !bNxtAccount const STAmount& saCurDeliverReq = curPN.saRevDeliver; - STAmount saCurDeliverAct; + STAmount saCurDeliverAct(saCurDeliverReq.getCurrency()); // For uIndex == uLast const STAmount& saCurWantedReq = pspCur->saOutReq; // XXX Credit limits? // STAmount saPrvDeliverReq = saPrvBalance.isPositive() ? saPrvLimit - saPrvBalance : saPrvLimit; - STAmount saCurWantedAct; + STAmount saCurWantedAct(saCurWantedReq.getCurrency()); + + Log(lsINFO) << str(boost::format("calcNodeAccountRev> saPrvRedeemReq=%s/%s saCurWantedAct=%s/%s") + % saPrvRedeemReq.getText() + % saPrvRedeemReq.getHumanCurrency() + % saCurWantedAct.getText() + % saCurWantedAct.getHumanCurrency()); if (bPrvAccount && bNxtAccount) { @@ -3156,6 +3192,40 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin !!pnCur.uCurrencyID ? uAccountID : ACCOUNT_XNS); // Account as issuer. } + if (bValid && !vpnNodes.empty()) + { + const paymentNode& pnBck = vpnNodes.back(); + bool bBckAccount = !!(pnBck.uFlags & STPathElement::typeAccount); + + if (bBckAccount) + { + SLE::pointer sleRippleState = mLedger->getSLE(Ledger::getRippleStateIndex(pnBck.uAccountID, pnCur.uAccountID, pnPrv.uCurrencyID)); + + if (!sleRippleState) + { + Log(lsINFO) << "pushNode: No credit line between " + << NewcoinAddress::createHumanAccountID(pnBck.uAccountID) + << " and " + << NewcoinAddress::createHumanAccountID(pnCur.uAccountID) + << " for " + << STAmount::createHumanCurrency(pnPrv.uCurrencyID) + << "." ; + + bValid = false; + } + else + { + Log(lsINFO) << "pushNode: Credit line found between " + << NewcoinAddress::createHumanAccountID(pnBck.uAccountID) + << " and " + << NewcoinAddress::createHumanAccountID(pnCur.uAccountID) + << " for " + << STAmount::createHumanCurrency(pnPrv.uCurrencyID) + << "." ; + } + } + } + if (bValid) vpnNodes.push_back(pnCur); } @@ -3199,11 +3269,11 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin if (bValid) { // Verify that previous account is allowed to issue. - const paymentNode& pnLst = vpnNodes.back(); - bool bLstAccount = !!(pnLst.uFlags & STPathElement::typeAccount); - bool bLstIssue = !!(pnLst.uFlags & STPathElement::typeIssue); + const paymentNode& pnBck = vpnNodes.back(); + bool bBckAccount = !!(pnBck.uFlags & STPathElement::typeAccount); + bool bBckIssue = !!(pnBck.uFlags & STPathElement::typeIssue); - if (bLstAccount && !bLstIssue) + if (bBckAccount && !bBckIssue) { Log(lsINFO) << "pushNode: previous account must be allowed to issue."; @@ -3222,6 +3292,7 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin // XXX Disallow loops in ripple paths PathState::PathState( + Ledger::pointer lpLedger, int iIndex, const LedgerEntrySet& lesSource, const STPath& spSourcePath, @@ -3231,7 +3302,7 @@ PathState::PathState( STAmount saSendMax, bool bPartialPayment ) - : mIndex(iIndex), uQuality(0) + : mLedger(lpLedger), mIndex(iIndex), uQuality(0) { uint160 uInCurrencyID = saSendMax.getCurrency(); uint160 uOutCurrencyID = saSend.getCurrency(); @@ -3335,7 +3406,7 @@ Json::Value PathState::getJson() const // Calculate a node and its previous nodes. // From the destination work towards the source calculating how much must be asked for. // --> bAllowPartial: If false, fail if can't meet requirements. -// <-- bSuccess: true=success, false=insufficient funds / liqudity. +// <-- bValid: true=success, false=insufficient funds / liqudity. // <-> pnNodes: // --> [end]saWanted.mAmount // --> [all]saWanted.mCurrency @@ -3346,28 +3417,28 @@ bool TransactionEngine::calcNode(unsigned int uIndex, PathState::pointer pspCur, { paymentNode& curPN = pspCur->vpnNodes[uIndex]; bool bCurAccount = !!(curPN.uFlags & STPathElement::typeAccount); - bool bSuccess; + bool bValid; // Do current node reverse. - bSuccess = bCurAccount - ? calcNodeAccountRev(uIndex, pspCur, bMultiQuality) - : calcNodeOfferRev(uIndex, pspCur, bMultiQuality); + bValid = bCurAccount + ? calcNodeAccountRev(uIndex, pspCur, bMultiQuality) + : calcNodeOfferRev(uIndex, pspCur, bMultiQuality); // Do previous. - if (bSuccess && uIndex) + if (bValid && uIndex) { - bSuccess = calcNode(uIndex-1, pspCur, bMultiQuality); + bValid = calcNode(uIndex-1, pspCur, bMultiQuality); } // Do current node forward. - if (bSuccess) + if (bValid) { - bSuccess = bCurAccount - ? calcNodeAccountFwd(uIndex, pspCur, bMultiQuality) - : calcNodeOfferFwd(uIndex, pspCur, bMultiQuality); + bValid = bCurAccount + ? calcNodeAccountFwd(uIndex, pspCur, bMultiQuality) + : calcNodeOfferFwd(uIndex, pspCur, bMultiQuality); } - return bSuccess; + return bValid; } // Calculate the next increment of a path. @@ -3384,9 +3455,14 @@ void TransactionEngine::pathNext(PathState::pointer pspCur, int iPaths) assert(pspCur->vpnNodes.size() >= 2); - bool bZero = !calcNode(uLast, pspCur, iPaths == 1); + bool bValid = calcNode(uLast, pspCur, iPaths == 1); - pspCur->uQuality = bZero + Log(lsINFO) << "pathNext: bValid=" + << bValid + << " saOutAct=" << pspCur->saOutAct.getText() + << " saInAct=" << pspCur->saInAct.getText(); + + pspCur->uQuality = bValid ? STAmount::getRate(pspCur->saOutAct, pspCur->saInAct) // Calculate relative quality. : 0; // Mark path as inactive. @@ -3603,6 +3679,7 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction // Direct path. Log(lsINFO) << "doPayment: Build direct:"; vpsPaths.push_back(PathState::createPathState( + mLedger, vpsPaths.size(), mNodes, STPath(), @@ -3618,6 +3695,7 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction { Log(lsINFO) << "doPayment: Build path:"; vpsPaths.push_back(PathState::createPathState( + mLedger, vpsPaths.size(), mNodes, spPath, diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index f6e054e4cd..3d54952d5a 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -125,6 +125,8 @@ typedef struct { class PathState { protected: + Ledger::pointer mLedger; + bool pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uint160 uIssuerID); bool pushImply(uint160 uAccountID, uint160 uCurrencyID, uint160 uIssuerID); @@ -143,6 +145,7 @@ public: STAmount saOutAct; // Amount actually sent (calc output). PathState( + Ledger::pointer lpLedger, int iIndex, const LedgerEntrySet& lesSource, const STPath& spSourcePath, @@ -156,6 +159,7 @@ public: Json::Value getJson() const; static PathState::pointer createPathState( + Ledger::pointer lpLedger, int iIndex, const LedgerEntrySet& lesSource, const STPath& spSourcePath, @@ -165,7 +169,7 @@ public: STAmount saSendMax, bool bPartialPayment ) - { return boost::make_shared(iIndex, lesSource, spSourcePath, uReceiverID, uSenderID, saSend, saSendMax, bPartialPayment); }; + { return boost::make_shared(lpLedger, iIndex, lesSource, spSourcePath, uReceiverID, uSenderID, saSend, saSendMax, bPartialPayment); }; static bool lessPriority(const PathState::pointer& lhs, const PathState::pointer& rhs); }; From 27f4a2ce30dfd742d87e6bedc8fddaf457ed1f10 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Thu, 16 Aug 2012 14:13:59 -0700 Subject: [PATCH 3/5] Disable SNTPClient in standalone mode, try 2. --- src/Application.cpp | 3 +-- src/SNTPClient.cpp | 16 ++++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Application.cpp b/src/Application.cpp index dd94fb43b9..2fe18c161f 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -73,8 +73,7 @@ void Application::run() boost::thread auxThread(boost::bind(&boost::asio::io_service::run, &mAuxService)); auxThread.detach(); - if (!theConfig.RUN_STANDALONE) - mSNTPClient.init(theConfig.SNTP_SERVERS); + mSNTPClient.init(theConfig.SNTP_SERVERS); // // Construct databases. diff --git a/src/SNTPClient.cpp b/src/SNTPClient.cpp index 11a7915fae..d204b6a8ec 100644 --- a/src/SNTPClient.cpp +++ b/src/SNTPClient.cpp @@ -6,6 +6,7 @@ #include #include "utils.h" +#include "Config.h" #include "Log.h" // #define SNTP_DEBUG @@ -43,13 +44,16 @@ static uint8_t SNTPQueryData[48] = SNTPClient::SNTPClient(boost::asio::io_service& service) : mSocket(service), mTimer(service), mResolver(service), mOffset(0), mLastOffsetUpdate((time_t) -1), mReceiveBuffer(256) { - mSocket.open(boost::asio::ip::udp::v4()); - mSocket.async_receive_from(boost::asio::buffer(mReceiveBuffer, 256), mReceiveEndpoint, - boost::bind(&SNTPClient::receivePacket, this, boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); + if (!theConfig.RUN_STANDALONE) + { + mSocket.open(boost::asio::ip::udp::v4()); + mSocket.async_receive_from(boost::asio::buffer(mReceiveBuffer, 256), mReceiveEndpoint, + boost::bind(&SNTPClient::receivePacket, this, boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); - mTimer.expires_from_now(boost::posix_time::seconds(NTP_QUERY_FREQUENCY)); - mTimer.async_wait(boost::bind(&SNTPClient::timerEntry, this, boost::asio::placeholders::error)); + mTimer.expires_from_now(boost::posix_time::seconds(NTP_QUERY_FREQUENCY)); + mTimer.async_wait(boost::bind(&SNTPClient::timerEntry, this, boost::asio::placeholders::error)); + } } void SNTPClient::resolveComplete(const boost::system::error_code& error, boost::asio::ip::udp::resolver::iterator it) From f2902ca0148d3e6fdd28c9f2bee3f9c1e63b124e Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Fri, 17 Aug 2012 17:08:23 -0700 Subject: [PATCH 4/5] Make json full text for STAccount more legible. --- src/Amount.cpp | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/Amount.cpp b/src/Amount.cpp index 1e2db3124c..e6616a9c35 100644 --- a/src/Amount.cpp +++ b/src/Amount.cpp @@ -880,6 +880,30 @@ STAmount STAmount::deserialize(SerializerIterator& it) } std::string STAmount::getFullText() const +{ + if (mIsNative) + { + return str(boost::format("%s/" SYSTEM_CURRENCY_CODE) % getText()); + } + else if (!mIssuer) + { + return str(boost::format("%s/%s/0") % getText() % getHumanCurrency()); + } + else if (mIssuer == ACCOUNT_ONE) + { + return str(boost::format("%s/%s/1") % getText() % getHumanCurrency()); + } + else + { + return str(boost::format("%s/%s/%s") + % getText() + % getHumanCurrency() + % NewcoinAddress::createHumanAccountID(mIssuer)); + } +} + +#if 0 +std::string STAmount::getExtendedText() const { if (mIsNative) { @@ -887,7 +911,7 @@ std::string STAmount::getFullText() const } else { - return str(boost::format("%s %s/%s %dE%d" ) + return str(boost::format("%s/%s/%s %dE%d" ) % getText() % getHumanCurrency() % NewcoinAddress::createHumanAccountID(mIssuer) @@ -895,6 +919,7 @@ std::string STAmount::getFullText() const % getExponent()); } } +#endif Json::Value STAmount::getJson(int) const { From 99d1451c29a9c65d637b0faac16683d975104b47 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Fri, 17 Aug 2012 17:11:13 -0700 Subject: [PATCH 5/5] Fixes for direct ripple with quality to work. --- src/SerializedTypes.h | 6 + src/TransactionEngine.cpp | 234 +++++++++++++++++++++++++++++--------- src/TransactionEngine.h | 4 +- 3 files changed, 190 insertions(+), 54 deletions(-) diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index 63977102ca..b1a264cde4 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -50,6 +50,12 @@ enum PathFlags PF_ISSUE = 0x80, }; +#define QUALITY_ONE 100000000 // 10e9 +#define CURRENCY_XNS uint160(0) +#define CURRENCY_ONE uint160(1) // Used as a place holder +#define ACCOUNT_XNS uint160(0) +#define ACCOUNT_ONE uint160(1) // Used as a place holder + class SerializedType { protected: diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index a2ebca5f4c..1170fd00ae 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -21,12 +21,6 @@ #define DIR_NODE_MAX 2 #define RIPPLE_PATHS_MAX 3 -#define QUALITY_ONE 100000000 // 10e9 -#define CURRENCY_XNS uint160(0) -#define CURRENCY_ONE uint160(1) // Used as a place holder -#define ACCOUNT_XNS uint160(0) -#define ACCOUNT_ONE uint160(1) // Used as a place holder - static STAmount saZero(CURRENCY_ONE, 0, 0); static STAmount saOne(CURRENCY_ONE, 1, 0); @@ -324,11 +318,11 @@ STAmount TransactionEngine::rippleTransfer(const uint160& uSenderID, const uint1 } // Direct send w/o fees: redeeming IOUs and/or sending own IOUs. -void TransactionEngine::rippleCredit(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount) +void TransactionEngine::rippleCredit(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount, bool bCheckIssuer) { uint160 uIssuerID = saAmount.getIssuer(); - assert(uSenderID == uIssuerID || uReceiverID == uIssuerID); + assert(!bCheckIssuer || uSenderID == uIssuerID || uReceiverID == uIssuerID); bool bFlipped = uSenderID > uReceiverID; uint256 uIndex = Ledger::getRippleStateIndex(uSenderID, uReceiverID, saAmount.getCurrency()); @@ -2545,13 +2539,13 @@ void TransactionEngine::calcNodeRipple( STAmount& saPrvAct, // <-> in limit including achieved STAmount& saCurAct) // <-> out limit achieved. { - Log(lsINFO) << str(boost::format("calcNodeRipple> uQualityIn=%d uQualityOut=%d saPrvReq=%s/%s saCurReq=%s/%s") + Log(lsINFO) << str(boost::format("calcNodeRipple> uQualityIn=%d uQualityOut=%d saPrvReq=%s saCurReq=%s saPrvAct=%s saCurAct=%s") % uQualityIn % uQualityOut - % saPrvReq.getText() - % saPrvReq.getHumanCurrency() - % saCurReq.getText() - % saCurReq.getHumanCurrency()); + % saPrvReq.getFullText() + % saCurReq.getFullText() + % saPrvAct.getFullText() + % saCurAct.getFullText()); assert(saPrvReq.getCurrency() == saCurReq.getCurrency()); @@ -2559,6 +2553,15 @@ void TransactionEngine::calcNodeRipple( STAmount saPrv = bPrvUnlimited ? STAmount(saPrvReq) : saPrvReq-saPrvAct; STAmount saCur = saCurReq-saCurAct; + Log(lsINFO) << str(boost::format("calcNodeRipple:1: saCurReq=%s") % saCurReq.getFullText()); + +#if 0 + Log(lsINFO) << str(boost::format("calcNodeRipple: bPrvUnlimited=%d saPrv=%s saCur=%s") + % bPrvUnlimited + % saPrv.getFullText() + % saCur.getFullText()); +#endif + if (uQualityIn >= uQualityOut) { // No fee. @@ -2570,23 +2573,37 @@ void TransactionEngine::calcNodeRipple( else { // Fee. - STAmount saCurIn = STAmount::divide(STAmount::multiply(saCur, uQualityOut, CURRENCY_ONE), uQualityIn, CURRENCY_ONE); + uint160 uCurrencyID = saCur.getCurrency(); + STAmount saCurIn = STAmount::divide(STAmount::multiply(saCur, uQualityOut, uCurrencyID), uQualityIn, uCurrencyID); +Log(lsINFO) << str(boost::format("calcNodeRipple:2: saCurReq=%s") % saCurReq.getFullText()); if (bPrvUnlimited || saCurIn >= saPrv) { // All of cur. Some amount of prv. +Log(lsINFO) << str(boost::format("calcNodeRipple:3a: saCurReq=%s") % saCurReq.getFullText()); saCurAct = saCurReq; saPrvAct += saCurIn; +Log(lsINFO) << str(boost::format("calcNodeRipple:3c: saCurReq=%s saPrvAct=%s") % saCurReq.getFullText() % saPrvAct.getFullText()); } else { // A part of cur. All of prv. (cur as driver) - STAmount saCurOut = STAmount::divide(STAmount::multiply(saPrv, uQualityIn, CURRENCY_ONE), uQualityOut, CURRENCY_ONE); + uint160 uCurrencyID = saPrv.getCurrency(); + STAmount saCurOut = STAmount::divide(STAmount::multiply(saPrv, uQualityIn, uCurrencyID), uQualityOut, uCurrencyID); +Log(lsINFO) << str(boost::format("calcNodeRipple:4: saCurReq=%s") % saCurReq.getFullText()); saCurAct += saCurOut; saPrvAct = saPrvReq; } } + + Log(lsINFO) << str(boost::format("calcNodeRipple< uQualityIn=%d uQualityOut=%d saPrvReq=%s saCurReq=%s saPrvAct=%s saCurAct=%s") + % uQualityIn + % uQualityOut + % saPrvReq.getFullText() + % saCurReq.getFullText() + % saPrvAct.getFullText() + % saCurAct.getFullText()); } // Calculate saPrvRedeemReq, saPrvIssueReq, saPrvDeliver; @@ -2603,30 +2620,30 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point bool bPrvRedeem = !!(prvPN.uFlags & STPathElement::typeRedeem); bool bIssue = !!(curPN.uFlags & STPathElement::typeIssue); bool bPrvIssue = !!(prvPN.uFlags & STPathElement::typeIssue); - bool bPrvAccount = uIndex && !!(prvPN.uFlags & STPathElement::typeAccount); - bool bNxtAccount = uIndex != uLast && !!(nxtPN.uFlags & STPathElement::typeAccount); + bool bPrvAccount = !uIndex || !!(prvPN.uFlags & STPathElement::typeAccount); + bool bNxtAccount = uIndex == uLast || !!(nxtPN.uFlags & STPathElement::typeAccount); - uint160& uPrvAccountID = prvPN.uAccountID; - uint160& uCurAccountID = curPN.uAccountID; - uint160& uNxtAccountID = bNxtAccount ? nxtPN.uAccountID : uCurAccountID; // Offers are always issue. + const uint160& uPrvAccountID = prvPN.uAccountID; + const uint160& uCurAccountID = curPN.uAccountID; + const uint160& uNxtAccountID = bNxtAccount ? nxtPN.uAccountID : uCurAccountID; // Offers are always issue. - uint160& uCurrencyID = curPN.uCurrencyID; + const uint160& uCurrencyID = curPN.uCurrencyID; - uint32 uQualityIn = uIndex ? rippleQualityIn(uCurAccountID, uPrvAccountID, uCurrencyID) : 0; - uint32 uQualityOut = uIndex != uLast ? rippleQualityOut(uCurAccountID, uNxtAccountID, uCurrencyID) : 0; + const uint32 uQualityIn = uIndex ? rippleQualityIn(uCurAccountID, uPrvAccountID, uCurrencyID) : 1; + const uint32 uQualityOut = uIndex != uLast ? rippleQualityOut(uCurAccountID, uNxtAccountID, uCurrencyID) : 1; // For bPrvAccount - STAmount saPrvBalance = bPrvAccount ? rippleBalance(uCurAccountID, uPrvAccountID, uCurrencyID) : STAmount(uCurrencyID); - STAmount saPrvLimit = bPrvAccount ? rippleLimit(uCurAccountID, uPrvAccountID, uCurrencyID) : STAmount(uCurrencyID); + const STAmount saPrvBalance = uIndex && bPrvAccount ? rippleBalance(uCurAccountID, uPrvAccountID, uCurrencyID) : STAmount(uCurrencyID); + const STAmount saPrvLimit = uIndex && bPrvAccount ? rippleLimit(uCurAccountID, uPrvAccountID, uCurrencyID) : STAmount(uCurrencyID); - STAmount saPrvRedeemReq = bPrvRedeem && saPrvBalance.isNegative() ? -saPrvBalance : STAmount(uCurrencyID, 0); + const STAmount saPrvRedeemReq = bPrvRedeem && saPrvBalance.isNegative() ? -saPrvBalance : STAmount(uCurrencyID, 0); STAmount& saPrvRedeemAct = prvPN.saRevRedeem; - STAmount saPrvIssueReq = bPrvIssue ? saPrvLimit - saPrvBalance : STAmount(uCurrencyID); + const STAmount saPrvIssueReq = bPrvIssue ? saPrvLimit - saPrvBalance : STAmount(uCurrencyID); STAmount& saPrvIssueAct = prvPN.saRevIssue; // For !bPrvAccount - STAmount saPrvDeliverReq = STAmount(uCurrencyID, -1); // Unlimited. + const STAmount saPrvDeliverReq = STAmount(uCurrencyID, -1); // Unlimited. STAmount& saPrvDeliverAct = prvPN.saRevDeliver; // For bNxtAccount @@ -2645,23 +2662,38 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point // STAmount saPrvDeliverReq = saPrvBalance.isPositive() ? saPrvLimit - saPrvBalance : saPrvLimit; STAmount saCurWantedAct(saCurWantedReq.getCurrency()); - Log(lsINFO) << str(boost::format("calcNodeAccountRev> saPrvRedeemReq=%s/%s saCurWantedAct=%s/%s") + Log(lsINFO) << str(boost::format("calcNodeAccountRev> uIndex=%d/%d saPrvRedeemReq=%s/%s saPrvIssueReq=%s/%s saCurWantedReq=%s/%s") + % uIndex + % uLast % saPrvRedeemReq.getText() % saPrvRedeemReq.getHumanCurrency() - % saCurWantedAct.getText() - % saCurWantedAct.getHumanCurrency()); + % saPrvIssueReq.getText() + % saPrvIssueReq.getHumanCurrency() + % saCurWantedReq.getText() + % saCurWantedReq.getHumanCurrency()); + + Log(lsINFO) << pspCur->getJson(); if (bPrvAccount && bNxtAccount) { - if (uIndex == uLast) + if (!uIndex) + { + // ^ --> ACCOUNT --> account|offer + // Nothing to do, there is no previous to adjust. + nothing(); + } + else if (uIndex == uLast) { // account --> ACCOUNT --> $ + Log(lsINFO) << str(boost::format("calcNodeAccountRev: account --> ACCOUNT --> $")); // Calculate redeem if (bRedeem && saPrvRedeemReq) // Previous has IOUs to redeem. { // Redeem at 1:1 + Log(lsINFO) << str(boost::format("calcNodeAccountRev: Redeem at 1:1")); + saCurWantedAct = MIN(saPrvRedeemReq, saCurWantedReq); saPrvRedeemAct = saCurWantedAct; } @@ -2672,6 +2704,8 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point && saPrvIssueReq) // Will accept IOUs. { // Rate: quality in : 1.0 + Log(lsINFO) << str(boost::format("calcNodeAccountRev: Rate: quality in : 1.0")); + calcNodeRipple(uQualityIn, QUALITY_ONE, saPrvIssueReq, saCurWantedReq, saPrvIssueAct, saCurWantedAct); } @@ -2684,7 +2718,7 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point } else { - // account --> ACCOUNT --> account + // ^|account --> ACCOUNT --> account // redeem (part 1) -> redeem if (bPrvRedeem @@ -2693,6 +2727,8 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point && saPrvBalance.isNegative()) // Previous has IOUs to redeem. { // Rate : 1.0 : quality out + Log(lsINFO) << str(boost::format("calcNodeAccountRev: Rate : 1.0 : quality out")); + calcNodeRipple(QUALITY_ONE, uQualityOut, saPrvRedeemReq, saCurRedeemReq, saPrvRedeemAct, saCurRedeemAct); } @@ -2704,6 +2740,8 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point && saCurIssueReq) // Need some issued. { // Rate : 1.0 : transfer_rate + Log(lsINFO) << str(boost::format("calcNodeAccountRev: Rate : 1.0 : transfer_rate")); + calcNodeRipple(QUALITY_ONE, rippleTransfer(uCurAccountID), saPrvRedeemReq, saCurIssueReq, saPrvRedeemAct, saCurIssueAct); } @@ -2714,17 +2752,21 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point && !saPrvBalance.isNegative()) // Previous has no IOUs. { // Rate: quality in : quality out + Log(lsINFO) << str(boost::format("calcNodeAccountRev: Rate: quality in : quality out")); + calcNodeRipple(uQualityIn, uQualityOut, saPrvIssueReq, saCurRedeemReq, saPrvIssueAct, saCurRedeemAct); } // issue (part 2) -> issue if (bPrvIssue && bIssue // Allowed to issue. - && saCurRedeemReq != saCurRedeemAct // Can only if issue if more can not be redeemed. + && saCurRedeemReq == saCurRedeemAct // Can only if issue if more can not be redeemed. && !saPrvBalance.isNegative() // Previous has no IOUs. && saCurIssueReq != saCurIssueAct) // Need some issued. { // Rate: quality in : 1.0 + Log(lsINFO) << str(boost::format("calcNodeAccountRev: Rate: quality in : 1.0")); + calcNodeRipple(uQualityIn, QUALITY_ONE, saPrvIssueReq, saCurIssueReq, saPrvIssueAct, saCurIssueAct); } @@ -2734,12 +2776,23 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point // terResult = tenBAD_AMOUNT; bSuccess = false; } + Log(lsINFO) << str(boost::format("calcNodeAccountRev: ^|account --> ACCOUNT --> account : bPrvRedeem=%d bPrvIssue=%d bRedeem=%d bIssue=%d saCurRedeemReq=%s saCurIssueReq=%s saPrvBalance=%s saCurRedeemAct=%s saCurIssueAct=%s") + % bPrvRedeem + % bPrvIssue + % bRedeem + % bIssue + % saCurRedeemReq.getFullText() + % saCurIssueReq.getFullText() + % saPrvBalance.getFullText() + % saCurRedeemAct.getFullText() + % saCurIssueAct.getFullText()); } } else if (bPrvAccount && !bNxtAccount) { // account --> ACCOUNT --> offer // Note: deliver is always issue as ACCOUNT is the issuer for the offer input. + Log(lsINFO) << str(boost::format("calcNodeAccountRev: account --> ACCOUNT --> offer")); // redeem -> deliver/issue. if (bPrvRedeem @@ -2773,6 +2826,7 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point if (uIndex == uLast) { // offer --> ACCOUNT --> $ + Log(lsINFO) << str(boost::format("calcNodeAccountRev: offer --> ACCOUNT --> $")); // Rate: quality in : 1.0 calcNodeRipple(uQualityIn, QUALITY_ONE, saPrvDeliverReq, saCurWantedReq, saPrvDeliverAct, saCurWantedAct); @@ -2788,6 +2842,7 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point { // offer --> ACCOUNT --> account // Note: offer is always deliver/redeeming as account is issuer. + Log(lsINFO) << str(boost::format("calcNodeAccountRev: offer --> ACCOUNT --> account")); // deliver -> redeem if (bRedeem // Allowed to redeem. @@ -2820,6 +2875,8 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point { // offer --> ACCOUNT --> offer // deliver/redeem -> deliver/issue. + Log(lsINFO) << str(boost::format("calcNodeAccountRev: offer --> ACCOUNT --> offer")); + if (bIssue // Allowed to issue. && saCurDeliverReq != saCurDeliverAct) // Can only if issue if more can not be redeemed. { @@ -2869,14 +2926,14 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point // For bNxtAccount const STAmount& saPrvRedeemReq = prvPN.saFwdRedeem; - STAmount saPrvRedeemAct; + STAmount saPrvRedeemAct(saPrvRedeemReq.getCurrency()); const STAmount& saPrvIssueReq = prvPN.saFwdIssue; - STAmount saPrvIssueAct; + STAmount saPrvIssueAct(saPrvIssueReq.getCurrency()); // For !bPrvAccount const STAmount& saPrvDeliverReq = prvPN.saRevDeliver; - STAmount saPrvDeliverAct; + STAmount saPrvDeliverAct(saPrvDeliverReq.getCurrency()); // For bNxtAccount const STAmount& saCurRedeemReq = curPN.saRevRedeem; @@ -2891,6 +2948,16 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point STAmount& saCurReceive = pspCur->saOutAct; + Log(lsINFO) << str(boost::format("calcNodeAccountFwd> uIndex=%d/%d saCurRedeemReq=%s/%s saCurIssueReq=%s/%s saCurDeliverReq=%s/%s") + % uIndex + % uLast + % saCurRedeemReq.getText() + % saCurRedeemReq.getHumanCurrency() + % saCurIssueReq.getText() + % saCurIssueReq.getHumanCurrency() + % saCurDeliverReq.getText() + % saCurDeliverReq.getHumanCurrency()); + // Ripple through account. if (bPrvAccount && bNxtAccount) @@ -2908,26 +2975,49 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point STAmount& saCurIssueReq = curPN.saRevIssue; STAmount& saCurIssueAct = curPN.saFwdIssue; - STAmount& saCurSendMaxReq = pspCur->saInReq; - STAmount& saCurSendMaxAct = pspCur->saInAct; + STAmount& saCurSendMaxReq = pspCur->saInReq; // Negative for no limit, doing a calculation. + STAmount& saCurSendMaxAct = pspCur->saInAct; // Report to user how much this sends. if (saCurRedeemReq) { // Redeem requested. - saCurRedeemAct = MIN(saCurRedeemAct, saCurSendMaxReq); - saCurSendMaxAct = saCurRedeemAct; + saCurRedeemAct = saCurRedeemReq.isNegative() + ? saCurRedeemReq + : MIN(saCurRedeemReq, saCurSendMaxReq); } + else + { + saCurRedeemAct = STAmount(saCurRedeemReq); + } + saCurSendMaxAct = saCurRedeemAct; - if (saCurIssueReq && saCurSendMaxReq != saCurRedeemAct) + if (saCurIssueReq && (saCurSendMaxReq.isNegative() || saCurSendMaxReq != saCurRedeemAct)) { // Issue requested and not over budget. - saCurIssueAct = MIN(saCurSendMaxReq-saCurRedeemAct, saCurIssueReq); - // saCurSendMaxAct += saCurIssueReq; // Not needed. + saCurIssueAct = saCurSendMaxReq.isNegative() + ? saCurIssueReq + : MIN(saCurSendMaxReq-saCurRedeemAct, saCurIssueReq); } + else + { + saCurIssueAct = STAmount(saCurIssueReq); + } + saCurSendMaxAct += saCurIssueAct; + + Log(lsINFO) << str(boost::format("calcNodeAccountFwd: ^ --> ACCOUNT --> account : saCurSendMaxReq=%s saCurRedeemAct=%s saCurIssueReq=%s saCurIssueAct=%s") + % saCurSendMaxReq.getFullText() + % saCurRedeemAct.getFullText() + % saCurIssueReq.getFullText() + % saCurIssueAct.getFullText()); } else if (uIndex == uLast) { // account --> ACCOUNT --> $ + Log(lsINFO) << str(boost::format("calcNodeAccountFwd: account --> ACCOUNT --> $ : uPrvAccountID=%s uCurAccountID=%s saPrvRedeemReq=%s saPrvIssueReq=%s") + % NewcoinAddress::createHumanAccountID(uPrvAccountID) + % NewcoinAddress::createHumanAccountID(uCurAccountID) + % saPrvRedeemReq.getFullText() + % saPrvIssueReq.getFullText()); // Last node. Accept all funds. Calculate amount actually to credit. @@ -2939,11 +3029,12 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point saCurReceive = saPrvRedeemReq+saIssueCrd; // Actually receive. - rippleCredit(uPrvAccountID, uCurAccountID, saPrvRedeemReq+saPrvIssueReq); + rippleCredit(uPrvAccountID, uCurAccountID, saPrvRedeemReq+saPrvIssueReq, false); } else { // account --> ACCOUNT --> account + Log(lsINFO) << str(boost::format("calcNodeAccountFwd: account --> ACCOUNT --> account")); // Previous redeem part 1: redeem -> redeem if (bRedeem // Can redeem. @@ -2984,12 +3075,13 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point // Adjust prv --> cur balance : take all inbound // XXX Currency must be in amount. - rippleCredit(uPrvAccountID, uCurAccountID, saPrvRedeemReq + saPrvIssueReq); + rippleCredit(uPrvAccountID, uCurAccountID, saPrvRedeemReq + saPrvIssueReq, false); } } else if (bPrvAccount && !bNxtAccount) { // account --> ACCOUNT --> offer + Log(lsINFO) << str(boost::format("calcNodeAccountFwd: account --> ACCOUNT --> offer")); // redeem -> issue. // wants to redeem and current would and can issue. @@ -3010,13 +3102,14 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point // Adjust prv --> cur balance : take all inbound // XXX Currency must be in amount. - rippleCredit(uPrvAccountID, uCurAccountID, saPrvRedeemReq + saPrvIssueReq); + rippleCredit(uPrvAccountID, uCurAccountID, saPrvRedeemReq + saPrvIssueReq, false); } else if (!bPrvAccount && bNxtAccount) { if (uIndex == uLast) { // offer --> ACCOUNT --> $ + Log(lsINFO) << str(boost::format("calcNodeAccountFwd: offer --> ACCOUNT --> $")); // Amount to credit. saCurReceive = saPrvDeliverAct; @@ -3026,6 +3119,7 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point else { // offer --> ACCOUNT --> account + Log(lsINFO) << str(boost::format("calcNodeAccountFwd: offer --> ACCOUNT --> account")); // deliver -> redeem if (bRedeem // Allowed to redeem. @@ -3053,6 +3147,8 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point { // offer --> ACCOUNT --> offer // deliver/redeem -> deliver/issue. + Log(lsINFO) << str(boost::format("calcNodeAccountFwd: offer --> ACCOUNT --> offer")); + if (bIssue // Allowed to issue. && saPrvDeliverReq // Previous wants to deliver && saCurIssueReq) // Current wants issue. @@ -3182,6 +3278,8 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin pnCur.uAccountID = uAccountID; pnCur.uCurrencyID = bCurrency ? uCurrencyID : pnPrv.uCurrencyID; pnCur.uIssuerID = bIssuer ? uIssuerID : uAccountID; + pnCur.saRevRedeem = STAmount(uCurrencyID); + pnCur.saRevIssue = STAmount(uCurrencyID); if (!bFirst) { @@ -3314,6 +3412,7 @@ PathState::PathState( saInReq = saSendMax; saOutReq = saSend; + // Push sending node. bValid = pushNode( STPathElement::typeAccount | STPathElement::typeRedeem @@ -3359,13 +3458,16 @@ Json::Value PathState::getJson() const { Json::Value jvNode(Json::objectValue); - Json::Value jvFlags(Json::objectValue); + Json::Value jvFlags(Json::arrayValue); + + if (pnNode.uFlags & STPathElement::typeAccount) + jvFlags.append("account"); if (pnNode.uFlags & STPathElement::typeRedeem) - jvFlags["redeem"] = 1; + jvFlags.append("redeem"); if (pnNode.uFlags & STPathElement::typeIssue) - jvFlags["issue"] = 1; + jvFlags.append("issue"); jvNode["flags"] = jvFlags; @@ -3378,6 +3480,24 @@ Json::Value PathState::getJson() const if (!!pnNode.uIssuerID) jvNode["issuer"] = NewcoinAddress::createHumanAccountID(pnNode.uIssuerID); + // if (!!pnNode.saRevRedeem) + jvNode["rev_redeem"] = pnNode.saRevRedeem.getFullText(); + + // if (!!pnNode.saRevIssue) + jvNode["rev_issue"] = pnNode.saRevIssue.getFullText(); + + // if (!!pnNode.saRevDeliver) + jvNode["rev_deliver"] = pnNode.saRevDeliver.getFullText(); + + // if (!!pnNode.saFwdRedeem) + jvNode["fwd_redeem"] = pnNode.saFwdRedeem.getFullText(); + + // if (!!pnNode.saFwdIssue) + jvNode["fwd_issue"] = pnNode.saFwdIssue.getFullText(); + + // if (!!pnNode.saFwdDeliver) + jvNode["fwd_deliver"] = pnNode.saFwdDeliver.getFullText(); + jvNodes.append(jvNode); } @@ -3761,9 +3881,19 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction } } - Log(lsINFO) << "doPayment: Delay transaction: No ripple paths could be satisfied."; + std::string strToken; + std::string strHuman; - return terBAD_RIPPLE; + if (transResultInfo(terResult, strToken, strHuman)) + { + Log(lsINFO) << str(boost::format("doPayment: %s: %s") % strToken % strHuman); + } + else + { + assert(false); + } + + return terResult; } TransactionEngineResult TransactionEngine::doWalletAdd(const SerializedTransaction& txn) diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index 3d54952d5a..35d9f23baa 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -104,7 +104,7 @@ typedef struct { uint16 uFlags; // --> From path. uint160 uAccountID; // --> Recieving/sending account. - uint160 uCurrencyID; // --> Currency to recieve. + uint160 uCurrencyID; // --> Accounts: receive and send, Offers: send. // --- For offer's next has currency out. uint160 uIssuerID; // --> Currency's issuer @@ -231,7 +231,7 @@ protected: STAmount rippleHolds(const uint160& uAccountID, const uint160& uCurrencyID, const uint160& uIssuerID); STAmount rippleTransfer(const uint160& uSenderID, const uint160& uReceiverID, const uint160& uIssuerID, const STAmount& saAmount); - void rippleCredit(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount); + void rippleCredit(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount, bool bCheckIssuer=true); STAmount rippleSend(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount); STAmount accountHolds(const uint160& uAccountID, const uint160& uCurrencyID, const uint160& uIssuerID);