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/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/ReadView.h>
11#include <xrpl/ledger/helpers/CredentialHelpers.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>
24 unsigned const apiVersion)>;
31 unsigned const apiVersion);
43 return parseFixed(keylet, params, fieldName, apiVersion);
47static Expected<uint256, Json::Value>
51 std::string const& expectedType =
"hex string or object")
53 if (
auto const uNodeIndex = LedgerEntryHelpers::parse<uint256>(params))
60static Expected<uint256, Json::Value>
63 if (apiVersion > 2u && params.
isString())
66 if (index == jss::amendments.c_str())
68 if (index == jss::fee.c_str())
70 if (index == jss::nunl)
72 if (index == jss::hashes)
82static Expected<uint256, Json::Value>
86 [[maybe_unused]]
unsigned const apiVersion)
88 if (
auto const account = LedgerEntryHelpers::parse<AccountID>(params))
102 [[maybe_unused]]
unsigned const apiVersion)
126static Expected<uint256, Json::Value>
130 [[maybe_unused]]
unsigned const apiVersion)
137 if (params[jss::bridge].isString())
147 params, jss::bridge_account,
"malformedBridgeAccount");
153 if (account.value() != bridge->door(chainType))
159static Expected<uint256, Json::Value>
163 [[maybe_unused]]
unsigned const apiVersion)
168static Expected<uint256, Json::Value>
172 [[maybe_unused]]
unsigned const apiVersion)
197static Expected<uint256, Json::Value>
201 [[maybe_unused]]
unsigned const apiVersion)
213 auto const authorize =
221static Expected<STArray, Json::Value>
227 "malformedAuthorizedCredentials", jss::authorized_credentials,
"array");
235 "malformedAuthorizedCredentials",
236 "Invalid field '" +
std::string(jss::authorized_credentials) +
237 "', array too long."));
244 "malformedAuthorizedCredentials",
245 "Invalid field '" +
std::string(jss::authorized_credentials) +
"', array empty."));
248 STArray arr(sfAuthorizeCredentials, n);
249 for (
auto const& jo : jv)
254 "malformedAuthorizedCredentials", jss::authorized_credentials,
"array");
258 jo, {jss::issuer, jss::credential_type},
"malformedAuthorizedCredentials");
265 jo, jss::issuer,
"malformedAuthorizedCredentials");
275 credential.setAccountID(sfIssuer, *issuer);
276 credential.setFieldVL(sfCredentialType, *credentialType);
283static Expected<uint256, Json::Value>
287 [[maybe_unused]]
unsigned const apiVersion)
294 if ((dp.
isMember(jss::authorized) == dp.
isMember(jss::authorized_credentials)))
298 "Must have exactly one of `authorized` and "
299 "`authorized_credentials`.");
310 if (
auto const authorized = LedgerEntryHelpers::parse<AccountID>(dp[jss::authorized]))
315 "malformedAuthorized", jss::authorized,
"AccountID");
318 auto const& ac(dp[jss::authorized_credentials]);
320 if (!arr.has_value())
328 "malformedAuthorizedCredentials", jss::authorized_credentials,
"array");
334static Expected<uint256, Json::Value>
338 [[maybe_unused]]
unsigned const apiVersion)
340 auto const account = LedgerEntryHelpers::parse<AccountID>(params);
349static Expected<uint256, Json::Value>
353 [[maybe_unused]]
unsigned const apiVersion)
360 if (params.
isMember(jss::sub_index) &&
362 params[jss::sub_index].
isBool()))
370 "malformedRequest",
"Must have exactly one of `owner` and `dir_root` fields.");
377 if (
auto const uDirRoot = LedgerEntryHelpers::parse<uint256>(params[jss::dir_root]))
387 auto const ownerID = LedgerEntryHelpers::parse<AccountID>(params[jss::owner]);
391 "malformedAddress", jss::owner,
"AccountID");
400static Expected<uint256, Json::Value>
404 [[maybe_unused]]
unsigned const apiVersion)
428 [[maybe_unused]]
unsigned const apiVersion)
442static Expected<uint256, Json::Value>
446 unsigned const apiVersion)
451 auto const index = params.
asUInt();
462static Expected<uint256, Json::Value>
466 [[maybe_unused]]
unsigned const apiVersion)
483static Expected<uint256, Json::Value>
487 [[maybe_unused]]
unsigned const apiVersion)
505static Expected<uint256, Json::Value>
509 [[maybe_unused]]
unsigned const apiVersion)
516 auto const mptIssuanceID =
529static Expected<uint256, Json::Value>
533 [[maybe_unused]]
unsigned const apiVersion)
535 auto const mptIssuanceID = LedgerEntryHelpers::parse<uint192>(params);
539 "malformedMPTokenIssuance", fieldName,
"Hash192");
545static Expected<uint256, Json::Value>
549 [[maybe_unused]]
unsigned const apiVersion)
554static Expected<uint256, Json::Value>
558 [[maybe_unused]]
unsigned const apiVersion)
569 [[maybe_unused]]
unsigned const apiVersion)
587static Expected<uint256, Json::Value>
591 [[maybe_unused]]
unsigned const apiVersion)
610static Expected<uint256, Json::Value>
614 [[maybe_unused]]
unsigned const apiVersion)
619static Expected<uint256, Json::Value>
623 [[maybe_unused]]
unsigned const apiVersion)
633 "malformedRequest", fieldName,
"hex string or object");
648static Expected<uint256, Json::Value>
652 [[maybe_unused]]
unsigned const apiVersion)
661 if (
auto const value =
668 if (!jvRippleState[jss::accounts].isArray() || jvRippleState[jss::accounts].size() != 2)
671 "malformedRequest", jss::accounts,
"length-2 array of Accounts");
674 auto const id1 = LedgerEntryHelpers::parse<AccountID>(jvRippleState[jss::accounts][0u]);
675 auto const id2 = LedgerEntryHelpers::parse<AccountID>(jvRippleState[jss::accounts][1u]);
679 "malformedAddress", jss::accounts,
"array of Accounts");
684 "malformedRequest",
"Cannot have a trustline to self.");
687 if (!jvRippleState[jss::currency].isString() || jvRippleState[jss::currency] ==
"" ||
688 !
to_currency(uCurrency, jvRippleState[jss::currency].asString()))
691 "malformedCurrency", jss::currency,
"Currency");
697static Expected<uint256, Json::Value>
701 [[maybe_unused]]
unsigned const apiVersion)
706static Expected<uint256, Json::Value>
710 [[maybe_unused]]
unsigned const apiVersion)
729static Expected<uint256, Json::Value>
733 [[maybe_unused]]
unsigned const apiVersion)
751static Expected<uint256, Json::Value>
755 [[maybe_unused]]
unsigned const apiVersion)
767 claim_id, jss::xchain_owned_claim_id,
"malformedXChainOwnedClaimID");
777static Expected<uint256, Json::Value>
781 [[maybe_unused]]
unsigned const apiVersion)
794 jss::xchain_owned_create_account_claim_id,
795 "malformedXChainOwnedCreateAccountClaimID");
821#pragma push_macro("LEDGER_ENTRY")
824#define LEDGER_ENTRY(tag, value, name, rpcName, fields) {jss::rpcName, parse##name, tag},
826#include <xrpl/protocol/detail/ledger_entries.macro>
829#pragma pop_macro("LEDGER_ENTRY")
836 auto const hasMoreThanOneMember = [&]() {
839 for (
auto const& ledgerEntry : ledgerEntryParsers)
851 if (hasMoreThanOneMember)
868 for (
auto const& ledgerEntry : ledgerEntryParsers)
872 expectedType = ledgerEntry.expectedType;
877 Json::Value const& params = ledgerEntry.fieldName == jss::bridge
879 : context.
params[ledgerEntry.fieldName];
881 ledgerEntry.parseFunction(params, ledgerEntry.fieldName, context.
apiVersion);
883 return result.error();
885 uNodeIndex = result.value();
894 jvResult[jss::error] =
"unknownOption";
913 jvResult[jss::index] =
to_string(uNodeIndex);
923 bool bNodeBinary =
false;
934 if ((expectedType !=
ltANY) && (expectedType != sleNode->getType()))
959 org::xrpl::rpc::v1::GetLedgerEntryRequest
const& request = context.
params;
960 org::xrpl::rpc::v1::GetLedgerEntryResponse response;
961 grpc::Status
const status = grpc::Status::OK;
966 grpc::Status errorStatus;
969 errorStatus = grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, status.message());
973 errorStatus = grpc::Status(grpc::StatusCode::NOT_FOUND, status.message());
975 return {response, errorStatus};
981 grpc::Status
const errorStatus{grpc::StatusCode::INVALID_ARGUMENT,
"index malformed"};
982 return {response, errorStatus};
988 grpc::Status
const errorStatus{grpc::StatusCode::NOT_FOUND,
"object not found"};
989 return {response, errorStatus};
995 auto& stateObject = *response.mutable_ledger_object();
997 stateObject.set_key(request.key());
998 *(response.mutable_ledger()) = request.ledger();
999 return {response, status};
Lightweight wrapper to tag static string.
UInt size() const
Number of values in array or object.
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.
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)
static STObject makeInnerObject(SField const &name)
static ChainType srcChain(bool wasLockingChainSend)
Blob const & peekData() const
An immutable linear range of bytes.
static std::optional< base_uint > fromVoidChecked(T const &from)
@ uintValue
unsigned integer value
Expected< std::uint32_t, Json::Value > requiredUInt32(Json::Value const ¶ms, Json::StaticString const fieldName, std::string const &err)
Expected< AccountID, Json::Value > requiredAccountID(Json::Value const ¶ms, Json::StaticString const fieldName, std::string const &err)
Unexpected< Json::Value > missingFieldError(Json::StaticString const field, std::optional< std::string > err=std::nullopt)
Expected< uint192, Json::Value > requiredUInt192(Json::Value const ¶ms, Json::StaticString const fieldName, std::string const &err)
Expected< bool, Json::Value > hasRequired(Json::Value const ¶ms, std::initializer_list< Json::StaticString > fields, std::optional< std::string > err=std::nullopt)
Expected< Blob, Json::Value > requiredHexBlob(Json::Value const ¶ms, Json::StaticString const fieldName, std::size_t maxLength, std::string const &err)
Expected< Issue, Json::Value > requiredIssue(Json::Value const ¶ms, Json::StaticString const fieldName, std::string const &err)
Expected< STXChainBridge, Json::Value > parseBridgeFields(Json::Value const ¶ms)
Unexpected< Json::Value > malformedError(std::string const &err, std::string const &message)
Expected< uint256, Json::Value > requiredUInt256(Json::Value const ¶ms, Json::StaticString const fieldName, std::string const &err)
Unexpected< Json::Value > invalidFieldError(std::string const &err, Json::StaticString const field, std::string const &type)
Json::Value make_param_error(std::string const &message)
Returns a new json object that indicates invalid parameters.
Status ledgerFromRequest(T &ledger, GRPCContext< R > const &context)
Retrieves a ledger from a gRPC request context.
void inject_error(error_code_i code, Json::Value &json)
Add or update the json update to reflect 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.
Json::Value make_error(error_code_i code)
Returns a new json object that reflects the error code.
std::set< std::pair< AccountID, Slice > > makeSorted(STArray const &credentials)
Keylet const & skip() noexcept
The index of the "short" skip list.
Keylet oracle(AccountID const &account, std::uint32_t const &documentID) noexcept
Keylet const & negativeUNL() noexcept
The (fixed) index of the object containing the ledger negativeUNL.
Keylet did(AccountID const &account) noexcept
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Keylet loanbroker(AccountID const &owner, std::uint32_t seq) noexcept
Keylet escrow(AccountID const &src, std::uint32_t seq) noexcept
An escrow entry.
Keylet bridge(STXChainBridge const &bridge, STXChainBridge::ChainType chainType)
Keylet const & amendments() noexcept
The index of the amendment table.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Keylet loan(uint256 const &loanBrokerID, std::uint32_t loanSeq) noexcept
Keylet offer(AccountID const &id, std::uint32_t seq) noexcept
An offer from an account.
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Keylet line(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
Keylet xChainCreateAccountClaimID(STXChainBridge const &bridge, std::uint64_t seq)
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Keylet delegate(AccountID const &account, AccountID const &authorizedAccount) noexcept
A keylet for Delegate object.
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet const & fees() noexcept
The (fixed) index of the object containing the ledger fees.
Keylet permissionedDomain(AccountID const &account, std::uint32_t seq) noexcept
Keylet page(uint256 const &root, std::uint64_t index=0) noexcept
A page in a directory.
Keylet credential(AccountID const &subject, AccountID const &issuer, Slice const &credType) noexcept
Keylet xChainClaimID(STXChainBridge const &bridge, std::uint64_t seq)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
static Expected< uint256, Json::Value > parseDirectoryNode(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseMPToken(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parsePermissionedDomain(Json::Value const &pd, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseAMM(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
auto const parseFeeSettings
static Expected< uint256, Json::Value > parseSignerList(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
std::string to_string(base_uint< Bits, Tag > const &a)
std::string strHex(FwdIt begin, FwdIt end)
static Expected< uint256, Json::Value > parseOracle(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseCheck(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
uint256 getTicketIndex(AccountID const &account, std::uint32_t uSequence)
static Expected< uint256, Json::Value > parseIndex(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseDID(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseLoan(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseXChainOwnedClaimID(Json::Value const &claim_id, Json::StaticString const fieldName, unsigned const apiVersion)
static bool authorized(Port const &port, std::map< std::string, std::string > const &h)
static FunctionType fixed(Keylet const &keylet)
static Expected< uint256, Json::Value > parseDelegate(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
auto const parseAmendments
static Expected< uint256, Json::Value > parseFixed(Keylet const &keylet, Json::Value const ¶ms, Json::StaticString const &fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseLedgerHashes(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseEscrow(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseTicket(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseCredential(Json::Value const &cred, Json::StaticString const fieldName, unsigned const apiVersion)
std::size_t constexpr maxCredentialsArraySize
The maximum number of credentials can be passed in array.
std::pair< org::xrpl::rpc::v1::GetLedgerEntryResponse, grpc::Status > doLedgerEntryGrpc(RPC::GRPCContext< org::xrpl::rpc::v1::GetLedgerEntryRequest > &context)
auto const parseNegativeUNL
static Expected< uint256, Json::Value > parsePayChannel(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseObjectID(Json::Value const ¶ms, Json::StaticString const fieldName, std::string const &expectedType="hex string or object")
static Expected< uint256, Json::Value > parseRippleState(Json::Value const &jvRippleState, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseNFTokenPage(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< STArray, Json::Value > parseAuthorizeCredentials(Json::Value const &jv)
static Expected< uint256, Json::Value > parseOffer(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseMPTokenIssuance(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseBridge(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseDepositPreauth(Json::Value const &dp, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseVault(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.
bool to_currency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.
static Expected< uint256, Json::Value > parseNFTokenOffer(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseLoanBroker(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
static Expected< uint256, Json::Value > parseAccountRoot(Json::Value const ¶ms, Json::StaticString const fieldName, unsigned const apiVersion)
@ rpcUNEXPECTED_LEDGER_TYPE
static Expected< uint256, Json::Value > parseXChainOwnedCreateAccountClaimID(Json::Value const &claim_id, Json::StaticString const fieldName, unsigned const apiVersion)
std::size_t constexpr maxCredentialTypeLength
The maximum length of a CredentialType inside a Credential.
Json::Value doLedgerEntry(RPC::JsonContext &)
A pair of SHAMap key and LedgerEntryType.
Json::StaticString fieldName
FunctionType parseFunction
LedgerEntryType expectedType