rippled
Loading...
Searching...
No Matches
Escrow.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpld/app/tx/detail/Escrow.h>
21
22#include <xrpld/app/misc/CredentialHelpers.h>
23#include <xrpld/app/misc/HashRouter.h>
24#include <xrpld/conditions/Condition.h>
25#include <xrpld/conditions/Fulfillment.h>
26#include <xrpld/ledger/ApplyView.h>
27#include <xrpld/ledger/View.h>
28#include <xrpl/basics/Log.h>
29#include <xrpl/basics/chrono.h>
30#include <xrpl/basics/safe_cast.h>
31#include <xrpl/protocol/Feature.h>
32#include <xrpl/protocol/Indexes.h>
33#include <xrpl/protocol/TxFlags.h>
34#include <xrpl/protocol/XRPAmount.h>
35#include <xrpl/protocol/digest.h>
36#include <xrpl/protocol/st.h>
37
38// During an EscrowFinish, the transaction must specify both
39// a condition and a fulfillment. We track whether that
40// fulfillment matches and validates the condition.
41#define SF_CF_INVALID SF_PRIVATE5
42#define SF_CF_VALID SF_PRIVATE6
43
44namespace ripple {
45
46/*
47 Escrow
48 ======
49
50 Escrow is a feature of the XRP Ledger that allows you to send conditional
51 XRP payments. These conditional payments, called escrows, set aside XRP and
52 deliver it later when certain conditions are met. Conditions to successfully
53 finish an escrow include time-based unlocks and crypto-conditions. Escrows
54 can also be set to expire if not finished in time.
55
56 The XRP set aside in an escrow is locked up. No one can use or destroy the
57 XRP until the escrow has been successfully finished or canceled. Before the
58 expiration time, only the intended receiver can get the XRP. After the
59 expiration time, the XRP can only be returned to the sender.
60
61 For more details on escrow, including examples, diagrams and more please
62 visit https://xrpl.org/escrow.html
63
64 For details on specific transactions, including fields and validation rules
65 please see:
66
67 `EscrowCreate`
68 --------------
69 See: https://xrpl.org/escrowcreate.html
70
71 `EscrowFinish`
72 --------------
73 See: https://xrpl.org/escrowfinish.html
74
75 `EscrowCancel`
76 --------------
77 See: https://xrpl.org/escrowcancel.html
78*/
79
80//------------------------------------------------------------------------------
81
88static inline bool
90{
91 return now.time_since_epoch().count() > mark;
92}
93
94TxConsequences
96{
97 return TxConsequences{ctx.tx, ctx.tx[sfAmount].xrp()};
98}
99
100NotTEC
102{
103 if (ctx.rules.enabled(fix1543) && ctx.tx.getFlags() & tfUniversalMask)
104 return temINVALID_FLAG;
105
106 if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
107 return ret;
108
109 if (!isXRP(ctx.tx[sfAmount]))
110 return temBAD_AMOUNT;
111
112 if (ctx.tx[sfAmount] <= beast::zero)
113 return temBAD_AMOUNT;
114
115 // We must specify at least one timeout value
116 if (!ctx.tx[~sfCancelAfter] && !ctx.tx[~sfFinishAfter])
117 return temBAD_EXPIRATION;
118
119 // If both finish and cancel times are specified then the cancel time must
120 // be strictly after the finish time.
121 if (ctx.tx[~sfCancelAfter] && ctx.tx[~sfFinishAfter] &&
122 ctx.tx[sfCancelAfter] <= ctx.tx[sfFinishAfter])
123 return temBAD_EXPIRATION;
124
125 if (ctx.rules.enabled(fix1571))
126 {
127 // In the absence of a FinishAfter, the escrow can be finished
128 // immediately, which can be confusing. When creating an escrow,
129 // we want to ensure that either a FinishAfter time is explicitly
130 // specified or a completion condition is attached.
131 if (!ctx.tx[~sfFinishAfter] && !ctx.tx[~sfCondition])
132 return temMALFORMED;
133 }
134
135 if (auto const cb = ctx.tx[~sfCondition])
136 {
137 using namespace ripple::cryptoconditions;
138
140
141 auto condition = Condition::deserialize(*cb, ec);
142 if (!condition)
143 {
144 JLOG(ctx.j.debug())
145 << "Malformed condition during escrow creation: "
146 << ec.message();
147 return temMALFORMED;
148 }
149
150 // Conditions other than PrefixSha256 require the
151 // "CryptoConditionsSuite" amendment:
152 if (condition->type != Type::preimageSha256 &&
153 !ctx.rules.enabled(featureCryptoConditionsSuite))
154 return temDISABLED;
155 }
156
157 return preflight2(ctx);
158}
159
160TER
162{
163 auto const sled = ctx.view.read(keylet::account(ctx.tx[sfDestination]));
164 if (!sled)
165 return tecNO_DST;
166 if (sled->isFieldPresent(sfAMMID))
167 return tecNO_PERMISSION;
168
169 return tesSUCCESS;
170}
171
172TER
174{
175 auto const closeTime = ctx_.view().info().parentCloseTime;
176
177 // Prior to fix1571, the cancel and finish times could be greater
178 // than or equal to the parent ledgers' close time.
179 //
180 // With fix1571, we require that they both be strictly greater
181 // than the parent ledgers' close time.
182 if (ctx_.view().rules().enabled(fix1571))
183 {
184 if (ctx_.tx[~sfCancelAfter] && after(closeTime, ctx_.tx[sfCancelAfter]))
185 return tecNO_PERMISSION;
186
187 if (ctx_.tx[~sfFinishAfter] && after(closeTime, ctx_.tx[sfFinishAfter]))
188 return tecNO_PERMISSION;
189 }
190 else
191 {
192 if (ctx_.tx[~sfCancelAfter])
193 {
194 auto const cancelAfter = ctx_.tx[sfCancelAfter];
195
196 if (closeTime.time_since_epoch().count() >= cancelAfter)
197 return tecNO_PERMISSION;
198 }
199
200 if (ctx_.tx[~sfFinishAfter])
201 {
202 auto const finishAfter = ctx_.tx[sfFinishAfter];
203
204 if (closeTime.time_since_epoch().count() >= finishAfter)
205 return tecNO_PERMISSION;
206 }
207 }
208
209 auto const account = ctx_.tx[sfAccount];
210 auto const sle = ctx_.view().peek(keylet::account(account));
211 if (!sle)
212 return tefINTERNAL;
213
214 // Check reserve and funds availability
215 {
216 auto const balance = STAmount((*sle)[sfBalance]).xrp();
217 auto const reserve =
218 ctx_.view().fees().accountReserve((*sle)[sfOwnerCount] + 1);
219
220 if (balance < reserve)
222
223 if (balance < reserve + STAmount(ctx_.tx[sfAmount]).xrp())
224 return tecUNFUNDED;
225 }
226
227 // Check destination account
228 {
229 auto const sled =
230 ctx_.view().read(keylet::account(ctx_.tx[sfDestination]));
231 if (!sled)
232 return tecNO_DST;
233 if (((*sled)[sfFlags] & lsfRequireDestTag) &&
234 !ctx_.tx[~sfDestinationTag])
235 return tecDST_TAG_NEEDED;
236
237 // Obeying the lsfDissalowXRP flag was a bug. Piggyback on
238 // featureDepositAuth to remove the bug.
239 if (!ctx_.view().rules().enabled(featureDepositAuth) &&
240 ((*sled)[sfFlags] & lsfDisallowXRP))
241 return tecNO_TARGET;
242 }
243
244 // Create escrow in ledger. Note that we we use the value from the
245 // sequence or ticket. For more explanation see comments in SeqProxy.h.
246 Keylet const escrowKeylet =
247 keylet::escrow(account, ctx_.tx.getSeqProxy().value());
248 auto const slep = std::make_shared<SLE>(escrowKeylet);
249 (*slep)[sfAmount] = ctx_.tx[sfAmount];
250 (*slep)[sfAccount] = account;
251 (*slep)[~sfCondition] = ctx_.tx[~sfCondition];
252 (*slep)[~sfSourceTag] = ctx_.tx[~sfSourceTag];
253 (*slep)[sfDestination] = ctx_.tx[sfDestination];
254 (*slep)[~sfCancelAfter] = ctx_.tx[~sfCancelAfter];
255 (*slep)[~sfFinishAfter] = ctx_.tx[~sfFinishAfter];
256 (*slep)[~sfDestinationTag] = ctx_.tx[~sfDestinationTag];
257
258 ctx_.view().insert(slep);
259
260 // Add escrow to sender's owner directory
261 {
262 auto page = ctx_.view().dirInsert(
263 keylet::ownerDir(account), escrowKeylet, describeOwnerDir(account));
264 if (!page)
265 return tecDIR_FULL;
266 (*slep)[sfOwnerNode] = *page;
267 }
268
269 // If it's not a self-send, add escrow to recipient's owner directory.
270 if (auto const dest = ctx_.tx[sfDestination]; dest != ctx_.tx[sfAccount])
271 {
272 auto page = ctx_.view().dirInsert(
273 keylet::ownerDir(dest), escrowKeylet, describeOwnerDir(dest));
274 if (!page)
275 return tecDIR_FULL;
276 (*slep)[sfDestinationNode] = *page;
277 }
278
279 // Deduct owner's balance, increment owner count
280 (*sle)[sfBalance] = (*sle)[sfBalance] - ctx_.tx[sfAmount];
282 ctx_.view().update(sle);
283
284 return tesSUCCESS;
285}
286
287//------------------------------------------------------------------------------
288
289static bool
291{
292 using namespace ripple::cryptoconditions;
293
295
296 auto condition = Condition::deserialize(c, ec);
297 if (!condition)
298 return false;
299
300 auto fulfillment = Fulfillment::deserialize(f, ec);
301 if (!fulfillment)
302 return false;
303
304 return validate(*fulfillment, *condition);
305}
306
307NotTEC
309{
310 if (ctx.rules.enabled(fix1543) && ctx.tx.getFlags() & tfUniversalMask)
311 return temINVALID_FLAG;
312
313 if (ctx.tx.isFieldPresent(sfCredentialIDs) &&
314 !ctx.rules.enabled(featureCredentials))
315 return temDISABLED;
316
317 if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
318 return ret;
319
320 auto const cb = ctx.tx[~sfCondition];
321 auto const fb = ctx.tx[~sfFulfillment];
322
323 // If you specify a condition, then you must also specify
324 // a fulfillment.
325 if (static_cast<bool>(cb) != static_cast<bool>(fb))
326 return temMALFORMED;
327
328 // Verify the transaction signature. If it doesn't work
329 // then don't do any more work.
330 {
331 auto const ret = preflight2(ctx);
332 if (!isTesSuccess(ret))
333 return ret;
334 }
335
336 if (cb && fb)
337 {
338 auto& router = ctx.app.getHashRouter();
339
340 auto const id = ctx.tx.getTransactionID();
341 auto const flags = router.getFlags(id);
342
343 // If we haven't checked the condition, check it
344 // now. Whether it passes or not isn't important
345 // in preflight.
346 if (!(flags & (SF_CF_INVALID | SF_CF_VALID)))
347 {
348 if (checkCondition(*fb, *cb))
349 router.setFlags(id, SF_CF_VALID);
350 else
351 router.setFlags(id, SF_CF_INVALID);
352 }
353 }
354
355 if (auto const err = credentials::checkFields(ctx); !isTesSuccess(err))
356 return err;
357
358 return tesSUCCESS;
359}
360
363{
364 XRPAmount extraFee{0};
365
366 if (auto const fb = tx[~sfFulfillment])
367 {
368 extraFee += view.fees().base * (32 + (fb->size() / 16));
369 }
370
371 return Transactor::calculateBaseFee(view, tx) + extraFee;
372}
373
374TER
376{
377 if (!ctx.view.rules().enabled(featureCredentials))
378 return Transactor::preclaim(ctx);
379
380 if (auto const err = credentials::valid(ctx, ctx.tx[sfAccount]);
381 !isTesSuccess(err))
382 return err;
383
384 return tesSUCCESS;
385}
386
387TER
389{
390 auto const k = keylet::escrow(ctx_.tx[sfOwner], ctx_.tx[sfOfferSequence]);
391 auto const slep = ctx_.view().peek(k);
392 if (!slep)
393 return tecNO_TARGET;
394
395 // If a cancel time is present, a finish operation should only succeed prior
396 // to that time. fix1571 corrects a logic error in the check that would make
397 // a finish only succeed strictly after the cancel time.
398 if (ctx_.view().rules().enabled(fix1571))
399 {
400 auto const now = ctx_.view().info().parentCloseTime;
401
402 // Too soon: can't execute before the finish time
403 if ((*slep)[~sfFinishAfter] && !after(now, (*slep)[sfFinishAfter]))
404 return tecNO_PERMISSION;
405
406 // Too late: can't execute after the cancel time
407 if ((*slep)[~sfCancelAfter] && after(now, (*slep)[sfCancelAfter]))
408 return tecNO_PERMISSION;
409 }
410 else
411 {
412 // Too soon?
413 if ((*slep)[~sfFinishAfter] &&
415 (*slep)[sfFinishAfter])
416 return tecNO_PERMISSION;
417
418 // Too late?
419 if ((*slep)[~sfCancelAfter] &&
421 (*slep)[sfCancelAfter])
422 return tecNO_PERMISSION;
423 }
424
425 // Check cryptocondition fulfillment
426 {
427 auto const id = ctx_.tx.getTransactionID();
428 auto flags = ctx_.app.getHashRouter().getFlags(id);
429
430 auto const cb = ctx_.tx[~sfCondition];
431
432 // It's unlikely that the results of the check will
433 // expire from the hash router, but if it happens,
434 // simply re-run the check.
435 if (cb && !(flags & (SF_CF_INVALID | SF_CF_VALID)))
436 {
437 auto const fb = ctx_.tx[~sfFulfillment];
438
439 if (!fb)
440 return tecINTERNAL;
441
442 if (checkCondition(*fb, *cb))
443 flags = SF_CF_VALID;
444 else
445 flags = SF_CF_INVALID;
446
447 ctx_.app.getHashRouter().setFlags(id, flags);
448 }
449
450 // If the check failed, then simply return an error
451 // and don't look at anything else.
452 if (flags & SF_CF_INVALID)
454
455 // Check against condition in the ledger entry:
456 auto const cond = (*slep)[~sfCondition];
457
458 // If a condition wasn't specified during creation,
459 // one shouldn't be included now.
460 if (!cond && cb)
462
463 // If a condition was specified during creation of
464 // the suspended payment, the identical condition
465 // must be presented again. We don't check if the
466 // fulfillment matches the condition since we did
467 // that in preflight.
468 if (cond && (cond != cb))
470 }
471
472 // NOTE: Escrow payments cannot be used to fund accounts.
473 AccountID const destID = (*slep)[sfDestination];
474 auto const sled = ctx_.view().peek(keylet::account(destID));
475 if (!sled)
476 return tecNO_DST;
477
478 if (ctx_.view().rules().enabled(featureDepositAuth))
479 {
480 if (auto err = verifyDepositPreauth(ctx_, account_, destID, sled);
481 !isTesSuccess(err))
482 return err;
483 }
484
485 AccountID const account = (*slep)[sfAccount];
486
487 // Remove escrow from owner directory
488 {
489 auto const page = (*slep)[sfOwnerNode];
490 if (!ctx_.view().dirRemove(
491 keylet::ownerDir(account), page, k.key, true))
492 {
493 JLOG(j_.fatal()) << "Unable to delete Escrow from owner.";
494 return tefBAD_LEDGER;
495 }
496 }
497
498 // Remove escrow from recipient's owner directory, if present.
499 if (auto const optPage = (*slep)[~sfDestinationNode])
500 {
501 if (!ctx_.view().dirRemove(
502 keylet::ownerDir(destID), *optPage, k.key, true))
503 {
504 JLOG(j_.fatal()) << "Unable to delete Escrow from recipient.";
505 return tefBAD_LEDGER;
506 }
507 }
508
509 // Transfer amount to destination
510 (*sled)[sfBalance] = (*sled)[sfBalance] + (*slep)[sfAmount];
511 ctx_.view().update(sled);
512
513 // Adjust source owner count
514 auto const sle = ctx_.view().peek(keylet::account(account));
516 ctx_.view().update(sle);
517
518 // Remove escrow from ledger
519 ctx_.view().erase(slep);
520
521 return tesSUCCESS;
522}
523
524//------------------------------------------------------------------------------
525
526NotTEC
528{
529 if (ctx.rules.enabled(fix1543) && ctx.tx.getFlags() & tfUniversalMask)
530 return temINVALID_FLAG;
531
532 if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
533 return ret;
534
535 return preflight2(ctx);
536}
537
538TER
540{
541 auto const k = keylet::escrow(ctx_.tx[sfOwner], ctx_.tx[sfOfferSequence]);
542 auto const slep = ctx_.view().peek(k);
543 if (!slep)
544 return tecNO_TARGET;
545
546 if (ctx_.view().rules().enabled(fix1571))
547 {
548 auto const now = ctx_.view().info().parentCloseTime;
549
550 // No cancel time specified: can't execute at all.
551 if (!(*slep)[~sfCancelAfter])
552 return tecNO_PERMISSION;
553
554 // Too soon: can't execute before the cancel time.
555 if (!after(now, (*slep)[sfCancelAfter]))
556 return tecNO_PERMISSION;
557 }
558 else
559 {
560 // Too soon?
561 if (!(*slep)[~sfCancelAfter] ||
563 (*slep)[sfCancelAfter])
564 return tecNO_PERMISSION;
565 }
566
567 AccountID const account = (*slep)[sfAccount];
568
569 // Remove escrow from owner directory
570 {
571 auto const page = (*slep)[sfOwnerNode];
572 if (!ctx_.view().dirRemove(
573 keylet::ownerDir(account), page, k.key, true))
574 {
575 JLOG(j_.fatal()) << "Unable to delete Escrow from owner.";
576 return tefBAD_LEDGER;
577 }
578 }
579
580 // Remove escrow from recipient's owner directory, if present.
581 if (auto const optPage = (*slep)[~sfDestinationNode]; optPage)
582 {
583 if (!ctx_.view().dirRemove(
584 keylet::ownerDir((*slep)[sfDestination]),
585 *optPage,
586 k.key,
587 true))
588 {
589 JLOG(j_.fatal()) << "Unable to delete Escrow from recipient.";
590 return tefBAD_LEDGER;
591 }
592 }
593
594 // Transfer amount back to owner, decrement owner count
595 auto const sle = ctx_.view().peek(keylet::account(account));
596 (*sle)[sfBalance] = (*sle)[sfBalance] + (*slep)[sfAmount];
598 ctx_.view().update(sle);
599
600 // Remove escrow from ledger
601 ctx_.view().erase(slep);
602
603 return tesSUCCESS;
604}
605
606} // namespace ripple
Stream fatal() const
Definition: Journal.h:341
Stream debug() const
Definition: Journal.h:317
virtual HashRouter & getHashRouter()=0
ApplyView & view()
Definition: ApplyContext.h:54
Application & app
Definition: ApplyContext.h:47
beast::Journal const journal
Definition: ApplyContext.h:51
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
bool dirRemove(Keylet const &directory, std::uint64_t page, uint256 const &key, bool keepRoot)
Remove an entry from a directory.
Definition: ApplyView.cpp:189
virtual void insert(std::shared_ptr< SLE > const &sle)=0
Insert a new state SLE.
std::optional< std::uint64_t > dirInsert(Keylet const &directory, uint256 const &key, std::function< void(std::shared_ptr< SLE > const &)> const &describe)
Insert an entry to a directory.
Definition: ApplyView.h:314
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
virtual void erase(std::shared_ptr< SLE > const &sle)=0
Remove a peeked SLE.
TER doApply() override
Definition: Escrow.cpp:539
static NotTEC preflight(PreflightContext const &ctx)
Definition: Escrow.cpp:527
static NotTEC preflight(PreflightContext const &ctx)
Definition: Escrow.cpp:101
TER doApply() override
Definition: Escrow.cpp:173
static TxConsequences makeTxConsequences(PreflightContext const &ctx)
Definition: Escrow.cpp:95
static TER preclaim(PreclaimContext const &ctx)
Definition: Escrow.cpp:161
static TER preclaim(PreclaimContext const &ctx)
Definition: Escrow.cpp:375
static NotTEC preflight(PreflightContext const &ctx)
Definition: Escrow.cpp:308
TER doApply() override
Definition: Escrow.cpp:388
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
Definition: Escrow.cpp:362
int getFlags(uint256 const &key)
Definition: HashRouter.cpp:94
bool setFlags(uint256 const &key, int flags)
Set the flags on a hash.
Definition: HashRouter.cpp:102
A view into a ledger.
Definition: ReadView.h:55
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 LedgerInfo const & info() const =0
Returns information about the ledger.
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:122
XRPAmount xrp() const
Definition: STAmount.cpp:273
bool isFieldPresent(SField const &field) const
Definition: STObject.cpp:454
std::uint32_t getFlags() const
Definition: STObject.cpp:507
SeqProxy getSeqProxy() const
Definition: STTx.cpp:186
uint256 getTransactionID() const
Definition: STTx.h:193
constexpr std::uint32_t value() const
Definition: SeqProxy.h:82
An immutable linear range of bytes.
Definition: Slice.h:45
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
Definition: Transactor.cpp:194
AccountID const account_
Definition: Transactor.h:91
ApplyView & view()
Definition: Transactor.h:107
static TER preclaim(PreclaimContext const &ctx)
Definition: Transactor.h:145
beast::Journal const j_
Definition: Transactor.h:89
ApplyContext & ctx_
Definition: Transactor.h:88
Class describing the consequences to the account of applying a transaction if the transaction consume...
Definition: applySteps.h:58
T message(T... args)
NotTEC checkFields(PreflightContext const &ctx)
TER valid(PreclaimContext const &ctx, AccountID const &src)
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:160
Keylet escrow(AccountID const &src, std::uint32_t seq) noexcept
An escrow entry.
Definition: Indexes.cpp:365
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition: Indexes.cpp:350
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
bool isXRP(AccountID const &c)
Definition: AccountID.h:91
@ lsfRequireDestTag
@ lsfDisallowXRP
bool isTesSuccess(TER x)
Definition: TER.h:656
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Definition: View.cpp:925
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
Definition: Transactor.cpp:82
@ tefBAD_LEDGER
Definition: TER.h:170
@ tefINTERNAL
Definition: TER.h:173
static bool adjustOwnerCount(ApplyContext &ctx, int count)
Definition: SetOracle.cpp:186
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
Definition: Transactor.cpp:134
static bool checkCondition(Slice f, Slice c)
Definition: Escrow.cpp:290
@ tecCRYPTOCONDITION_ERROR
Definition: TER.h:299
@ tecNO_DST
Definition: TER.h:277
@ tecUNFUNDED
Definition: TER.h:282
@ tecNO_TARGET
Definition: TER.h:291
@ tecDIR_FULL
Definition: TER.h:274
@ tecINTERNAL
Definition: TER.h:297
@ tecNO_PERMISSION
Definition: TER.h:292
@ tecDST_TAG_NEEDED
Definition: TER.h:296
@ tecINSUFFICIENT_RESERVE
Definition: TER.h:294
@ tesSUCCESS
Definition: TER.h:242
TER verifyDepositPreauth(ApplyContext &ctx, AccountID const &src, AccountID const &dst, std::shared_ptr< SLE > const &sleDst)
constexpr std::uint32_t tfUniversalMask
Definition: TxFlags.h:62
static bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition: Escrow.cpp:89
@ temBAD_AMOUNT
Definition: TER.h:89
@ temMALFORMED
Definition: TER.h:87
@ temBAD_EXPIRATION
Definition: TER.h:91
@ temINVALID_FLAG
Definition: TER.h:111
@ temDISABLED
Definition: TER.h:114
XRPAmount base
Definition: protocol/Fees.h:34
XRPAmount accountReserve(std::size_t ownerCount) const
Returns the account reserve given the owner count, in drops.
Definition: protocol/Fees.h:49
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:39
uint256 key
Definition: Keylet.h:40
NetClock::time_point parentCloseTime
Definition: LedgerHeader.h:42
State information when determining if a tx is likely to claim a fee.
Definition: Transactor.h:53
ReadView const & view
Definition: Transactor.h:56
State information when preflighting a tx.
Definition: Transactor.h:32
beast::Journal const j
Definition: Transactor.h:38
T time_since_epoch(T... args)