rippled
Loading...
Searching...
No Matches
LedgerEntry.cpp
1#include <xrpld/rpc/Context.h>
2#include <xrpld/rpc/GRPCHandlers.h>
3#include <xrpld/rpc/detail/RPCLedgerHelpers.h>
4#include <xrpld/rpc/handlers/LedgerEntryHelpers.h>
5
6#include <xrpl/basics/StringUtilities.h>
7#include <xrpl/basics/strHex.h>
8#include <xrpl/beast/core/LexicalCast.h>
9#include <xrpl/json/json_errors.h>
10#include <xrpl/ledger/CredentialHelpers.h>
11#include <xrpl/ledger/ReadView.h>
12#include <xrpl/protocol/ErrorCodes.h>
13#include <xrpl/protocol/Indexes.h>
14#include <xrpl/protocol/LedgerFormats.h>
15#include <xrpl/protocol/RPCErr.h>
16#include <xrpl/protocol/STXChainBridge.h>
17#include <xrpl/protocol/jss.h>
18
19namespace xrpl {
20
21static Expected<uint256, Json::Value>
23 Json::Value const& params,
24 Json::StaticString const fieldName,
25 std::string const& expectedType = "hex string or object")
26{
27 if (auto const uNodeIndex = LedgerEntryHelpers::parse<uint256>(params))
28 {
29 return *uNodeIndex;
30 }
32 "malformedRequest", fieldName, expectedType);
33}
34
35static Expected<uint256, Json::Value>
36parseIndex(Json::Value const& params, Json::StaticString const fieldName)
37{
38 return parseObjectID(params, fieldName, "hex string");
39}
40
41static Expected<uint256, Json::Value>
42parseAccountRoot(Json::Value const& params, Json::StaticString const fieldName)
43{
44 if (auto const account = LedgerEntryHelpers::parse<AccountID>(params))
45 {
46 return keylet::account(*account).key;
47 }
48
50 "malformedAddress", fieldName, "AccountID");
51}
52
53static Expected<uint256, Json::Value>
54parseAmendments(Json::Value const& params, Json::StaticString const fieldName)
55{
56 return parseObjectID(params, fieldName, "hex string");
57}
58
59static Expected<uint256, Json::Value>
60parseAMM(Json::Value const& params, Json::StaticString const fieldName)
61{
62 if (!params.isObject())
63 {
64 return parseObjectID(params, fieldName);
65 }
66
67 if (auto const value =
68 LedgerEntryHelpers::hasRequired(params, {jss::asset, jss::asset2});
69 !value)
70 {
71 return Unexpected(value.error());
72 }
73
74 auto const asset = LedgerEntryHelpers::requiredIssue(
75 params, jss::asset, "malformedRequest");
76 if (!asset)
77 return Unexpected(asset.error());
78
79 auto const asset2 = LedgerEntryHelpers::requiredIssue(
80 params, jss::asset2, "malformedRequest");
81 if (!asset2)
82 return Unexpected(asset2.error());
83
84 return keylet::amm(*asset, *asset2).key;
85}
86
87static Expected<uint256, Json::Value>
88parseBridge(Json::Value const& params, Json::StaticString const fieldName)
89{
90 if (!params.isMember(jss::bridge))
91 {
93 }
94
95 if (params[jss::bridge].isString())
96 {
97 return parseObjectID(params, fieldName);
98 }
99
100 auto const bridge =
101 LedgerEntryHelpers::parseBridgeFields(params[jss::bridge]);
102 if (!bridge)
103 return Unexpected(bridge.error());
104
105 auto const account = LedgerEntryHelpers::requiredAccountID(
106 params, jss::bridge_account, "malformedBridgeAccount");
107 if (!account)
108 return Unexpected(account.error());
109
110 STXChainBridge::ChainType const chainType =
111 STXChainBridge::srcChain(account.value() == bridge->lockingChainDoor());
112 if (account.value() != bridge->door(chainType))
113 return LedgerEntryHelpers::malformedError("malformedRequest", "");
114
115 return keylet::bridge(*bridge, chainType).key;
116}
117
118static Expected<uint256, Json::Value>
119parseCheck(Json::Value const& params, Json::StaticString const fieldName)
120{
121 return parseObjectID(params, fieldName, "hex string");
122}
123
124static Expected<uint256, Json::Value>
125parseCredential(Json::Value const& cred, Json::StaticString const fieldName)
126{
127 if (!cred.isObject())
128 {
129 return parseObjectID(cred, fieldName);
130 }
131
132 auto const subject = LedgerEntryHelpers::requiredAccountID(
133 cred, jss::subject, "malformedRequest");
134 if (!subject)
135 return Unexpected(subject.error());
136
137 auto const issuer = LedgerEntryHelpers::requiredAccountID(
138 cred, jss::issuer, "malformedRequest");
139 if (!issuer)
140 return Unexpected(issuer.error());
141
142 auto const credType = LedgerEntryHelpers::requiredHexBlob(
143 cred,
144 jss::credential_type,
146 "malformedRequest");
147 if (!credType)
148 return Unexpected(credType.error());
149
150 return keylet::credential(
151 *subject, *issuer, Slice(credType->data(), credType->size()))
152 .key;
153}
154
155static Expected<uint256, Json::Value>
156parseDelegate(Json::Value const& params, Json::StaticString const fieldName)
157{
158 if (!params.isObject())
159 {
160 return parseObjectID(params, fieldName);
161 }
162
163 auto const account = LedgerEntryHelpers::requiredAccountID(
164 params, jss::account, "malformedAddress");
165 if (!account)
166 return Unexpected(account.error());
167
168 auto const authorize = LedgerEntryHelpers::requiredAccountID(
169 params, jss::authorize, "malformedAddress");
170 if (!authorize)
171 return Unexpected(authorize.error());
172
173 return keylet::delegate(*account, *authorize).key;
174}
175
176static Expected<STArray, Json::Value>
178{
179 if (!jv.isArray())
180 {
182 "malformedAuthorizedCredentials",
183 jss::authorized_credentials,
184 "array");
185 }
186
187 std::uint32_t const n = jv.size();
189 {
191 "malformedAuthorizedCredentials",
192 "Invalid field '" + std::string(jss::authorized_credentials) +
193 "', array too long."));
194 }
195
196 if (n == 0)
197 {
199 "malformedAuthorizedCredentials",
200 "Invalid field '" + std::string(jss::authorized_credentials) +
201 "', array empty."));
202 }
203
204 STArray arr(sfAuthorizeCredentials, n);
205 for (auto const& jo : jv)
206 {
207 if (!jo.isObject())
208 {
210 "malformedAuthorizedCredentials",
211 jss::authorized_credentials,
212 "array");
213 }
214
215 if (auto const value = LedgerEntryHelpers::hasRequired(
216 jo,
217 {jss::issuer, jss::credential_type},
218 "malformedAuthorizedCredentials");
219 !value)
220 {
221 return Unexpected(value.error());
222 }
223
224 auto const issuer = LedgerEntryHelpers::requiredAccountID(
225 jo, jss::issuer, "malformedAuthorizedCredentials");
226 if (!issuer)
227 return Unexpected(issuer.error());
228
229 auto const credentialType = LedgerEntryHelpers::requiredHexBlob(
230 jo,
231 jss::credential_type,
233 "malformedAuthorizedCredentials");
234 if (!credentialType)
235 return Unexpected(credentialType.error());
236
237 auto credential = STObject::makeInnerObject(sfCredential);
238 credential.setAccountID(sfIssuer, *issuer);
239 credential.setFieldVL(sfCredentialType, *credentialType);
240 arr.push_back(std::move(credential));
241 }
242
243 return arr;
244}
245
246static Expected<uint256, Json::Value>
248{
249 if (!dp.isObject())
250 {
251 return parseObjectID(dp, fieldName);
252 }
253
254 if ((dp.isMember(jss::authorized) ==
255 dp.isMember(jss::authorized_credentials)))
256 {
258 "malformedRequest",
259 "Must have exactly one of `authorized` and "
260 "`authorized_credentials`.");
261 }
262
263 auto const owner =
264 LedgerEntryHelpers::requiredAccountID(dp, jss::owner, "malformedOwner");
265 if (!owner)
266 {
267 return Unexpected(owner.error());
268 }
269
270 if (dp.isMember(jss::authorized))
271 {
272 if (auto const authorized =
273 LedgerEntryHelpers::parse<AccountID>(dp[jss::authorized]))
274 {
275 return keylet::depositPreauth(*owner, *authorized).key;
276 }
278 "malformedAuthorized", jss::authorized, "AccountID");
279 }
280
281 auto const& ac(dp[jss::authorized_credentials]);
282 auto const arr = parseAuthorizeCredentials(ac);
283 if (!arr.has_value())
284 return Unexpected(arr.error());
285
286 auto const& sorted = credentials::makeSorted(arr.value());
287 if (sorted.empty())
288 {
289 // TODO: this error message is bad/inaccurate
291 "malformedAuthorizedCredentials",
292 jss::authorized_credentials,
293 "array");
294 }
295
296 return keylet::depositPreauth(*owner, std::move(sorted)).key;
297}
298
299static Expected<uint256, Json::Value>
300parseDID(Json::Value const& params, Json::StaticString const fieldName)
301{
302 auto const account = LedgerEntryHelpers::parse<AccountID>(params);
303 if (!account)
304 {
306 "malformedAddress", fieldName, "AccountID");
307 }
308
309 return keylet::did(*account).key;
310}
311
312static Expected<uint256, Json::Value>
314 Json::Value const& params,
315 Json::StaticString const fieldName)
316{
317 if (!params.isObject())
318 {
319 return parseObjectID(params, fieldName);
320 }
321
322 if (params.isMember(jss::sub_index) &&
323 (!params[jss::sub_index].isConvertibleTo(Json::uintValue) ||
324 params[jss::sub_index].isBool()))
325 {
327 "malformedRequest", jss::sub_index, "number");
328 }
329
330 if (params.isMember(jss::owner) == params.isMember(jss::dir_root))
331 {
333 "malformedRequest",
334 "Must have exactly one of `owner` and `dir_root` fields.");
335 }
336
337 std::uint64_t uSubIndex = params.get(jss::sub_index, 0).asUInt();
338
339 if (params.isMember(jss::dir_root))
340 {
341 if (auto const uDirRoot =
342 LedgerEntryHelpers::parse<uint256>(params[jss::dir_root]))
343 {
344 return keylet::page(*uDirRoot, uSubIndex).key;
345 }
346
348 "malformedDirRoot", jss::dir_root, "hash");
349 }
350
351 if (params.isMember(jss::owner))
352 {
353 auto const ownerID =
354 LedgerEntryHelpers::parse<AccountID>(params[jss::owner]);
355 if (!ownerID)
356 {
358 "malformedAddress", jss::owner, "AccountID");
359 }
360
361 return keylet::page(keylet::ownerDir(*ownerID), uSubIndex).key;
362 }
363
364 return LedgerEntryHelpers::malformedError("malformedRequest", "");
365}
366
367static Expected<uint256, Json::Value>
368parseEscrow(Json::Value const& params, Json::StaticString const fieldName)
369{
370 if (!params.isObject())
371 {
372 return parseObjectID(params, fieldName);
373 }
374
376 params, jss::owner, "malformedOwner");
377 if (!id)
378 return Unexpected(id.error());
379 auto const seq =
380 LedgerEntryHelpers::requiredUInt32(params, jss::seq, "malformedSeq");
381 if (!seq)
382 return Unexpected(seq.error());
383
384 return keylet::escrow(*id, *seq).key;
385}
386
387static Expected<uint256, Json::Value>
388parseFeeSettings(Json::Value const& params, Json::StaticString const fieldName)
389{
390 return parseObjectID(params, fieldName, "hex string");
391}
392
393static Expected<uint256, Json::Value>
394parseLedgerHashes(Json::Value const& params, Json::StaticString const fieldName)
395{
396 return parseObjectID(params, fieldName, "hex string");
397}
398
399static Expected<uint256, Json::Value>
400parseLoanBroker(Json::Value const& params, Json::StaticString const fieldName)
401{
402 if (!params.isObject())
403 {
404 return parseObjectID(params, fieldName, "hex string");
405 }
406
408 params, jss::owner, "malformedOwner");
409 if (!id)
410 return Unexpected(id.error());
411 auto const seq =
412 LedgerEntryHelpers::requiredUInt32(params, jss::seq, "malformedSeq");
413 if (!seq)
414 return Unexpected(seq.error());
415
416 return keylet::loanbroker(*id, *seq).key;
417}
418
419static Expected<uint256, Json::Value>
420parseLoan(Json::Value const& params, Json::StaticString const fieldName)
421{
422 if (!params.isObject())
423 {
424 return parseObjectID(params, fieldName, "hex string");
425 }
426
428 params, jss::loan_broker_id, "malformedLoanBrokerID");
429 if (!id)
430 return Unexpected(id.error());
431 auto const seq = LedgerEntryHelpers::requiredUInt32(
432 params, jss::loan_seq, "malformedSeq");
433 if (!seq)
434 return Unexpected(seq.error());
435
436 return keylet::loan(*id, *seq).key;
437}
438
439static Expected<uint256, Json::Value>
440parseMPToken(Json::Value const& params, Json::StaticString const fieldName)
441{
442 if (!params.isObject())
443 {
444 return parseObjectID(params, fieldName);
445 }
446
447 auto const mptIssuanceID = LedgerEntryHelpers::requiredUInt192(
448 params, jss::mpt_issuance_id, "malformedMPTIssuanceID");
449 if (!mptIssuanceID)
450 return Unexpected(mptIssuanceID.error());
451
452 auto const account = LedgerEntryHelpers::requiredAccountID(
453 params, jss::account, "malformedAccount");
454 if (!account)
455 return Unexpected(account.error());
456
457 return keylet::mptoken(*mptIssuanceID, *account).key;
458}
459
460static Expected<uint256, Json::Value>
462 Json::Value const& params,
463 Json::StaticString const fieldName)
464{
465 auto const mptIssuanceID = LedgerEntryHelpers::parse<uint192>(params);
466 if (!mptIssuanceID)
468 "malformedMPTokenIssuance", fieldName, "Hash192");
469
470 return keylet::mptIssuance(*mptIssuanceID).key;
471}
472
473static Expected<uint256, Json::Value>
474parseNFTokenOffer(Json::Value const& params, Json::StaticString const fieldName)
475{
476 return parseObjectID(params, fieldName, "hex string");
477}
478
479static Expected<uint256, Json::Value>
480parseNFTokenPage(Json::Value const& params, Json::StaticString const fieldName)
481{
482 return parseObjectID(params, fieldName, "hex string");
483}
484
485static Expected<uint256, Json::Value>
486parseNegativeUNL(Json::Value const& params, Json::StaticString const fieldName)
487{
488 return parseObjectID(params, fieldName, "hex string");
489}
490
491static Expected<uint256, Json::Value>
492parseOffer(Json::Value const& params, Json::StaticString const fieldName)
493{
494 if (!params.isObject())
495 {
496 return parseObjectID(params, fieldName);
497 }
498
500 params, jss::account, "malformedAddress");
501 if (!id)
502 return Unexpected(id.error());
503
504 auto const seq = LedgerEntryHelpers::requiredUInt32(
505 params, jss::seq, "malformedRequest");
506 if (!seq)
507 return Unexpected(seq.error());
508
509 return keylet::offer(*id, *seq).key;
510}
511
512static Expected<uint256, Json::Value>
513parseOracle(Json::Value const& params, Json::StaticString const fieldName)
514{
515 if (!params.isObject())
516 {
517 return parseObjectID(params, fieldName);
518 }
519
521 params, jss::account, "malformedAccount");
522 if (!id)
523 return Unexpected(id.error());
524
525 auto const seq = LedgerEntryHelpers::requiredUInt32(
526 params, jss::oracle_document_id, "malformedDocumentID");
527 if (!seq)
528 return Unexpected(seq.error());
529
530 return keylet::oracle(*id, *seq).key;
531}
532
533static Expected<uint256, Json::Value>
534parsePayChannel(Json::Value const& params, Json::StaticString const fieldName)
535{
536 return parseObjectID(params, fieldName, "hex string");
537}
538
539static Expected<uint256, Json::Value>
541 Json::Value const& pd,
542 Json::StaticString const fieldName)
543{
544 if (pd.isString())
545 {
546 return parseObjectID(pd, fieldName);
547 }
548
549 if (!pd.isObject())
550 {
552 "malformedRequest", fieldName, "hex string or object");
553 }
554
555 auto const account = LedgerEntryHelpers::requiredAccountID(
556 pd, jss::account, "malformedAddress");
557 if (!account)
558 return Unexpected(account.error());
559
560 auto const seq =
561 LedgerEntryHelpers::requiredUInt32(pd, jss::seq, "malformedRequest");
562 if (!seq)
563 return Unexpected(seq.error());
564
565 return keylet::permissionedDomain(*account, pd[jss::seq].asUInt()).key;
566}
567
568static Expected<uint256, Json::Value>
570 Json::Value const& jvRippleState,
571 Json::StaticString const fieldName)
572{
573 Currency uCurrency;
574
575 if (!jvRippleState.isObject())
576 {
577 return parseObjectID(jvRippleState, fieldName);
578 }
579
580 if (auto const value = LedgerEntryHelpers::hasRequired(
581 jvRippleState, {jss::currency, jss::accounts});
582 !value)
583 {
584 return Unexpected(value.error());
585 }
586
587 if (!jvRippleState[jss::accounts].isArray() ||
588 jvRippleState[jss::accounts].size() != 2)
589 {
591 "malformedRequest", jss::accounts, "length-2 array of Accounts");
592 }
593
594 auto const id1 =
595 LedgerEntryHelpers::parse<AccountID>(jvRippleState[jss::accounts][0u]);
596 auto const id2 =
597 LedgerEntryHelpers::parse<AccountID>(jvRippleState[jss::accounts][1u]);
598 if (!id1 || !id2)
599 {
601 "malformedAddress", jss::accounts, "array of Accounts");
602 }
603 if (id1 == id2)
604 {
606 "malformedRequest", "Cannot have a trustline to self.");
607 }
608
609 if (!jvRippleState[jss::currency].isString() ||
610 jvRippleState[jss::currency] == "" ||
611 !to_currency(uCurrency, jvRippleState[jss::currency].asString()))
612 {
614 "malformedCurrency", jss::currency, "Currency");
615 }
616
617 return keylet::line(*id1, *id2, uCurrency).key;
618}
619
620static Expected<uint256, Json::Value>
621parseSignerList(Json::Value const& params, Json::StaticString const fieldName)
622{
623 return parseObjectID(params, fieldName, "hex string");
624}
625
626static Expected<uint256, Json::Value>
627parseTicket(Json::Value const& params, Json::StaticString const fieldName)
628{
629 if (!params.isObject())
630 {
631 return parseObjectID(params, fieldName);
632 }
633
635 params, jss::account, "malformedAddress");
636 if (!id)
637 return Unexpected(id.error());
638
639 auto const seq = LedgerEntryHelpers::requiredUInt32(
640 params, jss::ticket_seq, "malformedRequest");
641 if (!seq)
642 return Unexpected(seq.error());
643
644 return getTicketIndex(*id, *seq);
645}
646
647static Expected<uint256, Json::Value>
648parseVault(Json::Value const& params, Json::StaticString const fieldName)
649{
650 if (!params.isObject())
651 {
652 return parseObjectID(params, fieldName);
653 }
654
656 params, jss::owner, "malformedOwner");
657 if (!id)
658 return Unexpected(id.error());
659
660 auto const seq = LedgerEntryHelpers::requiredUInt32(
661 params, jss::seq, "malformedRequest");
662 if (!seq)
663 return Unexpected(seq.error());
664
665 return keylet::vault(*id, *seq).key;
666}
667
668static Expected<uint256, Json::Value>
670 Json::Value const& claim_id,
671 Json::StaticString const fieldName)
672{
673 if (!claim_id.isObject())
674 {
675 return parseObjectID(claim_id, fieldName);
676 }
677
678 auto const bridge_spec = LedgerEntryHelpers::parseBridgeFields(claim_id);
679 if (!bridge_spec)
680 return Unexpected(bridge_spec.error());
681
682 auto const seq = LedgerEntryHelpers::requiredUInt32(
683 claim_id, jss::xchain_owned_claim_id, "malformedXChainOwnedClaimID");
684 if (!seq)
685 {
686 return Unexpected(seq.error());
687 }
688
689 Keylet keylet = keylet::xChainClaimID(*bridge_spec, *seq);
690 return keylet.key;
691}
692
693static Expected<uint256, Json::Value>
695 Json::Value const& claim_id,
696 Json::StaticString const fieldName)
697{
698 if (!claim_id.isObject())
699 {
700 return parseObjectID(claim_id, fieldName);
701 }
702
703 auto const bridge_spec = LedgerEntryHelpers::parseBridgeFields(claim_id);
704 if (!bridge_spec)
705 return Unexpected(bridge_spec.error());
706
707 auto const seq = LedgerEntryHelpers::requiredUInt32(
708 claim_id,
709 jss::xchain_owned_create_account_claim_id,
710 "malformedXChainOwnedCreateAccountClaimID");
711 if (!seq)
712 {
713 return Unexpected(seq.error());
714 }
715
716 Keylet keylet = keylet::xChainCreateAccountClaimID(*bridge_spec, *seq);
717 return keylet.key;
718}
719
721 Json::Value const&,
722 Json::StaticString const);
723
730
731// {
732// ledger_hash : <ledger>
733// ledger_index : <ledger_index>
734// ...
735// }
738{
739 static auto ledgerEntryParsers = std::to_array<LedgerEntry>({
740#pragma push_macro("LEDGER_ENTRY")
741#undef LEDGER_ENTRY
742
743#define LEDGER_ENTRY(tag, value, name, rpcName, fields) \
744 {jss::rpcName, parse##name, tag},
745
746#include <xrpl/protocol/detail/ledger_entries.macro>
747
748#undef LEDGER_ENTRY
749#pragma pop_macro("LEDGER_ENTRY")
750 {jss::index, parseIndex, ltANY},
751 // aliases
752 {jss::account_root, parseAccountRoot, ltACCOUNT_ROOT},
753 {jss::ripple_state, parseRippleState, ltRIPPLE_STATE},
754 });
755
756 auto hasMoreThanOneMember = [&]() {
757 int count = 0;
758
759 for (auto const& ledgerEntry : ledgerEntryParsers)
760 {
761 if (context.params.isMember(ledgerEntry.fieldName))
762 {
763 count++;
764 if (count > 1) // Early exit if more than one is found
765 return true;
766 }
767 }
768 return false; // Return false if <= 1 is found
769 }();
770
771 if (hasMoreThanOneMember)
772 {
773 return RPC::make_param_error("Too many fields provided.");
774 }
775
777 auto jvResult = RPC::lookupLedger(lpLedger, context);
778
779 if (!lpLedger)
780 return jvResult;
781
782 uint256 uNodeIndex;
783 LedgerEntryType expectedType = ltANY;
784
785 try
786 {
787 bool found = false;
788 for (auto const& ledgerEntry : ledgerEntryParsers)
789 {
790 if (context.params.isMember(ledgerEntry.fieldName))
791 {
792 expectedType = ledgerEntry.expectedType;
793 // `Bridge` is the only type that involves two fields at the
794 // `ledger_entry` param level.
795 // So that parser needs to have the whole `params` field.
796 // All other parsers only need the one field name's info.
797 Json::Value const& params = ledgerEntry.fieldName == jss::bridge
798 ? context.params
799 : context.params[ledgerEntry.fieldName];
800 auto const result =
801 ledgerEntry.parseFunction(params, ledgerEntry.fieldName);
802 if (!result)
803 return result.error();
804
805 uNodeIndex = result.value();
806 found = true;
807 break;
808 }
809 }
810 if (!found)
811 {
812 if (context.apiVersion < 2u)
813 {
814 jvResult[jss::error] = "unknownOption";
815 return jvResult;
816 }
817 return RPC::make_param_error("No ledger_entry params provided.");
818 }
819 }
820 catch (Json::error& e)
821 {
822 if (context.apiVersion > 1u)
823 {
824 // For apiVersion 2 onwards, any parsing failures that throw
825 // this exception return an invalidParam error.
827 }
828 else
829 throw;
830 }
831
832 if (uNodeIndex.isZero())
833 {
835 }
836
837 auto const sleNode = lpLedger->read(keylet::unchecked(uNodeIndex));
838
839 bool bNodeBinary = false;
840 if (context.params.isMember(jss::binary))
841 bNodeBinary = context.params[jss::binary].asBool();
842
843 if (!sleNode)
844 {
845 // Not found.
847 }
848
849 if ((expectedType != ltANY) && (expectedType != sleNode->getType()))
850 {
852 }
853
854 if (bNodeBinary)
855 {
856 Serializer s;
857
858 sleNode->add(s);
859
860 jvResult[jss::node_binary] = strHex(s.peekData());
861 jvResult[jss::index] = to_string(uNodeIndex);
862 }
863 else
864 {
865 jvResult[jss::node] = sleNode->getJson(JsonOptions::none);
866 jvResult[jss::index] = to_string(uNodeIndex);
867 }
868
869 return jvResult;
870}
871
875{
876 org::xrpl::rpc::v1::GetLedgerEntryRequest& request = context.params;
877 org::xrpl::rpc::v1::GetLedgerEntryResponse response;
878 grpc::Status status = grpc::Status::OK;
879
881 if (auto status = RPC::ledgerFromRequest(ledger, context))
882 {
883 grpc::Status errorStatus;
884 if (status.toErrorCode() == rpcINVALID_PARAMS)
885 {
886 errorStatus = grpc::Status(
887 grpc::StatusCode::INVALID_ARGUMENT, status.message());
888 }
889 else
890 {
891 errorStatus =
892 grpc::Status(grpc::StatusCode::NOT_FOUND, status.message());
893 }
894 return {response, errorStatus};
895 }
896
897 auto const key = uint256::fromVoidChecked(request.key());
898 if (!key)
899 {
900 grpc::Status errorStatus{
901 grpc::StatusCode::INVALID_ARGUMENT, "index malformed"};
902 return {response, errorStatus};
903 }
904
905 auto const sleNode = ledger->read(keylet::unchecked(*key));
906 if (!sleNode)
907 {
908 grpc::Status errorStatus{
909 grpc::StatusCode::NOT_FOUND, "object not found"};
910 return {response, errorStatus};
911 }
912
913 Serializer s;
914 sleNode->add(s);
915
916 auto& stateObject = *response.mutable_ledger_object();
917 stateObject.set_data(s.peekData().data(), s.getLength());
918 stateObject.set_key(request.key());
919 *(response.mutable_ledger()) = request.ledger();
920 return {response, status};
921}
922} // namespace xrpl
Lightweight wrapper to tag static string.
Definition json_value.h:45
Represents a JSON value.
Definition json_value.h:131
bool isArray() const
UInt size() const
Number of values in array or object.
bool isString() const
UInt asUInt() const
bool isObject() const
bool isBool() const
bool asBool() const
bool isMember(char const *key) const
Return true if the object has a member named key.
Value get(UInt index, Value const &defaultValue) const
If the array contains at least index+1 elements, returns the element value, otherwise returns default...
bool isConvertibleTo(ValueType other) const
void push_back(STObject const &object)
Definition STArray.h:193
static STObject makeInnerObject(SField const &name)
Definition STObject.cpp:76
static ChainType srcChain(bool wasLockingChainSend)
Blob const & peekData() const
Definition Serializer.h:183
int getLength() const
Definition Serializer.h:214
An immutable linear range of bytes.
Definition Slice.h:27
static std::optional< base_uint > fromVoidChecked(T const &from)
Definition base_uint.h:307
bool isZero() const
Definition base_uint.h:521
T data(T... args)
T is_same_v
@ uintValue
unsigned integer value
Definition json_value.h:22
Expected< std::uint32_t, Json::Value > requiredUInt32(Json::Value const &params, Json::StaticString const fieldName, std::string const &err)
Expected< AccountID, Json::Value > requiredAccountID(Json::Value const &params, Json::StaticString const fieldName, std::string const &err)
Unexpected< Json::Value > missingFieldError(Json::StaticString const field, std::optional< std::string > err=std::nullopt)
Expected< uint192, Json::Value > requiredUInt192(Json::Value const &params, Json::StaticString const fieldName, std::string const &err)
Expected< bool, Json::Value > hasRequired(Json::Value const &params, std::initializer_list< Json::StaticString > fields, std::optional< std::string > err=std::nullopt)
Expected< Blob, Json::Value > requiredHexBlob(Json::Value const &params, Json::StaticString const fieldName, std::size_t maxLength, std::string const &err)
Expected< Issue, Json::Value > requiredIssue(Json::Value const &params, Json::StaticString const fieldName, std::string const &err)
Expected< STXChainBridge, Json::Value > parseBridgeFields(Json::Value const &params)
Unexpected< Json::Value > malformedError(std::string const &err, std::string const &message)
Expected< uint256, Json::Value > requiredUInt256(Json::Value const &params, Json::StaticString const fieldName, std::string const &err)
Unexpected< Json::Value > invalidFieldError(std::string const &err, Json::StaticString const field, std::string const &type)
Json::Value make_param_error(std::string const &message)
Returns a new json object that indicates invalid parameters.
Definition ErrorCodes.h:230
Status ledgerFromRequest(T &ledger, GRPCContext< R > const &context)
Retrieves a ledger from a gRPC request context.
Status lookupLedger(std::shared_ptr< ReadView const > &ledger, JsonContext const &context, Json::Value &result)
Looks up a ledger from a request and fills a Json::Value with ledger data.
Json::Value make_error(error_code_i code)
Returns a new json object that reflects the error code.
std::set< std::pair< AccountID, Slice > > makeSorted(STArray const &credentials)
Keylet oracle(AccountID const &account, std::uint32_t const &documentID) noexcept
Definition Indexes.cpp:502
Keylet did(AccountID const &account) noexcept
Definition Indexes.cpp:496
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Definition Indexes.cpp:350
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Definition Indexes.cpp:324
Keylet loanbroker(AccountID const &owner, std::uint32_t seq) noexcept
Definition Indexes.cpp:552
Keylet escrow(AccountID const &src, std::uint32_t seq) noexcept
An escrow entry.
Definition Indexes.cpp:371
Keylet bridge(STXChainBridge const &bridge, STXChainBridge::ChainType chainType)
Definition Indexes.cpp:455
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:356
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:508
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Definition Indexes.cpp:428
Keylet loan(uint256 const &loanBrokerID, std::uint32_t loanSeq) noexcept
Definition Indexes.cpp:558
Keylet offer(AccountID const &id, std::uint32_t seq) noexcept
An offer from an account.
Definition Indexes.cpp:256
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Definition Indexes.cpp:546
Keylet line(AccountID const &id0, AccountID const &id1, Currency const &currency) noexcept
The index of a trust line for a given currency.
Definition Indexes.cpp:226
Keylet xChainCreateAccountClaimID(STXChainBridge const &bridge, std::uint64_t seq)
Definition Indexes.cpp:482
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Definition Indexes.cpp:522
Keylet delegate(AccountID const &account, AccountID const &authorizedAccount) noexcept
A keylet for Delegate object.
Definition Indexes.cpp:447
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:166
Keylet permissionedDomain(AccountID const &account, std::uint32_t seq) noexcept
Definition Indexes.cpp:564
Keylet page(uint256 const &root, std::uint64_t index=0) noexcept
A page in a directory.
Definition Indexes.cpp:362
Keylet credential(AccountID const &subject, AccountID const &issuer, Slice const &credType) noexcept
Definition Indexes.cpp:535
Keylet xChainClaimID(STXChainBridge const &bridge, std::uint64_t seq)
Definition Indexes.cpp:468
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
static Expected< uint256, Json::Value > parseRippleState(Json::Value const &jvRippleState, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseDirectoryNode(Json::Value const &params, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseXChainOwnedCreateAccountClaimID(Json::Value const &claim_id, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseSignerList(Json::Value const &params, Json::StaticString const fieldName)
Expected< uint256, Json::Value >(*)(Json::Value const &, Json::StaticString const) FunctionType
static Expected< uint256, Json::Value > parseDelegate(Json::Value const &params, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseAmendments(Json::Value const &params, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseMPToken(Json::Value const &params, Json::StaticString const fieldName)
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
std::string strHex(FwdIt begin, FwdIt end)
Definition strHex.h:11
static Expected< uint256, Json::Value > parseXChainOwnedClaimID(Json::Value const &claim_id, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseAccountRoot(Json::Value const &params, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseLedgerHashes(Json::Value const &params, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseEscrow(Json::Value const &params, Json::StaticString const fieldName)
uint256 getTicketIndex(AccountID const &account, std::uint32_t uSequence)
Definition Indexes.cpp:138
static Expected< uint256, Json::Value > parseLoanBroker(Json::Value const &params, Json::StaticString const fieldName)
static bool authorized(Port const &port, std::map< std::string, std::string > const &h)
static Expected< uint256, Json::Value > parseFeeSettings(Json::Value const &params, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parsePayChannel(Json::Value const &params, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseIndex(Json::Value const &params, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseLoan(Json::Value const &params, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseMPTokenIssuance(Json::Value const &params, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseNegativeUNL(Json::Value const &params, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseBridge(Json::Value const &params, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseNFTokenPage(Json::Value const &params, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseOffer(Json::Value const &params, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseVault(Json::Value const &params, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseCheck(Json::Value const &params, Json::StaticString const fieldName)
std::size_t constexpr maxCredentialsArraySize
The maximum number of credentials can be passed in array.
Definition Protocol.h:225
std::pair< org::xrpl::rpc::v1::GetLedgerEntryResponse, grpc::Status > doLedgerEntryGrpc(RPC::GRPCContext< org::xrpl::rpc::v1::GetLedgerEntryRequest > &context)
static Expected< uint256, Json::Value > parseObjectID(Json::Value const &params, Json::StaticString const fieldName, std::string const &expectedType="hex string or object")
static Expected< uint256, Json::Value > parseCredential(Json::Value const &cred, Json::StaticString const fieldName)
static Expected< STArray, Json::Value > parseAuthorizeCredentials(Json::Value const &jv)
static Expected< uint256, Json::Value > parseDID(Json::Value const &params, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parsePermissionedDomain(Json::Value const &pd, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseDepositPreauth(Json::Value const &dp, Json::StaticString const fieldName)
static Expected< uint256, Json::Value > parseOracle(Json::Value const &params, Json::StaticString const fieldName)
LedgerEntryType
Identifiers for on-ledger objects.
@ ltANY
A special type, matching any ledger entry type.
static Expected< uint256, Json::Value > parseAMM(Json::Value const &params, Json::StaticString const fieldName)
bool to_currency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.
Definition UintTypes.cpp:65
static Expected< uint256, Json::Value > parseTicket(Json::Value const &params, Json::StaticString const fieldName)
@ rpcUNEXPECTED_LEDGER_TYPE
Definition ErrorCodes.h:143
@ rpcENTRY_NOT_FOUND
Definition ErrorCodes.h:142
@ rpcINVALID_PARAMS
Definition ErrorCodes.h:65
static Expected< uint256, Json::Value > parseNFTokenOffer(Json::Value const &params, Json::StaticString const fieldName)
std::size_t constexpr maxCredentialTypeLength
The maximum length of a CredentialType inside a Credential.
Definition Protocol.h:222
Json::Value doLedgerEntry(RPC::JsonContext &)
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:20
uint256 key
Definition Keylet.h:21
Json::StaticString fieldName
FunctionType parseFunction
LedgerEntryType expectedType
unsigned int apiVersion
Definition Context.h:30
RequestType params
Definition Context.h:52
Json::Value params
Definition Context.h:44