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 (
84  metaNode[sfCreatedNode.jsonName]
85  [sfLedgerEntryType.jsonName].asString());
86 
87  else if (metaNode.isMember (sfDeletedNode.jsonName))
88  deletedNodes.insert (
89  metaNode[sfDeletedNode.jsonName]
90  [sfLedgerEntryType.jsonName].asString());
91 
92  else if (metaNode.isMember (sfModifiedNode.jsonName))
93  modifiedNodes.insert (
94  metaNode[sfModifiedNode.jsonName]
95  [sfLedgerEntryType.jsonName].asString());
96 
97  else
98  fail ("Unexpected or unlabeled node type in metadata.",
99  __FILE__, __LINE__);
100  }
101 
102  BEAST_EXPECT(createdNodes == sane.created);
103  BEAST_EXPECT(deletedNodes == sane.deleted);
104  BEAST_EXPECT(modifiedNodes == sane.modified);
105  };
106 
107  void
109  {
110  using namespace test::jtx;
111 
112  Env env(*this);
113  Account A1{"A1"};
114  env.fund(XRP(10000), A1);
115  env.close();
116 
117  // Ledger 3 has the two txs associated with funding the account
118  // All other ledgers have no txs
119 
120  auto hasTxs = [](Json::Value const& j) {
121  return j.isMember(jss::result) &&
122  (j[jss::result][jss::status] == "success") &&
123  (j[jss::result][jss::transactions].size() == 2) &&
124  (j[jss::result][jss::transactions][0u][jss::tx]
125  [jss::TransactionType] == jss::AccountSet) &&
126  (j[jss::result][jss::transactions][1u][jss::tx]
127  [jss::TransactionType] == jss::Payment);
128  };
129 
130  auto noTxs = [](Json::Value const& j) {
131  return j.isMember(jss::result) &&
132  (j[jss::result][jss::status] == "success") &&
133  (j[jss::result][jss::transactions].size() == 0);
134  };
135 
136  auto isErr = [](Json::Value const& j, error_code_i code) {
137  return j.isMember(jss::result) &&
138  j[jss::result].isMember(jss::error) &&
139  j[jss::result][jss::error] == RPC::get_error_info(code).token;
140  };
141 
142  Json::Value jParms;
143 
144  BEAST_EXPECT(isErr(
145  env.rpc("json", "account_tx", to_string(jParms)),
147 
148  jParms[jss::account] = "0xDEADBEEF";
149 
150  BEAST_EXPECT(isErr(
151  env.rpc("json", "account_tx", to_string(jParms)),
153 
154  jParms[jss::account] = A1.human();
155  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(jParms))));
156 
157  // Ledger min/max index
158  {
159  Json::Value p{jParms};
160  p[jss::ledger_index_min] = -1;
161  p[jss::ledger_index_max] = -1;
162  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
163 
164  p[jss::ledger_index_min] = 0;
165  p[jss::ledger_index_max] = 100;
166  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
167 
168  p[jss::ledger_index_min] = 1;
169  p[jss::ledger_index_max] = 2;
170  BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p))));
171 
172  p[jss::ledger_index_min] = 2;
173  p[jss::ledger_index_max] = 1;
174  BEAST_EXPECT(isErr(
175  env.rpc("json", "account_tx", to_string(p)),
177  }
178 
179  // Ledger index min only
180  {
181  Json::Value p{jParms};
182  p[jss::ledger_index_min] = -1;
183  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
184 
185  p[jss::ledger_index_min] = 1;
186  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
187 
188  p[jss::ledger_index_min] = env.current()->info().seq;
189  BEAST_EXPECT(isErr(
190  env.rpc("json", "account_tx", to_string(p)),
192  }
193 
194  // Ledger index max only
195  {
196  Json::Value p{jParms};
197  p[jss::ledger_index_max] = -1;
198  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
199 
200  p[jss::ledger_index_max] = env.current()->info().seq;
201  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
202 
203  p[jss::ledger_index_max] = env.closed()->info().seq;
204  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
205 
206  p[jss::ledger_index_max] = env.closed()->info().seq - 1 ;
207  BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p))));
208  }
209 
210  // Ledger Sequence
211  {
212  Json::Value p{jParms};
213 
214  p[jss::ledger_index] = env.closed()->info().seq;
215  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
216 
217  p[jss::ledger_index] = env.closed()->info().seq - 1;
218  BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p))));
219 
220  p[jss::ledger_index] = env.current()->info().seq;
221  BEAST_EXPECT(isErr(
222  env.rpc("json", "account_tx", to_string(p)),
224 
225  p[jss::ledger_index] = env.current()->info().seq + 1;
226  BEAST_EXPECT(isErr(
227  env.rpc("json", "account_tx", to_string(p)),
229  }
230 
231  // Ledger Hash
232  {
233  Json::Value p{jParms};
234 
235  p[jss::ledger_hash] = to_string(env.closed()->info().hash);
236  BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p))));
237 
238  p[jss::ledger_hash] = to_string(env.closed()->info().parentHash);
239  BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p))));
240  }
241  }
242 
243  void
245  {
246  // Get results for all transaction types that can be associated
247  // with an account. Start by generating all transaction types.
248  using namespace test::jtx;
249  using namespace std::chrono_literals;
250 
251  Env env(*this);
252  Account const alice {"alice"};
253  Account const alie {"alie"};
254  Account const gw {"gw"};
255  auto const USD {gw["USD"]};
256 
257  env.fund(XRP(1000000), alice, gw);
258  env.close();
259 
260  // AccountSet
261  env (noop (alice));
262 
263  // Payment
264  env (pay (alice, gw, XRP (100)));
265 
266  // Regular key set
267  env (regkey(alice, alie));
268  env.close();
269 
270  // Trust and Offers
271  env (trust (alice, USD (200)), sig (alie));
272  std::uint32_t const offerSeq {env.seq(alice)};
273  env (offer (alice, USD (50), XRP (150)), sig (alie));
274  env.close();
275 
276  {
277  Json::Value cancelOffer;
278  cancelOffer[jss::Account] = alice.human();
279  cancelOffer[jss::OfferSequence] = offerSeq;
280  cancelOffer[jss::TransactionType] = jss::OfferCancel;
281  env (cancelOffer, sig (alie));
282  }
283  env.close();
284 
285  // SignerListSet
286  env (signers (alice, 1, {{"bogie", 1}, {"demon", 1}}), sig (alie));
287 
288  // Escrow
289  {
290  // Create an escrow. Requires either a CancelAfter or FinishAfter.
291  auto escrow = [] (Account const& account,
292  Account const& to, STAmount const& amount)
293  {
294  Json::Value escro;
295  escro[jss::TransactionType] = jss::EscrowCreate;
296  escro[jss::Flags] = tfUniversal;
297  escro[jss::Account] = account.human();
298  escro[jss::Destination] = to.human();
299  escro[jss::Amount] = amount.getJson(JsonOptions::none);
300  return escro;
301  };
302 
303  NetClock::time_point const nextTime {env.now() + 2s};
304 
305  Json::Value escrowWithFinish {escrow (alice, alice, XRP (500))};
306  escrowWithFinish[sfFinishAfter.jsonName] =
307  nextTime.time_since_epoch().count();
308 
309  std::uint32_t const escrowFinishSeq {env.seq(alice)};
310  env (escrowWithFinish, sig (alie));
311 
312  Json::Value escrowWithCancel {escrow (alice, alice, XRP (500))};
313  escrowWithCancel[sfFinishAfter.jsonName] =
314  nextTime.time_since_epoch().count();
315  escrowWithCancel[sfCancelAfter.jsonName] =
316  nextTime.time_since_epoch().count() + 1;
317 
318  std::uint32_t const escrowCancelSeq {env.seq(alice)};
319  env (escrowWithCancel, sig (alie));
320  env.close();
321 
322  {
323  Json::Value escrowFinish;
324  escrowFinish[jss::TransactionType] = jss::EscrowFinish;
325  escrowFinish[jss::Flags] = tfUniversal;
326  escrowFinish[jss::Account] = alice.human();
327  escrowFinish[sfOwner.jsonName] = alice.human();
328  escrowFinish[sfOfferSequence.jsonName] = escrowFinishSeq;
329  env (escrowFinish, sig (alie));
330  }
331  {
332  Json::Value escrowCancel;
333  escrowCancel[jss::TransactionType] = jss::EscrowCancel;
334  escrowCancel[jss::Flags] = tfUniversal;
335  escrowCancel[jss::Account] = alice.human();
336  escrowCancel[sfOwner.jsonName] = alice.human();
337  escrowCancel[sfOfferSequence.jsonName] = escrowCancelSeq;
338  env (escrowCancel, sig (alie));
339  }
340  env.close();
341  }
342 
343  // PayChan
344  {
345  std::uint32_t payChanSeq {env.seq (alice)};
346  Json::Value payChanCreate;
347  payChanCreate[jss::TransactionType] = jss::PaymentChannelCreate;
348  payChanCreate[jss::Flags] = tfUniversal;
349  payChanCreate[jss::Account] = alice.human();
350  payChanCreate[jss::Destination] = gw.human();
351  payChanCreate[jss::Amount] =
352  XRP (500).value().getJson (JsonOptions::none);
353  payChanCreate[sfSettleDelay.jsonName] =
354  NetClock::duration{100s}.count();
355  payChanCreate[sfPublicKey.jsonName] = strHex (alice.pk().slice());
356  env (payChanCreate, sig (alie));
357  env.close();
358 
359  std::string const payChanIndex {
360  strHex (keylet::payChan (alice, gw, payChanSeq).key)};
361 
362  {
363  Json::Value payChanFund;
364  payChanFund[jss::TransactionType] = jss::PaymentChannelFund;
365  payChanFund[jss::Flags] = tfUniversal;
366  payChanFund[jss::Account] = alice.human();
367  payChanFund[sfPayChannel.jsonName] = payChanIndex;
368  payChanFund[jss::Amount] =
369  XRP (200).value().getJson (JsonOptions::none);
370  env (payChanFund, sig (alie));
371  env.close();
372  }
373  {
374  Json::Value payChanClaim;
375  payChanClaim[jss::TransactionType] = jss::PaymentChannelClaim;
376  payChanClaim[jss::Flags] = tfClose;
377  payChanClaim[jss::Account] = gw.human();
378  payChanClaim[sfPayChannel.jsonName] = payChanIndex;
379  payChanClaim[sfPublicKey.jsonName] = strHex(alice.pk().slice());
380  env (payChanClaim);
381  env.close();
382  }
383  }
384 
385  // Check
386  {
387  uint256 const aliceCheckId {
388  getCheckIndex (alice, env.seq (alice))};
389  env (check::create (alice, gw, XRP (300)), sig (alie));
390 
391  uint256 const gwCheckId {
392  getCheckIndex (gw, env.seq (gw))};
393  env (check::create (gw, alice, XRP (200)));
394  env.close();
395 
396  env (check::cash (alice, gwCheckId, XRP (200)), sig (alie));
397  env (check::cancel (alice, aliceCheckId), sig (alie));
398  env.close();
399  }
400 
401  // Deposit preauthorization.
402  env (deposit::auth (alice, gw), sig (alie));
403  env.close();
404 
405  // Setup is done. Look at the transactions returned by account_tx.
406  Json::Value params;
407  params[jss::account] = alice.human();
408  params[jss::ledger_index_min] = -1;
409  params[jss::ledger_index_max] = -1;
410 
411  Json::Value const result {
412  env.rpc("json", "account_tx", to_string(params))};
413 
414  BEAST_EXPECT (result[jss::result][jss::status] == "success");
415  BEAST_EXPECT (result[jss::result][jss::transactions].isArray());
416 
417  Json::Value const& txs {result[jss::result][jss::transactions]};
418 
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  {
423  // txType, created, deleted, modified
424  { 0, jss::DepositPreauth, {jss::DepositPreauth}, {}, {jss::AccountRoot, jss::DirectoryNode}},
425  { 1, jss::CheckCancel, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
426  { 2, jss::CheckCash, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
427  { 3, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
428  { 4, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
429  { 5, jss::PaymentChannelClaim, {}, {jss::PayChannel}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
430  { 6, jss::PaymentChannelFund, {}, {}, {jss::AccountRoot, jss::PayChannel }},
431  { 7, jss::PaymentChannelCreate, {jss::PayChannel}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
432  { 8, jss::EscrowCancel, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}},
433  { 9, jss::EscrowFinish, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}},
434  { 10, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},
435  { 11, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},
436  { 12, jss::SignerListSet, {jss::SignerList}, {}, {jss::AccountRoot, jss::DirectoryNode}},
437  { 13, jss::OfferCancel, {}, {jss::Offer, jss::DirectoryNode}, {jss::AccountRoot, jss::DirectoryNode}},
438  { 14, jss::OfferCreate, {jss::Offer, jss::DirectoryNode}, {}, {jss::AccountRoot, jss::DirectoryNode}},
439  { 15, jss::TrustSet, {jss::RippleState, jss::DirectoryNode, jss::DirectoryNode}, {}, {jss::AccountRoot, jss::AccountRoot}},
440  { 16, jss::SetRegularKey, {}, {}, {jss::AccountRoot}},
441  { 17, jss::Payment, {}, {}, {jss::AccountRoot, jss::AccountRoot}},
442  { 18, jss::AccountSet, {}, {}, {jss::AccountRoot}},
443  { 19, jss::AccountSet, {}, {}, {jss::AccountRoot}},
444  { 20, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}},
445  };
446 
447  BEAST_EXPECT (std::extent<decltype (sanity)>::value ==
448  result[jss::result][jss::transactions].size());
449 
450  for (unsigned int index {0};
451  index < std::extent<decltype (sanity)>::value; ++index)
452  {
453  checkSanity (txs[index], sanity[index]);
454  }
455  }
456 
457  void
459  {
460  // Verify that if an account is resurrected then the account_tx RPC
461  // command still recovers all transactions on that account before
462  // and after resurrection.
463  using namespace test::jtx;
464  using namespace std::chrono_literals;
465 
466  Env env(*this);
467  Account const alice {"alice"};
468  Account const becky {"becky"};
469 
470  env.fund(XRP(10000), alice, becky);
471  env.close();
472 
473  // Verify that becky's account root is present.
474  Keylet const beckyAcctKey {keylet::account (becky.id())};
475  BEAST_EXPECT (env.closed()->exists (beckyAcctKey));
476 
477  // becky does an AccountSet .
478  env (noop (becky));
479 
480  // Close enough ledgers to be able to delete becky's account.
481  std::uint32_t const ledgerCount {
482  env.current()->seq() + 257 - env.seq (becky)};
483 
484  for (std::uint32_t i = 0; i < ledgerCount; ++i)
485  env.close();
486 
487  auto const beckyPreDelBalance {env.balance (becky)};
488 
489  auto const acctDelFee {drops (env.current()->fees().increment)};
490  env (acctdelete (becky, alice), fee (acctDelFee));
491  env.close();
492 
493  // Verify that becky's account root is gone.
494  BEAST_EXPECT (! env.closed()->exists (beckyAcctKey));
495 
496  // All it takes is a large enough XRP payment to resurrect
497  // becky's account. Try too small a payment.
498  env (pay (alice, becky, XRP (19)), ter (tecNO_DST_INSUF_XRP));
499  env.close();
500 
501  // Actually resurrect becky's account.
502  env (pay (alice, becky, XRP (45)));
503  env.close();
504 
505  // becky's account root should be back.
506  BEAST_EXPECT (env.closed()->exists (beckyAcctKey));
507  BEAST_EXPECT (env.balance (becky) == XRP (45));
508 
509  // becky pays alice.
510  env (pay (becky, alice, XRP(20)));
511  env.close();
512 
513  // Setup is done. Look at the transactions returned by account_tx.
514  // Verify that account_tx locates all of becky's transactions.
515  Json::Value params;
516  params[jss::account] = becky.human();
517  params[jss::ledger_index_min] = -1;
518  params[jss::ledger_index_max] = -1;
519 
520  Json::Value const result {
521  env.rpc("json", "account_tx", to_string(params))};
522 
523  BEAST_EXPECT (result[jss::result][jss::status] == "success");
524  BEAST_EXPECT (result[jss::result][jss::transactions].isArray());
525 
526  Json::Value const& txs {result[jss::result][jss::transactions]};
527 
528  // Do a sanity check on each returned transaction. They should
529  // be returned in the reverse order of application to the ledger.
530  static const NodeSanity sanity[]
531  {
532  // txType, created, deleted, modified
533 /* becky pays alice */ { 0, jss::Payment, {}, {}, {jss::AccountRoot, jss::AccountRoot}},
534 /* alice resurrects becky's acct */ { 1, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}},
535 /* becky deletes her account */ { 2, jss::AccountDelete, {}, {jss::AccountRoot}, {jss::AccountRoot}},
536 /* becky's noop */ { 3, jss::AccountSet, {}, {}, {jss::AccountRoot}},
537 /* "fund" sets flags */ { 4, jss::AccountSet, {}, {}, {jss::AccountRoot}},
538 /* "fund" creates becky's acct */ { 5, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}}
539  };
540 
541  BEAST_EXPECT (std::extent<decltype (sanity)>::value ==
542  result[jss::result][jss::transactions].size());
543 
544  for (unsigned int index {0};
545  index < std::extent<decltype (sanity)>::value; ++index)
546  {
547  checkSanity (txs[index], sanity[index]);
548  }
549  }
550 
551 public:
552  void
553  run() override
554  {
555  testParameters();
556  testContents();
558  }
559 };
560 BEAST_DEFINE_TESTSUITE(AccountTx, app, ripple);
561 
562 } // namespace test
563 } // namespace ripple
ripple::test::AccountTx_test::testParameters
void testParameters()
Definition: AccountTx_test.cpp:108
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:32
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:109
ripple::Keylet
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:38
ripple::rpcLGR_IDXS_INVALID
@ rpcLGR_IDXS_INVALID
Definition: ErrorCodes.h:113
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
std::string
STL class.
ripple::rpcINVALID_PARAMS
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:85
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:261
ripple::sfLedgerEntryType
const SF_U16 sfLedgerEntryType(access, STI_UINT16, 1, "LedgerEntryType", SField::sMD_Never)
Definition: SField.h:330
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:175
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:108
ripple::tfClose
const std::uint32_t tfClose
Definition: TxFlags.h:103
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::keylet::payChan
Keylet payChan(AccountID const &source, AccountID const &dst, std::uint32_t seq)
A PaymentChannel.
Definition: Indexes.cpp:350
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:162
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:418
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::AccountTx_test::testContents
void testContents()
Definition: AccountTx_test.cpp:244
ripple::rpcLGR_NOT_FOUND
@ rpcLGR_NOT_FOUND
Definition: ErrorCodes.h:73
ripple::sfModifiedNode
const SField sfModifiedNode(access, STI_OBJECT, 5, "ModifiedNode")
Definition: SField.h:482
ripple::SField::jsonName
const Json::StaticString jsonName
Definition: SField.h:140
ripple::sfFinishAfter
const SF_U32 sfFinishAfter(access, STI_UINT32, 37, "FinishAfter")
Definition: SField.h:374
ripple::error_code_i
error_code_i
Definition: ErrorCodes.h:40
ripple::tecNO_DST_INSUF_XRP
@ tecNO_DST_INSUF_XRP
Definition: TER.h:256
ripple::base_uint< 256 >
ripple::test::AccountTx_test::run
void run() override
Definition: AccountTx_test.cpp:553
ripple::getCheckIndex
uint256 getCheckIndex(AccountID const &account, std::uint32_t uSequence)
Definition: Indexes.cpp:186
std::extent
ripple::sfOwner
const SF_Account sfOwner(access, STI_ACCOUNT, 2, "Owner")
Definition: SField.h:461
ripple::test::jtx::signers
Json::Value signers(Account const &account, std::uint32_t quorum, std::vector< signer > const &v)
Definition: multisign.cpp:33
ripple::keylet::account
static const account_t account
Definition: Indexes.h:116
ripple::JsonOptions::none
@ none
ripple::sfTransactionType
const SF_U16 sfTransactionType(access, STI_UINT16, 2, "TransactionType")
Definition: SField.h:331
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:961
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:192
ripple::sfCreatedNode
const SField sfCreatedNode(access, STI_OBJECT, 3, "CreatedNode")
Definition: SField.h:480
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:440
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:91
ripple::test::AccountTx_test::testAccountDelete
void testAccountDelete()
Definition: AccountTx_test.cpp:458
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:260
ripple::sfOfferSequence
const SF_U32 sfOfferSequence(access, STI_UINT32, 25, "OfferSequence")
Definition: SField.h:362
ripple::rpcLGR_NOT_VALIDATED
@ rpcLGR_NOT_VALIDATED
Definition: ErrorCodes.h:74
ripple::sfAffectedNodes
const SField sfAffectedNodes(access, STI_ARRAY, 8, "AffectedNodes")
Definition: SField.h:500
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
Json::StaticString
Lightweight wrapper to tag static string.
Definition: json_value.h:62
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:214
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:376
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::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:481
ripple::test::jtx::Env::current
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:296
ripple::sfCancelAfter
const SF_U32 sfCancelAfter(access, STI_UINT32, 36, "CancelAfter")
Definition: SField.h:373
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:117
ripple::RPC::ErrorInfo::token
Json::StaticString token
Definition: ErrorCodes.h:175
ripple::test::jtx::Env::rpc
Json::Value rpc(std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition: Env.h:688
Json::Value
Represents a JSON value.
Definition: json_value.h:141
std::initializer_list