xrpld
Loading...
Searching...
No Matches
Env.cpp
1#include <test/jtx/Env.h>
2
3#include <test/jtx/Account.h>
4#include <test/jtx/JSONRPCClient.h>
5#include <test/jtx/JTx.h>
6#include <test/jtx/ManualTimeKeeper.h>
7#include <test/jtx/amount.h>
8#include <test/jtx/balance.h>
9#include <test/jtx/fee.h>
10#include <test/jtx/flags.h>
11#include <test/jtx/pay.h>
12#include <test/jtx/seq.h>
13#include <test/jtx/sig.h>
14#include <test/jtx/tags.h>
15#include <test/jtx/trust.h>
16#include <test/jtx/utility.h>
17#include <test/unit_test/SuiteJournal.h>
18
19#include <xrpld/app/ledger/LedgerMaster.h>
20#include <xrpld/app/main/Application.h>
21#include <xrpld/core/Config.h>
22#include <xrpld/rpc/RPCCall.h>
23
24#include <xrpl/basics/Log.h>
25#include <xrpl/basics/Number.h>
26#include <xrpl/basics/chrono.h>
27#include <xrpl/basics/contract.h>
28#include <xrpl/basics/safe_cast.h>
29#include <xrpl/basics/scope.h>
30#include <xrpl/basics/strHex.h>
31#include <xrpl/beast/unit_test/suite.h>
32#include <xrpl/beast/utility/Journal.h>
33#include <xrpl/core/NetworkIDService.h>
34#include <xrpl/core/ServiceRegistry.h>
35#include <xrpl/json/to_string.h>
36#include <xrpl/net/HTTPClient.h>
37#include <xrpl/protocol/AccountID.h>
38#include <xrpl/protocol/Asset.h>
39#include <xrpl/protocol/ErrorCodes.h>
40#include <xrpl/protocol/Indexes.h>
41#include <xrpl/protocol/Issue.h>
42#include <xrpl/protocol/Keylet.h>
43#include <xrpl/protocol/MPTIssue.h>
44#include <xrpl/protocol/SField.h>
45#include <xrpl/protocol/STTx.h>
46#include <xrpl/protocol/Serializer.h>
47#include <xrpl/protocol/TER.h>
48#include <xrpl/protocol/TxFlags.h>
49#include <xrpl/protocol/UintTypes.h>
50#include <xrpl/protocol/jss.h>
51#include <xrpl/server/NetworkOPs.h>
52
53#include <cassert>
54#include <chrono>
55#include <cstdint>
56#include <iostream>
57#include <memory>
58#include <optional>
59#include <ostream>
60#include <source_location>
61#include <stdexcept>
62#include <string>
63#include <thread>
64#include <unordered_map>
65#include <utility>
66#include <vector>
67
68namespace xrpl::test::jtx {
69
70//------------------------------------------------------------------------------
71
76 beast::Severity thresh)
77 : AppBundle()
78{
79 using beast::Severity;
80 if (logs)
81 {
82 setDebugLogSink(logs->makeSink("Debug", Severity::Fatal));
83 }
84 else
85 {
86 logs = std::make_unique<SuiteLogs>(suite);
87 // Use kFatal threshold to reduce noise from STObject.
88 setDebugLogSink(std::make_unique<SuiteJournalSink>("Debug", Severity::Fatal, suite));
89 }
91 timeKeeper = tk.get();
92 // Hack so we don't have to call Config::setup
94 config->sslVerifyDir, config->sslVerifyFile, config->sslVerify, debugLog());
95 owned = makeApplication(std::move(config), std::move(logs), std::move(tk));
96 app = owned.get();
97 app->getLogs().threshold(thresh);
98 if (!app->setup({}))
99 Throw<std::runtime_error>("Env::AppBundle: setup failed");
100 timeKeeper->set(app->getLedgerMaster().getClosedLedger()->header().closeTime);
101 app->start(false /*don't start timers*/);
102 thread = std::thread([&]() { app->run(); });
103
104 client = makeJSONRPCClient(app->config());
105}
106
108{
109 client.reset();
110 // Make sure all jobs finish, otherwise tests
111 // might not get the coverage they expect.
112 if (app != nullptr)
113 {
114 app->getJobQueue().rendezvous();
115 app->signalStop("~AppBundle");
116 }
117 if (thread.joinable())
118 thread.join();
119
120 // Remove the debugLogSink before the suite goes out of scope.
121 setDebugLogSink(nullptr);
122}
123
124//------------------------------------------------------------------------------
125
128{
130}
131
132bool
134{
135 // Round up to next distinguishable value
136 using namespace std::chrono_literals;
137 bool res = true;
138 closeTime += closed()->header().closeTimeResolution - 1s;
139 timeKeeper().set(closeTime);
140 // Go through the rpc interface unless we need to simulate
141 // a specific consensus delay.
142 if (consensusDelay)
143 {
144 app().getOPs().acceptLedger(consensusDelay);
145 }
146 else
147 {
148 auto resp = rpc("ledger_accept");
149 if (resp["result"]["status"] != std::string("success"))
150 {
151 std::string reason = "internal error";
152 if (resp.isMember("error_what"))
153 {
154 reason = resp["error_what"].asString();
155 }
156 else if (resp.isMember("error_message"))
157 {
158 reason = resp["error_message"].asString();
159 }
160 else if (resp.isMember("error"))
161 {
162 reason = resp["error"].asString();
163 }
164
165 JLOG(journal.error()) << "Env::close() failed: " << reason;
166 res = false;
167 }
168 }
169 timeKeeper().set(closed()->header().closeTime);
170 return res;
171}
172
173void
174Env::memoize(Account const& account)
175{
176 map_.emplace(account.id(), account);
177}
178
179Account const&
180Env::lookup(AccountID const& id) const
181{
182 auto const iter = map_.find(id);
183 if (iter == map_.end())
184 {
185 std::cout << "Unknown account: " << id << "\n";
186 Throw<std::runtime_error>("Env::lookup:: unknown account ID");
187 }
188 return iter->second;
189}
190
191Account const&
192Env::lookup(std::string const& base58ID) const
193{
194 auto const account = parseBase58<AccountID>(base58ID);
195 if (!account)
196 Throw<std::runtime_error>("Env::lookup: invalid account ID");
197 return lookup(*account);
198}
199
201Env::balance(Account const& account) const
202{
203 auto const sle = le(account);
204 if (!sle)
205 return XRP(0);
206 return {sle->getFieldAmount(sfBalance), ""};
207}
208
210Env::balance(Account const& account, Asset const& asset) const
211{
212 return asset.visit(
213 [&](Issue const& issue) -> PrettyAmount {
214 if (isXRP(issue.currency))
215 return balance(account);
216 auto const sle = le(keylet::trustLine(account.id(), issue));
217 if (!sle)
218 return {STAmount(issue, 0), account.name()};
219 auto amount = sle->getFieldAmount(sfBalance);
220 amount.get<Issue>().account = issue.account;
221 if (account.id() > issue.account)
222 amount.negate();
223 return {amount, lookup(issue.account).name()};
224 },
225 [&](MPTIssue const& mptIssue) -> PrettyAmount {
226 MPTID const& id = mptIssue.getMptID();
227 if (!id)
228 return {STAmount(mptIssue, 0), account.name()};
229
230 AccountID const& issuer = mptIssue.getIssuer();
231 if (account.id() == issuer)
232 {
233 // Issuer balance
234 auto const sle = le(keylet::mptokenIssuance(id));
235 if (!sle)
236 return {STAmount(mptIssue, 0), account.name()};
237
238 // Make it negative
239 STAmount const amount{mptIssue, sle->getFieldU64(sfOutstandingAmount), 0, true};
240 return {amount, lookup(issuer).name()};
241 }
242
243 // Holder balance
244 auto const sle = le(keylet::mptoken(id, account));
245 if (!sle)
246 return {STAmount(mptIssue, 0), account.name()};
247
248 STAmount const amount{mptIssue, sle->getFieldU64(sfMPTAmount)};
249 return {amount, lookup(issuer).name()};
250 });
251}
252
254Env::limit(Account const& account, Issue const& issue) const
255{
256 auto const sle = le(keylet::trustLine(account.id(), issue));
257 if (!sle)
258 return {STAmount(issue, 0), account.name()};
259 auto const aHigh = account.id() > issue.account;
260 if (sle && sle->isFieldPresent(aHigh ? sfLowLimit : sfHighLimit))
261 return {(*sle)[aHigh ? sfLowLimit : sfHighLimit], account.name()};
262 return {STAmount(issue, 0), account.name()};
263}
264
266Env::ownerCount(Account const& account) const
267{
268 auto const sle = le(account);
269 if (!sle)
270 Throw<std::runtime_error>("missing account root");
271 return sle->getFieldU32(sfOwnerCount);
272}
273
275Env::seq(Account const& account) const
276{
277 auto const sle = le(account);
278 if (!sle)
279 Throw<std::runtime_error>("missing account root");
280 return sle->getFieldU32(sfSequence);
281}
282
284Env::le(Account const& account) const
285{
286 return le(keylet::account(account.id()));
287}
288
290Env::le(Keylet const& k) const
291{
292 return current()->read(k);
293}
294
295void
296Env::fund(bool setDefaultRipple, STAmount const& amount, Account const& account)
297{
298 memoize(account);
299 if (setDefaultRipple)
300 {
301 // VFALCO NOTE Is the fee formula correct?
302 apply(
303 pay(master, account, amount + drops(current()->fees().base)),
307 apply(
308 fset(account, asfDefaultRipple),
312 require(Flags(account, asfDefaultRipple));
313 }
314 else
315 {
316 apply(
317 pay(master, account, amount),
321 require(Nflags(account, asfDefaultRipple));
322 }
323 require(jtx::Balance(account, amount));
324}
325
326void
327Env::trust(STAmount const& amount, Account const& account)
328{
329 if (!amount.holds<Issue>())
330 Throw<std::runtime_error>("Env::trust: amount doesn't hold Issue");
331 auto const start = balance(account);
332 apply(
333 jtx::trust(account, amount),
337 apply(
338 pay(master, account, drops(current()->fees().base)),
342 test.expect(balance(account) == start);
343}
344
347{
348 auto error = [](ParsedResult& parsed, json::Value const& object) {
349 // Use an error code that is not used anywhere in the transaction
350 // engine to distinguish this case.
351 parsed.ter = telENV_RPC_FAILED;
352 // Extract information about the error
353 if (!object.isObject())
354 return;
355 if (object.isMember(jss::error_code))
356 parsed.rpcCode = safeCast<ErrorCodeI>(object[jss::error_code].asInt());
357 if (object.isMember(jss::error_message))
358 parsed.rpcMessage = object[jss::error_message].asString();
359 if (object.isMember(jss::error))
360 parsed.rpcError = object[jss::error].asString();
361 if (object.isMember(jss::error_exception))
362 parsed.rpcException = object[jss::error_exception].asString();
363 };
364 ParsedResult parsed;
365 if (jr.isObject() && jr.isMember(jss::result))
366 {
367 auto const& result = jr[jss::result];
368 if (result.isMember(jss::engine_result_code))
369 {
370 parsed.ter = TER::fromInt(result[jss::engine_result_code].asInt());
371 parsed.rpcCode.emplace(RpcSuccess);
372 }
373 else
374 {
375 error(parsed, result);
376 }
377 }
378 else
379 {
380 error(parsed, jr);
381 }
382
383 return parsed;
384}
385
386void
388{
389 ParsedResult parsedResult;
390 auto const jr = [&]() {
391 if (jt.stx)
392 {
393 txid_ = jt.stx->getTransactionID();
394 Serializer s;
395 jt.stx->add(s);
396 auto const jr = rpc("submit", strHex(s.slice()));
397
398 parsedResult = parseResult(jr);
399 test.expect(parsedResult.ter, "ter uninitialized!");
400 ter_ = parsedResult.ter.value_or(telENV_RPC_FAILED);
401
402 return jr;
403 }
404
405 // Parsing failed or the JTx is
406 // otherwise missing the stx field.
407 parsedResult.ter = ter_ = temMALFORMED;
408
409 return json::Value();
410 }();
411 postconditions(jt, parsedResult, jr, loc);
412}
413
414void
416{
417 auto const account = lookup(jt.jv[jss::Account].asString());
418 auto const& passphrase = account.name();
419
420 json::Value jr;
421 if (params.isNull())
422 {
423 // Use the command line interface
424 auto const jv = to_string(jt.jv);
425 jr = rpc("submit", passphrase, jv);
426 }
427 else
428 {
429 // Use the provided parameters, and go straight
430 // to the (RPC) client.
431 assert(params.isObject());
432 if (!params.isMember(jss::secret) && !params.isMember(jss::key_type) &&
433 !params.isMember(jss::seed) && !params.isMember(jss::seed_hex) &&
434 !params.isMember(jss::passphrase))
435 {
436 params[jss::secret] = passphrase;
437 }
438 params[jss::tx_json] = jt.jv;
439 jr = client().invoke("submit", params);
440 }
441
442 if (!txid_.parseHex(jr[jss::result][jss::tx_json][jss::hash].asString()))
443 txid_.zero();
444
445 ParsedResult const parsedResult = parseResult(jr);
446 test.expect(parsedResult.ter, "ter uninitialized!");
447 ter_ = parsedResult.ter.value_or(telENV_RPC_FAILED);
448
449 postconditions(jt, parsedResult, jr, loc);
450}
451
452void
454 JTx const& jt,
455 ParsedResult const& parsed,
456 json::Value const& jr,
457 std::source_location const& loc)
458{
459 auto const locStr = std::string("(") + loc.file_name() + ":" + to_string(loc.line()) + ")";
460 bool bad = !test.expect(parsed.ter, "apply " + locStr + ": No ter result!");
461 bad =
462 (jt.ter && parsed.ter &&
463 !test.expect(
464 *parsed.ter == *jt.ter,
465 "apply " + locStr + ": Got " + transToken(*parsed.ter) + " (" +
466 transHuman(*parsed.ter) + "); Expected " + transToken(*jt.ter) + " (" +
467 transHuman(*jt.ter) + ")"));
468 using namespace std::string_literals;
469 bad =
470 (jt.rpcCode &&
471 !test.expect(
472 parsed.rpcCode == jt.rpcCode->first && parsed.rpcMessage == jt.rpcCode->second,
473 "apply " + locStr + ": Got RPC result "s +
474 (parsed.rpcCode ? RPC::getErrorInfo(*parsed.rpcCode).token.cStr() : "NO RESULT") +
475 " (" + parsed.rpcMessage + "); Expected " +
476 RPC::getErrorInfo(jt.rpcCode->first).token.cStr() + " (" + jt.rpcCode->second +
477 ")")) ||
478 bad;
479 // If we have an rpcCode (just checked), then the rpcException check is
480 // optional - the 'error' field may not be defined, but if it is, it must
481 // match rpcError.
482 bad = (jt.rpcException &&
483 !test.expect(
484 (jt.rpcCode && parsed.rpcError.empty()) ||
485 (parsed.rpcError == jt.rpcException->first &&
486 (!jt.rpcException->second || parsed.rpcException == *jt.rpcException->second)),
487 "apply " + locStr + ": Got RPC result "s + parsed.rpcError + " (" +
488 parsed.rpcException + "); Expected " + jt.rpcException->first + " (" +
489 jt.rpcException->second.value_or("n/a") + ")")) ||
490 bad;
491 if (bad)
492 {
493 test.log << pretty(jt.jv) << std::endl;
494 if (jr)
495 test.log << pretty(jr) << std::endl;
496 // Don't check postconditions if
497 // we didn't get the expected result.
498 return;
499 }
500 if (trace_ != 0)
501 {
502 if (trace_ > 0)
503 --trace_;
504 test.log << pretty(jt.jv) << std::endl;
505 }
506 for (auto const& f : jt.require)
507 f(*this);
508}
509
512{
513 if (current()->txCount() != 0)
514 {
515 // close the ledger if it has not already been closed
516 // (metadata is not finalized until the ledger is closed)
517 close();
518 }
519 auto const item = closed()->txRead(txid_);
520 auto const result = item.second;
521 if (result == nullptr)
522 {
523 test.log << "Env::meta: no metadata for txid: " << txid_ << std::endl;
524 test.log << "This is probably because the transaction failed with a "
525 "non-tec error."
526 << std::endl;
527 Throw<std::runtime_error>("Env::meta: no metadata for txid");
528 }
529 return result;
530}
531
533Env::tx() const
534{
535 return current()->txRead(txid_).first;
536}
537
538void
540{
541 auto& jv = jt.jv;
542
543 ScopeSuccess const success([&]() {
544 // Call all the post-signers after the main signers or autofill are done
545 for (auto const& signer : jt.postSigners)
546 signer(*this, jt);
547 });
548
549 // Call all the main signers
550 if (!jt.mainSigners.empty())
551 {
552 for (auto const& signer : jt.mainSigners)
553 signer(*this, jt);
554 return;
555 }
556
557 // If the sig is still needed, get it here.
558 if (!jt.fillSig)
559 return;
560 auto const account = jv.isMember(sfDelegate.jsonName)
561 ? lookup(jv[sfDelegate.jsonName].asString())
562 : lookup(jv[jss::Account].asString());
563 if (!app().checkSigs())
564 {
565 jv[jss::SigningPubKey] = strHex(account.pk().slice());
566 // dummy sig otherwise STTx is invalid
567 jv[jss::TxnSignature] = "00";
568 return;
569 }
570 auto const ar = le(account);
571 if (ar && ar->isFieldPresent(sfRegularKey))
572 {
573 jtx::sign(jv, lookup(ar->getAccountID(sfRegularKey)));
574 }
575 else
576 {
577 jtx::sign(jv, account);
578 }
579}
580
581void
583{
584 auto& jv = jt.jv;
585 if (jt.fillFee)
586 jtx::fillFee(jv, *current());
587 if (jt.fillSeq)
588 jtx::fillSeq(jv, *current());
589
590 if (jt.fillNetid)
591 {
592 uint32_t const networkID = app().getNetworkIDService().getNetworkID();
593 if (!jv.isMember(jss::NetworkID) && networkID > 1024)
594 jv[jss::NetworkID] = std::to_string(networkID);
595 }
596
597 // Must come last
598 try
599 {
601 }
602 catch (ParseError const&)
603 {
605 test.log << "parse failed:\n" << pretty(jv) << std::endl;
606 rethrow();
607 }
608}
609
612{
613 // The parse must succeed, since we
614 // generated the JSON ourselves.
616 try
617 {
618 obj = jtx::parse(jt.jv);
619 }
620 catch (jtx::ParseError const&)
621 {
622 test.log << "Exception: ParseError\n" << pretty(jt.jv) << std::endl;
623 rethrow();
624 }
625
626 try
627 {
628 return sterilize(STTx{std::move(*obj)});
629 }
630 catch (...)
631 {
632 return nullptr;
633 }
634}
635
638{
639 // The parse must succeed, since we
640 // generated the JSON ourselves.
642 try
643 {
644 obj = jtx::parse(jt.jv);
645 }
646 catch (jtx::ParseError const&)
647 {
648 test.log << "Exception: ParseError\n" << pretty(jt.jv) << std::endl;
649 rethrow();
650 }
651
652 try
653 {
654 return std::make_shared<STTx const>(std::move(*obj));
655 }
656 catch (...)
657 {
658 return nullptr;
659 }
660}
661
664 unsigned apiVersion,
665 std::vector<std::string> const& args,
667{
668 auto response = rpcClient(args, app().config(), app().getLogs(), apiVersion, headers);
669
670 for (unsigned ctr = 0; (ctr < retries_) and (response.first == RpcInternal); ++ctr)
671 {
672 JLOG(journal.error()) << "Env::doRpc error, retrying, attempt #" << ctr + 1 << " ...";
674
675 response = rpcClient(args, app().config(), app().getLogs(), apiVersion, headers);
676 }
677
678 return response.second;
679}
680
681void
683{
684 // Env::close() must be called for feature
685 // enable to take place.
686 app().config().features.insert(feature);
687}
688
689void
691{
692 // Env::close() must be called for feature
693 // enable to take place.
694 app().config().features.erase(feature);
695}
696
697} // namespace xrpl::test::jtx
A testsuite class.
Definition suite.h:50
Represents a JSON value.
Definition json_value.h:130
bool isNull() const
isNull() tests to see if this field is null.
bool isObject() const
std::string asString() const
Returns the unquoted string value.
bool isMember(char const *key) const
Return true if the object has a member named key.
virtual Config & config()=0
constexpr auto visit(Visitors &&... visitors) const -> decltype(auto)
Definition Asset.h:107
std::unordered_set< uint256, beast::Uhash<> > features
Definition Config.h:261
static void initializeSSLContext(std::string const &sslVerifyDir, std::string const &sslVerifyFile, bool sslVerify, beast::Journal j)
A currency issued by an account.
Definition Issue.h:13
Currency currency
Definition Issue.h:15
AccountID account
Definition Issue.h:16
std::shared_ptr< Ledger const > getClosedLedger()
std::chrono::time_point< NetClock > time_point
Definition chrono.h:46
virtual std::uint32_t getNetworkID() const noexcept=0
Get the configured network ID.
virtual std::uint32_t acceptLedger(std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)=0
Accepts the current transaction tree, return the new ledger's sequence.
constexpr bool holds() const noexcept
Definition STAmount.h:460
std::shared_ptr< STLedgerEntry const > const_pointer
Slice slice() const noexcept
Definition Serializer.h:44
virtual NetworkOPs & getOPs()=0
virtual NetworkIDService & getNetworkIDService()=0
virtual LedgerMaster & getLedgerMaster()=0
static constexpr TERSubset fromInt(int from)
Definition TER.h:431
virtual json::Value invoke(std::string const &cmd, json::Value const &params={})=0
Submit a command synchronously.
Immutable cryptographic account descriptor.
Definition jtx/Account.h:17
std::string const & name() const
Return the name.
Definition jtx/Account.h:61
A balance matches.
Definition balance.h:19
Application & app()
Definition Env.h:280
std::shared_ptr< STTx const > st(JTx const &jt)
Create a STTx from a JTx The framework requires that JSON is valid.
Definition Env.cpp:611
SLE::const_pointer le(Account const &account) const
Return an account root.
Definition Env.cpp:284
std::uint32_t ownerCount(Account const &account) const
Return the number of objects owned by an account.
Definition Env.cpp:266
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
Definition Env.cpp:127
static ParsedResult parseResult(json::Value const &jr)
Gets the TER result and didApply flag from a RPC Json result object.
Definition Env.cpp:346
Account const & lookup(AccountID const &id) const
Returns the Account given the AccountID.
Definition Env.cpp:180
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:296
virtual void submit(JTx const &jt, std::source_location const &loc=std::source_location::current())
Submit an existing JTx.
Definition Env.cpp:387
void enableFeature(uint256 const feature)
Definition Env.cpp:682
PrettyAmount limit(Account const &account, Issue const &issue) const
Returns the IOU limit on an account.
Definition Env.cpp:254
void disableFeature(uint256 const feature)
Definition Env.cpp:690
json::Value doRpc(unsigned apiVersion, std::vector< std::string > const &args, std::unordered_map< std::string, std::string > const &headers={})
Definition Env.cpp:663
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
Definition Env.cpp:275
virtual void autofill(JTx &jt)
Definition Env.cpp:582
void postconditions(JTx const &jt, ParsedResult const &parsed, json::Value const &jr=json::Value(), std::source_location const &loc=std::source_location::current())
Check expected postconditions of JTx submission.
Definition Env.cpp:453
bool close()
Close and advance the ledger.
Definition Env.h:415
Account const & master
Definition Env.h:147
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:864
void autofillSig(JTx &jt)
Definition Env.cpp:539
void signAndSubmit(JTx const &jt, json::Value params=json::ValueType::Null, std::source_location const &loc=std::source_location::current())
Use the submit RPC command with a provided JTx object.
Definition Env.cpp:415
JTx jt(JsonValue &&jv, FN const &... fN)
Create a JTx from parameters.
Definition Env.h:566
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
Definition Env.cpp:201
unsigned retries_
Definition Env.h:817
beast::unit_test::Suite & test
Definition Env.h:145
uint256 txid_
Definition Env.h:814
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
Definition Env.cpp:327
std::shared_ptr< STTx const > ust(JTx const &jt)
Create a STTx from a JTx without sanitizing Use to inject bogus values into test transactions by firs...
Definition Env.cpp:637
std::shared_ptr< STObject const > meta()
Return metadata for the last JTx.
Definition Env.cpp:511
Env & apply(WithSourceLocation< json::Value > jv, FN const &... fN)
Apply funclets and submit.
Definition Env.h:644
std::unordered_map< AccountID, Account > map_
Definition Env.h:859
ManualTimeKeeper & timeKeeper()
Definition Env.h:293
bool parseFailureExpected_
Definition Env.h:816
std::shared_ptr< STTx const > tx() const
Return the tx data for the last JTx.
Definition Env.cpp:533
void memoize(Account const &account)
Associate AccountID with account.
Definition Env.cpp:174
beast::Journal const journal
Definition Env.h:184
AbstractClient & client()
Returns the connected client.
Definition Env.h:313
void require(Args const &... args)
Check a set of requirements.
Definition Env.h:605
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition Env.h:353
Set the fee on a JTx.
Definition fee.h:15
Match set account flags.
Definition flags.h:109
Match clear account flags.
Definition flags.h:125
Set the regular signature on a JTx.
Definition sig.h:13
T emplace(T... args)
T empty(T... args)
T endl(T... args)
T file_name(T... args)
T make_shared(T... args)
T make_unique(T... args)
Severity
Severity level / threshold of a Journal message.
Definition Journal.h:11
ErrorInfo const & getErrorInfo(ErrorCodeI code)
Returns an ErrorInfo that reflects the error code.
Keylet mptokenIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:521
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Definition Indexes.cpp:533
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:186
Keylet trustLine(AccountID const &id0, AccountID const &id1, Currency const &currency) noexcept
The index of a trust line for a given currency.
Definition Indexes.cpp:241
json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Definition pay.cpp:14
void fillFee(json::Value &jv, ReadView const &view)
Set the fee automatically.
Definition utility.cpp:57
XrpT const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:92
void sign(json::Value &jv, Account const &account, json::Value &sigObject)
Sign automatically into a specific Json field of the jv object.
Definition utility.cpp:40
json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Definition trust.cpp:18
static AutofillT const kAutofill
Definition tags.h:15
STObject parse(json::Value const &jv)
Convert JSON to STObject.
Definition utility.cpp:31
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Definition flags.cpp:15
void fillSeq(json::Value &jv, ReadView const &view)
Set the sequence number automatically.
Definition utility.cpp:80
std::unique_ptr< AbstractClient > makeJSONRPCClient(Config const &cfg, unsigned rpcVersion)
Returns a client using JSON-RPC over HTTP/S.
@ telENV_RPC_FAILED
Definition TER.h:52
@ RpcInternal
Definition ErrorCodes.h:112
@ RpcSuccess
Definition ErrorCodes.h:26
bool isXRP(AccountID const &c)
Definition AccountID.h:70
std::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
beast::Journal debugLog()
Returns a debug journal.
Definition Log.cpp:399
std::unique_ptr< beast::Journal::Sink > setDebugLogSink(std::unique_ptr< beast::Journal::Sink > sink)
Set the sink for the debug journal.
Definition Log.cpp:393
std::string strHex(FwdIt begin, FwdIt end)
Definition strHex.h:10
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > safeCast(Src s) noexcept
Definition safe_cast.h:21
std::string transHuman(TER code)
Definition TER.cpp:256
std::string transToken(TER code)
Definition TER.cpp:247
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:633
XRPL_NO_SANITIZE_ADDRESS void rethrow()
Rethrow the exception currently being handled.
Definition contract.h:33
BaseUInt< 192 > MPTID
MPTID is a 192-bit value representing MPT Issuance ID, which is a concatenation of a 32-bit sequence ...
Definition UintTypes.h:44
std::pair< int, json::Value > rpcClient(std::vector< std::string > const &args, Config const &config, Logs &logs, unsigned int apiVersion, std::unordered_map< std::string, std::string > const &headers)
Internal invocation of RPC client.
Definition RPCCall.cpp:1666
std::unique_ptr< Application > makeApplication(std::unique_ptr< Config > config, std::unique_ptr< Logs > logs, std::unique_ptr< TimeKeeper > timeKeeper)
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:28
@ temMALFORMED
Definition TER.h:73
std::shared_ptr< STTx const > sterilize(STTx const &stx)
Sterilize a transaction.
Definition STTx.cpp:801
BaseUInt< 256 > uint256
Definition base_uint.h:562
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:49
T sleep_for(T... args)
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:19
ManualTimeKeeper * timeKeeper
Definition Env.h:168
std::unique_ptr< AbstractClient > client
Definition Env.h:170
std::unique_ptr< Application > owned
Definition Env.h:167
Used by parseResult() and postConditions().
Definition Env.h:151
std::optional< TER > ter
Definition Env.h:152
std::optional< ErrorCodeI > rpcCode
Definition Env.h:157
Execution context for applying a JSON transaction.
Definition JTx.h:23
Thrown when parse fails.
Definition utility.h:16
Represents an XRP, IOU, or MPT quantity This customizes the string conversion and supports XRP conver...
Set the sequence number on a JTx.
Definition seq.h:12
T to_string(T... args)