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