rippled
Env_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 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 <ripple/app/misc/NetworkOPs.h>
21 #include <ripple/app/misc/TxQ.h>
22 #include <ripple/beast/hash/uhash.h>
23 #include <ripple/beast/unit_test.h>
24 #include <ripple/json/to_string.h>
25 #include <ripple/protocol/Feature.h>
26 #include <ripple/protocol/TxFlags.h>
27 #include <ripple/protocol/jss.h>
28 #include <boost/lexical_cast.hpp>
29 #include <boost/optional.hpp>
30 #include <test/jtx.h>
31 #include <utility>
32 
33 namespace ripple {
34 namespace test {
35 
36 class Env_test : public beast::unit_test::suite
37 {
38 public:
39  template <class T>
40  static std::string
41  to_string(T const& t)
42  {
43  return boost::lexical_cast<std::string>(t);
44  }
45 
46  // Declarations in Account.h
47  void
49  {
50  using namespace jtx;
51  {
52  Account a;
53  Account b(a);
54  a = b;
55  a = std::move(b);
56  Account c(std::move(a));
57  }
58  Account("alice");
59  Account("alice", KeyType::secp256k1);
60  Account("alice", KeyType::ed25519);
61  auto const gw = Account("gw");
62  [](AccountID) {}(gw);
63  auto const USD = gw["USD"];
64  void(Account("alice") < gw);
67  }
68 
69  // Declarations in amount.h
70  void
72  {
73  using namespace jtx;
74 
75  PrettyAmount(0);
76  PrettyAmount(1);
77  PrettyAmount(0u);
78  PrettyAmount(1u);
79  PrettyAmount(-1);
80  static_assert(
82  static_assert(
84  value,
85  "");
86  static_assert(
88  static_assert(
90  value,
91  "");
92 
93  try
94  {
95  XRP(0.0000001);
96  fail("missing exception");
97  }
98  catch (std::domain_error const&)
99  {
100  pass();
101  }
102  XRP(-0.000001);
103  try
104  {
105  XRP(-0.0000009);
106  fail("missing exception");
107  }
108  catch (std::domain_error const&)
109  {
110  pass();
111  }
112 
113  BEAST_EXPECT(to_string(XRP(5)) == "5 XRP");
114  BEAST_EXPECT(to_string(XRP(.80)) == "0.8 XRP");
115  BEAST_EXPECT(to_string(XRP(.005)) == "5000 drops");
116  BEAST_EXPECT(to_string(XRP(0.1)) == "0.1 XRP");
117  BEAST_EXPECT(to_string(XRP(10000)) == "10000 XRP");
118  BEAST_EXPECT(to_string(drops(10)) == "10 drops");
119  BEAST_EXPECT(to_string(drops(123400000)) == "123.4 XRP");
120  BEAST_EXPECT(to_string(XRP(-5)) == "-5 XRP");
121  BEAST_EXPECT(to_string(XRP(-.99)) == "-0.99 XRP");
122  BEAST_EXPECT(to_string(XRP(-.005)) == "-5000 drops");
123  BEAST_EXPECT(to_string(XRP(-0.1)) == "-0.1 XRP");
124  BEAST_EXPECT(to_string(drops(-10)) == "-10 drops");
125  BEAST_EXPECT(to_string(drops(-123400000)) == "-123.4 XRP");
126 
127  BEAST_EXPECT(XRP(1) == drops(1000000));
128  BEAST_EXPECT(XRP(1) == STAmount(1000000));
129  BEAST_EXPECT(STAmount(1000000) == XRP(1));
130 
131  auto const gw = Account("gw");
132  auto const USD = gw["USD"];
133  BEAST_EXPECT(to_string(USD(0)) == "0/USD(gw)");
134  BEAST_EXPECT(to_string(USD(10)) == "10/USD(gw)");
135  BEAST_EXPECT(to_string(USD(-10)) == "-10/USD(gw)");
136  BEAST_EXPECT(USD(0) == STAmount(USD, 0));
137  BEAST_EXPECT(USD(1) == STAmount(USD, 1));
138  BEAST_EXPECT(USD(-1) == STAmount(USD, -1));
139 
140  auto const get = [](AnyAmount a) { return a; };
141  BEAST_EXPECT(!get(USD(10)).is_any);
142  BEAST_EXPECT(get(any(USD(10))).is_any);
143  }
144 
145  // Test Env
146  void
148  {
149  using namespace jtx;
150  auto const n = XRP(10000);
151  auto const gw = Account("gw");
152  auto const USD = gw["USD"];
153  auto const alice = Account("alice");
154 
155  // unfunded
156  {
157  Env env(*this);
158  env(pay("alice", "bob", XRP(1000)),
159  seq(1),
160  fee(10),
161  sig("alice"),
162  ter(terNO_ACCOUNT));
163  }
164 
165  // fund
166  {
167  Env env(*this);
168 
169  // variadics
170  env.fund(n, "alice");
171  env.fund(n, "bob", "carol");
172  env.fund(n, "dave", noripple("eric"));
173  env.fund(n, "fred", noripple("gary", "hank"));
174  env.fund(n, noripple("irene"));
175  env.fund(n, noripple("jim"), "karen");
176  env.fund(n, noripple("lisa", "mary"));
177 
178  // flags
179  env.fund(n, noripple("xavier"));
180  env.require(nflags("xavier", asfDefaultRipple));
181  env.fund(n, "yana");
182  env.require(flags("yana", asfDefaultRipple));
183  }
184 
185  // trust
186  {
187  Env env(*this);
188  env.fund(n, "alice", "bob", gw);
189  env(trust("alice", USD(100)), require(lines("alice", 1)));
190  }
191 
192  // balance
193  {
194  Env env(*this);
195  BEAST_EXPECT(env.balance(alice) == 0);
196  BEAST_EXPECT(env.balance(alice, USD) != 0);
197  BEAST_EXPECT(env.balance(alice, USD) == USD(0));
198  env.fund(n, alice, gw);
199  BEAST_EXPECT(env.balance(alice) == n);
200  BEAST_EXPECT(env.balance(gw) == n);
201  env.trust(USD(1000), alice);
202  env(pay(gw, alice, USD(10)));
203  BEAST_EXPECT(to_string(env.balance("alice", USD)) == "10/USD(gw)");
204  BEAST_EXPECT(
205  to_string(env.balance(gw, alice["USD"])) == "-10/USD(alice)");
206  }
207 
208  // seq
209  {
210  Env env(*this);
211  env.fund(n, noripple("alice", gw));
212  BEAST_EXPECT(env.seq("alice") == 3);
213  BEAST_EXPECT(env.seq(gw) == 3);
214  }
215 
216  // autofill
217  {
218  Env env(*this);
219  env.fund(n, "alice");
220  env.require(balance("alice", n));
221  env(noop("alice"), fee(1), ter(telINSUF_FEE_P));
222  env(noop("alice"), seq(none), ter(temMALFORMED));
223  env(noop("alice"), seq(none), fee(10), ter(temMALFORMED));
224  env(noop("alice"), fee(none), ter(temMALFORMED));
225  env(noop("alice"), sig(none), ter(temMALFORMED));
226  env(noop("alice"), fee(autofill));
227  env(noop("alice"), fee(autofill), seq(autofill));
228  env(noop("alice"), fee(autofill), seq(autofill), sig(autofill));
229  }
230  }
231 
232  // Env::require
233  void
235  {
236  using namespace jtx;
237  Env env(*this);
238  auto const gw = Account("gw");
239  auto const USD = gw["USD"];
240  env.require(balance("alice", none));
241  env.require(balance("alice", XRP(none)));
242  env.fund(XRP(10000), "alice", gw);
243  env.require(balance("alice", USD(none)));
244  env.trust(USD(100), "alice");
245  env.require(balance("alice", XRP(10000))); // fee refunded
246  env.require(balance("alice", USD(0)));
247  env(pay(gw, "alice", USD(10)), require(balance("alice", USD(10))));
248 
249  env.require(nflags("alice", asfRequireDest));
250  env(fset("alice", asfRequireDest),
251  require(flags("alice", asfRequireDest)));
252  env(fclear("alice", asfRequireDest),
253  require(nflags("alice", asfRequireDest)));
254  }
255 
256  // Signing with secp256k1 and ed25519 keys
257  void
259  {
260  using namespace jtx;
261 
263  Account const alice("alice", KeyType::ed25519);
264  Account const bob("bob", KeyType::secp256k1);
265  Account const carol("carol");
266  env.fund(XRP(10000), alice, bob);
267 
268  // Master key only
269  env(noop(alice));
270  env(noop(bob));
271  env(noop(alice), sig("alice"), ter(tefBAD_AUTH));
272  env(noop(alice),
273  sig(Account("alice", KeyType::secp256k1)),
274  ter(tefBAD_AUTH));
275  env(noop(bob), sig(Account("bob", KeyType::ed25519)), ter(tefBAD_AUTH));
276  env(noop(alice), sig(carol), ter(tefBAD_AUTH));
277 
278  // Master and Regular key
279  env(regkey(alice, bob));
280  env(noop(alice));
281  env(noop(alice), sig(bob));
282  env(noop(alice), sig(alice));
283 
284  // Regular key only
285  env(fset(alice, asfDisableMaster), sig(alice));
286  env(noop(alice));
287  env(noop(alice), sig(bob));
288  env(noop(alice), sig(alice), ter(tefMASTER_DISABLED));
289  env(fclear(alice, asfDisableMaster),
290  sig(alice),
292  env(fclear(alice, asfDisableMaster), sig(bob));
293  env(noop(alice), sig(alice));
294  }
295 
296  // Payment basics
297  void
299  {
300  using namespace jtx;
301  Env env(*this);
302  auto const gw = Account("gateway");
303  auto const USD = gw["USD"];
304 
305  env.fund(XRP(10000), "alice", "bob", "carol", gw);
306  env.require(balance("alice", XRP(10000)));
307  env.require(balance("bob", XRP(10000)));
308  env.require(balance("carol", XRP(10000)));
309  env.require(balance(gw, XRP(10000)));
310 
311  env(pay(env.master, "alice", XRP(1000)), fee(none), ter(temMALFORMED));
312  env(pay(env.master, "alice", XRP(1000)), fee(1), ter(telINSUF_FEE_P));
313  env(pay(env.master, "alice", XRP(1000)), seq(none), ter(temMALFORMED));
314  env(pay(env.master, "alice", XRP(1000)), seq(20), ter(terPRE_SEQ));
315  env(pay(env.master, "alice", XRP(1000)), sig(none), ter(temMALFORMED));
316  env(pay(env.master, "alice", XRP(1000)), sig("bob"), ter(tefBAD_AUTH));
317 
318  env(pay(env.master, "dilbert", XRP(1000)), sig(env.master));
319 
320  env.trust(USD(100), "alice", "bob", "carol");
321  env.require(owners("alice", 1), lines("alice", 1));
322  env(rate(gw, 1.05));
323 
324  env(pay(gw, "carol", USD(50)));
325  env.require(balance("carol", USD(50)));
326  env.require(balance(gw, Account("carol")["USD"](-50)));
327 
328  env(offer("carol", XRP(50), USD(50)), require(owners("carol", 2)));
329  env(pay("alice", "bob", any(USD(10))), ter(tecPATH_DRY));
330  env(pay("alice", "bob", any(USD(10))),
331  paths(XRP),
332  sendmax(XRP(10)),
334  env(pay("alice", "bob", any(USD(10))), paths(XRP), sendmax(XRP(20)));
335  env.require(balance("bob", USD(10)));
336  env.require(balance("carol", USD(39.5)));
337 
338  env.memoize("eric");
339  env(regkey("alice", "eric"));
340  env(noop("alice"));
341  env(noop("alice"), sig("alice"));
342  env(noop("alice"), sig("eric"));
343  env(noop("alice"), sig("bob"), ter(tefBAD_AUTH));
344  env(fset("alice", asfDisableMaster), ter(tecNEED_MASTER_KEY));
345  env(fset("alice", asfDisableMaster),
346  sig("eric"),
348  env.require(nflags("alice", asfDisableMaster));
349  env(fset("alice", asfDisableMaster), sig("alice"));
350  env.require(flags("alice", asfDisableMaster));
351  env(regkey("alice", disabled), ter(tecNO_ALTERNATIVE_KEY));
352  env(noop("alice"));
353  env(noop("alice"), sig("alice"), ter(tefMASTER_DISABLED));
354  env(noop("alice"), sig("eric"));
355  env(noop("alice"), sig("bob"), ter(tefBAD_AUTH));
356  env(fclear("alice", asfDisableMaster), sig("bob"), ter(tefBAD_AUTH));
357  env(fclear("alice", asfDisableMaster),
358  sig("alice"),
360  env(fclear("alice", asfDisableMaster));
361  env.require(nflags("alice", asfDisableMaster));
362  env(regkey("alice", disabled));
363  env(noop("alice"), sig("eric"), ter(tefBAD_AUTH));
364  env(noop("alice"));
365  }
366 
367  // Rudimentary test to ensure fail_hard
368  // transactions are neither queued nor
369  // held.
370  void
372  {
373  using namespace jtx;
374  Env env(*this);
375  auto const gw = Account("gateway");
376  auto const USD = gw["USD"];
377 
378  auto const alice = Account{"alice"};
379  env.fund(XRP(10000), alice);
380 
381  auto const localTxCnt = env.app().getOPs().getLocalTxCount();
382  auto const queueTxCount =
383  env.app().getTxQ().getMetrics(*env.current()).txCount;
384  auto const openTxCount = env.current()->txCount();
385  BEAST_EXPECT(localTxCnt == 2 && queueTxCount == 0 && openTxCount == 2);
386 
387  auto applyTxn = [&env](auto&&... txnArgs) {
388  auto jt = env.jt(txnArgs...);
389  Serializer s;
390  jt.stx->add(s);
391 
393 
394  args[jss::tx_blob] = strHex(s.slice());
395  args[jss::fail_hard] = true;
396 
397  return env.rpc("json", "submit", args.toStyledString());
398  };
399 
400  auto jr = applyTxn(noop(alice), fee(1));
401 
402  BEAST_EXPECT(jr[jss::result][jss::engine_result] == "telINSUF_FEE_P");
403  BEAST_EXPECT(
404  env.app().getTxQ().getMetrics(*env.current()).txCount ==
405  queueTxCount);
406  BEAST_EXPECT(env.app().getOPs().getLocalTxCount() == localTxCnt);
407  BEAST_EXPECT(env.current()->txCount() == openTxCount);
408 
409  jr = applyTxn(noop(alice), sig("bob"));
410 
411  BEAST_EXPECT(jr[jss::result][jss::engine_result] == "tefBAD_AUTH");
412  BEAST_EXPECT(
413  env.app().getTxQ().getMetrics(*env.current()).txCount ==
414  queueTxCount);
415  BEAST_EXPECT(env.app().getOPs().getLocalTxCount() == localTxCnt);
416  BEAST_EXPECT(env.current()->txCount() == openTxCount);
417 
418  jr = applyTxn(noop(alice), seq(20));
419 
420  BEAST_EXPECT(jr[jss::result][jss::engine_result] == "terPRE_SEQ");
421  BEAST_EXPECT(
422  env.app().getTxQ().getMetrics(*env.current()).txCount ==
423  queueTxCount);
424  BEAST_EXPECT(env.app().getOPs().getLocalTxCount() == localTxCnt);
425  BEAST_EXPECT(env.current()->txCount() == openTxCount);
426 
427  jr = applyTxn(offer(alice, XRP(1000), USD(1000)));
428 
429  BEAST_EXPECT(
430  jr[jss::result][jss::engine_result] == "tecUNFUNDED_OFFER");
431  BEAST_EXPECT(
432  env.app().getTxQ().getMetrics(*env.current()).txCount ==
433  queueTxCount);
434  BEAST_EXPECT(env.app().getOPs().getLocalTxCount() == localTxCnt);
435  BEAST_EXPECT(env.current()->txCount() == openTxCount);
436 
437  jr = applyTxn(noop(alice), fee(drops(-10)));
438 
439  BEAST_EXPECT(jr[jss::result][jss::engine_result] == "temBAD_FEE");
440  BEAST_EXPECT(
441  env.app().getTxQ().getMetrics(*env.current()).txCount ==
442  queueTxCount);
443  BEAST_EXPECT(env.app().getOPs().getLocalTxCount() == localTxCnt);
444  BEAST_EXPECT(env.current()->txCount() == openTxCount);
445 
446  jr = applyTxn(noop(alice));
447 
448  BEAST_EXPECT(jr[jss::result][jss::engine_result] == "tesSUCCESS");
449  BEAST_EXPECT(env.app().getOPs().getLocalTxCount() == localTxCnt + 1);
450  BEAST_EXPECT(env.current()->txCount() == openTxCount + 1);
451  }
452 
453  // Multi-sign basics
454  void
456  {
457  using namespace jtx;
458 
459  Env env(*this);
460  env.fund(XRP(10000), "alice");
461  env(signers("alice", 1, {{"alice", 1}, {"bob", 2}}),
462  ter(temBAD_SIGNER));
463  env(signers("alice", 1, {{"bob", 1}, {"carol", 2}}));
464  env(noop("alice"));
465 
466  auto const baseFee = env.current()->fees().base;
467  env(noop("alice"), msig("bob"), fee(2 * baseFee));
468  env(noop("alice"), msig("carol"), fee(2 * baseFee));
469  env(noop("alice"), msig("bob", "carol"), fee(3 * baseFee));
470  env(noop("alice"),
471  msig("bob", "carol", "dilbert"),
472  fee(4 * baseFee),
474 
475  env(signers("alice", none));
476  }
477 
478  void
480  {
481  using namespace jtx;
482  // create syntax
483  ticket::create("alice", "bob");
484  ticket::create("alice", 60);
485  ticket::create("alice", "bob", 60);
486  ticket::create("alice", 60, "bob");
487 
488  {
490  env.fund(XRP(10000), "alice");
491  env(noop("alice"),
492  require(owners("alice", 0), tickets("alice", 0)));
493  env(ticket::create("alice"),
494  require(owners("alice", 1), tickets("alice", 1)));
495  env(ticket::create("alice"),
496  require(owners("alice", 2), tickets("alice", 2)));
497  }
498  }
499 
500  struct UDT
501  {
502  };
503 
504  void
506  {
507  struct T
508  {
509  };
510  using namespace jtx;
511  JTx jt1;
512  // Test a straightforward
513  // property
514  BEAST_EXPECT(!jt1.get<int>());
515  jt1.set<int>(7);
516  BEAST_EXPECT(jt1.get<int>());
517  BEAST_EXPECT(*jt1.get<int>() == 7);
518  BEAST_EXPECT(!jt1.get<UDT>());
519 
520  // Test that the property is
521  // replaced if it exists.
522  jt1.set<int>(17);
523  BEAST_EXPECT(jt1.get<int>());
524  BEAST_EXPECT(*jt1.get<int>() == 17);
525  BEAST_EXPECT(!jt1.get<UDT>());
526 
527  // Test that modifying the
528  // returned prop is saved
529  *jt1.get<int>() = 42;
530  BEAST_EXPECT(jt1.get<int>());
531  BEAST_EXPECT(*jt1.get<int>() == 42);
532  BEAST_EXPECT(!jt1.get<UDT>());
533 
534  // Test get() const
535  auto const& jt2 = jt1;
536  BEAST_EXPECT(jt2.get<int>());
537  BEAST_EXPECT(*jt2.get<int>() == 42);
538  BEAST_EXPECT(!jt2.get<UDT>());
539  }
540 
541  void
543  {
544  using namespace jtx;
545  Env env(*this);
546  env.fund(XRP(100000), "alice");
547  auto jt1 = env.jt(noop("alice"));
548  BEAST_EXPECT(!jt1.get<std::uint16_t>());
549  auto jt2 = env.jt(noop("alice"), prop<std::uint16_t>(-1));
550  BEAST_EXPECT(jt2.get<std::uint16_t>());
551  BEAST_EXPECT(*jt2.get<std::uint16_t>() == 65535);
552  auto jt3 = env.jt(
553  noop("alice"),
554  prop<std::string>("Hello, world!"),
555  prop<bool>(false));
556  BEAST_EXPECT(jt3.get<std::string>());
557  BEAST_EXPECT(*jt3.get<std::string>() == "Hello, world!");
558  BEAST_EXPECT(jt3.get<bool>());
559  BEAST_EXPECT(!*jt3.get<bool>());
560  }
561 
562  void
564  {
565  struct T
566  {
567  };
568  using namespace jtx;
569  JTx jt1;
570  jt1.set<int>(7);
571  BEAST_EXPECT(jt1.get<int>());
572  BEAST_EXPECT(*jt1.get<int>() == 7);
573  BEAST_EXPECT(!jt1.get<UDT>());
574  JTx jt2(jt1);
575  BEAST_EXPECT(jt2.get<int>());
576  BEAST_EXPECT(*jt2.get<int>() == 7);
577  BEAST_EXPECT(!jt2.get<UDT>());
578  JTx jt3;
579  jt3 = jt1;
580  BEAST_EXPECT(jt3.get<int>());
581  BEAST_EXPECT(*jt3.get<int>() == 7);
582  BEAST_EXPECT(!jt3.get<UDT>());
583  }
584 
585  void
587  {
588  struct T
589  {
590  };
591  using namespace jtx;
592  JTx jt1;
593  jt1.set<int>(7);
594  BEAST_EXPECT(jt1.get<int>());
595  BEAST_EXPECT(*jt1.get<int>() == 7);
596  BEAST_EXPECT(!jt1.get<UDT>());
597  JTx jt2(std::move(jt1));
598  BEAST_EXPECT(!jt1.get<int>());
599  BEAST_EXPECT(!jt1.get<UDT>());
600  BEAST_EXPECT(jt2.get<int>());
601  BEAST_EXPECT(*jt2.get<int>() == 7);
602  BEAST_EXPECT(!jt2.get<UDT>());
603  jt1 = std::move(jt2);
604  BEAST_EXPECT(!jt2.get<int>());
605  BEAST_EXPECT(!jt2.get<UDT>());
606  BEAST_EXPECT(jt1.get<int>());
607  BEAST_EXPECT(*jt1.get<int>() == 7);
608  BEAST_EXPECT(!jt1.get<UDT>());
609  }
610 
611  void
613  {
614  using namespace jtx;
615  Env env(*this);
616  env.fund(XRP(10000), "alice");
617  env(noop("alice"), memodata("data"));
618  env(noop("alice"), memoformat("format"));
619  env(noop("alice"), memotype("type"));
620  env(noop("alice"), memondata("format", "type"));
621  env(noop("alice"), memonformat("data", "type"));
622  env(noop("alice"), memontype("data", "format"));
623  env(noop("alice"), memo("data", "format", "type"));
624  env(noop("alice"),
625  memo("data1", "format1", "type1"),
626  memo("data2", "format2", "type2"));
627  }
628 
629  void
631  {
632  using namespace jtx;
633  Env env(*this);
634  JTx jt(noop("alice"));
635  memo("data", "format", "type")(env, jt);
636 
637  auto const& memo = jt.jv["Memos"][0u]["Memo"];
638  BEAST_EXPECT(
639  memo["MemoData"].asString() == strHex(std::string("data")));
640  BEAST_EXPECT(
641  memo["MemoFormat"].asString() == strHex(std::string("format")));
642  BEAST_EXPECT(
643  memo["MemoType"].asString() == strHex(std::string("type")));
644  }
645 
646  void
648  {
649  using namespace jtx;
650  Env env(*this);
651  auto seq = env.current()->seq();
652  BEAST_EXPECT(seq == env.closed()->seq() + 1);
653  env.close();
654  BEAST_EXPECT(env.closed()->seq() == seq);
655  BEAST_EXPECT(env.current()->seq() == seq + 1);
656  env.close();
657  BEAST_EXPECT(env.closed()->seq() == seq + 1);
658  BEAST_EXPECT(env.current()->seq() == seq + 2);
659  }
660 
661  void
663  {
664  using namespace jtx;
665  Env env(*this);
666  env.close();
667  env.close();
668  env.fund(XRP(100000), "alice", "bob");
669  env.close();
670  env(pay("alice", "bob", XRP(100)));
671  env.close();
672  env(noop("alice"));
673  env.close();
674  env(noop("bob"));
675  }
676 
677  void
679  {
680  using namespace jtx;
681  Env env(*this);
682  auto const gw = Account("gw");
683  auto const USD = gw["USD"];
684  env.fund(XRP(10000), "alice", "bob");
685  env.json(
686  pay("alice", "bob", USD(10)),
687  path(Account("alice")),
688  path("bob"),
689  path(USD),
690  path(~XRP),
691  path(~USD),
692  path("bob", USD, ~XRP, ~USD));
693  }
694 
695  // Test that jtx can re-sign a transaction that's already been signed.
696  void
698  {
699  using namespace jtx;
700  Env env(*this);
701 
702  env.fund(XRP(10000), "alice");
703  auto const baseFee = env.current()->fees().base;
704  std::uint32_t const aliceSeq = env.seq("alice");
705 
706  // Sign jsonNoop.
707  Json::Value jsonNoop =
708  env.json(noop("alice"), fee(baseFee), seq(aliceSeq), sig("alice"));
709  // Re-sign jsonNoop.
710  JTx jt = env.jt(jsonNoop);
711  env(jt);
712  }
713 
714  void
716  {
717  using namespace jtx;
718  Env env(*this);
719  Env_ss envs(env);
720 
721  auto const alice = Account("alice");
722  env.fund(XRP(10000), alice);
723 
724  {
725  envs(noop(alice), fee(none), seq(none))();
726 
727  // Make sure we get the right account back.
728  auto tx = env.tx();
729  if (BEAST_EXPECT(tx))
730  {
731  BEAST_EXPECT(tx->getAccountID(sfAccount) == alice.id());
732  BEAST_EXPECT(tx->getTxnType() == ttACCOUNT_SET);
733  }
734  }
735 
736  {
737  auto params = Json::Value(Json::nullValue);
738  envs(noop(alice), fee(none), seq(none))(params);
739 
740  // Make sure we get the right account back.
741  auto tx = env.tx();
742  if (BEAST_EXPECT(tx))
743  {
744  BEAST_EXPECT(tx->getAccountID(sfAccount) == alice.id());
745  BEAST_EXPECT(tx->getTxnType() == ttACCOUNT_SET);
746  }
747  }
748 
749  {
750  auto params = Json::Value(Json::objectValue);
751  // Force the factor low enough to fail
752  params[jss::fee_mult_max] = 1;
753  params[jss::fee_div_max] = 2;
754  // RPC errors result in temINVALID
755  envs(noop(alice), fee(none), seq(none), ter(temINVALID))(params);
756 
757  auto tx = env.tx();
758  BEAST_EXPECT(!tx);
759  }
760  }
761 
762  void
764  {
765  testcase("Env features");
766  using namespace jtx;
767  auto const supported = supported_amendments();
768 
769  // this finds a feature that is not in
770  // the supported amendments list and tests that it can be
771  // enabled explicitly
772 
773  auto const neverSupportedFeat = [&]() -> boost::optional<uint256> {
774  auto const n = supported.size();
775  for (size_t i = 0; i < n; ++i)
776  if (!supported[i])
777  return bitsetIndexToFeature(i);
778 
779  return boost::none;
780  }();
781 
782  if (!neverSupportedFeat)
783  {
784  log << "No unsupported features found - skipping test."
785  << std::endl;
786  pass();
787  return;
788  }
789 
790  auto hasFeature = [](Env& env, uint256 const& f) {
791  return (
792  env.app().config().features.find(f) !=
793  env.app().config().features.end());
794  };
795 
796  {
797  // default Env has all supported features
798  Env env{*this};
799  BEAST_EXPECT(
800  supported.count() == env.app().config().features.size());
801  foreachFeature(supported, [&](uint256 const& f) {
802  this->BEAST_EXPECT(hasFeature(env, f));
803  });
804  }
805 
806  {
807  // a Env FeatureBitset has *only* those features
809  BEAST_EXPECT(env.app().config().features.size() == 2);
810  foreachFeature(supported, [&](uint256 const& f) {
811  bool const has =
812  (f == featureMultiSignReserve || f == featureFlow);
813  this->BEAST_EXPECT(has == hasFeature(env, f));
814  });
815  }
816 
817  auto const missingSomeFeatures =
819  {
820  // a Env supported_features_except is missing *only* those features
821  Env env{*this, missingSomeFeatures};
822  BEAST_EXPECT(
823  env.app().config().features.size() == (supported.count() - 2));
824  foreachFeature(supported, [&](uint256 const& f) {
825  bool hasnot =
826  (f == featureMultiSignReserve || f == featureFlow);
827  this->BEAST_EXPECT(hasnot != hasFeature(env, f));
828  });
829  }
830 
831  {
832  // add a feature that is NOT in the supported amendments list
833  // along with a list of explicit amendments
834  // the unsupported feature should be enabled along with
835  // the two supported ones
836  Env env{
837  *this,
839  featureMultiSignReserve, featureFlow, *neverSupportedFeat)};
840 
841  // this app will have just 2 supported amendments and
842  // one additional never supported feature flag
843  BEAST_EXPECT(env.app().config().features.size() == (2 + 1));
844  BEAST_EXPECT(hasFeature(env, *neverSupportedFeat));
845 
846  foreachFeature(supported, [&](uint256 const& f) {
847  bool has = (f == featureMultiSignReserve || f == featureFlow);
848  this->BEAST_EXPECT(has == hasFeature(env, f));
849  });
850  }
851 
852  {
853  // add a feature that is NOT in the supported amendments list
854  // and omit a few standard amendments
855  // the unsupported features should be enabled
856  Env env{
857  *this,
858  missingSomeFeatures | FeatureBitset{*neverSupportedFeat}};
859 
860  // this app will have all supported amendments minus 2 and then the
861  // one additional never supported feature flag
862  BEAST_EXPECT(
863  env.app().config().features.size() ==
864  (supported.count() - 2 + 1));
865  BEAST_EXPECT(hasFeature(env, *neverSupportedFeat));
866  foreachFeature(supported, [&](uint256 const& f) {
867  bool hasnot =
868  (f == featureMultiSignReserve || f == featureFlow);
869  this->BEAST_EXPECT(hasnot != hasFeature(env, f));
870  });
871  }
872 
873  {
874  // add a feature that is NOT in the supported amendments list
875  // along with all supported amendments
876  // the unsupported features should be enabled
877  Env env{*this, supported_amendments().set(*neverSupportedFeat)};
878 
879  // this app will have all supported amendments and then the
880  // one additional never supported feature flag
881  BEAST_EXPECT(
882  env.app().config().features.size() == (supported.count() + 1));
883  BEAST_EXPECT(hasFeature(env, *neverSupportedFeat));
884  foreachFeature(supported, [&](uint256 const& f) {
885  this->BEAST_EXPECT(hasFeature(env, f));
886  });
887  }
888  }
889 
890  void
892  {
893  except([this] {
894  jtx::Env env{*this, jtx::envconfig([](std::unique_ptr<Config> cfg) {
895  (*cfg).deprecatedClearSection("port_rpc");
896  return cfg;
897  })};
898  });
899  pass();
900  }
901 
902  void
903  run() override
904  {
905  testAccount();
906  testAmount();
907  testEnv();
908  testRequire();
909  testKeyType();
910  testPayments();
911  testFailHard();
912  testMultiSign();
913  testTicket();
915  testProp();
916  testJTxCopy();
917  testJTxMove();
918  testMemo();
919  testMemoResult();
920  testAdvance();
921  testClose();
922  testPath();
925  testFeatures();
927  }
928 };
929 
930 BEAST_DEFINE_TESTSUITE(Env, app, ripple);
931 
932 } // namespace test
933 } // namespace ripple
ripple::test::Env_test::testJTxCopy
void testJTxCopy()
Definition: Env_test.cpp:563
ripple::test::jtx::noop
Json::Value noop(Account const &account)
The null transaction.
Definition: noop.h:31
ripple::test::Env_test::testTicket
void testTicket()
Definition: Env_test.cpp:479
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
std::domain_error
STL class.
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
std::string
STL class.
utility
ripple::test::jtx::drops
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Definition: amount.h:241
ripple::test::jtx::Env::tx
std::shared_ptr< STTx const > tx() const
Return the tx data for the last JTx.
Definition: Env.cpp:370
ripple::test::jtx::ter
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition: ter.h:33
ripple::test::jtx::owners
Match the number of items in the account's owner directory.
Definition: owners.h:69
ripple::test::jtx::Env::require
void require(Args const &... args)
Check a set of requirements.
Definition: Env.h:466
ripple::test::jtx::Env::closed
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
Definition: Env.cpp:115
std::unordered_set
STL class.
ripple::test::jtx::prop
Set a property on a JTx.
Definition: prop.h:32
ripple::test::jtx::memontype
Definition: memo.h:129
ripple::test::jtx::balance
A balance matches.
Definition: balance.h:38
ripple::test::jtx::trust
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Definition: trust.cpp:30
ripple::CashFilter::none
@ none
ripple::test::jtx::memo
Add a memo to a JTx.
Definition: memo.h:35
ripple::test::jtx::AnyAmount
Amount specifier with an option for any issuer.
Definition: amount.h:361
ripple::asfDefaultRipple
const std::uint32_t asfDefaultRipple
Definition: TxFlags.h:72
ripple::test::Env_test::testFeatures
void testFeatures()
Definition: Env_test.cpp:763
ripple::test::jtx::Env::jt
JTx jt(JsonValue &&jv, FN const &... fN)
Create a JTx from parameters.
Definition: Env.h:439
ripple::sfAccount
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
Definition: SField.h:480
ripple::test::jtx::require
Check a set of conditions.
Definition: require.h:63
std::set::emplace
T emplace(T... args)
ripple::featureMultiSignReserve
const uint256 featureMultiSignReserve
Definition: Feature.cpp:178
ripple::test::jtx::Env::balance
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
Definition: Env.cpp:174
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:240
ripple::test::Env_test::run
void run() override
Definition: Env_test.cpp:903
ripple::test::jtx::envconfig
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:49
ripple::test::jtx::memotype
Definition: memo.h:83
ripple::test::jtx::msig
Set a multisignature on a JTx.
Definition: multisign.h:58
ripple::test::jtx::memondata
Definition: memo.h:97
ripple::tefBAD_AUTH
@ tefBAD_AUTH
Definition: TER.h:145
ripple::test::jtx::Env::trust
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
Definition: Env.cpp:250
ripple::Application::getOPs
virtual NetworkOPs & getOPs()=0
ripple::test::Env_test::testPayments
void testPayments()
Definition: Env_test.cpp:298
ripple::KeyType::ed25519
@ ed25519
ripple::test::Env_test::testSignAndSubmit
void testSignAndSubmit()
Definition: Env_test.cpp:715
ripple::base_uint< 160, detail::AccountIDTag >
ripple::test::Env_test::testProp
void testProp()
Definition: Env_test.cpp:542
ripple::foreachFeature
void foreachFeature(FeatureBitset bs, F &&f)
Definition: Feature.h:339
ripple::test::Env_test::testJTxProperties
void testJTxProperties()
Definition: Env_test.cpp:505
ripple::test::Env_test::testAccount
void testAccount()
Definition: Env_test.cpp:48
ripple::tecNO_ALTERNATIVE_KEY
@ tecNO_ALTERNATIVE_KEY
Definition: TER.h:254
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
ripple::test::Env_test::testMultiSign
void testMultiSign()
Definition: Env_test.cpp:455
ripple::test::Env_test::testJTxMove
void testJTxMove()
Definition: Env_test.cpp:586
ripple::test::Env_test::testClose
void testClose()
Definition: Env_test.cpp:662
ripple::test::jtx::any
const any_t any
Returns an amount representing "any issuer".
Definition: amount.cpp:126
ripple::test::jtx::memoformat
Definition: memo.h:69
ripple::tefMASTER_DISABLED
@ tefMASTER_DISABLED
Definition: TER.h:153
ripple::test::Env_test::testExceptionalShutdown
void testExceptionalShutdown()
Definition: Env_test.cpp:891
ripple::temBAD_SIGNER
@ temBAD_SIGNER
Definition: TER.h:110
ripple::Application::config
virtual Config & config()=0
ripple::test::jtx::JTx::set
void set(std::unique_ptr< basic_prop > p)
Set a property If the property already exists, it is replaced.
Definition: JTx.h:111
ripple::test::jtx::sendmax
Sets the SendMax on a JTx.
Definition: sendmax.h:31
ripple::test::jtx::JTx
Execution context for applying a JSON transaction.
Definition: JTx.h:41
ripple::test::jtx::JTx::jv
Json::Value jv
Definition: JTx.h:43
ripple::Application::getTxQ
virtual TxQ & getTxQ()=0
ripple::test::jtx::fset
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Definition: flags.cpp:28
ripple::telINSUF_FEE_P
@ telINSUF_FEE_P
Definition: TER.h:56
ripple::set
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
Definition: BasicConfig.h:276
ripple::test::jtx::paths
Set Paths, SendMax on a JTx.
Definition: paths.h:32
ripple::STAmount
Definition: STAmount.h:42
ripple::Serializer::slice
Slice slice() const noexcept
Definition: Serializer.h:63
ripple::fixMasterKeyAsRegularKey
const uint256 fixMasterKeyAsRegularKey
Definition: Feature.cpp:180
ripple::test::jtx::path
Add a path.
Definition: paths.h:55
ripple::test::jtx::supported_amendments
FeatureBitset supported_amendments()
Definition: Env.h:70
std::uint16_t
ripple::test::jtx::sig
Set the regular signature on a JTx.
Definition: sig.h:33
ripple::featureTickets
const uint256 featureTickets
Definition: Feature.cpp:163
ripple::tecPATH_PARTIAL
@ tecPATH_PARTIAL
Definition: TER.h:240
ripple::test::Env_test::testMemoResult
void testMemoResult()
Definition: Env_test.cpp:630
ripple::test::jtx::Env::seq
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
Definition: Env.cpp:198
ripple::NetworkOPs::getLocalTxCount
virtual std::size_t getLocalTxCount()=0
ripple::test::jtx::memodata
Definition: memo.h:55
ripple::test::Env_test::testPath
void testPath()
Definition: Env_test.cpp:678
ripple::test::jtx::Env_ss
A transaction testing environment wrapper.
Definition: Env_ss.h:33
ripple::test::jtx::fclear
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Definition: flags.h:40
ripple::tecNEED_MASTER_KEY
@ tecNEED_MASTER_KEY
Definition: TER.h:266
ripple::asfRequireDest
const std::uint32_t asfRequireDest
Definition: TxFlags.h:65
ripple::test::jtx::fee
Set the fee on a JTx.
Definition: fee.h:34
ripple::test::Env_test::testEnv
void testEnv()
Definition: Env_test.cpp:147
ripple::test::Env_test::to_string
static std::string to_string(T const &t)
Definition: Env_test.cpp:41
ripple::KeyType::secp256k1
@ secp256k1
ripple::terNO_ACCOUNT
@ terNO_ACCOUNT
Definition: TER.h:190
ripple::Serializer
Definition: Serializer.h:39
ripple::asfDisableMaster
const std::uint32_t asfDisableMaster
Definition: TxFlags.h:68
ripple::test::jtx::JTx::get
Prop * get()
Return a property if it exists.
Definition: JTx.h:82
ripple::test::jtx::seq
Set the sequence number on a JTx.
Definition: seq.h:32
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::Config::features
std::unordered_set< uint256, beast::uhash<> > features
Definition: Config.h:185
ripple::test::Env_test::UDT
Definition: Env_test.cpp:500
ripple::test::jtx::flags
Match set account flags.
Definition: flags.h:108
ripple::test::jtx::noripple
std::array< Account, 1+sizeof...(Args)> noripple(Account const &account, Args const &... args)
Designate accounts as no-ripple in Env::fund.
Definition: Env.h:64
std::endl
T endl(T... args)
ripple::test::jtx::pay
Json::Value pay(Account const &account, Account const &to, AnyAmount amount)
Create a payment.
Definition: pay.cpp:29
ripple::ttACCOUNT_SET
@ ttACCOUNT_SET
Definition: TxFormats.h:39
ripple::test::Env_test::testKeyType
void testKeyType()
Definition: Env_test.cpp:258
ripple::test::jtx::Env::close
bool close(NetClock::time_point closeTime, boost::optional< std::chrono::milliseconds > consensusDelay=boost::none)
Close and advance the ledger.
Definition: Env.cpp:121
ripple::test::jtx::regkey
Json::Value regkey(Account const &account, disabled_t)
Disable the regular key.
Definition: regkey.cpp:28
ripple::featureFlow
const uint256 featureFlow
Definition: Feature.cpp:165
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:219
ripple::test::Env_test::testResignSigned
void testResignSigned()
Definition: Env_test.cpp:697
ripple::test::jtx::Env::master
Account const & master
Definition: Env.h:120
Json::nullValue
@ nullValue
'null' value
Definition: json_value.h:36
ripple::test::Env_test::testRequire
void testRequire()
Definition: Env_test.cpp:234
ripple::bitsetIndexToFeature
uint256 bitsetIndexToFeature(size_t i)
Definition: Feature.cpp:155
ripple::FeatureBitset::set
FeatureBitset & set(uint256 const &f, bool value=true)
Definition: Feature.h:220
ripple::FeatureBitset
Definition: Feature.h:155
ripple::TxQ::Metrics::txCount
std::size_t txCount
Number of transactions in the queue.
Definition: TxQ.h:186
ripple::test::Env_test::testFailHard
void testFailHard()
Definition: Env_test.cpp:371
ripple::tecPATH_DRY
@ tecPATH_DRY
Definition: TER.h:252
ripple::test::jtx::memonformat
Definition: memo.h:113
ripple::test::jtx::nflags
Match clear account flags.
Definition: flags.h:125
ripple::terPRE_SEQ
@ terPRE_SEQ
Definition: TER.h:194
std::is_trivially_constructible
ripple::test::Env_test
Definition: Env_test.cpp:36
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:67
ripple::test::Env_test::testAmount
void testAmount()
Definition: Env_test.cpp:71
ripple::temMALFORMED
@ temMALFORMED
Definition: TER.h:82
ripple::TxQ::getMetrics
Metrics getMetrics(OpenView const &view) const
Returns fee metrics in reference fee level units.
Definition: TxQ.cpp:1314
ripple::test::jtx::Env::memoize
void memoize(Account const &account)
Associate AccountID with account.
Definition: Env.cpp:150
std::unique_ptr
STL class.
std::set
STL class.
ripple::test::Env_test::testMemo
void testMemo()
Definition: Env_test.cpp:612
ripple::test::jtx::Env::current
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:299
ripple::test::jtx::Env::json
Json::Value json(JsonValue &&jv, FN const &... fN)
Create JSON from parameters.
Definition: Env.h:453
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:115
ripple::temINVALID
@ temINVALID
Definition: TER.h:105
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:684
ripple::test::Env_test::testAdvance
void testAdvance()
Definition: Env_test.cpp:647
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::test::jtx::PrettyAmount
Represents an XRP or IOU quantity This customizes the string conversion and supports XRP conversions ...
Definition: amount.h:73
ripple::get
T & get(EitherAmount &amt)
Definition: AmountSpec.h:116
ripple::test::jtx::owner_count
Definition: owners.h:49
ripple::tefBAD_SIGNATURE
@ tefBAD_SIGNATURE
Definition: TER.h:155
ripple::test::jtx::rate
Json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
Definition: rate.cpp:30