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