rippled
AccountInfo_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2016 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/protocol/Feature.h>
21 #include <ripple/protocol/jss.h>
22 #include <test/jtx.h>
23 
24 #include <ripple/resource/Charge.h>
25 #include <ripple/resource/Fees.h>
26 #include <ripple/rpc/GRPCHandlers.h>
27 #include <test/jtx/WSClient.h>
28 #include <test/rpc/GRPCTestClientBase.h>
29 
30 namespace ripple {
31 namespace test {
32 
33 class AccountInfo_test : public beast::unit_test::suite
34 {
35 public:
36  void
38  {
39  using namespace jtx;
40  Env env(*this);
41  {
42  // account_info with no account.
43  auto const info = env.rpc("json", "account_info", "{ }");
44  BEAST_EXPECT(
45  info[jss::result][jss::error_message] ==
46  "Missing field 'account'.");
47  }
48  {
49  // account_info with a malformed account string.
50  auto const info = env.rpc(
51  "json",
52  "account_info",
53  "{\"account\": "
54  "\"n94JNrQYkDrpt62bbSR7nVEhdyAvcJXRAsjEkFYyqRkh9SUTYEqV\"}");
55  BEAST_EXPECT(
56  info[jss::result][jss::error_code] == rpcACT_MALFORMED);
57  BEAST_EXPECT(
58  info[jss::result][jss::error_message] == "Account malformed.");
59  }
60  {
61  // account_info with an account that's not in the ledger.
62  Account const bogie{"bogie"};
63  auto const info = env.rpc(
64  "json",
65  "account_info",
66  R"({ "account": ")" + bogie.human() + R"("})");
67  BEAST_EXPECT(
68  info[jss::result][jss::error_code] == rpcACT_NOT_FOUND);
69  BEAST_EXPECT(
70  info[jss::result][jss::error_message] == "Account not found.");
71  }
72  {
73  // Cannot use a seed as account
74  auto const info =
75  env.rpc("json", "account_info", R"({"account": "foo"})");
76  BEAST_EXPECT(
77  info[jss::result][jss::error_code] == rpcACT_MALFORMED);
78  BEAST_EXPECT(
79  info[jss::result][jss::error_message] == "Account malformed.");
80  }
81  }
82 
83  // Test the "signer_lists" argument in account_info.
84  void
85  testSignerLists()
86  {
87  using namespace jtx;
88  Env env(*this);
89  Account const alice{"alice"};
90  env.fund(XRP(1000), alice);
91 
92  auto const withoutSigners =
93  std::string("{ ") + "\"account\": \"" + alice.human() + "\"}";
94 
95  auto const withSigners = std::string("{ ") + "\"account\": \"" +
96  alice.human() + "\", " + "\"signer_lists\": true }";
97 
98  // Alice has no SignerList yet.
99  {
100  // account_info without the "signer_lists" argument.
101  auto const info = env.rpc("json", "account_info", withoutSigners);
102  BEAST_EXPECT(
103  info.isMember(jss::result) &&
104  info[jss::result].isMember(jss::account_data));
105  BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
106  jss::signer_lists));
107  }
108  {
109  // account_info with the "signer_lists" argument.
110  auto const info = env.rpc("json", "account_info", withSigners);
111  BEAST_EXPECT(
112  info.isMember(jss::result) &&
113  info[jss::result].isMember(jss::account_data));
114  auto const& data = info[jss::result][jss::account_data];
115  BEAST_EXPECT(data.isMember(jss::signer_lists));
116  auto const& signerLists = data[jss::signer_lists];
117  BEAST_EXPECT(signerLists.isArray());
118  BEAST_EXPECT(signerLists.size() == 0);
119  }
120 
121  // Give alice a SignerList.
122  Account const bogie{"bogie"};
123 
124  Json::Value const smallSigners = signers(alice, 2, {{bogie, 3}});
125  env(smallSigners);
126  {
127  // account_info without the "signer_lists" argument.
128  auto const info = env.rpc("json", "account_info", withoutSigners);
129  BEAST_EXPECT(
130  info.isMember(jss::result) &&
131  info[jss::result].isMember(jss::account_data));
132  BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
133  jss::signer_lists));
134  }
135  {
136  // account_info with the "signer_lists" argument.
137  auto const info = env.rpc("json", "account_info", withSigners);
138  BEAST_EXPECT(
139  info.isMember(jss::result) &&
140  info[jss::result].isMember(jss::account_data));
141  auto const& data = info[jss::result][jss::account_data];
142  BEAST_EXPECT(data.isMember(jss::signer_lists));
143  auto const& signerLists = data[jss::signer_lists];
144  BEAST_EXPECT(signerLists.isArray());
145  BEAST_EXPECT(signerLists.size() == 1);
146  auto const& signers = signerLists[0u];
147  BEAST_EXPECT(signers.isObject());
148  BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 2);
149  auto const& signerEntries = signers[sfSignerEntries.jsonName];
150  BEAST_EXPECT(signerEntries.size() == 1);
151  auto const& entry0 = signerEntries[0u][sfSignerEntry.jsonName];
152  BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3);
153  }
154 
155  // Give alice a big signer list
156  Account const demon{"demon"};
157  Account const ghost{"ghost"};
158  Account const haunt{"haunt"};
159  Account const jinni{"jinni"};
160  Account const phase{"phase"};
161  Account const shade{"shade"};
162  Account const spook{"spook"};
163 
164  Json::Value const bigSigners = signers(
165  alice,
166  4,
167  {
168  {bogie, 1},
169  {demon, 1},
170  {ghost, 1},
171  {haunt, 1},
172  {jinni, 1},
173  {phase, 1},
174  {shade, 1},
175  {spook, 1},
176  });
177  env(bigSigners);
178  {
179  // account_info with the "signer_lists" argument.
180  auto const info = env.rpc("json", "account_info", withSigners);
181  BEAST_EXPECT(
182  info.isMember(jss::result) &&
183  info[jss::result].isMember(jss::account_data));
184  auto const& data = info[jss::result][jss::account_data];
185  BEAST_EXPECT(data.isMember(jss::signer_lists));
186  auto const& signerLists = data[jss::signer_lists];
187  BEAST_EXPECT(signerLists.isArray());
188  BEAST_EXPECT(signerLists.size() == 1);
189  auto const& signers = signerLists[0u];
190  BEAST_EXPECT(signers.isObject());
191  BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 4);
192  auto const& signerEntries = signers[sfSignerEntries.jsonName];
193  BEAST_EXPECT(signerEntries.size() == 8);
194  for (unsigned i = 0u; i < 8; ++i)
195  {
196  auto const& entry = signerEntries[i][sfSignerEntry.jsonName];
197  BEAST_EXPECT(entry.size() == 2);
198  BEAST_EXPECT(entry.isMember(sfAccount.jsonName));
199  BEAST_EXPECT(entry[sfSignerWeight.jsonName] == 1);
200  }
201  }
202  }
203 
204  // Test the "signer_lists" argument in account_info, with api_version 2.
205  void
206  testSignerListsApiVersion2()
207  {
208  using namespace jtx;
209  Env env{*this};
210  Account const alice{"alice"};
211  env.fund(XRP(1000), alice);
212 
213  auto const withoutSigners = std::string("{ ") +
214  "\"api_version\": 2, \"account\": \"" + alice.human() + "\"}";
215 
216  auto const withSigners = std::string("{ ") +
217  "\"api_version\": 2, \"account\": \"" + alice.human() + "\", " +
218  "\"signer_lists\": true }";
219 
220  // Alice has no SignerList yet.
221  {
222  // account_info without the "signer_lists" argument.
223  auto const info = env.rpc("json", "account_info", withoutSigners);
224  BEAST_EXPECT(info.isMember(jss::result));
225  BEAST_EXPECT(!info[jss::result].isMember(jss::signer_lists));
226  }
227  {
228  // account_info with the "signer_lists" argument.
229  auto const info = env.rpc("json", "account_info", withSigners);
230  BEAST_EXPECT(info.isMember(jss::result));
231  auto const& data = info[jss::result];
232  BEAST_EXPECT(data.isMember(jss::signer_lists));
233  auto const& signerLists = data[jss::signer_lists];
234  BEAST_EXPECT(signerLists.isArray());
235  BEAST_EXPECT(signerLists.size() == 0);
236  }
237 
238  // Give alice a SignerList.
239  Account const bogie{"bogie"};
240 
241  Json::Value const smallSigners = signers(alice, 2, {{bogie, 3}});
242  env(smallSigners);
243  {
244  // account_info without the "signer_lists" argument.
245  auto const info = env.rpc("json", "account_info", withoutSigners);
246  BEAST_EXPECT(info.isMember(jss::result));
247  BEAST_EXPECT(!info[jss::result].isMember(jss::signer_lists));
248  }
249  {
250  // account_info with the "signer_lists" argument.
251  auto const info = env.rpc("json", "account_info", withSigners);
252  BEAST_EXPECT(info.isMember(jss::result));
253  auto const& data = info[jss::result];
254  BEAST_EXPECT(data.isMember(jss::signer_lists));
255  auto const& signerLists = data[jss::signer_lists];
256  BEAST_EXPECT(signerLists.isArray());
257  BEAST_EXPECT(signerLists.size() == 1);
258  auto const& signers = signerLists[0u];
259  BEAST_EXPECT(signers.isObject());
260  BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 2);
261  auto const& signerEntries = signers[sfSignerEntries.jsonName];
262  BEAST_EXPECT(signerEntries.size() == 1);
263  auto const& entry0 = signerEntries[0u][sfSignerEntry.jsonName];
264  BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3);
265  }
266 
267  // Give alice a big signer list
268  Account const demon{"demon"};
269  Account const ghost{"ghost"};
270  Account const haunt{"haunt"};
271  Account const jinni{"jinni"};
272  Account const phase{"phase"};
273  Account const shade{"shade"};
274  Account const spook{"spook"};
275 
276  Json::Value const bigSigners = signers(
277  alice,
278  4,
279  {
280  {bogie, 1},
281  {demon, 1},
282  {ghost, 1},
283  {haunt, 1},
284  {jinni, 1},
285  {phase, 1},
286  {shade, 1},
287  {spook, 1},
288  });
289  env(bigSigners);
290  {
291  // account_info with the "signer_lists" argument.
292  auto const info = env.rpc("json", "account_info", withSigners);
293  BEAST_EXPECT(info.isMember(jss::result));
294  auto const& data = info[jss::result];
295  BEAST_EXPECT(data.isMember(jss::signer_lists));
296  auto const& signerLists = data[jss::signer_lists];
297  BEAST_EXPECT(signerLists.isArray());
298  BEAST_EXPECT(signerLists.size() == 1);
299  auto const& signers = signerLists[0u];
300  BEAST_EXPECT(signers.isObject());
301  BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 4);
302  auto const& signerEntries = signers[sfSignerEntries.jsonName];
303  BEAST_EXPECT(signerEntries.size() == 8);
304  for (unsigned i = 0u; i < 8; ++i)
305  {
306  auto const& entry = signerEntries[i][sfSignerEntry.jsonName];
307  BEAST_EXPECT(entry.size() == 2);
308  BEAST_EXPECT(entry.isMember(sfAccount.jsonName));
309  BEAST_EXPECT(entry[sfSignerWeight.jsonName] == 1);
310  }
311  }
312  }
313 
314  // Test the "signer_lists" argument in account_info, version 2 API.
315  void
316  testSignerListsV2()
317  {
318  using namespace jtx;
319  Env env(*this);
320  Account const alice{"alice"};
321  env.fund(XRP(1000), alice);
322 
323  auto const withoutSigners = std::string("{ ") +
324  "\"jsonrpc\": \"2.0\", "
325  "\"ripplerpc\": \"2.0\", "
326  "\"id\": 5, "
327  "\"method\": \"account_info\", "
328  "\"params\": { "
329  "\"account\": \"" +
330  alice.human() + "\"}}";
331 
332  auto const withSigners = std::string("{ ") +
333  "\"jsonrpc\": \"2.0\", "
334  "\"ripplerpc\": \"2.0\", "
335  "\"id\": 6, "
336  "\"method\": \"account_info\", "
337  "\"params\": { "
338  "\"account\": \"" +
339  alice.human() + "\", " + "\"signer_lists\": true }}";
340  // Alice has no SignerList yet.
341  {
342  // account_info without the "signer_lists" argument.
343  auto const info = env.rpc("json2", withoutSigners);
344  BEAST_EXPECT(
345  info.isMember(jss::result) &&
346  info[jss::result].isMember(jss::account_data));
347  BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
348  jss::signer_lists));
349  BEAST_EXPECT(
350  info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
351  BEAST_EXPECT(
352  info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
353  BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
354  }
355  {
356  // account_info with the "signer_lists" argument.
357  auto const info = env.rpc("json2", withSigners);
358  BEAST_EXPECT(
359  info.isMember(jss::result) &&
360  info[jss::result].isMember(jss::account_data));
361  auto const& data = info[jss::result][jss::account_data];
362  BEAST_EXPECT(data.isMember(jss::signer_lists));
363  auto const& signerLists = data[jss::signer_lists];
364  BEAST_EXPECT(signerLists.isArray());
365  BEAST_EXPECT(signerLists.size() == 0);
366  BEAST_EXPECT(
367  info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
368  BEAST_EXPECT(
369  info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
370  BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
371  }
372  {
373  // Do both of the above as a batch job
374  auto const info = env.rpc(
375  "json2", '[' + withoutSigners + ", " + withSigners + ']');
376  BEAST_EXPECT(
377  info[0u].isMember(jss::result) &&
378  info[0u][jss::result].isMember(jss::account_data));
379  BEAST_EXPECT(!info[0u][jss::result][jss::account_data].isMember(
380  jss::signer_lists));
381  BEAST_EXPECT(
382  info[0u].isMember(jss::jsonrpc) &&
383  info[0u][jss::jsonrpc] == "2.0");
384  BEAST_EXPECT(
385  info[0u].isMember(jss::ripplerpc) &&
386  info[0u][jss::ripplerpc] == "2.0");
387  BEAST_EXPECT(info[0u].isMember(jss::id) && info[0u][jss::id] == 5);
388 
389  BEAST_EXPECT(
390  info[1u].isMember(jss::result) &&
391  info[1u][jss::result].isMember(jss::account_data));
392  auto const& data = info[1u][jss::result][jss::account_data];
393  BEAST_EXPECT(data.isMember(jss::signer_lists));
394  auto const& signerLists = data[jss::signer_lists];
395  BEAST_EXPECT(signerLists.isArray());
396  BEAST_EXPECT(signerLists.size() == 0);
397  BEAST_EXPECT(
398  info[1u].isMember(jss::jsonrpc) &&
399  info[1u][jss::jsonrpc] == "2.0");
400  BEAST_EXPECT(
401  info[1u].isMember(jss::ripplerpc) &&
402  info[1u][jss::ripplerpc] == "2.0");
403  BEAST_EXPECT(info[1u].isMember(jss::id) && info[1u][jss::id] == 6);
404  }
405 
406  // Give alice a SignerList.
407  Account const bogie{"bogie"};
408 
409  Json::Value const smallSigners = signers(alice, 2, {{bogie, 3}});
410  env(smallSigners);
411  {
412  // account_info without the "signer_lists" argument.
413  auto const info = env.rpc("json2", withoutSigners);
414  BEAST_EXPECT(
415  info.isMember(jss::result) &&
416  info[jss::result].isMember(jss::account_data));
417  BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
418  jss::signer_lists));
419  BEAST_EXPECT(
420  info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
421  BEAST_EXPECT(
422  info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
423  BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
424  }
425  {
426  // account_info with the "signer_lists" argument.
427  auto const info = env.rpc("json2", withSigners);
428  BEAST_EXPECT(
429  info.isMember(jss::result) &&
430  info[jss::result].isMember(jss::account_data));
431  auto const& data = info[jss::result][jss::account_data];
432  BEAST_EXPECT(data.isMember(jss::signer_lists));
433  auto const& signerLists = data[jss::signer_lists];
434  BEAST_EXPECT(signerLists.isArray());
435  BEAST_EXPECT(signerLists.size() == 1);
436  auto const& signers = signerLists[0u];
437  BEAST_EXPECT(signers.isObject());
438  BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 2);
439  auto const& signerEntries = signers[sfSignerEntries.jsonName];
440  BEAST_EXPECT(signerEntries.size() == 1);
441  auto const& entry0 = signerEntries[0u][sfSignerEntry.jsonName];
442  BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3);
443  BEAST_EXPECT(
444  info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
445  BEAST_EXPECT(
446  info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
447  BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
448  }
449 
450  // Give alice a big signer list
451  Account const demon{"demon"};
452  Account const ghost{"ghost"};
453  Account const haunt{"haunt"};
454  Account const jinni{"jinni"};
455  Account const phase{"phase"};
456  Account const shade{"shade"};
457  Account const spook{"spook"};
458 
459  Json::Value const bigSigners = signers(
460  alice,
461  4,
462  {
463  {bogie, 1},
464  {demon, 1},
465  {ghost, 1},
466  {haunt, 1},
467  {jinni, 1},
468  {phase, 1},
469  {shade, 1},
470  {spook, 1},
471  });
472  env(bigSigners);
473  {
474  // account_info with the "signer_lists" argument.
475  auto const info = env.rpc("json2", withSigners);
476  BEAST_EXPECT(
477  info.isMember(jss::result) &&
478  info[jss::result].isMember(jss::account_data));
479  auto const& data = info[jss::result][jss::account_data];
480  BEAST_EXPECT(data.isMember(jss::signer_lists));
481  auto const& signerLists = data[jss::signer_lists];
482  BEAST_EXPECT(signerLists.isArray());
483  BEAST_EXPECT(signerLists.size() == 1);
484  auto const& signers = signerLists[0u];
485  BEAST_EXPECT(signers.isObject());
486  BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 4);
487  auto const& signerEntries = signers[sfSignerEntries.jsonName];
488  BEAST_EXPECT(signerEntries.size() == 8);
489  for (unsigned i = 0u; i < 8; ++i)
490  {
491  auto const& entry = signerEntries[i][sfSignerEntry.jsonName];
492  BEAST_EXPECT(entry.size() == 2);
493  BEAST_EXPECT(entry.isMember(sfAccount.jsonName));
494  BEAST_EXPECT(entry[sfSignerWeight.jsonName] == 1);
495  }
496  BEAST_EXPECT(
497  info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
498  BEAST_EXPECT(
499  info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
500  BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
501  }
502  }
503 
504  void
505  testAccountFlags(FeatureBitset const& features)
506  {
507  using namespace jtx;
508 
509  Env env(*this, features);
510  Account const alice{"alice"};
511  env.fund(XRP(1000), alice);
512 
513  auto getAccountFlag = [&env, &alice](std::string_view fName) {
514  auto const info = env.rpc(
515  "json",
516  "account_info",
517  R"({"account" : ")" + alice.human() + R"("})");
518 
520  if (info[jss::result][jss::status] == "success" &&
521  info[jss::result][jss::account_flags].isMember(fName.data()))
522  res.emplace(info[jss::result][jss::account_flags][fName.data()]
523  .asBool());
524 
525  return res;
526  };
527 
528  static constexpr std::
529  array<std::pair<std::string_view, std::uint32_t>, 7>
530  asFlags{
531  {{"defaultRipple", asfDefaultRipple},
532  {"depositAuth", asfDepositAuth},
533  {"disallowIncomingXRP", asfDisallowXRP},
534  {"globalFreeze", asfGlobalFreeze},
535  {"noFreeze", asfNoFreeze},
536  {"requireAuthorization", asfRequireAuth},
537  {"requireDestinationTag", asfRequireDest}}};
538 
539  for (auto& asf : asFlags)
540  {
541  // Clear a flag and check that account_info returns results
542  // as expected
543  env(fclear(alice, asf.second));
544  env.close();
545  auto const f1 = getAccountFlag(asf.first);
546  BEAST_EXPECT(f1.has_value());
547  BEAST_EXPECT(!f1.value());
548 
549  // Set a flag and check that account_info returns results
550  // as expected
551  env(fset(alice, asf.second));
552  env.close();
553  auto const f2 = getAccountFlag(asf.first);
554  BEAST_EXPECT(f2.has_value());
555  BEAST_EXPECT(f2.value());
556  }
557 
558  static constexpr std::
559  array<std::pair<std::string_view, std::uint32_t>, 4>
560  disallowIncomingFlags{
561  {{"disallowIncomingCheck", asfDisallowIncomingCheck},
562  {"disallowIncomingNFTokenOffer",
564  {"disallowIncomingPayChan", asfDisallowIncomingPayChan},
565  {"disallowIncomingTrustline",
567 
568  if (features[featureDisallowIncoming])
569  {
570  for (auto& asf : disallowIncomingFlags)
571  {
572  // Clear a flag and check that account_info returns results
573  // as expected
574  env(fclear(alice, asf.second));
575  env.close();
576  auto const f1 = getAccountFlag(asf.first);
577  BEAST_EXPECT(f1.has_value());
578  BEAST_EXPECT(!f1.value());
579 
580  // Set a flag and check that account_info returns results
581  // as expected
582  env(fset(alice, asf.second));
583  env.close();
584  auto const f2 = getAccountFlag(asf.first);
585  BEAST_EXPECT(f2.has_value());
586  BEAST_EXPECT(f2.value());
587  }
588  }
589  else
590  {
591  for (auto& asf : disallowIncomingFlags)
592  {
593  BEAST_EXPECT(!getAccountFlag(asf.first));
594  }
595  }
596  }
597 
598  void
599  run() override
600  {
601  testErrors();
602  testSignerLists();
603  testSignerListsApiVersion2();
604  testSignerListsV2();
605 
606  FeatureBitset const allFeatures{
608  testAccountFlags(allFeatures);
609  testAccountFlags(allFeatures - featureDisallowIncoming);
610  }
611 };
612 
613 BEAST_DEFINE_TESTSUITE(AccountInfo, app, ripple);
614 
615 } // namespace test
616 } // namespace ripple
ripple::sfSignerWeight
const SF_UINT16 sfSignerWeight
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
ripple::asfDisallowXRP
constexpr std::uint32_t asfDisallowXRP
Definition: TxFlags.h:76
ripple::asfDepositAuth
constexpr std::uint32_t asfDepositAuth
Definition: TxFlags.h:82
std::string
STL class.
ripple::keylet::signers
Keylet signers(AccountID const &account) noexcept
A SignerList.
Definition: Indexes.cpp:275
std::string_view
STL class.
ripple::asfNoFreeze
constexpr std::uint32_t asfNoFreeze
Definition: TxFlags.h:79
std::optional::emplace
T emplace(T... args)
ripple::asfDisallowIncomingPayChan
constexpr std::uint32_t asfDisallowIncomingPayChan
Definition: TxFlags.h:89
ripple::SField::jsonName
const Json::StaticString jsonName
Definition: SField.h:136
ripple::sfSignerQuorum
const SF_UINT32 sfSignerQuorum
ripple::asfDisallowIncomingTrustline
constexpr std::uint32_t asfDisallowIncomingTrustline
Definition: TxFlags.h:90
ripple::asfDisallowIncomingCheck
constexpr std::uint32_t asfDisallowIncomingCheck
Definition: TxFlags.h:88
ripple::featureDisallowIncoming
const uint256 featureDisallowIncoming
ripple::test::AccountInfo_test
Definition: AccountInfo_test.cpp:33
ripple::rpcACT_NOT_FOUND
@ rpcACT_NOT_FOUND
Definition: ErrorCodes.h:70
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::test::jtx::supported_amendments
FeatureBitset supported_amendments()
Definition: Env.h:70
ripple::test::jtx::fclear
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Definition: flags.h:40
ripple::sfSignerEntry
const SField sfSignerEntry
ripple::sfSignerEntries
const SField sfSignerEntries
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::asfRequireAuth
constexpr std::uint32_t asfRequireAuth
Definition: TxFlags.h:75
ripple::asfDefaultRipple
constexpr std::uint32_t asfDefaultRipple
Definition: TxFlags.h:81
ripple::asfRequireDest
constexpr std::uint32_t asfRequireDest
Definition: TxFlags.h:74
ripple::asfGlobalFreeze
constexpr std::uint32_t asfGlobalFreeze
Definition: TxFlags.h:80
std::optional< bool >
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::sfAccount
const SF_ACCOUNT sfAccount
std::data
T data(T... args)
ripple::test::AccountInfo_test::testErrors
void testErrors()
Definition: AccountInfo_test.cpp:37
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:116
ripple::asfDisallowIncomingNFTokenOffer
constexpr std::uint32_t asfDisallowIncomingNFTokenOffer
Definition: TxFlags.h:87
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:687
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(DeliverMin, app, ripple)