rippled
Loading...
Searching...
No Matches
LedgerData_test.cpp
1#include <test/jtx.h>
2
3#include <xrpl/basics/StringUtilities.h>
4#include <xrpl/protocol/jss.h>
5
6namespace xrpl {
7
9{
10public:
11 // test helper
12 static bool
14 {
15 return val.isMember(jss::marker) && val[jss::marker].isString() && val[jss::marker].asString().size() > 0;
16 }
17
18 void
20 {
21 using namespace test::jtx;
22 Env env{*this, asAdmin ? envconfig() : envconfig(no_admin)};
23 Account const gw{"gateway"};
24 auto const USD = gw["USD"];
25 env.fund(XRP(100000), gw);
26
27 int const max_limit = 256; // would be 2048 for binary requests, no
28 // need to test that here
29
30 for (auto i = 0; i < max_limit + 10; i++)
31 {
32 Account const bob{std::string("bob") + std::to_string(i)};
33 env.fund(XRP(1000), bob);
34 }
35 // Note that calls to env.close() fail without admin permission.
36 if (asAdmin)
37 env.close();
38
39 // with no limit specified, we get the max_limit if the total number of
40 // accounts is greater than max, which it is here
41 Json::Value jvParams;
42 jvParams[jss::ledger_index] = "current";
43 jvParams[jss::binary] = false;
44 {
45 auto const jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
46 BEAST_EXPECT(jrr[jss::ledger_current_index].isIntegral() && jrr[jss::ledger_current_index].asInt() > 0);
47 BEAST_EXPECT(checkMarker(jrr));
48 BEAST_EXPECT(checkArraySize(jrr[jss::state], max_limit));
49 }
50
51 // check limits values around the max_limit (+/- 1)
52 for (auto delta = -1; delta <= 1; delta++)
53 {
54 jvParams[jss::limit] = max_limit + delta;
55 auto const jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
56 BEAST_EXPECT(checkArraySize(jrr[jss::state], (delta > 0 && !asAdmin) ? max_limit : max_limit + delta));
57 }
58 }
59
60 void
62 {
63 using namespace test::jtx;
64 Env env{*this, envconfig(no_admin)};
65 Account const gw{"gateway"};
66 auto const USD = gw["USD"];
67 env.fund(XRP(100000), gw);
68
69 int const num_accounts = 10;
70
71 for (auto i = 0; i < num_accounts; i++)
72 {
73 Account const bob{std::string("bob") + std::to_string(i)};
74 env.fund(XRP(1000), bob);
75 }
76
77 // with no limit specified, we should get all of our fund entries
78 // plus three more related to the gateway setup
79 Json::Value jvParams;
80 jvParams[jss::ledger_index] = "current";
81 jvParams[jss::binary] = true;
82 auto const jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
83 BEAST_EXPECT(jrr[jss::ledger_current_index].isIntegral() && jrr[jss::ledger_current_index].asInt() > 0);
84 BEAST_EXPECT(!jrr.isMember(jss::marker));
85 BEAST_EXPECT(checkArraySize(jrr[jss::state], num_accounts + 4));
86 }
87
88 void
90 {
91 using namespace test::jtx;
92 Env env{*this};
93 Account const gw{"gateway"};
94 auto const USD = gw["USD"];
95 Account const bob{"bob"};
96
97 env.fund(XRP(10000), gw, bob);
98 env.trust(USD(1000), bob);
99
100 {
101 // bad limit
102 Json::Value jvParams;
103 jvParams[jss::limit] = "0"; // NOT an integer
104 auto const jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
105 BEAST_EXPECT(jrr[jss::error] == "invalidParams");
106 BEAST_EXPECT(jrr[jss::status] == "error");
107 BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'limit', not integer.");
108 }
109
110 {
111 // invalid marker
112 Json::Value jvParams;
113 jvParams[jss::marker] = "NOT_A_MARKER";
114 auto const jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
115 BEAST_EXPECT(jrr[jss::error] == "invalidParams");
116 BEAST_EXPECT(jrr[jss::status] == "error");
117 BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'marker', not valid.");
118 }
119
120 {
121 // invalid marker - not a string
122 Json::Value jvParams;
123 jvParams[jss::marker] = 1;
124 auto const jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
125 BEAST_EXPECT(jrr[jss::error] == "invalidParams");
126 BEAST_EXPECT(jrr[jss::status] == "error");
127 BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'marker', not valid.");
128 }
129
130 {
131 // ask for a bad ledger index
132 Json::Value jvParams;
133 jvParams[jss::ledger_index] = 10u;
134 auto const jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
135 BEAST_EXPECT(jrr[jss::error] == "lgrNotFound");
136 BEAST_EXPECT(jrr[jss::status] == "error");
137 BEAST_EXPECT(jrr[jss::error_message] == "ledgerNotFound");
138 }
139 }
140
141 void
143 {
144 using namespace test::jtx;
145 Env env{*this, envconfig(no_admin)};
146 Account const gw{"gateway"};
147 auto const USD = gw["USD"];
148 env.fund(XRP(100000), gw);
149
150 int const num_accounts = 20;
151
152 for (auto i = 0; i < num_accounts; i++)
153 {
154 Account const bob{std::string("bob") + std::to_string(i)};
155 env.fund(XRP(1000), bob);
156 }
157
158 // with no limit specified, we should get all of our fund entries
159 // plus three more related to the gateway setup
160 Json::Value jvParams;
161 jvParams[jss::ledger_index] = "current";
162 jvParams[jss::binary] = false;
163 auto jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
164 auto const total_count = jrr[jss::state].size();
165
166 // now make request with a limit and loop until we get all
167 jvParams[jss::limit] = 5;
168 jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
169 BEAST_EXPECT(checkMarker(jrr));
170 auto running_total = jrr[jss::state].size();
171 while (jrr.isMember(jss::marker))
172 {
173 jvParams[jss::marker] = jrr[jss::marker];
174 jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
175 running_total += jrr[jss::state].size();
176 }
177 BEAST_EXPECT(running_total == total_count);
178 }
179
180 void
182 {
183 using namespace test::jtx;
184 Env env{*this};
185 env.fund(XRP(100000), "alice");
186 env.close();
187
188 // Ledger header should be present in the first query
189 {
190 // Closed ledger with non binary form
191 Json::Value jvParams;
192 jvParams[jss::ledger_index] = "closed";
193 auto jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
194 if (BEAST_EXPECT(jrr.isMember(jss::ledger)))
195 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_hash] == to_string(env.closed()->header().hash));
196 }
197 {
198 // Closed ledger with binary form
199 Json::Value jvParams;
200 jvParams[jss::ledger_index] = "closed";
201 jvParams[jss::binary] = true;
202 auto jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
203 if (BEAST_EXPECT(jrr.isMember(jss::ledger)))
204 {
205 auto data = strUnHex(jrr[jss::ledger][jss::ledger_data].asString());
206 if (BEAST_EXPECT(data))
207 {
208 Serializer s(data->data(), data->size());
209 std::uint32_t seq = 0;
210 BEAST_EXPECT(s.getInteger<std::uint32_t>(seq, 0));
211 BEAST_EXPECT(seq == 3);
212 }
213 }
214 }
215 {
216 // Current ledger with binary form
217 Json::Value jvParams;
218 jvParams[jss::binary] = true;
219 auto jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
220 BEAST_EXPECT(jrr.isMember(jss::ledger));
221 BEAST_EXPECT(!jrr[jss::ledger].isMember(jss::ledger_data));
222 }
223 }
224
225 void
227 {
228 // Put a bunch of different LedgerEntryTypes into a ledger
229 using namespace test::jtx;
230
231 // Make sure fixInnerObjTemplate2 doesn't break amendments.
232 for (FeatureBitset const& features :
233 {testable_amendments() - fixInnerObjTemplate2, testable_amendments() | fixInnerObjTemplate2})
234 {
235 using namespace std::chrono;
236 Env env{*this, envconfig(validator, ""), features};
237
238 Account const gw{"gateway"};
239 auto const USD = gw["USD"];
240 env.fund(XRP(100000), gw);
241
242 auto makeRequest = [&env](Json::StaticString const& type) {
243 Json::Value jvParams;
244 jvParams[jss::ledger_index] = "current";
245 jvParams[jss::type] = type;
246 return env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
247 };
248
249 // Assert that state is an empty array.
250 for (auto const& type :
251 {jss::amendments,
252 jss::check,
253 jss::directory,
254 jss::offer,
255 jss::signer_list,
256 jss::state,
257 jss::ticket,
258 jss::escrow,
259 jss::payment_channel,
260 jss::deposit_preauth})
261 {
262 auto const jrr = makeRequest(type);
263 BEAST_EXPECT(checkArraySize(jrr[jss::state], 0));
264 }
265
266 int const num_accounts = 10;
267
268 for (auto i = 0; i < num_accounts; i++)
269 {
270 Account const bob{std::string("bob") + std::to_string(i)};
271 env.fund(XRP(1000), bob);
272 }
273 env(offer(Account{"bob0"}, USD(100), XRP(100)));
274 env.trust(Account{"bob2"}["USD"](100), Account{"bob3"});
275
276 auto majorities = getMajorityAmendments(*env.closed());
277 for (int i = 0; i <= 256; ++i)
278 {
279 env.close();
280 majorities = getMajorityAmendments(*env.closed());
281 if (!majorities.empty())
282 break;
283 }
284
285 env(signers(Account{"bob0"}, 1, {{Account{"bob1"}, 1}, {Account{"bob2"}, 1}}));
286 env(ticket::create(env.master, 1));
287
288 {
289 Json::Value jv;
290 jv[jss::TransactionType] = jss::EscrowCreate;
291 jv[jss::Account] = Account{"bob5"}.human();
292 jv[jss::Destination] = Account{"bob6"}.human();
293 jv[jss::Amount] = XRP(50).value().getJson(JsonOptions::none);
294 jv[sfFinishAfter.fieldName] = NetClock::time_point{env.now() + 10s}.time_since_epoch().count();
295 env(jv);
296 }
297
298 {
299 Json::Value jv;
300 jv[jss::TransactionType] = jss::PaymentChannelCreate;
301 jv[jss::Account] = Account{"bob6"}.human();
302 jv[jss::Destination] = Account{"bob7"}.human();
303 jv[jss::Amount] = XRP(100).value().getJson(JsonOptions::none);
304 jv[jss::SettleDelay] = NetClock::duration{10s}.count();
305 jv[sfPublicKey.fieldName] = strHex(Account{"bob6"}.pk().slice());
306 jv[sfCancelAfter.fieldName] = NetClock::time_point{env.now() + 300s}.time_since_epoch().count();
307 env(jv);
308 }
309
310 env(check::create("bob6", "bob7", XRP(100)));
311
312 // bob9 DepositPreauths bob4 and bob8.
313 env(deposit::auth(Account{"bob9"}, Account{"bob4"}));
314 env(deposit::auth(Account{"bob9"}, Account{"bob8"}));
315 env.close();
316
317 // Now fetch each type
318
319 { // jvParams[jss::type] = "account";
320 auto const jrr = makeRequest(jss::account);
321 BEAST_EXPECT(checkArraySize(jrr[jss::state], 12));
322 for (auto const& j : jrr[jss::state])
323 BEAST_EXPECT(j["LedgerEntryType"] == jss::AccountRoot);
324 }
325
326 { // jvParams[jss::type] = "amendments";
327 auto const jrr = makeRequest(jss::amendments);
328 BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
329 for (auto const& j : jrr[jss::state])
330 BEAST_EXPECT(j["LedgerEntryType"] == jss::Amendments);
331 }
332
333 { // jvParams[jss::type] = "check";
334 auto const jrr = makeRequest(jss::check);
335 BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
336 for (auto const& j : jrr[jss::state])
337 BEAST_EXPECT(j["LedgerEntryType"] == jss::Check);
338 }
339
340 { // jvParams[jss::type] = "directory";
341 auto const jrr = makeRequest(jss::directory);
342 BEAST_EXPECT(checkArraySize(jrr[jss::state], 9));
343 for (auto const& j : jrr[jss::state])
344 BEAST_EXPECT(j["LedgerEntryType"] == jss::DirectoryNode);
345 }
346
347 { // jvParams[jss::type] = "fee";
348 auto const jrr = makeRequest(jss::fee);
349 BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
350 for (auto const& j : jrr[jss::state])
351 BEAST_EXPECT(j["LedgerEntryType"] == jss::FeeSettings);
352 }
353
354 { // jvParams[jss::type] = "hashes";
355 auto const jrr = makeRequest(jss::hashes);
356 BEAST_EXPECT(checkArraySize(jrr[jss::state], 2));
357 for (auto const& j : jrr[jss::state])
358 BEAST_EXPECT(j["LedgerEntryType"] == jss::LedgerHashes);
359 }
360
361 { // jvParams[jss::type] = "offer";
362 auto const jrr = makeRequest(jss::offer);
363 BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
364 for (auto const& j : jrr[jss::state])
365 BEAST_EXPECT(j["LedgerEntryType"] == jss::Offer);
366 }
367
368 { // jvParams[jss::type] = "signer_list";
369 auto const jrr = makeRequest(jss::signer_list);
370 BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
371 for (auto const& j : jrr[jss::state])
372 BEAST_EXPECT(j["LedgerEntryType"] == jss::SignerList);
373 }
374
375 { // jvParams[jss::type] = "state";
376 auto const jrr = makeRequest(jss::state);
377 BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
378 for (auto const& j : jrr[jss::state])
379 BEAST_EXPECT(j["LedgerEntryType"] == jss::RippleState);
380 }
381
382 { // jvParams[jss::type] = "ticket";
383 auto const jrr = makeRequest(jss::ticket);
384 BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
385 for (auto const& j : jrr[jss::state])
386 BEAST_EXPECT(j["LedgerEntryType"] == jss::Ticket);
387 }
388
389 { // jvParams[jss::type] = "escrow";
390 auto const jrr = makeRequest(jss::escrow);
391 BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
392 for (auto const& j : jrr[jss::state])
393 BEAST_EXPECT(j["LedgerEntryType"] == jss::Escrow);
394 }
395
396 { // jvParams[jss::type] = "payment_channel";
397 auto const jrr = makeRequest(jss::payment_channel);
398 BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
399 for (auto const& j : jrr[jss::state])
400 BEAST_EXPECT(j["LedgerEntryType"] == jss::PayChannel);
401 }
402
403 { // jvParams[jss::type] = "deposit_preauth";
404 auto const jrr = makeRequest(jss::deposit_preauth);
405 BEAST_EXPECT(checkArraySize(jrr[jss::state], 2));
406 for (auto const& j : jrr[jss::state])
407 BEAST_EXPECT(j["LedgerEntryType"] == jss::DepositPreauth);
408 }
409
410 { // jvParams[jss::type] = "misspelling";
411 Json::Value jvParams;
412 jvParams[jss::ledger_index] = "current";
413 jvParams[jss::type] = "misspelling";
414 auto const jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result];
415 BEAST_EXPECT(jrr.isMember("error"));
416 BEAST_EXPECT(jrr["error"] == "invalidParams");
417 BEAST_EXPECT(jrr["error_message"] == "Invalid field 'type'.");
418 }
419 }
420 }
421
422 void
433};
434
435BEAST_DEFINE_TESTSUITE_PRIO(LedgerData, rpc, xrpl, 1);
436
437} // namespace xrpl
Lightweight wrapper to tag static string.
Definition json_value.h:45
Represents a JSON value.
Definition json_value.h:131
UInt size() const
Number of values in array or object.
bool isString() const
std::string asString() const
Returns the unquoted string value.
bool isMember(char const *key) const
Return true if the object has a member named key.
A testsuite class.
Definition suite.h:52
void run() override
Runs the suite.
static bool checkMarker(Json::Value const &val)
void testCurrentLedgerToLimits(bool asAdmin)
bool getInteger(Integer &number, int offset)
Definition Serializer.h:136
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:598
std::string strHex(FwdIt begin, FwdIt end)
Definition strHex.h:11
auto makeRequest(bool crawlPublic, bool comprEnabled, bool ledgerReplayEnabled, bool txReduceRelayEnabled, bool vpReduceRelayEnabled) -> request_type
Make outbound http request.
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
majorityAmendments_t getMajorityAmendments(ReadView const &view)
Definition View.cpp:856
T size(T... args)
T time_since_epoch(T... args)
T to_string(T... args)