mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Fixes for rippling through offers.
- More logging. - Respect multi-quality in reverse. - Per node respect delivery amounts for offers. - Pre-zero delivery amounts. - Sum delivery amounts. - Limit amount taken from offer by delivery amount. - More error checking for going past bounds. - Avoid == on float comparisons.
This commit is contained in:
@@ -1118,16 +1118,19 @@ TER RippleCalc::calcNodeAdvance(
|
|||||||
return terResult;
|
return terResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At the right most node of a list of consecutive offer nodes, given the amount requested to be delivered, push toward node 0 the
|
||||||
|
// amount requested for previous nodes to know how much to deliver.
|
||||||
|
//
|
||||||
// Between offer nodes, the fee charged may vary. Therefore, process one inbound offer at a time. Propagate the inbound offer's
|
// Between offer nodes, the fee charged may vary. Therefore, process one inbound offer at a time. Propagate the inbound offer's
|
||||||
// requirements to the previous node. The previous node adjusts the amount output and the amount spent on fees. Continue
|
// requirements to the previous node. The previous node adjusts the amount output and the amount spent on fees. Continue
|
||||||
// processing until the request is satisified as long as the rate does not increase past the initial rate.
|
// processing until the request is satisified as long as the rate does not increase past the initial rate.
|
||||||
TER RippleCalc::calcNodeDeliverRev(
|
TER RippleCalc::calcNodeDeliverRev(
|
||||||
const unsigned int uNode, // 0 < uNode < uLast
|
const unsigned int uNode, // 0 < uNode < uLast
|
||||||
PathState& psCur,
|
PathState& psCur,
|
||||||
const bool bMultiQuality,
|
const bool bMultiQuality, // True, if not constrained to do the same or better quality.
|
||||||
const uint160& uOutAccountID, // --> Output owner's account.
|
const uint160& uOutAccountID, // --> Output owner's account.
|
||||||
const STAmount& saOutReq, // --> Funds wanted.
|
const STAmount& saOutReq, // --> Funds requested to be delivered for an increment.
|
||||||
STAmount& saOutAct) // <-- Funds delivered.
|
STAmount& saOutAct) // <-- Funds actually delivered for an increment.
|
||||||
{
|
{
|
||||||
TER terResult = tesSUCCESS;
|
TER terResult = tesSUCCESS;
|
||||||
|
|
||||||
@@ -1136,22 +1139,25 @@ TER RippleCalc::calcNodeDeliverRev(
|
|||||||
|
|
||||||
const uint160& uCurIssuerID = pnCur.uIssuerID;
|
const uint160& uCurIssuerID = pnCur.uIssuerID;
|
||||||
const uint160& uPrvAccountID = pnPrv.uAccountID;
|
const uint160& uPrvAccountID = pnPrv.uAccountID;
|
||||||
const STAmount& saTransferRate = pnCur.saTransferRate;
|
const STAmount& saTransferRate = pnCur.saTransferRate; // Transfer rate of the TakerGets issuer.
|
||||||
|
|
||||||
STAmount& saPrvDlvReq = pnPrv.saRevDeliver; // To be set.
|
STAmount& saPrvDlvReq = pnPrv.saRevDeliver; // Accumulation of what the previous node must deliver.
|
||||||
STAmount& saCurDlvFwd = pnCur.saFwdDeliver;
|
|
||||||
|
|
||||||
uint256& uDirectTip = pnCur.uDirectTip;
|
uint256& uDirectTip = pnCur.uDirectTip;
|
||||||
|
|
||||||
uDirectTip = 0; // Restart book searching.
|
uDirectTip = 0; // Restart book searching.
|
||||||
|
|
||||||
saCurDlvFwd.zero(saOutReq); // For forward pass zero deliver.
|
// YYY Note this gets zeroed on each increment, ideally only on first increment, then it could be a limit on the forward pass.
|
||||||
|
|
||||||
saPrvDlvReq.zero(pnPrv.uCurrencyID, pnPrv.uIssuerID);
|
|
||||||
saOutAct.zero(saOutReq);
|
saOutAct.zero(saOutReq);
|
||||||
|
|
||||||
|
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: saOutAct=%s saOutReq=%s")
|
||||||
|
% saOutAct
|
||||||
|
% saOutReq);
|
||||||
|
|
||||||
|
assert(!!saOutReq);
|
||||||
|
|
||||||
int loopCount = 0;
|
int loopCount = 0;
|
||||||
while (saOutAct != saOutReq) // Did not deliver limit.
|
while (saOutAct < saOutReq) // Did not deliver as much as requested.
|
||||||
{
|
{
|
||||||
if (++loopCount > 40)
|
if (++loopCount > 40)
|
||||||
{
|
{
|
||||||
@@ -1178,17 +1184,23 @@ TER RippleCalc::calcNodeDeliverRev(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const STAmount saOutFeeRate = uOfrOwnerID == uCurIssuerID || uOutAccountID == uCurIssuerID // Issuer receiving or sending.
|
const STAmount saOutFeeRate = uOfrOwnerID == uCurIssuerID || uOutAccountID == uCurIssuerID // Issuer sending or receiving.
|
||||||
? saOne // No fee.
|
? saOne // No fee.
|
||||||
: saTransferRate; // Transfer rate of issuer.
|
: saTransferRate; // Transfer rate of issuer.
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: uOfrOwnerID=%s uOutAccountID=%s uCurIssuerID=%s saTransferRate=%s saOutFeeRate=%s")
|
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: uOfrOwnerID=%s uOutAccountID=%s uCurIssuerID=%s saTransferRate=%s saOutFeeRate=%s")
|
||||||
% RippleAddress::createHumanAccountID(uOfrOwnerID)
|
% RippleAddress::createHumanAccountID(uOfrOwnerID)
|
||||||
% RippleAddress::createHumanAccountID(uOutAccountID)
|
% RippleAddress::createHumanAccountID(uOutAccountID)
|
||||||
% RippleAddress::createHumanAccountID(uCurIssuerID)
|
% RippleAddress::createHumanAccountID(uCurIssuerID)
|
||||||
% saTransferRate.getFullText()
|
% saTransferRate
|
||||||
% saOutFeeRate.getFullText());
|
% saOutFeeRate);
|
||||||
|
|
||||||
if (!saRateMax)
|
if (bMultiQuality)
|
||||||
|
{
|
||||||
|
// In multi-quality mode, ignore rate.
|
||||||
|
|
||||||
|
nothing();
|
||||||
|
}
|
||||||
|
else if (!saRateMax)
|
||||||
{
|
{
|
||||||
// Set initial rate.
|
// Set initial rate.
|
||||||
saRateMax = saOutFeeRate;
|
saRateMax = saOutFeeRate;
|
||||||
@@ -1220,43 +1232,45 @@ TER RippleCalc::calcNodeDeliverRev(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Amount that goes to the taker.
|
// Amount that goes to the taker.
|
||||||
STAmount saOutPass = std::min(std::min(saOfferFunds, saTakerGets), saOutReq-saOutAct); // Offer maximum out - assuming no out fees.
|
STAmount saOutPassReq = std::min(std::min(saOfferFunds, saTakerGets), saOutReq-saOutAct); // Maximum out - assuming no out fees.
|
||||||
|
STAmount saOutPassAct = saOutPassReq;
|
||||||
|
|
||||||
// Amount charged to the offer owner.
|
// Amount charged to the offer owner.
|
||||||
// The fee goes to issuer. The fee is paid by offer owner and not passed as a cost to taker.
|
// The fee goes to issuer. The fee is paid by offer owner and not passed as a cost to taker.
|
||||||
// Round down: prefer liquidity rather than microscopic fees.
|
// Round down: prefer liquidity rather than microscopic fees.
|
||||||
STAmount saOutPlusFees = STAmount::mulRound(saOutPass, saOutFeeRate, false); // Offer out with fees.
|
STAmount saOutPlusFees = STAmount::mulRound(saOutPassAct, saOutFeeRate, false); // Offer out with fees.
|
||||||
|
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: saOutReq=%s saOutAct=%s saTakerGets=%s saOutPass=%s saOutPlusFees=%s saOfferFunds=%s")
|
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: saOutReq=%s saOutAct=%s saTakerGets=%s saOutPassAct=%s saOutPlusFees=%s saOfferFunds=%s")
|
||||||
% saOutReq
|
% saOutReq
|
||||||
% saOutAct
|
% saOutAct
|
||||||
% saTakerGets
|
% saTakerGets
|
||||||
% saOutPass
|
% saOutPassAct
|
||||||
% saOutPlusFees
|
% saOutPlusFees
|
||||||
% saOfferFunds);
|
% saOfferFunds);
|
||||||
|
|
||||||
if (saOutPlusFees > saOfferFunds)
|
if (saOutPlusFees > saOfferFunds)
|
||||||
{
|
{
|
||||||
// Offer owner can not cover all fees, compute saOutPass based on saOfferFunds.
|
// Offer owner can not cover all fees, compute saOutPassAct based on saOfferFunds.
|
||||||
|
|
||||||
saOutPlusFees = saOfferFunds;
|
saOutPlusFees = saOfferFunds;
|
||||||
// Round up: prefer liquidity rather than microscopic fees.
|
// Round up: prefer liquidity rather than microscopic fees. But, limit by requested.
|
||||||
saOutPass = STAmount::divRound(saOutPlusFees, saOutFeeRate, true);
|
saOutPassAct = std::min(saOutPassReq, STAmount::divRound(saOutPlusFees, saOutFeeRate, true));
|
||||||
|
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: Total exceeds fees: saOutPass=%s saOutPlusFees=%s saOfferFunds=%s")
|
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: Total exceeds fees: saOutPassAct=%s saOutPlusFees=%s saOfferFunds=%s")
|
||||||
% saOutPass
|
% saOutPassAct
|
||||||
% saOutPlusFees
|
% saOutPlusFees
|
||||||
% saOfferFunds);
|
% saOfferFunds);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute portion of input needed to cover actual output.
|
// Compute portion of input needed to cover actual output.
|
||||||
|
|
||||||
STAmount saInPassReq = STAmount::mulRound(saOutPass, saOfrRate, saTakerPays, true);
|
STAmount saInPassReq = STAmount::mulRound(saOutPassAct, saOfrRate, saTakerPays, true);
|
||||||
STAmount saInPassAct;
|
STAmount saInPassAct;
|
||||||
|
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: saInPassReq=%s saOfrRate=%s saOutPass=%s saOutPlusFees=%s")
|
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: saInPassReq=%s saOfrRate=%s saOutPassAct=%s saOutPlusFees=%s")
|
||||||
% saInPassReq
|
% saInPassReq
|
||||||
% saOfrRate
|
% saOfrRate
|
||||||
% saOutPass
|
% saOutPassAct
|
||||||
% saOutPlusFees);
|
% saOutPlusFees);
|
||||||
|
|
||||||
if (!saInPassReq)
|
if (!saInPassReq)
|
||||||
@@ -1280,12 +1294,12 @@ TER RippleCalc::calcNodeDeliverRev(
|
|||||||
saInPassAct = saInPassReq;
|
saInPassAct = saInPassReq;
|
||||||
|
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: account --> OFFER --> ? : saInPassAct=%s")
|
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: account --> OFFER --> ? : saInPassAct=%s")
|
||||||
% saPrvDlvReq);
|
% saInPassAct);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// offer --> OFFER --> ?
|
// offer --> OFFER --> ?
|
||||||
// Chain and compute the previous offer now.
|
// Compute in previous offer node how much could come in.
|
||||||
|
|
||||||
terResult = calcNodeDeliverRev(
|
terResult = calcNodeDeliverRev(
|
||||||
uNode-1,
|
uNode-1,
|
||||||
@@ -1302,17 +1316,20 @@ TER RippleCalc::calcNodeDeliverRev(
|
|||||||
if (tesSUCCESS != terResult)
|
if (tesSUCCESS != terResult)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (saInPassAct != saInPassReq)
|
if (saInPassAct < saInPassReq)
|
||||||
{
|
{
|
||||||
// Adjust output to conform to limited input.
|
// Adjust output to conform to limited input.
|
||||||
// XXX Verify it is impossible for these to be larger than available funds.
|
saOutPassAct = std::min(saOutPassReq, STAmount::divRound(saInPassAct, saOfrRate, saTakerGets, true));
|
||||||
saOutPass = STAmount::divRound(saInPassAct, saOfrRate, saTakerGets, !saTakerGets.isNative());
|
saOutPlusFees = std::min(saOfferFunds, STAmount::mulRound(saOutPassAct, saOutFeeRate, true));
|
||||||
saOutPlusFees = STAmount::mulRound(saOutPass, saOutFeeRate, true);
|
|
||||||
|
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: adjusted: saOutPass=%s saOutPlusFees=%s")
|
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: adjusted: saOutPassAct=%s saOutPlusFees=%s")
|
||||||
% saOutPass
|
% saOutPassAct
|
||||||
% saOutPlusFees);
|
% saOutPlusFees);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(saInPassAct == saInPassReq);
|
||||||
|
}
|
||||||
|
|
||||||
// Funds were spent.
|
// Funds were spent.
|
||||||
bFundsDirty = true;
|
bFundsDirty = true;
|
||||||
@@ -1321,13 +1338,13 @@ TER RippleCalc::calcNodeDeliverRev(
|
|||||||
// Sending could be complicated: could fund a previous offer not yet visited.
|
// Sending could be complicated: could fund a previous offer not yet visited.
|
||||||
// However, these deductions and adjustments are tenative.
|
// However, these deductions and adjustments are tenative.
|
||||||
// Must reset balances when going forward to perform actual transfers.
|
// Must reset balances when going forward to perform actual transfers.
|
||||||
terResult = lesActive.accountSend(uOfrOwnerID, uCurIssuerID, saOutPass);
|
terResult = lesActive.accountSend(uOfrOwnerID, uCurIssuerID, saOutPassAct);
|
||||||
|
|
||||||
if (tesSUCCESS != terResult)
|
if (tesSUCCESS != terResult)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Adjust offer
|
// Adjust offer
|
||||||
STAmount saTakerGetsNew = saTakerGets - saOutPass;
|
STAmount saTakerGetsNew = saTakerGets - saOutPassAct;
|
||||||
STAmount saTakerPaysNew = saTakerPays - saInPassAct;
|
STAmount saTakerPaysNew = saTakerPays - saInPassAct;
|
||||||
|
|
||||||
if (saTakerPaysNew.isNegative() || saTakerGetsNew.isNegative())
|
if (saTakerPaysNew.isNegative() || saTakerGetsNew.isNegative())
|
||||||
@@ -1346,18 +1363,28 @@ TER RippleCalc::calcNodeDeliverRev(
|
|||||||
|
|
||||||
lesActive.entryModify(sleOffer);
|
lesActive.entryModify(sleOffer);
|
||||||
|
|
||||||
if (saOutPass == saTakerGets)
|
if (saOutPassAct == saTakerGets)
|
||||||
{
|
{
|
||||||
// Offer became unfunded.
|
// Offer became unfunded.
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: offer became unfunded."));
|
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: offer became unfunded."));
|
||||||
|
|
||||||
bEntryAdvance = true; // XXX When don't we want to set advance?
|
bEntryAdvance = true; // XXX When don't we want to set advance?
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(saOutPassAct < saTakerGets);
|
||||||
|
}
|
||||||
|
|
||||||
saOutAct += saOutPass;
|
saOutAct += saOutPassAct;
|
||||||
saPrvDlvReq += saInPassAct;
|
saPrvDlvReq += saInPassAct; // Accumulate what is to be delivered from previous node.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tLog(saOutAct > saOutReq, lsWARNING)
|
||||||
|
<< boost::str(boost::format("calcNodeDeliverRev: TOO MUCH: saOutAct=%s saOutReq=%s")
|
||||||
|
% saOutAct
|
||||||
|
% saOutReq);
|
||||||
|
assert(saOutAct <= saOutReq);
|
||||||
|
|
||||||
// XXX Perhaps need to check if partial is okay to relax this?
|
// XXX Perhaps need to check if partial is okay to relax this?
|
||||||
if (tesSUCCESS == terResult && !saOutAct)
|
if (tesSUCCESS == terResult && !saOutAct)
|
||||||
terResult = tecPATH_DRY; // Unable to meet request, consider path dry.
|
terResult = tecPATH_DRY; // Unable to meet request, consider path dry.
|
||||||
@@ -1367,6 +1394,7 @@ TER RippleCalc::calcNodeDeliverRev(
|
|||||||
|
|
||||||
// For current offer, get input from deliver/limbo and output to next account or deliver for next offers.
|
// For current offer, get input from deliver/limbo and output to next account or deliver for next offers.
|
||||||
// <-- pnCur.saFwdDeliver: For calcNodeAccountFwd to know how much went through
|
// <-- pnCur.saFwdDeliver: For calcNodeAccountFwd to know how much went through
|
||||||
|
// --> pnCur.saRevDeliver: Do not exceed.
|
||||||
TER RippleCalc::calcNodeDeliverFwd(
|
TER RippleCalc::calcNodeDeliverFwd(
|
||||||
const unsigned int uNode, // 0 < uNode < uLast
|
const unsigned int uNode, // 0 < uNode < uLast
|
||||||
PathState& psCur,
|
PathState& psCur,
|
||||||
@@ -1389,6 +1417,7 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
const uint160& uPrvCurrencyID = pnPrv.uCurrencyID;
|
const uint160& uPrvCurrencyID = pnPrv.uCurrencyID;
|
||||||
const uint160& uPrvIssuerID = pnPrv.uIssuerID;
|
const uint160& uPrvIssuerID = pnPrv.uIssuerID;
|
||||||
const STAmount& saInTransRate = pnPrv.saTransferRate;
|
const STAmount& saInTransRate = pnPrv.saTransferRate;
|
||||||
|
const STAmount& saCurDeliverMax = pnCur.saRevDeliver; // Don't deliver more than wanted.
|
||||||
|
|
||||||
STAmount& saCurDeliverAct = pnCur.saFwdDeliver; // Zeroed in reverse pass.
|
STAmount& saCurDeliverAct = pnCur.saFwdDeliver; // Zeroed in reverse pass.
|
||||||
|
|
||||||
@@ -1400,8 +1429,9 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
saInFees.zero(saInReq);
|
saInFees.zero(saInReq);
|
||||||
|
|
||||||
int loopCount = 0;
|
int loopCount = 0;
|
||||||
|
// XXX Perhaps make sure do not exceed saCurDeliverMax as another way to stop.
|
||||||
while (tesSUCCESS == terResult
|
while (tesSUCCESS == terResult
|
||||||
&& saInAct + saInFees != saInReq) // Did not deliver all funds.
|
&& saInAct + saInFees < saInReq) // Did not spend all inbound deliver funds.
|
||||||
{
|
{
|
||||||
if (++loopCount > 40)
|
if (++loopCount > 40)
|
||||||
{
|
{
|
||||||
@@ -1442,12 +1472,13 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
|
|
||||||
// First calculate assuming no output fees: saInPassAct, saInPassFees, saOutPassAct
|
// First calculate assuming no output fees: saInPassAct, saInPassFees, saOutPassAct
|
||||||
|
|
||||||
STAmount saOutFunded = std::min(saOfferFunds, saTakerGets); // Offer maximum out - If there are no out fees.
|
STAmount saOutFunded = std::min(saOfferFunds, saTakerGets); // Offer maximum out - limited by funds with out fees.
|
||||||
STAmount saInFunded = STAmount::mulRound(saOutFunded, saOfrRate, saTakerPays, true); // Offer maximum in - Limited by by payout.
|
STAmount saOutPassFunded = std::min(saOutFunded, saCurDeliverMax-saCurDeliverAct); // Offer maximum out - limit by most to deliver.
|
||||||
|
STAmount saInFunded = STAmount::mulRound(saOutPassFunded, saOfrRate, saTakerPays, true);// Offer maximum in - Limited by by payout.
|
||||||
STAmount saInTotal = STAmount::mulRound(saInFunded, saInFeeRate, true); // Offer maximum in with fees.
|
STAmount saInTotal = STAmount::mulRound(saInFunded, saInFeeRate, true); // Offer maximum in with fees.
|
||||||
STAmount saInSum = std::min(saInTotal, saInReq-saInAct-saInFees); // In limited by remaining.
|
STAmount saInSum = std::min(saInTotal, saInReq-saInAct-saInFees); // In limited by remaining.
|
||||||
STAmount saInPassAct = STAmount::divRound(saInSum, saInFeeRate, true); // In without fees.
|
STAmount saInPassAct = STAmount::divRound(saInSum, saInFeeRate, true); // In without fees.
|
||||||
STAmount saOutPassMax = STAmount::divRound(saInPassAct, saOfrRate, saTakerGets, !saTakerGets.isNative()); // Out limited by in remaining.
|
STAmount saOutPassMax = std::min(saOutPassFunded, STAmount::divRound(saInPassAct, saOfrRate, saTakerGets, true)); // Out limited by in remaining.
|
||||||
|
|
||||||
STAmount saInPassFeesMax = saInSum-saInPassAct;
|
STAmount saInPassFeesMax = saInSum-saInPassAct;
|
||||||
|
|
||||||
@@ -1455,9 +1486,10 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
STAmount saInPassFees; // Will be determined by adjusted saInPassAct.
|
STAmount saInPassFees; // Will be determined by adjusted saInPassAct.
|
||||||
|
|
||||||
|
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverFwd: uNode=%d saOutFunded=%s saOfferFunds=%s saTakerGets=%s saInReq=%s saInAct=%s saInFees=%s saInFunded=%s saInTotal=%s saInSum=%s saInPassAct=%s saOutPassMax=%s")
|
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverFwd: uNode=%d saOutFunded=%s saOutPassFunded=%s saOfferFunds=%s saTakerGets=%s saInReq=%s saInAct=%s saInFees=%s saInFunded=%s saInTotal=%s saInSum=%s saInPassAct=%s saOutPassMax=%s")
|
||||||
% uNode
|
% uNode
|
||||||
% saOutFunded
|
% saOutFunded
|
||||||
|
% saOutPassFunded
|
||||||
% saOfferFunds
|
% saOfferFunds
|
||||||
% saTakerGets
|
% saTakerGets
|
||||||
% saInReq
|
% saInReq
|
||||||
@@ -1497,10 +1529,11 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
saOutPassAct = saOutPassMax;
|
saOutPassAct = saOutPassMax;
|
||||||
saInPassFees = saInPassFeesMax;
|
saInPassFees = saInPassFeesMax;
|
||||||
|
|
||||||
cLog(lsDEBUG) << boost::str(boost::format("calcNodeDeliverFwd: ? --> OFFER --> account: uOfrOwnerID=%s uNxtAccountID=%s saOutPassAct=%s")
|
cLog(lsDEBUG) << boost::str(boost::format("calcNodeDeliverFwd: ? --> OFFER --> account: uOfrOwnerID=%s uNxtAccountID=%s saOutPassAct=%s saOutFunded=%s")
|
||||||
% RippleAddress::createHumanAccountID(uOfrOwnerID)
|
% RippleAddress::createHumanAccountID(uOfrOwnerID)
|
||||||
% RippleAddress::createHumanAccountID(uNxtAccountID)
|
% RippleAddress::createHumanAccountID(uNxtAccountID)
|
||||||
% saOutPassAct.getFullText());
|
% saOutPassAct
|
||||||
|
% saOutFunded);
|
||||||
|
|
||||||
// Output: Debit offer owner, send XRP or non-XPR to next account.
|
// Output: Debit offer owner, send XRP or non-XPR to next account.
|
||||||
terResult = lesActive.accountSend(uOfrOwnerID, uNxtAccountID, saOutPassAct);
|
terResult = lesActive.accountSend(uOfrOwnerID, uNxtAccountID, saOutPassAct);
|
||||||
@@ -1540,6 +1573,9 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
{
|
{
|
||||||
// Fraction of output amount.
|
// Fraction of output amount.
|
||||||
// Output fees are paid by offer owner and not passed to previous.
|
// Output fees are paid by offer owner and not passed to previous.
|
||||||
|
|
||||||
|
assert(saOutPassAct < saOutPassMax);
|
||||||
|
|
||||||
saInPassAct = STAmount::mulRound(saOutPassAct, saOfrRate, saInReq, true);
|
saInPassAct = STAmount::mulRound(saOutPassAct, saOfrRate, saInReq, true);
|
||||||
saInPassFees = std::min(saInPassFeesMax, STAmount::mulRound(saInPassAct, saInFeeRate, true));
|
saInPassFees = std::min(saInPassFeesMax, STAmount::mulRound(saInPassAct, saInFeeRate, true));
|
||||||
}
|
}
|
||||||
@@ -1601,15 +1637,26 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
if (saOutPassAct == saOutFunded)
|
if (saOutPassAct == saOutFunded)
|
||||||
{
|
{
|
||||||
// Offer became unfunded.
|
// Offer became unfunded.
|
||||||
|
|
||||||
|
cLog(lsWARNING) << boost::str(boost::format("calcNodeDeliverFwd: unfunded: saOutPassAct=%s saOutFunded=%s")
|
||||||
|
% saOutPassAct % saOutFunded);
|
||||||
|
|
||||||
psCur.vUnfundedBecame.push_back(uOfferIndex);
|
psCur.vUnfundedBecame.push_back(uOfferIndex);
|
||||||
bEntryAdvance = true;
|
bEntryAdvance = true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tLog(saOutPassAct >= saOutFunded, lsWARNING) << boost::str(boost::format("calcNodeDeliverFwd: TOO MUCH: saOutPassAct=%s saOutFunded=%s")
|
||||||
|
% saOutPassAct % saOutFunded);
|
||||||
|
|
||||||
|
assert(saOutPassAct < saOutFunded);
|
||||||
|
}
|
||||||
|
|
||||||
saInAct += saInPassAct;
|
saInAct += saInPassAct;
|
||||||
saInFees += saInPassFees;
|
saInFees += saInPassFees;
|
||||||
|
|
||||||
// Adjust amount available to next node.
|
// Adjust amount available to next node.
|
||||||
saCurDeliverAct += saOutPassAct;
|
saCurDeliverAct = std::min(saCurDeliverMax, saCurDeliverAct+saOutPassAct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1637,17 +1684,52 @@ TER RippleCalc::calcNodeOfferRev(
|
|||||||
// Next is an account node, resolve current offer node's deliver.
|
// Next is an account node, resolve current offer node's deliver.
|
||||||
STAmount saDeliverAct;
|
STAmount saDeliverAct;
|
||||||
|
|
||||||
|
// For each offer node in the sequence clear saRevDeliver and the previous saFwdDeliver.
|
||||||
|
for (unsigned int uIndex = uNode; uIndex;)
|
||||||
|
{
|
||||||
|
PaymentNode& pnClrCur = psCur.vpnNodes[uIndex];
|
||||||
|
PaymentNode& pnClrPrv = psCur.vpnNodes[uIndex-1];
|
||||||
|
|
||||||
|
if (!pnClrCur.uAccountID)
|
||||||
|
{
|
||||||
|
// An offer.
|
||||||
|
|
||||||
|
// Reverse pass.
|
||||||
|
// Current entry is previously calculated.
|
||||||
|
// Clear prior entries which are derived.
|
||||||
|
pnClrPrv.saRevDeliver.zero(pnClrPrv.uCurrencyID, pnClrPrv.uIssuerID);
|
||||||
|
|
||||||
|
// Clear deliver entry to be added to in forward pass.
|
||||||
|
pnClrCur.saFwdDeliver.zero(pnClrCur.uCurrencyID, pnClrCur.uIssuerID);
|
||||||
|
|
||||||
|
--uIndex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// A non-offer.
|
||||||
|
|
||||||
|
uIndex = 0; // Done.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cLog(lsINFO) << boost::str(boost::format("calcNodeOfferRev: OFFER --> account: uNode=%d saRevDeliver=%s")
|
||||||
|
% uNode
|
||||||
|
% pnCur.saRevDeliver);
|
||||||
|
|
||||||
terResult = calcNodeDeliverRev(
|
terResult = calcNodeDeliverRev(
|
||||||
uNode,
|
uNode,
|
||||||
psCur,
|
psCur,
|
||||||
bMultiQuality,
|
bMultiQuality,
|
||||||
|
|
||||||
pnNxt.uAccountID,
|
pnNxt.uAccountID,
|
||||||
pnCur.saRevDeliver,
|
pnCur.saRevDeliver, // The next node wants the current node to deliver this much.
|
||||||
saDeliverAct);
|
saDeliverAct);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
cLog(lsINFO) << boost::str(boost::format("calcNodeOfferRev: OFFER --> offer: uNode=%d")
|
||||||
|
% uNode);
|
||||||
|
|
||||||
// Next is an offer. Deliver has already been resolved.
|
// Next is an offer. Deliver has already been resolved.
|
||||||
terResult = tesSUCCESS;
|
terResult = tesSUCCESS;
|
||||||
}
|
}
|
||||||
@@ -2096,6 +2178,12 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uNode, PathState& psCur, c
|
|||||||
// Must have processed something.
|
// Must have processed something.
|
||||||
terResult = tecPATH_DRY;
|
terResult = tecPATH_DRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cLog(lsDEBUG) << boost::str(boost::format("calcNodeAccountRev: saPrvDeliverAct=%s saPrvDeliverReq=%s saCurWantedAct=%s saCurWantedReq=%s")
|
||||||
|
% saPrvDeliverAct
|
||||||
|
% saPrvDeliverReq
|
||||||
|
% saCurWantedAct
|
||||||
|
% saCurWantedReq);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2118,11 +2206,11 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uNode, PathState& psCur, c
|
|||||||
calcNodeRipple(QUALITY_ONE, lesActive.rippleTransferRate(uCurAccountID), saPrvDeliverReq, saCurIssueReq, saPrvDeliverAct, saCurIssueAct, uRateMax);
|
calcNodeRipple(QUALITY_ONE, lesActive.rippleTransferRate(uCurAccountID), saPrvDeliverReq, saCurIssueReq, saPrvDeliverAct, saCurIssueAct, uRateMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
cLog(lsDEBUG) << boost::str(boost::format("calcNodeAccountRev: saCurRedeemReq=%s saCurIssueAct=%s saCurIssueReq=%s saPrvDeliverAct=%s")
|
cLog(lsDEBUG) << boost::str(boost::format("calcNodeAccountRev: saCurIssueAct=%s saCurRedeemReq=%s saPrvDeliverAct=%s saCurIssueReq=%s")
|
||||||
% saCurRedeemReq.getFullText()
|
% saCurRedeemAct
|
||||||
% saCurRedeemAct.getFullText()
|
% saCurRedeemReq
|
||||||
% saCurIssueReq.getFullText()
|
% saPrvDeliverAct
|
||||||
% saPrvDeliverAct.getFullText());
|
% saCurIssueReq);
|
||||||
|
|
||||||
if (!saPrvDeliverAct)
|
if (!saPrvDeliverAct)
|
||||||
{
|
{
|
||||||
@@ -2541,8 +2629,9 @@ TER RippleCalc::calcNodeRev(const unsigned int uNode, PathState& psCur, const bo
|
|||||||
|
|
||||||
saTransferRate = STAmount::saFromRate(lesActive.rippleTransferRate(uCurIssuerID));
|
saTransferRate = STAmount::saFromRate(lesActive.rippleTransferRate(uCurIssuerID));
|
||||||
|
|
||||||
cLog(lsDEBUG) << boost::str(boost::format("calcNodeRev> uNode=%d uIssuerID=%s saTransferRate=%s")
|
cLog(lsDEBUG) << boost::str(boost::format("calcNodeRev> uNode=%d bCurAccount=%d uIssuerID=%s saTransferRate=%s")
|
||||||
% uNode
|
% uNode
|
||||||
|
% bCurAccount
|
||||||
% RippleAddress::createHumanAccountID(uCurIssuerID)
|
% RippleAddress::createHumanAccountID(uCurIssuerID)
|
||||||
% saTransferRate.getFullText());
|
% saTransferRate.getFullText());
|
||||||
|
|
||||||
@@ -2779,12 +2868,20 @@ int iPass = 0;
|
|||||||
pspCur->saInAct = saMaxAmountAct; // Update to current amount processed.
|
pspCur->saInAct = saMaxAmountAct; // Update to current amount processed.
|
||||||
pspCur->saOutAct = saDstAmountAct;
|
pspCur->saOutAct = saDstAmountAct;
|
||||||
|
|
||||||
tLog(pspCur->saInReq.isPositive() && pspCur->saInAct >= pspCur->saInReq, lsWARNING) << boost::str(boost::format("rippleCalc: DONE: saInAct=%s saInReq=%s")
|
tLog(pspCur->saInReq.isPositive() && pspCur->saInAct >= pspCur->saInReq, lsWARNING)
|
||||||
% pspCur->saInAct
|
<< boost::str(boost::format("rippleCalc: DONE: saInAct=%s saInReq=%s")
|
||||||
% pspCur->saInReq);
|
% pspCur->saInAct
|
||||||
|
% pspCur->saInReq);
|
||||||
|
|
||||||
assert(pspCur->saInReq.isNegative() || pspCur->saInAct < pspCur->saInReq); // Error if done.
|
assert(pspCur->saInReq.isNegative() || pspCur->saInAct < pspCur->saInReq); // Error if done.
|
||||||
|
|
||||||
|
tLog(pspCur->saOutAct >= pspCur->saOutReq, lsWARNING)
|
||||||
|
<< boost::str(boost::format("rippleCalc: ALREADY DONE: saOutAct=%s saOutReq=%s")
|
||||||
|
% pspCur->saOutAct
|
||||||
|
% pspCur->saOutReq);
|
||||||
|
|
||||||
|
assert(pspCur->saOutAct < pspCur->saOutReq); // Error if done, output met.
|
||||||
|
|
||||||
rc.pathNext(pspCur, bMultiQuality, lesCheckpoint, lesActive); // Compute increment.
|
rc.pathNext(pspCur, bMultiQuality, lesCheckpoint, lesActive); // Compute increment.
|
||||||
cLog(lsDEBUG) << boost::str(boost::format("rippleCalc: AFTER: mIndex=%d uQuality=%d rate=%s")
|
cLog(lsDEBUG) << boost::str(boost::format("rippleCalc: AFTER: mIndex=%d uQuality=%d rate=%s")
|
||||||
% pspCur->mIndex
|
% pspCur->mIndex
|
||||||
@@ -2874,6 +2971,14 @@ int iPass = 0;
|
|||||||
|
|
||||||
terResult = tesSUCCESS;
|
terResult = tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
else if (saDstAmountAct > saDstAmountReq)
|
||||||
|
{
|
||||||
|
cLog(lsWARNING) << boost::str(boost::format("rippleCalc: TOO MUCH: saDstAmountAct=%s saDstAmountReq=%s")
|
||||||
|
% saDstAmountAct
|
||||||
|
% saDstAmountReq);
|
||||||
|
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
else if (saMaxAmountAct != saMaxAmountReq && iDry != vpsExpanded.size())
|
else if (saMaxAmountAct != saMaxAmountReq && iDry != vpsExpanded.size())
|
||||||
{
|
{
|
||||||
// Have not met requested amount or max send, try to do more. Prepare for next pass.
|
// Have not met requested amount or max send, try to do more. Prepare for next pass.
|
||||||
|
|||||||
Reference in New Issue
Block a user