20#include <xrpld/app/misc/DelegateUtils.h>
21#include <xrpld/app/tx/detail/SetTrust.h>
22#include <xrpld/ledger/View.h>
24#include <xrpl/basics/Log.h>
25#include <xrpl/protocol/AMMCore.h>
26#include <xrpl/protocol/Feature.h>
27#include <xrpl/protocol/Indexes.h>
28#include <xrpl/protocol/Quality.h>
40 bool bClearDeepFreeze)
42 if (bSetFreeze && !bClearFreeze && !bNoFreeze)
46 else if (bClearFreeze && !bSetFreeze)
50 if (bSetDeepFreeze && !bClearDeepFreeze && !bNoFreeze)
55 else if (bClearDeepFreeze && !bSetDeepFreeze)
81 JLOG(j.trace()) <<
"Malformed transaction: Invalid flags set.";
95 STAmount const saLimitAmount(tx.getFieldAmount(sfLimitAmount));
100 if (saLimitAmount.
native())
102 JLOG(j.trace()) <<
"Malformed transaction: specifies native limit "
109 JLOG(j.trace()) <<
"Malformed transaction: specifies XRP as IOU";
113 if (saLimitAmount < beast::zero)
115 JLOG(j.trace()) <<
"Malformed transaction: Negative credit limit.";
120 auto const& issuer = saLimitAmount.
getIssuer();
124 JLOG(j.trace()) <<
"Malformed transaction: no destination account.";
134 auto const delegate = tx[~sfDelegate];
139 auto const sle =
view.
read(delegateKey);
160 tx[sfAccount], saLimitAmount.getIssuer(), saLimitAmount.getCurrency()));
171 !granularPermissions.
contains(TrustlineAuthorize))
176 !granularPermissions.
contains(TrustlineUnfreeze))
181 auto const curLimit = tx[sfAccount] > saLimitAmount.getIssuer()
183 : sleRippleState->getFieldAmount(sfLowLimit);
185 STAmount saLimitAllow = saLimitAmount;
188 if (curLimit != saLimitAllow)
197 auto const id = ctx.
tx[sfAccount];
205 bool const bSetAuth = (uTxFlags &
tfSetfAuth);
209 JLOG(ctx.
j.
trace()) <<
"Retry: Auth not required.";
213 auto const saLimitAmount = ctx.
tx[sfLimitAmount];
215 auto const currency = saLimitAmount.getCurrency();
216 auto const uDstAccountID = saLimitAmount.getIssuer();
220 if (
id == uDstAccountID)
225 if (
id == uDstAccountID)
230 auto const sleDelete =
236 <<
"Malformed transaction: Can not extend credit to self.";
277 if (sleDst->isFieldPresent(sfAMMID) &&
280 if (
auto const ammSle =
281 ctx.
view.
read({ltAMM, sleDst->getFieldH256(sfAMMID)}))
283 if (
auto const lpTokens =
284 ammSle->getFieldAmount(sfLPTokenBalance);
285 lpTokens == beast::zero)
287 else if (lpTokens.getCurrency() != saLimitAmount.getCurrency())
302 if (bNoFreeze && (bSetFreeze || bSetDeepFreeze))
310 if ((bSetFreeze || bSetDeepFreeze) &&
311 (bClearFreeze || bClearDeepFreeze))
318 bool const bHigh =
id > uDstAccountID;
320 auto const sleRippleState =
323 sleRippleState ? sleRippleState->getFieldU32(sfFlags) : 0u;
325 uFlags = computeFreezeFlags(
335 auto const deepFrozen =
341 if (deepFrozen && !frozen)
363 bool const bHigh =
account_ > uDstAccountID;
369 std::uint32_t const uOwnerCount = sle->getFieldU32(sfOwnerCount);
390 (uOwnerCount < 2) ?
XRPAmount(beast::zero)
391 :
view().fees().accountReserve(uOwnerCount + 1));
397 if (bQualityOut && QUALITY_ONE == uQualityOut)
402 bool const bSetAuth = (uTxFlags &
tfSetfAuth);
432 <<
"Delay transaction: Destination account does not exist.";
436 STAmount saLimitAllow = saLimitAmount;
452 auto const& uLowAccountID = !bHigh ?
account_ : uDstAccountID;
453 auto const& uHighAccountID = bHigh ?
account_ : uDstAccountID;
454 SLE::ref sleLowAccount = !bHigh ? sle : sleDst;
455 SLE::ref sleHighAccount = bHigh ? sle : sleDst;
461 saLowBalance = sleRippleState->getFieldAmount(sfBalance);
462 saHighBalance = -saLowBalance;
468 sleRippleState->setFieldAmount(
469 !bHigh ? sfLowLimit : sfHighLimit, saLimitAllow);
472 !bHigh ? saLimitAllow : sleRippleState->getFieldAmount(sfLowLimit);
474 bHigh ? saLimitAllow : sleRippleState->getFieldAmount(sfHighLimit);
484 uLowQualityIn = sleRippleState->getFieldU32(sfLowQualityIn);
485 uHighQualityIn = sleRippleState->getFieldU32(sfHighQualityIn);
491 sleRippleState->setFieldU32(
492 !bHigh ? sfLowQualityIn : sfHighQualityIn, uQualityIn);
494 uLowQualityIn = !bHigh
496 : sleRippleState->getFieldU32(sfLowQualityIn);
497 uHighQualityIn = bHigh
499 : sleRippleState->getFieldU32(sfHighQualityIn);
505 sleRippleState->makeFieldAbsent(
506 !bHigh ? sfLowQualityIn : sfHighQualityIn);
509 !bHigh ? 0 : sleRippleState->getFieldU32(sfLowQualityIn);
511 bHigh ? 0 : sleRippleState->getFieldU32(sfHighQualityIn);
514 if (QUALITY_ONE == uLowQualityIn)
517 if (QUALITY_ONE == uHighQualityIn)
528 uLowQualityOut = sleRippleState->getFieldU32(sfLowQualityOut);
529 uHighQualityOut = sleRippleState->getFieldU32(sfHighQualityOut);
531 else if (uQualityOut)
535 sleRippleState->setFieldU32(
536 !bHigh ? sfLowQualityOut : sfHighQualityOut, uQualityOut);
538 uLowQualityOut = !bHigh
540 : sleRippleState->getFieldU32(sfLowQualityOut);
541 uHighQualityOut = bHigh
543 : sleRippleState->getFieldU32(sfHighQualityOut);
549 sleRippleState->makeFieldAbsent(
550 !bHigh ? sfLowQualityOut : sfHighQualityOut);
553 !bHigh ? 0 : sleRippleState->getFieldU32(sfLowQualityOut);
555 bHigh ? 0 : sleRippleState->getFieldU32(sfHighQualityOut);
558 std::uint32_t const uFlagsIn(sleRippleState->getFieldU32(sfFlags));
561 if (bSetNoRipple && !bClearNoRipple)
563 if ((bHigh ? saHighBalance : saLowBalance) >= beast::zero)
570 else if (bClearNoRipple && !bSetNoRipple)
577 uFlagsOut = computeFreezeFlags(
586 if (QUALITY_ONE == uLowQualityOut)
589 if (QUALITY_ONE == uHighQualityOut)
593 bool const bHighDefRipple =
596 bool const bLowReserveSet = uLowQualityIn || uLowQualityOut ||
599 saLowBalance > beast::zero;
600 bool const bLowReserveClear = !bLowReserveSet;
602 bool const bHighReserveSet = uHighQualityIn || uHighQualityOut ||
605 saHighBalance > beast::zero;
606 bool const bHighReserveClear = !bHighReserveSet;
608 bool const bDefault = bLowReserveClear && bHighReserveClear;
613 bool bReserveIncrease =
false;
620 if (bLowReserveSet && !bLowReserved)
627 bReserveIncrease =
true;
630 if (bLowReserveClear && bLowReserved)
634 uFlagsOut &= ~lsfLowReserve;
637 if (bHighReserveSet && !bHighReserved)
644 bReserveIncrease =
true;
647 if (bHighReserveClear && bHighReserved)
651 uFlagsOut &= ~lsfHighReserve;
654 if (uFlagsIn != uFlagsOut)
655 sleRippleState->setFieldU32(sfFlags, uFlagsOut);
662 view(), sleRippleState, uLowAccountID, uHighAccountID, viewJ);
667 JLOG(
j_.
trace()) <<
"Delay transaction: Insufficent reserve to "
678 JLOG(
j_.
trace()) <<
"Modify ripple line";
684 (!bQualityIn || !uQualityIn) &&
686 (!bQualityOut || !uQualityOut) &&
691 <<
"Redundant: Setting non-existent ripple line to defaults.";
697 JLOG(
j_.
trace()) <<
"Delay transaction: Line does not exist. "
698 "Insufficent reserve to create line.";
711 JLOG(
j_.
trace()) <<
"doTrustSet: Creating ripple line: "
723 bSetNoRipple && !bClearNoRipple,
724 bSetFreeze && !bClearFreeze,
Stream trace() const
Severity stream access functions.
virtual beast::Journal journal(std::string const &name)=0
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
A currency issued by an account.
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
virtual Rules const & rules() const =0
Returns the tx processing rules.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
void setIssuer(AccountID const &uIssuer)
Currency const & getCurrency() const
AccountID const & getIssuer() const
std::string getFullText() const override
bool native() const noexcept
std::uint32_t getFieldU32(SField const &field) const
STAmount const & getFieldAmount(SField const &field) const
bool isFieldPresent(SField const &field) const
std::uint32_t getFlags() const
static NotTEC preflight(PreflightContext const &ctx)
static TER preclaim(PreclaimContext const &ctx)
static TER checkPermission(ReadView const &view, STTx const &tx)
Keylet delegate(AccountID const &account, AccountID const &authorizedAccount) noexcept
A keylet for Delegate object.
Keylet line(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
Keylet account(AccountID const &id) noexcept
AccountID root.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
AccountID const & noAccount()
A placeholder for empty accounts.
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
constexpr std::uint32_t tfSetDeepFreeze
bool isLegalNet(STAmount const &value)
@ lsfDisallowIncomingTrustline
bool ammEnabled(Rules const &)
Return true if required AMM amendments are enabled.
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
constexpr std::uint32_t tfTrustSetPermissionMask
constexpr std::uint32_t tfClearNoRipple
static bool adjustOwnerCount(ApplyContext &ctx, int count)
void loadGranularPermission(std::shared_ptr< SLE const > const &delegate, TxType const &type, std::unordered_set< GranularPermissionType > &granularPermissions)
Load the granular permissions granted to the delegate account for the specified transaction type.
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
constexpr std::uint32_t tfSetfAuth
constexpr std::uint32_t tfClearFreeze
TER trustCreate(ApplyView &view, bool const bSrcHigh, AccountID const &uSrcAccountID, AccountID const &uDstAccountID, uint256 const &uIndex, SLE::ref sleAccount, bool const bAuth, bool const bNoRipple, bool const bFreeze, bool bDeepFreeze, STAmount const &saBalance, STAmount const &saLimit, std::uint32_t uQualityIn, std::uint32_t uQualityOut, beast::Journal j)
Create a trust line.
TER checkTxPermission(std::shared_ptr< SLE const > const &delegate, STTx const &tx)
Check if the delegate account has permission to execute the transaction.
TER trustDelete(ApplyView &view, std::shared_ptr< SLE > const &sleRippleState, AccountID const &uLowAccountID, AccountID const &uHighAccountID, beast::Journal j)
@ tecNO_LINE_INSUF_RESERVE
constexpr std::uint32_t tfClearDeepFreeze
constexpr std::uint32_t tfTrustSetMask
std::string to_string(base_uint< Bits, Tag > const &a)
constexpr std::uint32_t tfSetFreeze
constexpr std::uint32_t tfSetNoRipple
TERSubset< CanCvtToNotTEC > NotTEC
State information when determining if a tx is likely to claim a fee.
State information when preflighting a tx.