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#include <xrpl/protocol/TxFlags.h>
24
25namespace ripple {
26namespace test {
27namespace jtx {
28
29// Functions used in debugging
31getAccountOffers(Env& env, AccountID const& acct, bool current)
32{
33 Json::Value jv;
34 jv[jss::account] = to_string(acct);
35 return env.rpc("json", "account_offers", to_string(jv))[jss::result];
36}
37
39getAccountLines(Env& env, AccountID const& acctId)
40{
41 Json::Value jv;
42 jv[jss::account] = to_string(acctId);
43 return env.rpc("json", "account_lines", to_string(jv))[jss::result];
44}
45
46bool
47checkArraySize(Json::Value const& val, unsigned int size)
48{
49 return val.isArray() && val.size() == size;
50}
51
53ownerCount(Env const& env, Account const& account)
54{
55 return env.ownerCount(account);
56}
57
58/* Path finding */
59/******************************************************************************/
60void
61stpath_append_one(STPath& st, Account const& account)
62{
63 st.push_back(STPathElement({account.id(), std::nullopt, std::nullopt}));
64}
65
66void
68{
69 st.push_back(pe);
70}
71
72bool
73equal(STAmount const& sa1, STAmount const& sa2)
74{
75 return sa1 == sa2 && sa1.issue().account == sa2.issue().account;
76}
77
78// Issue path element
80IPE(Issue const& iss)
81{
82 return STPathElement(
84 xrpAccount(),
85 iss.currency,
86 iss.account);
87}
88
89/******************************************************************************/
90
92txfee(Env const& env, std::uint16_t n)
93{
94 return env.current()->fees().base * n;
95}
96
98xrpMinusFee(Env const& env, std::int64_t xrpAmount)
99{
100 auto feeDrops = env.current()->fees().base;
101 return drops(dropsPerXRP * xrpAmount - feeDrops);
102};
103
104[[nodiscard]] bool
106 Env& env,
107 AccountID const& account,
108 STAmount const& value,
109 bool defaultLimits)
110{
111 if (auto const sle = env.le(keylet::line(account, value.issue())))
112 {
113 Issue const issue = value.issue();
114 bool const accountLow = account < issue.account;
115
116 bool expectDefaultTrustLine = true;
117 if (defaultLimits)
118 {
119 STAmount low{issue};
120 STAmount high{issue};
121
122 low.setIssuer(accountLow ? account : issue.account);
123 high.setIssuer(accountLow ? issue.account : account);
124
125 expectDefaultTrustLine = sle->getFieldAmount(sfLowLimit) == low &&
126 sle->getFieldAmount(sfHighLimit) == high;
127 }
128
129 auto amount = sle->getFieldAmount(sfBalance);
130 amount.setIssuer(value.issue().account);
131 if (!accountLow)
132 amount.negate();
133 return amount == value && expectDefaultTrustLine;
134 }
135 return false;
136}
137
138[[nodiscard]] bool
139expectLine(Env& env, AccountID const& account, None const& value)
140{
141 return !env.le(keylet::line(account, value.issue));
142}
143
144[[nodiscard]] bool
146 Env& env,
147 AccountID const& account,
148 std::uint16_t size,
149 std::vector<Amounts> const& toMatch)
150{
151 std::uint16_t cnt = 0;
152 std::uint16_t matched = 0;
154 *env.current(), account, [&](std::shared_ptr<SLE const> const& sle) {
155 if (!sle)
156 return false;
157 if (sle->getType() == ltOFFER)
158 {
159 ++cnt;
160 if (std::find_if(
161 toMatch.begin(), toMatch.end(), [&](auto const& a) {
162 return a.in == sle->getFieldAmount(sfTakerPays) &&
163 a.out == sle->getFieldAmount(sfTakerGets);
164 }) != toMatch.end())
165 ++matched;
166 }
167 return true;
168 });
169 return size == cnt && matched == toMatch.size();
170}
171
173ledgerEntryRoot(Env& env, Account const& acct)
174{
175 Json::Value jvParams;
176 jvParams[jss::ledger_index] = "current";
177 jvParams[jss::account_root] = acct.human();
178 return env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result];
179}
180
183 Env& env,
184 Account const& acct_a,
185 Account const& acct_b,
186 std::string const& currency)
187{
188 Json::Value jvParams;
189 jvParams[jss::ledger_index] = "current";
190 jvParams[jss::ripple_state][jss::currency] = currency;
191 jvParams[jss::ripple_state][jss::accounts] = Json::arrayValue;
192 jvParams[jss::ripple_state][jss::accounts].append(acct_a.human());
193 jvParams[jss::ripple_state][jss::accounts].append(acct_b.human());
194 return env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result];
195}
196
198accountBalance(Env& env, Account const& acct)
199{
200 auto const jrr = ledgerEntryRoot(env, acct);
201 return jrr[jss::node][sfBalance.fieldName];
202}
203
204[[nodiscard]] bool
206 Env& env,
207 Account const& acct,
208 STAmount const& expectedValue)
209{
210 return accountBalance(env, acct) == to_string(expectedValue.xrp());
211}
212
213/* Escrow */
214/******************************************************************************/
215
217escrow(AccountID const& account, AccountID const& to, STAmount const& amount)
218{
219 Json::Value jv;
220 jv[jss::TransactionType] = jss::EscrowCreate;
221 jv[jss::Flags] = tfUniversal;
222 jv[jss::Account] = to_string(account);
223 jv[jss::Destination] = to_string(to);
224 jv[jss::Amount] = amount.getJson(JsonOptions::none);
225 return jv;
226}
227
229finish(AccountID const& account, AccountID const& from, std::uint32_t seq)
230{
231 Json::Value jv;
232 jv[jss::TransactionType] = jss::EscrowFinish;
233 jv[jss::Flags] = tfUniversal;
234 jv[jss::Account] = to_string(account);
235 jv[sfOwner.jsonName] = to_string(from);
236 jv[sfOfferSequence.jsonName] = seq;
237 return jv;
238}
239
241cancel(AccountID const& account, Account const& from, std::uint32_t seq)
242{
243 Json::Value jv;
244 jv[jss::TransactionType] = jss::EscrowCancel;
245 jv[jss::Flags] = tfUniversal;
246 jv[jss::Account] = to_string(account);
247 jv[sfOwner.jsonName] = from.human();
248 jv[sfOfferSequence.jsonName] = seq;
249 return jv;
250}
251
252/* Payment Channel */
253/******************************************************************************/
256 AccountID const& account,
257 AccountID const& to,
258 STAmount const& amount,
259 NetClock::duration const& settleDelay,
260 PublicKey const& pk,
261 std::optional<NetClock::time_point> const& cancelAfter,
262 std::optional<std::uint32_t> const& dstTag)
263{
264 Json::Value jv;
265 jv[jss::TransactionType] = jss::PaymentChannelCreate;
266 jv[jss::Flags] = tfUniversal;
267 jv[jss::Account] = to_string(account);
268 jv[jss::Destination] = to_string(to);
269 jv[jss::Amount] = amount.getJson(JsonOptions::none);
270 jv[jss::SettleDelay] = settleDelay.count();
271 jv[sfPublicKey.fieldName] = strHex(pk.slice());
272 if (cancelAfter)
273 jv[sfCancelAfter.fieldName] = cancelAfter->time_since_epoch().count();
274 if (dstTag)
275 jv[sfDestinationTag.fieldName] = *dstTag;
276 return jv;
277}
278
281 AccountID const& account,
282 uint256 const& channel,
283 STAmount const& amount,
285{
286 Json::Value jv;
287 jv[jss::TransactionType] = jss::PaymentChannelFund;
288 jv[jss::Flags] = tfUniversal;
289 jv[jss::Account] = to_string(account);
290 jv[sfChannel.fieldName] = to_string(channel);
291 jv[jss::Amount] = amount.getJson(JsonOptions::none);
292 if (expiration)
293 jv[sfExpiration.fieldName] = expiration->time_since_epoch().count();
294 return jv;
295}
296
299 AccountID const& account,
300 uint256 const& channel,
302 std::optional<STAmount> const& amount,
303 std::optional<Slice> const& signature,
304 std::optional<PublicKey> const& pk)
305{
306 Json::Value jv;
307 jv[jss::TransactionType] = jss::PaymentChannelClaim;
308 jv[jss::Flags] = tfUniversal;
309 jv[jss::Account] = to_string(account);
310 jv["Channel"] = to_string(channel);
311 if (amount)
312 jv[jss::Amount] = amount->getJson(JsonOptions::none);
313 if (balance)
314 jv["Balance"] = balance->getJson(JsonOptions::none);
315 if (signature)
316 jv["Signature"] = strHex(*signature);
317 if (pk)
318 jv["PublicKey"] = strHex(pk->slice());
319 return jv;
320}
321
324 AccountID const& account,
325 AccountID const& dst,
326 std::uint32_t seqProxyValue)
327{
328 auto const k = keylet::payChan(account, dst, seqProxyValue);
329 return k.key;
330}
331
333channelBalance(ReadView const& view, uint256 const& chan)
334{
335 auto const slep = view.read({ltPAYCHAN, chan});
336 if (!slep)
337 return XRPAmount{-1};
338 return (*slep)[sfBalance];
339}
340
341bool
342channelExists(ReadView const& view, uint256 const& chan)
343{
344 auto const slep = view.read({ltPAYCHAN, chan});
345 return bool(slep);
346}
347
348/* Crossing Limits */
349/******************************************************************************/
350
351void
353 Env& env,
354 std::size_t n,
355 Account const& account,
356 STAmount const& in,
357 STAmount const& out)
358{
359 auto const ownerCount = env.le(account)->getFieldU32(sfOwnerCount);
360 for (std::size_t i = 0; i < n; i++)
361 {
362 env(offer(account, in, out));
363 env.close();
364 }
365 env.require(owners(account, ownerCount + n));
366}
367
368/* Pay Strand */
369/***************************************************************/
370
371// Currency path element
373cpe(Currency const& c)
374{
375 return STPathElement(
377};
378
379// All path element
381allpe(AccountID const& a, Issue const& iss)
382{
383 return STPathElement(
386 a,
387 iss.currency,
388 iss.account);
389};
390
391} // namespace jtx
392} // namespace test
393} // namespace ripple
Represents a JSON value.
Definition: json_value.h:148
bool isArray() const
UInt size() const
Number of values in array or object.
Definition: json_value.cpp:712
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:897
A currency issued by an account.
Definition: Issue.h:36
AccountID account
Definition: Issue.h:39
Currency currency
Definition: Issue.h:38
A public key.
Definition: PublicKey.h:62
Slice slice() const noexcept
Definition: PublicKey.h:123
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) const override
Definition: STAmount.cpp:636
XRPAmount xrp() const
Definition: STAmount.cpp:305
Issue const & issue() const
Definition: STAmount.h:487
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:114
A transaction testing environment.
Definition: Env.h:118
std::uint32_t ownerCount(Account const &account) const
Return the number of objects owned by an account.
Definition: Env.cpp:201
void require(Args const &... args)
Check a set of requirements.
Definition: Env.h:530
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:326
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition: Env.cpp:115
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:765
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
Definition: Env.cpp:219
A balance matches.
Definition: balance.h:39
Set Expiration on a JTx.
Definition: Check_test.cpp:30
Match the number of items in the account's owner directory.
Definition: owners.h:71
@ arrayValue
array value (ordered list)
Definition: json_value.h:43
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:235
Keylet payChan(AccountID const &src, AccountID const &dst, std::uint32_t seq) noexcept
A PaymentChannel.
Definition: Indexes.cpp:386
bool checkArraySize(Json::Value const &val, unsigned int size)
Definition: TestHelpers.cpp:47
std::uint32_t ownerCount(Env const &env, Account const &account)
Definition: TestHelpers.cpp:53
Json::Value ledgerEntryRoot(Env &env, Account const &acct)
Json::Value escrow(AccountID const &account, AccountID const &to, STAmount const &amount)
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)
Definition: TestHelpers.cpp:98
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
bool expectLine(Env &env, AccountID const &account, STAmount const &value, bool defaultLimits)
bool equal(STAmount const &sa1, STAmount const &sa2)
Definition: TestHelpers.cpp:73
constexpr XRPAmount dropsPerXRP
Json::Value getAccountLines(Env &env, AccountID const &acctId)
Definition: TestHelpers.cpp:39
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)
Definition: TestHelpers.cpp:61
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:34
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)
Json::Value cancel(AccountID const &account, Account const &from, std::uint32_t seq)
STPathElement IPE(Issue const &iss)
Definition: TestHelpers.cpp:80
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 finish(AccountID const &account, AccountID const &from, std::uint32_t seq)
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
Definition: offer.cpp:28
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)
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)
Definition: TestHelpers.cpp:92
Json::Value getAccountOffers(Env &env, AccountID const &acct, bool current)
Definition: TestHelpers.cpp:31
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
AccountID const & xrpAccount()
Compute AccountID from public key.
Definition: AccountID.cpp:178
@ current
This was a new validation and was added.
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:30
constexpr std::uint32_t tfUniversal
Definition: TxFlags.h:61
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:630
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:543
Represents an XRP or IOU quantity This customizes the string conversion and supports XRP conversions ...
Set the sequence number on a JTx.
Definition: seq.h:34