rippled
Loading...
Searching...
No Matches
TestHelpers.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2023 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 <test/jtx/TestHelpers.h>
21#include <test/jtx/offer.h>
22#include <test/jtx/owners.h>
23
24#include <xrpl/protocol/TxFlags.h>
25
26namespace ripple {
27namespace test {
28namespace jtx {
29
30// Functions used in debugging
32getAccountOffers(Env& env, AccountID const& acct, bool current)
33{
34 Json::Value jv;
35 jv[jss::account] = to_string(acct);
36 return env.rpc("json", "account_offers", to_string(jv))[jss::result];
37}
38
40getAccountLines(Env& env, AccountID const& acctId)
41{
42 Json::Value jv;
43 jv[jss::account] = to_string(acctId);
44 return env.rpc("json", "account_lines", to_string(jv))[jss::result];
45}
46
47bool
48checkArraySize(Json::Value const& val, unsigned int size)
49{
50 return val.isArray() && val.size() == size;
51}
52
54ownerCount(Env const& env, Account const& account)
55{
56 return env.ownerCount(account);
57}
58
59/* Path finding */
60/******************************************************************************/
61void
62stpath_append_one(STPath& st, Account const& account)
63{
65}
66
67void
69{
70 st.push_back(pe);
71}
72
73bool
74equal(STAmount const& sa1, STAmount const& sa2)
75{
76 return sa1 == sa2 && sa1.issue().account == sa2.issue().account;
77}
78
79// Issue path element
81IPE(Issue const& iss)
82{
83 return STPathElement(
85 xrpAccount(),
86 iss.currency,
87 iss.account);
88}
89
90/******************************************************************************/
91
93txfee(Env const& env, std::uint16_t n)
94{
95 return env.current()->fees().base * n;
96}
97
99xrpMinusFee(Env const& env, std::int64_t xrpAmount)
100{
101 auto feeDrops = env.current()->fees().base;
102 return drops(dropsPerXRP * xrpAmount - feeDrops);
103};
104
105[[nodiscard]] bool
107 Env& env,
108 AccountID const& account,
109 STAmount const& value,
110 bool defaultLimits)
111{
112 if (auto const sle = env.le(keylet::line(account, value.issue())))
113 {
114 Issue const issue = value.issue();
115 bool const accountLow = account < issue.account;
116
117 bool expectDefaultTrustLine = true;
118 if (defaultLimits)
119 {
120 STAmount low{issue};
121 STAmount high{issue};
122
123 low.setIssuer(accountLow ? account : issue.account);
124 high.setIssuer(accountLow ? issue.account : account);
125
126 expectDefaultTrustLine = sle->getFieldAmount(sfLowLimit) == low &&
127 sle->getFieldAmount(sfHighLimit) == high;
128 }
129
130 auto amount = sle->getFieldAmount(sfBalance);
131 amount.setIssuer(value.issue().account);
132 if (!accountLow)
133 amount.negate();
134 return amount == value && expectDefaultTrustLine;
135 }
136 return false;
137}
138
139[[nodiscard]] bool
141 Env& env,
142 AccountID const& account,
143 None const&,
144 Issue const& issue)
145{
146 return !env.le(keylet::line(account, issue));
147}
148
149[[nodiscard]] bool
151 Env& env,
152 AccountID const& account,
153 None const&,
154 MPTIssue const& mptIssue)
155{
156 return !env.le(keylet::mptoken(mptIssue.getMptID(), account));
157}
158
159[[nodiscard]] bool
160expectHolding(Env& env, AccountID const& account, None const& value)
161{
162 return std::visit(
163 [&](auto const& issue) {
164 return expectHolding(env, account, value, issue);
165 },
166 value.asset.value());
167}
168
169[[nodiscard]] bool
171 Env& env,
172 AccountID const& account,
173 std::uint16_t size,
174 std::vector<Amounts> const& toMatch)
175{
176 std::uint16_t cnt = 0;
177 std::uint16_t matched = 0;
179 *env.current(), account, [&](std::shared_ptr<SLE const> const& sle) {
180 if (!sle)
181 return false;
182 if (sle->getType() == ltOFFER)
183 {
184 ++cnt;
185 if (std::find_if(
186 toMatch.begin(), toMatch.end(), [&](auto const& a) {
187 return a.in == sle->getFieldAmount(sfTakerPays) &&
188 a.out == sle->getFieldAmount(sfTakerGets);
189 }) != toMatch.end())
190 ++matched;
191 }
192 return true;
193 });
194 return size == cnt && matched == toMatch.size();
195}
196
198ledgerEntryRoot(Env& env, Account const& acct)
199{
200 Json::Value jvParams;
201 jvParams[jss::ledger_index] = "current";
202 jvParams[jss::account_root] = acct.human();
203 return env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result];
204}
205
208 Env& env,
209 Account const& acct_a,
210 Account const& acct_b,
211 std::string const& currency)
212{
213 Json::Value jvParams;
214 jvParams[jss::ledger_index] = "current";
215 jvParams[jss::ripple_state][jss::currency] = currency;
216 jvParams[jss::ripple_state][jss::accounts] = Json::arrayValue;
217 jvParams[jss::ripple_state][jss::accounts].append(acct_a.human());
218 jvParams[jss::ripple_state][jss::accounts].append(acct_b.human());
219 return env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result];
220}
221
223accountBalance(Env& env, Account const& acct)
224{
225 auto const jrr = ledgerEntryRoot(env, acct);
226 return jrr[jss::node][sfBalance.fieldName];
227}
228
229[[nodiscard]] bool
231 Env& env,
232 Account const& acct,
233 STAmount const& expectedValue)
234{
235 return accountBalance(env, acct) == to_string(expectedValue.xrp());
236}
237
238/* Payment Channel */
239/******************************************************************************/
242 AccountID const& account,
243 AccountID const& to,
244 STAmount const& amount,
245 NetClock::duration const& settleDelay,
246 PublicKey const& pk,
247 std::optional<NetClock::time_point> const& cancelAfter,
248 std::optional<std::uint32_t> const& dstTag)
249{
250 Json::Value jv;
251 jv[jss::TransactionType] = jss::PaymentChannelCreate;
252 jv[jss::Account] = to_string(account);
253 jv[jss::Destination] = to_string(to);
254 jv[jss::Amount] = amount.getJson(JsonOptions::none);
255 jv[jss::SettleDelay] = settleDelay.count();
256 jv[sfPublicKey.fieldName] = strHex(pk.slice());
257 if (cancelAfter)
258 jv[sfCancelAfter.fieldName] = cancelAfter->time_since_epoch().count();
259 if (dstTag)
260 jv[sfDestinationTag.fieldName] = *dstTag;
261 return jv;
262}
263
266 AccountID const& account,
267 uint256 const& channel,
268 STAmount const& amount,
270{
271 Json::Value jv;
272 jv[jss::TransactionType] = jss::PaymentChannelFund;
273 jv[jss::Account] = to_string(account);
274 jv[sfChannel.fieldName] = to_string(channel);
275 jv[jss::Amount] = amount.getJson(JsonOptions::none);
276 if (expiration)
277 jv[sfExpiration.fieldName] = expiration->time_since_epoch().count();
278 return jv;
279}
280
283 AccountID const& account,
284 uint256 const& channel,
286 std::optional<STAmount> const& amount,
287 std::optional<Slice> const& signature,
288 std::optional<PublicKey> const& pk)
289{
290 Json::Value jv;
291 jv[jss::TransactionType] = jss::PaymentChannelClaim;
292 jv[jss::Account] = to_string(account);
293 jv["Channel"] = to_string(channel);
294 if (amount)
295 jv[jss::Amount] = amount->getJson(JsonOptions::none);
296 if (balance)
297 jv["Balance"] = balance->getJson(JsonOptions::none);
298 if (signature)
299 jv["Signature"] = strHex(*signature);
300 if (pk)
301 jv["PublicKey"] = strHex(pk->slice());
302 return jv;
303}
304
307 AccountID const& account,
308 AccountID const& dst,
309 std::uint32_t seqProxyValue)
310{
311 auto const k = keylet::payChan(account, dst, seqProxyValue);
312 return k.key;
313}
314
316channelBalance(ReadView const& view, uint256 const& chan)
317{
318 auto const slep = view.read({ltPAYCHAN, chan});
319 if (!slep)
320 return XRPAmount{-1};
321 return (*slep)[sfBalance];
322}
323
324bool
325channelExists(ReadView const& view, uint256 const& chan)
326{
327 auto const slep = view.read({ltPAYCHAN, chan});
328 return bool(slep);
329}
330
331/* Crossing Limits */
332/******************************************************************************/
333
334void
336 Env& env,
337 std::size_t n,
338 Account const& account,
339 STAmount const& in,
340 STAmount const& out)
341{
342 auto const ownerCount = env.le(account)->getFieldU32(sfOwnerCount);
343 for (std::size_t i = 0; i < n; i++)
344 {
345 env(offer(account, in, out));
346 env.close();
347 }
348 env.require(owners(account, ownerCount + n));
349}
350
351/* Pay Strand */
352/***************************************************************/
353
354// Currency path element
356cpe(Currency const& c)
357{
358 return STPathElement(
360};
361
362// All path element
364allpe(AccountID const& a, Issue const& iss)
365{
366 return STPathElement(
369 a,
370 iss.currency,
371 iss.account);
372};
373
374} // namespace jtx
375} // namespace test
376} // namespace ripple
Represents a JSON value.
Definition json_value.h:149
bool isArray() const
Value & append(Value const &value)
Append value to array at the end.
UInt size() const
Number of values in array or object.
constexpr value_type const & value() const
Definition Asset.h:156
A currency issued by an account.
Definition Issue.h:33
AccountID account
Definition Issue.h:36
Currency currency
Definition Issue.h:35
constexpr MPTID const & getMptID() const
Definition MPTIssue.h:46
A public key.
Definition PublicKey.h:61
Slice slice() const noexcept
Definition PublicKey.h:122
A view into a ledger.
Definition ReadView.h:51
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
Json::Value getJson(JsonOptions=JsonOptions::none) const override
Definition STAmount.cpp:795
XRPAmount xrp() const
Definition STAmount.cpp:306
Issue const & issue() const
Definition STAmount.h:496
void push_back(STPathElement const &e)
Definition STPathSet.h:410
Immutable cryptographic account descriptor.
Definition Account.h:39
std::string const & human() const
Returns the human readable public key.
Definition Account.h:118
A transaction testing environment.
Definition Env.h:121
std::uint32_t ownerCount(Account const &account) const
Return the number of objects owned by an account.
Definition Env.cpp:259
void require(Args const &... args)
Check a set of requirements.
Definition Env.h:547
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition Env.h:331
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:121
Json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition Env.h:791
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
Definition Env.cpp:277
A balance matches.
Definition balance.h:39
Set Expiration on a JTx.
Match the number of items in the account's owner directory.
Definition owners.h:73
T is_same_v
@ arrayValue
array value (ordered list)
Definition json_value.h:44
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Definition Indexes.cpp:540
Keylet line(AccountID const &id0, AccountID const &id1, Currency const &currency) noexcept
The index of a trust line for a given currency.
Definition Indexes.cpp:244
Keylet payChan(AccountID const &src, AccountID const &dst, std::uint32_t seq) noexcept
A PaymentChannel.
Definition Indexes.cpp:395
bool checkArraySize(Json::Value const &val, unsigned int size)
std::uint32_t ownerCount(Env const &env, Account const &account)
Json::Value ledgerEntryRoot(Env &env, Account const &acct)
bool expectOffers(Env &env, AccountID const &account, std::uint16_t size, std::vector< Amounts > const &toMatch)
STAmount channelBalance(ReadView const &view, uint256 const &chan)
uint256 channel(AccountID const &account, AccountID const &dst, std::uint32_t seqProxyValue)
PrettyAmount xrpMinusFee(Env const &env, std::int64_t xrpAmount)
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
bool equal(STAmount const &sa1, STAmount const &sa2)
constexpr XRPAmount dropsPerXRP
Json::Value getAccountLines(Env &env, AccountID const &acctId)
Json::Value ledgerEntryState(Env &env, Account const &acct_a, Account const &acct_b, std::string const &currency)
void stpath_append_one(STPath &st, Account const &account)
void fund(jtx::Env &env, jtx::Account const &gw, std::vector< jtx::Account > const &accounts, std::vector< STAmount > const &amts, Fund how)
Definition AMMTest.cpp:37
void n_offers(Env &env, std::size_t n, Account const &account, STAmount const &in, STAmount const &out)
Json::Value accountBalance(Env &env, Account const &acct)
STPathElement IPE(Issue const &iss)
Json::Value claim(AccountID const &account, uint256 const &channel, std::optional< STAmount > const &balance, std::optional< STAmount > const &amount, std::optional< Slice > const &signature, std::optional< PublicKey > const &pk)
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
Definition offer.cpp:29
Json::Value create(AccountID const &account, AccountID const &to, STAmount const &amount, NetClock::duration const &settleDelay, PublicKey const &pk, std::optional< NetClock::time_point > const &cancelAfter, std::optional< std::uint32_t > const &dstTag)
bool expectHolding(Env &env, AccountID const &account, STAmount const &value, bool defaultLimits)
STPathElement cpe(Currency const &c)
bool expectLedgerEntryRoot(Env &env, Account const &acct, STAmount const &expectedValue)
STPathElement allpe(AccountID const &a, Issue const &iss)
bool channelExists(ReadView const &view, uint256 const &chan)
XRPAmount txfee(Env const &env, std::uint16_t n)
Json::Value getAccountOffers(Env &env, AccountID const &acct, bool current)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
AccountID const & xrpAccount()
Compute AccountID from public key.
@ current
This was a new validation and was added.
void forEachItem(ReadView const &view, Keylet const &root, std::function< void(std::shared_ptr< SLE const > const &)> const &f)
Iterate all items in the given directory.
Definition View.cpp:653
std::string strHex(FwdIt begin, FwdIt end)
Definition strHex.h:30
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:630
Represents an XRP or IOU quantity This customizes the string conversion and supports XRP conversions ...
T visit(T... args)