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