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