20 #include <ripple/app/ledger/LedgerMaster.h>
21 #include <ripple/app/ledger/OpenLedger.h>
22 #include <ripple/app/misc/Transaction.h>
23 #include <ripple/app/paths/RippleState.h>
24 #include <ripple/app/rdb/RelationalDBInterface.h>
25 #include <ripple/ledger/View.h>
26 #include <ripple/net/RPCErr.h>
27 #include <ripple/protocol/AccountID.h>
28 #include <ripple/protocol/Feature.h>
29 #include <ripple/rpc/Context.h>
30 #include <ripple/rpc/DeliveredAmount.h>
31 #include <ripple/rpc/impl/RPCHelpers.h>
32 #include <boost/algorithm/string/case_conv.hpp>
34 #include <ripple/rpc/impl/GRPCHelpers.h>
44 auto const publicKey =
50 result = parseBase58<AccountID>(account);
98 if (sle->getFieldAmount(
sfLowLimit).getIssuer() == accountID)
100 else if (sle->getFieldAmount(
sfHighLimit).getIssuer() == accountID)
118 return (sle->getFieldAmount(
sfLowLimit).getIssuer() == accountID) ||
119 (sle->getFieldAmount(
sfHighLimit).getIssuer() == accountID);
123 return sle->getAccountID(
sfAccount) == accountID;
128 return sle->key() == accountSignerList.
key;
161 auto const& entries = dir->getFieldV256(
sfIndexes);
162 auto iter = entries.begin();
166 iter =
std::find(iter, entries.end(), entryIndex);
167 if (iter == entries.end())
173 for (; iter != entries.end(); ++iter)
177 auto typeMatchesFilter =
181 typeFilter.
begin(), typeFilter.
end(), ledgerType);
182 return it != typeFilter.
end();
185 if (!typeFilter.has_value() ||
186 typeMatchesFilter(typeFilter.value(), sleNode->getType()))
193 if (++iter != entries.end())
195 jvResult[jss::limit] = limit;
196 jvResult[jss::marker] =
205 auto const nodeIndex = dir->getFieldU64(
sfIndexNext);
216 auto const& e = dir->getFieldV256(
sfIndexes);
219 jvResult[jss::limit] = limit;
220 jvResult[jss::marker] =
232 isValidatedOld(
LedgerMaster& ledgerMaster,
bool standaloneOrReporting)
234 if (standaloneOrReporting)
246 auto& params = context.params;
248 auto indexValue = params[jss::ledger_index];
249 auto hashValue = params[jss::ledger_hash];
252 auto& legacyLedger = params[jss::ledger];
255 if (legacyLedger.asString().size() > 12)
256 hashValue = legacyLedger;
258 indexValue = legacyLedger;
263 if (!hashValue.isString())
267 if (!ledgerHash.parseHex(hashValue.asString()))
269 return getLedger(ledger, ledgerHash, context);
272 auto const index = indexValue.asString();
274 if (index ==
"current" ||
275 (index.empty() && !context.app.config().reporting()))
276 return getLedger(ledger, LedgerShortcut::CURRENT, context);
278 if (index ==
"validated" ||
279 (index.empty() && context.app.config().reporting()))
280 return getLedger(ledger, LedgerShortcut::VALIDATED, context);
282 if (index ==
"closed")
283 return getLedger(ledger, LedgerShortcut::CLOSED, context);
293 template <
class T,
class R>
297 R& request = context.
params;
305 GRPCContext<org::xrpl::rpc::v1::GetAccountInfoRequest>&);
311 GRPCContext<org::xrpl::rpc::v1::GetLedgerEntryRequest>&);
317 GRPCContext<org::xrpl::rpc::v1::GetLedgerDataRequest>&);
323 GRPCContext<org::xrpl::rpc::v1::GetLedgerRequest>&);
329 org::xrpl::rpc::v1::LedgerSpecifier
const& specifier,
334 using LedgerCase = org::xrpl::rpc::v1::LedgerSpecifier::LedgerCase;
335 LedgerCase ledgerCase = specifier.ledger_case();
338 case LedgerCase::kHash: {
341 return getLedger(ledger, *hash, context);
345 case LedgerCase::kSequence:
346 return getLedger(ledger, specifier.sequence(), context);
347 case LedgerCase::kShortcut:
349 case LedgerCase::LEDGER_NOT_SET: {
350 auto const shortcut = specifier.shortcut();
353 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED ||
355 org::xrpl::rpc::v1::LedgerSpecifier::
356 SHORTCUT_UNSPECIFIED &&
359 return getLedger(ledger, LedgerShortcut::VALIDATED, context);
364 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT ||
366 org::xrpl::rpc::v1::LedgerSpecifier::
367 SHORTCUT_UNSPECIFIED)
369 return getLedger(ledger, LedgerShortcut::CURRENT, context);
373 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED)
375 return getLedger(ledger, LedgerShortcut::CLOSED, context);
389 if (ledger ==
nullptr)
399 if (ledger ==
nullptr)
404 if (cur->info().seq == ledgerIndex)
410 if (ledger ==
nullptr)
439 if (shortcut == LedgerShortcut::VALIDATED)
442 if (ledger ==
nullptr)
449 assert(!ledger->open());
453 if (shortcut == LedgerShortcut::CURRENT)
458 "Reporting does not track current ledger"};
460 assert(ledger->open());
462 else if (shortcut == LedgerShortcut::CLOSED)
468 assert(!ledger->open());
475 if (ledger ==
nullptr)
482 static auto const minSequenceGap = 10;
484 if (ledger->info().seq + minSequenceGap <
533 if (!hash || ledger.
info().
hash != *hash)
538 assert(hash->isNonZero());
553 JLOG(stream) <<
"Ledger #" << seq <<
": " << mn.
what();
590 auto& info = ledger->info();
594 result[jss::ledger_hash] =
to_string(info.hash);
595 result[jss::ledger_index] = info.seq;
599 result[jss::ledger_current_index] = info.seq;
602 result[jss::validated] =
611 if (
auto status =
lookupLedger(ledger, context, result))
612 status.inject(result);
621 for (
auto const& jv : jvArray)
625 auto const id = parseBase58<AccountID>(jv.asString());
642 Blob const b(hash.begin(), hash.end());
644 boost::to_lower(md5);
648 jv[jss::urlgravatar] =
649 str(boost::format(
"http://www.gravatar.com/avatar/%s") % md5);
654 jv[jss::Invalid] =
true;
664 limit =
range.rdefault;
665 if (
auto const& jvLimit = context.
params[jss::limit])
667 if (!(jvLimit.isUInt() || (jvLimit.isInt() && jvLimit.asInt() >= 0)))
670 limit = jvLimit.asUInt();
688 if (result.size() == 18 &&
700 static char const*
const seedTypes[]{
701 jss::passphrase.c_str(), jss::seed.c_str(), jss::seed_hex.c_str()};
704 char const* seedType =
nullptr;
706 for (
auto t : seedTypes)
718 "Exactly one of the following must be specified: " +
725 if (!params[seedType].isString())
731 auto const fieldContents = params[seedType].
asString();
736 if (seedType == jss::seed.c_str())
737 seed = parseBase58<Seed>(fieldContents);
738 else if (seedType == jss::passphrase.c_str())
740 else if (seedType == jss::seed_hex.c_str())
757 bool const has_key_type = params.
isMember(jss::key_type);
761 static char const*
const secretTypes[]{
762 jss::passphrase.c_str(),
765 jss::seed_hex.c_str()};
768 char const* secretType =
nullptr;
770 for (
auto t : secretTypes)
779 if (count == 0 || secretType ==
nullptr)
788 "Exactly one of the following must be specified: " +
800 if (!params[jss::key_type].isString())
814 if (secretType == jss::secret.c_str())
817 "The secret field is not allowed if " +
826 if (secretType != jss::seed_hex.c_str())
837 rpcBAD_SEED,
"Specified seed is for an Ed25519 wallet.");
854 if (!params[jss::secret].isString())
876 LogicError(
"keypairForSignature: invalid key type");
903 auto const& p = params[jss::type];
912 auto const filter = p.asString();
914 types.begin(), types.end(), [&filter](decltype(types.front())& t) {
915 return t.first == filter;
917 if (iter == types.end())
924 result.second = iter->second;
944 requestedVersion = jv.
get(jss::api_version, requestedVersion);
946 if (!(requestedVersion.
isInt() || requestedVersion.
isUInt()) ||
947 requestedVersion < minVersion || requestedVersion > maxVersion)
949 requestedVersion = invalidVersion;
951 return requestedVersion.
asUInt();
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")
std::optional< Seed > parseGenericSeed(std::string const &str)
Attempt to parse a string as a seed.
Json::Value rpcError(int iError)
@ ltANY
A special type, matching any ledger entry type.
const SF_UINT64 sfOwnerNode
@ 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()
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.
virtual RelationalDBInterface & getRelationalDBInterface()=0
@ 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
const SF_HASH128 sfEmailHash
std::shared_ptr< Ledger const > getLedgerByHash(uint256 const &hash)
virtual uint256 getHashByIndex(LedgerIndex ledgerIndex)=0
getHashByIndex Returns hash of ledger with given sequence.
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)
constexpr unsigned int apiBetaVersion
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)
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.
bool isOwnedByAccount(ReadView const &ledger, std::shared_ptr< SLE const > const &sle, AccountID const &accountID)
Tests if a SLE is owned by accountID.
@ ltESCROW
A ledger object describing a single escrow.
virtual Config & config()=0
Keylet page(uint256 const &key, std::uint64_t index) noexcept
A page in a directory.
AccountID calcAccountID(PublicKey const &pk)
@ ltDEPOSIT_PREAUTH
A ledger object which describes a deposit preauthorization.
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
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.
Status
Return codes from Backend operations.
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.
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)
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
@ ltPAYCHAN
A ledger object describing a single unidirectional XRP payment channel.
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.