Add V2 implementation of payments:

Add a new algorithm for finding the liquidity in a payment path. There
is still a reverse and forward pass, but the forward pass starts at the
limiting step rather than the payment source. This insures the limiting
step is completely consumed rather than potentially leaving a 'dust'
amount in the forward pass.

Each step in a payment is either a book step, a direct step (account to
account step), or an xrp endpoint. Each step in the existing
implementation is a triple, where each element in the triple is either
an account of a book, for a total of eight step types.

Since accounts are considered in pairs, rather than triples, transfer
fees are handled differently. In V1 of payments, in the payment path
A -> gw ->B, if A redeems to gw, and gw issues to B, a transfer fee is
changed. In the new code, a transfer fee is changed even if A issues to
gw.
This commit is contained in:
seelabs
2015-11-15 13:20:26 -05:00
parent f3e93bbbeb
commit 122a5cdf89
44 changed files with 4654 additions and 223 deletions

View File

@@ -31,6 +31,14 @@
namespace ripple {
bool flowV2Switchover (NetClock::time_point const closeTime)
{
using namespace std::chrono_literals;
// Mon March 28, 2016 10:00:00am PST
static NetClock::time_point const soTime{512503200s};
return closeTime > soTime;
}
// VFALCO NOTE A copy of the other one for now
/** Maximum number of entries in a directory page
A change would be protocol-breaking.
@@ -1344,7 +1352,7 @@ rippleTransferFee (ReadView const& view,
// Send regardless of limits.
// --> saAmount: Amount/currency/issuer to deliver to reciever.
// <-- saActual: Amount actually cost. Sender pay's fees.
// <-- saActual: Amount actually cost. Sender pays fees.
static
TER
rippleSend (ApplyView& view,
@@ -1352,7 +1360,6 @@ rippleSend (ApplyView& view,
STAmount const& saAmount, STAmount& saActual, beast::Journal j)
{
auto const issuer = saAmount.getIssuer ();
TER terResult;
assert (!isXRP (uSenderID) && !isXRP (uReceiverID));
assert (uSenderID != uReceiverID);
@@ -1361,33 +1368,43 @@ rippleSend (ApplyView& view,
{
// Direct send: redeeming IOUs and/or sending own IOUs.
rippleCredit (view, uSenderID, uReceiverID, saAmount, false, j);
saActual = saAmount;
terResult = tesSUCCESS;
saActual = saAmount;
return tesSUCCESS;
}
// Sending 3rd party IOUs: transit.
// Calculate the amount to transfer accounting
// for any transfer fees:
if (!flowV2Switchover (view.info ().parentCloseTime))
{
STAmount const saTransitFee = rippleTransferFee (
view, uSenderID, uReceiverID, issuer, saAmount, j);
saActual = !saTransitFee ? saAmount : saAmount + saTransitFee;
saActual.setIssuer (issuer); // XXX Make sure this done in + above.
}
else
{
// Sending 3rd party IOUs: transit.
STAmount saTransitFee = rippleTransferFee (view,
uSenderID, uReceiverID, issuer, saAmount, j);
saActual = !saTransitFee ? saAmount : saAmount + saTransitFee;
saActual.setIssuer (issuer); // XXX Make sure this done in + above.
JLOG (j.debug) << "rippleSend> " <<
to_string (uSenderID) <<
" - > " << to_string (uReceiverID) <<
" : deliver=" << saAmount.getFullText () <<
" fee=" << saTransitFee.getFullText () <<
" cost=" << saActual.getFullText ();
terResult = rippleCredit (view, issuer, uReceiverID, saAmount, true, j);
if (tesSUCCESS == terResult)
terResult = rippleCredit (view, uSenderID, issuer, saActual, true, j);
auto const rate = rippleTransferRate (view, issuer);
if (QUALITY_ONE == rate)
saActual = saAmount;
else
saActual =
multiply (saAmount, amountFromRate (rate), saAmount.issue ());
}
JLOG (j.debug) << "rippleSend> " <<
to_string (uSenderID) <<
" - > " << to_string (uReceiverID) <<
" : deliver=" << saAmount.getFullText () <<
" cost=" << saActual.getFullText ();
TER terResult = rippleCredit (view, issuer, uReceiverID, saAmount, true, j);
if (tesSUCCESS == terResult)
terResult = rippleCredit (view, uSenderID, issuer, saActual, true, j);
return terResult;
}