xrpld
Loading...
Searching...
No Matches
TrustSet.cpp
1#include <xrpl/tx/transactors/token/TrustSet.h>
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/base_uint.h>
5#include <xrpl/beast/utility/Zero.h>
6#include <xrpl/core/ServiceRegistry.h>
7#include <xrpl/ledger/ReadView.h>
8#include <xrpl/ledger/helpers/AccountRootHelpers.h>
9#include <xrpl/ledger/helpers/RippleStateHelpers.h>
10#include <xrpl/protocol/AMMCore.h>
11#include <xrpl/protocol/AccountID.h>
12#include <xrpl/protocol/Feature.h>
13#include <xrpl/protocol/Indexes.h>
14#include <xrpl/protocol/LedgerFormats.h>
15#include <xrpl/protocol/Permissions.h>
16#include <xrpl/protocol/Quality.h>
17#include <xrpl/protocol/SField.h>
18#include <xrpl/protocol/STAmount.h>
19#include <xrpl/protocol/STLedgerEntry.h>
20#include <xrpl/protocol/STTx.h>
21#include <xrpl/protocol/TER.h>
22#include <xrpl/protocol/TxFlags.h>
23#include <xrpl/protocol/UintTypes.h>
24#include <xrpl/protocol/XRPAmount.h>
25#include <xrpl/tx/Transactor.h>
26
27#include <cstdint>
28#include <unordered_set>
29
30namespace {
31
32uint32_t
33computeFreezeFlags(
34 uint32_t uFlags,
35 bool bHigh,
36 bool bNoFreeze,
37 bool bSetFreeze,
38 bool bClearFreeze,
39 bool bSetDeepFreeze,
40 bool bClearDeepFreeze)
41{
42 if (bSetFreeze && !bClearFreeze && !bNoFreeze)
43 {
44 uFlags |= (bHigh ? xrpl::lsfHighFreeze : xrpl::lsfLowFreeze);
45 }
46 else if (bClearFreeze && !bSetFreeze)
47 {
48 uFlags &= ~(bHigh ? xrpl::lsfHighFreeze : xrpl::lsfLowFreeze);
49 }
50 if (bSetDeepFreeze && !bClearDeepFreeze && !bNoFreeze)
51 {
52 uFlags |= (bHigh ? xrpl::lsfHighDeepFreeze : xrpl::lsfLowDeepFreeze);
53 }
54 else if (bClearDeepFreeze && !bSetDeepFreeze)
55 {
56 uFlags &= ~(bHigh ? xrpl::lsfHighDeepFreeze : xrpl::lsfLowDeepFreeze);
57 }
58
59 return uFlags;
60}
61
62} // namespace
63
64namespace xrpl {
65
66std::uint32_t
68{
69 return tfTrustSetMask;
70}
71
74{
75 auto& tx = ctx.tx;
76 auto& j = ctx.j;
77
78 if (!ctx.rules.enabled(featureDeepFreeze))
79 {
80 // Even though the deep freeze flags are included in the
81 // `tfTrustSetMask`, they are not valid if the amendment is not enabled.
82 if ((tx.getFlags() & (tfSetDeepFreeze | tfClearDeepFreeze)) != 0u)
83 {
84 return temINVALID_FLAG;
85 }
86 }
87
88 STAmount const saLimitAmount(tx.getFieldAmount(sfLimitAmount));
89
90 if (!isLegalNet(saLimitAmount))
91 return temBAD_AMOUNT;
92
93 if (saLimitAmount.native())
94 {
95 JLOG(j.trace()) << "Malformed transaction: specifies native limit "
96 << saLimitAmount.getFullText();
97 return temBAD_LIMIT;
98 }
99
100 if (badCurrency() == saLimitAmount.get<Issue>().currency)
101 {
102 JLOG(j.trace()) << "Malformed transaction: specifies XRP as IOU";
103 return temBAD_CURRENCY;
104 }
105
106 if (saLimitAmount < beast::kZero)
107 {
108 JLOG(j.trace()) << "Malformed transaction: Negative credit limit.";
109 return temBAD_LIMIT;
110 }
111
112 // Check if destination makes sense.
113 auto const& issuer = saLimitAmount.getIssuer();
114
115 if (!issuer || issuer == noAccount())
116 {
117 JLOG(j.trace()) << "Malformed transaction: no destination account.";
118 return temDST_NEEDED;
119 }
120
121 return tesSUCCESS;
122}
123
124NotTEC
126 ReadView const& view,
127 STTx const& tx,
128 std::unordered_set<GranularPermissionType> const& heldGranularPermissions)
129{
130 auto const saLimitAmount = tx.getFieldAmount(sfLimitAmount);
131 auto const sleRippleState = view.read(
133 tx[sfAccount], saLimitAmount.getIssuer(), saLimitAmount.get<Issue>().currency));
134
135 // granular permissions are not allowed to create a trustline
136 if (!sleRippleState)
138
139 // updating LimitAmount is not allowed with granular permissions,
140 // unless there's a new granular permission for this in the future.
141 auto const curLimit = tx[sfAccount] > saLimitAmount.getIssuer()
142 ? sleRippleState->getFieldAmount(sfHighLimit)
143 : sleRippleState->getFieldAmount(sfLowLimit);
144
145 STAmount saLimitAllow = saLimitAmount;
146 saLimitAllow.get<Issue>().account = tx[sfAccount];
147
148 if (curLimit != saLimitAllow)
150
151 return tesSUCCESS;
152}
153
154TER
156{
157 auto const id = ctx.tx[sfAccount];
158
159 auto const sle = ctx.view.read(keylet::account(id));
160 if (!sle)
161 return terNO_ACCOUNT;
162
163 bool const bSetAuth = ctx.tx.isFlag(tfSetfAuth);
164
165 if (bSetAuth && !sle->isFlag(lsfRequireAuth))
166 {
167 JLOG(ctx.j.trace()) << "Retry: Auth not required.";
168 return tefNO_AUTH_REQUIRED;
169 }
170
171 auto const saLimitAmount = ctx.tx[sfLimitAmount];
172
173 auto const currency = saLimitAmount.get<Issue>().currency;
174 auto const uDstAccountID = saLimitAmount.getIssuer();
175
176 if (id == uDstAccountID)
177 return temDST_IS_SRC;
178
179 // This might be nullptr
180 auto const sleDst = ctx.view.read(keylet::account(uDstAccountID));
181 if ((ammEnabled(ctx.view.rules()) || ctx.view.rules().enabled(featureSingleAssetVault)) &&
182 sleDst == nullptr)
183 return tecNO_DST;
184
185 // If the destination has opted to disallow incoming trustlines
186 // then honour that flag
187 if (sleDst->isFlag(lsfDisallowIncomingTrustline))
188 {
189 // The original implementation of featureDisallowIncoming was
190 // too restrictive. If
191 // o fixDisallowIncomingV1 is enabled and
192 // o The trust line already exists
193 // Then allow the TrustSet.
194 if (ctx.view.rules().enabled(fixDisallowIncomingV1) &&
195 ctx.view.exists(keylet::trustLine(id, uDstAccountID, currency)))
196 {
197 // pass
198 }
199 else
200 {
201 return tecNO_PERMISSION;
202 }
203 }
204
205 // In general, trust lines to pseudo accounts are not permitted, unless
206 // enabled in the code section below, for specific cases. This block is not
207 // amendment-gated because sleDst will not have a pseudo-account designator
208 // field populated, unless the appropriate amendment was already enabled.
209 if (sleDst && isPseudoAccount(sleDst))
210 {
211 // If destination is AMM and the trustline doesn't exist then only allow
212 // TrustSet if the asset is AMM LP token and AMM is not in empty state.
213 if (sleDst->isFieldPresent(sfAMMID))
214 {
215 if (ctx.view.exists(keylet::trustLine(id, uDstAccountID, currency)))
216 {
217 // pass
218 }
219 else if (auto const ammSle = ctx.view.read({ltAMM, sleDst->getFieldH256(sfAMMID)}))
220 {
221 auto const lpTokens = ammSle->getFieldAmount(sfLPTokenBalance);
222 if (lpTokens == beast::kZero)
223 {
224 return tecAMM_EMPTY;
225 }
226 if (lpTokens.get<Issue>().currency != saLimitAmount.get<Issue>().currency)
227 {
228 return tecNO_PERMISSION;
229 }
230 }
231 else
232 {
233 return tecINTERNAL; // LCOV_EXCL_LINE
234 }
235 }
236 else if (sleDst->isFieldPresent(sfVaultID) || sleDst->isFieldPresent(sfLoanBrokerID))
237 {
238 if (!ctx.view.exists(keylet::trustLine(id, uDstAccountID, currency)))
239 return tecNO_PERMISSION;
240 // else pass
241 }
242 else
243 {
244 return tecPSEUDO_ACCOUNT;
245 }
246 }
247
248 // Checking all freeze/deep freeze flag invariants.
249 if (ctx.view.rules().enabled(featureDeepFreeze))
250 {
251 bool const bNoFreeze = sle->isFlag(lsfNoFreeze);
252 bool const bSetFreeze = ctx.tx.isFlag(tfSetFreeze);
253 bool const bSetDeepFreeze = ctx.tx.isFlag(tfSetDeepFreeze);
254
255 if (bNoFreeze && (bSetFreeze || bSetDeepFreeze))
256 {
257 // Cannot freeze the trust line if NoFreeze is set
258 return tecNO_PERMISSION;
259 }
260
261 bool const bClearFreeze = ctx.tx.isFlag(tfClearFreeze);
262 bool const bClearDeepFreeze = ctx.tx.isFlag(tfClearDeepFreeze);
263 if ((bSetFreeze || bSetDeepFreeze) && (bClearFreeze || bClearDeepFreeze))
264 {
265 // Freezing and unfreezing in the same transaction should be
266 // illegal
267 return tecNO_PERMISSION;
268 }
269
270 bool const bHigh = id > uDstAccountID;
271 // Fetching current state of trust line
272 auto const sleRippleState = ctx.view.read(keylet::trustLine(id, uDstAccountID, currency));
273 std::uint32_t uFlags = sleRippleState ? sleRippleState->getFieldU32(sfFlags) : 0u;
274 // Computing expected trust line state
275 uFlags = computeFreezeFlags(
276 uFlags, bHigh, bNoFreeze, bSetFreeze, bClearFreeze, bSetDeepFreeze, bClearDeepFreeze);
277
278 auto const frozen = uFlags & (bHigh ? lsfHighFreeze : lsfLowFreeze);
279 auto const deepFrozen = uFlags & (bHigh ? lsfHighDeepFreeze : lsfLowDeepFreeze);
280
281 // Trying to set deep freeze on not already frozen trust line must
282 // fail. This also checks that clearing normal freeze while deep
283 // frozen must not work
284 if ((deepFrozen != 0u) && (frozen == 0u))
285 {
286 return tecNO_PERMISSION;
287 }
288 }
289
290 return tesSUCCESS;
291}
292
293TER
295{
296 TER terResult = tesSUCCESS;
297
298 STAmount const saLimitAmount(ctx_.tx.getFieldAmount(sfLimitAmount));
299 bool const bQualityIn(ctx_.tx.isFieldPresent(sfQualityIn));
300 bool const bQualityOut(ctx_.tx.isFieldPresent(sfQualityOut));
301
302 Currency const currency(saLimitAmount.get<Issue>().currency);
303 AccountID const uDstAccountID(saLimitAmount.getIssuer());
304
305 // true, if current is high account.
306 bool const bHigh = accountID_ > uDstAccountID;
307
308 auto const sle = view().peek(keylet::account(accountID_));
309 if (!sle)
310 return tefINTERNAL; // LCOV_EXCL_LINE
311
312 std::uint32_t const uOwnerCount = sle->getFieldU32(sfOwnerCount);
313
314 // The reserve that is required to create the line. Note
315 // that although the reserve increases with every item
316 // an account owns, in the case of trust lines we only
317 // *enforce* a reserve if the user owns more than two
318 // items.
319 //
320 // We do this because being able to exchange currencies,
321 // which needs trust lines, is a powerful XRPL feature.
322 // So we want to make it easy for a gateway to fund the
323 // accounts of its users without fear of being tricked.
324 //
325 // Without this logic, a gateway that wanted to have a
326 // new user use its services, would have to give that
327 // user enough XRP to cover not only the account reserve
328 // but the incremental reserve for the trust line as
329 // well. A person with no intention of using the gateway
330 // could use the extra XRP for their own purposes.
331
332 XRPAmount const reserveCreate(
333 (uOwnerCount < 2) ? XRPAmount(beast::kZero)
334 : view().fees().accountReserve(uOwnerCount + 1));
335
336 std::uint32_t const uQualityIn(bQualityIn ? ctx_.tx.getFieldU32(sfQualityIn) : 0);
337 std::uint32_t uQualityOut(bQualityOut ? ctx_.tx.getFieldU32(sfQualityOut) : 0);
338
339 if (bQualityOut && QUALITY_ONE == uQualityOut)
340 uQualityOut = 0;
341
342 bool const bSetAuth = ctx_.tx.isFlag(tfSetfAuth);
343 bool const bSetNoRipple = ctx_.tx.isFlag(tfSetNoRipple);
344 bool const bClearNoRipple = ctx_.tx.isFlag(tfClearNoRipple);
345 bool const bSetFreeze = ctx_.tx.isFlag(tfSetFreeze);
346 bool const bClearFreeze = ctx_.tx.isFlag(tfClearFreeze);
347 bool const bSetDeepFreeze = ctx_.tx.isFlag(tfSetDeepFreeze);
348 bool const bClearDeepFreeze = ctx_.tx.isFlag(tfClearDeepFreeze);
349
350 auto viewJ = ctx_.registry.get().getJournal("View");
351
352 SLE::pointer const sleDst = view().peek(keylet::account(uDstAccountID));
353
354 if (!sleDst)
355 {
356 JLOG(j_.trace()) << "Delay transaction: Destination account does not exist.";
357 return tecNO_DST;
358 }
359
360 STAmount saLimitAllow = saLimitAmount;
361 saLimitAllow.get<Issue>().account = accountID_;
362
363 SLE::pointer const sleRippleState =
364 view().peek(keylet::trustLine(accountID_, uDstAccountID, currency));
365
366 if (sleRippleState)
367 {
368 STAmount saLowBalance;
369 STAmount saLowLimit;
370 STAmount saHighBalance;
371 STAmount saHighLimit;
372 std::uint32_t uLowQualityIn = 0;
373 std::uint32_t uLowQualityOut = 0;
374 std::uint32_t uHighQualityIn = 0;
375 std::uint32_t uHighQualityOut = 0;
376 auto const& uLowAccountID = !bHigh ? accountID_ : uDstAccountID;
377 auto const& uHighAccountID = bHigh ? accountID_ : uDstAccountID;
378 SLE::ref sleLowAccount = !bHigh ? sle : sleDst;
379 SLE::ref sleHighAccount = bHigh ? sle : sleDst;
380
381 //
382 // Balances
383 //
384
385 saLowBalance = sleRippleState->getFieldAmount(sfBalance);
386 saHighBalance = -saLowBalance;
387
388 //
389 // Limits
390 //
391
392 sleRippleState->setFieldAmount(!bHigh ? sfLowLimit : sfHighLimit, saLimitAllow);
393
394 saLowLimit = !bHigh ? saLimitAllow : sleRippleState->getFieldAmount(sfLowLimit);
395 saHighLimit = bHigh ? saLimitAllow : sleRippleState->getFieldAmount(sfHighLimit);
396
397 //
398 // Quality in
399 //
400
401 if (!bQualityIn)
402 {
403 // Not setting. Just get it.
404
405 uLowQualityIn = sleRippleState->getFieldU32(sfLowQualityIn);
406 uHighQualityIn = sleRippleState->getFieldU32(sfHighQualityIn);
407 }
408 else if (uQualityIn != 0u)
409 {
410 // Setting.
411
412 sleRippleState->setFieldU32(!bHigh ? sfLowQualityIn : sfHighQualityIn, uQualityIn);
413
414 uLowQualityIn = !bHigh ? uQualityIn : sleRippleState->getFieldU32(sfLowQualityIn);
415 uHighQualityIn = bHigh ? uQualityIn : sleRippleState->getFieldU32(sfHighQualityIn);
416 }
417 else
418 {
419 // Clearing.
420
421 sleRippleState->makeFieldAbsent(!bHigh ? sfLowQualityIn : sfHighQualityIn);
422
423 uLowQualityIn = !bHigh ? 0 : sleRippleState->getFieldU32(sfLowQualityIn);
424 uHighQualityIn = bHigh ? 0 : sleRippleState->getFieldU32(sfHighQualityIn);
425 }
426
427 if (QUALITY_ONE == uLowQualityIn)
428 uLowQualityIn = 0;
429
430 if (QUALITY_ONE == uHighQualityIn)
431 uHighQualityIn = 0;
432
433 //
434 // Quality out
435 //
436
437 if (!bQualityOut)
438 {
439 // Not setting. Just get it.
440
441 uLowQualityOut = sleRippleState->getFieldU32(sfLowQualityOut);
442 uHighQualityOut = sleRippleState->getFieldU32(sfHighQualityOut);
443 }
444 else if (uQualityOut != 0u)
445 {
446 // Setting.
447
448 sleRippleState->setFieldU32(!bHigh ? sfLowQualityOut : sfHighQualityOut, uQualityOut);
449
450 uLowQualityOut = !bHigh ? uQualityOut : sleRippleState->getFieldU32(sfLowQualityOut);
451 uHighQualityOut = bHigh ? uQualityOut : sleRippleState->getFieldU32(sfHighQualityOut);
452 }
453 else
454 {
455 // Clearing.
456
457 sleRippleState->makeFieldAbsent(!bHigh ? sfLowQualityOut : sfHighQualityOut);
458
459 uLowQualityOut = !bHigh ? 0 : sleRippleState->getFieldU32(sfLowQualityOut);
460 uHighQualityOut = bHigh ? 0 : sleRippleState->getFieldU32(sfHighQualityOut);
461 }
462
463 std::uint32_t const uFlagsIn(sleRippleState->getFieldU32(sfFlags));
464 std::uint32_t uFlagsOut(uFlagsIn);
465
466 if (bSetNoRipple && !bClearNoRipple)
467 {
468 if ((bHigh ? saHighBalance : saLowBalance) >= beast::kZero)
469 {
470 uFlagsOut |= (bHigh ? lsfHighNoRipple : lsfLowNoRipple);
471 }
472 else
473 {
474 // Cannot set noRipple on a negative balance.
475 return tecNO_PERMISSION;
476 }
477 }
478 else if (bClearNoRipple && !bSetNoRipple)
479 {
480 uFlagsOut &= ~(bHigh ? lsfHighNoRipple : lsfLowNoRipple);
481 }
482
483 // Have to use lsfNoFreeze to maintain pre-deep freeze behavior
484 bool const bNoFreeze = sle->isFlag(lsfNoFreeze);
485 uFlagsOut = computeFreezeFlags(
486 uFlagsOut,
487 bHigh,
488 bNoFreeze,
489 bSetFreeze,
490 bClearFreeze,
491 bSetDeepFreeze,
492 bClearDeepFreeze);
493
494 if (QUALITY_ONE == uLowQualityOut)
495 uLowQualityOut = 0;
496
497 if (QUALITY_ONE == uHighQualityOut)
498 uHighQualityOut = 0;
499
500 bool const bLowDefRipple = sleLowAccount->isFlag(lsfDefaultRipple);
501 bool const bHighDefRipple = sleHighAccount->isFlag(lsfDefaultRipple);
502
503 bool const bLowReserveSet = (uLowQualityIn != 0u) || (uLowQualityOut != 0u) ||
504 ((uFlagsOut & lsfLowNoRipple) == 0) != bLowDefRipple ||
505 ((uFlagsOut & lsfLowFreeze) != 0u) || saLowLimit || saLowBalance > beast::kZero;
506 bool const bLowReserveClear = !bLowReserveSet;
507
508 bool const bHighReserveSet = (uHighQualityIn != 0u) || (uHighQualityOut != 0u) ||
509 ((uFlagsOut & lsfHighNoRipple) == 0) != bHighDefRipple ||
510 ((uFlagsOut & lsfHighFreeze) != 0u) || saHighLimit || saHighBalance > beast::kZero;
511 bool const bHighReserveClear = !bHighReserveSet;
512
513 bool const bDefault = bLowReserveClear && bHighReserveClear;
514
515 bool const bLowReserved = sleRippleState->isFlag(lsfLowReserve);
516 bool const bHighReserved = sleRippleState->isFlag(lsfHighReserve);
517
518 bool bReserveIncrease = false;
519
520 if (bSetAuth)
521 {
522 uFlagsOut |= (bHigh ? lsfHighAuth : lsfLowAuth);
523 }
524
525 if (bLowReserveSet && !bLowReserved)
526 {
527 // Set reserve for low account.
528 adjustOwnerCount(view(), sleLowAccount, 1, viewJ);
529 uFlagsOut |= lsfLowReserve;
530
531 if (!bHigh)
532 bReserveIncrease = true;
533 }
534
535 if (bLowReserveClear && bLowReserved)
536 {
537 // Clear reserve for low account.
538 adjustOwnerCount(view(), sleLowAccount, -1, viewJ);
539 uFlagsOut &= ~lsfLowReserve;
540 }
541
542 if (bHighReserveSet && !bHighReserved)
543 {
544 // Set reserve for high account.
545 adjustOwnerCount(view(), sleHighAccount, 1, viewJ);
546 uFlagsOut |= lsfHighReserve;
547
548 if (bHigh)
549 bReserveIncrease = true;
550 }
551
552 if (bHighReserveClear && bHighReserved)
553 {
554 // Clear reserve for high account.
555 adjustOwnerCount(view(), sleHighAccount, -1, viewJ);
556 uFlagsOut &= ~lsfHighReserve;
557 }
558
559 if (uFlagsIn != uFlagsOut)
560 sleRippleState->setFieldU32(sfFlags, uFlagsOut);
561
562 if (bDefault || badCurrency() == currency)
563 {
564 // Delete.
565
566 terResult = trustDelete(view(), sleRippleState, uLowAccountID, uHighAccountID, viewJ);
567 }
568 // Reserve is not scaled by load.
569 else if (bReserveIncrease && preFeeBalance_ < reserveCreate)
570 {
571 JLOG(j_.trace()) << "Delay transaction: Insufficent reserve to "
572 "add trust line.";
573
574 // Another transaction could provide XRP to the account and then
575 // this transaction would succeed.
576 terResult = tecINSUF_RESERVE_LINE;
577 }
578 else
579 {
580 view().update(sleRippleState);
581
582 JLOG(j_.trace()) << "Modify ripple line";
583 }
584 }
585 // Line does not exist.
586 else if (
587 !saLimitAmount && // Setting default limit.
588 (!bQualityIn || (uQualityIn == 0u)) && // Not setting quality in or
589 // setting default quality in.
590 (!bQualityOut || (uQualityOut == 0u)) && // Not setting quality out or
591 // setting default quality out.
592 (!bSetAuth))
593 {
594 JLOG(j_.trace()) << "Redundant: Setting non-existent ripple line to defaults.";
596 }
597 else if (preFeeBalance_ < reserveCreate) // Reserve is not scaled by
598 // load.
599 {
600 JLOG(j_.trace()) << "Delay transaction: Line does not exist. "
601 "Insufficent reserve to create line.";
602
603 // Another transaction could create the account and then this
604 // transaction would succeed.
605 terResult = tecNO_LINE_INSUF_RESERVE;
606 }
607 else
608 {
609 // Zero balance in currency.
610 STAmount const saBalance(Issue{currency, noAccount()});
611
612 auto const k = keylet::trustLine(accountID_, uDstAccountID, currency);
613
614 JLOG(j_.trace()) << "doTrustSet: Creating ripple line: " << to_string(k.key);
615
616 // Create a new ripple line.
617 terResult = trustCreate(
618 view(),
619 bHigh,
621 uDstAccountID,
622 k.key,
623 sle,
624 bSetAuth,
625 bSetNoRipple && !bClearNoRipple,
626 bSetFreeze && !bClearFreeze,
627 bSetDeepFreeze,
628 saBalance,
629 saLimitAllow, // Limit for who is being charged.
630 uQualityIn,
631 uQualityOut,
632 viewJ);
633 }
634
635 return terResult;
636}
637
638void
640{
641 // No transaction-specific invariants yet (future work).
642}
643
644bool
646{
647 // No transaction-specific invariants yet (future work).
648 return true;
649}
650
651} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:38
Stream trace() const
Severity stream access functions.
Definition Journal.h:291
virtual SLE::pointer peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
virtual void update(SLE::ref sle)=0
Indicate changes to a peeked SLE.
A currency issued by an account.
Definition Issue.h:13
Currency currency
Definition Issue.h:15
AccountID const & getIssuer() const
Definition Issue.h:25
A view into a ledger.
Definition ReadView.h:31
virtual Rules const & rules() const =0
Returns the tx processing rules.
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:171
constexpr TIss const & get() const
std::string getFullText() const override
Definition STAmount.cpp:636
bool native() const noexcept
Definition STAmount.h:453
AccountID const & getIssuer() const
Definition STAmount.h:498
std::shared_ptr< STLedgerEntry > const & ref
std::shared_ptr< STLedgerEntry > pointer
std::shared_ptr< STLedgerEntry const > const & const_ref
bool isFlag(std::uint32_t) const
Definition STObject.cpp:501
STAmount const & getFieldAmount(SField const &field) const
Definition STObject.cpp:647
beast::Journal const j_
Definition Transactor.h:118
ApplyView & view()
Definition Transactor.h:136
AccountID const accountID_
Definition Transactor.h:120
XRPAmount preFeeBalance_
Definition Transactor.h:121
ApplyContext & ctx_
Definition Transactor.h:116
static TER preclaim(PreclaimContext const &ctx)
Definition TrustSet.cpp:155
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
Definition TrustSet.cpp:67
TER doApply() override
Definition TrustSet.cpp:294
static NotTEC checkGranularSemantics(ReadView const &view, STTx const &tx, std::unordered_set< GranularPermissionType > const &heldGranularPermissions)
Definition TrustSet.cpp:125
static NotTEC preflight(PreflightContext const &ctx)
Definition TrustSet.cpp:73
void visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override
Inspect a single ledger entry modified by this transaction.
Definition TrustSet.cpp:639
bool finalizeInvariants(STTx const &tx, TER result, XRPAmount fee, ReadView const &view, beast::Journal const &j) override
Check transaction-specific post-conditions after all entries have been visited.
Definition TrustSet.cpp:645
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:186
Keylet trustLine(AccountID const &id0, AccountID const &id1, Currency const &currency) noexcept
The index of a trust line for a given currency.
Definition Indexes.cpp:241
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
@ terNO_DELEGATE_PERMISSION
Definition TER.h:222
@ terNO_ACCOUNT
Definition TER.h:209
bool ammEnabled(Rules const &)
Return true if required AMM amendment is enabled.
Definition AMMCore.cpp:128
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.
@ tefNO_AUTH_REQUIRED
Definition TER.h:164
@ tefINTERNAL
Definition TER.h:163
bool isLegalNet(STAmount const &value)
Definition STAmount.h:598
BaseUInt< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
Definition UintTypes.h:36
TER trustDelete(ApplyView &view, SLE::ref sleRippleState, AccountID const &uLowAccountID, AccountID const &uHighAccountID, beast::Journal j)
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:633
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:594
void adjustOwnerCount(ApplyView &view, SLE::ref sle, std::int32_t amount, beast::Journal j)
Adjust the owner count up or down.
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:28
AccountID const & noAccount()
A placeholder for empty accounts.
@ temBAD_CURRENCY
Definition TER.h:76
@ temINVALID_FLAG
Definition TER.h:97
@ temDST_IS_SRC
Definition TER.h:94
@ temDST_NEEDED
Definition TER.h:95
@ temBAD_LIMIT
Definition TER.h:80
@ temBAD_AMOUNT
Definition TER.h:75
TERSubset< CanCvtToTER > TER
Definition TER.h:634
@ tecPSEUDO_ACCOUNT
Definition TER.h:360
@ tecAMM_EMPTY
Definition TER.h:330
@ tecNO_LINE_INSUF_RESERVE
Definition TER.h:290
@ tecINSUF_RESERVE_LINE
Definition TER.h:286
@ tecINTERNAL
Definition TER.h:308
@ tecNO_LINE_REDUNDANT
Definition TER.h:291
@ tecNO_PERMISSION
Definition TER.h:303
@ tecNO_DST
Definition TER.h:288
bool isPseudoAccount(SLE::const_pointer sleAcct, std::set< SField const * > const &pseudoFieldFilter={})
Returns true if and only if sleAcct is a pseudo-account or specific pseudo-accounts in pseudoFieldFil...
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
@ tesSUCCESS
Definition TER.h:240
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:61
ReadView const & view
Definition Transactor.h:64
beast::Journal const j
Definition Transactor.h:69
State information when preflighting a tx.
Definition Transactor.h:18
beast::Journal const j
Definition Transactor.h:25