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