rippled
CashCheck.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2017 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 <ripple/app/tx/impl/CashCheck.h>
21 #include <ripple/app/ledger/Ledger.h>
22 #include <ripple/app/paths/Flow.h>
23 #include <ripple/basics/Log.h>
24 #include <ripple/protocol/Feature.h>
25 #include <ripple/protocol/Indexes.h>
26 #include <ripple/protocol/STAccount.h>
27 #include <ripple/protocol/TER.h>
28 #include <ripple/protocol/TxFlags.h>
29 
30 #include <algorithm>
31 
32 namespace ripple {
33 
34 NotTEC
36 {
37  if (! ctx.rules.enabled (featureChecks))
38  return temDISABLED;
39 
40  NotTEC const ret {preflight1 (ctx)};
41  if (! isTesSuccess (ret))
42  return ret;
43 
44  if (ctx.tx.getFlags() & tfUniversalMask)
45  {
46  // There are no flags (other than universal) for CashCheck yet.
47  JLOG(ctx.j.warn()) << "Malformed transaction: Invalid flags set.";
48  return temINVALID_FLAG;
49  }
50 
51  // Exactly one of Amount or DeliverMin must be present.
52  auto const optAmount = ctx.tx[~sfAmount];
53  auto const optDeliverMin = ctx.tx[~sfDeliverMin];
54 
55  if (static_cast<bool>(optAmount) == static_cast<bool>(optDeliverMin))
56  {
57  JLOG(ctx.j.warn()) << "Malformed transaction: "
58  "does not specify exactly one of Amount and DeliverMin.";
59  return temMALFORMED;
60  }
61 
62  // Make sure the amount is valid.
63  STAmount const value {optAmount ? *optAmount : *optDeliverMin};
64  if (!isLegalNet (value) || value.signum() <= 0)
65  {
66  JLOG(ctx.j.warn()) << "Malformed transaction: bad amount: "
67  << value.getFullText();
68  return temBAD_AMOUNT;
69  }
70 
71  if (badCurrency() == value.getCurrency())
72  {
73  JLOG(ctx.j.warn()) <<"Malformed transaction: Bad currency.";
74  return temBAD_CURRENCY;
75  }
76 
77  return preflight2 (ctx);
78 }
79 
80 TER
82 {
83  auto const sleCheck = ctx.view.read (keylet::check (ctx.tx[sfCheckID]));
84  if (! sleCheck)
85  {
86  JLOG(ctx.j.warn()) << "Check does not exist.";
87  return tecNO_ENTRY;
88  }
89 
90  // Only cash a check with this account as the destination.
91  AccountID const dstId {(*sleCheck)[sfDestination]};
92  if (ctx.tx[sfAccount] != dstId)
93  {
94  JLOG(ctx.j.warn()) << "Cashing a check with wrong Destination.";
95  return tecNO_PERMISSION;
96  }
97  AccountID const srcId {(*sleCheck)[sfAccount]};
98  if (srcId == dstId)
99  {
100  // They wrote a check to themselves. This should be caught when
101  // the check is created, but better late than never.
102  JLOG(ctx.j.error()) << "Malformed transaction: Cashing check to self.";
103  return tecINTERNAL;
104  }
105  {
106  auto const sleSrc = ctx.view.read (keylet::account (srcId));
107  auto const sleDst = ctx.view.read (keylet::account (dstId));
108  if (!sleSrc || !sleDst)
109  {
110  // If the check exists this should never occur.
111  JLOG(ctx.j.warn())
112  << "Malformed transaction: source or destination not in ledger";
113  return tecNO_ENTRY;
114  }
115 
116  if ((sleDst->getFlags() & lsfRequireDestTag) &&
117  !sleCheck->isFieldPresent (sfDestinationTag))
118  {
119  // The tag is basically account-specific information we don't
120  // understand, but we can require someone to fill it in.
121  JLOG(ctx.j.warn())
122  << "Malformed transaction: DestinationTag required in check.";
123  return tecDST_TAG_NEEDED;
124  }
125  }
126  {
127  using duration = NetClock::duration;
128  using timepoint = NetClock::time_point;
129  auto const optExpiry = (*sleCheck)[~sfExpiration];
130 
131  // Expiration is defined in terms of the close time of the parent
132  // ledger, because we definitively know the time that it closed but
133  // we do not know the closing time of the ledger that is under
134  // construction.
135  if (optExpiry &&
136  (ctx.view.parentCloseTime() >= timepoint {duration {*optExpiry}}))
137  {
138  JLOG(ctx.j.warn()) << "Cashing a check that has already expired.";
139  return tecEXPIRED;
140  }
141  }
142  {
143  // Preflight verified exactly one of Amount or DeliverMin is present.
144  // Make sure the requested amount is reasonable.
145  STAmount const value {[] (STTx const& tx)
146  {
147  auto const optAmount = tx[~sfAmount];
148  return optAmount ? *optAmount : tx[sfDeliverMin];
149  } (ctx.tx)};
150 
151  STAmount const sendMax {(*sleCheck)[sfSendMax]};
152  Currency const currency {value.getCurrency()};
153  if (currency != sendMax.getCurrency())
154  {
155  JLOG(ctx.j.warn()) << "Check cash does not match check currency.";
156  return temMALFORMED;
157  }
158  AccountID const issuerId {value.getIssuer()};
159  if (issuerId != sendMax.getIssuer())
160  {
161  JLOG(ctx.j.warn()) << "Check cash does not match check issuer.";
162  return temMALFORMED;
163  }
164  if (value > sendMax)
165  {
166  JLOG(ctx.j.warn()) << "Check cashed for more than check sendMax.";
167  return tecPATH_PARTIAL;
168  }
169 
170  // Make sure the check owner holds at least value. If they have
171  // less than value the check cannot be cashed.
172  {
173  STAmount availableFunds {accountFunds (ctx.view,
174  (*sleCheck)[sfAccount], value, fhZERO_IF_FROZEN, ctx.j)};
175 
176  // Note that src will have one reserve's worth of additional XRP
177  // once the check is cashed, since the check's reserve will no
178  // longer be required. So, if we're dealing in XRP, we add one
179  // reserve's worth to the available funds.
180  if (value.native())
181  availableFunds += XRPAmount{ctx.view.fees().increment};
182 
183  if (value > availableFunds)
184  {
185  JLOG(ctx.j.warn())
186  << "Check cashed for more than owner's balance.";
187  return tecPATH_PARTIAL;
188  }
189  }
190 
191  // An issuer can always accept their own currency.
192  if (! value.native() && (value.getIssuer() != dstId))
193  {
194  auto const sleTrustLine = ctx.view.read (
195  keylet::line (dstId, issuerId, currency));
196  if (! sleTrustLine)
197  {
198  JLOG(ctx.j.warn())
199  << "Cannot cash check for IOU without trustline.";
200  return tecNO_LINE;
201  }
202 
203  auto const sleIssuer = ctx.view.read (keylet::account (issuerId));
204  if (! sleIssuer)
205  {
206  JLOG(ctx.j.warn())
207  << "Can't receive IOUs from non-existent issuer: "
208  << to_string (issuerId);
209  return tecNO_ISSUER;
210  }
211 
212  if ((*sleIssuer)[sfFlags] & lsfRequireAuth)
213  {
214  // Entries have a canonical representation, determined by a
215  // lexicographical "greater than" comparison employing strict
216  // weak ordering. Determine which entry we need to access.
217  bool const canonical_gt (dstId > issuerId);
218 
219  bool const is_authorized ((*sleTrustLine)[sfFlags] &
220  (canonical_gt ? lsfLowAuth : lsfHighAuth));
221 
222  if (! is_authorized)
223  {
224  JLOG(ctx.j.warn())
225  << "Can't receive IOUs from issuer without auth.";
226  return tecNO_AUTH;
227  }
228  }
229 
230  // The trustline from source to issuer does not need to
231  // be checked for freezing, since we already verified that the
232  // source has sufficient non-frozen funds available.
233 
234  // However, the trustline from destination to issuer may not
235  // be frozen.
236  if (isFrozen (ctx.view, dstId, currency, issuerId))
237  {
238  JLOG(ctx.j.warn())
239  << "Cashing a check to a frozen trustline.";
240  return tecFROZEN;
241  }
242  }
243  }
244  return tesSUCCESS;
245 }
246 
247 TER
248 CashCheck::doApply ()
249 {
250  // Flow requires that we operate on a PaymentSandbox, rather than
251  // directly on a View.
252  PaymentSandbox psb (&ctx_.view());
253 
254  uint256 const checkKey {ctx_.tx[sfCheckID]};
255  auto const sleCheck = psb.peek (keylet::check (checkKey));
256  if (! sleCheck)
257  {
258  JLOG(j_.fatal())
259  << "Precheck did not verify check's existence.";
260  return tecFAILED_PROCESSING;
261  }
262 
263  AccountID const srcId {sleCheck->getAccountID (sfAccount)};
264  auto const sleSrc = psb.peek (keylet::account (srcId));
265  auto const sleDst = psb.peek (keylet::account (account_));
266 
267  if (!sleSrc || !sleDst)
268  {
269  JLOG(ctx_.journal.fatal())
270  << "Precheck did not verify source or destination's existence.";
271  return tecFAILED_PROCESSING;
272  }
273 
274  // Preclaim already checked that source has at least the requested
275  // funds.
276  //
277  // Therefore, if this is a check written to self, (and it shouldn't be)
278  // we know they have sufficient funds to pay the check. Since they are
279  // taking the funds from their own pocket and putting it back in their
280  // pocket no balance will change.
281  //
282  // If it is not a check to self (as should be the case), then there's
283  // work to do...
284  auto viewJ = ctx_.app.journal ("View");
285  auto const optDeliverMin = ctx_.tx[~sfDeliverMin];
286  bool const doFix1623 {ctx_.view().rules().enabled (fix1623)};
287  if (srcId != account_)
288  {
289  STAmount const sendMax {sleCheck->getFieldAmount (sfSendMax)};
290 
291  // Flow() doesn't do XRP to XRP transfers.
292  if (sendMax.native())
293  {
294  // Here we need to calculate the amount of XRP sleSrc can send.
295  // The amount they have available is their balance minus their
296  // reserve.
297  //
298  // Since (if we're successful) we're about to remove an entry
299  // from src's directory, we allow them to send that additional
300  // incremental reserve amount in the transfer. Hence the -1
301  // argument.
302  STAmount const srcLiquid {xrpLiquid (psb, srcId, -1, viewJ)};
303 
304  // Now, how much do they need in order to be successful?
305  STAmount const xrpDeliver {optDeliverMin ?
306  std::max (*optDeliverMin, std::min (sendMax, srcLiquid)) :
307  ctx_.tx.getFieldAmount (sfAmount)};
308 
309  if (srcLiquid < xrpDeliver)
310  {
311  // Vote no. However the transaction might succeed if applied
312  // in a different order.
313  JLOG(j_.trace()) << "Cash Check: Insufficient XRP: "
314  << srcLiquid.getFullText()
315  << " < " << xrpDeliver.getFullText();
316  return tecUNFUNDED_PAYMENT;
317  }
318 
319  if (optDeliverMin && doFix1623)
320  // Set the DeliveredAmount metadata.
321  ctx_.deliver (xrpDeliver);
322 
323  // The source account has enough XRP so make the ledger change.
324  if (TER const ter {transferXRP (
325  psb, srcId, account_, xrpDeliver, viewJ)}; ter != tesSUCCESS)
326  {
327  // The transfer failed. Return the error code.
328  return ter;
329  }
330  }
331  else
332  {
333  // Let flow() do the heavy lifting on a check for an IOU.
334  //
335  // Note that for DeliverMin we don't know exactly how much
336  // currency we want flow to deliver. We can't ask for the
337  // maximum possible currency because there might be a gateway
338  // transfer rate to account for. Since the transfer rate cannot
339  // exceed 200%, we use 1/2 maxValue as our limit.
340  STAmount const flowDeliver {optDeliverMin ?
341  STAmount { optDeliverMin->issue(),
342  STAmount::cMaxValue / 2, STAmount::cMaxOffset } :
343  static_cast<STAmount>(ctx_.tx[sfAmount])};
344 
345  // Call the payment engine's flow() to do the actual work.
346  auto const result = flow (psb, flowDeliver, srcId, account_,
347  STPathSet{},
348  true, // default path
349  static_cast<bool>(optDeliverMin), // partial payment
350  true, // owner pays transfer fee
351  false, // offer crossing
352  boost::none,
353  sleCheck->getFieldAmount (sfSendMax),
354  viewJ);
355 
356  if (result.result() != tesSUCCESS)
357  {
358  JLOG(ctx_.journal.warn())
359  << "flow failed when cashing check.";
360  return result.result();
361  }
362 
363  // Make sure that deliverMin was satisfied.
364  if (optDeliverMin)
365  {
366  if (result.actualAmountOut < *optDeliverMin)
367  {
368  JLOG(ctx_.journal.warn()) << "flow did not produce DeliverMin.";
369  return tecPATH_PARTIAL;
370  }
371  if (doFix1623)
372  // Set the delivered_amount metadata.
373  ctx_.deliver (result.actualAmountOut);
374  }
375  }
376  }
377 
378  // Check was cashed. If not a self send (and it shouldn't be), remove
379  // check link from destination directory.
380  if (srcId != account_)
381  {
382  std::uint64_t const page {(*sleCheck)[sfDestinationNode]};
383  if (! ctx_.view().dirRemove(
384  keylet::ownerDir(account_), page, checkKey, true))
385  {
386  JLOG(j_.warn()) << "Unable to delete check from destination.";
387  return tefBAD_LEDGER;
388  }
389  }
390  // Remove check from check owner's directory.
391  {
392  std::uint64_t const page {(*sleCheck)[sfOwnerNode]};
393  if (! ctx_.view().dirRemove(
394  keylet::ownerDir(srcId), page, checkKey, true))
395  {
396  JLOG(j_.warn()) << "Unable to delete check from owner.";
397  return tefBAD_LEDGER;
398  }
399  }
400  // If we succeeded, update the check owner's reserve.
401  adjustOwnerCount (psb, sleSrc, -1, viewJ);
402 
403  // Remove check from ledger.
404  psb.erase (sleCheck);
405 
406  psb.apply (ctx_.rawView());
407  return tesSUCCESS;
408 }
409 
410 } // namespace ripple
ripple::badCurrency
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
Definition: UintTypes.cpp:123
beast::Journal::fatal
Stream fatal() const
Definition: Journal.h:312
ripple::tecFROZEN
@ tecFROZEN
Definition: TER.h:268
ripple::preflight2
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
Definition: Transactor.cpp:90
ripple::PreclaimContext::view
ReadView const & view
Definition: Transactor.h:53
ripple::fhZERO_IF_FROZEN
@ fhZERO_IF_FROZEN
Definition: View.h:56
ripple::temBAD_CURRENCY
@ temBAD_CURRENCY
Definition: TER.h:88
ripple::PreclaimContext::j
const beast::Journal j
Definition: Transactor.h:57
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:287
ripple::PaymentSandbox
A wrapper which makes credits unavailable to balances.
Definition: PaymentSandbox.h:110
ripple::isTesSuccess
bool isTesSuccess(TER x)
Definition: TER.h:501
ripple::CashCheck::preflight
static NotTEC preflight(PreflightContext const &ctx)
Definition: CashCheck.cpp:35
ripple::lsfLowAuth
@ lsfLowAuth
Definition: LedgerFormats.h:149
ripple::sfAccount
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
Definition: SField.h:460
ripple::sfFlags
const SF_U32 sfFlags(access, STI_UINT32, 2, "Flags")
Definition: SField.h:338
ripple::AccountID
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition: AccountID.h:48
ripple::tecDST_TAG_NEEDED
@ tecDST_TAG_NEEDED
Definition: TER.h:274
beast::Journal::warn
Stream warn() const
Definition: Journal.h:302
ripple::isLegalNet
bool isLegalNet(STAmount const &value)
Definition: STAmount.h:325
ripple::keylet::check
static const check_t check
Definition: Indexes.h:254
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
ripple::sfOwnerNode
const SF_U64 sfOwnerNode(access, STI_UINT64, 4, "OwnerNode")
Definition: SField.h:382
ripple::sfAmount
const SF_Amount sfAmount(access, STI_AMOUNT, 1, "Amount")
Definition: SField.h:423
ripple::ReadView::parentCloseTime
NetClock::time_point parentCloseTime() const
Returns the close time of the previous ledger.
Definition: ReadView.h:251
ripple::PreflightContext::j
const beast::Journal j
Definition: Transactor.h:39
ripple::STPathSet
Definition: STPathSet.h:297
algorithm
ripple::preflight1
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
Definition: Transactor.cpp:56
ripple::lsfHighAuth
@ lsfHighAuth
Definition: LedgerFormats.h:150
ripple::sfDestinationTag
const SF_U32 sfDestinationTag(access, STI_UINT32, 14, "DestinationTag")
Definition: SField.h:350
ripple::base_uint< 160, detail::AccountIDTag >
ripple::temINVALID_FLAG
@ temINVALID_FLAG
Definition: TER.h:109
ripple::lsfRequireAuth
@ lsfRequireAuth
Definition: LedgerFormats.h:134
ripple::tefBAD_LEDGER
@ tefBAD_LEDGER
Definition: TER.h:150
ripple::adjustOwnerCount
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:629
ripple::keylet::line
static const line_t line
Definition: Indexes.h:176
ripple::CashCheck::preclaim
static TER preclaim(PreclaimContext const &ctx)
Definition: CashCheck.cpp:81
ripple::keylet::account
static const account_t account
Definition: Indexes.h:116
ripple::sfSendMax
const SF_Amount sfSendMax(access, STI_AMOUNT, 9, "SendMax")
Definition: SField.h:431
ripple::TERSubset
Definition: TER.h:311
ripple::tecFAILED_PROCESSING
@ tecFAILED_PROCESSING
Definition: TER.h:251
ripple::sfDestinationNode
const SF_U64 sfDestinationNode(access, STI_UINT64, 9, "DestinationNode")
Definition: SField.h:387
ripple::TER
TERSubset< CanCvtToTER > TER
Definition: TER.h:477
ripple::fix1623
const uint256 fix1623
Definition: Feature.cpp:168
ripple::STAmount
Definition: STAmount.h:42
ripple::tecUNFUNDED_PAYMENT
@ tecUNFUNDED_PAYMENT
Definition: TER.h:250
beast::Journal::error
Stream error() const
Definition: Journal.h:307
ripple::tecINTERNAL
@ tecINTERNAL
Definition: TER.h:275
ripple::xrpLiquid
XRPAmount xrpLiquid(ReadView const &view, AccountID const &id, std::int32_t ownerCountAdj, beast::Journal j)
Definition: View.cpp:207
ripple::STObject::getFlags
std::uint32_t getFlags() const
Definition: STObject.cpp:439
ripple::STTx
Definition: STTx.h:43
ripple::temBAD_AMOUNT
@ temBAD_AMOUNT
Definition: TER.h:87
std::uint64_t
ripple::Rules::enabled
bool enabled(uint256 const &id) const
Returns true if a feature is enabled.
Definition: ReadView.cpp:107
ripple::tecPATH_PARTIAL
@ tecPATH_PARTIAL
Definition: TER.h:247
ripple::featureChecks
const uint256 featureChecks
Definition: Feature.cpp:165
ripple::sfExpiration
const SF_U32 sfExpiration(access, STI_UINT32, 10, "Expiration")
Definition: SField.h:346
ripple::ReadView::read
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
ripple::PreclaimContext::tx
STTx const & tx
Definition: Transactor.h:55
ripple::accountFunds
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
Definition: View.cpp:133
ripple::transferXRP
TER transferXRP(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &amount, beast::Journal j)
Definition: View.cpp:1405
ripple::lsfRequireDestTag
@ lsfRequireDestTag
Definition: LedgerFormats.h:133
std::min
T min(T... args)
ripple::PreclaimContext
State information when determining if a tx is likely to claim a fee.
Definition: Transactor.h:49
ripple::detail::ApplyViewBase::erase
void erase(std::shared_ptr< SLE > const &sle) override
Remove a peeked SLE.
Definition: ApplyViewBase.cpp:144
ripple::Currency
base_uint< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
Definition: UintTypes.h:56
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::tecNO_LINE
@ tecNO_LINE
Definition: TER.h:266
ripple::tecEXPIRED
@ tecEXPIRED
Definition: TER.h:279
ripple::sfDeliverMin
const SF_Amount sfDeliverMin(access, STI_AMOUNT, 10, "DeliverMin")
Definition: SField.h:432
ripple::temDISABLED
@ temDISABLED
Definition: TER.h:112
ripple::PaymentSandbox::apply
void apply(RawView &to)
Apply changes to base view.
Definition: PaymentSandbox.cpp:245
ripple::STAmount::issue
Issue const & issue() const
Definition: STAmount.h:156
ripple::tecNO_ISSUER
@ tecNO_ISSUER
Definition: TER.h:264
ripple::tecNO_PERMISSION
@ tecNO_PERMISSION
Definition: TER.h:270
ripple::flow
path::RippleCalc::Output flow(PaymentSandbox &view, STAmount const &deliver, AccountID const &src, AccountID const &dst, STPathSet const &paths, bool defaultPaths, bool partialPayment, bool ownerPaysTransferFee, bool offerCrossing, boost::optional< Quality > const &limitQuality, boost::optional< STAmount > const &sendMax, beast::Journal j, path::detail::FlowDebugInfo *flowDebugInfo=nullptr)
Make a payment from the src account to the dst account.
ripple::sfDestination
const SF_Account sfDestination(access, STI_ACCOUNT, 3, "Destination")
Definition: SField.h:462
ripple::sfCheckID
const SF_U256 sfCheckID(access, STI_HASH256, 24, "CheckID")
Definition: SField.h:420
ripple::detail::ApplyViewBase::peek
std::shared_ptr< SLE > peek(Keylet const &k) override
Prepare to modify the SLE associated with key.
Definition: ApplyViewBase.cpp:138
ripple::tecNO_ENTRY
@ tecNO_ENTRY
Definition: TER.h:271
ripple::temMALFORMED
@ temMALFORMED
Definition: TER.h:85
ripple::NetClock::duration
std::chrono::duration< rep, period > duration
Definition: chrono.h:52
ripple::tfUniversalMask
const std::uint32_t tfUniversalMask
Definition: TxFlags.h:50
ripple::PreflightContext::tx
STTx const & tx
Definition: Transactor.h:36
std::max
T max(T... args)
ripple::PreflightContext
State information when preflighting a tx.
Definition: Transactor.h:32
ripple::tecNO_AUTH
@ tecNO_AUTH
Definition: TER.h:265
ripple::PreflightContext::rules
const Rules rules
Definition: Transactor.h:37
ripple::NetClock::time_point
std::chrono::time_point< NetClock > time_point
Definition: chrono.h:53
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:219
ripple::isFrozen
bool isFrozen(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer)
Definition: View.cpp:68
ripple::NotTEC
TERSubset< CanCvtToNotTEC > NotTEC
Definition: TER.h:461