rippled
Freeze_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2016 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 #include <test/jtx.h>
20 #include <ripple/protocol/AccountID.h>
21 #include <ripple/protocol/Feature.h>
22 #include <ripple/protocol/jss.h>
23 #include <ripple/protocol/SField.h>
24 #include <ripple/protocol/TxFlags.h>
25 
26 namespace ripple {
27 
28 class Freeze_test : public beast::unit_test::suite
29 {
30 
31  static Json::Value
33  {
34  Json::Value jq;
35  jq[jss::account] = account.human();
36  return env.rpc("json", "account_lines", to_string(jq))[jss::result];
37  }
38 
39  static Json::Value
41  test::jtx::Env& env,
42  test::jtx::Account const& account,
43  bool current = false)
44  {
45  Json::Value jq;
46  jq[jss::account] = account.human();
47  jq[jss::ledger_index] = current ? "current" : "validated";
48  return env.rpc("json", "account_offers", to_string(jq))[jss::result];
49  }
50 
51  static bool checkArraySize(Json::Value const& val, unsigned int size)
52  {
53  return val.isArray() && val.size() == size;
54  }
55 
57  {
58  testcase("RippleState Freeze");
59 
60  using namespace test::jtx;
61  Env env(*this, features);
62 
63  Account G1 {"G1"};
64  Account alice {"alice"};
65  Account bob {"bob"};
66 
67  env.fund(XRP(1000), G1, alice, bob);
68  env.close();
69 
70  env.trust(G1["USD"](100), bob);
71  env.trust(G1["USD"](100), alice);
72  env.close();
73 
74  env(pay(G1, bob, G1["USD"](10)));
75  env(pay(G1, alice, G1["USD"](100)));
76  env.close();
77 
78  env(offer(alice, XRP(500), G1["USD"](100)));
79  env.close();
80 
81  {
82  auto lines = getAccountLines(env, bob);
83  if(! BEAST_EXPECT(checkArraySize(lines[jss::lines], 1u)))
84  return;
85  BEAST_EXPECT(lines[jss::lines][0u][jss::account] == G1.human());
86  BEAST_EXPECT(lines[jss::lines][0u][jss::limit] == "100");
87  BEAST_EXPECT(lines[jss::lines][0u][jss::balance] == "10");
88  }
89 
90  {
91  auto lines = getAccountLines(env, alice);
92  if(! BEAST_EXPECT(checkArraySize(lines[jss::lines], 1u)))
93  return;
94  BEAST_EXPECT(lines[jss::lines][0u][jss::account] == G1.human());
95  BEAST_EXPECT(lines[jss::lines][0u][jss::limit] == "100");
96  BEAST_EXPECT(lines[jss::lines][0u][jss::balance] == "100");
97  }
98 
99  {
100  // Account with line unfrozen (proving operations normally work)
101  // test: can make Payment on that line
102  env(pay(alice, bob, G1["USD"](1)));
103 
104  // test: can receive Payment on that line
105  env(pay(bob, alice, G1["USD"](1)));
106  env.close();
107  }
108 
109  {
110  // Is created via a TrustSet with SetFreeze flag
111  // test: sets LowFreeze | HighFreeze flags
112  env(trust(G1, bob["USD"](0), tfSetFreeze));
113  auto affected = env.meta()->
115  if(! BEAST_EXPECT(checkArraySize(affected, 2u)))
116  return;
117  auto ff =
119  BEAST_EXPECT(
120  ff[sfLowLimit.fieldName] ==
121  G1["USD"](0).value().getJson(JsonOptions::none));
122  BEAST_EXPECT(ff[jss::Flags].asUInt() & lsfLowFreeze);
123  BEAST_EXPECT(! (ff[jss::Flags].asUInt() & lsfHighFreeze));
124  env.close();
125  }
126 
127  {
128  // Account with line frozen by issuer
129  // test: can buy more assets on that line
130  env(offer(bob, G1["USD"](5), XRP(25)));
131  auto affected = env.meta()->
133  if(! BEAST_EXPECT(checkArraySize(affected, 5u)))
134  return;
135  auto ff =
137  BEAST_EXPECT(
138  ff[sfHighLimit.fieldName] ==
139  bob["USD"](100).value().getJson(JsonOptions::none));
140  auto amt =
141  STAmount{Issue{to_currency("USD"), noAccount()}, -15}
142  .value().getJson(JsonOptions::none);
143  BEAST_EXPECT(ff[sfBalance.fieldName] == amt);
144  env.close();
145  }
146 
147  {
148  // test: can not sell assets from that line
149  env(offer(bob, XRP(1), G1["USD"](5)),
150  ter(tecUNFUNDED_OFFER));
151 
152  // test: can receive Payment on that line
153  env(pay(alice, bob, G1["USD"](1)));
154 
155  // test: can not make Payment from that line
156  env(pay(bob, alice, G1["USD"](1)), ter(tecPATH_DRY));
157  }
158 
159  {
160  // check G1 account lines
161  // test: shows freeze
162  auto lines = getAccountLines(env, G1);
163  Json::Value bobLine;
164  for (auto const& it : lines[jss::lines])
165  {
166  if(it[jss::account] == bob.human())
167  {
168  bobLine = it;
169  break;
170  }
171  }
172  if(! BEAST_EXPECT(bobLine))
173  return;
174  BEAST_EXPECT(bobLine[jss::freeze] == true);
175  BEAST_EXPECT(bobLine[jss::balance] == "-16");
176  }
177 
178  {
179  // test: shows freeze peer
180  auto lines = getAccountLines(env, bob);
181  Json::Value g1Line;
182  for (auto const& it : lines[jss::lines])
183  {
184  if(it[jss::account] == G1.human())
185  {
186  g1Line = it;
187  break;
188  }
189  }
190  if(! BEAST_EXPECT(g1Line))
191  return;
192  BEAST_EXPECT(g1Line[jss::freeze_peer] == true);
193  BEAST_EXPECT(g1Line[jss::balance] == "16");
194  }
195 
196  {
197  //Is cleared via a TrustSet with ClearFreeze flag
198  // test: sets LowFreeze | HighFreeze flags
199  env(trust(G1, bob["USD"](0), tfClearFreeze));
200  auto affected = env.meta()->
202  if(! BEAST_EXPECT(checkArraySize(affected, 2u)))
203  return;
204  auto ff =
206  BEAST_EXPECT(
207  ff[sfLowLimit.fieldName] ==
208  G1["USD"](0).value().getJson(JsonOptions::none));
209  BEAST_EXPECT(! (ff[jss::Flags].asUInt() & lsfLowFreeze));
210  BEAST_EXPECT(! (ff[jss::Flags].asUInt() & lsfHighFreeze));
211  env.close();
212  }
213  }
214 
215  void
217  {
218  testcase("Global Freeze");
219 
220  using namespace test::jtx;
221  Env env(*this, features);
222 
223  Account G1 {"G1"};
224  Account A1 {"A1"};
225  Account A2 {"A2"};
226  Account A3 {"A3"};
227  Account A4 {"A4"};
228 
229  env.fund(XRP(12000), G1);
230  env.fund(XRP(1000), A1);
231  env.fund(XRP(20000), A2, A3, A4);
232  env.close();
233 
234  env.trust(G1["USD"](1200), A1);
235  env.trust(G1["USD"](200), A2);
236  env.trust(G1["BTC"](100), A3);
237  env.trust(G1["BTC"](100), A4);
238  env.close();
239 
240  env(pay(G1, A1, G1["USD"](1000)));
241  env(pay(G1, A2, G1["USD"](100)));
242  env(pay(G1, A3, G1["BTC"](100)));
243  env(pay(G1, A4, G1["BTC"](100)));
244  env.close();
245 
246  env(offer(G1, XRP(10000), G1["USD"](100)), txflags(tfPassive));
247  env(offer(G1, G1["USD"](100), XRP(10000)), txflags(tfPassive));
248  env(offer(A1, XRP(10000), G1["USD"](100)), txflags(tfPassive));
249  env(offer(A2, G1["USD"](100), XRP(10000)), txflags(tfPassive));
250  env.close();
251 
252  {
253  //Is toggled via AccountSet using SetFlag and ClearFlag
254  // test: SetFlag GlobalFreeze
255  env.require(nflags(G1, asfGlobalFreeze));
256  env(fset(G1, asfGlobalFreeze));
257  env.require(flags(G1, asfGlobalFreeze));
258  env.require(nflags(G1, asfNoFreeze));
259 
260  // test: ClearFlag GlobalFreeze
261  env(fclear(G1, asfGlobalFreeze));
262  env.require(nflags(G1, asfGlobalFreeze));
263  env.require(nflags(G1, asfNoFreeze));
264  }
265 
266  {
267  //Account without GlobalFreeze (proving operations normally work)
268  // test: visible offers where taker_pays is unfrozen issuer
269  auto offers =
270  env.rpc("book_offers",
271  std::string("USD/")+G1.human(), "XRP")
272  [jss::result][jss::offers];
273  if(! BEAST_EXPECT(checkArraySize(offers, 2u)))
274  return;
275  std::set<std::string> accounts;
276  for (auto const& offer : offers)
277  {
278  accounts.insert(offer[jss::Account].asString());
279  }
280  BEAST_EXPECT(accounts.find(A2.human()) != std::end(accounts));
281  BEAST_EXPECT(accounts.find(G1.human()) != std::end(accounts));
282 
283  // test: visible offers where taker_gets is unfrozen issuer
284  offers =
285  env.rpc("book_offers",
286  "XRP", std::string("USD/")+G1.human())
287  [jss::result][jss::offers];
288  if(! BEAST_EXPECT(checkArraySize(offers, 2u)))
289  return;
290  accounts.clear();
291  for (auto const& offer : offers)
292  {
293  accounts.insert(offer[jss::Account].asString());
294  }
295  BEAST_EXPECT(accounts.find(A1.human()) != std::end(accounts));
296  BEAST_EXPECT(accounts.find(G1.human()) != std::end(accounts));
297  }
298 
299  {
300  // Offers/Payments
301  // test: assets can be bought on the market
302  env(offer(A3, G1["BTC"](1), XRP(1)));
303 
304  // test: assets can be sold on the market
305  env(offer(A4, XRP(1), G1["BTC"](1)));
306 
307  // test: direct issues can be sent
308  env(pay(G1, A2, G1["USD"](1)));
309 
310  // test: direct redemptions can be sent
311  env(pay(A2, G1, G1["USD"](1)));
312 
313  // test: via rippling can be sent
314  env(pay(A2, A1, G1["USD"](1)));
315 
316  // test: via rippling can be sent back
317  env(pay(A1, A2, G1["USD"](1)));
318  }
319 
320  {
321  // Account with GlobalFreeze
322  // set GlobalFreeze first
323  // test: SetFlag GlobalFreeze will toggle back to freeze
324  env.require(nflags(G1, asfGlobalFreeze));
325  env(fset(G1, asfGlobalFreeze));
326  env.require(flags(G1, asfGlobalFreeze));
327  env.require(nflags(G1, asfNoFreeze));
328 
329  // test: assets can't be bought on the market
330  env(offer(A3, G1["BTC"](1), XRP(1)), ter(tecFROZEN));
331 
332  // test: assets can't be sold on the market
333  env(offer(A4, XRP(1), G1["BTC"](1)), ter(tecFROZEN));
334  }
335 
336  {
337  // offers are filtered (seems to be broken?)
338  // test: account_offers always shows own offers
339  auto offers = getAccountOffers(env, G1)[jss::offers];
340  if(! BEAST_EXPECT(checkArraySize(offers, 2u)))
341  return;
342 
343  // test: book_offers shows offers
344  // (should these actually be filtered?)
345  offers =
346  env.rpc("book_offers",
347  "XRP", std::string("USD/")+G1.human())
348  [jss::result][jss::offers];
349  if(! BEAST_EXPECT(checkArraySize(offers, 2u)))
350  return;
351 
352  offers =
353  env.rpc("book_offers",
354  std::string("USD/")+G1.human(), "XRP")
355  [jss::result][jss::offers];
356  if(! BEAST_EXPECT(checkArraySize(offers, 2u)))
357  return;
358  }
359 
360  {
361  // Payments
362  // test: direct issues can be sent
363  env(pay(G1, A2, G1["USD"](1)));
364 
365  // test: direct redemptions can be sent
366  env(pay(A2, G1, G1["USD"](1)));
367 
368  // test: via rippling cant be sent
369  env(pay(A2, A1, G1["USD"](1)), ter(tecPATH_DRY));
370  }
371  }
372 
373  void
375  {
376  testcase("No Freeze");
377 
378  using namespace test::jtx;
379  Env env(*this, features);
380 
381  Account G1 {"G1"};
382  Account A1 {"A1"};
383 
384  env.fund(XRP(12000), G1);
385  env.fund(XRP(1000), A1);
386  env.close();
387 
388  env.trust(G1["USD"](1000), A1);
389  env.close();
390 
391  env(pay(G1, A1, G1["USD"](1000)));
392  env.close();
393 
394  //TrustSet NoFreeze
395  // test: should set NoFreeze in Flags
396  env.require(nflags(G1, asfNoFreeze));
397  env(fset(G1, asfNoFreeze));
398  env.require(flags(G1, asfNoFreeze));
399  env.require(nflags(G1, asfGlobalFreeze));
400 
401  // test: cannot be cleared
402  env(fclear(G1, asfNoFreeze));
403  env.require(flags(G1, asfNoFreeze));
404  env.require(nflags(G1, asfGlobalFreeze));
405 
406  // test: can set GlobalFreeze
407  env(fset(G1, asfGlobalFreeze));
408  env.require(flags(G1, asfNoFreeze));
409  env.require(flags(G1, asfGlobalFreeze));
410 
411  // test: cannot unset GlobalFreeze
412  env(fclear(G1, asfGlobalFreeze));
413  env.require(flags(G1, asfNoFreeze));
414  env.require(flags(G1, asfGlobalFreeze));
415 
416  // test: trustlines can't be frozen
417  env(trust(G1, A1["USD"](0), tfSetFreeze));
418  auto affected =
419  env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName];
420  if(! BEAST_EXPECT(checkArraySize(affected, 1u)))
421  return;
422 
423  auto let =
425  BEAST_EXPECT(let == jss::AccountRoot);
426  }
427 
428  void
430  {
431  testcase("Offers for Frozen Trust Lines");
432 
433  using namespace test::jtx;
434  Env env(*this, features);
435 
436  Account G1 {"G1"};
437  Account A2 {"A2"};
438  Account A3 {"A3"};
439  Account A4 {"A4"};
440 
441  env.fund(XRP(1000), G1, A3, A4);
442  env.fund(XRP(2000), A2);
443  env.close();
444 
445  env.trust(G1["USD"](1000), A2);
446  env.trust(G1["USD"](2000), A3);
447  env.trust(G1["USD"](2000), A4);
448  env.close();
449 
450  env(pay(G1, A3, G1["USD"](2000)));
451  env(pay(G1, A4, G1["USD"](2000)));
452  env.close();
453 
454  env(offer(A3, XRP(1000), G1["USD"](1000)), txflags(tfPassive));
455  env.close();
456 
457  // removal after successful payment
458  // test: make a payment with partially consuming offer
459  env(pay(A2, G1, G1["USD"](1)), paths(G1["USD"]), sendmax(XRP(1)));
460  env.close();
461 
462  // test: offer was only partially consumed
463  auto offers = getAccountOffers(env, A3)[jss::offers];
464  if(! BEAST_EXPECT(checkArraySize(offers, 1u)))
465  return;
466  BEAST_EXPECT(
467  offers[0u][jss::taker_gets] ==
468  G1["USD"](999).value().getJson(JsonOptions::none));
469 
470  // test: someone else creates an offer providing liquidity
471  env(offer(A4, XRP(999), G1["USD"](999)));
472  env.close();
473 
474  // test: owner of partially consumed offers line is frozen
475  env(trust(G1, A3["USD"](0), tfSetFreeze));
476  auto affected =
477  env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName];
478  if(! BEAST_EXPECT(checkArraySize(affected, 2u)))
479  return;
480  auto ff =
482  BEAST_EXPECT(
483  ff[sfHighLimit.fieldName] ==
484  G1["USD"](0).value().getJson(JsonOptions::none));
485  BEAST_EXPECT(! (ff[jss::Flags].asUInt() & lsfLowFreeze));
486  BEAST_EXPECT(ff[jss::Flags].asUInt() & lsfHighFreeze);
487  env.close();
488 
489  // verify offer on the books
490  offers = getAccountOffers(env, A3)[jss::offers];
491  if(! BEAST_EXPECT(checkArraySize(offers, 1u)))
492  return;
493 
494  // test: Can make a payment via the new offer
495  env(pay(A2, G1, G1["USD"](1)), paths(G1["USD"]), sendmax(XRP(1)));
496  env.close();
497 
498  // test: Partially consumed offer was removed by tes* payment
499  offers = getAccountOffers(env, A3)[jss::offers];
500  if(! BEAST_EXPECT(checkArraySize(offers, 0u)))
501  return;
502 
503  // removal buy successful OfferCreate
504  // test: freeze the new offer
505  env(trust(G1, A4["USD"](0), tfSetFreeze));
506  affected =
507  env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName];
508  if(! BEAST_EXPECT(checkArraySize(affected, 2u)))
509  return;
510  ff =
512  BEAST_EXPECT(
513  ff[sfLowLimit.fieldName] ==
514  G1["USD"](0).value().getJson(JsonOptions::none));
515  BEAST_EXPECT(ff[jss::Flags].asUInt() & lsfLowFreeze);
516  BEAST_EXPECT(! (ff[jss::Flags].asUInt() & lsfHighFreeze));
517  env.close();
518 
519  // test: can no longer create a crossing offer
520  env(offer(A2, G1["USD"](999), XRP(999)));
521  affected =
522  env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName];
523  if(! BEAST_EXPECT(checkArraySize(affected, 8u)))
524  return;
525  auto created = affected[0u][sfCreatedNode.fieldName];
526  BEAST_EXPECT(created[sfNewFields.fieldName][jss::Account] == A2.human());
527  env.close();
528 
529  // test: offer was removed by offer_create
530  offers = getAccountOffers(env, A4)[jss::offers];
531  if(! BEAST_EXPECT(checkArraySize(offers, 0u)))
532  return;
533  }
534 
535 public:
536 
537  void run() override
538  {
539  auto testAll = [this](FeatureBitset features)
540  {
541  testRippleState(features);
542  testGlobalFreeze(features);
543  testNoFreeze(features);
544  testOffersWhenFrozen(features);
545  };
546  using namespace test::jtx;
547  auto const sa = supported_amendments();
548  testAll(sa - featureFlowCross);
549  testAll(sa);
550  }
551 };
552 
553 BEAST_DEFINE_TESTSUITE(Freeze, app, ripple);
554 } // ripple
ripple::tecUNFUNDED_OFFER
@ tecUNFUNDED_OFFER
Definition: TER.h:249
ripple::to_currency
bool to_currency(Currency &currency, std::string const &code)
Tries to convert a string to a Currency, returns true on success.
Definition: UintTypes.cpp:67
ripple::tecFROZEN
@ tecFROZEN
Definition: TER.h:268
ripple::Issue
A currency issued by an account.
Definition: Issue.h:34
std::string
STL class.
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
ripple::Freeze_test::testOffersWhenFrozen
void testOffersWhenFrozen(FeatureBitset features)
Definition: Freeze_test.cpp:429
ripple::sfLedgerEntryType
const SF_U16 sfLedgerEntryType(access, STI_UINT16, 1, "LedgerEntryType", SField::sMD_Never)
Definition: SField.h:330
ripple::asfGlobalFreeze
const std::uint32_t asfGlobalFreeze
Definition: TxFlags.h:71
std::set::find
T find(T... args)
ripple::SField::fieldName
const std::string fieldName
Definition: SField.h:136
ripple::tfPassive
const std::uint32_t tfPassive
Definition: TxFlags.h:76
ripple::sfNewFields
const SField sfNewFields(access, STI_OBJECT, 8, "NewFields")
Definition: SField.h:485
ripple::Freeze_test::checkArraySize
static bool checkArraySize(Json::Value const &val, unsigned int size)
Definition: Freeze_test.cpp:51
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
ripple::tfClearFreeze
const std::uint32_t tfClearFreeze
Definition: TxFlags.h:93
ripple::sfFinalFields
const SField sfFinalFields(access, STI_OBJECT, 7, "FinalFields")
Definition: SField.h:484
ripple::sfModifiedNode
const SField sfModifiedNode(access, STI_OBJECT, 5, "ModifiedNode")
Definition: SField.h:482
ripple::sfHighLimit
const SF_Amount sfHighLimit(access, STI_AMOUNT, 7, "HighLimit")
Definition: SField.h:429
ripple::sfLowLimit
const SF_Amount sfLowLimit(access, STI_AMOUNT, 6, "LowLimit")
Definition: SField.h:428
std::set::clear
T clear(T... args)
ripple::Freeze_test::getAccountOffers
static Json::Value getAccountOffers(test::jtx::Env &env, test::jtx::Account const &account, bool current=false)
Definition: Freeze_test.cpp:40
ripple::Freeze_test::testGlobalFreeze
void testGlobalFreeze(FeatureBitset features)
Definition: Freeze_test.cpp:216
ripple::JsonOptions::none
@ none
ripple::Freeze_test::getAccountLines
static Json::Value getAccountLines(test::jtx::Env &env, test::jtx::Account const &account)
Definition: Freeze_test.cpp:32
ripple::STAmount
Definition: STAmount.h:42
ripple::Freeze_test::testNoFreeze
void testNoFreeze(FeatureBitset features)
Definition: Freeze_test.cpp:374
Json::Value::size
UInt size() const
Number of values in array or object.
Definition: json_value.cpp:720
ripple::Freeze_test::testRippleState
void testRippleState(FeatureBitset features)
Definition: Freeze_test.cpp:56
ripple::ValStatus::current
@ current
This was a new validation and was added.
ripple::tfSetFreeze
const std::uint32_t tfSetFreeze
Definition: TxFlags.h:92
ripple::sfCreatedNode
const SField sfCreatedNode(access, STI_OBJECT, 3, "CreatedNode")
Definition: SField.h:480
Json::Value::isArray
bool isArray() const
Definition: json_value.cpp:1056
ripple::lsfHighFreeze
@ lsfHighFreeze
Definition: LedgerFormats.h:154
ripple::getJson
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
Definition: LedgerToJson.cpp:272
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::asfNoFreeze
const std::uint32_t asfNoFreeze
Definition: TxFlags.h:70
ripple::sfBalance
const SF_Amount sfBalance(access, STI_AMOUNT, 2, "Balance")
Definition: SField.h:424
ripple::sfAffectedNodes
const SField sfAffectedNodes(access, STI_ARRAY, 8, "AffectedNodes")
Definition: SField.h:500
std::set::insert
T insert(T... args)
ripple::FeatureBitset
Definition: Feature.h:153
ripple::tecPATH_DRY
@ tecPATH_DRY
Definition: TER.h:259
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::Freeze_test::run
void run() override
Definition: Freeze_test.cpp:537
std::end
T end(T... args)
ripple::lsfLowFreeze
@ lsfLowFreeze
Definition: LedgerFormats.h:153
ripple::featureFlowCross
const uint256 featureFlowCross
Definition: Feature.cpp:161
std::set< std::string >
ripple::noAccount
AccountID const & noAccount()
A placeholder for empty accounts.
Definition: AccountID.cpp:156
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:117
ripple::test::jtx::Env::rpc
Json::Value rpc(std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition: Env.h:688
Json::Value
Represents a JSON value.
Definition: json_value.h:141
ripple::Freeze_test
Definition: Freeze_test.cpp:28