rippled
Loading...
Searching...
No Matches
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 <test/jtx.h>
21#include <test/jtx/WSClient.h>
22#include <test/rpc/GRPCTestClientBase.h>
23
24#include <xrpl/protocol/Feature.h>
25#include <xrpl/protocol/jss.h>
26
27namespace ripple {
28namespace test {
29
31{
32public:
33 void
35 {
36 testcase("Errors");
37 using namespace jtx;
38 Env env(*this);
39 {
40 // account_info with no account.
41 auto const info = env.rpc("json", "account_info", "{ }");
42 BEAST_EXPECT(
43 info[jss::result][jss::error_message] ==
44 "Missing field 'account'.");
45 }
46 {
47 // account_info with a malformed account string.
48 auto const info = env.rpc(
49 "json",
50 "account_info",
51 "{\"account\": "
52 "\"n94JNrQYkDrpt62bbSR7nVEhdyAvcJXRAsjEkFYyqRkh9SUTYEqV\"}");
53 BEAST_EXPECT(
54 info[jss::result][jss::error_code] == rpcACT_MALFORMED);
55 BEAST_EXPECT(
56 info[jss::result][jss::error_message] == "Account malformed.");
57 }
58 {
59 // account_info with an account that's not in the ledger.
60 Account const bogie{"bogie"};
61 Json::Value params;
62 params[jss::account] = bogie.human();
63 auto const info =
64 env.rpc("json", "account_info", to_string(params));
65 BEAST_EXPECT(
66 info[jss::result][jss::error_code] == rpcACT_NOT_FOUND);
67 BEAST_EXPECT(
68 info[jss::result][jss::error_message] == "Account not found.");
69 }
70 {
71 // Cannot use a seed as account
72 auto const info =
73 env.rpc("json", "account_info", R"({"account": "foo"})");
74 BEAST_EXPECT(
75 info[jss::result][jss::error_code] == rpcACT_MALFORMED);
76 BEAST_EXPECT(
77 info[jss::result][jss::error_message] == "Account malformed.");
78 }
79 {
80 // Cannot pass a non-string into the `account` param
81
82 auto testInvalidAccountParam = [&](auto const& param) {
83 Json::Value params;
84 params[jss::account] = param;
85 auto jrr = env.rpc(
86 "json", "account_info", to_string(params))[jss::result];
87 BEAST_EXPECT(jrr[jss::error] == "invalidParams");
88 BEAST_EXPECT(
89 jrr[jss::error_message] == "Invalid field 'account'.");
90 };
91
92 testInvalidAccountParam(1);
93 testInvalidAccountParam(1.1);
94 testInvalidAccountParam(true);
95 testInvalidAccountParam(Json::Value(Json::nullValue));
96 testInvalidAccountParam(Json::Value(Json::objectValue));
97 testInvalidAccountParam(Json::Value(Json::arrayValue));
98 }
99 {
100 // Cannot pass a non-string into the `ident` param
101
102 auto testInvalidIdentParam = [&](auto const& param) {
103 Json::Value params;
104 params[jss::ident] = param;
105 auto jrr = env.rpc(
106 "json", "account_info", to_string(params))[jss::result];
107 BEAST_EXPECT(jrr[jss::error] == "invalidParams");
108 BEAST_EXPECT(
109 jrr[jss::error_message] == "Invalid field 'ident'.");
110 };
111
112 testInvalidIdentParam(1);
113 testInvalidIdentParam(1.1);
114 testInvalidIdentParam(true);
115 testInvalidIdentParam(Json::Value(Json::nullValue));
116 testInvalidIdentParam(Json::Value(Json::objectValue));
117 testInvalidIdentParam(Json::Value(Json::arrayValue));
118 }
119 }
120
121 // Test the "signer_lists" argument in account_info.
122 void
124 {
125 testcase("Signer lists");
126 using namespace jtx;
127 Env env(*this);
128 Account const alice{"alice"};
129 env.fund(XRP(1000), alice);
130
131 Json::Value withoutSigners;
132 withoutSigners[jss::account] = alice.human();
133
134 Json::Value withSigners;
135 withSigners[jss::account] = alice.human();
136 withSigners[jss::signer_lists] = true;
137
138 // Alice has no SignerList yet.
139 {
140 // account_info without the "signer_lists" argument.
141 auto const info =
142 env.rpc("json", "account_info", to_string(withoutSigners));
143 BEAST_EXPECT(
144 info.isMember(jss::result) &&
145 info[jss::result].isMember(jss::account_data));
146 BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
147 jss::signer_lists));
148 }
149 {
150 // account_info with the "signer_lists" argument.
151 auto const info =
152 env.rpc("json", "account_info", to_string(withSigners));
153 BEAST_EXPECT(
154 info.isMember(jss::result) &&
155 info[jss::result].isMember(jss::account_data));
156 auto const& data = info[jss::result][jss::account_data];
157 BEAST_EXPECT(data.isMember(jss::signer_lists));
158 auto const& signerLists = data[jss::signer_lists];
159 BEAST_EXPECT(signerLists.isArray());
160 BEAST_EXPECT(signerLists.size() == 0);
161 }
162
163 // Give alice a SignerList.
164 Account const bogie{"bogie"};
165
166 Json::Value const smallSigners = signers(alice, 2, {{bogie, 3}});
167 env(smallSigners);
168 {
169 // account_info without the "signer_lists" argument.
170 auto const info =
171 env.rpc("json", "account_info", to_string(withoutSigners));
172 BEAST_EXPECT(
173 info.isMember(jss::result) &&
174 info[jss::result].isMember(jss::account_data));
175 BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
176 jss::signer_lists));
177 }
178 {
179 // account_info with the "signer_lists" argument.
180 auto const info =
181 env.rpc("json", "account_info", to_string(withSigners));
182 BEAST_EXPECT(
183 info.isMember(jss::result) &&
184 info[jss::result].isMember(jss::account_data));
185 auto const& data = info[jss::result][jss::account_data];
186 BEAST_EXPECT(data.isMember(jss::signer_lists));
187 auto const& signerLists = data[jss::signer_lists];
188 BEAST_EXPECT(signerLists.isArray());
189 BEAST_EXPECT(signerLists.size() == 1);
190 auto const& signers = signerLists[0u];
191 BEAST_EXPECT(signers.isObject());
192 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 2);
193 auto const& signerEntries = signers[sfSignerEntries.jsonName];
194 BEAST_EXPECT(signerEntries.size() == 1);
195 auto const& entry0 = signerEntries[0u][sfSignerEntry.jsonName];
196 BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3);
197 }
198
199 // Give alice a big signer list
200 Account const demon{"demon"};
201 Account const ghost{"ghost"};
202 Account const haunt{"haunt"};
203 Account const jinni{"jinni"};
204 Account const phase{"phase"};
205 Account const shade{"shade"};
206 Account const spook{"spook"};
207
208 Json::Value const bigSigners = signers(
209 alice,
210 4,
211 {
212 {bogie, 1},
213 {demon, 1},
214 {ghost, 1},
215 {haunt, 1},
216 {jinni, 1},
217 {phase, 1},
218 {shade, 1},
219 {spook, 1},
220 });
221 env(bigSigners);
222 {
223 // account_info with the "signer_lists" argument.
224 auto const info =
225 env.rpc("json", "account_info", to_string(withSigners));
226 BEAST_EXPECT(
227 info.isMember(jss::result) &&
228 info[jss::result].isMember(jss::account_data));
229 auto const& data = info[jss::result][jss::account_data];
230 BEAST_EXPECT(data.isMember(jss::signer_lists));
231 auto const& signerLists = data[jss::signer_lists];
232 BEAST_EXPECT(signerLists.isArray());
233 BEAST_EXPECT(signerLists.size() == 1);
234 auto const& signers = signerLists[0u];
235 BEAST_EXPECT(signers.isObject());
236 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 4);
237 auto const& signerEntries = signers[sfSignerEntries.jsonName];
238 BEAST_EXPECT(signerEntries.size() == 8);
239 for (unsigned i = 0u; i < 8; ++i)
240 {
241 auto const& entry = signerEntries[i][sfSignerEntry.jsonName];
242 BEAST_EXPECT(entry.size() == 2);
243 BEAST_EXPECT(entry.isMember(sfAccount.jsonName));
244 BEAST_EXPECT(entry[sfSignerWeight.jsonName] == 1);
245 }
246 }
247 }
248
249 // Test the "signer_lists" argument in account_info, with api_version 2.
250 void
252 {
253 testcase("Signer lists APIv2");
254 using namespace jtx;
255 Env env{*this};
256 Account const alice{"alice"};
257 env.fund(XRP(1000), alice);
258
259 Json::Value withoutSigners;
260 withoutSigners[jss::api_version] = 2;
261 withoutSigners[jss::account] = alice.human();
262
263 Json::Value withSigners;
264 withSigners[jss::api_version] = 2;
265 withSigners[jss::account] = alice.human();
266 withSigners[jss::signer_lists] = true;
267
268 auto const withSignersAsString = std::string("{ ") +
269 "\"api_version\": 2, \"account\": \"" + alice.human() + "\", " +
270 "\"signer_lists\": asdfggh }";
271
272 // Alice has no SignerList yet.
273 {
274 // account_info without the "signer_lists" argument.
275 auto const info =
276 env.rpc("json", "account_info", to_string(withoutSigners));
277 BEAST_EXPECT(info.isMember(jss::result));
278 BEAST_EXPECT(!info[jss::result].isMember(jss::signer_lists));
279 }
280 {
281 // account_info with the "signer_lists" argument.
282 auto const info =
283 env.rpc("json", "account_info", to_string(withSigners));
284 BEAST_EXPECT(info.isMember(jss::result));
285 auto const& data = info[jss::result];
286 BEAST_EXPECT(data.isMember(jss::signer_lists));
287 auto const& signerLists = data[jss::signer_lists];
288 BEAST_EXPECT(signerLists.isArray());
289 BEAST_EXPECT(signerLists.size() == 0);
290 }
291
292 // Give alice a SignerList.
293 Account const bogie{"bogie"};
294
295 Json::Value const smallSigners = signers(alice, 2, {{bogie, 3}});
296 env(smallSigners);
297 {
298 // account_info without the "signer_lists" argument.
299 auto const info =
300 env.rpc("json", "account_info", to_string(withoutSigners));
301 BEAST_EXPECT(info.isMember(jss::result));
302 BEAST_EXPECT(!info[jss::result].isMember(jss::signer_lists));
303 }
304 {
305 // account_info with the "signer_lists" argument.
306 auto const info =
307 env.rpc("json", "account_info", to_string(withSigners));
308 BEAST_EXPECT(info.isMember(jss::result));
309 auto const& data = info[jss::result];
310 BEAST_EXPECT(data.isMember(jss::signer_lists));
311 auto const& signerLists = data[jss::signer_lists];
312 BEAST_EXPECT(signerLists.isArray());
313 BEAST_EXPECT(signerLists.size() == 1);
314 auto const& signers = signerLists[0u];
315 BEAST_EXPECT(signers.isObject());
316 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 2);
317 auto const& signerEntries = signers[sfSignerEntries.jsonName];
318 BEAST_EXPECT(signerEntries.size() == 1);
319 auto const& entry0 = signerEntries[0u][sfSignerEntry.jsonName];
320 BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3);
321 }
322 {
323 // account_info with "signer_lists" as not bool should error out
324 auto const info =
325 env.rpc("json", "account_info", withSignersAsString);
326 BEAST_EXPECT(info[jss::status] == "error");
327 BEAST_EXPECT(info[jss::error] == "invalidParams");
328 }
329
330 // Give alice a big signer list
331 Account const demon{"demon"};
332 Account const ghost{"ghost"};
333 Account const haunt{"haunt"};
334 Account const jinni{"jinni"};
335 Account const phase{"phase"};
336 Account const shade{"shade"};
337 Account const spook{"spook"};
338
339 Json::Value const bigSigners = signers(
340 alice,
341 4,
342 {
343 {bogie, 1},
344 {demon, 1},
345 {ghost, 1},
346 {haunt, 1},
347 {jinni, 1},
348 {phase, 1},
349 {shade, 1},
350 {spook, 1},
351 });
352 env(bigSigners);
353 {
354 // account_info with the "signer_lists" argument.
355 auto const info =
356 env.rpc("json", "account_info", to_string(withSigners));
357 BEAST_EXPECT(info.isMember(jss::result));
358 auto const& data = info[jss::result];
359 BEAST_EXPECT(data.isMember(jss::signer_lists));
360 auto const& signerLists = data[jss::signer_lists];
361 BEAST_EXPECT(signerLists.isArray());
362 BEAST_EXPECT(signerLists.size() == 1);
363 auto const& signers = signerLists[0u];
364 BEAST_EXPECT(signers.isObject());
365 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 4);
366 auto const& signerEntries = signers[sfSignerEntries.jsonName];
367 BEAST_EXPECT(signerEntries.size() == 8);
368 for (unsigned i = 0u; i < 8; ++i)
369 {
370 auto const& entry = signerEntries[i][sfSignerEntry.jsonName];
371 BEAST_EXPECT(entry.size() == 2);
372 BEAST_EXPECT(entry.isMember(sfAccount.jsonName));
373 BEAST_EXPECT(entry[sfSignerWeight.jsonName] == 1);
374 }
375 }
376 }
377
378 // Test the "signer_lists" argument in account_info, version 2 API.
379 void
381 {
382 testcase("Signer lists v2");
383 using namespace jtx;
384 Env env(*this);
385 Account const alice{"alice"};
386 env.fund(XRP(1000), alice);
387
388 auto const withoutSigners = std::string("{ ") +
389 "\"jsonrpc\": \"2.0\", "
390 "\"ripplerpc\": \"2.0\", "
391 "\"id\": 5, "
392 "\"method\": \"account_info\", "
393 "\"params\": { "
394 "\"account\": \"" +
395 alice.human() + "\"}}";
396
397 auto const withSigners = std::string("{ ") +
398 "\"jsonrpc\": \"2.0\", "
399 "\"ripplerpc\": \"2.0\", "
400 "\"id\": 6, "
401 "\"method\": \"account_info\", "
402 "\"params\": { "
403 "\"account\": \"" +
404 alice.human() + "\", " + "\"signer_lists\": true }}";
405 // Alice has no SignerList yet.
406 {
407 // account_info without the "signer_lists" argument.
408 auto const info = env.rpc("json2", withoutSigners);
409 BEAST_EXPECT(
410 info.isMember(jss::result) &&
411 info[jss::result].isMember(jss::account_data));
412 BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
413 jss::signer_lists));
414 BEAST_EXPECT(
415 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
416 BEAST_EXPECT(
417 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
418 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
419 }
420 {
421 // account_info with the "signer_lists" argument.
422 auto const info = env.rpc("json2", withSigners);
423 BEAST_EXPECT(
424 info.isMember(jss::result) &&
425 info[jss::result].isMember(jss::account_data));
426 auto const& data = info[jss::result][jss::account_data];
427 BEAST_EXPECT(data.isMember(jss::signer_lists));
428 auto const& signerLists = data[jss::signer_lists];
429 BEAST_EXPECT(signerLists.isArray());
430 BEAST_EXPECT(signerLists.size() == 0);
431 BEAST_EXPECT(
432 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
433 BEAST_EXPECT(
434 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
435 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
436 }
437 {
438 // Do both of the above as a batch job
439 auto const info = env.rpc(
440 "json2", '[' + withoutSigners + ", " + withSigners + ']');
441 BEAST_EXPECT(
442 info[0u].isMember(jss::result) &&
443 info[0u][jss::result].isMember(jss::account_data));
444 BEAST_EXPECT(!info[0u][jss::result][jss::account_data].isMember(
445 jss::signer_lists));
446 BEAST_EXPECT(
447 info[0u].isMember(jss::jsonrpc) &&
448 info[0u][jss::jsonrpc] == "2.0");
449 BEAST_EXPECT(
450 info[0u].isMember(jss::ripplerpc) &&
451 info[0u][jss::ripplerpc] == "2.0");
452 BEAST_EXPECT(info[0u].isMember(jss::id) && info[0u][jss::id] == 5);
453
454 BEAST_EXPECT(
455 info[1u].isMember(jss::result) &&
456 info[1u][jss::result].isMember(jss::account_data));
457 auto const& data = info[1u][jss::result][jss::account_data];
458 BEAST_EXPECT(data.isMember(jss::signer_lists));
459 auto const& signerLists = data[jss::signer_lists];
460 BEAST_EXPECT(signerLists.isArray());
461 BEAST_EXPECT(signerLists.size() == 0);
462 BEAST_EXPECT(
463 info[1u].isMember(jss::jsonrpc) &&
464 info[1u][jss::jsonrpc] == "2.0");
465 BEAST_EXPECT(
466 info[1u].isMember(jss::ripplerpc) &&
467 info[1u][jss::ripplerpc] == "2.0");
468 BEAST_EXPECT(info[1u].isMember(jss::id) && info[1u][jss::id] == 6);
469 }
470
471 // Give alice a SignerList.
472 Account const bogie{"bogie"};
473
474 Json::Value const smallSigners = signers(alice, 2, {{bogie, 3}});
475 env(smallSigners);
476 {
477 // account_info without the "signer_lists" argument.
478 auto const info = env.rpc("json2", withoutSigners);
479 BEAST_EXPECT(
480 info.isMember(jss::result) &&
481 info[jss::result].isMember(jss::account_data));
482 BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
483 jss::signer_lists));
484 BEAST_EXPECT(
485 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
486 BEAST_EXPECT(
487 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
488 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
489 }
490 {
491 // account_info with the "signer_lists" argument.
492 auto const info = env.rpc("json2", withSigners);
493 BEAST_EXPECT(
494 info.isMember(jss::result) &&
495 info[jss::result].isMember(jss::account_data));
496 auto const& data = info[jss::result][jss::account_data];
497 BEAST_EXPECT(data.isMember(jss::signer_lists));
498 auto const& signerLists = data[jss::signer_lists];
499 BEAST_EXPECT(signerLists.isArray());
500 BEAST_EXPECT(signerLists.size() == 1);
501 auto const& signers = signerLists[0u];
502 BEAST_EXPECT(signers.isObject());
503 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 2);
504 auto const& signerEntries = signers[sfSignerEntries.jsonName];
505 BEAST_EXPECT(signerEntries.size() == 1);
506 auto const& entry0 = signerEntries[0u][sfSignerEntry.jsonName];
507 BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3);
508 BEAST_EXPECT(
509 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
510 BEAST_EXPECT(
511 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
512 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
513 }
514
515 // Give alice a big signer list
516 Account const demon{"demon"};
517 Account const ghost{"ghost"};
518 Account const haunt{"haunt"};
519 Account const jinni{"jinni"};
520 Account const phase{"phase"};
521 Account const shade{"shade"};
522 Account const spook{"spook"};
523
524 Json::Value const bigSigners = signers(
525 alice,
526 4,
527 {
528 {bogie, 1},
529 {demon, 1},
530 {ghost, 1},
531 {haunt, 1},
532 {jinni, 1},
533 {phase, 1},
534 {shade, 1},
535 {spook, 1},
536 });
537 env(bigSigners);
538 {
539 // account_info with the "signer_lists" argument.
540 auto const info = env.rpc("json2", withSigners);
541 BEAST_EXPECT(
542 info.isMember(jss::result) &&
543 info[jss::result].isMember(jss::account_data));
544 auto const& data = info[jss::result][jss::account_data];
545 BEAST_EXPECT(data.isMember(jss::signer_lists));
546 auto const& signerLists = data[jss::signer_lists];
547 BEAST_EXPECT(signerLists.isArray());
548 BEAST_EXPECT(signerLists.size() == 1);
549 auto const& signers = signerLists[0u];
550 BEAST_EXPECT(signers.isObject());
551 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 4);
552 auto const& signerEntries = signers[sfSignerEntries.jsonName];
553 BEAST_EXPECT(signerEntries.size() == 8);
554 for (unsigned i = 0u; i < 8; ++i)
555 {
556 auto const& entry = signerEntries[i][sfSignerEntry.jsonName];
557 BEAST_EXPECT(entry.size() == 2);
558 BEAST_EXPECT(entry.isMember(sfAccount.jsonName));
559 BEAST_EXPECT(entry[sfSignerWeight.jsonName] == 1);
560 }
561 BEAST_EXPECT(
562 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
563 BEAST_EXPECT(
564 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
565 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
566 }
567 }
568
569 void
571 {
572 testcase("Account flags");
573 using namespace jtx;
574
575 Env env(*this, features);
576 Account const alice{"alice"};
577 Account const bob{"bob"};
578 env.fund(XRP(1000), alice, bob);
579
580 auto getAccountFlag = [&env](
581 std::string_view fName,
582 Account const& account) {
583 Json::Value params;
584 params[jss::account] = account.human();
585 auto const info =
586 env.rpc("json", "account_info", to_string(params));
587
589 if (info[jss::result][jss::status] == "success" &&
590 info[jss::result][jss::account_flags].isMember(fName.data()))
591 res.emplace(info[jss::result][jss::account_flags][fName.data()]
592 .asBool());
593
594 return res;
595 };
596
597 static constexpr std::
599 asFlags{
600 {{"defaultRipple", asfDefaultRipple},
601 {"depositAuth", asfDepositAuth},
602 {"disallowIncomingXRP", asfDisallowXRP},
603 {"globalFreeze", asfGlobalFreeze},
604 {"noFreeze", asfNoFreeze},
605 {"requireAuthorization", asfRequireAuth},
606 {"requireDestinationTag", asfRequireDest}}};
607
608 for (auto& asf : asFlags)
609 {
610 // Clear a flag and check that account_info returns results
611 // as expected
612 env(fclear(alice, asf.second));
613 env.close();
614 auto const f1 = getAccountFlag(asf.first, alice);
615 BEAST_EXPECT(f1.has_value());
616 BEAST_EXPECT(!f1.value());
617
618 // Set a flag and check that account_info returns results
619 // as expected
620 env(fset(alice, asf.second));
621 env.close();
622 auto const f2 = getAccountFlag(asf.first, alice);
623 BEAST_EXPECT(f2.has_value());
624 BEAST_EXPECT(f2.value());
625 }
626
627 static constexpr std::
629 disallowIncomingFlags{
630 {{"disallowIncomingCheck", asfDisallowIncomingCheck},
631 {"disallowIncomingNFTokenOffer",
633 {"disallowIncomingPayChan", asfDisallowIncomingPayChan},
634 {"disallowIncomingTrustline",
636
637 if (features[featureDisallowIncoming])
638 {
639 for (auto& asf : disallowIncomingFlags)
640 {
641 // Clear a flag and check that account_info returns results
642 // as expected
643 env(fclear(alice, asf.second));
644 env.close();
645 auto const f1 = getAccountFlag(asf.first, alice);
646 BEAST_EXPECT(f1.has_value());
647 BEAST_EXPECT(!f1.value());
648
649 // Set a flag and check that account_info returns results
650 // as expected
651 env(fset(alice, asf.second));
652 env.close();
653 auto const f2 = getAccountFlag(asf.first, alice);
654 BEAST_EXPECT(f2.has_value());
655 BEAST_EXPECT(f2.value());
656 }
657 }
658 else
659 {
660 for (auto& asf : disallowIncomingFlags)
661 {
662 BEAST_EXPECT(!getAccountFlag(asf.first, alice));
663 }
664 }
665
667 allowTrustLineClawbackFlag{
668 "allowTrustLineClawback", asfAllowTrustLineClawback};
669
670 if (features[featureClawback])
671 {
672 // must use bob's account because alice has noFreeze set
673 auto const f1 =
674 getAccountFlag(allowTrustLineClawbackFlag.first, bob);
675 BEAST_EXPECT(f1.has_value());
676 BEAST_EXPECT(!f1.value());
677
678 // Set allowTrustLineClawback
679 env(fset(bob, allowTrustLineClawbackFlag.second));
680 env.close();
681 auto const f2 =
682 getAccountFlag(allowTrustLineClawbackFlag.first, bob);
683 BEAST_EXPECT(f2.has_value());
684 BEAST_EXPECT(f2.value());
685 }
686 else
687 {
688 BEAST_EXPECT(
689 !getAccountFlag(allowTrustLineClawbackFlag.first, bob));
690 }
691
693 allowTrustLineLockingFlag{
694 "allowTrustLineLocking", asfAllowTrustLineLocking};
695
696 if (features[featureTokenEscrow])
697 {
698 auto const f1 =
699 getAccountFlag(allowTrustLineLockingFlag.first, bob);
700 BEAST_EXPECT(f1.has_value());
701 BEAST_EXPECT(!f1.value());
702
703 // Set allowTrustLineLocking
704 env(fset(bob, allowTrustLineLockingFlag.second));
705 env.close();
706 auto const f2 =
707 getAccountFlag(allowTrustLineLockingFlag.first, bob);
708 BEAST_EXPECT(f2.has_value());
709 BEAST_EXPECT(f2.value());
710 }
711 else
712 {
713 BEAST_EXPECT(!getAccountFlag(allowTrustLineLockingFlag.first, bob));
714 }
715 }
716
717 void
718 run() override
719 {
720 testErrors();
724
725 FeatureBitset const allFeatures{
727 testAccountFlags(allFeatures);
728 testAccountFlags(allFeatures - featureDisallowIncoming);
730 allFeatures - featureDisallowIncoming - featureClawback);
732 allFeatures - featureDisallowIncoming - featureClawback -
733 featureTokenEscrow);
734 }
735};
736
737BEAST_DEFINE_TESTSUITE(AccountInfo, rpc, ripple);
738
739} // namespace test
740} // namespace ripple
Represents a JSON value.
Definition json_value.h:149
UInt size() const
Number of values in array or object.
bool isObject() const
bool isMember(char const *key) const
Return true if the object has a member named key.
A testsuite class.
Definition suite.h:55
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:155
void run() override
Runs the suite.
void testAccountFlags(FeatureBitset const &features)
Immutable cryptographic account descriptor.
Definition Account.h:39
A transaction testing environment.
Definition Env.h:121
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:122
Json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition Env.h:791
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:290
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition rpc.h:35
T data(T... args)
T emplace(T... args)
T is_same_v
@ nullValue
'null' value
Definition json_value.h:38
@ arrayValue
array value (ordered list)
Definition json_value.h:44
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:45
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Definition flags.h:121
auto const data
General field definitions, or fields used in multiple transaction namespaces.
Json::Value signers(Account const &account, std::uint32_t quorum, std::vector< signer > const &v)
Definition multisign.cpp:34
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Definition flags.cpp:29
FeatureBitset testable_amendments()
Definition Env.h:74
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:111
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
constexpr std::uint32_t asfGlobalFreeze
Definition TxFlags.h:83
constexpr std::uint32_t asfDepositAuth
Definition TxFlags.h:85
constexpr std::uint32_t asfDisallowIncomingNFTokenOffer
Definition TxFlags.h:90
constexpr std::uint32_t asfAllowTrustLineLocking
Definition TxFlags.h:95
constexpr std::uint32_t asfRequireDest
Definition TxFlags.h:77
@ rpcACT_NOT_FOUND
Definition ErrorCodes.h:70
@ rpcACT_MALFORMED
Definition ErrorCodes.h:90
constexpr std::uint32_t asfNoFreeze
Definition TxFlags.h:82
constexpr std::uint32_t asfDisallowIncomingTrustline
Definition TxFlags.h:93
constexpr std::uint32_t asfDefaultRipple
Definition TxFlags.h:84
constexpr std::uint32_t asfDisallowIncomingCheck
Definition TxFlags.h:91
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:630
constexpr std::uint32_t asfDisallowIncomingPayChan
Definition TxFlags.h:92
constexpr std::uint32_t asfAllowTrustLineClawback
Definition TxFlags.h:94
constexpr std::uint32_t asfRequireAuth
Definition TxFlags.h:78
constexpr std::uint32_t asfDisallowXRP
Definition TxFlags.h:79