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>
399parseMPToken(Json::Value const& params, Json::StaticString const fieldName)
400{
401 if (!params.isObject())
402 {
403 return parseObjectID(params, fieldName);
404 }
405
406 auto const mptIssuanceID = LedgerEntryHelpers::requiredUInt192(
407 params, jss::mpt_issuance_id, "malformedMPTIssuanceID");
408 if (!mptIssuanceID)
409 return Unexpected(mptIssuanceID.error());
410
411 auto const account = LedgerEntryHelpers::requiredAccountID(
412 params, jss::account, "malformedAccount");
413 if (!account)
414 return Unexpected(account.error());
415
416 return keylet::mptoken(*mptIssuanceID, *account).key;
417}
418
419static Expected<uint256, Json::Value>
421 Json::Value const& params,
422 Json::StaticString const fieldName)
423{
424 auto const mptIssuanceID = LedgerEntryHelpers::parse<uint192>(params);
425 if (!mptIssuanceID)
427 "malformedMPTokenIssuance", fieldName, "Hash192");
428
429 return keylet::mptIssuance(*mptIssuanceID).key;
430}
431
432static Expected<uint256, Json::Value>
433parseNFTokenOffer(Json::Value const& params, Json::StaticString const fieldName)
434{
435 return parseObjectID(params, fieldName, "hex string");
436}
437
438static Expected<uint256, Json::Value>
439parseNFTokenPage(Json::Value const& params, Json::StaticString const fieldName)
440{
441 return parseObjectID(params, fieldName, "hex string");
442}
443
444static Expected<uint256, Json::Value>
445parseNegativeUNL(Json::Value const& params, Json::StaticString const fieldName)
446{
447 return parseObjectID(params, fieldName, "hex string");
448}
449
450static Expected<uint256, Json::Value>
451parseOffer(Json::Value const& params, Json::StaticString const fieldName)
452{
453 if (!params.isObject())
454 {
455 return parseObjectID(params, fieldName);
456 }
457
459 params, jss::account, "malformedAddress");
460 if (!id)
461 return Unexpected(id.error());
462
463 auto const seq = LedgerEntryHelpers::requiredUInt32(
464 params, jss::seq, "malformedRequest");
465 if (!seq)
466 return Unexpected(seq.error());
467
468 return keylet::offer(*id, *seq).key;
469}
470
471static Expected<uint256, Json::Value>
472parseOracle(Json::Value const& params, Json::StaticString const fieldName)
473{
474 if (!params.isObject())
475 {
476 return parseObjectID(params, fieldName);
477 }
478
480 params, jss::account, "malformedAccount");
481 if (!id)
482 return Unexpected(id.error());
483
484 auto const seq = LedgerEntryHelpers::requiredUInt32(
485 params, jss::oracle_document_id, "malformedDocumentID");
486 if (!seq)
487 return Unexpected(seq.error());
488
489 return keylet::oracle(*id, *seq).key;
490}
491
492static Expected<uint256, Json::Value>
493parsePayChannel(Json::Value const& params, Json::StaticString const fieldName)
494{
495 return parseObjectID(params, fieldName, "hex string");
496}
497
498static Expected<uint256, Json::Value>
500 Json::Value const& pd,
501 Json::StaticString const fieldName)
502{
503 if (pd.isString())
504 {
505 return parseObjectID(pd, fieldName);
506 }
507
508 if (!pd.isObject())
509 {
511 "malformedRequest", fieldName, "hex string or object");
512 }
513
514 auto const account = LedgerEntryHelpers::requiredAccountID(
515 pd, jss::account, "malformedAddress");
516 if (!account)
517 return Unexpected(account.error());
518
519 auto const seq =
520 LedgerEntryHelpers::requiredUInt32(pd, jss::seq, "malformedRequest");
521 if (!seq)
522 return Unexpected(seq.error());
523
524 return keylet::permissionedDomain(*account, pd[jss::seq].asUInt()).key;
525}
526
527static Expected<uint256, Json::Value>
529 Json::Value const& jvRippleState,
530 Json::StaticString const fieldName)
531{
532 Currency uCurrency;
533
534 if (!jvRippleState.isObject())
535 {
536 return parseObjectID(jvRippleState, fieldName);
537 }
538
539 if (auto const value = LedgerEntryHelpers::hasRequired(
540 jvRippleState, {jss::currency, jss::accounts});
541 !value)
542 {
543 return Unexpected(value.error());
544 }
545
546 if (!jvRippleState[jss::accounts].isArray() ||
547 jvRippleState[jss::accounts].size() != 2)
548 {
550 "malformedRequest", jss::accounts, "length-2 array of Accounts");
551 }
552
553 auto const id1 =
554 LedgerEntryHelpers::parse<AccountID>(jvRippleState[jss::accounts][0u]);
555 auto const id2 =
556 LedgerEntryHelpers::parse<AccountID>(jvRippleState[jss::accounts][1u]);
557 if (!id1 || !id2)
558 {
560 "malformedAddress", jss::accounts, "array of Accounts");
561 }
562 if (id1 == id2)
563 {
565 "malformedRequest", "Cannot have a trustline to self.");
566 }
567
568 if (!jvRippleState[jss::currency].isString() ||
569 jvRippleState[jss::currency] == "" ||
570 !to_currency(uCurrency, jvRippleState[jss::currency].asString()))
571 {
573 "malformedCurrency", jss::currency, "Currency");
574 }
575
576 return keylet::line(*id1, *id2, uCurrency).key;
577}
578
579static Expected<uint256, Json::Value>
580parseSignerList(Json::Value const& params, Json::StaticString const fieldName)
581{
582 return parseObjectID(params, fieldName, "hex string");
583}
584
585static Expected<uint256, Json::Value>
586parseTicket(Json::Value const& params, Json::StaticString const fieldName)
587{
588 if (!params.isObject())
589 {
590 return parseObjectID(params, fieldName);
591 }
592
594 params, jss::account, "malformedAddress");
595 if (!id)
596 return Unexpected(id.error());
597
598 auto const seq = LedgerEntryHelpers::requiredUInt32(
599 params, jss::ticket_seq, "malformedRequest");
600 if (!seq)
601 return Unexpected(seq.error());
602
603 return getTicketIndex(*id, *seq);
604}
605
606static Expected<uint256, Json::Value>
607parseVault(Json::Value const& params, Json::StaticString const fieldName)
608{
609 if (!params.isObject())
610 {
611 return parseObjectID(params, fieldName);
612 }
613
615 params, jss::owner, "malformedOwner");
616 if (!id)
617 return Unexpected(id.error());
618
619 auto const seq = LedgerEntryHelpers::requiredUInt32(
620 params, jss::seq, "malformedRequest");
621 if (!seq)
622 return Unexpected(seq.error());
623
624 return keylet::vault(*id, *seq).key;
625}
626
627static Expected<uint256, Json::Value>
629 Json::Value const& claim_id,
630 Json::StaticString const fieldName)
631{
632 if (!claim_id.isObject())
633 {
634 return parseObjectID(claim_id, fieldName);
635 }
636
637 auto const bridge_spec = LedgerEntryHelpers::parseBridgeFields(claim_id);
638 if (!bridge_spec)
639 return Unexpected(bridge_spec.error());
640
641 auto const seq = LedgerEntryHelpers::requiredUInt32(
642 claim_id, jss::xchain_owned_claim_id, "malformedXChainOwnedClaimID");
643 if (!seq)
644 {
645 return Unexpected(seq.error());
646 }
647
648 Keylet keylet = keylet::xChainClaimID(*bridge_spec, *seq);
649 return keylet.key;
650}
651
652static Expected<uint256, Json::Value>
654 Json::Value const& claim_id,
655 Json::StaticString const fieldName)
656{
657 if (!claim_id.isObject())
658 {
659 return parseObjectID(claim_id, fieldName);
660 }
661
662 auto const bridge_spec = LedgerEntryHelpers::parseBridgeFields(claim_id);
663 if (!bridge_spec)
664 return Unexpected(bridge_spec.error());
665
666 auto const seq = LedgerEntryHelpers::requiredUInt32(
667 claim_id,
668 jss::xchain_owned_create_account_claim_id,
669 "malformedXChainOwnedCreateAccountClaimID");
670 if (!seq)
671 {
672 return Unexpected(seq.error());
673 }
674
675 Keylet keylet = keylet::xChainCreateAccountClaimID(*bridge_spec, *seq);
676 return keylet.key;
677}
678
680 Json::Value const&,
681 Json::StaticString const);
682
689
690// {
691// ledger_hash : <ledger>
692// ledger_index : <ledger_index>
693// ...
694// }
697{
698 static auto ledgerEntryParsers = std::to_array<LedgerEntry>({
699#pragma push_macro("LEDGER_ENTRY")
700#undef LEDGER_ENTRY
701
702#define LEDGER_ENTRY(tag, value, name, rpcName, fields) \
703 {jss::rpcName, parse##name, tag},
704
705#include <xrpl/protocol/detail/ledger_entries.macro>
706
707#undef LEDGER_ENTRY
708#pragma pop_macro("LEDGER_ENTRY")
709 {jss::index, parseIndex, ltANY},
710 // aliases
711 {jss::account_root, parseAccountRoot, ltACCOUNT_ROOT},
712 {jss::ripple_state, parseRippleState, ltRIPPLE_STATE},
713 });
714
715 auto hasMoreThanOneMember = [&]() {
716 int count = 0;
717
718 for (auto const& ledgerEntry : ledgerEntryParsers)
719 {
720 if (context.params.isMember(ledgerEntry.fieldName))
721 {
722 count++;
723 if (count > 1) // Early exit if more than one is found
724 return true;
725 }
726 }
727 return false; // Return false if <= 1 is found
728 }();
729
730 if (hasMoreThanOneMember)
731 {
732 return RPC::make_param_error("Too many fields provided.");
733 }
734
736 auto jvResult = RPC::lookupLedger(lpLedger, context);
737
738 if (!lpLedger)
739 return jvResult;
740
741 uint256 uNodeIndex;
742 LedgerEntryType expectedType = ltANY;
743
744 try
745 {
746 bool found = false;
747 for (auto const& ledgerEntry : ledgerEntryParsers)
748 {
749 if (context.params.isMember(ledgerEntry.fieldName))
750 {
751 expectedType = ledgerEntry.expectedType;
752 // `Bridge` is the only type that involves two fields at the
753 // `ledger_entry` param level.
754 // So that parser needs to have the whole `params` field.
755 // All other parsers only need the one field name's info.
756 Json::Value const& params = ledgerEntry.fieldName == jss::bridge
757 ? context.params
758 : context.params[ledgerEntry.fieldName];
759 auto const result =
760 ledgerEntry.parseFunction(params, ledgerEntry.fieldName);
761 if (!result)
762 return result.error();
763
764 uNodeIndex = result.value();
765 found = true;
766 break;
767 }
768 }
769 if (!found)
770 {
771 if (context.apiVersion < 2u)
772 {
773 jvResult[jss::error] = "unknownOption";
774 return jvResult;
775 }
776 return RPC::make_param_error("No ledger_entry params provided.");
777 }
778 }
779 catch (Json::error& e)
780 {
781 if (context.apiVersion > 1u)
782 {
783 // For apiVersion 2 onwards, any parsing failures that throw
784 // this exception return an invalidParam error.
786 }
787 else
788 throw;
789 }
790
791 if (uNodeIndex.isZero())
792 {
794 }
795
796 auto const sleNode = lpLedger->read(keylet::unchecked(uNodeIndex));
797
798 bool bNodeBinary = false;
799 if (context.params.isMember(jss::binary))
800 bNodeBinary = context.params[jss::binary].asBool();
801
802 if (!sleNode)
803 {
804 // Not found.
806 }
807
808 if ((expectedType != ltANY) && (expectedType != sleNode->getType()))
809 {
811 }
812
813 if (bNodeBinary)
814 {
815 Serializer s;
816
817 sleNode->add(s);
818
819 jvResult[jss::node_binary] = strHex(s.peekData());
820 jvResult[jss::index] = to_string(uNodeIndex);
821 }
822 else
823 {
824 jvResult[jss::node] = sleNode->getJson(JsonOptions::none);
825 jvResult[jss::index] = to_string(uNodeIndex);
826 }
827
828 return jvResult;
829}
830
834{
835 org::xrpl::rpc::v1::GetLedgerEntryRequest& request = context.params;
836 org::xrpl::rpc::v1::GetLedgerEntryResponse response;
837 grpc::Status status = grpc::Status::OK;
838
840 if (auto status = RPC::ledgerFromRequest(ledger, context))
841 {
842 grpc::Status errorStatus;
843 if (status.toErrorCode() == rpcINVALID_PARAMS)
844 {
845 errorStatus = grpc::Status(
846 grpc::StatusCode::INVALID_ARGUMENT, status.message());
847 }
848 else
849 {
850 errorStatus =
851 grpc::Status(grpc::StatusCode::NOT_FOUND, status.message());
852 }
853 return {response, errorStatus};
854 }
855
856 auto const key = uint256::fromVoidChecked(request.key());
857 if (!key)
858 {
859 grpc::Status errorStatus{
860 grpc::StatusCode::INVALID_ARGUMENT, "index malformed"};
861 return {response, errorStatus};
862 }
863
864 auto const sleNode = ledger->read(keylet::unchecked(*key));
865 if (!sleNode)
866 {
867 grpc::Status errorStatus{
868 grpc::StatusCode::NOT_FOUND, "object not found"};
869 return {response, errorStatus};
870 }
871
872 Serializer s;
873 sleNode->add(s);
874
875 auto& stateObject = *response.mutable_ledger_object();
876 stateObject.set_data(s.peekData().data(), s.getLength());
877 stateObject.set_key(request.key());
878 *(response.mutable_ledger()) = request.ledger();
879 return {response, status};
880}
881} // 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)
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:521
Keylet oracle(AccountID const &account, std::uint32_t const &documentID) noexcept
Definition Indexes.cpp:501
Keylet delegate(AccountID const &account, AccountID const &authorizedAccount) noexcept
A keylet for Delegate object.
Definition Indexes.cpp:446
Keylet permissionedDomain(AccountID const &account, std::uint32_t seq) noexcept
Definition Indexes.cpp:551
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Definition Indexes.cpp:427
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:225
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:507
Keylet xChainClaimID(STXChainBridge const &bridge, std::uint64_t seq)
Definition Indexes.cpp:467
Keylet did(AccountID const &account) noexcept
Definition Indexes.cpp:495
Keylet credential(AccountID const &subject, AccountID const &issuer, Slice const &credType) noexcept
Definition Indexes.cpp:534
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Definition Indexes.cpp:545
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:165
Keylet page(uint256 const &root, std::uint64_t index=0) noexcept
A page in a directory.
Definition Indexes.cpp:361
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Definition Indexes.cpp:349
Keylet escrow(AccountID const &src, std::uint32_t seq) noexcept
An escrow entry.
Definition Indexes.cpp:370
Keylet bridge(STXChainBridge const &bridge, STXChainBridge::ChainType chainType)
Definition Indexes.cpp:454
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:355
Keylet xChainCreateAccountClaimID(STXChainBridge const &bridge, std::uint64_t seq)
Definition Indexes.cpp:481
Keylet offer(AccountID const &id, std::uint32_t seq) noexcept
An offer from an account.
Definition Indexes.cpp:255
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Definition Indexes.cpp:323
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:90
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:87
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:137
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 > 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