|
|
|
|
@@ -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);
|
|
|
|
|
|
|
|
|
|
@@ -113,13 +107,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 +169,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 +201,8 @@ uint32 TransactionEngine::rippleQualityOut(const uint160& uToAccountID, const ui
|
|
|
|
|
if (sleRippleState)
|
|
|
|
|
{
|
|
|
|
|
uQualityOut = sleRippleState->getIFieldU32(uToAccountID < uFromAccountID ? sfLowQualityOut : sfHighQualityOut);
|
|
|
|
|
if (!uQualityOut)
|
|
|
|
|
uQualityOut = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
@@ -305,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());
|
|
|
|
|
@@ -2505,6 +2518,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,
|
|
|
|
|
@@ -2513,10 +2527,29 @@ 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 saCurReq=%s saPrvAct=%s saCurAct=%s")
|
|
|
|
|
% uQualityIn
|
|
|
|
|
% uQualityOut
|
|
|
|
|
% saPrvReq.getFullText()
|
|
|
|
|
% saCurReq.getFullText()
|
|
|
|
|
% saPrvAct.getFullText()
|
|
|
|
|
% saCurAct.getFullText());
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
@@ -2528,23 +2561,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;
|
|
|
|
|
@@ -2561,59 +2608,80 @@ 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;
|
|
|
|
|
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 = rippleQualityIn(uCurAccountID, uPrvAccountID, uCurrencyID);
|
|
|
|
|
uint32 uQualityOut = rippleQualityOut(uCurAccountID, uNxtAccountID, uCurrencyID);
|
|
|
|
|
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) : saZero;
|
|
|
|
|
STAmount saPrvLimit = bPrvAccount ? rippleLimit(uCurAccountID, uPrvAccountID, uCurrencyID) : saZero;
|
|
|
|
|
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;
|
|
|
|
|
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
|
|
|
|
|
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> uIndex=%d/%d saPrvRedeemReq=%s/%s saPrvIssueReq=%s/%s saCurWantedReq=%s/%s")
|
|
|
|
|
% uIndex
|
|
|
|
|
% uLast
|
|
|
|
|
% saPrvRedeemReq.getText()
|
|
|
|
|
% saPrvRedeemReq.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;
|
|
|
|
|
}
|
|
|
|
|
@@ -2624,6 +2692,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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2636,7 +2706,7 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// account --> ACCOUNT --> account
|
|
|
|
|
// ^|account --> ACCOUNT --> account
|
|
|
|
|
|
|
|
|
|
// redeem (part 1) -> redeem
|
|
|
|
|
if (bPrvRedeem
|
|
|
|
|
@@ -2645,6 +2715,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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2656,6 +2728,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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2666,17 +2740,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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2686,12 +2764,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
|
|
|
|
|
@@ -2725,6 +2814,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);
|
|
|
|
|
@@ -2740,6 +2830,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.
|
|
|
|
|
@@ -2772,6 +2863,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.
|
|
|
|
|
{
|
|
|
|
|
@@ -2821,14 +2914,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;
|
|
|
|
|
@@ -2843,6 +2936,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)
|
|
|
|
|
@@ -2860,26 +2963,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.
|
|
|
|
|
|
|
|
|
|
@@ -2891,11 +3017,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.
|
|
|
|
|
@@ -2936,12 +3063,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.
|
|
|
|
|
@@ -2962,13 +3090,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;
|
|
|
|
|
@@ -2978,6 +3107,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.
|
|
|
|
|
@@ -3005,6 +3135,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.
|
|
|
|
|
@@ -3134,6 +3266,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)
|
|
|
|
|
{
|
|
|
|
|
@@ -3144,6 +3278,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);
|
|
|
|
|
}
|
|
|
|
|
@@ -3187,11 +3355,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.";
|
|
|
|
|
|
|
|
|
|
@@ -3210,6 +3378,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,
|
|
|
|
|
@@ -3219,7 +3388,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();
|
|
|
|
|
@@ -3231,6 +3400,7 @@ PathState::PathState(
|
|
|
|
|
saInReq = saSendMax;
|
|
|
|
|
saOutReq = saSend;
|
|
|
|
|
|
|
|
|
|
// Push sending node.
|
|
|
|
|
bValid = pushNode(
|
|
|
|
|
STPathElement::typeAccount
|
|
|
|
|
| STPathElement::typeRedeem
|
|
|
|
|
@@ -3276,13 +3446,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;
|
|
|
|
|
|
|
|
|
|
@@ -3295,6 +3468,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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -3323,7 +3514,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
|
|
|
|
|
@@ -3334,28 +3525,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
|
|
|
|
|
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
|
|
|
|
|
bValid = bCurAccount
|
|
|
|
|
? calcNodeAccountFwd(uIndex, pspCur, bMultiQuality)
|
|
|
|
|
: calcNodeOfferFwd(uIndex, pspCur, bMultiQuality);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return bSuccess;
|
|
|
|
|
return bValid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Calculate the next increment of a path.
|
|
|
|
|
@@ -3372,9 +3563,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.
|
|
|
|
|
|
|
|
|
|
@@ -3591,6 +3787,7 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
|
|
|
|
|
// Direct path.
|
|
|
|
|
Log(lsINFO) << "doPayment: Build direct:";
|
|
|
|
|
vpsPaths.push_back(PathState::createPathState(
|
|
|
|
|
mLedger,
|
|
|
|
|
vpsPaths.size(),
|
|
|
|
|
mNodes,
|
|
|
|
|
STPath(),
|
|
|
|
|
@@ -3606,6 +3803,7 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
|
|
|
|
|
{
|
|
|
|
|
Log(lsINFO) << "doPayment: Build path:";
|
|
|
|
|
vpsPaths.push_back(PathState::createPathState(
|
|
|
|
|
mLedger,
|
|
|
|
|
vpsPaths.size(),
|
|
|
|
|
mNodes,
|
|
|
|
|
spPath,
|
|
|
|
|
@@ -3671,9 +3869,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)
|
|
|
|
|
|