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 auto const info = env.rpc(
62 "json",
63 "account_info",
64 R"({ "account": ")" + bogie.human() + R"("})");
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
123 testSignerLists()
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 auto const withoutSigners =
132 std::string("{ ") + "\"account\": \"" + alice.human() + "\"}";
133
134 auto const withSigners = std::string("{ ") + "\"account\": \"" +
135 alice.human() + "\", " + "\"signer_lists\": true }";
136
137 // Alice has no SignerList yet.
138 {
139 // account_info without the "signer_lists" argument.
140 auto const info = env.rpc("json", "account_info", withoutSigners);
141 BEAST_EXPECT(
142 info.isMember(jss::result) &&
143 info[jss::result].isMember(jss::account_data));
144 BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
145 jss::signer_lists));
146 }
147 {
148 // account_info with the "signer_lists" argument.
149 auto const info = env.rpc("json", "account_info", withSigners);
150 BEAST_EXPECT(
151 info.isMember(jss::result) &&
152 info[jss::result].isMember(jss::account_data));
153 auto const& data = info[jss::result][jss::account_data];
154 BEAST_EXPECT(data.isMember(jss::signer_lists));
155 auto const& signerLists = data[jss::signer_lists];
156 BEAST_EXPECT(signerLists.isArray());
157 BEAST_EXPECT(signerLists.size() == 0);
158 }
159
160 // Give alice a SignerList.
161 Account const bogie{"bogie"};
162
163 Json::Value const smallSigners = signers(alice, 2, {{bogie, 3}});
164 env(smallSigners);
165 {
166 // account_info without the "signer_lists" argument.
167 auto const info = env.rpc("json", "account_info", withoutSigners);
168 BEAST_EXPECT(
169 info.isMember(jss::result) &&
170 info[jss::result].isMember(jss::account_data));
171 BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
172 jss::signer_lists));
173 }
174 {
175 // account_info with the "signer_lists" argument.
176 auto const info = env.rpc("json", "account_info", withSigners);
177 BEAST_EXPECT(
178 info.isMember(jss::result) &&
179 info[jss::result].isMember(jss::account_data));
180 auto const& data = info[jss::result][jss::account_data];
181 BEAST_EXPECT(data.isMember(jss::signer_lists));
182 auto const& signerLists = data[jss::signer_lists];
183 BEAST_EXPECT(signerLists.isArray());
184 BEAST_EXPECT(signerLists.size() == 1);
185 auto const& signers = signerLists[0u];
186 BEAST_EXPECT(signers.isObject());
187 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 2);
188 auto const& signerEntries = signers[sfSignerEntries.jsonName];
189 BEAST_EXPECT(signerEntries.size() == 1);
190 auto const& entry0 = signerEntries[0u][sfSignerEntry.jsonName];
191 BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3);
192 }
193
194 // Give alice a big signer list
195 Account const demon{"demon"};
196 Account const ghost{"ghost"};
197 Account const haunt{"haunt"};
198 Account const jinni{"jinni"};
199 Account const phase{"phase"};
200 Account const shade{"shade"};
201 Account const spook{"spook"};
202
203 Json::Value const bigSigners = signers(
204 alice,
205 4,
206 {
207 {bogie, 1},
208 {demon, 1},
209 {ghost, 1},
210 {haunt, 1},
211 {jinni, 1},
212 {phase, 1},
213 {shade, 1},
214 {spook, 1},
215 });
216 env(bigSigners);
217 {
218 // account_info with the "signer_lists" argument.
219 auto const info = env.rpc("json", "account_info", withSigners);
220 BEAST_EXPECT(
221 info.isMember(jss::result) &&
222 info[jss::result].isMember(jss::account_data));
223 auto const& data = info[jss::result][jss::account_data];
224 BEAST_EXPECT(data.isMember(jss::signer_lists));
225 auto const& signerLists = data[jss::signer_lists];
226 BEAST_EXPECT(signerLists.isArray());
227 BEAST_EXPECT(signerLists.size() == 1);
228 auto const& signers = signerLists[0u];
229 BEAST_EXPECT(signers.isObject());
230 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 4);
231 auto const& signerEntries = signers[sfSignerEntries.jsonName];
232 BEAST_EXPECT(signerEntries.size() == 8);
233 for (unsigned i = 0u; i < 8; ++i)
234 {
235 auto const& entry = signerEntries[i][sfSignerEntry.jsonName];
236 BEAST_EXPECT(entry.size() == 2);
237 BEAST_EXPECT(entry.isMember(sfAccount.jsonName));
238 BEAST_EXPECT(entry[sfSignerWeight.jsonName] == 1);
239 }
240 }
241 }
242
243 // Test the "signer_lists" argument in account_info, with api_version 2.
244 void
245 testSignerListsApiVersion2()
246 {
247 testcase("Signer lists APIv2");
248 using namespace jtx;
249 Env env{*this};
250 Account const alice{"alice"};
251 env.fund(XRP(1000), alice);
252
253 auto const withoutSigners = std::string("{ ") +
254 "\"api_version\": 2, \"account\": \"" + alice.human() + "\"}";
255
256 auto const withSigners = std::string("{ ") +
257 "\"api_version\": 2, \"account\": \"" + alice.human() + "\", " +
258 "\"signer_lists\": true }";
259
260 auto const withSignersAsString = std::string("{ ") +
261 "\"api_version\": 2, \"account\": \"" + alice.human() + "\", " +
262 "\"signer_lists\": asdfggh }";
263
264 // Alice has no SignerList yet.
265 {
266 // account_info without the "signer_lists" argument.
267 auto const info = env.rpc("json", "account_info", withoutSigners);
268 BEAST_EXPECT(info.isMember(jss::result));
269 BEAST_EXPECT(!info[jss::result].isMember(jss::signer_lists));
270 }
271 {
272 // account_info with the "signer_lists" argument.
273 auto const info = env.rpc("json", "account_info", withSigners);
274 BEAST_EXPECT(info.isMember(jss::result));
275 auto const& data = info[jss::result];
276 BEAST_EXPECT(data.isMember(jss::signer_lists));
277 auto const& signerLists = data[jss::signer_lists];
278 BEAST_EXPECT(signerLists.isArray());
279 BEAST_EXPECT(signerLists.size() == 0);
280 }
281
282 // Give alice a SignerList.
283 Account const bogie{"bogie"};
284
285 Json::Value const smallSigners = signers(alice, 2, {{bogie, 3}});
286 env(smallSigners);
287 {
288 // account_info without the "signer_lists" argument.
289 auto const info = env.rpc("json", "account_info", withoutSigners);
290 BEAST_EXPECT(info.isMember(jss::result));
291 BEAST_EXPECT(!info[jss::result].isMember(jss::signer_lists));
292 }
293 {
294 // account_info with the "signer_lists" argument.
295 auto const info = env.rpc("json", "account_info", withSigners);
296 BEAST_EXPECT(info.isMember(jss::result));
297 auto const& data = info[jss::result];
298 BEAST_EXPECT(data.isMember(jss::signer_lists));
299 auto const& signerLists = data[jss::signer_lists];
300 BEAST_EXPECT(signerLists.isArray());
301 BEAST_EXPECT(signerLists.size() == 1);
302 auto const& signers = signerLists[0u];
303 BEAST_EXPECT(signers.isObject());
304 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 2);
305 auto const& signerEntries = signers[sfSignerEntries.jsonName];
306 BEAST_EXPECT(signerEntries.size() == 1);
307 auto const& entry0 = signerEntries[0u][sfSignerEntry.jsonName];
308 BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3);
309 }
310 {
311 // account_info with "signer_lists" as not bool should error out
312 auto const info =
313 env.rpc("json", "account_info", withSignersAsString);
314 BEAST_EXPECT(info[jss::status] == "error");
315 BEAST_EXPECT(info[jss::error] == "invalidParams");
316 }
317
318 // Give alice a big signer list
319 Account const demon{"demon"};
320 Account const ghost{"ghost"};
321 Account const haunt{"haunt"};
322 Account const jinni{"jinni"};
323 Account const phase{"phase"};
324 Account const shade{"shade"};
325 Account const spook{"spook"};
326
327 Json::Value const bigSigners = signers(
328 alice,
329 4,
330 {
331 {bogie, 1},
332 {demon, 1},
333 {ghost, 1},
334 {haunt, 1},
335 {jinni, 1},
336 {phase, 1},
337 {shade, 1},
338 {spook, 1},
339 });
340 env(bigSigners);
341 {
342 // account_info with the "signer_lists" argument.
343 auto const info = env.rpc("json", "account_info", withSigners);
344 BEAST_EXPECT(info.isMember(jss::result));
345 auto const& data = info[jss::result];
346 BEAST_EXPECT(data.isMember(jss::signer_lists));
347 auto const& signerLists = data[jss::signer_lists];
348 BEAST_EXPECT(signerLists.isArray());
349 BEAST_EXPECT(signerLists.size() == 1);
350 auto const& signers = signerLists[0u];
351 BEAST_EXPECT(signers.isObject());
352 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 4);
353 auto const& signerEntries = signers[sfSignerEntries.jsonName];
354 BEAST_EXPECT(signerEntries.size() == 8);
355 for (unsigned i = 0u; i < 8; ++i)
356 {
357 auto const& entry = signerEntries[i][sfSignerEntry.jsonName];
358 BEAST_EXPECT(entry.size() == 2);
359 BEAST_EXPECT(entry.isMember(sfAccount.jsonName));
360 BEAST_EXPECT(entry[sfSignerWeight.jsonName] == 1);
361 }
362 }
363 }
364
365 // Test the "signer_lists" argument in account_info, version 2 API.
366 void
367 testSignerListsV2()
368 {
369 testcase("Signer lists v2");
370 using namespace jtx;
371 Env env(*this);
372 Account const alice{"alice"};
373 env.fund(XRP(1000), alice);
374
375 auto const withoutSigners = std::string("{ ") +
376 "\"jsonrpc\": \"2.0\", "
377 "\"ripplerpc\": \"2.0\", "
378 "\"id\": 5, "
379 "\"method\": \"account_info\", "
380 "\"params\": { "
381 "\"account\": \"" +
382 alice.human() + "\"}}";
383
384 auto const withSigners = std::string("{ ") +
385 "\"jsonrpc\": \"2.0\", "
386 "\"ripplerpc\": \"2.0\", "
387 "\"id\": 6, "
388 "\"method\": \"account_info\", "
389 "\"params\": { "
390 "\"account\": \"" +
391 alice.human() + "\", " + "\"signer_lists\": true }}";
392 // Alice has no SignerList yet.
393 {
394 // account_info without the "signer_lists" argument.
395 auto const info = env.rpc("json2", withoutSigners);
396 BEAST_EXPECT(
397 info.isMember(jss::result) &&
398 info[jss::result].isMember(jss::account_data));
399 BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
400 jss::signer_lists));
401 BEAST_EXPECT(
402 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
403 BEAST_EXPECT(
404 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
405 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
406 }
407 {
408 // account_info with the "signer_lists" argument.
409 auto const info = env.rpc("json2", withSigners);
410 BEAST_EXPECT(
411 info.isMember(jss::result) &&
412 info[jss::result].isMember(jss::account_data));
413 auto const& data = info[jss::result][jss::account_data];
414 BEAST_EXPECT(data.isMember(jss::signer_lists));
415 auto const& signerLists = data[jss::signer_lists];
416 BEAST_EXPECT(signerLists.isArray());
417 BEAST_EXPECT(signerLists.size() == 0);
418 BEAST_EXPECT(
419 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
420 BEAST_EXPECT(
421 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
422 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
423 }
424 {
425 // Do both of the above as a batch job
426 auto const info = env.rpc(
427 "json2", '[' + withoutSigners + ", " + withSigners + ']');
428 BEAST_EXPECT(
429 info[0u].isMember(jss::result) &&
430 info[0u][jss::result].isMember(jss::account_data));
431 BEAST_EXPECT(!info[0u][jss::result][jss::account_data].isMember(
432 jss::signer_lists));
433 BEAST_EXPECT(
434 info[0u].isMember(jss::jsonrpc) &&
435 info[0u][jss::jsonrpc] == "2.0");
436 BEAST_EXPECT(
437 info[0u].isMember(jss::ripplerpc) &&
438 info[0u][jss::ripplerpc] == "2.0");
439 BEAST_EXPECT(info[0u].isMember(jss::id) && info[0u][jss::id] == 5);
440
441 BEAST_EXPECT(
442 info[1u].isMember(jss::result) &&
443 info[1u][jss::result].isMember(jss::account_data));
444 auto const& data = info[1u][jss::result][jss::account_data];
445 BEAST_EXPECT(data.isMember(jss::signer_lists));
446 auto const& signerLists = data[jss::signer_lists];
447 BEAST_EXPECT(signerLists.isArray());
448 BEAST_EXPECT(signerLists.size() == 0);
449 BEAST_EXPECT(
450 info[1u].isMember(jss::jsonrpc) &&
451 info[1u][jss::jsonrpc] == "2.0");
452 BEAST_EXPECT(
453 info[1u].isMember(jss::ripplerpc) &&
454 info[1u][jss::ripplerpc] == "2.0");
455 BEAST_EXPECT(info[1u].isMember(jss::id) && info[1u][jss::id] == 6);
456 }
457
458 // Give alice a SignerList.
459 Account const bogie{"bogie"};
460
461 Json::Value const smallSigners = signers(alice, 2, {{bogie, 3}});
462 env(smallSigners);
463 {
464 // account_info without the "signer_lists" argument.
465 auto const info = env.rpc("json2", withoutSigners);
466 BEAST_EXPECT(
467 info.isMember(jss::result) &&
468 info[jss::result].isMember(jss::account_data));
469 BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
470 jss::signer_lists));
471 BEAST_EXPECT(
472 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
473 BEAST_EXPECT(
474 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
475 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
476 }
477 {
478 // account_info with the "signer_lists" argument.
479 auto const info = env.rpc("json2", withSigners);
480 BEAST_EXPECT(
481 info.isMember(jss::result) &&
482 info[jss::result].isMember(jss::account_data));
483 auto const& data = info[jss::result][jss::account_data];
484 BEAST_EXPECT(data.isMember(jss::signer_lists));
485 auto const& signerLists = data[jss::signer_lists];
486 BEAST_EXPECT(signerLists.isArray());
487 BEAST_EXPECT(signerLists.size() == 1);
488 auto const& signers = signerLists[0u];
489 BEAST_EXPECT(signers.isObject());
490 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 2);
491 auto const& signerEntries = signers[sfSignerEntries.jsonName];
492 BEAST_EXPECT(signerEntries.size() == 1);
493 auto const& entry0 = signerEntries[0u][sfSignerEntry.jsonName];
494 BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3);
495 BEAST_EXPECT(
496 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
497 BEAST_EXPECT(
498 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
499 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
500 }
501
502 // Give alice a big signer list
503 Account const demon{"demon"};
504 Account const ghost{"ghost"};
505 Account const haunt{"haunt"};
506 Account const jinni{"jinni"};
507 Account const phase{"phase"};
508 Account const shade{"shade"};
509 Account const spook{"spook"};
510
511 Json::Value const bigSigners = signers(
512 alice,
513 4,
514 {
515 {bogie, 1},
516 {demon, 1},
517 {ghost, 1},
518 {haunt, 1},
519 {jinni, 1},
520 {phase, 1},
521 {shade, 1},
522 {spook, 1},
523 });
524 env(bigSigners);
525 {
526 // account_info with the "signer_lists" argument.
527 auto const info = env.rpc("json2", withSigners);
528 BEAST_EXPECT(
529 info.isMember(jss::result) &&
530 info[jss::result].isMember(jss::account_data));
531 auto const& data = info[jss::result][jss::account_data];
532 BEAST_EXPECT(data.isMember(jss::signer_lists));
533 auto const& signerLists = data[jss::signer_lists];
534 BEAST_EXPECT(signerLists.isArray());
535 BEAST_EXPECT(signerLists.size() == 1);
536 auto const& signers = signerLists[0u];
537 BEAST_EXPECT(signers.isObject());
538 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 4);
539 auto const& signerEntries = signers[sfSignerEntries.jsonName];
540 BEAST_EXPECT(signerEntries.size() == 8);
541 for (unsigned i = 0u; i < 8; ++i)
542 {
543 auto const& entry = signerEntries[i][sfSignerEntry.jsonName];
544 BEAST_EXPECT(entry.size() == 2);
545 BEAST_EXPECT(entry.isMember(sfAccount.jsonName));
546 BEAST_EXPECT(entry[sfSignerWeight.jsonName] == 1);
547 }
548 BEAST_EXPECT(
549 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
550 BEAST_EXPECT(
551 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
552 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
553 }
554 }
555
556 void
557 testAccountFlags(FeatureBitset const& features)
558 {
559 testcase("Account flags");
560 using namespace jtx;
561
562 Env env(*this, features);
563 Account const alice{"alice"};
564 Account const bob{"bob"};
565 env.fund(XRP(1000), alice, bob);
566
567 auto getAccountFlag = [&env](
568 std::string_view fName,
569 Account const& account) {
570 auto const info = env.rpc(
571 "json",
572 "account_info",
573 R"({"account" : ")" + account.human() + R"("})");
574
576 if (info[jss::result][jss::status] == "success" &&
577 info[jss::result][jss::account_flags].isMember(fName.data()))
578 res.emplace(info[jss::result][jss::account_flags][fName.data()]
579 .asBool());
580
581 return res;
582 };
583
584 static constexpr std::
586 asFlags{
587 {{"defaultRipple", asfDefaultRipple},
588 {"depositAuth", asfDepositAuth},
589 {"disallowIncomingXRP", asfDisallowXRP},
590 {"globalFreeze", asfGlobalFreeze},
591 {"noFreeze", asfNoFreeze},
592 {"requireAuthorization", asfRequireAuth},
593 {"requireDestinationTag", asfRequireDest}}};
594
595 for (auto& asf : asFlags)
596 {
597 // Clear a flag and check that account_info returns results
598 // as expected
599 env(fclear(alice, asf.second));
600 env.close();
601 auto const f1 = getAccountFlag(asf.first, alice);
602 BEAST_EXPECT(f1.has_value());
603 BEAST_EXPECT(!f1.value());
604
605 // Set a flag and check that account_info returns results
606 // as expected
607 env(fset(alice, asf.second));
608 env.close();
609 auto const f2 = getAccountFlag(asf.first, alice);
610 BEAST_EXPECT(f2.has_value());
611 BEAST_EXPECT(f2.value());
612 }
613
614 static constexpr std::
616 disallowIncomingFlags{
617 {{"disallowIncomingCheck", asfDisallowIncomingCheck},
618 {"disallowIncomingNFTokenOffer",
620 {"disallowIncomingPayChan", asfDisallowIncomingPayChan},
621 {"disallowIncomingTrustline",
623
624 if (features[featureDisallowIncoming])
625 {
626 for (auto& asf : disallowIncomingFlags)
627 {
628 // Clear a flag and check that account_info returns results
629 // as expected
630 env(fclear(alice, asf.second));
631 env.close();
632 auto const f1 = getAccountFlag(asf.first, alice);
633 BEAST_EXPECT(f1.has_value());
634 BEAST_EXPECT(!f1.value());
635
636 // Set a flag and check that account_info returns results
637 // as expected
638 env(fset(alice, asf.second));
639 env.close();
640 auto const f2 = getAccountFlag(asf.first, alice);
641 BEAST_EXPECT(f2.has_value());
642 BEAST_EXPECT(f2.value());
643 }
644 }
645 else
646 {
647 for (auto& asf : disallowIncomingFlags)
648 {
649 BEAST_EXPECT(!getAccountFlag(asf.first, alice));
650 }
651 }
652
654 allowTrustLineClawbackFlag{
655 "allowTrustLineClawback", asfAllowTrustLineClawback};
656
657 if (features[featureClawback])
658 {
659 // must use bob's account because alice has noFreeze set
660 auto const f1 =
661 getAccountFlag(allowTrustLineClawbackFlag.first, bob);
662 BEAST_EXPECT(f1.has_value());
663 BEAST_EXPECT(!f1.value());
664
665 // Set allowTrustLineClawback
666 env(fset(bob, allowTrustLineClawbackFlag.second));
667 env.close();
668 auto const f2 =
669 getAccountFlag(allowTrustLineClawbackFlag.first, bob);
670 BEAST_EXPECT(f2.has_value());
671 BEAST_EXPECT(f2.value());
672 }
673 else
674 {
675 BEAST_EXPECT(
676 !getAccountFlag(allowTrustLineClawbackFlag.first, bob));
677 }
678
680 allowTrustLineLockingFlag{
681 "allowTrustLineLocking", asfAllowTrustLineLocking};
682
683 if (features[featureTokenEscrow])
684 {
685 auto const f1 =
686 getAccountFlag(allowTrustLineLockingFlag.first, bob);
687 BEAST_EXPECT(f1.has_value());
688 BEAST_EXPECT(!f1.value());
689
690 // Set allowTrustLineLocking
691 env(fset(bob, allowTrustLineLockingFlag.second));
692 env.close();
693 auto const f2 =
694 getAccountFlag(allowTrustLineLockingFlag.first, bob);
695 BEAST_EXPECT(f2.has_value());
696 BEAST_EXPECT(f2.value());
697 }
698 else
699 {
700 BEAST_EXPECT(!getAccountFlag(allowTrustLineLockingFlag.first, bob));
701 }
702 }
703
704 void
705 run() override
706 {
707 testErrors();
708 testSignerLists();
709 testSignerListsApiVersion2();
710 testSignerListsV2();
711
712 FeatureBitset const allFeatures{
714 testAccountFlags(allFeatures);
715 testAccountFlags(allFeatures - featureDisallowIncoming);
716 testAccountFlags(
717 allFeatures - featureDisallowIncoming - featureClawback);
718 testAccountFlags(
719 allFeatures - featureDisallowIncoming - featureClawback -
720 featureTokenEscrow);
721 }
722};
723
724BEAST_DEFINE_TESTSUITE(AccountInfo, rpc, ripple);
725
726} // namespace test
727} // 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
virtual void run()=0
Runs the suite.
Immutable cryptographic account descriptor.
Definition Account.h:39
A transaction testing environment.
Definition Env.h:121
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
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 entry(jtx::Env &env, jtx::Account const &account, jtx::Account const &authorize)
Definition delegate.cpp:55
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