mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
compiling
This commit is contained in:
@@ -233,19 +233,18 @@ EscrowCreate::doApply()
|
|||||||
// Check reserve and funds availability
|
// Check reserve and funds availability
|
||||||
if (isXRP(amount) && balance < reserve + STAmount(ctx_.tx[sfAmount]).xrp())
|
if (isXRP(amount) && balance < reserve + STAmount(ctx_.tx[sfAmount]).xrp())
|
||||||
return tecUNFUNDED;
|
return tecUNFUNDED;
|
||||||
else if (ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
|
else
|
||||||
{
|
{
|
||||||
sleLine = view.peek(keylet::line(account, issuer, currency));
|
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
|
||||||
// RH TODO: does doing a dry run here add any value? it should be done in
|
return tefINTERNAL;
|
||||||
// preclaim but there is no preclaim in escrow.
|
|
||||||
|
sleLine = ctx_.view().peek(keylet::line(account, amount.getIssuer(), amount.getCurrency()));
|
||||||
|
|
||||||
// perform the lock as a dry run first
|
// perform the lock as a dry run first
|
||||||
if (TER result = trustAdjustLockedBalance(ctx_.view(), sleLine, amount, true);
|
if (TER result = trustAdjustLockedBalance(ctx_.view(), sleLine, amount, true);
|
||||||
result != tesSUCCESS)
|
result != tesSUCCESS)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return tecINTERNAL; // should never happen
|
|
||||||
|
|
||||||
// Check destination account
|
// Check destination account
|
||||||
{
|
{
|
||||||
@@ -306,7 +305,7 @@ EscrowCreate::doApply()
|
|||||||
{
|
{
|
||||||
// do the lock-up for real now
|
// do the lock-up for real now
|
||||||
TER result =
|
TER result =
|
||||||
trustAdjustLockedBalance(ctx_.view(), sleLine, amount);
|
trustAdjustLockedBalance(ctx_.view(), sleLine, amount, true);
|
||||||
if (result != tesSUCCESS)
|
if (result != tesSUCCESS)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -619,6 +618,29 @@ EscrowCancel::doApply()
|
|||||||
}
|
}
|
||||||
|
|
||||||
AccountID const account = (*slep)[sfAccount];
|
AccountID const account = (*slep)[sfAccount];
|
||||||
|
auto const sle = ctx_.view().peek(keylet::account(account));
|
||||||
|
auto amount = slep->getFieldAmount(sfAmount);
|
||||||
|
|
||||||
|
std::shared_ptr<SLE> sleLine;
|
||||||
|
|
||||||
|
if (!isXRP(amount))
|
||||||
|
{
|
||||||
|
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
|
||||||
|
return tefINTERNAL;
|
||||||
|
|
||||||
|
sleLine =
|
||||||
|
ctx_.view().peek(
|
||||||
|
keylet::line(account, amount.getIssuer(), amount.getCurrency()));
|
||||||
|
|
||||||
|
// dry run before we make any changes to ledger
|
||||||
|
if (TER result = trustAdjustLockedBalance(
|
||||||
|
ctx_.view(),
|
||||||
|
sleLine,
|
||||||
|
-amount,
|
||||||
|
true);
|
||||||
|
result != tesSUCCESS)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove escrow from owner directory
|
// Remove escrow from owner directory
|
||||||
{
|
{
|
||||||
@@ -645,20 +667,17 @@ EscrowCancel::doApply()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const sle = ctx_.view().peek(keylet::account(account));
|
|
||||||
auto amount = slep->getFieldAmount(sfAmount);
|
|
||||||
|
|
||||||
// Transfer amount back to the owner (or unlock it in TL case)
|
// Transfer amount back to the owner (or unlock it in TL case)
|
||||||
if (isXRP(amount))
|
if (isXRP(amount))
|
||||||
(*sle)[sfBalance] = (*sle)[sfBalance] + (*slep)[sfAmount];
|
(*sle)[sfBalance] = (*sle)[sfBalance] + (*slep)[sfAmount];
|
||||||
else if (ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
|
else if (ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
|
||||||
{
|
{
|
||||||
// unlock previously locked tokens from source line
|
// unlock previously locked tokens from source line
|
||||||
auto line = view.peek(keylet::line(account, issuerAccID, currency));
|
|
||||||
TER result = trustAdjustLockedBalance(
|
TER result = trustAdjustLockedBalance(
|
||||||
ctx_.view(),
|
ctx_.view(),
|
||||||
line,
|
sleLine,
|
||||||
-amount);
|
-amount,
|
||||||
|
false);
|
||||||
if (result != tesSUCCESS)
|
if (result != tesSUCCESS)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,19 +156,21 @@ closeChannel(
|
|||||||
{
|
{
|
||||||
(*sle)[sfBalance] = (*sle)[sfBalance] + amount;
|
(*sle)[sfBalance] = (*sle)[sfBalance] + amount;
|
||||||
}
|
}
|
||||||
else if (view.rules().enabled(featurePaychanAndEscrowForTokens))
|
else
|
||||||
{
|
{
|
||||||
|
if (view.rules().enabled(featurePaychanAndEscrowForTokens))
|
||||||
|
return tefINTERNAL;
|
||||||
|
|
||||||
auto line = view.peek(keylet::line(src, amount.getIssuer(), amount.getCurrency()));
|
auto line = view.peek(keylet::line(src, amount.getIssuer(), amount.getCurrency()));
|
||||||
TER result =
|
TER result =
|
||||||
trustAdjustLockedBalance(
|
trustAdjustLockedBalance(
|
||||||
view,
|
view,
|
||||||
line,
|
line,
|
||||||
-amount);
|
-amount,
|
||||||
|
false);
|
||||||
if (result != tesSUCCESS)
|
if (result != tesSUCCESS)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return tefINTERNAL;
|
|
||||||
|
|
||||||
adjustOwnerCount(view, sle, -1, j);
|
adjustOwnerCount(view, sle, -1, j);
|
||||||
view.update(sle);
|
view.update(sle);
|
||||||
@@ -262,14 +264,15 @@ PayChanCreate::preclaim(PreclaimContext const& ctx)
|
|||||||
trustXferAllowed(
|
trustXferAllowed(
|
||||||
ctx.view,
|
ctx.view,
|
||||||
{account, dst},
|
{account, dst},
|
||||||
amount.issue);
|
amount.issue());
|
||||||
result != tesSUCCESS)
|
result != tesSUCCESS)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
// check if the amount can be locked
|
// check if the amount can be locked
|
||||||
auto sleLine = ctx.view.read(keylet::line(account, amount.issuer(), amount.currency()));
|
std::shared_ptr<SLE const> sleLine =
|
||||||
|
ctx.view.read(keylet::line(account, amount.getIssuer(), amount.getCurrency()));
|
||||||
if (TER result =
|
if (TER result =
|
||||||
trustAdjustLockedBalance(
|
trustAdjustLockedBalance<ReadView const, std::shared_ptr<SLE const>>(
|
||||||
ctx.view,
|
ctx.view,
|
||||||
sleLine,
|
sleLine,
|
||||||
amount,
|
amount,
|
||||||
@@ -363,7 +366,7 @@ PayChanCreate::doApply()
|
|||||||
return tefINTERNAL;
|
return tefINTERNAL;
|
||||||
|
|
||||||
auto sleLine =
|
auto sleLine =
|
||||||
view.peek(keylet::line(account, amount.getIssuer(), amount.getCurrency()));
|
ctx_.view().peek(keylet::line(account, amount.getIssuer(), amount.getCurrency()));
|
||||||
|
|
||||||
if (!sleLine)
|
if (!sleLine)
|
||||||
return tecUNFUNDED_PAYMENT;
|
return tecUNFUNDED_PAYMENT;
|
||||||
@@ -430,7 +433,6 @@ PayChanFund::preflight(PreflightContext const& ctx)
|
|||||||
return preflight2(ctx);
|
return preflight2(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// RH UPTO
|
|
||||||
TER
|
TER
|
||||||
PayChanFund::doApply()
|
PayChanFund::doApply()
|
||||||
{
|
{
|
||||||
@@ -438,11 +440,33 @@ PayChanFund::doApply()
|
|||||||
auto const slep = ctx_.view().peek(k);
|
auto const slep = ctx_.view().peek(k);
|
||||||
if (!slep)
|
if (!slep)
|
||||||
return tecNO_ENTRY;
|
return tecNO_ENTRY;
|
||||||
|
|
||||||
|
STAmount const amount {ctx_.tx[sfAmount]};
|
||||||
|
|
||||||
|
std::shared_ptr<SLE> sleLine; // if XRP or featurePaychanAndEscrowForTokens
|
||||||
|
// not enabled this remains null
|
||||||
|
|
||||||
|
// if this is a Fund operation on an IOU then perform a dry run here
|
||||||
|
if (!isXRP(amount) &&
|
||||||
|
ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
|
||||||
|
sleLine = ctx_.view().peek(
|
||||||
|
keylet::line(
|
||||||
|
(*slep)[sfAccount],
|
||||||
|
amount.getIssuer(),
|
||||||
|
amount.getCurrency()));
|
||||||
|
|
||||||
|
if (TER result =
|
||||||
|
trustAdjustLockedBalance(
|
||||||
|
ctx_.view(),
|
||||||
|
sleLine,
|
||||||
|
amount,
|
||||||
|
true);
|
||||||
|
result != tesSUCCESS)
|
||||||
|
return result;
|
||||||
|
|
||||||
AccountID const src = (*slep)[sfAccount];
|
AccountID const src = (*slep)[sfAccount];
|
||||||
auto const txAccount = ctx_.tx[sfAccount];
|
auto const txAccount = ctx_.tx[sfAccount];
|
||||||
auto const expiration = (*slep)[~sfExpiration];
|
auto const expiration = (*slep)[~sfExpiration];
|
||||||
|
|
||||||
{
|
{
|
||||||
auto const cancelAfter = (*slep)[~sfCancelAfter];
|
auto const cancelAfter = (*slep)[~sfCancelAfter];
|
||||||
auto const closeTime =
|
auto const closeTime =
|
||||||
@@ -490,7 +514,6 @@ PayChanFund::doApply()
|
|||||||
if (balance < reserve)
|
if (balance < reserve)
|
||||||
return tecINSUFFICIENT_RESERVE;
|
return tecINSUFFICIENT_RESERVE;
|
||||||
|
|
||||||
STAmount const amount {ctx_.tx[sfAmount]};
|
|
||||||
|
|
||||||
if (isXRP(amount))
|
if (isXRP(amount))
|
||||||
{
|
{
|
||||||
@@ -500,47 +523,21 @@ PayChanFund::doApply()
|
|||||||
(*sle)[sfBalance] = (*sle)[sfBalance] - amount;
|
(*sle)[sfBalance] = (*sle)[sfBalance] - amount;
|
||||||
ctx_.view().update(sle);
|
ctx_.view().update(sle);
|
||||||
}
|
}
|
||||||
else if (ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
|
|
||||||
{
|
|
||||||
// RH UPTO: add freeze checks for all featurePaychanAndEscrowForTokens applies on escrow and paychan
|
|
||||||
// find the user's trustline
|
|
||||||
auto const& account = src;
|
|
||||||
auto const currency = amount.getCurrency();
|
|
||||||
auto const issuer = amount.getIssuer();
|
|
||||||
|
|
||||||
auto& view = ctx_.view();
|
|
||||||
|
|
||||||
auto const chanAmount = slep->getFieldAmount(sfAmount);
|
|
||||||
|
|
||||||
if (chanAmount.getCurrency() != currency || chanAmount.getIssuer() != issuer)
|
|
||||||
return tecNO_AUTH;
|
|
||||||
|
|
||||||
auto sleLine = view.peek(keylet::line(account, issuer, currency));
|
|
||||||
if (!sleLine)
|
|
||||||
return tecUNFUNDED_PAYMENT;
|
|
||||||
|
|
||||||
bool high = account > issuer;
|
|
||||||
|
|
||||||
STAmount balance = (*sleLine)[sfBalance];
|
|
||||||
|
|
||||||
STAmount lockedBalance {sfLockedBalance, amount.issue()};
|
|
||||||
if (sleLine->isFieldPresent(sfLockedBalance))
|
|
||||||
lockedBalance = (*sleLine)[sfLockedBalance];
|
|
||||||
|
|
||||||
auto spendableBalance = balance - lockedBalance;
|
|
||||||
|
|
||||||
if (high)
|
|
||||||
spendableBalance = -spendableBalance;
|
|
||||||
|
|
||||||
if (amount > spendableBalance)
|
|
||||||
return tecUNFUNDED_PAYMENT;
|
|
||||||
|
|
||||||
lockedBalance += high ? -amount : amount;
|
|
||||||
sleLine->setFieldAmount(sfLockedBalance, lockedBalance);
|
|
||||||
view.update(sleLine);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
return tecINTERNAL;
|
{
|
||||||
|
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
|
||||||
|
return tefINTERNAL;
|
||||||
|
|
||||||
|
|
||||||
|
TER result =
|
||||||
|
trustAdjustLockedBalance(
|
||||||
|
ctx_.view(),
|
||||||
|
sleLine,
|
||||||
|
amount,
|
||||||
|
false);
|
||||||
|
if (result != tesSUCCESS)
|
||||||
|
return tefINTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
(*slep)[sfAmount] = (*slep)[sfAmount] + ctx_.tx[sfAmount];
|
(*slep)[sfAmount] = (*slep)[sfAmount] + ctx_.tx[sfAmount];
|
||||||
ctx_.view().update(slep);
|
ctx_.view().update(slep);
|
||||||
@@ -574,7 +571,7 @@ PayChanClaim::preflight(PreflightContext const& ctx)
|
|||||||
if (!isXRP(*amt) && !ctx.rules.enabled(featurePaychanAndEscrowForTokens))
|
if (!isXRP(*amt) && !ctx.rules.enabled(featurePaychanAndEscrowForTokens))
|
||||||
return temBAD_AMOUNT;
|
return temBAD_AMOUNT;
|
||||||
|
|
||||||
if (*amt)
|
if (*amt <= beast::zero)
|
||||||
return temBAD_AMOUNT;
|
return temBAD_AMOUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -682,6 +679,7 @@ PayChanClaim::doApply()
|
|||||||
// featureDepositAuth to remove the bug.
|
// featureDepositAuth to remove the bug.
|
||||||
bool const depositAuth{ctx_.view().rules().enabled(featureDepositAuth)};
|
bool const depositAuth{ctx_.view().rules().enabled(featureDepositAuth)};
|
||||||
if (!depositAuth &&
|
if (!depositAuth &&
|
||||||
|
// RH TODO: does this condition need to be changed for IOU paychans?
|
||||||
(txAccount == src && (sled->getFlags() & lsfDisallowXRP)))
|
(txAccount == src && (sled->getFlags() & lsfDisallowXRP)))
|
||||||
return tecNO_TARGET;
|
return tecNO_TARGET;
|
||||||
|
|
||||||
@@ -704,231 +702,26 @@ PayChanClaim::doApply()
|
|||||||
assert(reqDelta >= beast::zero);
|
assert(reqDelta >= beast::zero);
|
||||||
if (isXRP(reqDelta))
|
if (isXRP(reqDelta))
|
||||||
(*sled)[sfBalance] = (*sled)[sfBalance] + reqDelta;
|
(*sled)[sfBalance] = (*sled)[sfBalance] + reqDelta;
|
||||||
else if (ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
|
else
|
||||||
{
|
{
|
||||||
// There are three involved accounts and two trustlines (at the end)
|
// xfer locked tokens to satisfy claim
|
||||||
// Src - Account which created the paychan
|
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
|
||||||
// Dst - Account which will receive a payout in the event of success
|
|
||||||
// Issuer - Account which issued the IOU the escrow locks
|
|
||||||
|
|
||||||
auto const& amount = reqDelta;
|
|
||||||
auto issuerAccID = amount.getIssuer();
|
|
||||||
auto currency = amount.getCurrency();
|
|
||||||
|
|
||||||
Keylet klIssuer = keylet::account(issuerAccID);
|
|
||||||
|
|
||||||
auto& view = ctx_.view();
|
|
||||||
|
|
||||||
auto& srcAccID = src;
|
|
||||||
auto& dstAccID = dst;
|
|
||||||
|
|
||||||
bool dstLow = dstAccID < issuerAccID;
|
|
||||||
bool srcLow = srcAccID < issuerAccID;
|
|
||||||
|
|
||||||
auto sleSrcAcc = view.peek(keylet::account(srcAccID));
|
|
||||||
auto& sleDstAcc = sled;
|
|
||||||
|
|
||||||
auto& j = ctx_.journal;
|
|
||||||
|
|
||||||
if (!sleSrcAcc)
|
|
||||||
{
|
|
||||||
JLOG(j.warn())
|
|
||||||
<< "Src account not found in paychan claim";
|
|
||||||
return tecINTERNAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
STAmount dstBalanceDrops = sleDstAcc->getFieldAmount(sfBalance);
|
|
||||||
|
|
||||||
// check if the destination has a trustline already
|
|
||||||
Keylet klDstLine = keylet::line(dstAccID, issuerAccID, currency);
|
|
||||||
|
|
||||||
auto sleSrcLine = view.peek(keylet::line(srcAccID, issuerAccID, currency));
|
|
||||||
auto sleDstLine = view.peek(klDstLine);
|
|
||||||
|
|
||||||
// check the issuer exists
|
|
||||||
auto sleIssuer = view.peek(klIssuer);
|
|
||||||
if (!sleIssuer)
|
|
||||||
{
|
|
||||||
JLOG(j.warn())
|
|
||||||
<< "Cannot paychan claim for token from non-existent issuer: "
|
|
||||||
<< to_string(issuerAccID);
|
|
||||||
return tecNO_ISSUER;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check the trustline isn't frozen
|
|
||||||
if (isGlobalFrozen(view, issuerAccID))
|
|
||||||
{
|
|
||||||
JLOG(j.warn()) << "Cannot finish an escrow for frozen issuer";
|
|
||||||
return tecFROZEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check the source line exists
|
|
||||||
if (!sleSrcLine)
|
|
||||||
{
|
|
||||||
JLOG(j.error())
|
|
||||||
<< "Cannot claim a paychan where the source line does not exist: "
|
|
||||||
<< "src: " << to_string(srcAccID) << " "
|
|
||||||
<< "iss: " << to_string(issuerAccID) << " "
|
|
||||||
<< "cur: " << to_string(currency);
|
|
||||||
return tefINTERNAL;
|
return tefINTERNAL;
|
||||||
}
|
|
||||||
|
|
||||||
// check if rippling is allowed on the source line
|
auto sleSrcAcc = ctx_.view().peek(keylet::account(src));
|
||||||
{
|
TER result =
|
||||||
auto const flag {srcLow ? lsfLowNoRipple : lsfHighNoRipple};
|
trustXferLockedBalance(
|
||||||
bool tlNoRipple = sleSrcLine->getFieldU32(sfFlags) & flag;
|
ctx_.view(),
|
||||||
if (tlNoRipple)
|
txAccount,
|
||||||
{
|
sleSrcAcc,
|
||||||
JLOG(j.warn()) << "PayChan claim would violate noripple status on issuer.";
|
sled,
|
||||||
return tecPATH_DRY;
|
reqDelta,
|
||||||
}
|
ctx_.journal);
|
||||||
}
|
|
||||||
|
|
||||||
// dstLow XNOR srcLow tells us if we need to flip the balance amount
|
|
||||||
// on the destination line
|
|
||||||
bool flipDstAmt = !((dstLow && srcLow) || (!dstLow && !srcLow));
|
|
||||||
|
|
||||||
// compute transfer fee, if any
|
|
||||||
auto xferRate = transferRate(view, issuerAccID);
|
|
||||||
|
|
||||||
// the destination will sometimes get less depending on xfer rate
|
|
||||||
// with any difference in tokens burned
|
|
||||||
auto dstAmt =
|
|
||||||
xferRate == parityRate
|
|
||||||
? amount
|
|
||||||
: multiplyRound(amount, xferRate, amount.issue(), true);
|
|
||||||
|
|
||||||
// check if the dest line exists, and if it doesn't create it if we're allowed to
|
|
||||||
if (!sleDstLine)
|
|
||||||
{
|
|
||||||
// if a line doesn't already exist between issuer and destination then
|
|
||||||
// such a line can now be created but only if either the person who signed
|
|
||||||
// for this txn is the destination account or the source and dest are the same
|
|
||||||
if (srcAccID != dstAccID && account_ != dstAccID)
|
|
||||||
return tecNO_PERMISSION;
|
|
||||||
|
|
||||||
// create trustline
|
|
||||||
|
|
||||||
if (std::uint32_t const ownerCount = {sleDstAcc->at(sfOwnerCount)};
|
|
||||||
dstBalanceDrops < view.fees().accountReserve(ownerCount + 1))
|
|
||||||
{
|
|
||||||
JLOG(j.trace()) << "Dest Trust line does not exist. "
|
|
||||||
"Insufficent reserve to create line.";
|
|
||||||
return tecNO_LINE_INSUF_RESERVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
if (TER const ter = trustCreate(
|
|
||||||
view,
|
|
||||||
dstLow, // is dest low?
|
|
||||||
issuerAccID, // source
|
|
||||||
dstAccID, // destination
|
|
||||||
klDstLine.key, // ledger index
|
|
||||||
sleDstAcc, // Account to add to
|
|
||||||
false, // authorize account
|
|
||||||
(sleDstAcc->getFlags() & lsfDefaultRipple) == 0,
|
|
||||||
false, // freeze trust line
|
|
||||||
flipDstAmt ? -dstAmt : dstAmt, // initial balance
|
|
||||||
Issue(currency, account_), // limit of zero
|
|
||||||
0, // quality in
|
|
||||||
0, // quality out
|
|
||||||
j); // journal
|
|
||||||
!isTesSuccess(ter))
|
|
||||||
{
|
|
||||||
return ter;
|
|
||||||
}
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// trustline already exists
|
|
||||||
// check is it's frozen
|
|
||||||
if (dstAccID != issuerAccID &&
|
|
||||||
sleDstLine->isFlag(dstLow ? lsfLowFreeze : lsfHighFreeze))
|
|
||||||
{
|
|
||||||
JLOG(j.warn())
|
|
||||||
<< "Finishing an escrow for destination frozen trustline.";
|
|
||||||
return tecFROZEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
// increment dest balance
|
|
||||||
{
|
|
||||||
// if balance is higher than limit then only allow if dest is signer
|
|
||||||
STAmount dstLimit =
|
|
||||||
dstLow ? (*sleDstLine)[sfLowLimit] : (*sleDstLine)[sfHighLimit];
|
|
||||||
|
|
||||||
STAmount priorBalance =
|
|
||||||
dstLow ? (*sleDstLine)[sfBalance] : -((*sleDstLine)[sfBalance]);
|
|
||||||
|
|
||||||
STAmount finalBalance = priorBalance + (flipDstAmt ? -dstAmt : dstAmt);
|
|
||||||
|
|
||||||
if (finalBalance < priorBalance)
|
|
||||||
{
|
|
||||||
JLOG(j.warn())
|
|
||||||
<< "Escrow finish resulted in a lower final balance on dest line";
|
|
||||||
return tecINTERNAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (finalBalance > dstLimit && account_ != dstAccID)
|
|
||||||
{
|
|
||||||
JLOG(j.trace())
|
|
||||||
<< "Escrow finish would increase dest line above limit without permission";
|
|
||||||
return tecPATH_DRY;
|
|
||||||
}
|
|
||||||
|
|
||||||
sleDstLine->setFieldAmount(sfBalance, dstLow ? finalBalance : -finalBalance);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// decrement source balance
|
|
||||||
{
|
|
||||||
STAmount priorBalance =
|
|
||||||
srcLow ? (*sleSrcLine)[sfBalance] : -((*sleSrcLine)[sfBalance]);
|
|
||||||
|
|
||||||
STAmount finalBalance = priorBalance - amount;
|
|
||||||
if (finalBalance < beast::zero)
|
|
||||||
{
|
|
||||||
JLOG(j.warn())
|
|
||||||
<< "Escrow finish results in a negative balance on source line";
|
|
||||||
return tecINTERNAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sleSrcLine->isFieldPresent(sfLockedBalance))
|
|
||||||
{
|
|
||||||
JLOG(j.warn())
|
|
||||||
<< "Escrow finish could not find sfLockedBalance on source line";
|
|
||||||
return tecINTERNAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
STAmount priorLockedBalance =
|
|
||||||
srcLow ? (*sleSrcLine)[sfLockedBalance] : -((*sleSrcLine)[sfLockedBalance]);
|
|
||||||
|
|
||||||
STAmount finalLockedBalance = priorLockedBalance - amount;
|
|
||||||
if (finalLockedBalance < beast::zero)
|
|
||||||
{
|
|
||||||
JLOG(j.warn())
|
|
||||||
<< "Escrow finish results in a negative locked balance on source line";
|
|
||||||
return tecINTERNAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
sleSrcLine->setFieldAmount(sfBalance, srcLow ? finalBalance : -finalBalance);
|
|
||||||
|
|
||||||
if (finalLockedBalance == beast::zero)
|
|
||||||
sleSrcLine->makeFieldAbsent(sfLockedBalance);
|
|
||||||
else
|
|
||||||
sleSrcLine->setFieldAmount(sfLockedBalance, srcLow ? finalLockedBalance : -finalLockedBalance);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update source and dest lines to reflect balance mutation
|
|
||||||
view.update(sleSrcLine);
|
|
||||||
|
|
||||||
if (sleDstLine)
|
|
||||||
view.update(sleDstLine);
|
|
||||||
|
|
||||||
|
if (result != tesSUCCESS)
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return tecINTERNAL;
|
|
||||||
ctx_.view().update(sled);
|
ctx_.view().update(sled);
|
||||||
ctx_.view().update(slep);
|
ctx_.view().update(slep);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -299,6 +299,111 @@ trustDelete(
|
|||||||
AccountID const& uHighAccountID,
|
AccountID const& uHighAccountID,
|
||||||
beast::Journal j);
|
beast::Journal j);
|
||||||
|
|
||||||
|
bool isTrustDefault(
|
||||||
|
std::shared_ptr<SLE> const& acc,
|
||||||
|
std::shared_ptr<SLE> const& line);
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
trustXferAllowed(
|
||||||
|
ReadView const& view,
|
||||||
|
std::vector<AccountID> const& parties,
|
||||||
|
Issue const& issue);
|
||||||
|
|
||||||
|
template<class V, class S>
|
||||||
|
[[nodiscard]] TER
|
||||||
|
trustAdjustLockedBalance(
|
||||||
|
V& view,
|
||||||
|
S& sleLine,
|
||||||
|
STAmount const& deltaAmt,
|
||||||
|
bool dryRun)
|
||||||
|
{
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
(std::is_same<V, ReadView const>::value && std::is_same<S, std::shared_ptr<SLE const>>::value) ||
|
||||||
|
(std::is_same<V, ApplyView>::value && std::is_same<S, std::shared_ptr<SLE>>::value));
|
||||||
|
|
||||||
|
constexpr bool bReadView = std::is_same<V, ReadView const>::value;
|
||||||
|
|
||||||
|
// dry runs are explicit in code, but really the view type determines
|
||||||
|
// what occurs here, so this combination is invalid.
|
||||||
|
|
||||||
|
if (bReadView && !dryRun)
|
||||||
|
return tefINTERNAL;
|
||||||
|
|
||||||
|
auto const currency = deltaAmt.getCurrency();
|
||||||
|
auto const issuer = deltaAmt.getIssuer();
|
||||||
|
|
||||||
|
STAmount lowLimit = sleLine->getFieldAmount(sfLowLimit);
|
||||||
|
|
||||||
|
// the account which is modifying the LockedBalance is always
|
||||||
|
// the side that isn't the issuer, so if the low side is the
|
||||||
|
// issuer then the high side is the account.
|
||||||
|
bool high = lowLimit.getIssuer() == issuer;
|
||||||
|
|
||||||
|
std::vector<AccountID> parties
|
||||||
|
{high ? sleLine->getFieldAmount(sfHighLimit).getIssuer(): lowLimit.getIssuer()};
|
||||||
|
|
||||||
|
// check for freezes & auth
|
||||||
|
if (TER result =
|
||||||
|
trustXferAllowed(
|
||||||
|
view,
|
||||||
|
parties,
|
||||||
|
deltaAmt.issue());
|
||||||
|
result != tesSUCCESS)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// pull the TL balance from the account's perspective
|
||||||
|
STAmount balance =
|
||||||
|
high ? -(*sleLine)[sfBalance] : (*sleLine)[sfBalance];
|
||||||
|
|
||||||
|
// this would mean somehow the issuer is trying to lock balance
|
||||||
|
if (balance < beast::zero)
|
||||||
|
return tecINTERNAL;
|
||||||
|
|
||||||
|
// can't lock or unlock a zero balance
|
||||||
|
if (balance == beast::zero)
|
||||||
|
return tecUNFUNDED_PAYMENT;
|
||||||
|
|
||||||
|
STAmount lockedBalance {sfLockedBalance, deltaAmt.issue()};
|
||||||
|
if (sleLine->isFieldPresent(sfLockedBalance))
|
||||||
|
lockedBalance =
|
||||||
|
high ? -(*sleLine)[sfLockedBalance] : (*sleLine)[sfLockedBalance];
|
||||||
|
|
||||||
|
lockedBalance += deltaAmt;
|
||||||
|
|
||||||
|
if (lockedBalance > balance)
|
||||||
|
return tecUNFUNDED_PAYMENT;
|
||||||
|
|
||||||
|
if (lockedBalance < beast::zero)
|
||||||
|
return tecINTERNAL;
|
||||||
|
|
||||||
|
// we won't update any SLEs if it is a dry run
|
||||||
|
if (dryRun)
|
||||||
|
return tesSUCCESS;
|
||||||
|
|
||||||
|
if constexpr(std::is_same<V, ApplyView>::value && std::is_same<S, std::shared_ptr<SLE>>::value)
|
||||||
|
{
|
||||||
|
if (lockedBalance == beast::zero)
|
||||||
|
sleLine->makeFieldAbsent(sfLockedBalance);
|
||||||
|
else
|
||||||
|
sleLine->
|
||||||
|
setFieldAmount(sfLockedBalance, high ? -lockedBalance : lockedBalance);
|
||||||
|
|
||||||
|
view.update(sleLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tesSUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
trustXferLockedBalance(
|
||||||
|
ApplyView& view,
|
||||||
|
AccountID const& actingAccID, // the account whose tx is actioning xfer
|
||||||
|
std::shared_ptr<SLE> const& sleSrcAcc,
|
||||||
|
std::shared_ptr<SLE> const& sleDstAcc,
|
||||||
|
STAmount const& amount, // issuer, currency are in this field
|
||||||
|
beast::Journal const& j);
|
||||||
|
|
||||||
/** Delete an offer.
|
/** Delete an offer.
|
||||||
|
|
||||||
Requirements:
|
Requirements:
|
||||||
|
|||||||
@@ -913,19 +913,26 @@ trustDelete(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isTrustDefault(
|
bool isTrustDefault(
|
||||||
std::shared_ptr<SLE> acc,
|
std::shared_ptr<SLE> const& acc,
|
||||||
std::shared_ptr<SLE> line)
|
std::shared_ptr<SLE> const& line)
|
||||||
{
|
{
|
||||||
assert(acc && line);
|
assert(acc && line);
|
||||||
|
|
||||||
uint32_t tlFlags = line->getFieldU32(sfFlags);
|
uint32_t tlFlags = line->getFieldU32(sfFlags);
|
||||||
bool high =
|
|
||||||
acc == line->getFieldAmount(sfHighLimit).issuer();
|
AccountID highAccID = line->getFieldAmount(sfHighLimit).issue().account;
|
||||||
|
AccountID lowAccID = line->getFieldAmount(sfLowLimit ).issue().account;
|
||||||
|
|
||||||
|
AccountID accID = acc->getAccountID(sfAccount);
|
||||||
|
|
||||||
|
assert(accID == highAccID || accID == lowAccID);
|
||||||
|
|
||||||
|
bool high = accID == highAccID;
|
||||||
|
|
||||||
uint32_t acFlags = line->getFieldU32(sfFlags);
|
uint32_t acFlags = line->getFieldU32(sfFlags);
|
||||||
|
|
||||||
const bool fNoRipple {high ? lsfHighNoRipple : lsfLowNoRipple};
|
const auto fNoRipple {high ? lsfHighNoRipple : lsfLowNoRipple};
|
||||||
const bool fFreeze {high ? lsfHighFreeze : lsfLowFreeze};
|
const auto fFreeze {high ? lsfHighFreeze : lsfLowFreeze};
|
||||||
|
|
||||||
if (tlFlags & fFreeze)
|
if (tlFlags & fFreeze)
|
||||||
return false;
|
return false;
|
||||||
@@ -942,13 +949,13 @@ bool isTrustDefault(
|
|||||||
if (line->getFieldAmount(high ? sfHighLimit : sfLowLimit) != beast::zero)
|
if (line->getFieldAmount(high ? sfHighLimit : sfLowLimit) != beast::zero)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
STAmount qualityIn = line->getFieldAmount(high ? sfHighQualityIn : sfLowQualityIn);
|
uint32_t qualityIn = line->getFieldU32(high ? sfHighQualityIn : sfLowQualityIn);
|
||||||
STAmount qualityOut = line->getFieldAmount(high ? sfHighQualityOut : sfLowQualityOut);
|
uint32_t qualityOut = line->getFieldU32(high ? sfHighQualityOut : sfLowQualityOut);
|
||||||
|
|
||||||
if (qualityIn != beast::zero && qualityIn != 1000000000)
|
if (qualityIn && qualityIn != QUALITY_ONE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (qualityOut != beast::zero && qualityOut != 1000000000)
|
if (qualityOut && qualityOut != QUALITY_ONE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -961,15 +968,15 @@ bool isTrustDefault(
|
|||||||
// Part of featurePaychanAndEscrowForTokens, but can be callled without guard
|
// Part of featurePaychanAndEscrowForTokens, but can be callled without guard
|
||||||
TER
|
TER
|
||||||
trustXferAllowed(
|
trustXferAllowed(
|
||||||
ReadView& view,
|
ReadView const& view,
|
||||||
std::vector<AccountID const> const& parties,
|
std::vector<AccountID> const& parties,
|
||||||
Issue const& issue)
|
Issue const& issue)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (isFakeXRP(issue.currency))
|
if (isFakeXRP(issue.currency))
|
||||||
return tecNO_PERMISSION;
|
return tecNO_PERMISSION;
|
||||||
|
|
||||||
auto const sleIssuerAcc = view.peek(keylet::account(issue.account));
|
auto const sleIssuerAcc = view.read(keylet::account(issue.account));
|
||||||
|
|
||||||
bool lockedBalanceAllowed =
|
bool lockedBalanceAllowed =
|
||||||
view.rules().enabled(featurePaychanAndEscrowForTokens);
|
view.rules().enabled(featurePaychanAndEscrowForTokens);
|
||||||
@@ -1012,7 +1019,8 @@ trustXferAllowed(
|
|||||||
{
|
{
|
||||||
// these "strange" old lines, if they even exist anymore are
|
// these "strange" old lines, if they even exist anymore are
|
||||||
// always a bar to xfer
|
// always a bar to xfer
|
||||||
if (line->getFieldAccount(sfLowAccount) == line->getFieldAccount(sfHighAccount))
|
if (line->getFieldAmount(sfLowLimit).getIssuer() ==
|
||||||
|
line->getFieldAmount(sfHighLimit).getIssuer())
|
||||||
return tecINTERNAL;
|
return tecINTERNAL;
|
||||||
|
|
||||||
if (line->isFieldPresent(sfLockedBalance))
|
if (line->isFieldPresent(sfLockedBalance))
|
||||||
@@ -1023,8 +1031,8 @@ trustXferAllowed(
|
|||||||
STAmount lockedBalance = line->getFieldAmount(sfLockedBalance);
|
STAmount lockedBalance = line->getFieldAmount(sfLockedBalance);
|
||||||
STAmount balance = line->getFieldAmount(sfBalance);
|
STAmount balance = line->getFieldAmount(sfBalance);
|
||||||
|
|
||||||
if (lockedBalance.issuer() != balance.issuer() ||
|
if (lockedBalance.getIssuer() != balance.getIssuer() ||
|
||||||
lockedBalance.currency() != balance.currency())
|
lockedBalance.getCurrency() != balance.getCurrency())
|
||||||
return tecINTERNAL;
|
return tecINTERNAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1061,121 +1069,14 @@ trustXferAllowed(
|
|||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type juggling to allow dry runs of helper functions from preclaim
|
|
||||||
// context, without forcing the caller to recast or change their view.
|
|
||||||
// ApplyView is a subclass of ReadView so this logic works fine and
|
|
||||||
// allows a helper to be called explicitly and without confusion.
|
|
||||||
using ReadOrApplyView =
|
|
||||||
std::variant<
|
|
||||||
std::reference_wrapper<ReadView const>,
|
|
||||||
std::reference_wrapper<ApplyView>>;
|
|
||||||
|
|
||||||
inline ReadView const&
|
|
||||||
forceReadView(ReadOrApplyView& view)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
*(std::holds_alternative<ReadViewRef>(view)
|
|
||||||
? &(std::get<ReadViewRef>(view).get())
|
|
||||||
: std::reintrepret_cast<ReadView const*>(
|
|
||||||
&(std::get<ReadViewRef>(view).get())));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modify a locked trustline balance, creating one if none exists
|
|
||||||
// or removing one if no longer needed. deltaAmt is in absolute terms
|
|
||||||
// positive means increment locked balance and negative decrement.
|
|
||||||
TER
|
|
||||||
trustAdjustLockedBalance(
|
|
||||||
ReadOrApplyView view_,
|
|
||||||
std::shared_ptr<SLE>& sleLine,
|
|
||||||
STAmount const& deltaAmt,
|
|
||||||
bool dryRun = false /* don't actually update, just try the delta */)
|
|
||||||
{
|
|
||||||
bool bReadView = std::holds_alternative<ReadViewRef>(view_);
|
|
||||||
|
|
||||||
// dry runs are explicit in code, but really the view type determines
|
|
||||||
// what occurs here, so this combination is invalid.
|
|
||||||
if (bReadView && !dryRun)
|
|
||||||
return tefINTERNAL;
|
|
||||||
|
|
||||||
ReadView const& view = forceReadView(view_);
|
|
||||||
|
|
||||||
if (!view.rules.enabled(featurePaychanAndEscrowForTokens))
|
|
||||||
return tefINTERNAL;
|
|
||||||
|
|
||||||
if (!sleLine)
|
|
||||||
return tecUNFUNDED_PAYMENT;
|
|
||||||
|
|
||||||
auto const currency = deltaAmt.getCurrency();
|
|
||||||
auto const issuer = deltaAmt.getIssuer();
|
|
||||||
|
|
||||||
STAmount lowLimit = sleLine->getFieldAmount(sfLowLimit);
|
|
||||||
|
|
||||||
// the account which is modifying the LockedBalance is always
|
|
||||||
// the side that isn't the issuer, so if the low side is the
|
|
||||||
// issuer then the high side is the account.
|
|
||||||
bool high = lowLimit.issuer() == issuer;
|
|
||||||
|
|
||||||
std::vector<AccountID> parties
|
|
||||||
{high ? sleLine->getFieldAmount(sfHighLimit).issuer(): lowLimit.issuer()};
|
|
||||||
|
|
||||||
// check for freezes & auth
|
|
||||||
if (TER result =
|
|
||||||
trustXferAllowed(
|
|
||||||
view,
|
|
||||||
parties,
|
|
||||||
deltaAmt.issue())
|
|
||||||
result != tesSUCCESS)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// pull the TL balance from the account's perspective
|
|
||||||
STAmount balance =
|
|
||||||
high ? -(*sleLine)[sfBalance] : (*sleLine)[sfBalance];
|
|
||||||
|
|
||||||
// this would mean somehow the issuer is trying to lock balance
|
|
||||||
if (balance < beast::zero)
|
|
||||||
return tecINTERNAL;
|
|
||||||
|
|
||||||
// can't lock or unlock a zero balance
|
|
||||||
if (balance == beast::zero)
|
|
||||||
return tecUNFUNDED_PAYMENT;
|
|
||||||
|
|
||||||
STAmount lockedBalance {sfLockedBalance, deltaAmt.issue()};
|
|
||||||
if (sleLine->isFieldPresent(sfLockedBalance))
|
|
||||||
lockedBalance =
|
|
||||||
high ? -(*sleLine)[sfLockedBalance] : (*sleLine)[sfLockedBalance];
|
|
||||||
|
|
||||||
lockedBalance += deltaAmt;
|
|
||||||
|
|
||||||
if (lockedBalance > balance
|
|
||||||
return tecUNFUNDED_PAYMENT;
|
|
||||||
|
|
||||||
if (lockedBalance < beast::zero)
|
|
||||||
return tecINTERNAL;
|
|
||||||
|
|
||||||
// we won't update any SLEs if it is a dry run
|
|
||||||
if (dryRun)
|
|
||||||
return tesSUCCESS;
|
|
||||||
|
|
||||||
if (lockedBalance == beast::zero)
|
|
||||||
sleLine->makeFieldAbsent(sfLockedBalance);
|
|
||||||
else
|
|
||||||
sleLine->setFieldAmount(sfLockedBalance, high ? -lockedBalance : lockedBalance);
|
|
||||||
|
|
||||||
// dryRun must be true if we have a ReadView in the variant
|
|
||||||
// therefore this is safe to execute
|
|
||||||
std::get<std::reference_wrapper<ApplyView>>(view_).get().update(sleLine);
|
|
||||||
|
|
||||||
return tesSUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
TER
|
TER
|
||||||
trustXferLockedBalance(
|
trustXferLockedBalance(
|
||||||
ApplyView& view,
|
ApplyView& view,
|
||||||
AccountID const& actingAccID, // the account whose tx is actioning xfer
|
AccountID const& actingAccID, // the account whose tx is actioning xfer
|
||||||
std::shared_ptr<SLE>& sleSrcAcc,
|
std::shared_ptr<SLE> const& sleSrcAcc,
|
||||||
std::shared_ptr<SLE>& sleDstAcc,
|
std::shared_ptr<SLE> const& sleDstAcc,
|
||||||
STAmount const& amount, // issuer, currency are in this field
|
STAmount const& amount, // issuer, currency are in this field
|
||||||
Journal& j)
|
beast::Journal const& j)
|
||||||
{
|
{
|
||||||
if (!view.rules().enabled(featurePaychanAndEscrowForTokens))
|
if (!view.rules().enabled(featurePaychanAndEscrowForTokens))
|
||||||
return tefINTERNAL;
|
return tefINTERNAL;
|
||||||
@@ -1196,11 +1097,11 @@ trustXferLockedBalance(
|
|||||||
|
|
||||||
auto issuerAccID = amount.getIssuer();
|
auto issuerAccID = amount.getIssuer();
|
||||||
auto currency = amount.getCurrency();
|
auto currency = amount.getCurrency();
|
||||||
auto srcAccID = sleSrcAcc->getFieldAccount(sfAccount);
|
auto srcAccID = sleSrcAcc->getAccountID(sfAccount);
|
||||||
auto dstAccID = sleDstAcc->getFieldAccount(sfAccount);
|
auto dstAccID = sleDstAcc->getAccountID(sfAccount);
|
||||||
|
|
||||||
bool srcHigh = srcAccID > issuerAccID;
|
bool srcHigh = srcAccID > issuerAccID;
|
||||||
bool dsthigh = dstAccID > issuerAccID;
|
bool dstHigh = dstAccID > issuerAccID;
|
||||||
|
|
||||||
// check for freezing, auth, no ripple and TL sanity
|
// check for freezing, auth, no ripple and TL sanity
|
||||||
if (TER result =
|
if (TER result =
|
||||||
@@ -1234,7 +1135,7 @@ trustXferLockedBalance(
|
|||||||
srcHigh ? -((*sleSrcLine)[sfBalance]) : (*sleSrcLine)[sfBalance];
|
srcHigh ? -((*sleSrcLine)[sfBalance]) : (*sleSrcLine)[sfBalance];
|
||||||
|
|
||||||
// ensure the currency/issuer in the locked balance matches the xfer amount
|
// ensure the currency/issuer in the locked balance matches the xfer amount
|
||||||
if (priorBalance.issuer() != issuerAccID || priorBalance.currency() != currency)
|
if (priorBalance.getIssuer() != issuerAccID || priorBalance.getCurrency() != currency)
|
||||||
return tecNO_PERMISSION;
|
return tecNO_PERMISSION;
|
||||||
|
|
||||||
STAmount finalBalance = priorBalance - amount;
|
STAmount finalBalance = priorBalance - amount;
|
||||||
@@ -1276,7 +1177,8 @@ trustXferLockedBalance(
|
|||||||
: multiplyRound(amount, xferRate, amount.issue(), true);
|
: multiplyRound(amount, xferRate, amount.issue(), true);
|
||||||
|
|
||||||
// check for a destination line
|
// check for a destination line
|
||||||
auto sleDstLine = view.peek(keylet::line(dstAccID, issuerAccID, currency));
|
Keylet klDstLine = keylet::line(dstAccID, issuerAccID, currency);
|
||||||
|
auto sleDstLine = view.peek(klDstLine);
|
||||||
|
|
||||||
if (!sleDstLine)
|
if (!sleDstLine)
|
||||||
{
|
{
|
||||||
@@ -1296,7 +1198,7 @@ trustXferLockedBalance(
|
|||||||
// clang-format off
|
// clang-format off
|
||||||
if (TER const ter = trustCreate(
|
if (TER const ter = trustCreate(
|
||||||
view,
|
view,
|
||||||
dstLow, // is dest low?
|
!dstHigh, // is dest low?
|
||||||
issuerAccID, // source
|
issuerAccID, // source
|
||||||
dstAccID, // destination
|
dstAccID, // destination
|
||||||
klDstLine.key, // ledger index
|
klDstLine.key, // ledger index
|
||||||
@@ -1305,7 +1207,7 @@ trustXferLockedBalance(
|
|||||||
(sleDstAcc->getFlags() & lsfDefaultRipple) == 0,
|
(sleDstAcc->getFlags() & lsfDefaultRipple) == 0,
|
||||||
false, // freeze trust line
|
false, // freeze trust line
|
||||||
flipDstAmt ? -dstAmt : dstAmt, // initial balance
|
flipDstAmt ? -dstAmt : dstAmt, // initial balance
|
||||||
Issue(currency, account_), // limit of zero
|
Issue(currency, dstAccID), // limit of zero
|
||||||
0, // quality in
|
0, // quality in
|
||||||
0, // quality out
|
0, // quality out
|
||||||
j); // journal
|
j); // journal
|
||||||
@@ -1343,19 +1245,19 @@ trustXferLockedBalance(
|
|||||||
return tecPATH_DRY;
|
return tecPATH_DRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
sleDstLine->setFieldAmount(sfBalance, dstLow ? finalBalance : -finalBalance);
|
sleDstLine->setFieldAmount(sfBalance, dstHigh ? -finalBalance : finalBalance);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if source line ended up in default state and adjust owner count if it did
|
// check if source line ended up in default state and adjust owner count if it did
|
||||||
if (isTrustDefault(sleSrc, sleSrcLine))
|
if (isTrustDefault(sleSrcAcc, sleSrcLine))
|
||||||
{
|
{
|
||||||
uint32_t flags = sleSrcLine->getFieldU32(sfFlags);
|
uint32_t flags = sleSrcLine->getFieldU32(sfFlags);
|
||||||
const bool fReserve { srcHigh ? lsfHighReserve : lsfLowReserve };
|
uint32_t fReserve { srcHigh ? lsfHighReserve : lsfLowReserve };
|
||||||
if (flags & fReserve)
|
if (flags & fReserve)
|
||||||
{
|
{
|
||||||
sleSrcLine->setFieldU32(sfFlags, flags & ~fReserve);
|
sleSrcLine->setFieldU32(sfFlags, flags & ~fReserve);
|
||||||
adjustOwnerCount(view, sleSrc, -1, j);
|
adjustOwnerCount(view, sleSrcAcc, -1, j);
|
||||||
view.update(sleSrc);
|
view.update(sleSrcAcc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user