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/rpc/Context.h>
32 #include <ripple/rpc/DeliveredAmount.h>
33 #include <ripple/rpc/impl/RPCHelpers.h>
34 #include <boost/algorithm/string/case_conv.hpp>
36 #include <ripple/resource/Fees.h>
46 auto const publicKey =
52 result = parseBase58<AccountID>(account);
100 if (sle->getFieldAmount(
sfLowLimit).getIssuer() == accountID)
102 else if (sle->getFieldAmount(
sfHighLimit).getIssuer() == accountID)
120 return (sle->getFieldAmount(
sfLowLimit).getIssuer() == accountID) ||
121 (sle->getFieldAmount(
sfHighLimit).getIssuer() == accountID);
131 return sle->getAccountID(
sfAccount) == accountID ||
138 return sle->key() == accountSignerList.
key;
144 return sle->getAccountID(
sfOwner) == accountID;
177 auto const& entries = dir->getFieldV256(
sfIndexes);
178 auto iter = entries.begin();
182 iter =
std::find(iter, entries.end(), entryIndex);
183 if (iter == entries.end())
189 for (; iter != entries.end(); ++iter)
193 auto typeMatchesFilter =
197 typeFilter.
begin(), typeFilter.
end(), ledgerType);
198 return it != typeFilter.
end();
201 if (!typeFilter.has_value() ||
202 typeMatchesFilter(typeFilter.value(), sleNode->getType()))
209 if (++iter != entries.end())
211 jvResult[jss::limit] = limit;
212 jvResult[jss::marker] =
221 auto const nodeIndex = dir->getFieldU64(
sfIndexNext);
232 auto const& e = dir->getFieldV256(
sfIndexes);
235 jvResult[jss::limit] = limit;
236 jvResult[jss::marker] =
248 isValidatedOld(
LedgerMaster& ledgerMaster,
bool standaloneOrReporting)
250 if (standaloneOrReporting)
262 auto& params = context.params;
264 auto indexValue = params[jss::ledger_index];
265 auto hashValue = params[jss::ledger_hash];
268 auto& legacyLedger = params[jss::ledger];
271 if (legacyLedger.asString().size() > 12)
272 hashValue = legacyLedger;
274 indexValue = legacyLedger;
279 if (!hashValue.isString())
283 if (!ledgerHash.parseHex(hashValue.asString()))
285 return getLedger(ledger, ledgerHash, context);
288 auto const index = indexValue.asString();
290 if (index ==
"current" ||
291 (index.empty() && !context.app.config().reporting()))
292 return getLedger(ledger, LedgerShortcut::CURRENT, context);
294 if (index ==
"validated" ||
295 (index.empty() && context.app.config().reporting()))
296 return getLedger(ledger, LedgerShortcut::VALIDATED, context);
298 if (index ==
"closed")
299 return getLedger(ledger, LedgerShortcut::CLOSED, context);
309 template <
class T,
class R>
313 R& request = context.
params;
321 GRPCContext<org::xrpl::rpc::v1::GetLedgerEntryRequest>&);
327 GRPCContext<org::xrpl::rpc::v1::GetLedgerDataRequest>&);
333 GRPCContext<org::xrpl::rpc::v1::GetLedgerRequest>&);
339 org::xrpl::rpc::v1::LedgerSpecifier
const& specifier,
344 using LedgerCase = org::xrpl::rpc::v1::LedgerSpecifier::LedgerCase;
345 LedgerCase ledgerCase = specifier.ledger_case();
348 case LedgerCase::kHash: {
351 return getLedger(ledger, *hash, context);
355 case LedgerCase::kSequence:
356 return getLedger(ledger, specifier.sequence(), context);
357 case LedgerCase::kShortcut:
359 case LedgerCase::LEDGER_NOT_SET: {
360 auto const shortcut = specifier.shortcut();
363 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED ||
365 org::xrpl::rpc::v1::LedgerSpecifier::
366 SHORTCUT_UNSPECIFIED &&
369 return getLedger(ledger, LedgerShortcut::VALIDATED, context);
374 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT ||
376 org::xrpl::rpc::v1::LedgerSpecifier::
377 SHORTCUT_UNSPECIFIED)
379 return getLedger(ledger, LedgerShortcut::CURRENT, context);
383 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED)
385 return getLedger(ledger, LedgerShortcut::CLOSED, context);
399 if (ledger ==
nullptr)
409 if (ledger ==
nullptr)
414 if (cur->info().seq == ledgerIndex)
420 if (ledger ==
nullptr)
449 if (shortcut == LedgerShortcut::VALIDATED)
452 if (ledger ==
nullptr)
459 assert(!ledger->open());
463 if (shortcut == LedgerShortcut::CURRENT)
468 "Reporting does not track current ledger"};
470 assert(ledger->open());
472 else if (shortcut == LedgerShortcut::CLOSED)
478 assert(!ledger->open());
485 if (ledger ==
nullptr)
492 static auto const minSequenceGap = 10;
494 if (ledger->info().seq + minSequenceGap <
543 if (!hash || ledger.
info().
hash != *hash)
548 assert(hash->isNonZero());
563 JLOG(stream) <<
"Ledger #" << seq <<
": " << mn.
what();
600 auto& info = ledger->info();
604 result[jss::ledger_hash] =
to_string(info.hash);
605 result[jss::ledger_index] = info.seq;
609 result[jss::ledger_current_index] = info.seq;
612 result[jss::validated] =
621 if (
auto status =
lookupLedger(ledger, context, result))
622 status.inject(result);
631 for (
auto const& jv : jvArray)
635 auto const id = parseBase58<AccountID>(jv.asString());
652 Blob const b(hash.begin(), hash.end());
654 boost::to_lower(md5);
658 jv[jss::urlgravatar] =
659 str(boost::format(
"http://www.gravatar.com/avatar/%s") % md5);
664 jv[jss::Invalid] =
true;
674 limit =
range.rdefault;
675 if (
auto const& jvLimit = context.
params[jss::limit])
677 if (!(jvLimit.isUInt() || (jvLimit.isInt() && jvLimit.asInt() >= 0)))
680 limit = jvLimit.asUInt();
698 if (result.size() == 18 &&
709 using string_to_seed_t =
713 static seed_match_t
const seedTypes[]{
714 {jss::passphrase.c_str(),
717 [](
std::string const& s) {
return parseBase58<Seed>(s); }},
726 seed_match_t
const* seedType =
nullptr;
728 for (
auto const& t : seedTypes)
740 "Exactly one of the following must be specified: " +
747 auto const& param = params[seedType->first];
748 if (!param.isString())
754 auto const fieldContents = param.asString();
768 bool const has_key_type = params.
isMember(jss::key_type);
771 static char const*
const secretTypes[]{
772 jss::passphrase.c_str(),
775 jss::seed_hex.c_str()};
778 char const* secretType =
nullptr;
780 for (
auto t : secretTypes)
789 if (count == 0 || secretType ==
nullptr)
798 "Exactly one of the following must be specified: " +
810 if (!params[jss::key_type].isString())
826 if (strcmp(secretType, jss::secret.c_str()) == 0)
829 "The secret field is not allowed if " +
840 if (strcmp(secretType, jss::seed_hex.c_str()) != 0)
851 rpcBAD_SEED,
"Specified seed is for an Ed25519 wallet.");
868 if (!params[jss::secret].isString())
890 LogicError(
"keypairForSignature: invalid key type");
918 auto const& p = params[jss::type];
927 auto const filter = p.asString();
929 types.begin(), types.end(), [&filter](decltype(types.front())& t) {
930 return t.first == filter;
932 if (iter == types.end())
939 result.second = iter->second;
959 requestedVersion = jv.
get(jss::api_version, requestedVersion);
961 if (!(requestedVersion.
isInt() || requestedVersion.
isUInt()) ||
962 requestedVersion < minVersion || requestedVersion > maxVersion)
964 requestedVersion = invalidVersion;
966 return requestedVersion.
asUInt();
982 if ((hasHash && hasIndex) || !(hasHash || hasIndex))
985 "Exactly one of ledger_hash and ledger_index can be set.");
992 auto const& jsonHash = context.
params[jss::ledger_hash];
993 if (!jsonHash.isString() || !ledgerHash.
parseHex(jsonHash.asString()))
998 auto const& jsonIndex = context.
params[jss::ledger_index];
999 if (!jsonIndex.isInt())
1011 ledgerIndex = jsonIndex.asInt();
1014 if (ledgerIndex >= ledger->info().seq)
1016 if (ledgerIndex <= 0)
1019 auto const j = context.
app.
journal(
"RPCHandler");
1021 auto neededHash =
hashOfSeq(*ledger, ledgerIndex, j);
1026 auto refHash =
hashOfSeq(*ledger, refIndex, j);
1040 "acquiring ledger containing requested index");
1041 jvResult[jss::acquiring] =
1050 "acquiring ledger containing requested index");
1051 jvResult[jss::acquiring] = il->getJson(0);
1059 neededHash =
hashOfSeq(*ledger, ledgerIndex, j);
1062 ledgerHash = neededHash ? *neededHash : beast::zero;
1078 return il->getJson(0);
1081 rpcNOT_READY,
"findCreate failed to return an inbound ledger");
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.
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.
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.
@ 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.
Json::Value missing_field_error(std::string const &name)
const SF_VECTOR256 sfIndexes
const SF_UINT64 sfLowNode
@ ltAMENDMENTS
The ledger object which lists details about amendments on the network.
const SF_AMOUNT sfLowLimit
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.
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.
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
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)
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)
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.
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::pair< PublicKey, SecretKey > keypairForSignature(Json::Value const ¶ms, Json::Value &error)
std::optional< Seed > getSeedFromRPC(Json::Value const ¶ms, Json::Value &error)
constexpr unsigned int apiMaximumSupportedVersion
std::shared_ptr< Ledger const > getValidatedLedger()
Status ledgerFromSpecifier(T &ledger, org::xrpl::rpc::v1::LedgerSpecifier const &specifier, Context &context)
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
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
bool getAccountObjects(ReadView const &ledger, AccountID const &account, std::optional< std::vector< LedgerEntryType >> const &typeFilter, uint256 dirIndex, uint256 const &entryIndex, std::uint32_t const limit, Json::Value &jvResult)
Gathers all objects for an account in a ledger.
std::string asString() const
Returns the unquoted string value.
Number root(Number f, unsigned d)