rippled
Loading...
Searching...
No Matches
LedgerEntry.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012-2014 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpld/rpc/Context.h>
21#include <xrpld/rpc/GRPCHandlers.h>
22#include <xrpld/rpc/detail/RPCHelpers.h>
23#include <xrpld/rpc/handlers/LedgerEntryHelpers.h>
24
25#include <xrpl/basics/StringUtilities.h>
26#include <xrpl/basics/strHex.h>
27#include <xrpl/beast/core/LexicalCast.h>
28#include <xrpl/json/json_errors.h>
29#include <xrpl/ledger/CredentialHelpers.h>
30#include <xrpl/ledger/ReadView.h>
31#include <xrpl/protocol/ErrorCodes.h>
32#include <xrpl/protocol/Indexes.h>
33#include <xrpl/protocol/LedgerFormats.h>
34#include <xrpl/protocol/RPCErr.h>
35#include <xrpl/protocol/STXChainBridge.h>
36#include <xrpl/protocol/jss.h>
37
38#include <functional>
39
40namespace ripple {
41
42static Expected<uint256, Json::Value>
44 Json::Value const& params,
45 Json::StaticString const fieldName,
46 std::string const& expectedType = "hex string or object")
47{
48 if (auto const uNodeIndex = LedgerEntryHelpers::parse<uint256>(params))
49 {
50 return *uNodeIndex;
51 }
53 "malformedRequest", fieldName, expectedType);
54}
55
56static Expected<uint256, Json::Value>
57parseIndex(Json::Value const& params, Json::StaticString const fieldName)
58{
59 return parseObjectID(params, fieldName, "hex string");
60}
61
62static Expected<uint256, Json::Value>
63parseAccountRoot(Json::Value const& params, Json::StaticString const fieldName)
64{
65 if (auto const account = LedgerEntryHelpers::parse<AccountID>(params))
66 {
67 return keylet::account(*account).key;
68 }
69
71 "malformedAddress", fieldName, "AccountID");
72}
73
74static Expected<uint256, Json::Value>
75parseAmendments(Json::Value const& params, Json::StaticString const fieldName)
76{
77 return parseObjectID(params, fieldName, "hex string");
78}
79
80static Expected<uint256, Json::Value>
81parseAMM(Json::Value const& params, Json::StaticString const fieldName)
82{
83 if (!params.isObject())
84 {
85 return parseObjectID(params, fieldName);
86 }
87
88 if (auto const value =
89 LedgerEntryHelpers::hasRequired(params, {jss::asset, jss::asset2});
90 !value)
91 {
92 return Unexpected(value.error());
93 }
94
95 try
96 {
97 auto const issue = issueFromJson(params[jss::asset]);
98 auto const issue2 = issueFromJson(params[jss::asset2]);
99 return keylet::amm(issue, issue2).key;
100 }
101 catch (std::runtime_error const&)
102 {
103 return LedgerEntryHelpers::malformedError("malformedRequest", "");
104 }
105}
106
107static Expected<uint256, Json::Value>
108parseBridge(Json::Value const& params, Json::StaticString const fieldName)
109{
110 if (!params.isMember(jss::bridge))
111 {
113 }
114
115 if (params[jss::bridge].isString())
116 {
117 return parseObjectID(params, fieldName);
118 }
119
120 auto const bridge =
121 LedgerEntryHelpers::parseBridgeFields(params[jss::bridge]);
122 if (!bridge)
123 return Unexpected(bridge.error());
124
125 auto const account = LedgerEntryHelpers::requiredAccountID(
126 params, jss::bridge_account, "malformedBridgeAccount");
127 if (!account)
128 return Unexpected(account.error());
129
130 STXChainBridge::ChainType const chainType =
131 STXChainBridge::srcChain(account.value() == bridge->lockingChainDoor());
132 if (account.value() != bridge->door(chainType))
133 return LedgerEntryHelpers::malformedError("malformedRequest", "");
134
135 return keylet::bridge(*bridge, chainType).key;
136}
137
138static Expected<uint256, Json::Value>
139parseCheck(Json::Value const& params, Json::StaticString const fieldName)
140{
141 return parseObjectID(params, fieldName, "hex string");
142}
143
144static Expected<uint256, Json::Value>
145parseCredential(Json::Value const& cred, Json::StaticString const fieldName)
146{
147 if (!cred.isObject())
148 {
149 return parseObjectID(cred, fieldName);
150 }
151
152 auto const subject = LedgerEntryHelpers::requiredAccountID(
153 cred, jss::subject, "malformedRequest");
154 if (!subject)
155 return Unexpected(subject.error());
156
157 auto const issuer = LedgerEntryHelpers::requiredAccountID(
158 cred, jss::issuer, "malformedRequest");
159 if (!issuer)
160 return Unexpected(issuer.error());
161
162 auto const credType = LedgerEntryHelpers::requiredHexBlob(
163 cred,
164 jss::credential_type,
166 "malformedRequest");
167 if (!credType)
168 return Unexpected(credType.error());
169
170 return keylet::credential(
171 *subject, *issuer, Slice(credType->data(), credType->size()))
172 .key;
173}
174
175static Expected<uint256, Json::Value>
176parseDelegate(Json::Value const& params, Json::StaticString const fieldName)
177{
178 if (!params.isObject())
179 {
180 return parseObjectID(params, fieldName);
181 }
182
183 auto const account = LedgerEntryHelpers::requiredAccountID(
184 params, jss::account, "malformedAddress");
185 if (!account)
186 return Unexpected(account.error());
187
188 auto const authorize = LedgerEntryHelpers::requiredAccountID(
189 params, jss::authorize, "malformedAddress");
190 if (!authorize)
191 return Unexpected(authorize.error());
192
193 return keylet::delegate(*account, *authorize).key;
194}
195
196static Expected<STArray, Json::Value>
198{
199 if (!jv.isArray())
201 "malformedAuthorizedCredentials",
202 jss::authorized_credentials,
203 "array");
204 STArray arr(sfAuthorizeCredentials, jv.size());
205 for (auto const& jo : jv)
206 {
207 if (!jo.isObject())
209 "malformedAuthorizedCredentials",
210 jss::authorized_credentials,
211 "array");
212 if (auto const value = LedgerEntryHelpers::hasRequired(
213 jo,
214 {jss::issuer, jss::credential_type},
215 "malformedAuthorizedCredentials");
216 !value)
217 {
218 return Unexpected(value.error());
219 }
220
221 auto const issuer = LedgerEntryHelpers::requiredAccountID(
222 jo, jss::issuer, "malformedAuthorizedCredentials");
223 if (!issuer)
224 return Unexpected(issuer.error());
225
226 auto const credentialType = LedgerEntryHelpers::requiredHexBlob(
227 jo,
228 jss::credential_type,
230 "malformedAuthorizedCredentials");
231 if (!credentialType)
232 return Unexpected(credentialType.error());
233
234 auto credential = STObject::makeInnerObject(sfCredential);
235 credential.setAccountID(sfIssuer, *issuer);
236 credential.setFieldVL(sfCredentialType, *credentialType);
237 arr.push_back(std::move(credential));
238 }
239
240 return arr;
241}
242
243static Expected<uint256, Json::Value>
245{
246 if (!dp.isObject())
247 {
248 return parseObjectID(dp, fieldName);
249 }
250
251 if ((dp.isMember(jss::authorized) ==
252 dp.isMember(jss::authorized_credentials)))
253 {
255 "malformedRequest",
256 "Must have exactly one of `authorized` and "
257 "`authorized_credentials`.");
258 }
259
260 auto const owner =
261 LedgerEntryHelpers::requiredAccountID(dp, jss::owner, "malformedOwner");
262 if (!owner)
263 {
264 return Unexpected(owner.error());
265 }
266
267 if (dp.isMember(jss::authorized))
268 {
269 if (auto const authorized =
270 LedgerEntryHelpers::parse<AccountID>(dp[jss::authorized]))
271 {
272 return keylet::depositPreauth(*owner, *authorized).key;
273 }
275 "malformedAuthorized", jss::authorized, "AccountID");
276 }
277
278 auto const& ac(dp[jss::authorized_credentials]);
279 auto const arr = parseAuthorizeCredentials(ac);
280 if (!arr.has_value())
281 return Unexpected(arr.error());
282 if (arr->empty() || (arr->size() > maxCredentialsArraySize))
283 {
285 "malformedAuthorizedCredentials",
286 jss::authorized_credentials,
287 "array");
288 }
289
290 auto const& sorted = credentials::makeSorted(arr.value());
291 if (sorted.empty())
292 {
293 // TODO: this error message is bad/inaccurate
295 "malformedAuthorizedCredentials",
296 jss::authorized_credentials,
297 "array");
298 }
299
300 return keylet::depositPreauth(*owner, std::move(sorted)).key;
301}
302
303static Expected<uint256, Json::Value>
304parseDID(Json::Value const& params, Json::StaticString const fieldName)
305{
306 auto const account = LedgerEntryHelpers::parse<AccountID>(params);
307 if (!account)
308 {
310 "malformedAddress", fieldName, "AccountID");
311 }
312
313 return keylet::did(*account).key;
314}
315
316static Expected<uint256, Json::Value>
318 Json::Value const& params,
319 Json::StaticString const fieldName)
320{
321 if (!params.isObject())
322 {
323 return parseObjectID(params, fieldName);
324 }
325
326 if (params.isMember(jss::sub_index) &&
327 (!params[jss::sub_index].isConvertibleTo(Json::uintValue) ||
328 params[jss::sub_index].isBool()))
329 {
331 "malformedRequest", jss::sub_index, "number");
332 }
333
334 if (params.isMember(jss::owner) == params.isMember(jss::dir_root))
335 {
337 "malformedRequest",
338 "Must have exactly one of `owner` and `dir_root` fields.");
339 }
340
341 std::uint64_t uSubIndex = params.get(jss::sub_index, 0).asUInt();
342
343 if (params.isMember(jss::dir_root))
344 {
345 if (auto const uDirRoot =
346 LedgerEntryHelpers::parse<uint256>(params[jss::dir_root]))
347 {
348 return keylet::page(*uDirRoot, uSubIndex).key;
349 }
350
352 "malformedDirRoot", jss::dir_root, "hash");
353 }
354
355 if (params.isMember(jss::owner))
356 {
357 auto const ownerID =
358 LedgerEntryHelpers::parse<AccountID>(params[jss::owner]);
359 if (!ownerID)
360 {
362 "malformedAddress", jss::owner, "AccountID");
363 }
364
365 return keylet::page(keylet::ownerDir(*ownerID), uSubIndex).key;
366 }
367
368 return LedgerEntryHelpers::malformedError("malformedRequest", "");
369}
370
371static Expected<uint256, Json::Value>
372parseEscrow(Json::Value const& params, Json::StaticString const fieldName)
373{
374 if (!params.isObject())
375 {
376 return parseObjectID(params, fieldName);
377 }
378
380 params, jss::owner, "malformedOwner");
381 if (!id)
382 return Unexpected(id.error());
383 auto const seq =
384 LedgerEntryHelpers::requiredUInt32(params, jss::seq, "malformedSeq");
385 if (!seq)
386 return Unexpected(seq.error());
387
388 return keylet::escrow(*id, *seq).key;
389}
390
391static Expected<uint256, Json::Value>
392parseFeeSettings(Json::Value const& params, Json::StaticString const fieldName)
393{
394 return parseObjectID(params, fieldName, "hex string");
395}
396
397static Expected<uint256, Json::Value>
398parseLedgerHashes(Json::Value const& params, Json::StaticString const fieldName)
399{
400 return parseObjectID(params, fieldName, "hex string");
401}
402
403static Expected<uint256, Json::Value>
404parseMPToken(Json::Value const& params, Json::StaticString const fieldName)
405{
406 if (!params.isObject())
407 {
408 return parseObjectID(params, fieldName);
409 }
410
411 auto const mptIssuanceID = LedgerEntryHelpers::requiredUInt192(
412 params, jss::mpt_issuance_id, "malformedMPTIssuanceID");
413 if (!mptIssuanceID)
414 return Unexpected(mptIssuanceID.error());
415
416 auto const account = LedgerEntryHelpers::requiredAccountID(
417 params, jss::account, "malformedAccount");
418 if (!account)
419 return Unexpected(account.error());
420
421 return keylet::mptoken(*mptIssuanceID, *account).key;
422}
423
424static Expected<uint256, Json::Value>
426 Json::Value const& params,
427 Json::StaticString const fieldName)
428{
429 auto const mptIssuanceID = LedgerEntryHelpers::parse<uint192>(params);
430 if (!mptIssuanceID)
432 "malformedMPTokenIssuance", fieldName, "Hash192");
433
434 return keylet::mptIssuance(*mptIssuanceID).key;
435}
436
437static Expected<uint256, Json::Value>
438parseNFTokenOffer(Json::Value const& params, Json::StaticString const fieldName)
439{
440 return parseObjectID(params, fieldName, "hex string");
441}
442
443static Expected<uint256, Json::Value>
444parseNFTokenPage(Json::Value const& params, Json::StaticString const fieldName)
445{
446 return parseObjectID(params, fieldName, "hex string");
447}
448
449static Expected<uint256, Json::Value>
450parseNegativeUNL(Json::Value const& params, Json::StaticString const fieldName)
451{
452 return parseObjectID(params, fieldName, "hex string");
453}
454
455static Expected<uint256, Json::Value>
456parseOffer(Json::Value const& params, Json::StaticString const fieldName)
457{
458 if (!params.isObject())
459 {
460 return parseObjectID(params, fieldName);
461 }
462
464 params, jss::account, "malformedAddress");
465 if (!id)
466 return Unexpected(id.error());
467
468 auto const seq = LedgerEntryHelpers::requiredUInt32(
469 params, jss::seq, "malformedRequest");
470 if (!seq)
471 return Unexpected(seq.error());
472
473 return keylet::offer(*id, *seq).key;
474}
475
476static Expected<uint256, Json::Value>
477parseOracle(Json::Value const& params, Json::StaticString const fieldName)
478{
479 if (!params.isObject())
480 {
481 return parseObjectID(params, fieldName);
482 }
483
485 params, jss::account, "malformedAccount");
486 if (!id)
487 return Unexpected(id.error());
488
489 auto const seq = LedgerEntryHelpers::requiredUInt32(
490 params, jss::oracle_document_id, "malformedDocumentID");
491 if (!seq)
492 return Unexpected(seq.error());
493
494 return keylet::oracle(*id, *seq).key;
495}
496
497static Expected<uint256, Json::Value>
498parsePayChannel(Json::Value const& params, Json::StaticString const fieldName)
499{
500 return parseObjectID(params, fieldName, "hex string");
501}
502
503static Expected<uint256, Json::Value>
505 Json::Value const& pd,
506 Json::StaticString const fieldName)
507{
508 if (pd.isString())
509 {
510 return parseObjectID(pd, fieldName);
511 }
512
513 if (!pd.isObject())
514 {
516 "malformedRequest", fieldName, "hex string or object");
517 }
518
519 auto const account = LedgerEntryHelpers::requiredAccountID(
520 pd, jss::account, "malformedAddress");
521 if (!account)
522 return Unexpected(account.error());
523
524 auto const seq =
525 LedgerEntryHelpers::requiredUInt32(pd, jss::seq, "malformedRequest");
526 if (!seq)
527 return Unexpected(seq.error());
528
529 return keylet::permissionedDomain(*account, pd[jss::seq].asUInt()).key;
530}
531
532static Expected<uint256, Json::Value>
534 Json::Value const& jvRippleState,
535 Json::StaticString const fieldName)
536{
537 Currency uCurrency;
538
539 if (!jvRippleState.isObject())
540 {
541 return parseObjectID(jvRippleState, fieldName);
542 }
543
544 if (auto const value = LedgerEntryHelpers::hasRequired(
545 jvRippleState, {jss::currency, jss::accounts});
546 !value)
547 {
548 return Unexpected(value.error());
549 }
550
551 if (!jvRippleState[jss::accounts].isArray() ||
552 jvRippleState[jss::accounts].size() != 2)
553 {
555 "malformedRequest", jss::accounts, "length-2 array of Accounts");
556 }
557
558 auto const id1 =
559 LedgerEntryHelpers::parse<AccountID>(jvRippleState[jss::accounts][0u]);
560 auto const id2 =
561 LedgerEntryHelpers::parse<AccountID>(jvRippleState[jss::accounts][1u]);
562 if (!id1 || !id2)
563 {
565 "malformedAddress", jss::accounts, "array of Accounts");
566 }
567 if (id1 == id2)
568 {
570 "malformedRequest", "Cannot have a trustline to self.");
571 }
572
573 if (!jvRippleState[jss::currency].isString() ||
574 jvRippleState[jss::currency] == "" ||
575 !to_currency(uCurrency, jvRippleState[jss::currency].asString()))
576 {
578 "malformedCurrency", jss::currency, "Currency");
579 }
580
581 return keylet::line(*id1, *id2, uCurrency).key;
582}
583
584static Expected<uint256, Json::Value>
585parseSignerList(Json::Value const& params, Json::StaticString const fieldName)
586{
587 return parseObjectID(params, fieldName, "hex string");
588}
589
590static Expected<uint256, Json::Value>
591parseTicket(Json::Value const& params, Json::StaticString const fieldName)
592{
593 if (!params.isObject())
594 {
595 return parseObjectID(params, fieldName);
596 }
597
599 params, jss::account, "malformedAddress");
600 if (!id)
601 return Unexpected(id.error());
602
603 auto const seq = LedgerEntryHelpers::requiredUInt32(
604 params, jss::ticket_seq, "malformedRequest");
605 if (!seq)
606 return Unexpected(seq.error());
607
608 return getTicketIndex(*id, *seq);
609}
610
611static Expected<uint256, Json::Value>
612parseVault(Json::Value const& params, Json::StaticString const fieldName)
613{
614 if (!params.isObject())
615 {
616 return parseObjectID(params, fieldName);
617 }
618
620 params, jss::owner, "malformedOwner");
621 if (!id)
622 return Unexpected(id.error());
623
624 auto const seq = LedgerEntryHelpers::requiredUInt32(
625 params, jss::seq, "malformedRequest");
626 if (!seq)
627 return Unexpected(seq.error());
628
629 return keylet::vault(*id, *seq).key;
630}
631
632static Expected<uint256, Json::Value>
634 Json::Value const& claim_id,
635 Json::StaticString const fieldName)
636{
637 if (!claim_id.isObject())
638 {
639 return parseObjectID(claim_id, fieldName);
640 }
641
642 auto const bridge_spec = LedgerEntryHelpers::parseBridgeFields(claim_id);
643 if (!bridge_spec)
644 return Unexpected(bridge_spec.error());
645
646 auto const seq = LedgerEntryHelpers::requiredUInt32(
647 claim_id, jss::xchain_owned_claim_id, "malformedXChainOwnedClaimID");
648 if (!seq)
649 {
650 return Unexpected(seq.error());
651 }
652
653 Keylet keylet = keylet::xChainClaimID(*bridge_spec, *seq);
654 return keylet.key;
655}
656
657static Expected<uint256, Json::Value>
659 Json::Value const& claim_id,
660 Json::StaticString const fieldName)
661{
662 if (!claim_id.isObject())
663 {
664 return parseObjectID(claim_id, fieldName);
665 }
666
667 auto const bridge_spec = LedgerEntryHelpers::parseBridgeFields(claim_id);
668 if (!bridge_spec)
669 return Unexpected(bridge_spec.error());
670
671 auto const seq = LedgerEntryHelpers::requiredUInt32(
672 claim_id,
673 jss::xchain_owned_create_account_claim_id,
674 "malformedXChainOwnedCreateAccountClaimID");
675 if (!seq)
676 {
677 return Unexpected(seq.error());
678 }
679
680 Keylet keylet = keylet::xChainCreateAccountClaimID(*bridge_spec, *seq);
681 return keylet.key;
682}
683
685 Json::Value const&,
686 Json::StaticString const);
687
694
695// {
696// ledger_hash : <ledger>
697// ledger_index : <ledger_index>
698// ...
699// }
702{
703 static auto ledgerEntryParsers = std::to_array<LedgerEntry>({
704#pragma push_macro("LEDGER_ENTRY")
705#undef LEDGER_ENTRY
706
707#define LEDGER_ENTRY(tag, value, name, rpcName, fields) \
708 {jss::rpcName, parse##name, tag},
709
710#include <xrpl/protocol/detail/ledger_entries.macro>
711
712#undef LEDGER_ENTRY
713#pragma pop_macro("LEDGER_ENTRY")
714 {jss::index, parseIndex, ltANY},
715 // aliases
716 {jss::account_root, parseAccountRoot, ltACCOUNT_ROOT},
717 {jss::ripple_state, parseRippleState, ltRIPPLE_STATE},
718 });
719
720 auto hasMoreThanOneMember = [&]() {
721 int count = 0;
722
723 for (auto const& ledgerEntry : ledgerEntryParsers)
724 {
725 if (context.params.isMember(ledgerEntry.fieldName))
726 {
727 count++;
728 if (count > 1) // Early exit if more than one is found
729 return true;
730 }
731 }
732 return false; // Return false if <= 1 is found
733 }();
734
735 if (hasMoreThanOneMember)
736 {
737 return RPC::make_param_error("Too many fields provided.");
738 }
739
741 auto jvResult = RPC::lookupLedger(lpLedger, context);
742
743 if (!lpLedger)
744 return jvResult;
745
746 uint256 uNodeIndex;
747 LedgerEntryType expectedType = ltANY;
748
749 try
750 {
751 bool found = false;
752 for (auto const& ledgerEntry : ledgerEntryParsers)
753 {
754 if (context.params.isMember(ledgerEntry.fieldName))
755 {
756 expectedType = ledgerEntry.expectedType;
757 // `Bridge` is the only type that involves two fields at the
758 // `ledger_entry` param level.
759 // So that parser needs to have the whole `params` field.
760 // All other parsers only need the one field name's info.
761 Json::Value const& params = ledgerEntry.fieldName == jss::bridge
762 ? context.params
763 : context.params[ledgerEntry.fieldName];
764 auto const result =
765 ledgerEntry.parseFunction(params, ledgerEntry.fieldName);
766 if (!result)
767 return result.error();
768
769 uNodeIndex = result.value();
770 found = true;
771 break;
772 }
773 }
774 if (!found)
775 {
776 if (context.apiVersion < 2u)
777 {
778 jvResult[jss::error] = "unknownOption";
779 return jvResult;
780 }
781 return RPC::make_param_error("No ledger_entry params provided.");
782 }
783 }
784 catch (Json::error& e)
785 {
786 if (context.apiVersion > 1u)
787 {
788 // For apiVersion 2 onwards, any parsing failures that throw
789 // this exception return an invalidParam error.
791 }
792 else
793 throw;
794 }
795
796 if (uNodeIndex.isZero())
797 {
799 }
800
801 auto const sleNode = lpLedger->read(keylet::unchecked(uNodeIndex));
802
803 bool bNodeBinary = false;
804 if (context.params.isMember(jss::binary))
805 bNodeBinary = context.params[jss::binary].asBool();
806
807 if (!sleNode)
808 {
809 // Not found.
811 }
812
813 if ((expectedType != ltANY) && (expectedType != sleNode->getType()))
814 {
816 }
817
818 if (bNodeBinary)
819 {
820 Serializer s;
821
822 sleNode->add(s);
823
824 jvResult[jss::node_binary] = strHex(s.peekData());
825 jvResult[jss::index] = to_string(uNodeIndex);
826 }
827 else
828 {
829 jvResult[jss::node] = sleNode->getJson(JsonOptions::none);
830 jvResult[jss::index] = to_string(uNodeIndex);
831 }
832
833 return jvResult;
834}
835
839{
840 org::xrpl::rpc::v1::GetLedgerEntryRequest& request = context.params;
841 org::xrpl::rpc::v1::GetLedgerEntryResponse response;
842 grpc::Status status = grpc::Status::OK;
843
845 if (auto status = RPC::ledgerFromRequest(ledger, context))
846 {
847 grpc::Status errorStatus;
848 if (status.toErrorCode() == rpcINVALID_PARAMS)
849 {
850 errorStatus = grpc::Status(
851 grpc::StatusCode::INVALID_ARGUMENT, status.message());
852 }
853 else
854 {
855 errorStatus =
856 grpc::Status(grpc::StatusCode::NOT_FOUND, status.message());
857 }
858 return {response, errorStatus};
859 }
860
861 auto const key = uint256::fromVoidChecked(request.key());
862 if (!key)
863 {
864 grpc::Status errorStatus{
865 grpc::StatusCode::INVALID_ARGUMENT, "index malformed"};
866 return {response, errorStatus};
867 }
868
869 auto const sleNode = ledger->read(keylet::unchecked(*key));
870 if (!sleNode)
871 {
872 grpc::Status errorStatus{
873 grpc::StatusCode::NOT_FOUND, "object not found"};
874 return {response, errorStatus};
875 }
876
877 Serializer s;
878 sleNode->add(s);
879
880 auto& stateObject = *response.mutable_ledger_object();
881 stateObject.set_data(s.peekData().data(), s.getLength());
882 stateObject.set_key(request.key());
883 *(response.mutable_ledger()) = request.ledger();
884 return {response, status};
885}
886} // namespace ripple
Lightweight wrapper to tag static string.
Definition json_value.h:63
Represents a JSON value.
Definition json_value.h:149
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:212
static STObject makeInnerObject(SField const &name)
Definition STObject.cpp:95
static ChainType srcChain(bool wasLockingChainSend)
Blob const & peekData() const
Definition Serializer.h:202
int getLength() const
Definition Serializer.h:233
An immutable linear range of bytes.
Definition Slice.h:46
static std::optional< base_uint > fromVoidChecked(T const &from)
Definition base_uint.h:326
bool isZero() const
Definition base_uint.h:540
T data(T... args)
T is_same_v
@ uintValue
unsigned integer value
Definition json_value.h:40
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:271
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:540
Keylet oracle(AccountID const &account, std::uint32_t const &documentID) noexcept
Definition Indexes.cpp:520
Keylet delegate(AccountID const &account, AccountID const &authorizedAccount) noexcept
A keylet for Delegate object.
Definition Indexes.cpp:465
Keylet permissionedDomain(AccountID const &account, std::uint32_t seq) noexcept
Definition Indexes.cpp:570
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Definition Indexes.cpp:446
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:244
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:526
Keylet xChainClaimID(STXChainBridge const &bridge, std::uint64_t seq)
Definition Indexes.cpp:486
Keylet did(AccountID const &account) noexcept
Definition Indexes.cpp:514
Keylet credential(AccountID const &subject, AccountID const &issuer, Slice const &credType) noexcept
Definition Indexes.cpp:553
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Definition Indexes.cpp:564
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:184
Keylet page(uint256 const &root, std::uint64_t index=0) noexcept
A page in a directory.
Definition Indexes.cpp:380
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Definition Indexes.cpp:368
Keylet escrow(AccountID const &src, std::uint32_t seq) noexcept
An escrow entry.
Definition Indexes.cpp:389
Keylet bridge(STXChainBridge const &bridge, STXChainBridge::ChainType chainType)
Definition Indexes.cpp:473
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:374
Keylet xChainCreateAccountClaimID(STXChainBridge const &bridge, std::uint64_t seq)
Definition Indexes.cpp:500
Keylet offer(AccountID const &id, std::uint32_t seq) noexcept
An offer from an account.
Definition Indexes.cpp:274
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Definition Indexes.cpp:342
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
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:161
@ rpcINVALID_PARAMS
Definition ErrorCodes.h:84
@ rpcUNEXPECTED_LEDGER_TYPE
Definition ErrorCodes.h:162
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:95
std::string strHex(FwdIt begin, FwdIt end)
Definition strHex.h:30
std::size_t constexpr maxCredentialsArraySize
The maximum number of credentials can be passed in array.
Definition Protocol.h:109
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:106
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:156
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:630
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:84
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:39
uint256 key
Definition Keylet.h:40
LedgerEntryType expectedType
Json::StaticString fieldName
FunctionType parseFunction
unsigned int apiVersion
Definition Context.h:49