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