xrpld
Loading...
Searching...
No Matches
EscrowCancel.cpp
1#include <xrpl/tx/transactors/escrow/EscrowCancel.h>
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/ledger/ApplyView.h>
5#include <xrpl/ledger/View.h>
6#include <xrpl/ledger/entries/EscrowEntry.h>
7#include <xrpl/ledger/helpers/AccountRootHelpers.h>
8#include <xrpl/ledger/helpers/EscrowHelpers.h>
9#include <xrpl/ledger/helpers/MPTokenHelpers.h>
10#include <xrpl/ledger/helpers/RippleStateHelpers.h>
11#include <xrpl/ledger/helpers/TokenHelpers.h>
12#include <xrpl/protocol/AccountID.h>
13#include <xrpl/protocol/Concepts.h>
14#include <xrpl/protocol/Feature.h>
15#include <xrpl/protocol/Indexes.h>
16#include <xrpl/protocol/Issue.h>
17#include <xrpl/protocol/MPTIssue.h>
18#include <xrpl/protocol/Rate.h>
19#include <xrpl/protocol/SField.h>
20#include <xrpl/protocol/STAmount.h>
21#include <xrpl/protocol/STLedgerEntry.h>
22#include <xrpl/protocol/STTx.h>
23#include <xrpl/protocol/SeqProxy.h>
24#include <xrpl/protocol/TER.h>
25#include <xrpl/protocol/XRPAmount.h>
26#include <xrpl/tx/Transactor.h>
27
28#include <variant>
29
30namespace xrpl {
31
37
38template <ValidIssueType T>
39static TER
41 PreclaimContext const& ctx,
42 AccountID const& account,
43 STAmount const& amount);
44
45template <>
48 PreclaimContext const& ctx,
49 AccountID const& account,
50 STAmount const& amount)
51{
52 AccountID const& issuer = amount.getIssuer();
53 // If the issuer is the same as the account, return tecINTERNAL
54 if (issuer == account)
55 return tecINTERNAL; // LCOV_EXCL_LINE
56
57 // If the issuer has requireAuth set, check if the account is authorized
58 if (auto const ter = requireAuth(ctx.view, amount.get<Issue>(), account); !isTesSuccess(ter))
59 return ter;
60
61 return tesSUCCESS;
62}
63
64template <>
67 PreclaimContext const& ctx,
68 AccountID const& account,
69 STAmount const& amount)
70{
71 AccountID const issuer = amount.getIssuer();
72 // If the issuer is the same as the account, return tecINTERNAL
73 if (issuer == account)
74 return tecINTERNAL; // LCOV_EXCL_LINE
75
76 // If the mpt does not exist, return tecOBJECT_NOT_FOUND
77 auto const issuanceKey = keylet::mptokenIssuance(amount.get<MPTIssue>().getMptID());
78 auto const sleIssuance = ctx.view.read(issuanceKey);
79 if (!sleIssuance)
81
82 // If the issuer has requireAuth set, check if the account is
83 // authorized
84 auto const& mptIssue = amount.get<MPTIssue>();
85 if (auto const ter = requireAuth(ctx.view, mptIssue, account, AuthType::WeakAuth);
86 !isTesSuccess(ter))
87 return ter;
88
89 return tesSUCCESS;
90}
91
92TER
94{
95 if (ctx.view.rules().enabled(featureTokenEscrow))
96 {
97 auto const seqProxy = SeqProxy::rawSequence(ctx.tx[sfOfferSequence]);
98 EscrowEntryR const escrow(ctx.tx[sfOwner], seqProxy, ctx.view);
99 if (!escrow)
100 return tecNO_TARGET;
101
102 AccountID const account = (*escrow)[sfAccount];
103 STAmount const amount = (*escrow)[sfAmount];
104
105 if (!isXRP(amount))
106 {
107 if (auto const ret = std::visit(
108 [&]<typename T>(T const&) {
109 return escrowCancelPreclaimHelper<T>(ctx, account, amount);
110 },
111 amount.asset().value());
112 !isTesSuccess(ret))
113 return ret;
114 }
115 }
116 return tesSUCCESS;
117}
118
119TER
121{
122 auto const seqProxy = SeqProxy::rawSequence(ctx_.tx[sfOfferSequence]);
123 EscrowEntryW escrow(ctx_.tx[sfOwner], seqProxy, ctx_.view(), j_);
124 if (!escrow)
125 {
126 if (ctx_.view().rules().enabled(featureTokenEscrow))
127 return tecINTERNAL; // LCOV_EXCL_LINE
128
129 return tecNO_TARGET;
130 }
131
132 auto const now = ctx_.view().header().parentCloseTime;
133
134 // No cancel time specified: can't execute at all.
135 if (!(*escrow)[~sfCancelAfter])
136 return tecNO_PERMISSION;
137
138 // Too soon: can't execute before the cancel time.
139 if (!after(now, (*escrow)[sfCancelAfter]))
140 return tecNO_PERMISSION;
141
142 AccountID const account = (*escrow)[sfAccount];
143
144 // Remove escrow from owner directory
145 {
146 auto const page = (*escrow)[sfOwnerNode];
147 if (!ctx_.view().dirRemove(keylet::ownerDir(account), page, escrow.key(), true))
148 {
149 // LCOV_EXCL_START
150 JLOG(j_.fatal()) << "Unable to delete Escrow from owner.";
151 return tefBAD_LEDGER;
152 // LCOV_EXCL_STOP
153 }
154 }
155
156 // Remove escrow from recipient's owner directory, if present.
157 if (auto const optPage = (*escrow)[~sfDestinationNode]; optPage)
158 {
159 if (!ctx_.view().dirRemove(
160 keylet::ownerDir((*escrow)[sfDestination]), *optPage, escrow.key(), true))
161 {
162 // LCOV_EXCL_START
163 JLOG(j_.fatal()) << "Unable to delete Escrow from recipient.";
164 return tefBAD_LEDGER;
165 // LCOV_EXCL_STOP
166 }
167 }
168
169 auto const sle = ctx_.view().peek(keylet::account(account));
170 STAmount const amount = escrow->getFieldAmount(sfAmount);
171
172 // The return can re-create a holding the owner deleted while the escrow
173 // was pending; the removed escrow must not be counted against its reserve.
174 bool const recycleReserve = ctx_.view().rules().enabled(fixCleanup3_4_0);
175 if (recycleReserve)
176 decreaseOwnerCountForObject(ctx_.view(), sle, escrow.mutableRawSle(), 1, ctx_.journal);
177
178 // Transfer amount back to the owner
179 if (isXRP(amount))
180 {
181 (*sle)[sfBalance] = (*sle)[sfBalance] + amount;
182 }
183 else
184 {
185 if (!ctx_.view().rules().enabled(featureTokenEscrow))
186 return temDISABLED; // LCOV_EXCL_LINE
187
188 auto const issuer = amount.getIssuer();
189 bool const createAsset = account == accountID_;
190 if (auto const ret = std::visit(
191 [&]<typename T>(T const&) {
193 ctx_.getApplyViewContext(),
195 ctx_.view().rules().enabled(fixCleanup3_2_0) ? sle : escrow.mutableRawSle(),
197 amount,
198 issuer,
199 account, // sender and receiver are the same
200 account,
201 createAsset,
202 j_);
203 },
204 amount.asset().value());
205 !isTesSuccess(ret))
206 return ret; // LCOV_EXCL_LINE
207
208 // Remove escrow from issuers owner directory, if present.
209 if (auto const optPage = (*escrow)[~sfIssuerNode]; optPage)
210 {
211 if (!ctx_.view().dirRemove(keylet::ownerDir(issuer), *optPage, escrow.key(), true))
212 {
213 // LCOV_EXCL_START
214 JLOG(j_.fatal()) << "Unable to delete Escrow from recipient.";
215 return tefBAD_LEDGER;
216 // LCOV_EXCL_STOP
217 }
218 }
219 }
220
221 if (!recycleReserve)
222 decreaseOwnerCountForObject(ctx_.view(), sle, escrow.mutableRawSle(), 1, ctx_.journal);
223
224 // Remove escrow from ledger
225 escrow.erase();
226
227 return tesSUCCESS;
228}
229
230void
232{
233 // No transaction-specific invariants yet (future work).
234}
235
236bool
238 STTx const&,
239 TER,
240 XRPAmount,
241 ReadView const&,
242 beast::Journal const&)
243{
244 // No transaction-specific invariants yet (future work).
245 return true;
246}
247} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:44
void visitInvariantEntry(bool isDelete, SLE::ConstRef before, SLE::ConstRef after) override
Inspect a single ledger entry modified by this transaction.
static NotTEC preflight(PreflightContext const &ctx)
static TER preclaim(PreclaimContext const &ctx)
bool finalizeInvariants(STTx const &tx, TER result, XRPAmount fee, ReadView const &view, beast::Journal const &j) override
Check transaction-specific post-conditions after all entries have been visited.
TER doApply() override
A currency issued by an account.
Definition Issue.h:18
constexpr MPTID const & getMptID() const
Definition MPTIssue.h:43
A view into a ledger.
Definition ReadView.h:41
virtual Rules const & rules() const =0
Returns the tx processing rules.
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
bool enabled(UInt256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:182
constexpr TIss const & get() const
Asset const & asset() const
Definition STAmount.h:496
AccountID const & getIssuer() const
Definition STAmount.h:516
std::shared_ptr< STLedgerEntry const > const & ConstRef
static constexpr SeqProxy rawSequence(std::uint32_t v)
Factory function to return a sequence-based SeqProxy.
Definition SeqProxy.h:62
beast::Journal const j_
Definition Transactor.h:164
AccountID const accountID_
Definition Transactor.h:166
XRPAmount preFeeBalance_
Definition Transactor.h:167
ApplyContext & ctx_
Definition Transactor.h:162
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:403
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:220
Keylet mptokenIssuance(MPTID const &issuanceID) noexcept
Definition Indexes.cpp:567
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
bool isXRP(AccountID const &c)
Definition AccountID.h:84
TER escrowCancelPreclaimHelper< MPTIssue >(PreclaimContext const &ctx, AccountID const &account, STAmount const &amount)
@ tefBAD_LEDGER
Definition TER.h:165
TER escrowUnlockApplyHelper(ApplyViewContext ctx, Rate lockedRate, SLE::Ref sleDest, XRPAmount xrpBalance, STAmount const &amount, AccountID const &issuer, AccountID const &sender, AccountID const &receiver, bool createAsset, beast::Journal journal)
TER escrowCancelPreclaimHelper< Issue >(PreclaimContext const &ctx, AccountID const &account, STAmount const &amount)
EscrowEntry< ReadView > EscrowEntryR
Definition EscrowEntry.h:34
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:614
void decreaseOwnerCountForObject(ApplyView &view, SLE::Ref accountSle, SLE::Ref objectSle, std::uint32_t count, beast::Journal j)
Decrease owner-count fields for an existing ledger object.
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:644
Rate const kParityRate
A transfer rate signifying a 1:1 exchange.
EscrowEntry< ApplyView > EscrowEntryW
Definition EscrowEntry.h:35
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:34
static TER escrowCancelPreclaimHelper(PreclaimContext const &ctx, AccountID const &account, STAmount const &amount)
@ temDISABLED
Definition TER.h:102
bool isTesSuccess(TER x) noexcept
Definition TER.h:683
TERSubset< CanCvtToTER > TER
Definition TER.h:654
TER requireAuth(ReadView const &view, MPTIssue const &mptIssue, AccountID const &account, AuthType authType=AuthType::Legacy, std::uint8_t depth=0)
Check if the account lacks required authorization for MPT.
@ tecNO_TARGET
Definition TER.h:312
@ tecOBJECT_NOT_FOUND
Definition TER.h:334
@ tecINTERNAL
Definition TER.h:318
@ tecNO_PERMISSION
Definition TER.h:313
@ tesSUCCESS
Definition TER.h:250
UInt256 key
Definition Keylet.h:21
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:92
ReadView const & view
Definition Transactor.h:95
State information when preflighting a tx.
Definition Transactor.h:39
T visit(T... args)