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