20#include <xrpld/app/misc/HashRouter.h> 
   21#include <xrpld/app/tx/detail/Escrow.h> 
   22#include <xrpld/app/tx/detail/MPTokenAuthorize.h> 
   23#include <xrpld/conditions/Condition.h> 
   24#include <xrpld/conditions/Fulfillment.h> 
   26#include <xrpl/basics/Log.h> 
   27#include <xrpl/basics/chrono.h> 
   28#include <xrpl/ledger/ApplyView.h> 
   29#include <xrpl/ledger/CredentialHelpers.h> 
   30#include <xrpl/ledger/View.h> 
   31#include <xrpl/protocol/Feature.h> 
   32#include <xrpl/protocol/Indexes.h> 
   33#include <xrpl/protocol/MPTAmount.h> 
   34#include <xrpl/protocol/TxFlags.h> 
   35#include <xrpl/protocol/XRPAmount.h> 
   84    auto const amount = ctx.
tx[sfAmount];
 
 
   88template <Val
idIssueType T>
 
   97    if (amount.
native() || amount <= beast::zero)
 
 
  113    auto const amount = ctx.
tx[sfAmount];
 
  114    if (amount.native() || amount.mpt() > 
MPTAmount{maxMPTokenAmount} ||
 
  115        amount <= beast::zero)
 
 
  131                [&]<
typename T>(T 
const&) {
 
  132                    return escrowCreatePreflightHelper<T>(ctx);
 
  134                amount.asset().value());
 
  140        if (amount <= beast::zero)
 
  145    if (!ctx.
tx[~sfCancelAfter] && !ctx.
tx[~sfFinishAfter])
 
  150    if (ctx.
tx[~sfCancelAfter] && ctx.
tx[~sfFinishAfter] &&
 
  151        ctx.
tx[sfCancelAfter] <= ctx.
tx[sfFinishAfter])
 
  158    if (!ctx.
tx[~sfFinishAfter] && !ctx.
tx[~sfCondition])
 
  161    if (
auto const cb = ctx.
tx[~sfCondition])
 
  167        auto condition = Condition::deserialize(*cb, ec);
 
  171                << 
"Malformed condition during escrow creation: " 
  178        if (condition->type != Type::preimageSha256 &&
 
 
  186template <Val
idIssueType T>
 
  204    if (issuer == account)
 
  215    auto const sleRippleState =
 
  220    STAmount const balance = (*sleRippleState)[sfBalance];
 
  223    if (balance > beast::zero && issuer < account)
 
  227    if (balance < beast::zero && issuer > account)
 
  257    if (spendableAmount <= beast::zero)
 
  262    if (spendableAmount < amount)
 
  266    if (!
canAdd(spendableAmount, amount))
 
 
  282    if (issuer == account)
 
  286    auto const issuanceKey =
 
  288    auto const sleIssuance = ctx.
view.
read(issuanceKey);
 
  298    if (sleIssuance->getAccountID(sfIssuer) != issuer)
 
  342    if (spendableAmount <= beast::zero)
 
  347    if (spendableAmount < amount)
 
 
  377                [&]<
typename T>(T 
const&) {
 
  378                    return escrowCreatePreclaimHelper<T>(
 
  379                        ctx, account, dest, amount);
 
  381                amount.asset().value());
 
 
  388template <Val
idIssueType T>
 
  407    if (issuer == sender)
 
 
  432    if (issuer == sender)
 
 
  479            !
ctx_.
tx[~sfDestinationTag])
 
  493    (*slep)[sfAmount] = amount;
 
  495    (*slep)[~sfCondition] = 
ctx_.
tx[~sfCondition];
 
  496    (*slep)[~sfSourceTag] = 
ctx_.
tx[~sfSourceTag];
 
  497    (*slep)[sfDestination] = 
ctx_.
tx[sfDestination];
 
  498    (*slep)[~sfCancelAfter] = 
ctx_.
tx[~sfCancelAfter];
 
  499    (*slep)[~sfFinishAfter] = 
ctx_.
tx[~sfFinishAfter];
 
  500    (*slep)[~sfDestinationTag] = 
ctx_.
tx[~sfDestinationTag];
 
  511            (*slep)[sfTransferRate] = xferRate.value;
 
  524        (*slep)[sfOwnerNode] = *page;
 
  535        (*slep)[sfDestinationNode] = *page;
 
  541    AccountID const issuer = amount.getIssuer();
 
  542    if (!
isXRP(amount) && issuer != 
account_ && issuer != dest &&
 
  549        (*slep)[sfIssuerNode] = *page;
 
  554        (*sle)[sfBalance] = (*sle)[sfBalance] - amount;
 
  558                [&]<
typename T>(T 
const&) {
 
  559                    return escrowLockApplyHelper<T>(
 
  562                amount.asset().value());
 
 
  584    auto condition = Condition::deserialize(c, ec);
 
  588    auto fulfillment = Fulfillment::deserialize(f, ec);
 
  592    return validate(*fulfillment, *condition);
 
 
  605    auto const cb = ctx.
tx[~sfCondition];
 
  606    auto const fb = ctx.
tx[~sfFulfillment];
 
  610    if (
static_cast<bool>(cb) != 
static_cast<bool>(fb))
 
 
  619    auto const cb = ctx.
tx[~sfCondition];
 
  620    auto const fb = ctx.
tx[~sfFulfillment];
 
  627        auto const flags = router.getFlags(
id);
 
 
  653    if (
auto const fb = tx[~sfFulfillment])
 
  655        extraFee += 
view.
fees().
base * (32 + (fb->size() / 16));
 
 
  661template <Val
idIssueType T>
 
  705    auto const issuanceKey =
 
  707    auto const sleIssuance = ctx.
view.
read(issuanceKey);
 
 
  744        AccountID const dest = (*slep)[sfDestination];
 
  745        STAmount const amount = (*slep)[sfAmount];
 
  750                    [&]<
typename T>(T 
const&) {
 
  751                        return escrowFinishPreclaimHelper<T>(ctx, dest, amount);
 
 
  761template <Val
idIssueType T>
 
  790    bool const recvLow = issuer > receiver;
 
  791    bool const senderIssuer = issuer == sender;
 
  792    bool const receiverIssuer = issuer == receiver;
 
  793    bool const issuerHigh = issuer > receiver;
 
  801    if (!view.
exists(trustLineKey) && createAsset && !receiverIssuer)
 
  804        if (
std::uint32_t const ownerCount = {sleDest->at(sfOwnerCount)};
 
  805            xrpBalance < view.
fees().accountReserve(ownerCount + 1))
 
  807            JLOG(journal.
trace()) << 
"Trust line does not exist. " 
  808                                     "Insufficent reserve to create line.";
 
  830                Issue(currency, receiver),      
 
  843    if (!view.
exists(trustLineKey) && !receiverIssuer)
 
  848    if (xferRate < lockedRate)
 
  849        lockedRate = xferRate;
 
  860    auto finalAmt = amount;
 
  861    if ((!senderIssuer && !receiverIssuer) && lockedRate != 
parityRate)
 
  864        auto const xferFee = amount.
value() -
 
  867        finalAmt = amount.
value() - xferFee;
 
  874        auto const sleRippleState = view.
peek(trustLineKey);
 
  880        STAmount const lineLimit = sleRippleState->getFieldAmount(
 
  881            issuerHigh ? sfLowLimit : sfHighLimit);
 
  883        STAmount lineBalance = sleRippleState->getFieldAmount(sfBalance);
 
  890        lineBalance += finalAmt;
 
  893        if (lineLimit < lineBalance)
 
  901            rippleCredit(view, issuer, receiver, finalAmt, 
true, journal);
 
 
  922    bool const senderIssuer = issuer == sender;
 
  923    bool const receiverIssuer = issuer == receiver;
 
  925    auto const mptID = amount.
get<
MPTIssue>().getMptID();
 
  928        createAsset && !receiverIssuer)
 
  930        if (
std::uint32_t const ownerCount = {sleDest->at(sfOwnerCount)};
 
  931            xrpBalance < view.
fees().accountReserve(ownerCount + 1))
 
  953    if (xferRate < lockedRate)
 
  954        lockedRate = xferRate;
 
  965    auto finalAmt = amount;
 
  966    if ((!senderIssuer && !receiverIssuer) && lockedRate != 
parityRate)
 
  969        auto const xferFee = amount.
value() -
 
  972        finalAmt = amount.
value() - xferFee;
 
  979        view.
rules().
enabled(fixTokenEscrowV1) ? amount : finalAmt,
 
 
 1001    if ((*slep)[~sfFinishAfter] && !
after(now, (*slep)[sfFinishAfter]))
 
 1005    if ((*slep)[~sfCancelAfter] && 
after(now, (*slep)[sfCancelAfter]))
 
 1013        auto const cb = 
ctx_.
tx[~sfCondition];
 
 1021            auto const fb = 
ctx_.
tx[~sfFulfillment];
 
 1041        auto const cond = (*slep)[~sfCondition];
 
 1053        if (cond && (cond != cb))
 
 1058    AccountID const destID = (*slep)[sfDestination];
 
 1071    AccountID const account = (*slep)[sfAccount];
 
 1075        auto const page = (*slep)[sfOwnerNode];
 
 1080            JLOG(
j_.
fatal()) << 
"Unable to delete Escrow from owner.";
 
 1087    if (
auto const optPage = (*slep)[~sfDestinationNode])
 
 1093            JLOG(
j_.
fatal()) << 
"Unable to delete Escrow from recipient.";
 
 1099    STAmount const amount = slep->getFieldAmount(sfAmount);
 
 1102        (*sled)[sfBalance] = (*sled)[sfBalance] + amount;
 
 1108        Rate lockedRate = slep->isFieldPresent(sfTransferRate)
 
 1112        bool const createAsset = destID == 
account_;
 
 1114                [&]<
typename T>(T 
const&) {
 
 1115                    return escrowUnlockApplyHelper<T>(
 
 1132        if (
auto const optPage = (*slep)[~sfIssuerNode]; optPage)
 
 1138                JLOG(
j_.
fatal()) << 
"Unable to delete Escrow from recipient.";
 
 
 1165template <Val
idIssueType T>
 
 1181    if (issuer == account)
 
 
 1201    if (issuer == account)
 
 1205    auto const issuanceKey =
 
 1207    auto const sleIssuance = ctx.
view.
read(issuanceKey);
 
 1214    if (
auto const ter =
 
 
 1228        auto const slep = ctx.
view.
read(k);
 
 1232        AccountID const account = (*slep)[sfAccount];
 
 1233        STAmount const amount = (*slep)[sfAmount];
 
 1238                    [&]<
typename T>(T 
const&) {
 
 1239                        return escrowCancelPreclaimHelper<T>(
 
 1240                            ctx, account, amount);
 
 
 1266    if (!(*slep)[~sfCancelAfter])
 
 1270    if (!
after(now, (*slep)[sfCancelAfter]))
 
 1273    AccountID const account = (*slep)[sfAccount];
 
 1277        auto const page = (*slep)[sfOwnerNode];
 
 1282            JLOG(
j_.
fatal()) << 
"Unable to delete Escrow from owner.";
 
 1289    if (
auto const optPage = (*slep)[~sfDestinationNode]; optPage)
 
 1298            JLOG(
j_.
fatal()) << 
"Unable to delete Escrow from recipient.";
 
 1305    STAmount const amount = slep->getFieldAmount(sfAmount);
 
 1309        (*sle)[sfBalance] = (*sle)[sfBalance] + amount;
 
 1316        bool const createAsset = account == 
account_;
 
 1318                [&]<
typename T>(T 
const&) {
 
 1319                    return escrowUnlockApplyHelper<T>(
 
 1336        if (
auto const optPage = (*slep)[~sfIssuerNode]; optPage)
 
 1342                JLOG(
j_.
fatal()) << 
"Unable to delete Escrow from recipient.";
 
 
A generic endpoint for log messages.
 
Stream trace() const
Severity stream access functions.
 
virtual HashRouter & getHashRouter()=0
 
beast::Journal const journal
 
Writeable view to a ledger, for applying a transaction.
 
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.
 
constexpr value_type const & value() const
 
static NotTEC preflight(PreflightContext const &ctx)
 
static TER preclaim(PreclaimContext 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 NotTEC preflightSigValidated(PreflightContext const &ctx)
 
static bool checkExtraFeatures(PreflightContext const &ctx)
 
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
 
HashRouterFlags getFlags(uint256 const &key)
 
bool setFlags(uint256 const &key, HashRouterFlags flags)
Set the flags on a hash.
 
A currency issued by an account.
 
constexpr MPTID const & getMptID() const
 
static TER createMPToken(ApplyView &view, MPTID const &mptIssuanceID, AccountID const &account, std::uint32_t const flags)
 
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 bool exists(Keylet const &k) const =0
Determine if a state item exists.
 
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.
 
constexpr bool holds() const noexcept
 
Asset const & asset() const
 
constexpr TIss const & get() const
 
void setIssuer(AccountID const &uIssuer)
 
Currency const & getCurrency() const
 
STAmount const & value() const noexcept
 
AccountID const & getIssuer() const
 
Issue const & issue() const
 
bool native() const noexcept
 
bool isFieldPresent(SField const &field) const
 
std::uint32_t getSeqValue() const
Returns the first non-zero value of (Sequence, TicketSequence).
 
uint256 getTransactionID() const
 
An immutable linear range of bytes.
 
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
 
Class describing the consequences to the account of applying a transaction if the transaction consume...
 
NotTEC checkFields(STTx const &tx, beast::Journal j)
 
TER valid(STTx const &tx, ReadView const &view, AccountID const &src, beast::Journal j)
 
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
 
Keylet line(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
 
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
 
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.
 
AccountID const & noAccount()
A placeholder for empty accounts.
 
TER escrowFinishPreclaimHelper< Issue >(PreclaimContext const &ctx, AccountID const &dest, STAmount const &amount)
 
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
 
TER escrowCreatePreclaimHelper< MPTIssue >(PreclaimContext const &ctx, AccountID const &account, AccountID const &dest, STAmount const &amount)
 
bool isXRP(AccountID const &c)
 
TER rippleLockEscrowMPT(ApplyView &view, AccountID const &uGrantorID, STAmount const &saAmount, beast::Journal j)
 
static TER escrowFinishPreclaimHelper(PreclaimContext const &ctx, AccountID const &dest, STAmount const &amount)
 
bool canAdd(STAmount const &amt1, STAmount const &amt2)
Safely checks if two STAmount values can be added without overflow, underflow, or precision loss.
 
TER escrowLockApplyHelper< Issue >(ApplyView &view, AccountID const &issuer, AccountID const &sender, STAmount const &amount, beast::Journal journal)
 
bool isDeepFrozen(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer)
 
@ lsfAllowTrustLineLocking
 
TER escrowCancelPreclaimHelper< MPTIssue >(PreclaimContext const &ctx, AccountID const &account, STAmount const &amount)
 
void adjustOwnerCount(ApplyView &view, std::shared_ptr< SLE > const &sle, std::int32_t amount, beast::Journal j)
Adjust the owner count up or down.
 
static TER escrowLockApplyHelper(ApplyView &view, AccountID const &issuer, AccountID const &sender, STAmount const &amount, beast::Journal journal)
 
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
 
STAmount divideRound(STAmount const &amount, Rate const &rate, bool roundUp)
 
TER verifyDepositPreauth(STTx const &tx, ApplyView &view, AccountID const &src, AccountID const &dst, std::shared_ptr< SLE > const &sleDst, beast::Journal j)
 
bool isFrozen(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer)
 
TER rippleUnlockEscrowMPT(ApplyView &view, AccountID const &uGrantorID, AccountID const &uGranteeID, STAmount const &netAmount, STAmount const &grossAmount, beast::Journal j)
 
TER requireAuth(ReadView const &view, Issue const &issue, AccountID const &account, AuthType authType=AuthType::Legacy)
Check if the account lacks required authorization.
 
constexpr HashRouterFlags SF_CF_VALID
 
TER escrowCreatePreclaimHelper< Issue >(PreclaimContext const &ctx, AccountID const &account, AccountID const &dest, STAmount const &amount)
 
TER canTransfer(ReadView const &view, MPTIssue const &mptIssue, AccountID const &from, AccountID const &to)
Check if the destination account is allowed to receive MPT.
 
static bool checkCondition(Slice f, Slice c)
 
TER escrowUnlockApplyHelper< MPTIssue >(ApplyView &view, Rate lockedRate, std::shared_ptr< SLE > const &sleDest, STAmount const &xrpBalance, STAmount const &amount, AccountID const &issuer, AccountID const &sender, AccountID const &receiver, bool createAsset, beast::Journal journal)
 
static NotTEC escrowCreatePreflightHelper(PreflightContext const &ctx)
 
Rate transferRate(ReadView const &view, AccountID const &issuer)
Returns IOU issuer transfer fee as Rate.
 
static TER escrowCancelPreclaimHelper(PreclaimContext const &ctx, AccountID const &account, STAmount const &amount)
 
@ tecCRYPTOCONDITION_ERROR
 
@ tecNO_LINE_INSUF_RESERVE
 
@ tecINSUFFICIENT_RESERVE
 
TER rippleCredit(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, bool bCheckIssuer, beast::Journal j)
Calls static rippleCreditIOU if saAmount represents Issue.
 
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
 
constexpr HashRouterFlags SF_CF_INVALID
 
NotTEC escrowCreatePreflightHelper< MPTIssue >(PreflightContext const &ctx)
 
bool isTesSuccess(TER x) noexcept
 
TER escrowFinishPreclaimHelper< MPTIssue >(PreclaimContext const &ctx, AccountID const &dest, STAmount const &amount)
 
NotTEC escrowCreatePreflightHelper< Issue >(PreflightContext const &ctx)
 
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
 
TER trustCreate(ApplyView &view, bool const bSrcHigh, AccountID const &uSrcAccountID, AccountID const &uDstAccountID, uint256 const &uIndex, SLE::ref sleAccount, bool const bAuth, bool const bNoRipple, bool const bFreeze, bool bDeepFreeze, STAmount const &saBalance, STAmount const &saLimit, std::uint32_t uSrcQualityIn, std::uint32_t uSrcQualityOut, beast::Journal j)
Create a trust line.
 
TER escrowCancelPreclaimHelper< Issue >(PreclaimContext const &ctx, AccountID const &account, STAmount const &amount)
 
TER escrowLockApplyHelper< MPTIssue >(ApplyView &view, AccountID const &issuer, AccountID const &sender, STAmount const &amount, beast::Journal journal)
 
static TER escrowUnlockApplyHelper(ApplyView &view, Rate lockedRate, std::shared_ptr< SLE > const &sleDest, STAmount const &xrpBalance, STAmount const &amount, AccountID const &issuer, AccountID const &sender, AccountID const &receiver, bool createAsset, beast::Journal journal)
 
bool isPseudoAccount(std::shared_ptr< SLE const > sleAcct)
 
TERSubset< CanCvtToNotTEC > NotTEC
 
TER escrowUnlockApplyHelper< Issue >(ApplyView &view, Rate lockedRate, std::shared_ptr< SLE > const &sleDest, STAmount const &xrpBalance, STAmount const &amount, AccountID const &issuer, AccountID const &sender, AccountID const &receiver, bool createAsset, beast::Journal journal)
 
Rate const parityRate
A transfer rate signifying a 1:1 exchange.
 
static TER escrowCreatePreclaimHelper(PreclaimContext const &ctx, AccountID const &account, AccountID const &dest, STAmount const &amount)
 
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.
 
Represents a transfer rate.