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