rippled
Loading...
Searching...
No Matches
LedgerRequestRPC_test.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012-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
22#include <xrpld/app/ledger/LedgerMaster.h>
23#include <xrpld/rpc/detail/RPCHelpers.h>
24
25#include <xrpl/beast/unit_test.h>
26#include <xrpl/protocol/ErrorCodes.h>
27#include <xrpl/protocol/jss.h>
28
29#include <functional>
30
31namespace ripple {
32
33namespace RPC {
34
36{
37 static constexpr char const* hash1 =
38 "3020EB9E7BE24EF7D7A060CB051583EC117384636D1781AFB5B87F3E348DA489";
39 static constexpr char const* accounthash1 =
40 "BD8A3D72CA73DDE887AD63666EC2BAD07875CBA997A102579B5B95ECDFFEAED8";
41
42 static constexpr char const* zerohash =
43 "0000000000000000000000000000000000000000000000000000000000000000";
44
45public:
46 void
48 {
49 using namespace test::jtx;
50
51 Env env(*this);
52
53 env.close();
54 env.close();
55 BEAST_EXPECT(env.current()->info().seq == 5);
56
57 {
58 // arbitrary text is converted to 0.
59 auto const result = env.rpc("ledger_request", "arbitrary_text");
60 BEAST_EXPECT(
61 RPC::contains_error(result[jss::result]) &&
62 result[jss::result][jss::error_message] ==
63 "Ledger index too small");
64 }
65
66 {
67 auto const result = env.rpc("ledger_request", "-1");
68 BEAST_EXPECT(
69 RPC::contains_error(result[jss::result]) &&
70 result[jss::result][jss::error_message] ==
71 "Ledger index too small");
72 }
73
74 {
75 auto const result = env.rpc("ledger_request", "0");
76 BEAST_EXPECT(
77 RPC::contains_error(result[jss::result]) &&
78 result[jss::result][jss::error_message] ==
79 "Ledger index too small");
80 }
81
82 {
83 auto const result = env.rpc("ledger_request", "1");
84 BEAST_EXPECT(
85 !RPC::contains_error(result[jss::result]) &&
86 result[jss::result][jss::ledger_index] == 1 &&
87 result[jss::result].isMember(jss::ledger));
88 BEAST_EXPECT(
89 result[jss::result][jss::ledger].isMember(jss::ledger_hash) &&
90 result[jss::result][jss::ledger][jss::ledger_hash].isString());
91 }
92
93 {
94 auto const result = env.rpc("ledger_request", "2");
95 BEAST_EXPECT(
96 !RPC::contains_error(result[jss::result]) &&
97 result[jss::result][jss::ledger_index] == 2 &&
98 result[jss::result].isMember(jss::ledger));
99 BEAST_EXPECT(
100 result[jss::result][jss::ledger].isMember(jss::ledger_hash) &&
101 result[jss::result][jss::ledger][jss::ledger_hash].isString());
102 }
103
104 {
105 auto const result = env.rpc("ledger_request", "3");
106 BEAST_EXPECT(
107 !RPC::contains_error(result[jss::result]) &&
108 result[jss::result][jss::ledger_index] == 3 &&
109 result[jss::result].isMember(jss::ledger));
110 BEAST_EXPECT(
111 result[jss::result][jss::ledger].isMember(jss::ledger_hash) &&
112 result[jss::result][jss::ledger][jss::ledger_hash].isString());
113
114 auto const ledgerHash =
115 result[jss::result][jss::ledger][jss::ledger_hash].asString();
116
117 {
118 auto const r = env.rpc("ledger_request", ledgerHash);
119 BEAST_EXPECT(
120 !RPC::contains_error(r[jss::result]) &&
121 r[jss::result][jss::ledger_index] == 3 &&
122 r[jss::result].isMember(jss::ledger));
123 BEAST_EXPECT(
124 r[jss::result][jss::ledger].isMember(jss::ledger_hash) &&
125 r[jss::result][jss::ledger][jss::ledger_hash] ==
126 ledgerHash);
127 }
128 }
129
130 {
131 std::string ledgerHash(64, 'q');
132
133 auto const result = env.rpc("ledger_request", ledgerHash);
134
135 BEAST_EXPECT(
136 RPC::contains_error(result[jss::result]) &&
137 result[jss::result][jss::error_message] ==
138 "Invalid field 'ledger_hash'.");
139 }
140
141 {
142 std::string ledgerHash(64, '1');
143
144 auto const result = env.rpc("ledger_request", ledgerHash);
145
146 BEAST_EXPECT(
147 !RPC::contains_error(result[jss::result]) &&
148 result[jss::result][jss::have_header] == false);
149 }
150
151 {
152 auto const result = env.rpc("ledger_request", "4");
153 BEAST_EXPECT(
154 RPC::contains_error(result[jss::result]) &&
155 result[jss::result][jss::error_message] ==
156 "Ledger index too large");
157 }
158
159 {
160 auto const result = env.rpc("ledger_request", "5");
161 BEAST_EXPECT(
162 RPC::contains_error(result[jss::result]) &&
163 result[jss::result][jss::error_message] ==
164 "Ledger index too large");
165 }
166 }
167
168 void
170 {
171 using namespace test::jtx;
172
173 auto cfg = envconfig();
174 cfg->FEES.reference_fee = 10;
175 Env env{
176 *this,
177 std::move(cfg),
178 FeatureBitset{}}; // the hashes being checked below
179 // assume no amendments
180 Account const gw{"gateway"};
181 auto const USD = gw["USD"];
182 env.fund(XRP(100000), gw);
183 env.close();
184
185 env.memoize("bob");
186 env.fund(XRP(1000), "bob");
187 env.close();
188
189 env.memoize("alice");
190 env.fund(XRP(1000), "alice");
191 env.close();
192
193 env.memoize("carol");
194 env.fund(XRP(1000), "carol");
195 env.close();
196
197 auto result = env.rpc("ledger_request", "1")[jss::result];
198 BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "1");
199 BEAST_EXPECT(
200 result[jss::ledger][jss::total_coins] == "100000000000000000");
201 BEAST_EXPECT(result[jss::ledger][jss::closed] == true);
202 BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash1);
203 BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == zerohash);
204 BEAST_EXPECT(result[jss::ledger][jss::account_hash] == accounthash1);
205 BEAST_EXPECT(result[jss::ledger][jss::transaction_hash] == zerohash);
206
207 result = env.rpc("ledger_request", "2")[jss::result];
208 constexpr char const* hash2 =
209 "CCC3B3E88CCAC17F1BE6B4A648A55999411F19E3FE55EB721960EB0DF28EDDA5";
210 BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "2");
211 BEAST_EXPECT(
212 result[jss::ledger][jss::total_coins] == "100000000000000000");
213 BEAST_EXPECT(result[jss::ledger][jss::closed] == true);
214 BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash2);
215 BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == hash1);
216 BEAST_EXPECT(
217 result[jss::ledger][jss::account_hash] ==
218 "3C834285F7F464FBE99AFEB84D354A968EB2CAA24523FF26797A973D906A3D29");
219 BEAST_EXPECT(result[jss::ledger][jss::transaction_hash] == zerohash);
220
221 result = env.rpc("ledger_request", "3")[jss::result];
222 constexpr char const* hash3 =
223 "8D631B20BC989AF568FBA97375290544B0703A5ADC1CF9E9053580461690C9EE";
224 BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "3");
225 BEAST_EXPECT(
226 result[jss::ledger][jss::total_coins] == "99999999999999980");
227 BEAST_EXPECT(result[jss::ledger][jss::closed] == true);
228 BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash3);
229 BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == hash2);
230 BEAST_EXPECT(
231 result[jss::ledger][jss::account_hash] ==
232 "BC9EF2A16BFF80BCFABA6FA84688D858D33BD0FA0435CAA9DF6DA4105A39A29E");
233 BEAST_EXPECT(
234 result[jss::ledger][jss::transaction_hash] ==
235 "0213EC486C058B3942FBE3DAC6839949A5C5B02B8B4244C8998EFDF04DBD8222");
236
237 result = env.rpc("ledger_request", "4")[jss::result];
238 constexpr char const* hash4 =
239 "1A8E7098B23597E73094DADA58C9D62F3AB93A12C6F7666D56CA85A6CFDE530F";
240 BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "4");
241 BEAST_EXPECT(
242 result[jss::ledger][jss::total_coins] == "99999999999999960");
243 BEAST_EXPECT(result[jss::ledger][jss::closed] == true);
244 BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash4);
245 BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == hash3);
246 BEAST_EXPECT(
247 result[jss::ledger][jss::account_hash] ==
248 "C690188F123C91355ADA8BDF4AC5B5C927076D3590C215096868A5255264C6DD");
249 BEAST_EXPECT(
250 result[jss::ledger][jss::transaction_hash] ==
251 "3CBDB8F42E04333E1642166BFB93AC9A7E1C6C067092CD5D881D6F3AB3D67E76");
252
253 result = env.rpc("ledger_request", "5")[jss::result];
254 constexpr char const* hash5 =
255 "C6A222D71AE65D7B4F240009EAD5DEB20D7EEDE5A4064F28BBDBFEEB6FBE48E5";
256 BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "5");
257 BEAST_EXPECT(
258 result[jss::ledger][jss::total_coins] == "99999999999999940");
259 BEAST_EXPECT(result[jss::ledger][jss::closed] == true);
260 BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash5);
261 BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == hash4);
262 BEAST_EXPECT(
263 result[jss::ledger][jss::account_hash] ==
264 "EA81CD9D36740736F00CB747E0D0E32D3C10B695823D961F0FB9A1CE7133DD4D");
265 BEAST_EXPECT(
266 result[jss::ledger][jss::transaction_hash] ==
267 "C3D086CD6BDB9E97AD1D513B2C049EF2840BD21D0B3E22D84EBBB89B6D2EF59D");
268
269 result = env.rpc("ledger_request", "6")[jss::result];
270 BEAST_EXPECT(result[jss::error] == "invalidParams");
271 BEAST_EXPECT(result[jss::status] == "error");
272 BEAST_EXPECT(result[jss::error_message] == "Ledger index too large");
273 }
274
275 void
277 {
278 using namespace test::jtx;
279 Env env{*this};
280 Account const gw{"gateway"};
281 auto const USD = gw["USD"];
282 env.fund(XRP(100000), gw);
283 env.close();
284
285 Json::Value jvParams;
286 jvParams[jss::ledger_hash] =
287 "AB868A6CFEEC779C2FF845C0AF00A642259986AF40C01976A7F842B6918936C7";
288 jvParams[jss::ledger_index] = "1";
289 auto result = env.rpc(
290 "json", "ledger_request", jvParams.toStyledString())[jss::result];
291 BEAST_EXPECT(result[jss::error] == "invalidParams");
292 BEAST_EXPECT(result[jss::status] == "error");
293 BEAST_EXPECT(
294 result[jss::error_message] ==
295 "Exactly one of ledger_hash and ledger_index can be set.");
296
297 // the purpose in this test is to force the ledger expiration/out of
298 // date check to trigger
299 env.timeKeeper().adjustCloseTime(weeks{3});
300 result = env.rpc(apiVersion, "ledger_request", "1")[jss::result];
301 BEAST_EXPECT(result[jss::status] == "error");
302 if (apiVersion == 1)
303 {
304 BEAST_EXPECT(result[jss::error] == "noCurrent");
305 BEAST_EXPECT(
306 result[jss::error_message] == "Current ledger is unavailable.");
307 }
308 else
309 {
310 BEAST_EXPECT(result[jss::error] == "notSynced");
311 BEAST_EXPECT(
312 result[jss::error_message] == "Not synced to the network.");
313 }
314 }
315
316 void
318 {
319 using namespace test::jtx;
320 using namespace std::chrono_literals;
321 Env env{*this, envconfig([](std::unique_ptr<Config> cfg) {
322 cfg->FEES.reference_fee = 10;
323 cfg->NODE_SIZE = 0;
324 return cfg;
325 })};
326 Account const gw{"gateway"};
327 auto const USD = gw["USD"];
328 env.fund(XRP(100000), gw);
329
330 int const max_limit = 256;
331
332 for (auto i = 0; i < max_limit + 10; i++)
333 {
334 Account const bob{std::string("bob") + std::to_string(i)};
335 env.fund(XRP(1000), bob);
336 env.close();
337 }
338
339 auto result = env.rpc("ledger_request", "1")[jss::result];
340 BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "1");
341 BEAST_EXPECT(
342 result[jss::ledger][jss::total_coins] == "100000000000000000");
343 BEAST_EXPECT(result[jss::ledger][jss::closed] == true);
344 BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash1);
345 BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == zerohash);
346 BEAST_EXPECT(result[jss::ledger][jss::account_hash] == accounthash1);
347 BEAST_EXPECT(result[jss::ledger][jss::transaction_hash] == zerohash);
348 }
349
350 void
352 {
353 using namespace test::jtx;
354 Env env{*this, envconfig(no_admin)};
355 Account const gw{"gateway"};
356 auto const USD = gw["USD"];
357 env.fund(XRP(100000), gw);
358
359 env.set_retries(0);
360 auto const result = env.rpc("ledger_request", "1")[jss::result];
361 // The current HTTP/S ServerHandler returns an HTTP 403 error code here
362 // rather than a noPermission JSON error. The JSONRPCClient just eats
363 // that error and returns an null result.
364 BEAST_EXPECT(result.type() == Json::nullValue);
365 }
366
367 void
377};
378
379BEAST_DEFINE_TESTSUITE(LedgerRequestRPC, rpc, ripple);
380
381} // namespace RPC
382} // namespace ripple
T bind_front(T... args)
Represents a JSON value.
Definition json_value.h:149
std::string toStyledString() const
A testsuite class.
Definition suite.h:55
static constexpr char const * hash1
static constexpr char const * accounthash1
static constexpr char const * zerohash
@ nullValue
'null' value
Definition json_value.h:38
bool contains_error(Json::Value const &json)
Returns true if the json contains an rpc error specification.
static constexpr std::integral_constant< unsigned, Version > apiVersion
Definition ApiVersion.h:53
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
void forAllApiVersions(Fn const &fn, Args &&... args)
Definition ApiVersion.h:101
T to_string(T... args)