20 #include <ripple/app/ledger/LedgerMaster.h>
21 #include <ripple/app/ledger/LedgerToJson.h>
22 #include <ripple/app/ledger/OpenLedger.h>
23 #include <ripple/app/misc/Transaction.h>
24 #include <ripple/app/paths/TrustLine.h>
25 #include <ripple/app/rdb/RelationalDatabase.h>
26 #include <ripple/app/tx/impl/details/NFTokenUtils.h>
27 #include <ripple/ledger/View.h>
28 #include <ripple/net/RPCErr.h>
29 #include <ripple/protocol/AccountID.h>
30 #include <ripple/protocol/Feature.h>
31 #include <ripple/protocol/nftPageMask.h>
32 #include <ripple/resource/Fees.h>
33 #include <ripple/rpc/Context.h>
34 #include <ripple/rpc/DeliveredAmount.h>
35 #include <ripple/rpc/impl/RPCHelpers.h>
36 #include <boost/algorithm/string/case_conv.hpp>
47 auto const publicKey =
53 result = parseBase58<AccountID>(account);
101 if (sle->getFieldAmount(
sfLowLimit).getIssuer() == accountID)
103 else if (sle->getFieldAmount(
sfHighLimit).getIssuer() == accountID)
121 return (sle->getFieldAmount(
sfLowLimit).getIssuer() == accountID) ||
122 (sle->getFieldAmount(
sfHighLimit).getIssuer() == accountID);
132 return sle->getAccountID(
sfAccount) == accountID ||
139 return sle->key() == accountSignerList.
key;
145 return sle->getAccountID(
sfOwner) == accountID;
164 return it != typeFilter.
end();
169 bool iterateNFTPages =
170 (!typeFilter.has_value() ||
172 dirIndex == beast::zero;
177 if (iterateNFTPages && entryIndex != beast::zero)
183 iterateNFTPages =
false;
190 uint32_t mlimit = limit;
195 Keylet const first = entryIndex == beast::zero
220 jvResult[jss::limit] = limit;
236 entryIndex = beast::zero;
253 return mlimit < limit;
259 auto const& entries = dir->getFieldV256(
sfIndexes);
260 auto iter = entries.begin();
264 iter =
std::find(iter, entries.end(), entryIndex);
265 if (iter == entries.end())
273 if (i == mlimit && mlimit < limit)
275 jvResult[jss::limit] = limit;
276 jvResult[jss::marker] =
281 for (; iter != entries.end(); ++iter)
285 if (!typeFilter.has_value() ||
286 typeMatchesFilter(typeFilter.value(), sleNode->getType()))
293 if (++iter != entries.end())
295 jvResult[jss::limit] = limit;
296 jvResult[jss::marker] =
305 auto const nodeIndex = dir->getFieldU64(
sfIndexNext);
316 auto const& e = dir->getFieldV256(
sfIndexes);
319 jvResult[jss::limit] = limit;
320 jvResult[jss::marker] =
332 isValidatedOld(
LedgerMaster& ledgerMaster,
bool standaloneOrReporting)
334 if (standaloneOrReporting)
346 auto& params = context.params;
348 auto indexValue = params[jss::ledger_index];
349 auto hashValue = params[jss::ledger_hash];
352 auto& legacyLedger = params[jss::ledger];
355 if (legacyLedger.asString().size() > 12)
356 hashValue = legacyLedger;
358 indexValue = legacyLedger;
363 if (!hashValue.isString())
367 if (!ledgerHash.parseHex(hashValue.asString()))
369 return getLedger(ledger, ledgerHash, context);
372 auto const index = indexValue.asString();
374 if (index ==
"current" ||
375 (index.empty() && !context.app.config().reporting()))
376 return getLedger(ledger, LedgerShortcut::CURRENT, context);
378 if (index ==
"validated" ||
379 (index.empty() && context.app.config().reporting()))
380 return getLedger(ledger, LedgerShortcut::VALIDATED, context);
382 if (index ==
"closed")
383 return getLedger(ledger, LedgerShortcut::CLOSED, context);
393 template <
class T,
class R>
397 R& request = context.
params;
405 GRPCContext<org::xrpl::rpc::v1::GetLedgerEntryRequest>&);
411 GRPCContext<org::xrpl::rpc::v1::GetLedgerDataRequest>&);
417 GRPCContext<org::xrpl::rpc::v1::GetLedgerRequest>&);
423 org::xrpl::rpc::v1::LedgerSpecifier
const& specifier,
428 using LedgerCase = org::xrpl::rpc::v1::LedgerSpecifier::LedgerCase;
429 LedgerCase ledgerCase = specifier.ledger_case();
432 case LedgerCase::kHash: {
435 return getLedger(ledger, *hash, context);
439 case LedgerCase::kSequence:
440 return getLedger(ledger, specifier.sequence(), context);
441 case LedgerCase::kShortcut:
443 case LedgerCase::LEDGER_NOT_SET: {
444 auto const shortcut = specifier.shortcut();
447 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED ||
449 org::xrpl::rpc::v1::LedgerSpecifier::
450 SHORTCUT_UNSPECIFIED &&
453 return getLedger(ledger, LedgerShortcut::VALIDATED, context);
458 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT ||
460 org::xrpl::rpc::v1::LedgerSpecifier::
461 SHORTCUT_UNSPECIFIED)
463 return getLedger(ledger, LedgerShortcut::CURRENT, context);
467 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED)
469 return getLedger(ledger, LedgerShortcut::CLOSED, context);
483 if (ledger ==
nullptr)
493 if (ledger ==
nullptr)
498 if (cur->info().seq == ledgerIndex)
504 if (ledger ==
nullptr)
533 if (shortcut == LedgerShortcut::VALIDATED)
536 if (ledger ==
nullptr)
543 assert(!ledger->open());
547 if (shortcut == LedgerShortcut::CURRENT)
552 "Reporting does not track current ledger"};
554 assert(ledger->open());
556 else if (shortcut == LedgerShortcut::CLOSED)
562 assert(!ledger->open());
569 if (ledger ==
nullptr)
576 static auto const minSequenceGap = 10;
578 if (ledger->info().seq + minSequenceGap <
627 if (!hash || ledger.
info().
hash != *hash)
632 assert(hash->isNonZero());
647 JLOG(stream) <<
"Ledger #" << seq <<
": " << mn.
what();
684 auto& info = ledger->info();
688 result[jss::ledger_hash] =
to_string(info.hash);
689 result[jss::ledger_index] = info.seq;
693 result[jss::ledger_current_index] = info.seq;
696 result[jss::validated] =
705 if (
auto status =
lookupLedger(ledger, context, result))
706 status.inject(result);
715 for (
auto const& jv : jvArray)
719 auto const id = parseBase58<AccountID>(jv.asString());
736 Blob const b(hash.begin(), hash.end());
738 boost::to_lower(md5);
742 jv[jss::urlgravatar] =
743 str(boost::format(
"http://www.gravatar.com/avatar/%s") % md5);
748 jv[jss::Invalid] =
true;
758 limit =
range.rdefault;
759 if (
auto const& jvLimit = context.
params[jss::limit])
761 if (!(jvLimit.isUInt() || (jvLimit.isInt() && jvLimit.asInt() >= 0)))
764 limit = jvLimit.asUInt();
782 if (result.size() == 18 &&
793 using string_to_seed_t =
797 static seed_match_t
const seedTypes[]{
798 {jss::passphrase.c_str(),
801 [](
std::string const& s) {
return parseBase58<Seed>(s); }},
810 seed_match_t
const* seedType =
nullptr;
812 for (
auto const& t : seedTypes)
824 "Exactly one of the following must be specified: " +
831 auto const& param = params[seedType->first];
832 if (!param.isString())
838 auto const fieldContents = param.asString();
853 unsigned int apiVersion)
855 bool const has_key_type = params.
isMember(jss::key_type);
858 static char const*
const secretTypes[]{
859 jss::passphrase.c_str(),
862 jss::seed_hex.c_str()};
865 char const* secretType =
nullptr;
867 for (
auto t : secretTypes)
876 if (count == 0 || secretType ==
nullptr)
885 "Exactly one of the following must be specified: " +
897 if (!params[jss::key_type].isString())
916 if (strcmp(secretType, jss::secret.c_str()) == 0)
919 "The secret field is not allowed if " +
930 if (strcmp(secretType, jss::seed_hex.c_str()) != 0)
941 rpcBAD_SEED,
"Specified seed is for an Ed25519 wallet.");
958 if (!params[jss::secret].isString())
980 LogicError(
"keypairForSignature: invalid key type");
1011 {jss::xchain_owned_create_account_claim_id,
1013 {jss::did,
ltDID}}};
1015 auto const& p = params[jss::type];
1024 auto const filter = p.asString();
1026 types.begin(), types.end(), [&filter](decltype(types.front())& t) {
1027 return t.first == filter;
1029 if (iter == types.end())
1036 result.second = iter->second;
1056 requestedVersion = jv.
get(jss::api_version, requestedVersion);
1058 if (!(requestedVersion.
isInt() || requestedVersion.
isUInt()) ||
1059 requestedVersion < minVersion || requestedVersion > maxVersion)
1061 requestedVersion = invalidVersion;
1063 return requestedVersion.
asUInt();
1073 auto const hasIndex = context.
params.
isMember(jss::ledger_index);
1079 if ((hasHash && hasIndex) || !(hasHash || hasIndex))
1082 "Exactly one of ledger_hash and ledger_index can be set.");
1089 auto const& jsonHash = context.
params[jss::ledger_hash];
1090 if (!jsonHash.isString() || !ledgerHash.
parseHex(jsonHash.asString()))
1095 auto const& jsonIndex = context.
params[jss::ledger_index];
1096 if (!jsonIndex.isInt())
1108 ledgerIndex = jsonIndex.asInt();
1111 if (ledgerIndex >= ledger->info().seq)
1113 if (ledgerIndex <= 0)
1116 auto const j = context.
app.
journal(
"RPCHandler");
1119 auto neededHash =
hashOfSeq(*ledger, ledgerIndex, j);
1125 auto refHash =
hashOfSeq(*ledger, refIndex, j);
1139 "acquiring ledger containing requested index");
1140 jvResult[jss::acquiring] =
1149 "acquiring ledger containing requested index");
1150 jvResult[jss::acquiring] = il->getJson(0);
1158 neededHash =
hashOfSeq(*ledger, ledgerIndex, j);
1161 ledgerHash = neededHash ? *neededHash : beast::zero;
1177 return il->getJson(0);
1180 rpcNOT_READY,
"findCreate failed to return an inbound ledger");
1187 if (params.
isMember(jss::sync_mode))
1190 if (syncMode ==
"async")
1192 else if (syncMode ==
"wait")
1194 else if (syncMode !=
"sync")
1197 "sync_mode parameter must be one of \"sync\", \"async\", or "
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
constexpr unsigned int apiInvalidVersion
API version numbers used in later API versions.
const SF_UINT64 sfIndexNext
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
constexpr unsigned int apiVersionIfUnspecified
@ ledgerMaster
ledger master data for signing
@ ltTICKET
A ledger object which describes a ticket.
SubmitSync
Possible values for defining synchronous behavior of the transaction submission API.
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
A pair of SHAMap key and LedgerEntryType.
Json::Value getJson(JsonOptions options) const override
const beast::SemanticVersion firstVersion("1.0.0")
API version numbers used in API version 1.
const beast::SemanticVersion goodVersion("1.0.0")
Json::Value rpcError(int iError)
@ ltANY
A special type, matching any ledger entry type.
const SF_UINT64 sfOwnerNode
const SF_ACCOUNT sfDestination
@ ltLEDGER_HASHES
A ledger object that contains a list of ledger hashes.
An immutable linear range of bytes.
@ arrayValue
array value (ordered list)
void injectSLE(Json::Value &jv, SLE const &sle)
Inject JSON describing ledger entry.
bool getAccountObjects(ReadView const &ledger, AccountID const &account, std::optional< std::vector< LedgerEntryType >> const &typeFilter, uint256 dirIndex, uint256 entryIndex, std::uint32_t const limit, Json::Value &jvResult)
Gathers all objects for an account in a ledger.
LedgerIndex getValidLedgerIndex()
Resource::Charge & loadType
Value get(UInt index, const Value &defaultValue) const
If the array contains at least index+1 elements, returns the element value, otherwise returns default...
std::optional< KeyType > keyTypeFromString(std::string const &s)
unsigned int getAPIVersionNumber(Json::Value const &jv, bool betaEnabled)
Retrieve the api version number from the json value.
Unexpected(E(&)[N]) -> Unexpected< E const * >
@ ltSIGNER_LIST
A ledger object which contains a signer list for an account.
LedgerMaster & ledgerMaster
std::string decodeBase58Token(std::string const &s, TokenType type)
Decode a token of given type encoded using Base58Check and the XRPL alphabet.
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
std::optional< Json::Value > readLimitField(unsigned int &limit, Tuning::LimitRange const &range, JsonContext const &context)
Retrieve the limit value from a JsonContext, or set a default - then restrict the limit by max and mi...
uint128 getFieldH128(SField const &field) const
std::shared_ptr< Ledger const > getLedgerByHash(uint256 const &hash)
A Semantic Version number.
@ ltCHECK
A ledger object which describes a check.
@ ltFEE_SETTINGS
The ledger object which lists the network's fee settings.
static std::optional< base_uint > fromVoidChecked(T const &from)
std::variant< std::shared_ptr< Ledger const >, Json::Value > getLedgerByContext(RPC::JsonContext &context)
Return a ledger based on ledger_hash or ledger_index, or an RPC error.
constexpr unsigned int apiBetaVersion
@ rpcREPORTING_UNSUPPORTED
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::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
Json::Value expected_field_error(std::string const &name, std::string const &type)
virtual InboundLedgers & getInboundLedgers()=0
constexpr static std::size_t size()
@ ltDIR_NODE
A ledger object which contains a list of object identifiers.
constexpr uint256 pageMask(std::string_view("0000000000000000000000000000000000000000ffffffffffffffffffffffff"))
Json::Value missing_field_error(std::string const &name)
const SF_VECTOR256 sfIndexes
const SF_UINT64 sfLowNode
std::pair< PublicKey, SecretKey > keypairForSignature(Json::Value const ¶ms, Json::Value &error, unsigned int apiVersion)
@ ltAMENDMENTS
The ledger object which lists details about amendments on the network.
const SF_AMOUNT sfLowLimit
Keylet nftpage_min(AccountID const &owner)
NFT page keylets.
std::optional< Seed > parseRippleLibSeed(Json::Value const &value)
@ ltOFFER
A ledger object which describes an offer on the DEX.
@ objectValue
object value (collection of name/value pairs).
bool contains_error(Json::Value const &json)
Returns true if the json contains an rpc error specification.
error_code_i accountFromStringWithCode(AccountID &result, std::string const &strIdent, bool bStrict)
Decode account ID from string.
virtual LedgerMaster & getLedgerMaster()=0
virtual std::shared_ptr< Ledger const > acquire(uint256 const &hash, std::uint32_t seq, InboundLedger::Reason)=0
@ ltESCROW
A ledger object describing a single escrow.
@ ltDID
The ledger object which tracks the DID.
virtual uint256 getHashByIndex(LedgerIndex ledgerIndex)=0
getHashByIndex Returns the hash of the ledger with the given sequence.
virtual Config & config()=0
@ ltNFTOKEN_OFFER
A ledger object which identifies an offer to buy or sell an NFT.
Keylet page(uint256 const &key, std::uint64_t index) noexcept
A page in a directory.
AccountID calcAccountID(PublicKey const &pk)
virtual RelationalDatabase & getRelationalDatabase()=0
@ ltDEPOSIT_PREAUTH
A ledger object which describes a deposit preauthorization.
Keylet nftpage_max(AccountID const &owner)
A keylet for the owner's last possible NFT page.
std::optional< uint256 > hashOfSeq(ReadView const &ledger, LedgerIndex seq, beast::Journal journal)
Return the hash of a ledger by sequence.
std::shared_ptr< Ledger const > getLedgerBySeq(std::uint32_t index)
bool isMember(const char *key) const
Return true if the object has a member named key.
const SF_AMOUNT sfHighLimit
virtual std::optional< key_type > succ(key_type const &key, std::optional< key_type > const &last=std::nullopt) const =0
Return the key of the next state item.
std::optional< Seed > parseGenericSeed(std::string const &str, bool rfc1751)
Attempt to parse a string as a seed.
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
LedgerEntryType getType() const
std::shared_ptr< ReadView const > getCurrentLedger()
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
Status represents the results of an operation that might fail.
bool isUnlimited(Role const &role)
ADMIN and IDENTIFIED roles shall have unlimited resources.
const SF_UINT128 sfEmailHash
Status
Return codes from Backend operations.
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
std::shared_ptr< Ledger const > getClosedLedger()
std::string invalid_field_message(std::string const &name)
@ ltNFTOKEN_PAGE
A ledger object which contains a list of NFTs.
constexpr unsigned int apiMinimumSupportedVersion
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
virtual beast::Journal journal(std::string const &name)=0
bool isValidated(LedgerMaster &ledgerMaster, ReadView const &ledger, Application &app)
@ ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID
A claim id for a cross chain create account transaction.
Status getLedger(T &ledger, uint256 const &ledgerHash, Context &context)
Get ledger by hash If there is no error in the return value, the ledger pointer will have been filled...
Seeds are used to generate deterministic secret keys.
LedgerEntryType
Identifiers for on-ledger objects.
@ ltBRIDGE
The ledger object which lists details about sidechains.
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
std::pair< RPC::Status, LedgerEntryType > chooseLedgerEntryType(Json::Value const ¶ms)
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
@ ltACCOUNT_ROOT
A ledger object which describes an account.
bool isFieldPresent(SField const &field) const
std::uint64_t getStartHint(std::shared_ptr< SLE const > const &sle, AccountID const &accountID)
Gets the start hint for traversing account objects.
std::optional< Seed > getSeedFromRPC(Json::Value const ¶ms, Json::Value &error)
ripple::Expected< RPC::SubmitSync, Json::Value > getSubmitSyncMode(Json::Value const ¶ms)
Helper to parse submit_mode parameter to RPC submit.
constexpr unsigned int apiMaximumSupportedVersion
std::shared_ptr< Ledger const > getValidatedLedger()
Status ledgerFromSpecifier(T &ledger, org::xrpl::rpc::v1::LedgerSpecifier const &specifier, Context &context)
const SF_UINT256 sfNextPageMin
@ ltXCHAIN_OWNED_CLAIM_ID
A claim id for a cross chain transaction.
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
const SF_ACCOUNT sfAccount
@ ltRIPPLE_STATE
A ledger object which describes a bidirectional trust line.
std::string strHex(FwdIt begin, FwdIt end)
hash_set< AccountID > parseAccountIds(Json::Value const &jvArray)
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
LedgerIndex getCandidateLedger(LedgerIndex requested)
Find a ledger index from which we could easily get the requested ledger.
Represents RPC limit parameter values that have a min, default and max.
static Keylet signers(AccountID const &account, std::uint32_t page) noexcept
Json::Value make_param_error(std::string const &message)
Returns a new json object that indicates invalid parameters.
std::optional< AccountID > accountFromStringStrict(std::string const &account)
Get an AccountID from an account ID or public key.
virtual bool open() const =0
Returns true if this reflects an open ledger.
const beast::SemanticVersion lastVersion("1.0.0")
Json::Value invalid_field_error(std::string const &name)
const SF_UINT64 sfHighNode
The context of information needed to call an RPC.
Status ledgerFromRequest(T &ledger, GRPCContext< R > &context)
const Charge feeHighBurdenRPC
@ ltAMM
The ledger object which tracks the AMM.
Json::Value accountFromString(AccountID &result, std::string const &strIdent, bool bStrict)
Json::Value make_error(error_code_i code)
Returns a new json object that reflects the error code.
constexpr auto maxValidatedLedgerAge
bool isRelatedToAccount(ReadView const &ledger, std::shared_ptr< SLE const > const &sle, AccountID const &accountID)
Tests if a SLE is owned by accountID.
@ ltPAYCHAN
A ledger object describing a single unidirectional XRP payment channel.
virtual std::shared_ptr< InboundLedger > find(LedgerHash const &hash)=0
std::string asString() const
Returns the unquoted string value.
Number root(Number f, unsigned d)