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