XRPLF review of XLS34 (#69)

* add amendment guard for sfTransferRate

* make `sfTransferRate` optional

* split tests into existing / xls34

* make variables `const`

* clang-format

* chage error code

* guard optional `sfTransferRate`

* rename tests

* Guard Optional sfTransferRate

* clang-format

* fixup tests
This commit is contained in:
Denis Angell
2023-07-17 12:12:36 +02:00
committed by GitHub
parent 5aec64c84d
commit c36683a825
8 changed files with 688 additions and 1556 deletions

View File

@@ -218,7 +218,7 @@ EscrowCreate::doApply()
auto const balance = STAmount((*sle)[sfBalance]).xrp();
auto const reserve =
ctx_.view().fees().accountReserve((*sle)[sfOwnerCount] + 1);
bool isIssuer = amount.getIssuer() == account;
bool const isIssuer = amount.getIssuer() == account;
if (balance < reserve)
return tecINSUFFICIENT_RESERVE;
@@ -237,7 +237,7 @@ EscrowCreate::doApply()
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
return temDISABLED;
TER result = trustTransferAllowed(
TER const result = trustTransferAllowed(
ctx_.view(),
{account, ctx_.tx[sfDestination]},
amount.issue(),
@@ -263,7 +263,7 @@ EscrowCreate::doApply()
return tecNO_LINE;
{
TER result = trustAdjustLockedBalance(
TER const result = trustAdjustLockedBalance(
ctx_.view(), sleLine, amount, 1, ctx_.journal, DryRun);
JLOG(ctx_.journal.trace())
@@ -296,13 +296,11 @@ EscrowCreate::doApply()
// Create escrow in ledger. Note that we we use the value from the
// sequence or ticket. For more explanation see comments in SeqProxy.h.
auto xferRate = transferRate(view(), amount.getIssuer());
Keylet const escrowKeylet =
keylet::escrow(account, seqID(ctx_));
auto const slep = std::make_shared<SLE>(escrowKeylet);
(*slep)[sfAmount] = ctx_.tx[sfAmount];
(*slep)[sfAccount] = account;
(*slep)[sfTransferRate] = xferRate.value;
(*slep)[~sfCondition] = ctx_.tx[~sfCondition];
(*slep)[~sfSourceTag] = ctx_.tx[~sfSourceTag];
(*slep)[sfDestination] = ctx_.tx[sfDestination];
@@ -310,6 +308,12 @@ EscrowCreate::doApply()
(*slep)[~sfFinishAfter] = ctx_.tx[~sfFinishAfter];
(*slep)[~sfDestinationTag] = ctx_.tx[~sfDestinationTag];
if (ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
{
auto const xferRate = transferRate(view(), amount.getIssuer());
(*slep)[~sfTransferRate] = xferRate.value;
}
ctx_.view().insert(slep);
// Add escrow to sender's owner directory
@@ -346,7 +350,7 @@ EscrowCreate::doApply()
return tecNO_LINE;
// do the lock-up for real now
TER result = trustAdjustLockedBalance(
TER const result = trustAdjustLockedBalance(
ctx_.view(), sleLine, amount, 1, ctx_.journal, WetRun);
JLOG(ctx_.journal.trace())
@@ -469,7 +473,7 @@ EscrowFinish::doApply()
AccountID const account = (*slep)[sfAccount];
auto const sle = ctx_.view().peek(keylet::account(account));
auto amount = slep->getFieldAmount(sfAmount);
auto const amount = slep->getFieldAmount(sfAmount);
// If a cancel time is present, a finish operation should only succeed prior
// to that time. fix1571 corrects a logic error in the check that would make
@@ -576,8 +580,11 @@ EscrowFinish::doApply()
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
return temDISABLED;
if (!slep->isFieldPresent(sfTransferRate))
return tecINTERNAL;
Rate lockedRate = ripple::Rate(slep->getFieldU32(sfTransferRate));
auto issuerAccID = amount.getIssuer();
auto const issuerAccID = amount.getIssuer();
auto const xferRate = transferRate(view(), issuerAccID);
// update if issuer rate is less than locked rate
if (xferRate < lockedRate)
@@ -585,7 +592,7 @@ EscrowFinish::doApply()
// perform a dry run of the transfer before we
// change anything on-ledger
TER result = trustTransferLockedBalance(
TER const result = trustTransferLockedBalance(
ctx_.view(),
account_, // txn signing account
sle, // src account
@@ -632,8 +639,11 @@ EscrowFinish::doApply()
else
{
// compute transfer fee, if any
if (!slep->isFieldPresent(sfTransferRate))
return tecINTERNAL;
Rate lockedRate = ripple::Rate(slep->getFieldU32(sfTransferRate));
auto issuerAccID = amount.getIssuer();
auto const issuerAccID = amount.getIssuer();
auto const xferRate = transferRate(view(), issuerAccID);
// update if issuer rate is less than locked rate
if (xferRate < lockedRate)
@@ -642,7 +652,7 @@ EscrowFinish::doApply()
// all the significant complexity of checking the validity of this
// transfer and ensuring the lines exist etc is hidden away in this
// function, all we need to do is call it and return if unsuccessful.
TER result = trustTransferLockedBalance(
TER const result = trustTransferLockedBalance(
ctx_.view(),
account_, // txn signing account
sle, // src account
@@ -733,8 +743,8 @@ EscrowCancel::doApply()
AccountID const account = (*slep)[sfAccount];
auto const sle = ctx_.view().peek(keylet::account(account));
auto amount = slep->getFieldAmount(sfAmount);
bool isIssuer = amount.getIssuer() == account;
auto const amount = slep->getFieldAmount(sfAmount);
bool const isIssuer = amount.getIssuer() == account;
std::shared_ptr<SLE> sleLine;
@@ -750,7 +760,7 @@ EscrowCancel::doApply()
account, amount.getIssuer(), amount.getCurrency()));
// dry run before we make any changes to ledger
if (TER result = trustAdjustLockedBalance(
if (TER const result = trustAdjustLockedBalance(
ctx_.view(), sleLine, -amount, -1, ctx_.journal, DryRun);
result != tesSUCCESS)
return result;
@@ -794,7 +804,7 @@ EscrowCancel::doApply()
if (!isIssuer)
{
// unlock previously locked tokens from source line
TER result = trustAdjustLockedBalance(
TER const result = trustAdjustLockedBalance(
ctx_.view(), sleLine, -amount, -1, ctx_.journal, WetRun);
JLOG(ctx_.journal.trace())

View File

@@ -361,7 +361,7 @@ NoZeroEscrow::finalize(
if (bad_ && rv.rules().enabled(featurePaychanAndEscrowForTokens) &&
txn.isFieldPresent(sfTransactionType))
{
uint16_t tt = txn.getFieldU16(sfTransactionType);
uint16_t const tt = txn.getFieldU16(sfTransactionType);
if (tt == ttESCROW_CANCEL || tt == ttESCROW_FINISH)
return true;

View File

@@ -133,7 +133,7 @@ closeChannel(
keylet::line(src, amount.getIssuer(), amount.getCurrency()));
// dry run
TER result =
TER const result =
trustAdjustLockedBalance(view, sleLine, -amount, -1, j, DryRun);
JLOG(j.trace()) << "closeChannel: trustAdjustLockedBalance(dry) result="
@@ -178,7 +178,7 @@ closeChannel(
(*sle)[sfBalance] = (*sle)[sfBalance] + amount;
else
{
TER result =
TER const result =
trustAdjustLockedBalance(view, sleLine, -amount, -1, j, WetRun);
JLOG(j.trace()) << "closeChannel: trustAdjustLockedBalance(wet) result="
@@ -257,7 +257,7 @@ PayChanCreate::preclaim(PreclaimContext const& ctx)
return tecINSUFFICIENT_RESERVE;
auto const dst = ctx.tx[sfDestination];
bool isIssuer = amount.getIssuer() == account;
bool const isIssuer = amount.getIssuer() == account;
// Check reserve and funds availability
if (isXRP(amount) && balance < reserve + amount)
@@ -272,7 +272,7 @@ PayChanCreate::preclaim(PreclaimContext const& ctx)
// check for any possible bars to a channel existing
// between these accounts for this asset
{
TER result = trustTransferAllowed(
TER const result = trustTransferAllowed(
ctx.view, {account, dst}, amount.issue(), ctx.j);
JLOG(ctx.j.trace())
<< "PayChanCreate::preclaim trustTransferAllowed result="
@@ -287,7 +287,7 @@ PayChanCreate::preclaim(PreclaimContext const& ctx)
{
auto sleLine = ctx.view.read(keylet::line(
account, amount.getIssuer(), amount.getCurrency()));
TER result = trustAdjustLockedBalance(
TER const result = trustAdjustLockedBalance(
ctx.view, sleLine, amount, 1, ctx.j, DryRun);
JLOG(ctx.j.trace()) << "PayChanCreate::preclaim "
"trustAdjustLockedBalance(dry) result="
@@ -334,8 +334,7 @@ PayChanCreate::doApply()
auto const dst = ctx_.tx[sfDestination];
STAmount const amount{ctx_.tx[sfAmount]};
bool isIssuer = amount.getIssuer() == account;
auto xferRate = transferRate(view(), amount.getIssuer());
bool const isIssuer = amount.getIssuer() == account;
// Create PayChan in ledger.
//
@@ -353,12 +352,17 @@ PayChanCreate::doApply()
(*slep)[sfAccount] = account;
(*slep)[sfDestination] = dst;
(*slep)[sfSettleDelay] = ctx_.tx[sfSettleDelay];
(*slep)[sfTransferRate] = xferRate.value;
(*slep)[sfPublicKey] = ctx_.tx[sfPublicKey];
(*slep)[~sfCancelAfter] = ctx_.tx[~sfCancelAfter];
(*slep)[~sfSourceTag] = ctx_.tx[~sfSourceTag];
(*slep)[~sfDestinationTag] = ctx_.tx[~sfDestinationTag];
if (ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
{
auto xferRate = transferRate(view(), amount.getIssuer());
(*slep)[~sfTransferRate] = xferRate.value;
}
ctx_.view().insert(slep);
// Add PayChan to owner directory
@@ -398,7 +402,7 @@ PayChanCreate::doApply()
if (!sleLine)
return tecNO_LINE;
TER result = trustAdjustLockedBalance(
TER const result = trustAdjustLockedBalance(
ctx_.view(), sleLine, amount, 1, ctx_.journal, WetRun);
JLOG(ctx_.journal.trace())
@@ -470,24 +474,28 @@ PayChanFund::doApply()
AccountID const src = (*slep)[sfAccount];
auto const txAccount = ctx_.tx[sfAccount];
auto const expiration = (*slep)[~sfExpiration];
bool isIssuer = amount.getIssuer() == txAccount;
// auto const chanFunds = (*slep)[sfAmount];
// adjust transfer rate
Rate lockedRate = ripple::Rate(slep->getFieldU32(sfTransferRate));
auto issuerAccID = amount.getIssuer();
auto const xferRate = transferRate(view(), issuerAccID);
// update if issuer rate less than locked rate
if (xferRate < lockedRate)
(*slep)[sfTransferRate] = xferRate.value;
// throw if issuer rate greater than locked rate
if (xferRate > lockedRate)
return temBAD_TRANSFER_RATE;
bool const isIssuer = amount.getIssuer() == txAccount;
// if this is a Fund operation on an IOU then perform a dry run here
if (!isXRP(amount) &&
ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
{
// adjust transfer rate
if (!slep->isFieldPresent(sfTransferRate))
return tecINTERNAL;
Rate lockedRate = ripple::Rate(slep->getFieldU32(sfTransferRate));
auto const issuerAccID = amount.getIssuer();
auto const xferRate = transferRate(view(), issuerAccID);
// update if issuer rate less than locked rate
if (xferRate < lockedRate)
(*slep)[~sfTransferRate] = xferRate.value;
// throw if issuer rate greater than locked rate
if (xferRate > lockedRate)
return temBAD_TRANSFER_RATE;
// issuer does not need to lock anything
if (!isIssuer)
{
@@ -497,7 +505,7 @@ PayChanFund::doApply()
sleLine = ctx_.view().peek(keylet::line(
(*slep)[sfAccount], amount.getIssuer(), amount.getCurrency()));
TER result = trustAdjustLockedBalance(
TER const result = trustAdjustLockedBalance(
ctx_.view(), sleLine, amount, 1, ctx_.journal, DryRun);
JLOG(ctx_.journal.trace())
@@ -571,7 +579,7 @@ PayChanFund::doApply()
// issuer does not need to lock anything
if (!isIssuer)
{
TER result = trustAdjustLockedBalance(
TER const result = trustAdjustLockedBalance(
ctx_.view(), sleLine, amount, 1, ctx_.journal, WetRun);
JLOG(ctx_.journal.trace())
@@ -715,11 +723,11 @@ PayChanClaim::doApply()
}
if (reqBalance > chanFunds)
return tecINSUFFICIENT_FUNDS;
return tecUNFUNDED_PAYMENT;
if (reqBalance <= chanBalance)
// nothing requested
return tecINSUFFICIENT_FUNDS;
return tecUNFUNDED_PAYMENT;
auto sled = ctx_.view().peek(keylet::account(dst));
if (!sled)
@@ -746,17 +754,6 @@ PayChanClaim::doApply()
}
}
// compute transfer fee, if any
Rate lockedRate = ripple::Rate(slep->getFieldU32(sfTransferRate));
auto issuerAccID = chanFunds.getIssuer();
auto const xferRate = transferRate(view(), issuerAccID);
// update if issuer rate is less than locked rate
if (xferRate < lockedRate)
{
(*slep)[sfTransferRate] = xferRate.value;
lockedRate = xferRate;
}
(*slep)[sfBalance] = ctx_.tx[sfBalance];
STAmount const reqDelta = reqBalance - chanBalance;
assert(reqDelta >= beast::zero);
@@ -770,8 +767,22 @@ PayChanClaim::doApply()
if (!ctx_.view().rules().enabled(featurePaychanAndEscrowForTokens))
return temDISABLED;
// compute transfer fee, if any
if (!slep->isFieldPresent(sfTransferRate))
return tecINTERNAL;
Rate lockedRate = ripple::Rate(slep->getFieldU32(sfTransferRate));
auto const issuerAccID = chanFunds.getIssuer();
auto const xferRate = transferRate(view(), issuerAccID);
// update if issuer rate is less than locked rate
if (xferRate < lockedRate)
{
(*slep)[~sfTransferRate] = xferRate.value;
lockedRate = xferRate;
}
auto sleSrcAcc = ctx_.view().peek(keylet::account(src));
TER result = trustTransferLockedBalance(
TER const result = trustTransferLockedBalance(
ctx_.view(),
txAccount,
sleSrcAcc,

View File

@@ -506,12 +506,12 @@ trustAdjustLockedBalance(
// auto const currency = deltaAmt.getCurrency();
auto const issuer = deltaAmt.getIssuer();
STAmount lowLimit = sleLine->getFieldAmount(sfLowLimit);
STAmount const 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;
bool const high = lowLimit.getIssuer() == issuer;
std::vector<AccountID> parties{
high ? sleLine->getFieldAmount(sfHighLimit).getIssuer()
@@ -519,7 +519,8 @@ trustAdjustLockedBalance(
// check for freezes & auth
{
TER result = trustTransferAllowed(view, parties, deltaAmt.issue(), j);
TER const result =
trustTransferAllowed(view, parties, deltaAmt.issue(), j);
JLOG(j.trace())
<< "trustAdjustLockedBalance: trustTransferAllowed result="
@@ -810,19 +811,19 @@ trustTransferLockedBalance(
return tecINTERNAL;
}
auto issuerAccID = amount.getIssuer();
auto currency = amount.getCurrency();
auto srcAccID = sleSrcAcc->getAccountID(sfAccount);
auto dstAccID = sleDstAcc->getAccountID(sfAccount);
auto const issuerAccID = amount.getIssuer();
auto const currency = amount.getCurrency();
auto const srcAccID = sleSrcAcc->getAccountID(sfAccount);
auto const dstAccID = sleDstAcc->getAccountID(sfAccount);
bool srcHigh = srcAccID > issuerAccID;
bool dstHigh = dstAccID > issuerAccID;
bool srcIssuer = issuerAccID == srcAccID;
bool dstIssuer = issuerAccID == dstAccID;
bool const srcHigh = srcAccID > issuerAccID;
bool const dstHigh = dstAccID > issuerAccID;
bool const srcIssuer = issuerAccID == srcAccID;
bool const dstIssuer = issuerAccID == dstAccID;
// check for freezing, auth, no ripple and TL sanity
{
TER result = trustTransferAllowed(
TER const result = trustTransferAllowed(
view, {srcAccID, dstAccID}, {currency, issuerAccID}, j);
JLOG(j.trace())
@@ -876,10 +877,6 @@ trustTransferLockedBalance(
uint32_t priorLockCount = (*sleSrcLine)[sfLockCount];
AccountID srcIssuerAccID =
sleSrcLine->getFieldAmount(srcHigh ? sfLowLimit : sfHighLimit)
.getIssuer();
// check they have sufficient funds
if (amount > priorLockedBalance)
{

View File

@@ -260,8 +260,8 @@ accountHolds(
if (view.rules().enabled(featurePaychanAndEscrowForTokens) &&
sle->isFieldPresent(sfLockedBalance))
{
STAmount lockedBalance = sle->getFieldAmount(sfLockedBalance);
STAmount spendableBalance =
STAmount const lockedBalance = sle->getFieldAmount(sfLockedBalance);
STAmount const spendableBalance =
amount - (account > issuer ? -lockedBalance : lockedBalance);
// RH NOTE: this is defensively programmed, it should never fire
@@ -919,18 +919,19 @@ isTrustDefault(
{
assert(acc && line);
uint32_t tlFlags = line->getFieldU32(sfFlags);
uint32_t const tlFlags = line->getFieldU32(sfFlags);
AccountID highAccID = line->getFieldAmount(sfHighLimit).issue().account;
AccountID lowAccID = line->getFieldAmount(sfLowLimit).issue().account;
AccountID const highAccID =
line->getFieldAmount(sfHighLimit).issue().account;
AccountID const lowAccID = line->getFieldAmount(sfLowLimit).issue().account;
AccountID accID = acc->getAccountID(sfAccount);
AccountID const accID = acc->getAccountID(sfAccount);
assert(accID == highAccID || accID == lowAccID);
bool high = accID == highAccID;
bool const high = accID == highAccID;
uint32_t acFlags = line->getFieldU32(sfFlags);
uint32_t const acFlags = line->getFieldU32(sfFlags);
const auto fNoRipple{high ? lsfHighNoRipple : lsfLowNoRipple};
const auto fFreeze{high ? lsfHighFreeze : lsfLowFreeze};
@@ -950,9 +951,9 @@ isTrustDefault(
if (line->getFieldAmount(high ? sfHighLimit : sfLowLimit) != beast::zero)
return false;
uint32_t qualityIn =
uint32_t const qualityIn =
line->getFieldU32(high ? sfHighQualityIn : sfLowQualityIn);
uint32_t qualityOut =
uint32_t const qualityOut =
line->getFieldU32(high ? sfHighQualityOut : sfLowQualityOut);
if (qualityIn && qualityIn != QUALITY_ONE)

View File

@@ -127,7 +127,7 @@ LedgerFormats::LedgerFormats()
{sfAccount, soeREQUIRED},
{sfDestination, soeREQUIRED},
{sfAmount, soeREQUIRED},
{sfTransferRate, soeREQUIRED},
{sfTransferRate, soeOPTIONAL},
{sfCondition, soeOPTIONAL},
{sfCancelAfter, soeOPTIONAL},
{sfFinishAfter, soeOPTIONAL},
@@ -250,7 +250,7 @@ LedgerFormats::LedgerFormats()
{sfBalance, soeREQUIRED},
{sfPublicKey, soeREQUIRED},
{sfSettleDelay, soeREQUIRED},
{sfTransferRate, soeREQUIRED},
{sfTransferRate, soeOPTIONAL},
{sfExpiration, soeOPTIONAL},
{sfCancelAfter, soeOPTIONAL},
{sfSourceTag, soeOPTIONAL},

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff