Compare commits

..

1 Commits

Author SHA1 Message Date
Bart
ce2a02e828 refactor: Apply various minor improvements and corrections 2026-04-29 06:37:51 -04:00
11 changed files with 35 additions and 605 deletions

View File

@@ -19,7 +19,6 @@ XRPL_FIX (Cleanup3_2_0, Supported::no, VoteBehavior::DefaultNo
XRPL_FEATURE(MPTokensV2, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (Security3_1_3, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (PermissionedDomainInvariant, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (ExpiredNFTokenOfferRemoval, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (BatchInnerSigs, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(LendingProtocol, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(PermissionDelegationV1_1, Supported::no, VoteBehavior::DefaultNo)

View File

@@ -81,12 +81,9 @@ setCurrentThreadNameImpl(std::string_view name)
{
// truncate and set the thread name.
char boundedName[maxThreadNameLength + 1];
std::snprintf(
boundedName,
sizeof(boundedName),
"%.*s",
static_cast<int>(maxThreadNameLength),
name.data()); // NOLINT(bugprone-suspicious-stringview-data-usage)
auto const boundedSize = name.size() < maxThreadNameLength ? name.size() : maxThreadNameLength;
name.copy(boundedName, boundedSize);
boundedName[boundedSize] = '\0';
pthread_setname_np(pthread_self(), boundedName);

View File

@@ -452,489 +452,6 @@ doWithdraw(
return accountSend(view, sourceAcct, dstAcct, amount, j, WaiveTransferFee::Yes);
}
// Direct send w/o fees:
// - Redeeming IOUs and/or sending sender's own IOUs.
// - Create trust line if needed.
// --> bCheckIssuer : normally require issuer to be involved.
static TER
rippleCreditIOU(
ApplyView& view,
AccountID const& uSenderID,
AccountID const& uReceiverID,
STAmount const& saAmount,
bool bCheckIssuer,
beast::Journal j)
{
AccountID const& issuer = saAmount.getIssuer();
Currency const& currency = saAmount.getCurrency();
// Make sure issuer is involved.
XRPL_ASSERT(
!bCheckIssuer || uSenderID == issuer || uReceiverID == issuer,
"xrpl::rippleCreditIOU : matching issuer or don't care");
(void)issuer;
// Disallow sending to self.
XRPL_ASSERT(uSenderID != uReceiverID, "xrpl::rippleCreditIOU : sender is not receiver");
bool const bSenderHigh = uSenderID > uReceiverID;
auto const index = keylet::line(uSenderID, uReceiverID, currency);
XRPL_ASSERT(
!isXRP(uSenderID) && uSenderID != noAccount(), "xrpl::rippleCreditIOU : sender is not XRP");
XRPL_ASSERT(
!isXRP(uReceiverID) && uReceiverID != noAccount(),
"xrpl::rippleCreditIOU : receiver is not XRP");
// If the line exists, modify it accordingly.
if (auto const sleRippleState = view.peek(index))
{
STAmount saBalance = sleRippleState->getFieldAmount(sfBalance);
if (bSenderHigh)
saBalance.negate(); // Put balance in sender terms.
view.creditHook(uSenderID, uReceiverID, saAmount, saBalance);
STAmount const saBefore = saBalance;
saBalance -= saAmount;
JLOG(j.trace()) << "rippleCreditIOU: " << to_string(uSenderID) << " -> "
<< to_string(uReceiverID) << " : before=" << saBefore.getFullText()
<< " amount=" << saAmount.getFullText()
<< " after=" << saBalance.getFullText();
std::uint32_t const uFlags(sleRippleState->getFieldU32(sfFlags));
bool bDelete = false;
// FIXME This NEEDS to be cleaned up and simplified. It's impossible
// for anyone to understand.
if (saBefore > beast::zero
// Sender balance was positive.
&& saBalance <= beast::zero
// Sender is zero or negative.
&& (uFlags & (!bSenderHigh ? lsfLowReserve : lsfHighReserve))
// Sender reserve is set.
&& static_cast<bool>(uFlags & (!bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple)) !=
static_cast<bool>(
view.read(keylet::account(uSenderID))->getFlags() & lsfDefaultRipple) &&
!(uFlags & (!bSenderHigh ? lsfLowFreeze : lsfHighFreeze)) &&
!sleRippleState->getFieldAmount(!bSenderHigh ? sfLowLimit : sfHighLimit)
// Sender trust limit is 0.
&& !sleRippleState->getFieldU32(!bSenderHigh ? sfLowQualityIn : sfHighQualityIn)
// Sender quality in is 0.
&& !sleRippleState->getFieldU32(!bSenderHigh ? sfLowQualityOut : sfHighQualityOut))
// Sender quality out is 0.
{
// Clear the reserve of the sender, possibly delete the line!
adjustOwnerCount(view, view.peek(keylet::account(uSenderID)), -1, j);
// Clear reserve flag.
sleRippleState->setFieldU32(
sfFlags, uFlags & (!bSenderHigh ? ~lsfLowReserve : ~lsfHighReserve));
// Balance is zero, receiver reserve is clear.
bDelete = !saBalance // Balance is zero.
&& !(uFlags & (bSenderHigh ? lsfLowReserve : lsfHighReserve));
// Receiver reserve is clear.
}
if (bSenderHigh)
saBalance.negate();
// Want to reflect balance to zero even if we are deleting line.
sleRippleState->setFieldAmount(sfBalance, saBalance);
// ONLY: Adjust ripple balance.
if (bDelete)
{
return trustDelete(
view,
sleRippleState,
bSenderHigh ? uReceiverID : uSenderID,
!bSenderHigh ? uReceiverID : uSenderID,
j);
}
view.update(sleRippleState);
return tesSUCCESS;
}
STAmount const saReceiverLimit(Issue{currency, uReceiverID});
STAmount saBalance{saAmount};
saBalance.setIssuer(noAccount());
JLOG(j.debug()) << "rippleCreditIOU: "
"create line: "
<< to_string(uSenderID) << " -> " << to_string(uReceiverID) << " : "
<< saAmount.getFullText();
auto const sleAccount = view.peek(keylet::account(uReceiverID));
if (!sleAccount)
return tefINTERNAL; // LCOV_EXCL_LINE
bool const noRipple = (sleAccount->getFlags() & lsfDefaultRipple) == 0;
return trustCreate(
view,
bSenderHigh,
uSenderID,
uReceiverID,
index.key,
sleAccount,
false,
noRipple,
false,
false,
saBalance,
saReceiverLimit,
0,
0,
j);
}
// Send regardless of limits.
// --> saAmount: Amount/currency/issuer to deliver to receiver.
// <-- saActual: Amount actually cost. Sender pays fees.
static TER
rippleSendIOU(
ApplyView& view,
AccountID const& uSenderID,
AccountID const& uReceiverID,
STAmount const& saAmount,
STAmount& saActual,
beast::Journal j,
WaiveTransferFee waiveFee)
{
auto const& issuer = saAmount.getIssuer();
XRPL_ASSERT(
!isXRP(uSenderID) && !isXRP(uReceiverID),
"xrpl::rippleSendIOU : neither sender nor receiver is XRP");
XRPL_ASSERT(uSenderID != uReceiverID, "xrpl::rippleSendIOU : sender is not receiver");
if (uSenderID == issuer || uReceiverID == issuer || issuer == noAccount())
{
// Direct send: redeeming IOUs and/or sending own IOUs.
auto const ter = rippleCreditIOU(view, uSenderID, uReceiverID, saAmount, false, j);
if (ter != tesSUCCESS)
return ter;
saActual = saAmount;
return tesSUCCESS;
}
// Sending 3rd party IOUs: transit.
// Calculate the amount to transfer accounting
// for any transfer fees if the fee is not waived:
saActual = (waiveFee == WaiveTransferFee::Yes) ? saAmount
: multiply(saAmount, transferRate(view, issuer));
JLOG(j.debug()) << "rippleSendIOU> " << to_string(uSenderID) << " - > "
<< to_string(uReceiverID) << " : deliver=" << saAmount.getFullText()
<< " cost=" << saActual.getFullText();
TER terResult = rippleCreditIOU(view, issuer, uReceiverID, saAmount, true, j);
if (tesSUCCESS == terResult)
terResult = rippleCreditIOU(view, uSenderID, issuer, saActual, true, j);
return terResult;
}
template <class TAsset>
static TER
doSendMulti(
std::string const& name,
ApplyView& view,
AccountID const& senderID,
TAsset const& issue,
MultiplePaymentDestinations const& receivers,
STAmount& actual,
beast::Journal j,
WaiveTransferFee waiveFee,
// Don't pass back parameters that the caller already has
std::function<
TER(AccountID const& senderID,
AccountID const& receiverID,
STAmount const& amount,
bool checkIssuer)> doCredit,
std::function<
TER(AccountID const& issuer, STAmount const& takeFromSender, STAmount const& amount)>
preMint = {})
{
// Use the same pattern for all the SendMulti functions to help avoid
// divergence and copy/paste errors.
auto const& issuer = issue.getIssuer();
// These values may not stay in sync
STAmount takeFromSender{issue};
actual = takeFromSender;
// Failures return immediately.
for (auto const& r : receivers)
{
auto const& receiverID = r.first;
STAmount amount{issue, r.second};
if (amount < beast::zero)
{
return tecINTERNAL; // LCOV_EXCL_LINE
}
/* If we aren't sending anything or if the sender is the same as the
* receiver then we don't need to do anything.
*/
if (!amount || (senderID == receiverID))
continue;
using namespace std::string_literals;
XRPL_ASSERT(!isXRP(receiverID), ("xrpl::"s + name + " : receiver is not XRP").c_str());
if (senderID == issuer || receiverID == issuer || issuer == noAccount())
{
if (preMint)
{
if (auto const ter = preMint(issuer, takeFromSender, amount))
return ter;
}
// Direct send: redeeming IOUs and/or sending own IOUs.
if (auto const ter = doCredit(senderID, receiverID, amount, false))
return ter;
actual += amount;
// Do not add amount to takeFromSender, because doCredit took
// it.
continue;
}
// Sending 3rd party: transit.
// Calculate the amount to transfer accounting
// for any transfer fees if the fee is not waived:
STAmount actualSend = (waiveFee == WaiveTransferFee::Yes || issue.native())
? amount
: multiply(amount, transferRate(view, amount));
actual += actualSend;
takeFromSender += actualSend;
JLOG(j.debug()) << name << "> " << to_string(senderID) << " - > " << to_string(receiverID)
<< " : deliver=" << amount.getFullText()
<< " cost=" << actualSend.getFullText();
if (TER const terResult = doCredit(issuer, receiverID, amount, true))
return terResult;
}
if (senderID != issuer && takeFromSender)
{
if (TER const terResult = doCredit(senderID, issuer, takeFromSender, true))
return terResult;
}
return tesSUCCESS;
}
// Send regardless of limits.
// --> receivers: Amount/currency/issuer to deliver to receivers.
// <-- saActual: Amount actually cost to sender. Sender pays fees.
static TER
rippleSendMultiIOU(
ApplyView& view,
AccountID const& senderID,
Issue const& issue,
MultiplePaymentDestinations const& receivers,
STAmount& actual,
beast::Journal j,
WaiveTransferFee waiveFee)
{
XRPL_ASSERT(!isXRP(senderID), "xrpl::rippleSendMultiIOU : sender is not XRP");
auto doCredit = [&view, j](
AccountID const& senderID,
AccountID const& receiverID,
STAmount const& amount,
bool checkIssuer) {
return rippleCreditIOU(view, senderID, receiverID, amount, checkIssuer, j);
};
return doSendMulti(
"rippleSendMultiIOU", view, senderID, issue, receivers, actual, j, waiveFee, doCredit);
}
static TER
rippleCreditMPT(
ApplyView& view,
AccountID const& uSenderID,
AccountID const& uReceiverID,
STAmount const& saAmount,
beast::Journal j)
{
// Do not check MPT authorization here - it must have been checked earlier
auto const mptID = keylet::mptIssuance(saAmount.get<MPTIssue>().getMptID());
auto const& issuer = saAmount.getIssuer();
auto sleIssuance = view.peek(mptID);
if (!sleIssuance)
return tecOBJECT_NOT_FOUND;
if (uSenderID == issuer)
{
(*sleIssuance)[sfOutstandingAmount] += saAmount.mpt().value();
view.update(sleIssuance);
}
else
{
auto const mptokenID = keylet::mptoken(mptID.key, uSenderID);
if (auto sle = view.peek(mptokenID))
{
auto const amt = sle->getFieldU64(sfMPTAmount);
auto const pay = saAmount.mpt().value();
if (amt < pay)
return tecINSUFFICIENT_FUNDS;
(*sle)[sfMPTAmount] = amt - pay;
view.update(sle);
}
else
return tecNO_AUTH;
}
if (uReceiverID == issuer)
{
auto const outstanding = sleIssuance->getFieldU64(sfOutstandingAmount);
auto const redeem = saAmount.mpt().value();
if (outstanding >= redeem)
{
sleIssuance->setFieldU64(sfOutstandingAmount, outstanding - redeem);
view.update(sleIssuance);
}
else
return tecINTERNAL; // LCOV_EXCL_LINE
}
else
{
auto const mptokenID = keylet::mptoken(mptID.key, uReceiverID);
if (auto sle = view.peek(mptokenID))
{
(*sle)[sfMPTAmount] += saAmount.mpt().value();
view.update(sle);
}
else
return tecNO_AUTH;
}
return tesSUCCESS;
}
static TER
rippleSendMPT(
ApplyView& view,
AccountID const& uSenderID,
AccountID const& uReceiverID,
STAmount const& saAmount,
STAmount& saActual,
beast::Journal j,
WaiveTransferFee waiveFee)
{
XRPL_ASSERT(uSenderID != uReceiverID, "xrpl::rippleSendMPT : sender is not receiver");
// Safe to get MPT since rippleSendMPT is only called by accountSendMPT
auto const& issuer = saAmount.getIssuer();
auto const sle = view.read(keylet::mptIssuance(saAmount.get<MPTIssue>().getMptID()));
if (!sle)
return tecOBJECT_NOT_FOUND;
if (uSenderID == issuer || uReceiverID == issuer)
{
// if sender is issuer, check that the new OutstandingAmount will not
// exceed MaximumAmount
if (uSenderID == issuer)
{
auto const sendAmount = saAmount.mpt().value();
auto const maximumAmount = sle->at(~sfMaximumAmount).value_or(maxMPTokenAmount);
if (sendAmount > maximumAmount ||
sle->getFieldU64(sfOutstandingAmount) > maximumAmount - sendAmount)
return tecPATH_DRY;
}
// Direct send: redeeming MPTs and/or sending own MPTs.
auto const ter = rippleCreditMPT(view, uSenderID, uReceiverID, saAmount, j);
if (ter != tesSUCCESS)
return ter;
saActual = saAmount;
return tesSUCCESS;
}
// Sending 3rd party MPTs: transit.
saActual = (waiveFee == WaiveTransferFee::Yes)
? saAmount
: multiply(saAmount, transferRate(view, saAmount.get<MPTIssue>().getMptID()));
JLOG(j.debug()) << "rippleSendMPT> " << to_string(uSenderID) << " - > "
<< to_string(uReceiverID) << " : deliver=" << saAmount.getFullText()
<< " cost=" << saActual.getFullText();
if (auto const terResult = rippleCreditMPT(view, issuer, uReceiverID, saAmount, j);
terResult != tesSUCCESS)
return terResult;
return rippleCreditMPT(view, uSenderID, issuer, saActual, j);
}
static TER
rippleSendMultiMPT(
ApplyView& view,
AccountID const& senderID,
MPTIssue const& mptIssue,
MultiplePaymentDestinations const& receivers,
STAmount& actual,
beast::Journal j,
WaiveTransferFee waiveFee)
{
auto const sle = view.read(keylet::mptIssuance(mptIssue.getMptID()));
if (!sle)
return tecOBJECT_NOT_FOUND;
auto preMint = [&](AccountID const& issuer,
STAmount const& takeFromSender,
STAmount const& amount) -> TER {
// if sender is issuer, check that the new OutstandingAmount will
// not exceed MaximumAmount
if (senderID == issuer)
{
XRPL_ASSERT_PARTS(
takeFromSender == beast::zero,
"rippler::rippleSendMultiMPT",
"sender == issuer, takeFromSender == zero");
auto const sendAmount = amount.mpt().value();
auto const maximumAmount = sle->at(~sfMaximumAmount).value_or(maxMPTokenAmount);
if (sendAmount > maximumAmount ||
sle->getFieldU64(sfOutstandingAmount) > maximumAmount - sendAmount)
return tecPATH_DRY;
}
return tesSUCCESS;
};
auto doCredit =
[&view, j](
AccountID const& senderID, AccountID const& receiverID, STAmount const& amount, bool) {
return rippleCreditMPT(view, senderID, receiverID, amount, j);
};
return doSendMulti(
"rippleSendMultiMPT",
view,
senderID,
mptIssue,
receivers,
actual,
j,
waiveFee,
doCredit,
preMint);
}
TER
cleanupOnAccountDelete(
ApplyView& view,

View File

@@ -21,7 +21,7 @@ offerDelete(ApplyView& view, std::shared_ptr<SLE> const& sle, beast::Journal j)
if (!sle)
return tesSUCCESS;
auto offerIndex = sle->key();
auto const owner = sle->getAccountID(sfAccount);
auto owner = sle->getAccountID(sfAccount);
// Detect legacy directories.
uint256 const uDirectory = sle->getFieldH256(sfBookDirectory);

View File

@@ -579,7 +579,7 @@ requireAuth(ReadView const& view, Issue const& issue, AccountID const& account,
return tesSUCCESS;
}
[[nodiscard]] TER
TER
canTransfer(ReadView const& view, Issue const& issue, AccountID const& from, AccountID const& to)
{
if (issue.native())
@@ -617,7 +617,7 @@ canTransfer(ReadView const& view, Issue const& issue, AccountID const& from, Acc
//
//------------------------------------------------------------------------------
[[nodiscard]] TER
TER
addEmptyHolding(
ApplyView& view,
AccountID const& accountID,
@@ -671,7 +671,7 @@ addEmptyHolding(
journal);
}
[[nodiscard]] TER
TER
removeEmptyHolding(
ApplyView& view,
AccountID const& accountID,

View File

@@ -938,85 +938,6 @@ accountSendMultiIOU(
<< receivers.size() << " receivers.";
}
auto doCredit = [&view, &sender, &receivers, j](
AccountID const& senderID,
AccountID const& receiverID,
STAmount const& amount,
bool /*checkIssuer*/) -> TER {
if (!senderID)
{
SLE::pointer receiver =
receiverID != beast::zero ? view.peek(keylet::account(receiverID)) : SLE::pointer();
if (auto stream = j.trace())
{
std::string receiver_bal("-");
if (receiver)
receiver_bal = receiver->getFieldAmount(sfBalance).getFullText();
stream << "accountSendMultiIOU> " << to_string(senderID) << " -> "
<< to_string(receiverID) << " (" << receiver_bal
<< ") : " << amount.getFullText();
}
if (receiver)
{
// Increment XRP balance.
auto const rcvBal = receiver->getFieldAmount(sfBalance);
receiver->setFieldAmount(sfBalance, rcvBal + amount);
view.creditHook(xrpAccount(), receiverID, amount, -rcvBal);
view.update(receiver);
}
if (auto stream = j.trace())
{
std::string receiver_bal("-");
if (receiver)
receiver_bal = receiver->getFieldAmount(sfBalance).getFullText();
stream << "accountSendMultiIOU< " << to_string(senderID) << " -> "
<< to_string(receiverID) << " (" << receiver_bal
<< ") : " << amount.getFullText();
}
return tesSUCCESS;
}
// Sender
if (sender)
{
if (sender->getFieldAmount(sfBalance) < amount)
{
return TER{tecFAILED_PROCESSING};
}
else
{
auto const sndBal = sender->getFieldAmount(sfBalance);
view.creditHook(senderID, xrpAccount(), amount, sndBal);
// Decrement XRP balance.
sender->setFieldAmount(sfBalance, sndBal - amount);
view.update(sender);
}
}
if (auto stream = j.trace())
{
std::string sender_bal("-");
if (sender)
sender_bal = sender->getFieldAmount(sfBalance).getFullText();
stream << "accountSendMultiIOU< " << to_string(senderID) << " (" << sender_bal
<< ") -> " << receivers.size() << " receivers.";
}
return tesSUCCESS;
};
return doSendMulti(
"accountSendMultiIOU", view, senderID, issue, receivers, actual, j, waiveFee, doCredit);
// Failures return immediately.
STAmount takeFromSender{issue};
for (auto const& r : receivers)

View File

@@ -68,15 +68,12 @@ NFTokenAcceptOffer::preclaim(PreclaimContext const& ctx)
if (hasExpired(ctx.view, (*offerSLE)[~sfExpiration]))
{
// Before fixExpiredNFTokenOfferRemoval amendment, expired
// offers caused tecEXPIRED in preclaim, leaving them on ledger
// forever. After the amendment, we allow expired offers to
// reach doApply() where they get deleted and tecEXPIRED is
// returned.
if (!ctx.view.rules().enabled(fixExpiredNFTokenOfferRemoval))
// Before fixSecurity3_1_3 amendment, expired offers caused tecEXPIRED in preclaim,
// leaving them on ledger forever. After the amendment, we allow expired offers to
// reach doApply() where they get deleted and tecEXPIRED is returned.
if (!ctx.view.rules().enabled(fixSecurity3_1_3))
return {nullptr, tecEXPIRED};
// Amendment enabled: return the expired offer to be handled in
// doApply
// Amendment enabled: return the expired offer to be handled in doApply.
}
if ((*offerSLE)[sfAmount].negative())
@@ -450,10 +447,9 @@ NFTokenAcceptOffer::doApply()
auto bo = loadToken(ctx_.tx[~sfNFTokenBuyOffer]);
auto so = loadToken(ctx_.tx[~sfNFTokenSellOffer]);
// With fixExpiredNFTokenOfferRemoval amendment, check for expired offers
// and delete them, returning tecEXPIRED. This ensures expired offers
// are properly cleaned up from the ledger.
if (view().rules().enabled(fixExpiredNFTokenOfferRemoval))
// With fixSecurity3_1_3 amendment, check for expired offers and delete them, returning
// tecEXPIRED. This ensures expired offers are properly cleaned up from the ledger.
if (view().rules().enabled(fixSecurity3_1_3))
{
bool foundExpired = false;

View File

@@ -1096,10 +1096,10 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite
// The buy offer must not have expired.
// NOTE: this is only a preclaim check with the
// fixExpiredNFTokenOfferRemoval amendment disabled.
// fixSecurity3_1_3 amendment disabled.
env(token::acceptBuyOffer(alice, buyerExpOfferIndex), ter(tecEXPIRED));
env.close();
if (features[fixExpiredNFTokenOfferRemoval])
if (features[fixSecurity3_1_3])
{
buyerCount--;
}
@@ -1117,12 +1117,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite
// The sell offer must not have expired.
// NOTE: this is only a preclaim check with the
// fixExpiredNFTokenOfferRemoval amendment disabled.
// fixSecurity3_1_3 amendment disabled.
env(token::acceptSellOffer(buyer, aliceExpOfferIndex), ter(tecEXPIRED));
env.close();
// Alice's count is decremented by one when the expired offer is
// removed.
if (features[fixExpiredNFTokenOfferRemoval])
if (features[fixSecurity3_1_3])
{
aliceCount--;
}
@@ -3101,10 +3101,10 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite
// No one can accept an expired sell offer.
env(token::acceptSellOffer(buyer, offer1), ter(tecEXPIRED));
// With fixExpiredNFTokenOfferRemoval amendment, the first accept
// With fixSecurity3_1_3 amendment, the first accept
// attempt deletes the expired offer. Without the amendment,
// the offer remains and we can try to accept it again.
if (features[fixExpiredNFTokenOfferRemoval])
if (features[fixSecurity3_1_3])
{
// After amendment: offer was deleted by first accept attempt
minterCount--;
@@ -3123,7 +3123,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite
BEAST_EXPECT(ownerCount(env, minter) == minterCount);
BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
if (!features[fixExpiredNFTokenOfferRemoval])
if (!features[fixSecurity3_1_3])
{
// Before amendment: expired offer still exists and needs to be
// cancelled
@@ -3189,10 +3189,10 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite
// An expired buy offer cannot be accepted.
env(token::acceptBuyOffer(minter, offer1), ter(tecEXPIRED));
// With fixExpiredNFTokenOfferRemoval amendment, the first accept
// With fixSecurity3_1_3 amendment, the first accept
// attempt deletes the expired offer. Without the amendment,
// the offer remains and we can try to accept it again.
if (features[fixExpiredNFTokenOfferRemoval])
if (features[fixSecurity3_1_3])
{
// After amendment: offer was deleted by first accept attempt
buyerCount--;
@@ -3211,7 +3211,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite
BEAST_EXPECT(ownerCount(env, minter) == minterCount);
BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
if (!features[fixExpiredNFTokenOfferRemoval])
if (!features[fixSecurity3_1_3])
{
// Before amendment: expired offer still exists and can be
// cancelled
@@ -3288,7 +3288,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite
env(token::brokerOffers(issuer, buyOffer1, sellOffer1), ter(tecEXPIRED));
env.close();
if (features[fixExpiredNFTokenOfferRemoval])
if (features[fixSecurity3_1_3])
{
// With amendment: expired offers are deleted
minterCount--;
@@ -3298,7 +3298,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite
BEAST_EXPECT(ownerCount(env, minter) == minterCount);
BEAST_EXPECT(ownerCount(env, buyer) == buyerCount);
if (features[fixExpiredNFTokenOfferRemoval])
if (features[fixSecurity3_1_3])
{
// The buy offer was deleted, so no need to cancel it
// The sell offer still exists, so we can cancel it
@@ -3377,7 +3377,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite
env.close();
BEAST_EXPECT(ownerCount(env, issuer) == 0);
if (features[fixExpiredNFTokenOfferRemoval])
if (features[fixSecurity3_1_3])
{
// After amendment: expired offers were deleted during broker
// attempt
@@ -3463,7 +3463,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite
// The expired offers are still in the ledger.
BEAST_EXPECT(ownerCount(env, issuer) == 0);
if (!features[fixExpiredNFTokenOfferRemoval])
if (!features[fixSecurity3_1_3])
{
// Before amendment: expired offers still exist in ledger
BEAST_EXPECT(ownerCount(env, minter) == 2);
@@ -7190,7 +7190,7 @@ public:
{
testWithFeats(
allFeatures - fixNFTokenReserve - featureNFTokenMintOffer - featureDynamicNFT -
fixExpiredNFTokenOfferRemoval);
fixSecurity3_1_3);
}
};
@@ -7227,7 +7227,7 @@ class NFTokenWOExpiredOfferRemoval_test : public NFTokenBaseUtil_test
void
run() override
{
testWithFeats(allFeatures - fixExpiredNFTokenOfferRemoval);
testWithFeats(allFeatures - fixSecurity3_1_3);
}
};

View File

@@ -1201,7 +1201,7 @@ class LedgerEntry_test : public beast::unit_test::suite
checkErrorValue(
jrr[jss::result],
"malformedAuthorizedCredentials",
"Invalid field 'authorized_credentials', not array.");
"Invalid field 'authorized_credentials', not array of objects.");
}
{
@@ -1219,7 +1219,7 @@ class LedgerEntry_test : public beast::unit_test::suite
checkErrorValue(
jrr[jss::result],
"malformedAuthorizedCredentials",
"Invalid field 'authorized_credentials', not array.");
"Invalid field 'authorized_credentials', not array of objects.");
}
{

View File

@@ -2639,7 +2639,7 @@ PeerImp::onMessage(std::shared_ptr<protocol::TMGetObjectByHash> const& m)
{
fee_.update(
Resource::feeModerateBurdenPeer,
" Reply limit reached. Truncating reply.");
"Reply limit reached. Truncating reply.");
break;
}
}

View File

@@ -267,7 +267,7 @@ parseAuthorizeCredentials(Json::Value const& jv)
if (!jo.isObject())
{
return LedgerEntryHelpers::invalidFieldError(
"malformedAuthorizedCredentials", jss::authorized_credentials, "array");
"malformedAuthorizedCredentials", jss::authorized_credentials, "array of objects");
}
if (auto const value = LedgerEntryHelpers::hasRequired(