rippled
AccountTx_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2017 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/beast/unit_test.h>
21 #include <ripple/protocol/ErrorCodes.h>
22 #include <ripple/protocol/jss.h>
23 #include <test/jtx.h>
24 
25 #include <boost/container/flat_set.hpp>
26 
27 namespace ripple {
28 
29 namespace test {
30 
31 class AccountTx_test : public beast::unit_test::suite
32 {
33  // A data structure used to describe the basic structure of a
34  // transactions array node as returned by the account_tx RPC command.
35  struct NodeSanity
36  {
37  int const index;
39  boost::container::flat_set<std::string> created;
40  boost::container::flat_set<std::string> deleted;
41  boost::container::flat_set<std::string> modified;
42 
44  int idx,
45  Json::StaticString const& t,
49  : index(idx), txType(t)
50  {
51  auto buildSet = [](auto&& init) {
52  boost::container::flat_set<std::string> r;
53  r.reserve(init.size());
54  for (auto&& s : init)
55  r.insert(s);
56  return r;
57  };
58 
59  created = buildSet(c);
60  deleted = buildSet(d);
61  modified = buildSet(m);
62  }
63  };
64 
65  // A helper method tests can use to validate returned JSON vs NodeSanity.
66  void
67  checkSanity(Json::Value const& txNode, NodeSanity const& sane)
68  {
69  BEAST_EXPECT(txNode[jss::validated].asBool() == true);
70  BEAST_EXPECT(
71  txNode[jss::tx][sfTransactionType.jsonName].asString() ==
72  sane.txType);
73 
74  // Make sure all of the expected node types are present.
75  boost::container::flat_set<std::string> createdNodes;
76  boost::container::flat_set<std::string> deletedNodes;
77  boost::container::flat_set<std::string> modifiedNodes;
78 
79  for (Json::Value const& metaNode :
80  txNode[jss::meta][sfAffectedNodes.jsonName])
81  {
82  if (metaNode.isMember(sfCreatedNode.jsonName))
83  createdNodes.insert(
85  .asString());
86 
87  else if (metaNode.isMember(sfDeletedNode.jsonName))
88  deletedNodes.insert(
90  .asString());
91 
92  else if (metaNode.isMember(sfModifiedNode.jsonName))
93  modifiedNodes.insert(metaNode[sfModifiedNode.jsonName]
95  .asString());
96 
97  else
98  fail(
99  "Unexpected or unlabeled node type in metadata.",
100  __FILE__,
101  __LINE__);
102  }
103 
104  BEAST_EXPECT(createdNodes == sane.created);
105  BEAST_EXPECT(deletedNodes == sane.deleted);
106  BEAST_EXPECT(modifiedNodes == sane.modified);
107  };
108 
109  void
111  {
112  using namespace test::jtx;
113 
114  Env env(*this);
115  Account A1{"A1"};
116  env.fund(XRP(10000), A1);
117  env.close();
118 
119  // Ledger 3 has the two txs associated with funding the account
120  // All other ledgers have no txs
121 
122  auto hasTxs = [](Json::Value const& j) {
123  return j.isMember(jss::result) &&
124  (j[jss::result][jss::status] == "success") &&
125  (j[jss::result][jss::transactions].size() == 2) &&
126  (j[jss::result][jss::transactions][0u][jss::tx]
127  [jss::TransactionType] == jss::AccountSet) &&
128  (j[jss::result][jss::transactions][1u][jss::tx]
129  [jss::TransactionType] == jss::Payment);
130  };
131 
132  auto noTxs = [](Json::Value const& j) {
133  return j.isMember(jss::result) &&
134  (j[jss::result][jss::status] == "success") &&
135  (j[jss::result][jss::transactions].size() == 0);
136  };
137 
138  auto isErr = [](Json::Value const& j, error_code_i code) {
139  return j.isMember(jss::result) &&
140  j[jss::result].isMember(jss::error) &&
141  j[jss::result][jss::error] == RPC::get_error_info(code).token;
142  };
143 
144  Json::Value jParms;
145 
146  BEAST_EXPECT(isErr(
147  env.rpc("json", "account_tx", to_string(jParms)),
149 
150  jParms[jss::account] = "0xDEADBEEF";
151 
152  BEAST_EXPECT(isErr(
153  env.rpc("json", "account_tx", to_string(jParms)),
155 
156  jParms[jss::account] = A1.human();
157  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(jParms))));
158 
159  // Ledger min/max index
160  {
161  Json::Value p{jParms};
162  p[jss::ledger_index_min] = -1;
163  p[jss::ledger_index_max] = -1;
164  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
165 
166  p[jss::ledger_index_min] = 0;
167  p[jss::ledger_index_max] = 100;
168  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
169 
170  p[jss::ledger_index_min] = 1;
171  p[jss::ledger_index_max] = 2;
172  BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p))));
173 
174  p[jss::ledger_index_min] = 2;
175  p[jss::ledger_index_max] = 1;
176  BEAST_EXPECT(isErr(
177  env.rpc("json", "account_tx", to_string(p)),
179  }
180 
181  // Ledger index min only
182  {
183  Json::Value p{jParms};
184  p[jss::ledger_index_min] = -1;
185  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
186 
187  p[jss::ledger_index_min] = 1;
188  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
189 
190  p[jss::ledger_index_min] = env.current()->info().seq;
191  BEAST_EXPECT(isErr(
192  env.rpc("json", "account_tx", to_string(p)),
194  }
195 
196  // Ledger index max only
197  {
198  Json::Value p{jParms};
199  p[jss::ledger_index_max] = -1;
200  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
201 
202  p[jss::ledger_index_max] = env.current()->info().seq;
203  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
204 
205  p[jss::ledger_index_max] = env.closed()->info().seq;
206  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
207 
208  p[jss::ledger_index_max] = env.closed()->info().seq - 1;
209  BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p))));
210  }
211 
212  // Ledger Sequence
213  {
214  Json::Value p{jParms};
215 
216  p[jss::ledger_index] = env.closed()->info().seq;
217  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
218 
219  p[jss::ledger_index] = env.closed()->info().seq - 1;
220  BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p))));
221 
222  p[jss::ledger_index] = env.current()->info().seq;
223  BEAST_EXPECT(isErr(
224  env.rpc("json", "account_tx", to_string(p)),
226 
227  p[jss::ledger_index] = env.current()->info().seq + 1;
228  BEAST_EXPECT(isErr(
229  env.rpc("json", "account_tx", to_string(p)), rpcLGR_NOT_FOUND));
230  }
231 
232  // Ledger Hash
233  {
234  Json::Value p{jParms};
235 
236  p[jss::ledger_hash] = to_string(env.closed()->info().hash);
237  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
238 
239  p[jss::ledger_hash] = to_string(env.closed()->info().parentHash);
240  BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p))));
241  }
242  }
243 
244  void
246  {
247  // Get results for all transaction types that can be associated
248  // with an account. Start by generating all transaction types.
249  using namespace test::jtx;
250  using namespace std::chrono_literals;
251 
252  Env env(*this);
253  Account const alice{"alice"};
254  Account const alie{"alie"};
255  Account const gw{"gw"};
256  auto const USD{gw["USD"]};
257 
258  env.fund(XRP(1000000), alice, gw);
259  env.close();
260 
261  // AccountSet
262  env(noop(alice));
263 
264  // Payment
265  env(pay(alice, gw, XRP(100)));
266 
267  // Regular key set
268  env(regkey(alice, alie));
269  env.close();
270 
271  // Trust and Offers
272  env(trust(alice, USD(200)), sig(alie));
273  std::uint32_t const offerSeq{env.seq(alice)};
274  env(offer(alice, USD(50), XRP(150)), sig(alie));
275  env.close();
276 
277  {
278  Json::Value cancelOffer;
279  cancelOffer[jss::Account] = alice.human();
280  cancelOffer[jss::OfferSequence] = offerSeq;
281  cancelOffer[jss::TransactionType] = jss::OfferCancel;
282  env(cancelOffer, sig(alie));
283  }
284  env.close();
285 
286  // SignerListSet
287  env(signers(alice, 1, {{"bogie", 1}, {"demon", 1}}), sig(alie));
288 
289  // Escrow
290  {
291  // Create an escrow. Requires either a CancelAfter or FinishAfter.
292  auto escrow = [](Account const& account,
293  Account const& to,
294  STAmount const& amount) {
295  Json::Value escro;
296  escro[jss::TransactionType] = jss::EscrowCreate;
297  escro[jss::Flags] = tfUniversal;
298  escro[jss::Account] = account.human();
299  escro[jss::Destination] = to.human();
300  escro[jss::Amount] = amount.getJson(JsonOptions::none);
301  return escro;
302  };
303 
304  NetClock::time_point const nextTime{env.now() + 2s};
305 
306  Json::Value escrowWithFinish{escrow(alice, alice, XRP(500))};
307  escrowWithFinish[sfFinishAfter.jsonName] =
308  nextTime.time_since_epoch().count();
309 
310  std::uint32_t const escrowFinishSeq{env.seq(alice)};
311  env(escrowWithFinish, sig(alie));
312 
313  Json::Value escrowWithCancel{escrow(alice, alice, XRP(500))};
314  escrowWithCancel[sfFinishAfter.jsonName] =
315  nextTime.time_since_epoch().count();
316  escrowWithCancel[sfCancelAfter.jsonName] =
317  nextTime.time_since_epoch().count() + 1;
318 
319  std::uint32_t const escrowCancelSeq{env.seq(alice)};
320  env(escrowWithCancel, sig(alie));
321  env.close();
322 
323  {
324  Json::Value escrowFinish;
325  escrowFinish[jss::TransactionType] = jss::EscrowFinish;
326  escrowFinish[jss::Flags] = tfUniversal;
327  escrowFinish[jss::Account] = alice.human();
328  escrowFinish[sfOwner.jsonName] = alice.human();
329  escrowFinish[sfOfferSequence.jsonName] = escrowFinishSeq;
330  env(escrowFinish, sig(alie));
331  }
332  {
333  Json::Value escrowCancel;
334  escrowCancel[jss::TransactionType] = jss::EscrowCancel;
335  escrowCancel[jss::Flags] = tfUniversal;
336  escrowCancel[jss::Account] = alice.human();
337  escrowCancel[sfOwner.jsonName] = alice.human();
338  escrowCancel[sfOfferSequence.jsonName] = escrowCancelSeq;
339  env(escrowCancel, sig(alie));
340  }
341  env.close();
342  }
343 
344  // PayChan
345  {
346  std::uint32_t payChanSeq{env.seq(alice)};
347  Json::Value payChanCreate;
348  payChanCreate[jss::TransactionType] = jss::PaymentChannelCreate;
349  payChanCreate[jss::Flags] = tfUniversal;
350  payChanCreate[jss::Account] = alice.human();
351  payChanCreate[jss::Destination] = gw.human();
352  payChanCreate[jss::Amount] =
353  XRP(500).value().getJson(JsonOptions::none);
354  payChanCreate[sfSettleDelay.jsonName] =
355  NetClock::duration{100s}.count();
356  payChanCreate[sfPublicKey.jsonName] = strHex(alice.pk().slice());
357  env(payChanCreate, sig(alie));
358  env.close();
359 
360  std::string const payChanIndex{
361  strHex(keylet::payChan(alice, gw, payChanSeq).key)};
362 
363  {
364  Json::Value payChanFund;
365  payChanFund[jss::TransactionType] = jss::PaymentChannelFund;
366  payChanFund[jss::Flags] = tfUniversal;
367  payChanFund[jss::Account] = alice.human();
368  payChanFund[sfPayChannel.jsonName] = payChanIndex;
369  payChanFund[jss::Amount] =
370  XRP(200).value().getJson(JsonOptions::none);
371  env(payChanFund, sig(alie));
372  env.close();
373  }
374  {
375  Json::Value payChanClaim;
376  payChanClaim[jss::TransactionType] = jss::PaymentChannelClaim;
377  payChanClaim[jss::Flags] = tfClose;
378  payChanClaim[jss::Account] = gw.human();
379  payChanClaim[sfPayChannel.jsonName] = payChanIndex;
380  payChanClaim[sfPublicKey.jsonName] = strHex(alice.pk().slice());
381  env(payChanClaim);
382  env.close();
383  }
384  }
385 
386  // Check
387  {
388  auto const aliceCheckId = keylet::check(alice, env.seq(alice)).key;
389  env(check::create(alice, gw, XRP(300)), sig(alie));
390 
391  auto const gwCheckId = keylet::check(gw, env.seq(gw)).key;
392  env(check::create(gw, alice, XRP(200)));
393  env.close();
394 
395  env(check::cash(alice, gwCheckId, XRP(200)), sig(alie));
396  env(check::cancel(alice, aliceCheckId), sig(alie));
397  env.close();
398  }
399 
400  // Deposit preauthorization.
401  env(deposit::auth(alice, gw), sig(alie));
402  env.close();
403 
404  // Setup is done. Look at the transactions returned by account_tx.
405  Json::Value params;
406  params[jss::account] = alice.human();
407  params[jss::ledger_index_min] = -1;
408  params[jss::ledger_index_max] = -1;
409 
410  Json::Value const result{
411  env.rpc("json", "account_tx", to_string(params))};
412 
413  BEAST_EXPECT(result[jss::result][jss::status] == "success");
414  BEAST_EXPECT(result[jss::result][jss::transactions].isArray());
415 
416  Json::Value const& txs{result[jss::result][jss::transactions]};
417 
418  // clang-format off
419  // Do a sanity check on each returned transaction. They should
420  // be returned in the reverse order of application to the ledger.
421  static const NodeSanity sanity[]{
422  // txType, created, deleted, modified
423  { 0, jss::DepositPreauth, {jss::DepositPreauth}, {}, {jss::AccountRoot, jss::DirectoryNode}},
424  { 1, jss::CheckCancel, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
425  { 2, jss::CheckCash, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
426  { 3, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
427  { 4, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
428  { 5, jss::PaymentChannelClaim, {}, {jss::PayChannel}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
429  { 6, jss::PaymentChannelFund, {}, {}, {jss::AccountRoot, jss::PayChannel }},
430  { 7, jss::PaymentChannelCreate, {jss::PayChannel}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
431  { 8, jss::EscrowCancel, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}},
432  { 9, jss::EscrowFinish, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}},
433  { 10, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},
434  { 11, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},
435  { 12, jss::SignerListSet, {jss::SignerList}, {}, {jss::AccountRoot, jss::DirectoryNode}},
436  { 13, jss::OfferCancel, {}, {jss::Offer, jss::DirectoryNode}, {jss::AccountRoot, jss::DirectoryNode}},
437  { 14, jss::OfferCreate, {jss::Offer, jss::DirectoryNode}, {}, {jss::AccountRoot, jss::DirectoryNode}},
438  { 15, jss::TrustSet, {jss::RippleState, jss::DirectoryNode, jss::DirectoryNode}, {}, {jss::AccountRoot, jss::AccountRoot}},
439  { 16, jss::SetRegularKey, {}, {}, {jss::AccountRoot}},
440  { 17, jss::Payment, {}, {}, {jss::AccountRoot, jss::AccountRoot}},
441  { 18, jss::AccountSet, {}, {}, {jss::AccountRoot}},
442  { 19, jss::AccountSet, {}, {}, {jss::AccountRoot}},
443  { 20, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}},
444  };
445  // clang-format on
446 
447  BEAST_EXPECT(
448  std::size(sanity) == result[jss::result][jss::transactions].size());
449 
450  for (unsigned int index{0}; index < std::size(sanity); ++index)
451  {
452  checkSanity(txs[index], sanity[index]);
453  }
454  }
455 
456  void
458  {
459  // Verify that if an account is resurrected then the account_tx RPC
460  // command still recovers all transactions on that account before
461  // and after resurrection.
462  using namespace test::jtx;
463  using namespace std::chrono_literals;
464 
465  Env env(*this);
466  Account const alice{"alice"};
467  Account const becky{"becky"};
468 
469  env.fund(XRP(10000), alice, becky);
470  env.close();
471 
472  // Verify that becky's account root is present.
473  Keylet const beckyAcctKey{keylet::account(becky.id())};
474  BEAST_EXPECT(env.closed()->exists(beckyAcctKey));
475 
476  // becky does an AccountSet .
477  env(noop(becky));
478 
479  // Close enough ledgers to be able to delete becky's account.
480  std::uint32_t const ledgerCount{
481  env.current()->seq() + 257 - env.seq(becky)};
482 
483  for (std::uint32_t i = 0; i < ledgerCount; ++i)
484  env.close();
485 
486  auto const beckyPreDelBalance{env.balance(becky)};
487 
488  auto const acctDelFee{drops(env.current()->fees().increment)};
489  env(acctdelete(becky, alice), fee(acctDelFee));
490  env.close();
491 
492  // Verify that becky's account root is gone.
493  BEAST_EXPECT(!env.closed()->exists(beckyAcctKey));
494  env.close();
495 
496  // clang-format off
497  // Do a sanity check on each returned transaction. They should
498  // be returned in the reverse order of application to the ledger.
499  //
500  // Note that the first two transactions in sanity have not occurred
501  // yet. We'll see those after becky's account is resurrected.
502  static const NodeSanity sanity[]
503  {
504  // txType, created, deleted, modified
505 /* becky pays alice */ { 0, jss::Payment, {}, {}, {jss::AccountRoot, jss::AccountRoot}},
506 /* alice resurrects becky's acct */ { 1, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}},
507 /* becky deletes her account */ { 2, jss::AccountDelete, {}, {jss::AccountRoot}, {jss::AccountRoot}},
508 /* becky's noop */ { 3, jss::AccountSet, {}, {}, {jss::AccountRoot}},
509 /* "fund" sets flags */ { 4, jss::AccountSet, {}, {}, {jss::AccountRoot}},
510 /* "fund" creates becky's acct */ { 5, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}}
511  };
512  // clang-format on
513 
514  // Verify that we can recover becky's account_tx information even
515  // after the account is deleted.
516  {
517  Json::Value params;
518  params[jss::account] = becky.human();
519  params[jss::ledger_index_min] = -1;
520  params[jss::ledger_index_max] = -1;
521 
522  Json::Value const result{
523  env.rpc("json", "account_tx", to_string(params))};
524 
525  BEAST_EXPECT(result[jss::result][jss::status] == "success");
526  BEAST_EXPECT(result[jss::result][jss::transactions].isArray());
527 
528  // The first two transactions listed in sanity haven't happened yet.
529  constexpr unsigned int beckyDeletedOffest = 2;
530  BEAST_EXPECT(
531  std::size(sanity) ==
532  result[jss::result][jss::transactions].size() +
533  beckyDeletedOffest);
534 
535  Json::Value const& txs{result[jss::result][jss::transactions]};
536 
537  for (unsigned int index = beckyDeletedOffest;
538  index < std::size(sanity);
539  ++index)
540  {
541  checkSanity(txs[index - beckyDeletedOffest], sanity[index]);
542  }
543  }
544 
545  // All it takes is a large enough XRP payment to resurrect
546  // becky's account. Try too small a payment.
547  env(pay(alice, becky, XRP(19)), ter(tecNO_DST_INSUF_XRP));
548  env.close();
549 
550  // Actually resurrect becky's account.
551  env(pay(alice, becky, XRP(45)));
552  env.close();
553 
554  // becky's account root should be back.
555  BEAST_EXPECT(env.closed()->exists(beckyAcctKey));
556  BEAST_EXPECT(env.balance(becky) == XRP(45));
557 
558  // becky pays alice.
559  env(pay(becky, alice, XRP(20)));
560  env.close();
561 
562  // Setup is done. Look at the transactions returned by account_tx.
563  // Verify that account_tx locates all of becky's transactions.
564  Json::Value params;
565  params[jss::account] = becky.human();
566  params[jss::ledger_index_min] = -1;
567  params[jss::ledger_index_max] = -1;
568 
569  Json::Value const result{
570  env.rpc("json", "account_tx", to_string(params))};
571 
572  BEAST_EXPECT(result[jss::result][jss::status] == "success");
573  BEAST_EXPECT(result[jss::result][jss::transactions].isArray());
574 
575  BEAST_EXPECT(
576  std::size(sanity) == result[jss::result][jss::transactions].size());
577 
578  Json::Value const& txs{result[jss::result][jss::transactions]};
579 
580  for (unsigned int index = 0; index < std::size(sanity); ++index)
581  {
582  checkSanity(txs[index], sanity[index]);
583  }
584  }
585 
586 public:
587  void
588  run() override
589  {
590  testParameters();
591  testContents();
593  }
594 };
595 BEAST_DEFINE_TESTSUITE(AccountTx, app, ripple);
596 
597 } // namespace test
598 } // namespace ripple
ripple::test::AccountTx_test::testParameters
void testParameters()
Definition: AccountTx_test.cpp:110
ripple::test::AccountTx_test::NodeSanity::NodeSanity
NodeSanity(int idx, Json::StaticString const &t, std::initializer_list< char const * > c, std::initializer_list< char const * > d, std::initializer_list< char const * > m)
Definition: AccountTx_test.cpp:43
ripple::test::AccountTx_test::NodeSanity::txType
Json::StaticString const & txType
Definition: AccountTx_test.cpp:38
ripple::test::jtx::noop
Json::Value noop(Account const &account)
The null transaction.
Definition: noop.h:31
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
ripple::Keylet
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:38
ripple::rpcLGR_IDXS_INVALID
@ rpcLGR_IDXS_INVALID
Definition: ErrorCodes.h:112
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
std::string
STL class.
ripple::rpcINVALID_PARAMS
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:84
ripple::HashPrefix::txNode
@ txNode
transaction plus metadata
ripple::test::jtx::drops
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Definition: amount.h:241
ripple::sfLedgerEntryType
const SF_U16 sfLedgerEntryType(access, STI_UINT16, 1, "LedgerEntryType", SField::sMD_Never)
Definition: SField.h:345
ripple::RPC::get_error_info
ErrorInfo const & get_error_info(error_code_i code)
Returns an ErrorInfo that reflects the error code.
Definition: ErrorCodes.cpp:194
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::Env::closed
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
Definition: Env.cpp:105
ripple::tfClose
const std::uint32_t tfClose
Definition: TxFlags.h:106
std::size
T size(T... args)
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
std::chrono::duration
ripple::test::AccountTx_test::NodeSanity::index
const int index
Definition: AccountTx_test.cpp:37
ripple::test::AccountTx_test::NodeSanity
Definition: AccountTx_test.cpp:35
ripple::test::jtx::Env::balance
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
Definition: Env.cpp:164
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
ripple::sfPayChannel
const SF_U256 sfPayChannel(access, STI_HASH256, 22, "Channel")
Definition: SField.h:433
ripple::test::AccountTx_test::testContents
void testContents()
Definition: AccountTx_test.cpp:245
ripple::rpcLGR_NOT_FOUND
@ rpcLGR_NOT_FOUND
Definition: ErrorCodes.h:72
ripple::sfModifiedNode
const SField sfModifiedNode(access, STI_OBJECT, 5, "ModifiedNode")
Definition: SField.h:498
ripple::SField::jsonName
const Json::StaticString jsonName
Definition: SField.h:133
ripple::sfFinishAfter
const SF_U32 sfFinishAfter(access, STI_UINT32, 37, "FinishAfter")
Definition: SField.h:389
ripple::error_code_i
error_code_i
Definition: ErrorCodes.h:40
ripple::tecNO_DST_INSUF_XRP
@ tecNO_DST_INSUF_XRP
Definition: TER.h:249
ripple::Keylet::key
uint256 key
Definition: Keylet.h:41
ripple::test::AccountTx_test::run
void run() override
Definition: AccountTx_test.cpp:588
ripple::sfOwner
const SF_Account sfOwner(access, STI_ACCOUNT, 2, "Owner")
Definition: SField.h:477
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:120
ripple::JsonOptions::none
@ none
ripple::sfTransactionType
const SF_U16 sfTransactionType(access, STI_UINT16, 2, "TransactionType")
Definition: SField.h:346
ripple::STAmount
Definition: STAmount.h:42
ripple::test::AccountTx_test::NodeSanity::deleted
boost::container::flat_set< std::string > deleted
Definition: AccountTx_test.cpp:40
std::chrono::time_point
ripple::test::AccountTx_test
Definition: AccountTx_test.cpp:31
Json::Value::isMember
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:932
std::uint32_t
ripple::test::jtx::sig
Set the regular signature on a JTx.
Definition: sig.h:33
ripple::test::jtx::Env::seq
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
Definition: Env.cpp:188
ripple::sfCreatedNode
const SField sfCreatedNode(access, STI_OBJECT, 3, "CreatedNode")
Definition: SField.h:496
ripple::tfUniversal
const std::uint32_t tfUniversal
Definition: TxFlags.h:49
ripple::test::jtx::fee
Set the fee on a JTx.
Definition: fee.h:34
ripple::sfPublicKey
const SF_Blob sfPublicKey(access, STI_VL, 1, "PublicKey")
Definition: SField.h:456
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::rpcACT_MALFORMED
@ rpcACT_MALFORMED
Definition: ErrorCodes.h:90
ripple::test::AccountTx_test::testAccountDelete
void testAccountDelete()
Definition: AccountTx_test.cpp:457
ripple::test::jtx::pay
Json::Value pay(Account const &account, Account const &to, AnyAmount amount)
Create a payment.
Definition: pay.cpp:29
ripple::test::jtx::Env::now
NetClock::time_point now()
Returns the current Ripple Network Time.
Definition: Env.h:261
ripple::keylet::payChan
Keylet payChan(AccountID const &src, AccountID const &dst, std::uint32_t seq) noexcept
A PaymentChannel.
Definition: Indexes.cpp:297
ripple::sfOfferSequence
const SF_U32 sfOfferSequence(access, STI_UINT32, 25, "OfferSequence")
Definition: SField.h:377
ripple::rpcLGR_NOT_VALIDATED
@ rpcLGR_NOT_VALIDATED
Definition: ErrorCodes.h:73
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:111
ripple::sfAffectedNodes
const SField sfAffectedNodes(access, STI_ARRAY, 8, "AffectedNodes")
Definition: SField.h:516
ripple::test::jtx::regkey
Json::Value regkey(Account const &account, disabled_t)
Disable the regular key.
Definition: regkey.cpp:28
Json::StaticString
Lightweight wrapper to tag static string.
Definition: json_value.h:60
ripple::test::AccountTx_test::checkSanity
void checkSanity(Json::Value const &txNode, NodeSanity const &sane)
Definition: AccountTx_test.cpp:67
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:209
ripple::test::jtx::acctdelete
Json::Value acctdelete(Account const &account, Account const &dest)
Delete account.
Definition: acctdelete.cpp:29
std::chrono::duration::count
T count(T... args)
ripple::sfSettleDelay
const SF_U32 sfSettleDelay(access, STI_UINT32, 39, "SettleDelay")
Definition: SField.h:391
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::AccountTx_test::NodeSanity::modified
boost::container::flat_set< std::string > modified
Definition: AccountTx_test.cpp:41
ripple::test::AccountTx_test::NodeSanity::created
boost::container::flat_set< std::string > created
Definition: AccountTx_test.cpp:39
ripple::sfDeletedNode
const SField sfDeletedNode(access, STI_OBJECT, 4, "DeletedNode")
Definition: SField.h:497
ripple::keylet::check
Keylet check(AccountID const &id, std::uint32_t seq) noexcept
A Check.
Definition: Indexes.cpp:254
ripple::test::jtx::Env::current
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:297
ripple::sfCancelAfter
const SF_U32 sfCancelAfter(access, STI_UINT32, 36, "CancelAfter")
Definition: SField.h:388
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:114
ripple::RPC::ErrorInfo::token
Json::StaticString token
Definition: ErrorCodes.h:174
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:682
Json::Value
Represents a JSON value.
Definition: json_value.h:145
std::initializer_list