20#include <xrpld/app/tx/detail/Escrow.h>
22#include <xrpld/app/misc/CredentialHelpers.h>
23#include <xrpld/app/misc/HashRouter.h>
24#include <xrpld/conditions/Condition.h>
25#include <xrpld/conditions/Fulfillment.h>
26#include <xrpld/ledger/ApplyView.h>
27#include <xrpld/ledger/View.h>
28#include <xrpl/basics/Log.h>
29#include <xrpl/basics/chrono.h>
30#include <xrpl/basics/safe_cast.h>
31#include <xrpl/protocol/Feature.h>
32#include <xrpl/protocol/Indexes.h>
33#include <xrpl/protocol/TxFlags.h>
34#include <xrpl/protocol/XRPAmount.h>
35#include <xrpl/protocol/digest.h>
36#include <xrpl/protocol/st.h>
41#define SF_CF_INVALID SF_PRIVATE5
42#define SF_CF_VALID SF_PRIVATE6
112 if (ctx.
tx[sfAmount] <= beast::zero)
116 if (!ctx.
tx[~sfCancelAfter] && !ctx.
tx[~sfFinishAfter])
121 if (ctx.
tx[~sfCancelAfter] && ctx.
tx[~sfFinishAfter] &&
122 ctx.
tx[sfCancelAfter] <= ctx.
tx[sfFinishAfter])
131 if (!ctx.
tx[~sfFinishAfter] && !ctx.
tx[~sfCondition])
135 if (
auto const cb = ctx.
tx[~sfCondition])
141 auto condition = Condition::deserialize(*cb, ec);
145 <<
"Malformed condition during escrow creation: "
152 if (condition->type != Type::preimageSha256 &&
166 if (sled->isFieldPresent(sfAMMID))
192 if (
ctx_.
tx[~sfCancelAfter])
194 auto const cancelAfter =
ctx_.
tx[sfCancelAfter];
196 if (closeTime.time_since_epoch().count() >= cancelAfter)
200 if (
ctx_.
tx[~sfFinishAfter])
202 auto const finishAfter =
ctx_.
tx[sfFinishAfter];
204 if (closeTime.time_since_epoch().count() >= finishAfter)
209 auto const account =
ctx_.
tx[sfAccount];
216 auto const balance =
STAmount((*sle)[sfBalance]).
xrp();
220 if (balance < reserve)
234 !
ctx_.
tx[~sfDestinationTag])
246 Keylet const escrowKeylet =
248 auto const slep = std::make_shared<SLE>(escrowKeylet);
249 (*slep)[sfAmount] =
ctx_.
tx[sfAmount];
250 (*slep)[sfAccount] = account;
251 (*slep)[~sfCondition] =
ctx_.
tx[~sfCondition];
252 (*slep)[~sfSourceTag] =
ctx_.
tx[~sfSourceTag];
253 (*slep)[sfDestination] =
ctx_.
tx[sfDestination];
254 (*slep)[~sfCancelAfter] =
ctx_.
tx[~sfCancelAfter];
255 (*slep)[~sfFinishAfter] =
ctx_.
tx[~sfFinishAfter];
256 (*slep)[~sfDestinationTag] =
ctx_.
tx[~sfDestinationTag];
266 (*slep)[sfOwnerNode] = *page;
270 if (
auto const dest =
ctx_.
tx[sfDestination]; dest !=
ctx_.
tx[sfAccount])
276 (*slep)[sfDestinationNode] = *page;
280 (*sle)[sfBalance] = (*sle)[sfBalance] -
ctx_.
tx[sfAmount];
296 auto condition = Condition::deserialize(c, ec);
300 auto fulfillment = Fulfillment::deserialize(f, ec);
304 return validate(*fulfillment, *condition);
320 auto const cb = ctx.
tx[~sfCondition];
321 auto const fb = ctx.
tx[~sfFulfillment];
325 if (
static_cast<bool>(cb) !=
static_cast<bool>(fb))
341 auto const flags = router.getFlags(
id);
346 if (!(flags & (SF_CF_INVALID | SF_CF_VALID)))
349 router.setFlags(
id, SF_CF_VALID);
351 router.setFlags(
id, SF_CF_INVALID);
366 if (
auto const fb = tx[~sfFulfillment])
368 extraFee +=
view.
fees().
base * (32 + (fb->size() / 16));
403 if ((*slep)[~sfFinishAfter] && !
after(now, (*slep)[sfFinishAfter]))
407 if ((*slep)[~sfCancelAfter] &&
after(now, (*slep)[sfCancelAfter]))
413 if ((*slep)[~sfFinishAfter] &&
415 (*slep)[sfFinishAfter])
419 if ((*slep)[~sfCancelAfter] &&
421 (*slep)[sfCancelAfter])
430 auto const cb =
ctx_.
tx[~sfCondition];
435 if (cb && !(flags & (SF_CF_INVALID | SF_CF_VALID)))
437 auto const fb =
ctx_.
tx[~sfFulfillment];
445 flags = SF_CF_INVALID;
452 if (flags & SF_CF_INVALID)
456 auto const cond = (*slep)[~sfCondition];
468 if (cond && (cond != cb))
473 AccountID const destID = (*slep)[sfDestination];
485 AccountID const account = (*slep)[sfAccount];
489 auto const page = (*slep)[sfOwnerNode];
493 JLOG(
j_.
fatal()) <<
"Unable to delete Escrow from owner.";
499 if (
auto const optPage = (*slep)[~sfDestinationNode])
504 JLOG(
j_.
fatal()) <<
"Unable to delete Escrow from recipient.";
510 (*sled)[sfBalance] = (*sled)[sfBalance] + (*slep)[sfAmount];
551 if (!(*slep)[~sfCancelAfter])
555 if (!
after(now, (*slep)[sfCancelAfter]))
561 if (!(*slep)[~sfCancelAfter] ||
563 (*slep)[sfCancelAfter])
567 AccountID const account = (*slep)[sfAccount];
571 auto const page = (*slep)[sfOwnerNode];
575 JLOG(
j_.
fatal()) <<
"Unable to delete Escrow from owner.";
581 if (
auto const optPage = (*slep)[~sfDestinationNode]; optPage)
589 JLOG(
j_.
fatal()) <<
"Unable to delete Escrow from recipient.";
596 (*sle)[sfBalance] = (*sle)[sfBalance] + (*slep)[sfAmount];
virtual HashRouter & getHashRouter()=0
beast::Journal const journal
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.
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)
static NotTEC preflight(PreflightContext const &ctx)
static TxConsequences makeTxConsequences(PreflightContext const &ctx)
static TER preclaim(PreclaimContext const &ctx)
static TER preclaim(PreclaimContext const &ctx)
static NotTEC preflight(PreflightContext const &ctx)
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
int getFlags(uint256 const &key)
bool setFlags(uint256 const &key, int flags)
Set the flags on a hash.
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.
bool isFieldPresent(SField const &field) const
std::uint32_t getFlags() const
SeqProxy getSeqProxy() const
uint256 getTransactionID() const
constexpr std::uint32_t value() const
An immutable linear range of bytes.
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
static TER preclaim(PreclaimContext const &ctx)
Class describing the consequences to the account of applying a transaction if the transaction consume...
NotTEC checkFields(PreflightContext const &ctx)
TER valid(PreclaimContext const &ctx, AccountID const &src)
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet escrow(AccountID const &src, std::uint32_t seq) noexcept
An escrow entry.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool isXRP(AccountID const &c)
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
static bool adjustOwnerCount(ApplyContext &ctx, int count)
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
static bool checkCondition(Slice f, Slice c)
@ tecCRYPTOCONDITION_ERROR
@ tecINSUFFICIENT_RESERVE
TER verifyDepositPreauth(ApplyContext &ctx, AccountID const &src, AccountID const &dst, std::shared_ptr< SLE > const &sleDst)
constexpr std::uint32_t tfUniversalMask
static bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
XRPAmount accountReserve(std::size_t ownerCount) const
Returns the account reserve given the owner count, in drops.
A pair of SHAMap key and LedgerEntryType.
State information when determining if a tx is likely to claim a fee.
State information when preflighting a tx.
T time_since_epoch(T... args)