1#include <xrpld/rpc/Context.h>
2#include <xrpld/rpc/GRPCHandlers.h>
3#include <xrpld/rpc/detail/RPCLedgerHelpers.h>
4#include <xrpld/rpc/handlers/ledger/LedgerEntryHelpers.h>
6#include <xrpl/basics/base_uint.h>
7#include <xrpl/basics/strHex.h>
8#include <xrpl/json/json_errors.h>
9#include <xrpl/json/json_value.h>
10#include <xrpl/ledger/ReadView.h>
11#include <xrpl/ledger/helpers/CredentialHelpers.h>
12#include <xrpl/protocol/AccountID.h>
13#include <xrpl/protocol/ErrorCodes.h>
14#include <xrpl/protocol/Indexes.h>
15#include <xrpl/protocol/Keylet.h>
16#include <xrpl/protocol/LedgerFormats.h>
17#include <xrpl/protocol/Protocol.h>
18#include <xrpl/protocol/SField.h>
19#include <xrpl/protocol/STArray.h>
20#include <xrpl/protocol/STXChainBridge.h>
21#include <xrpl/protocol/SeqProxy.h>
22#include <xrpl/protocol/UintTypes.h>
23#include <xrpl/protocol/jss.h>
25#include <grpcpp/support/status.h>
26#include <org/xrpl/rpc/v1/get_ledger_entry.pb.h>
41 unsigned const apiVersion)>;
43static std::expected<UInt256, json::Value>
48 unsigned const apiVersion);
59 unsigned const apiVersion) -> std::expected<UInt256, json::Value> {
64static std::expected<UInt256, json::Value>
68 std::string const& expectedType =
"hex string or object")
77static std::expected<UInt256, json::Value>
80 if (apiVersion > 2u && params.
isString())
83 if (index == jss::amendments.cStr())
85 if (index == jss::fee.cStr())
87 if (index == jss::nunl)
89 if (index == jss::hashes)
99static std::expected<UInt256, json::Value>
103 [[maybe_unused]]
unsigned const apiVersion)
115static std::expected<UInt256, json::Value>
119 [[maybe_unused]]
unsigned const apiVersion)
144static std::expected<UInt256, json::Value>
148 [[maybe_unused]]
unsigned const apiVersion)
155 if (params[jss::bridge].isString())
165 params, jss::bridge_account,
"malformedBridgeAccount");
171 if (account.value() != bridge->door(chainType))
177static std::expected<UInt256, json::Value>
181 [[maybe_unused]]
unsigned const apiVersion)
193 auto const sequence =
202static std::expected<UInt256, json::Value>
206 [[maybe_unused]]
unsigned const apiVersion)
231static std::expected<UInt256, json::Value>
235 [[maybe_unused]]
unsigned const apiVersion)
247 auto const authorize =
255static std::expected<STArray, json::Value>
261 "malformedAuthorizedCredentials", jss::authorized_credentials,
"array");
269 "malformedAuthorizedCredentials",
270 "Invalid field '" +
std::string(jss::authorized_credentials) +
271 "', array too long."));
278 "malformedAuthorizedCredentials",
279 "Invalid field '" +
std::string(jss::authorized_credentials) +
"', array empty."));
282 STArray arr(sfAuthorizeCredentials, n);
283 for (
auto const& jo : jv)
288 "malformedAuthorizedCredentials", jss::authorized_credentials,
"array of objects");
292 jo, {jss::issuer, jss::credential_type},
"malformedAuthorizedCredentials");
299 jo, jss::issuer,
"malformedAuthorizedCredentials");
309 credential.setAccountID(sfIssuer, *issuer);
310 credential.setFieldVL(sfCredentialType, *credentialType);
311 arr.
pushBack(std::move(credential));
317static std::expected<UInt256, json::Value>
321 [[maybe_unused]]
unsigned const apiVersion)
328 if ((dp.
isMember(jss::authorized) == dp.
isMember(jss::authorized_credentials)))
332 "Must have exactly one of `authorized` and "
333 "`authorized_credentials`.");
349 "malformedAuthorized", jss::authorized,
"AccountID");
352 auto const& ac(dp[jss::authorized_credentials]);
354 if (!arr.has_value())
362 "malformedAuthorizedCredentials", jss::authorized_credentials,
"array");
368static std::expected<UInt256, json::Value>
372 [[maybe_unused]]
unsigned const apiVersion)
383static std::expected<UInt256, json::Value>
387 [[maybe_unused]]
unsigned const apiVersion)
394 if (params.
isMember(jss::sub_index) &&
396 params[jss::sub_index].
isBool()))
399 "malformedRequest", jss::sub_index,
"number");
405 "malformedRequest",
"Must have exactly one of `owner` and `dir_root` fields.");
426 "malformedAddress", jss::owner,
"AccountID");
435static std::expected<UInt256, json::Value>
439 [[maybe_unused]]
unsigned const apiVersion)
459static std::expected<UInt256, json::Value>
464 [[maybe_unused]]
unsigned const apiVersion)
478static std::expected<UInt256, json::Value>
482 unsigned const apiVersion)
487 auto const index = params.
asUInt();
498static std::expected<UInt256, json::Value>
502 [[maybe_unused]]
unsigned const apiVersion)
520static std::expected<UInt256, json::Value>
524 [[maybe_unused]]
unsigned const apiVersion)
543static std::expected<UInt256, json::Value>
547 [[maybe_unused]]
unsigned const apiVersion)
555 params, jss::mpt_issuance_id,
"malformedMPTIssuanceID");
567static std::expected<UInt256, json::Value>
571 [[maybe_unused]]
unsigned const apiVersion)
577 "malformedMPTokenIssuance", fieldName,
"Hash192");
583static std::expected<UInt256, json::Value>
587 [[maybe_unused]]
unsigned const apiVersion)
599 auto const sequence =
608static std::expected<UInt256, json::Value>
612 [[maybe_unused]]
unsigned const apiVersion)
619static std::expected<UInt256, json::Value>
623 [[maybe_unused]]
unsigned const apiVersion)
643static std::expected<UInt256, json::Value>
647 [[maybe_unused]]
unsigned const apiVersion)
660 params, jss::oracle_document_id,
"malformedDocumentID");
667static std::expected<UInt256, json::Value>
671 [[maybe_unused]]
unsigned const apiVersion)
683 auto const destination =
688 auto const sequence =
697static std::expected<UInt256, json::Value>
701 [[maybe_unused]]
unsigned const apiVersion)
711 "malformedRequest", fieldName,
"hex string or object");
727static std::expected<UInt256, json::Value>
731 [[maybe_unused]]
unsigned const apiVersion)
740 if (
auto const value =
747 if (!jvRippleState[jss::accounts].isArray() || jvRippleState[jss::accounts].size() != 2)
750 "malformedRequest", jss::accounts,
"length-2 array of Accounts");
758 "malformedAddress", jss::accounts,
"array of Accounts");
763 "malformedRequest",
"Cannot have a trustline to self.");
766 if (!jvRippleState[jss::currency].isString() || jvRippleState[jss::currency] ==
"" ||
767 !
toCurrency(uCurrency, jvRippleState[jss::currency].asString()))
770 "malformedCurrency", jss::currency,
"Currency");
776static std::expected<UInt256, json::Value>
780 [[maybe_unused]]
unsigned const apiVersion)
795static std::expected<UInt256, json::Value>
799 [[maybe_unused]]
unsigned const apiVersion)
804 auto const sponsorID =
809 auto const sponseeID =
817static std::expected<UInt256, json::Value>
821 [[maybe_unused]]
unsigned const apiVersion)
831 auto const targetID =
838 auto const ticketSequence =
846static std::expected<UInt256, json::Value>
850 [[maybe_unused]]
unsigned const apiVersion)
871static std::expected<UInt256, json::Value>
875 [[maybe_unused]]
unsigned const apiVersion)
894static std::expected<UInt256, json::Value>
898 [[maybe_unused]]
unsigned const apiVersion)
910 claimId, jss::xchain_owned_claim_id,
"malformedXChainOwnedClaimID");
920static std::expected<UInt256, json::Value>
924 [[maybe_unused]]
unsigned const apiVersion)
937 jss::xchain_owned_create_account_claim_id,
938 "malformedXChainOwnedCreateAccountClaimID");
963 static auto kLedgerEntryParsers = std::to_array<LedgerEntry>({
964#pragma push_macro("LEDGER_ENTRY")
967#define LEDGER_ENTRY(tag, value, name, rpcName, fields) {jss::rpcName, parse##name, tag},
969#include <xrpl/protocol/detail/ledger_entries.macro>
972#pragma pop_macro("LEDGER_ENTRY")
973 {.fieldName = jss::index, .parseFunction =
parseIndex, .expectedType =
ltANY},
975 {.fieldName = jss::account_root,
977 .expectedType = ltACCOUNT_ROOT},
978 {.fieldName = jss::ripple_state,
980 .expectedType = ltRIPPLE_STATE},
983 auto const hasMoreThanOneMember = [&]() {
986 for (
auto const& ledgerEntry : kLedgerEntryParsers)
998 if (hasMoreThanOneMember)
1015 for (
auto const& ledgerEntry : kLedgerEntryParsers)
1019 expectedType = ledgerEntry.expectedType;
1024 json::Value const& params = ledgerEntry.fieldName == jss::bridge
1026 : context.
params[ledgerEntry.fieldName];
1028 ledgerEntry.parseFunction(params, ledgerEntry.fieldName, context.
apiVersion);
1030 return result.error();
1032 uNodeIndex = result.value();
1041 jvResult[jss::error] =
"unknownOption";
1060 jvResult[jss::index] =
to_string(uNodeIndex);
1070 bool bNodeBinary =
false;
1081 if ((expectedType !=
ltANY) && (expectedType != sleNode->getType()))
1106 org::xrpl::rpc::v1::GetLedgerEntryRequest
const& request = context.
params;
1107 org::xrpl::rpc::v1::GetLedgerEntryResponse response;
1108 grpc::Status
const status = grpc::Status::OK;
1113 grpc::Status errorStatus;
1116 errorStatus = grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, status.message());
1120 errorStatus = grpc::Status(grpc::StatusCode::NOT_FOUND, status.message());
1122 return {response, errorStatus};
1128 grpc::Status
const errorStatus{grpc::StatusCode::INVALID_ARGUMENT,
"index malformed"};
1129 return {response, errorStatus};
1135 grpc::Status
const errorStatus{grpc::StatusCode::NOT_FOUND,
"object not found"};
1136 return {response, errorStatus};
1142 auto& stateObject = *response.mutable_ledger_object();
1144 stateObject.set_key(request.key());
1145 *(response.mutable_ledger()) = request.ledger();
1146 return {response, status};
Lightweight wrapper to tag static string.
Value get(UInt index, Value const &defaultValue) const
If the array contains at least index+1 elements, returns the element value, otherwise returns default...
UInt size() const
Number of values in array or object.
bool isConvertibleTo(ValueType other) const
std::string asString() const
Returns the unquoted string value.
bool isMember(char const *key) const
Return true if the object has a member named key.
static std::optional< BaseUInt > fromVoidChecked(T const &from)
void pushBack(STObject const &object)
static STObject makeInnerObject(SField const &name)
static ChainType srcChain(bool wasLockingChainSend)
static constexpr SeqProxy rawSequence(std::uint32_t v)
Factory function to return a sequence-based SeqProxy.
static constexpr SeqProxy rawTicket(std::uint32_t v)
Factory function to return a ticket-based SeqProxy.
Blob const & peekData() const
An immutable linear range of bytes.
@ UInt
unsigned integer value
std::set< std::pair< AccountID, Slice > > makeSorted(STArray const &credentials)
Keylet computation functions.
Keylet const & skip() noexcept
The index of the "short" skip list.
Keylet nftokenOffer(AccountID const &owner, SeqProxy const &seq)
An offer from an account to buy or sell an NFT.
Keylet oracle(AccountID const &account, std::uint32_t const documentID) noexcept
Keylet payChannel(AccountID const &src, AccountID const &dst, SeqProxy const &seq) noexcept
A PaymentChannel.
Keylet const & negativeUNL() noexcept
The (fixed) index of the object containing the ledger negativeUNL.
Keylet escrow(AccountID const &src, SeqProxy const &seq) noexcept
An escrow entry.
Keylet did(AccountID const &account) noexcept
Keylet offer(AccountID const &id, SeqProxy const &seq) noexcept
An offer from an account.
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Keylet bridge(STXChainBridge const &bridge, STXChainBridge::ChainType chainType)
Keylet const & feeSettings() noexcept
The (fixed) index of the object containing the ledger fees.
Keylet const & amendments() noexcept
The index of the amendment table.
Keylet signerList(AccountID const &account) noexcept
A SignerList.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet txProposal(AccountID const &target, std::uint32_t ticketSequence) noexcept
A TransactionProposal.
Keylet check(AccountID const &id, SeqProxy const &seq) noexcept
A Check.
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Keylet unchecked(UInt256 const &key) noexcept
Any ledger entry.
Keylet ticket(AccountID const &id, SeqProxy const &ticketSeq)
A ticket belonging to an account.
Keylet vault(AccountID const &owner, SeqProxy const &seq) noexcept
Keylet permissionedDomain(AccountID const &account, SeqProxy const &seq) noexcept
Keylet page(UInt256 const &root, std::uint64_t const index=0) noexcept
A page in a directory.
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Keylet delegate(AccountID const &account, AccountID const &authorizedAccount) noexcept
A keylet for Delegate object.
Keylet loanBroker(AccountID const &owner, SeqProxy const &seq) noexcept
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet xChainClaimID(STXChainBridge const &bridge, std::uint64_t const seq)
Keylet sponsorship(AccountID const &sponsor, AccountID const &sponsee) noexcept
A Sponsorship.
Keylet loan(UInt256 const &loanBrokerID, SeqProxy const &loanSeq) noexcept
Keylet xChainCreateAccountClaimID(STXChainBridge const &bridge, std::uint64_t const seq)
Keylet credential(AccountID const &subject, AccountID const &issuer, Slice const &credType) noexcept
Keylet mptokenIssuance(MPTID const &issuanceID) noexcept
Keylet trustLine(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
std::optional< T > parse(json::Value const ¶m)
std::expected< AccountID, json::Value > requiredAccountID(json::Value const ¶ms, json::StaticString const fieldName, std::string const &err)
std::expected< STXChainBridge, json::Value > parseBridgeFields(json::Value const ¶ms)
std::expected< UInt192, json::Value > requiredUInt192(json::Value const ¶ms, json::StaticString const fieldName, std::string const &err)
std::expected< Asset, json::Value > requiredAsset(json::Value const ¶ms, json::StaticString const fieldName, std::string const &err)
std::expected< Blob, json::Value > requiredHexBlob(json::Value const ¶ms, json::StaticString const fieldName, std::size_t maxLength, std::string const &err)
std::unexpected< json::Value > malformedError(std::string const &err, std::string const &message)
std::expected< std::uint32_t, json::Value > requiredUInt32(json::Value const ¶ms, json::StaticString const fieldName, std::string const &err)
std::expected< UInt256, json::Value > requiredUInt256(json::Value const ¶ms, json::StaticString const fieldName, std::string const &err)
std::unexpected< json::Value > missingFieldError(json::StaticString const field, std::optional< std::string > err=std::nullopt)
std::unexpected< json::Value > invalidFieldError(std::string const &err, json::StaticString const field, std::string const &type)
std::expected< bool, json::Value > hasRequired(json::Value const ¶ms, std::initializer_list< json::StaticString > fields, std::optional< std::string > err=std::nullopt)
Status ledgerFromRequest(T &ledger, GRPCContext< R > const &context)
Retrieves a ledger from a gRPC request context.
json::Value makeParamError(std::string const &message)
Returns a new json object that indicates invalid parameters.
void injectError(ErrorCodeI code, json::Value &json)
Add or update the json update to reflect the error code.
json::Value makeError(ErrorCodeI code)
Returns a new json object that reflects the error code.
Status lookupLedger(std::shared_ptr< ReadView const > &ledger, JsonContext const &context, json::Value &result)
Looks up a ledger from a request and fills a json::Value with ledger data.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::function< std::expected< UInt256, json::Value >( json::Value const &, json::StaticString const, unsigned const apiVersion)> FunctionType
@ RpcUnexpectedLedgerType
static std::expected< STArray, json::Value > parseAuthorizeCredentials(json::Value const &jv)
static std::expected< UInt256, json::Value > parseFixed(Keylet const &keylet, json::Value const ¶ms, json::StaticString const &fieldName, unsigned const apiVersion)
auto const parseFeeSettings
static std::expected< UInt256, json::Value > parseEscrow(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
constexpr std::size_t kMaxCredentialTypeLength
The maximum length of a CredentialType inside a Credential.
static std::expected< UInt256, json::Value > parseCredential(json::Value const &cred, json::StaticString const fieldName, unsigned const apiVersion)
std::string strHex(FwdIt begin, FwdIt end)
static std::expected< UInt256, json::Value > parseSponsorship(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseLoan(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseMPToken(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseRippleState(json::Value const &jvRippleState, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseIndex(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseTransactionProposal(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
BaseUInt< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
static bool authorized(Port const &port, std::map< std::string, std::string > const &h)
bool toCurrency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.
static std::expected< UInt256, json::Value > parseLoanBroker(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseDirectoryNode(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static FunctionType fixed(Keylet const &keylet)
static std::expected< UInt256, json::Value > parseXChainOwnedClaimID(json::Value const &claimId, json::StaticString const fieldName, unsigned const apiVersion)
std::string to_string(BaseUInt< Bits, Tag > const &a)
static std::expected< UInt256, json::Value > parseXChainOwnedCreateAccountClaimID(json::Value const &claimId, json::StaticString const fieldName, unsigned const apiVersion)
auto const parseAmendments
static std::expected< UInt256, json::Value > parseTicket(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseOracle(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
constexpr std::size_t kMaxCredentialsArraySize
The maximum number of credentials can be passed in array.
static std::expected< UInt256, json::Value > parseAccountRoot(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parsePermissionedDomain(json::Value const &pd, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseLedgerHashes(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
auto const parseNegativeUNL
static std::expected< UInt256, json::Value > parseCheck(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
json::Value doLedgerEntry(rpc::JsonContext &)
std::pair< org::xrpl::rpc::v1::GetLedgerEntryResponse, grpc::Status > doLedgerEntryGrpc(rpc::GRPCContext< org::xrpl::rpc::v1::GetLedgerEntryRequest > &context)
static std::expected< UInt256, json::Value > parseOffer(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseSignerList(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseVault(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseMPTokenIssuance(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseNFTokenOffer(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
LedgerEntryType
Identifiers for on-ledger objects.
@ ltANY
A special type, matching any ledger entry type.
static std::expected< UInt256, json::Value > parseDID(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parsePayChannel(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseDepositPreauth(json::Value const &dp, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseNFTokenPage(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseObjectID(json::Value const ¶ms, json::StaticString const fieldName, std::string const &expectedType="hex string or object")
static std::expected< UInt256, json::Value > parseAMM(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseDelegate(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
static std::expected< UInt256, json::Value > parseBridge(json::Value const ¶ms, json::StaticString const fieldName, unsigned const apiVersion)
A pair of SHAMap key and LedgerEntryType.
json::StaticString fieldName
FunctionType parseFunction
LedgerEntryType expectedType