mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-21 03:26:01 +00:00
Fixes for rippling through offers.
This commit is contained in:
@@ -287,11 +287,15 @@ TER RippleCalc::calcNodeDeliverRev(
|
|||||||
const STAmount& saTransferRate = pnCur.saTransferRate;
|
const STAmount& saTransferRate = pnCur.saTransferRate;
|
||||||
|
|
||||||
STAmount& saPrvDlvReq = pnPrv.saRevDeliver; // To be set.
|
STAmount& saPrvDlvReq = pnPrv.saRevDeliver; // To be set.
|
||||||
|
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.
|
||||||
|
|
||||||
saPrvDlvReq.zero(pnPrv.uCurrencyID, pnPrv.uIssuerID);
|
saPrvDlvReq.zero(pnPrv.uCurrencyID, pnPrv.uIssuerID);
|
||||||
saOutAct.zero(saOutReq);
|
saOutAct.zero(saOutReq);
|
||||||
|
|
||||||
@@ -472,14 +476,15 @@ 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
|
||||||
TER RippleCalc::calcNodeDeliverFwd(
|
TER RippleCalc::calcNodeDeliverFwd(
|
||||||
const unsigned int uNode, // 0 < uNode < uLast
|
const unsigned int uNode, // 0 < uNode < uLast
|
||||||
PathState::ref pspCur,
|
PathState::ref pspCur,
|
||||||
const bool bMultiQuality,
|
const bool bMultiQuality,
|
||||||
const uint160& uInAccountID, // --> Input owner's account.
|
const uint160& uInAccountID, // --> Input owner's account.
|
||||||
const STAmount& saInReq, // --> Amount to deliver.
|
const STAmount& saInReq, // --> Amount to deliver.
|
||||||
STAmount& saInAct, // <-- Amount delivered.
|
STAmount& saInAct, // <-- Amount delivered, this invokation.
|
||||||
STAmount& saInFees) // <-- Fees charged.
|
STAmount& saInFees) // <-- Fees charged, this invokation.
|
||||||
{
|
{
|
||||||
TER terResult = tesSUCCESS;
|
TER terResult = tesSUCCESS;
|
||||||
|
|
||||||
@@ -492,9 +497,9 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
const uint160& uCurIssuerID = pnCur.uIssuerID;
|
const uint160& uCurIssuerID = pnCur.uIssuerID;
|
||||||
const uint160& uPrvCurrencyID = pnPrv.uCurrencyID;
|
const uint160& uPrvCurrencyID = pnPrv.uCurrencyID;
|
||||||
const uint160& uPrvIssuerID = pnPrv.uIssuerID;
|
const uint160& uPrvIssuerID = pnPrv.uIssuerID;
|
||||||
const STAmount& saTransferRate = pnPrv.saTransferRate;
|
const STAmount& saInTransRate = pnPrv.saTransferRate;
|
||||||
|
|
||||||
STAmount& saCurDeliverAct = pnCur.saFwdDeliver;
|
STAmount& saCurDeliverAct = pnCur.saFwdDeliver; // Zeroed in reverse pass.
|
||||||
|
|
||||||
uint256& uDirectTip = pnCur.uDirectTip;
|
uint256& uDirectTip = pnCur.uDirectTip;
|
||||||
|
|
||||||
@@ -502,11 +507,11 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
|
|
||||||
saInAct.zero(saInReq);
|
saInAct.zero(saInReq);
|
||||||
saInFees.zero(saInReq);
|
saInFees.zero(saInReq);
|
||||||
saCurDeliverAct.zero(uCurCurrencyID, uCurIssuerID);
|
|
||||||
|
|
||||||
while (tesSUCCESS == terResult
|
while (tesSUCCESS == terResult
|
||||||
&& saInAct + saInFees != saInReq) // Did not deliver all funds.
|
&& saInAct + saInFees != saInReq) // Did not deliver all funds.
|
||||||
{
|
{
|
||||||
|
// Determine values for pass to adjust saInAct, saInFees, and saCurDeliverAct
|
||||||
terResult = calcNodeAdvance(uNode, pspCur, bMultiQuality, false); // If needed, advance to next funded offer.
|
terResult = calcNodeAdvance(uNode, pspCur, bMultiQuality, false); // If needed, advance to next funded offer.
|
||||||
|
|
||||||
if (tesSUCCESS == terResult)
|
if (tesSUCCESS == terResult)
|
||||||
@@ -522,28 +527,33 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
STAmount& saTakerPays = pnCur.saTakerPays;
|
STAmount& saTakerPays = pnCur.saTakerPays;
|
||||||
STAmount& saTakerGets = pnCur.saTakerGets;
|
STAmount& saTakerGets = pnCur.saTakerGets;
|
||||||
|
|
||||||
const STAmount saInFeeRate = !!uPrvCurrencyID
|
const STAmount saInFeeRate = !uPrvCurrencyID // XRP.
|
||||||
? uInAccountID == uPrvIssuerID || uOfrOwnerID == uPrvIssuerID // Issuer receiving or sending.
|
|| uInAccountID == uPrvIssuerID // Sender is issuer.
|
||||||
? saOne // No fee.
|
|| uOfrOwnerID == uPrvIssuerID // Reciever is issuer.
|
||||||
: saTransferRate // Transfer rate of issuer.
|
? saOne // No fee.
|
||||||
: saOne;
|
: saInTransRate; // Transfer rate of issuer.
|
||||||
|
|
||||||
//
|
// First calculate assuming no output fees: saInPassAct, saInPassFees, saOutPassAct
|
||||||
// First calculate assuming no output fees.
|
|
||||||
// XXX Make sure derived in does not exceed actual saTakerPays due to rounding.
|
|
||||||
|
|
||||||
STAmount saOutFunded = std::max(saOfferFunds, saTakerGets); // Offer maximum out - There are no out fees.
|
STAmount saOutFunded = std::min(saOfferFunds, saTakerGets); // Offer maximum out - If there are no out fees.
|
||||||
STAmount saInFunded = STAmount::multiply(saOutFunded, saOfrRate, saInReq); // Offer maximum in - Limited by by payout.
|
STAmount saInFunded = STAmount::multiply(saOutFunded, saOfrRate, saTakerPays); // Offer maximum in - Limited by by payout.
|
||||||
STAmount saInTotal = STAmount::multiply(saInFunded, saTransferRate); // Offer maximum in with fees.
|
STAmount saInTotal = STAmount::multiply(saInFunded, saInTransRate); // Offer maximum in with fees.
|
||||||
STAmount saInSum = std::min(saInTotal, saInReq-saInAct-saInFees); // In limited by saInReq.
|
STAmount saInSum = std::min(saInTotal, saInReq-saInAct-saInFees); // In limited by remaining.
|
||||||
STAmount saInPassAct = STAmount::divide(saInSum, saInFeeRate); // In without fees.
|
STAmount saInPassAct = STAmount::divide(saInSum, saInFeeRate); // In without fees.
|
||||||
STAmount saOutPassMax = STAmount::divide(saInPassAct, saOfrRate, saOutFunded); // Out.
|
STAmount saOutPassMax = STAmount::divide(saInPassAct, saOfrRate, saTakerGets); // Out limited by in remaining.
|
||||||
|
|
||||||
STAmount saInPassFees(saInReq.getCurrency(), saInReq.getIssuer());
|
STAmount saInPassFeesMax = saInSum-saInPassAct;
|
||||||
STAmount saOutPassAct(saOfferFunds.getCurrency(), saOfferFunds.getIssuer());
|
|
||||||
|
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverFwd: saOutFunded=%s saInFunded=%s saInTotal=%s saInSum=%s saInPassAct=%s saOutPassMax=%s")
|
STAmount saOutPassAct; // Will be determined by next node.
|
||||||
|
STAmount saInPassFees; // Will be determined by adjusted saInPassAct.
|
||||||
|
|
||||||
|
|
||||||
|
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverFwd: uNode=%d saOutFunded=%s saInReq=%s saInAct=%s saInFees=%s saInFunded=%s saInTotal=%s saInSum=%s saInPassAct=%s saOutPassMax=%s")
|
||||||
|
% uNode
|
||||||
% saOutFunded
|
% saOutFunded
|
||||||
|
% saInReq
|
||||||
|
% saInAct
|
||||||
|
% saInFees
|
||||||
% saInFunded
|
% saInFunded
|
||||||
% saInTotal
|
% saInTotal
|
||||||
% saInSum
|
% saInSum
|
||||||
@@ -557,13 +567,14 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
// Output fees: none as XRP or the destination account is the issuer.
|
// Output fees: none as XRP or the destination account is the issuer.
|
||||||
|
|
||||||
saOutPassAct = saOutPassMax;
|
saOutPassAct = saOutPassMax;
|
||||||
|
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")
|
||||||
% RippleAddress::createHumanAccountID(uOfrOwnerID)
|
% RippleAddress::createHumanAccountID(uOfrOwnerID)
|
||||||
% RippleAddress::createHumanAccountID(uNxtAccountID)
|
% RippleAddress::createHumanAccountID(uNxtAccountID)
|
||||||
% saOutPassAct.getFullText());
|
% saOutPassAct.getFullText());
|
||||||
|
|
||||||
// Debit offer owner, send XRP or non-XPR to next account.
|
// Output: Debit offer owner, send XRP or non-XPR to next account.
|
||||||
lesActive.accountSend(uOfrOwnerID, uNxtAccountID, saOutPassAct);
|
lesActive.accountSend(uOfrOwnerID, uNxtAccountID, saOutPassAct);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -571,43 +582,60 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
// ? --> OFFER --> offer
|
// ? --> OFFER --> offer
|
||||||
// Offer to offer means current order book's output currency and issuer match next order book's input current and
|
// Offer to offer means current order book's output currency and issuer match next order book's input current and
|
||||||
// issuer.
|
// issuer.
|
||||||
|
// Output fees: possible if issuer has fees and is not on either side.
|
||||||
STAmount saOutPassFees;
|
STAmount saOutPassFees;
|
||||||
|
|
||||||
|
// Output fees vary as the next nodes offer owners may vary.
|
||||||
|
// Therefore, immediately push through output for current offer.
|
||||||
terResult = RippleCalc::calcNodeDeliverFwd(
|
terResult = RippleCalc::calcNodeDeliverFwd(
|
||||||
uNode+1,
|
uNode+1,
|
||||||
pspCur,
|
pspCur,
|
||||||
bMultiQuality,
|
bMultiQuality,
|
||||||
uOfrOwnerID,
|
uOfrOwnerID, // --> Current holder.
|
||||||
saOutPassMax,
|
saOutPassMax, // --> Amount available.
|
||||||
saOutPassAct, // <-- Amount delivered.
|
saOutPassAct, // <-- Amount delivered.
|
||||||
saOutPassFees); // <-- Fees charged.
|
saOutPassFees); // <-- Fees charged.
|
||||||
|
|
||||||
if (tesSUCCESS != terResult)
|
if (tesSUCCESS != terResult)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Offer maximum in split into fees by next payout.
|
if (saOutPassAct == saOutPassMax)
|
||||||
saInPassAct = STAmount::multiply(saOutPassAct, saOfrRate);
|
{
|
||||||
saInPassFees = STAmount::multiply(saInFunded, saInFeeRate)-saInPassAct;
|
// No fees and entire output amount.
|
||||||
|
|
||||||
|
saInPassFees = saInPassFeesMax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Fraction of output amount.
|
||||||
|
// Output fees are paid by offer owner and not passed to previous.
|
||||||
|
saInPassAct = STAmount::multiply(saOutPassAct, saOfrRate, saInReq);
|
||||||
|
saInPassFees = std::min(saInPassFeesMax, STAmount::multiply(saInPassAct, saInFeeRate));
|
||||||
|
}
|
||||||
|
|
||||||
// Do outbound debiting.
|
// Do outbound debiting.
|
||||||
// Send to issuer/limbo total amount (no fees to issuer).
|
// Send to issuer/limbo total amount including fees (issuer gets fees).
|
||||||
lesActive.accountSend(uOfrOwnerID, !!uCurCurrencyID ? uCurIssuerID : ACCOUNT_XRP, saOutPassAct);
|
lesActive.accountSend(uOfrOwnerID, !!uCurCurrencyID ? uCurIssuerID : ACCOUNT_XRP, saOutPassAct+saOutPassFees);
|
||||||
|
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverFwd: ? --> OFFER --> offer: saOutPassAct=%s")
|
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverFwd: ? --> OFFER --> offer: saOutPassAct=%s saOutPassFees=%s")
|
||||||
% saOutPassAct);
|
% saOutPassAct
|
||||||
|
% saOutPassFees);
|
||||||
}
|
}
|
||||||
|
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverFwd: saTakerGets=%s saTakerPays=%s saInPassAct=%s saOutPassAct=%s")
|
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverFwd: uNode=%d saTakerGets=%s saTakerPays=%s saInPassAct=%s saInPassFees=%s saOutPassAct=%s saOutFunded=%s")
|
||||||
% saTakerGets.getFullText()
|
% uNode
|
||||||
% saTakerPays.getFullText()
|
% saTakerGets
|
||||||
% saInPassAct.getFullText()
|
% saTakerPays
|
||||||
% saOutPassAct.getFullText());
|
% saInPassAct
|
||||||
|
% saInPassFees
|
||||||
|
% saOutPassAct
|
||||||
|
% saOutFunded);
|
||||||
|
|
||||||
// Funds were spent.
|
// Funds were spent.
|
||||||
bFundsDirty = true;
|
bFundsDirty = true;
|
||||||
|
|
||||||
// Do inbound crediting.
|
// Do inbound crediting.
|
||||||
// Credit offer owner from in issuer/limbo (don't take transfer fees).
|
// Credit offer owner from in issuer/limbo (input transfer fees left with owner).
|
||||||
lesActive.accountSend(!!uPrvCurrencyID ? uInAccountID : ACCOUNT_XRP, uOfrOwnerID, saInPassAct);
|
lesActive.accountSend(!!uPrvCurrencyID ? uInAccountID : ACCOUNT_XRP, uOfrOwnerID, saInPassAct);
|
||||||
|
|
||||||
// Adjust offer
|
// Adjust offer
|
||||||
@@ -617,7 +645,7 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
|
|
||||||
lesActive.entryModify(sleOffer);
|
lesActive.entryModify(sleOffer);
|
||||||
|
|
||||||
if (saOutPassAct == saTakerGets)
|
if (saOutPassAct == saOutFunded)
|
||||||
{
|
{
|
||||||
// Offer became unfunded.
|
// Offer became unfunded.
|
||||||
pspCur->vUnfundedBecame.push_back(uOfferIndex);
|
pspCur->vUnfundedBecame.push_back(uOfferIndex);
|
||||||
@@ -632,6 +660,11 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cLog(lsDEBUG) << boost::str(boost::format("calcNodeDeliverFwd< uNode=%d saInAct=%s saInFees=%s")
|
||||||
|
% uNode
|
||||||
|
% saInAct
|
||||||
|
% saInFees);
|
||||||
|
|
||||||
return terResult;
|
return terResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,7 +729,7 @@ TER RippleCalc::calcNodeOfferFwd(
|
|||||||
pspCur,
|
pspCur,
|
||||||
bMultiQuality,
|
bMultiQuality,
|
||||||
pnPrv.uAccountID,
|
pnPrv.uAccountID,
|
||||||
pnPrv.saFwdDeliver,
|
pnPrv.saFwdDeliver, // Previous is sending this much.
|
||||||
saInAct,
|
saInAct,
|
||||||
saInFees);
|
saInFees);
|
||||||
|
|
||||||
@@ -1354,6 +1387,11 @@ TER RippleCalc::calcNodeAccountFwd(
|
|||||||
}
|
}
|
||||||
else if (bPrvAccount && !bNxtAccount)
|
else if (bPrvAccount && !bNxtAccount)
|
||||||
{
|
{
|
||||||
|
// Current account is issuer to next offer.
|
||||||
|
// Determine deliver to offer amount.
|
||||||
|
// Don't adjust outbound balances- keep funds with issuer as limbo.
|
||||||
|
// If issuer hold's an offer owners inbound IOUs, there is no fee and redeem/issue will transparently happen.
|
||||||
|
|
||||||
if (uNode)
|
if (uNode)
|
||||||
{
|
{
|
||||||
// Non-XRP, current node is the issuer.
|
// Non-XRP, current node is the issuer.
|
||||||
@@ -1444,7 +1482,7 @@ TER RippleCalc::calcNodeAccountFwd(
|
|||||||
saCurIssueAct.zero(saCurIssueReq);
|
saCurIssueAct.zero(saCurIssueReq);
|
||||||
|
|
||||||
// deliver -> redeem
|
// deliver -> redeem
|
||||||
if (saPrvDeliverReq) // Previous wants to deliver.
|
if (saPrvDeliverReq && saCurRedeemReq) // Previous wants to deliver and can current redeem.
|
||||||
{
|
{
|
||||||
// Rate : 1.0 : quality out
|
// Rate : 1.0 : quality out
|
||||||
calcNodeRipple(QUALITY_ONE, uQualityOut, saPrvDeliverReq, saCurRedeemReq, saPrvDeliverAct, saCurRedeemAct, uRateMax);
|
calcNodeRipple(QUALITY_ONE, uQualityOut, saPrvDeliverReq, saCurRedeemReq, saPrvDeliverAct, saCurRedeemAct, uRateMax);
|
||||||
|
|||||||
Reference in New Issue
Block a user