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