rippled
Loading...
Searching...
No Matches
PayChan.cpp
1#include <xrpld/app/tx/detail/PayChan.h>
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/chrono.h>
5#include <xrpl/ledger/ApplyView.h>
6#include <xrpl/ledger/CredentialHelpers.h>
7#include <xrpl/ledger/View.h>
8#include <xrpl/protocol/Feature.h>
9#include <xrpl/protocol/Indexes.h>
10#include <xrpl/protocol/PayChan.h>
11#include <xrpl/protocol/PublicKey.h>
12#include <xrpl/protocol/TxFlags.h>
13#include <xrpl/protocol/XRPAmount.h>
14#include <xrpl/protocol/digest.h>
15
16namespace ripple {
17
18/*
19 PaymentChannel
20
21 Payment channels permit off-ledger checkpoints of XRP payments flowing
22 in a single direction. A channel sequesters the owner's XRP in its own
23 ledger entry. The owner can authorize the recipient to claim up to a
24 given balance by giving the receiver a signed message (off-ledger). The
25 recipient can use this signed message to claim any unpaid balance while
26 the channel remains open. The owner can top off the line as needed. If
27 the channel has not paid out all its funds, the owner must wait out a
28 delay to close the channel to give the recipient a chance to supply any
29 claims. The recipient can close the channel at any time. Any transaction
30 that touches the channel after the expiration time will close the
31 channel. The total amount paid increases monotonically as newer claims
32 are issued. When the channel is closed any remaining balance is returned
33 to the owner. Channels are intended to permit intermittent off-ledger
34 settlement of ILP trust lines as balances get substantial. For
35 bidirectional channels, a payment channel can be used in each direction.
36
37 PaymentChannelCreate
38
39 Create a unidirectional channel. The parameters are:
40 Destination
41 The recipient at the end of the channel.
42 Amount
43 The amount of XRP to deposit in the channel immediately.
44 SettleDelay
45 The amount of time everyone but the recipient must wait for a
46 superior claim.
47 PublicKey
48 The key that will sign claims against the channel.
49 CancelAfter (optional)
50 Any channel transaction that touches this channel after the
51 `CancelAfter` time will close it.
52 DestinationTag (optional)
53 Destination tags allow the different accounts inside of a Hosted
54 Wallet to be mapped back onto the Ripple ledger. The destination tag
55 tells the server to which account in the Hosted Wallet the funds are
56 intended to go to. Required if the destination has lsfRequireDestTag
57 set.
58 SourceTag (optional)
59 Source tags allow the different accounts inside of a Hosted Wallet
60 to be mapped back onto the Ripple ledger. Source tags are similar to
61 destination tags but are for the channel owner to identify their own
62 transactions.
63
64 PaymentChannelFund
65
66 Add additional funds to the payment channel. Only the channel owner may
67 use this transaction. The parameters are:
68 Channel
69 The 256-bit ID of the channel.
70 Amount
71 The amount of XRP to add.
72 Expiration (optional)
73 Time the channel closes. The transaction will fail if the expiration
74 times does not satisfy the SettleDelay constraints.
75
76 PaymentChannelClaim
77
78 Place a claim against an existing channel. The parameters are:
79 Channel
80 The 256-bit ID of the channel.
81 Balance (optional)
82 The total amount of XRP delivered after this claim is processed
83 (optional, not needed if just closing). Amount (optional) The amount of XRP
84 the signature is for (not needed if equal to Balance or just closing the
85 line). Signature (optional) Authorization for the balance above, signed by
86 the owner (optional, not needed if closing or owner is performing the
87 transaction). The signature if for the following message: CLM\0 followed by
88 the 256-bit channel ID, and a 64-bit integer drops. PublicKey (optional) The
89 public key that made the signature (optional, required if a signature is
90 present) Flags tfClose Request that the channel be closed tfRenew Request
91 that the channel's expiration be reset. Only the owner may renew a channel.
92
93*/
94
95//------------------------------------------------------------------------------
96
97static TER
99 std::shared_ptr<SLE> const& slep,
100 ApplyView& view,
101 uint256 const& key,
103{
104 AccountID const src = (*slep)[sfAccount];
105 // Remove PayChan from owner directory
106 {
107 auto const page = (*slep)[sfOwnerNode];
108 if (!view.dirRemove(keylet::ownerDir(src), page, key, true))
109 {
110 // LCOV_EXCL_START
111 JLOG(j.fatal())
112 << "Could not remove paychan from src owner directory";
113 return tefBAD_LEDGER;
114 // LCOV_EXCL_STOP
115 }
116 }
117
118 // Remove PayChan from recipient's owner directory, if present.
119 if (auto const page = (*slep)[~sfDestinationNode])
120 {
121 auto const dst = (*slep)[sfDestination];
122 if (!view.dirRemove(keylet::ownerDir(dst), *page, key, true))
123 {
124 // LCOV_EXCL_START
125 JLOG(j.fatal())
126 << "Could not remove paychan from dst owner directory";
127 return tefBAD_LEDGER;
128 // LCOV_EXCL_STOP
129 }
130 }
131
132 // Transfer amount back to owner, decrement owner count
133 auto const sle = view.peek(keylet::account(src));
134 if (!sle)
135 return tefINTERNAL; // LCOV_EXCL_LINE
136
137 XRPL_ASSERT(
138 (*slep)[sfAmount] >= (*slep)[sfBalance],
139 "ripple::closeChannel : minimum channel amount");
140 (*sle)[sfBalance] =
141 (*sle)[sfBalance] + (*slep)[sfAmount] - (*slep)[sfBalance];
142 adjustOwnerCount(view, sle, -1, j);
143 view.update(sle);
144
145 // Remove PayChan from ledger
146 view.erase(slep);
147 return tesSUCCESS;
148}
149
150//------------------------------------------------------------------------------
151
152TxConsequences
154{
155 return TxConsequences{ctx.tx, ctx.tx[sfAmount].xrp()};
156}
157
158NotTEC
160{
161 if (!isXRP(ctx.tx[sfAmount]) || (ctx.tx[sfAmount] <= beast::zero))
162 return temBAD_AMOUNT;
163
164 if (ctx.tx[sfAccount] == ctx.tx[sfDestination])
165 return temDST_IS_SRC;
166
167 if (!publicKeyType(ctx.tx[sfPublicKey]))
168 return temMALFORMED;
169
170 return tesSUCCESS;
171}
172
173TER
175{
176 auto const account = ctx.tx[sfAccount];
177 auto const sle = ctx.view.read(keylet::account(account));
178 if (!sle)
179 return terNO_ACCOUNT;
180
181 // Check reserve and funds availability
182 {
183 auto const balance = (*sle)[sfBalance];
184 auto const reserve =
185 ctx.view.fees().accountReserve((*sle)[sfOwnerCount] + 1);
186
187 if (balance < reserve)
189
190 if (balance < reserve + ctx.tx[sfAmount])
191 return tecUNFUNDED;
192 }
193
194 auto const dst = ctx.tx[sfDestination];
195
196 {
197 // Check destination account
198 auto const sled = ctx.view.read(keylet::account(dst));
199 if (!sled)
200 return tecNO_DST;
201
202 auto const flags = sled->getFlags();
203
204 // Check if they have disallowed incoming payment channels
205 if (ctx.view.rules().enabled(featureDisallowIncoming) &&
207 return tecNO_PERMISSION;
208
209 if ((flags & lsfRequireDestTag) && !ctx.tx[~sfDestinationTag])
210 return tecDST_TAG_NEEDED;
211
212 // Pseudo-accounts cannot receive payment channels, other than native
213 // to their underlying ledger object - implemented in their respective
214 // transaction types. Note, this is not amendment-gated because all
215 // writes to pseudo-account discriminator fields **are** amendment
216 // gated, hence the behaviour of this check will always match the
217 // currently active amendments.
218 if (isPseudoAccount(sled))
219 return tecNO_PERMISSION;
220 }
221
222 return tesSUCCESS;
223}
224
225TER
227{
228 auto const account = ctx_.tx[sfAccount];
229 auto const sle = ctx_.view().peek(keylet::account(account));
230 if (!sle)
231 return tefINTERNAL; // LCOV_EXCL_LINE
232
233 if (ctx_.view().rules().enabled(fixPayChanCancelAfter))
234 {
235 auto const closeTime = ctx_.view().info().parentCloseTime;
236 if (ctx_.tx[~sfCancelAfter] && after(closeTime, ctx_.tx[sfCancelAfter]))
237 return tecEXPIRED;
238 }
239
240 auto const dst = ctx_.tx[sfDestination];
241
242 // Create PayChan in ledger.
243 //
244 // Note that we we use the value from the sequence or ticket as the
245 // payChan sequence. For more explanation see comments in SeqProxy.h.
246 Keylet const payChanKeylet =
247 keylet::payChan(account, dst, ctx_.tx.getSeqValue());
248 auto const slep = std::make_shared<SLE>(payChanKeylet);
249
250 // Funds held in this channel
251 (*slep)[sfAmount] = ctx_.tx[sfAmount];
252 // Amount channel has already paid
253 (*slep)[sfBalance] = ctx_.tx[sfAmount].zeroed();
254 (*slep)[sfAccount] = account;
255 (*slep)[sfDestination] = dst;
256 (*slep)[sfSettleDelay] = ctx_.tx[sfSettleDelay];
257 (*slep)[sfPublicKey] = ctx_.tx[sfPublicKey];
258 (*slep)[~sfCancelAfter] = ctx_.tx[~sfCancelAfter];
259 (*slep)[~sfSourceTag] = ctx_.tx[~sfSourceTag];
260 (*slep)[~sfDestinationTag] = ctx_.tx[~sfDestinationTag];
261 if (ctx_.view().rules().enabled(fixIncludeKeyletFields))
262 {
263 (*slep)[sfSequence] = ctx_.tx.getSeqValue();
264 }
265
266 ctx_.view().insert(slep);
267
268 // Add PayChan to owner directory
269 {
270 auto const page = ctx_.view().dirInsert(
271 keylet::ownerDir(account),
272 payChanKeylet,
273 describeOwnerDir(account));
274 if (!page)
275 return tecDIR_FULL; // LCOV_EXCL_LINE
276 (*slep)[sfOwnerNode] = *page;
277 }
278
279 // Add PayChan to the recipient's owner directory
280 {
281 auto const page = ctx_.view().dirInsert(
282 keylet::ownerDir(dst), payChanKeylet, describeOwnerDir(dst));
283 if (!page)
284 return tecDIR_FULL; // LCOV_EXCL_LINE
285 (*slep)[sfDestinationNode] = *page;
286 }
287
288 // Deduct owner's balance, increment owner count
289 (*sle)[sfBalance] = (*sle)[sfBalance] - ctx_.tx[sfAmount];
291 ctx_.view().update(sle);
292
293 return tesSUCCESS;
294}
295
296//------------------------------------------------------------------------------
297
300{
301 return TxConsequences{ctx.tx, ctx.tx[sfAmount].xrp()};
302}
303
304NotTEC
306{
307 if (!isXRP(ctx.tx[sfAmount]) || (ctx.tx[sfAmount] <= beast::zero))
308 return temBAD_AMOUNT;
309
310 return tesSUCCESS;
311}
312
313TER
315{
316 Keylet const k(ltPAYCHAN, ctx_.tx[sfChannel]);
317 auto const slep = ctx_.view().peek(k);
318 if (!slep)
319 return tecNO_ENTRY;
320
321 AccountID const src = (*slep)[sfAccount];
322 auto const txAccount = ctx_.tx[sfAccount];
323 auto const expiration = (*slep)[~sfExpiration];
324
325 {
326 auto const cancelAfter = (*slep)[~sfCancelAfter];
327 auto const closeTime =
329 if ((cancelAfter && closeTime >= *cancelAfter) ||
330 (expiration && closeTime >= *expiration))
331 return closeChannel(
332 slep, ctx_.view(), k.key, ctx_.app.journal("View"));
333 }
334
335 if (src != txAccount)
336 // only the owner can add funds or extend
337 return tecNO_PERMISSION;
338
339 if (auto extend = ctx_.tx[~sfExpiration])
340 {
341 auto minExpiration =
343 (*slep)[sfSettleDelay];
344 if (expiration && *expiration < minExpiration)
345 minExpiration = *expiration;
346
347 if (*extend < minExpiration)
348 return temBAD_EXPIRATION;
349 (*slep)[~sfExpiration] = *extend;
350 ctx_.view().update(slep);
351 }
352
353 auto const sle = ctx_.view().peek(keylet::account(txAccount));
354 if (!sle)
355 return tefINTERNAL; // LCOV_EXCL_LINE
356
357 {
358 // Check reserve and funds availability
359 auto const balance = (*sle)[sfBalance];
360 auto const reserve =
361 ctx_.view().fees().accountReserve((*sle)[sfOwnerCount]);
362
363 if (balance < reserve)
365
366 if (balance < reserve + ctx_.tx[sfAmount])
367 return tecUNFUNDED;
368 }
369
370 // do not allow adding funds if dst does not exist
371 if (AccountID const dst = (*slep)[sfDestination];
372 !ctx_.view().read(keylet::account(dst)))
373 {
374 return tecNO_DST;
375 }
376
377 (*slep)[sfAmount] = (*slep)[sfAmount] + ctx_.tx[sfAmount];
378 ctx_.view().update(slep);
379
380 (*sle)[sfBalance] = (*sle)[sfBalance] - ctx_.tx[sfAmount];
381 ctx_.view().update(sle);
382
383 return tesSUCCESS;
384}
385
386//------------------------------------------------------------------------------
387
388bool
390{
391 return !ctx.tx.isFieldPresent(sfCredentialIDs) ||
392 ctx.rules.enabled(featureCredentials);
393}
394
400
401NotTEC
403{
404 auto const bal = ctx.tx[~sfBalance];
405 if (bal && (!isXRP(*bal) || *bal <= beast::zero))
406 return temBAD_AMOUNT;
407
408 auto const amt = ctx.tx[~sfAmount];
409 if (amt && (!isXRP(*amt) || *amt <= beast::zero))
410 return temBAD_AMOUNT;
411
412 if (bal && amt && *bal > *amt)
413 return temBAD_AMOUNT;
414
415 {
416 auto const flags = ctx.tx.getFlags();
417
418 if ((flags & tfClose) && (flags & tfRenew))
419 return temMALFORMED;
420 }
421
422 if (auto const sig = ctx.tx[~sfSignature])
423 {
424 if (!(ctx.tx[~sfPublicKey] && bal))
425 return temMALFORMED;
426
427 // Check the signature
428 // The signature isn't needed if txAccount == src, but if it's
429 // present, check it
430
431 auto const reqBalance = bal->xrp();
432 auto const authAmt = amt ? amt->xrp() : reqBalance;
433
434 if (reqBalance > authAmt)
435 return temBAD_AMOUNT;
436
437 Keylet const k(ltPAYCHAN, ctx.tx[sfChannel]);
438 if (!publicKeyType(ctx.tx[sfPublicKey]))
439 return temMALFORMED;
440
441 PublicKey const pk(ctx.tx[sfPublicKey]);
442 Serializer msg;
443 serializePayChanAuthorization(msg, k.key, authAmt);
444 if (!verify(pk, msg.slice(), *sig, /*canonical*/ true))
445 return temBAD_SIGNATURE;
446 }
447
448 if (auto const err = credentials::checkFields(ctx.tx, ctx.j);
449 !isTesSuccess(err))
450 return err;
451
452 return tesSUCCESS;
453}
454
455TER
457{
458 if (!ctx.view.rules().enabled(featureCredentials))
459 return Transactor::preclaim(ctx);
460
461 if (auto const err =
462 credentials::valid(ctx.tx, ctx.view, ctx.tx[sfAccount], ctx.j);
463 !isTesSuccess(err))
464 return err;
465
466 return tesSUCCESS;
467}
468
469TER
471{
472 Keylet const k(ltPAYCHAN, ctx_.tx[sfChannel]);
473 auto const slep = ctx_.view().peek(k);
474 if (!slep)
475 return tecNO_TARGET;
476
477 AccountID const src = (*slep)[sfAccount];
478 AccountID const dst = (*slep)[sfDestination];
479 AccountID const txAccount = ctx_.tx[sfAccount];
480
481 auto const curExpiration = (*slep)[~sfExpiration];
482 {
483 auto const cancelAfter = (*slep)[~sfCancelAfter];
484 auto const closeTime =
486 if ((cancelAfter && closeTime >= *cancelAfter) ||
487 (curExpiration && closeTime >= *curExpiration))
488 return closeChannel(
489 slep, ctx_.view(), k.key, ctx_.app.journal("View"));
490 }
491
492 if (txAccount != src && txAccount != dst)
493 return tecNO_PERMISSION;
494
495 if (ctx_.tx[~sfBalance])
496 {
497 auto const chanBalance = slep->getFieldAmount(sfBalance).xrp();
498 auto const chanFunds = slep->getFieldAmount(sfAmount).xrp();
499 auto const reqBalance = ctx_.tx[sfBalance].xrp();
500
501 if (txAccount == dst && !ctx_.tx[~sfSignature])
502 return temBAD_SIGNATURE;
503
504 if (ctx_.tx[~sfSignature])
505 {
506 PublicKey const pk((*slep)[sfPublicKey]);
507 if (ctx_.tx[sfPublicKey] != pk)
508 return temBAD_SIGNER;
509 }
510
511 if (reqBalance > chanFunds)
512 return tecUNFUNDED_PAYMENT;
513
514 if (reqBalance <= chanBalance)
515 // nothing requested
516 return tecUNFUNDED_PAYMENT;
517
518 auto const sled = ctx_.view().peek(keylet::account(dst));
519 if (!sled)
520 return tecNO_DST;
521
522 if (auto err = verifyDepositPreauth(
523 ctx_.tx, ctx_.view(), txAccount, dst, sled, ctx_.journal);
524 !isTesSuccess(err))
525 return err;
526
527 (*slep)[sfBalance] = ctx_.tx[sfBalance];
528 XRPAmount const reqDelta = reqBalance - chanBalance;
529 XRPL_ASSERT(
530 reqDelta >= beast::zero,
531 "ripple::PayChanClaim::doApply : minimum balance delta");
532 (*sled)[sfBalance] = (*sled)[sfBalance] + reqDelta;
533 ctx_.view().update(sled);
534 ctx_.view().update(slep);
535 }
536
537 if (ctx_.tx.getFlags() & tfRenew)
538 {
539 if (src != txAccount)
540 return tecNO_PERMISSION;
541 (*slep)[~sfExpiration] = std::nullopt;
542 ctx_.view().update(slep);
543 }
544
545 if (ctx_.tx.getFlags() & tfClose)
546 {
547 // Channel will close immediately if dry or the receiver closes
548 if (dst == txAccount || (*slep)[sfBalance] == (*slep)[sfAmount])
549 return closeChannel(
550 slep, ctx_.view(), k.key, ctx_.app.journal("View"));
551
552 auto const settleExpiration =
554 (*slep)[sfSettleDelay];
555
556 if (!curExpiration || *curExpiration > settleExpiration)
557 {
558 (*slep)[~sfExpiration] = settleExpiration;
559 ctx_.view().update(slep);
560 }
561 }
562
563 return tesSUCCESS;
564}
565
566} // namespace ripple
A generic endpoint for log messages.
Definition Journal.h:41
Stream fatal() const
Definition Journal.h:333
virtual beast::Journal journal(std::string const &name)=0
ApplyView & view()
Application & app
beast::Journal const journal
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:124
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.
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:300
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.
static NotTEC preflight(PreflightContext const &ctx)
Definition PayChan.cpp:402
static TER preclaim(PreclaimContext const &ctx)
Definition PayChan.cpp:456
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
Definition PayChan.cpp:396
static bool checkExtraFeatures(PreflightContext const &ctx)
Definition PayChan.cpp:389
TER doApply() override
Definition PayChan.cpp:470
static NotTEC preflight(PreflightContext const &ctx)
Definition PayChan.cpp:159
TER doApply() override
Definition PayChan.cpp:226
static TxConsequences makeTxConsequences(PreflightContext const &ctx)
Definition PayChan.cpp:153
static TER preclaim(PreclaimContext const &ctx)
Definition PayChan.cpp:174
TER doApply() override
Definition PayChan.cpp:314
static NotTEC preflight(PreflightContext const &ctx)
Definition PayChan.cpp:305
static TxConsequences makeTxConsequences(PreflightContext const &ctx)
Definition PayChan.cpp:299
A public key.
Definition PublicKey.h:43
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:111
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:465
std::uint32_t getFlags() const
Definition STObject.cpp:518
std::uint32_t getSeqValue() const
Returns the first non-zero value of (Sequence, TicketSequence).
Definition STTx.cpp:212
Slice slice() const noexcept
Definition Serializer.h:47
static TER preclaim(PreclaimContext const &ctx)
Definition Transactor.h:214
ApplyContext & ctx_
Definition Transactor.h:124
Class describing the consequences to the account of applying a transaction if the transaction consume...
Definition applySteps.h:39
T is_same_v
NotTEC checkFields(STTx const &tx, beast::Journal j)
TER valid(STTx const &tx, ReadView const &view, AccountID const &src, beast::Journal j)
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:165
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:355
Keylet payChan(AccountID const &src, AccountID const &dst, std::uint32_t seq) noexcept
A PaymentChannel.
Definition Indexes.cpp:376
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
static TER closeChannel(std::shared_ptr< SLE > const &slep, ApplyView &view, uint256 const &key, beast::Journal j)
Definition PayChan.cpp:98
bool isXRP(AccountID const &c)
Definition AccountID.h:71
constexpr std::uint32_t tfRenew
Definition TxFlags.h:115
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical=true) noexcept
Verify a signature on a message.
@ lsfRequireDestTag
@ lsfDisallowIncomingPayChan
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
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Definition View.cpp:1031
TER verifyDepositPreauth(STTx const &tx, ApplyView &view, AccountID const &src, AccountID const &dst, std::shared_ptr< SLE > const &sleDst, beast::Journal j)
void serializePayChanAuthorization(Serializer &msg, uint256 const &key, XRPAmount const &amt)
@ tefBAD_LEDGER
Definition TER.h:151
@ tefINTERNAL
Definition TER.h:154
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
@ tecNO_ENTRY
Definition TER.h:288
@ tecNO_DST
Definition TER.h:272
@ tecUNFUNDED
Definition TER.h:277
@ tecNO_TARGET
Definition TER.h:286
@ tecDIR_FULL
Definition TER.h:269
@ tecNO_PERMISSION
Definition TER.h:287
@ tecDST_TAG_NEEDED
Definition TER.h:291
@ tecUNFUNDED_PAYMENT
Definition TER.h:267
@ tecINSUFFICIENT_RESERVE
Definition TER.h:289
@ tecEXPIRED
Definition TER.h:296
@ tesSUCCESS
Definition TER.h:226
bool isTesSuccess(TER x) noexcept
Definition TER.h:659
constexpr std::uint32_t tfClose
Definition TxFlags.h:116
constexpr std::uint32_t tfPayChanClaimMask
Definition TxFlags.h:117
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:3247
@ terNO_ACCOUNT
Definition TER.h:198
TERSubset< CanCvtToTER > TER
Definition TER.h:630
bool isPseudoAccount(std::shared_ptr< SLE const > sleAcct)
Definition View.cpp:1099
@ temBAD_AMOUNT
Definition TER.h:70
@ temBAD_SIGNER
Definition TER.h:96
@ temMALFORMED
Definition TER.h:68
@ temBAD_EXPIRATION
Definition TER.h:72
@ temDST_IS_SRC
Definition TER.h:89
@ temBAD_SIGNATURE
Definition TER.h:86
XRPAmount accountReserve(std::size_t ownerCount) const
Returns the account reserve given the owner count, in drops.
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:20
uint256 key
Definition Keylet.h:21
NetClock::time_point parentCloseTime
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
T time_since_epoch(T... args)