20 #include <ripple/app/ledger/LedgerMaster.h>
21 #include <ripple/app/ledger/OpenLedger.h>
22 #include <ripple/app/misc/Transaction.h>
23 #include <ripple/ledger/View.h>
24 #include <ripple/net/RPCErr.h>
25 #include <ripple/protocol/AccountID.h>
26 #include <ripple/protocol/Feature.h>
27 #include <ripple/rpc/Context.h>
28 #include <ripple/rpc/DeliveredAmount.h>
29 #include <ripple/rpc/impl/RPCHelpers.h>
30 #include <boost/algorithm/string/case_conv.hpp>
32 #include <ripple/rpc/impl/GRPCHelpers.h>
37 boost::optional<AccountID>
40 boost::optional<AccountID> result;
42 auto const publicKey =
48 result = parseBase58<AccountID>(account);
121 auto const& entries = dir->getFieldV256(
sfIndexes);
122 auto iter = entries.begin();
126 iter =
std::find(iter, entries.end(), entryIndex);
127 if (iter == entries.end())
133 for (; iter != entries.end(); ++iter)
137 auto typeMatchesFilter =
141 typeFilter.
begin(), typeFilter.
end(), ledgerType);
142 return it != typeFilter.
end();
145 if (!typeFilter.has_value() ||
146 typeMatchesFilter(typeFilter.value(), sleNode->getType()))
152 if (++iter != entries.end())
154 jvResult[jss::limit] = limit;
155 jvResult[jss::marker] =
165 auto const nodeIndex = dir->getFieldU64(
sfIndexNext);
176 auto const& e = dir->getFieldV256(
sfIndexes);
179 jvResult[jss::limit] = limit;
180 jvResult[jss::marker] =
192 isValidatedOld(
LedgerMaster& ledgerMaster,
bool standalone)
206 auto& params = context.params;
208 auto indexValue = params[jss::ledger_index];
209 auto hashValue = params[jss::ledger_hash];
212 auto& legacyLedger = params[jss::ledger];
215 if (legacyLedger.asString().size() > 12)
216 hashValue = legacyLedger;
218 indexValue = legacyLedger;
223 if (!hashValue.isString())
227 if (!ledgerHash.SetHex(hashValue.asString()))
229 return getLedger(ledger, ledgerHash, context);
231 else if (indexValue.isNumeric())
233 return getLedger(ledger, indexValue.asInt(), context);
237 auto const index = indexValue.asString();
238 if (index ==
"validated")
240 return getLedger(ledger, LedgerShortcut::VALIDATED, context);
244 if (index.empty() || index ==
"current")
245 return getLedger(ledger, LedgerShortcut::CURRENT, context);
246 else if (index ==
"closed")
247 return getLedger(ledger, LedgerShortcut::CLOSED, context);
267 org::xrpl::rpc::v1::GetAccountInfoRequest& request = context.
params;
269 using LedgerCase = org::xrpl::rpc::v1::LedgerSpecifier::LedgerCase;
270 LedgerCase ledgerCase = request.ledger().ledger_case();
273 case LedgerCase::kHash: {
276 return getLedger(ledger, ledgerHash, context);
278 case LedgerCase::kSequence:
279 return getLedger(ledger, request.ledger().sequence(), context);
280 case LedgerCase::kShortcut:
282 case LedgerCase::LEDGER_NOT_SET: {
283 auto const shortcut = request.ledger().shortcut();
285 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED)
286 return getLedger(ledger, LedgerShortcut::VALIDATED, context);
291 org::xrpl::rpc::v1::LedgerSpecifier::
292 SHORTCUT_UNSPECIFIED ||
294 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT)
296 return getLedger(ledger, LedgerShortcut::CURRENT, context);
300 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED)
302 return getLedger(ledger, LedgerShortcut::CLOSED, context);
315 GRPCContext<org::xrpl::rpc::v1::GetAccountInfoRequest>&);
324 if (ledger ==
nullptr)
334 if (ledger ==
nullptr)
337 if (cur->info().seq == ledgerIndex)
343 if (ledger ==
nullptr)
369 if (shortcut == LedgerShortcut::VALIDATED)
372 if (ledger ==
nullptr)
379 assert(!ledger->open());
383 if (shortcut == LedgerShortcut::CURRENT)
386 assert(ledger->open());
388 else if (shortcut == LedgerShortcut::CLOSED)
391 assert(!ledger->open());
398 if (ledger ==
nullptr)
405 static auto const minSequenceGap = 10;
407 if (ledger->info().seq + minSequenceGap <
450 if (!hash || ledger.
info().
hash != *hash)
455 assert(hash->isNonZero());
469 JLOG(stream) <<
"Ledger #" << seq <<
": " << mn.
what();
506 auto& info = ledger->info();
510 result[jss::ledger_hash] =
to_string(info.hash);
511 result[jss::ledger_index] = info.seq;
515 result[jss::ledger_current_index] = info.seq;
518 result[jss::validated] =
527 if (
auto status =
lookupLedger(ledger, context, result))
528 status.inject(result);
537 for (
auto const& jv : jvArray)
541 auto const id = parseBase58<AccountID>(jv.asString());
558 Blob const b(hash.begin(), hash.end());
560 boost::to_lower(md5);
564 jv[jss::urlgravatar] =
565 str(boost::format(
"http://www.gravatar.com/avatar/%s") % md5);
570 jv[jss::Invalid] =
true;
574 boost::optional<Json::Value>
580 limit =
range.rdefault;
581 if (
auto const& jvLimit = context.
params[jss::limit])
583 if (!(jvLimit.isUInt() || (jvLimit.isInt() && jvLimit.asInt() >= 0)))
586 limit = jvLimit.asUInt();
593 boost::optional<Seed>
604 if (result.size() == 18 &&
612 boost::optional<Seed>
616 static char const*
const seedTypes[]{
617 jss::passphrase.c_str(), jss::seed.c_str(), jss::seed_hex.c_str()};
620 char const* seedType =
nullptr;
622 for (
auto t : seedTypes)
634 "Exactly one of the following must be specified: " +
641 if (!params[seedType].isString())
647 auto const fieldContents = params[seedType].
asString();
650 boost::optional<Seed> seed;
652 if (seedType == jss::seed.c_str())
653 seed = parseBase58<Seed>(fieldContents);
654 else if (seedType == jss::passphrase.c_str())
656 else if (seedType == jss::seed_hex.c_str())
673 bool const has_key_type = params.
isMember(jss::key_type);
677 static char const*
const secretTypes[]{
678 jss::passphrase.c_str(),
681 jss::seed_hex.c_str()};
684 char const* secretType =
nullptr;
686 for (
auto t : secretTypes)
695 if (count == 0 || secretType ==
nullptr)
704 "Exactly one of the following must be specified: " +
711 boost::optional<KeyType> keyType;
712 boost::optional<Seed> seed;
716 if (!params[jss::key_type].isString())
730 if (secretType == jss::secret.c_str())
733 "The secret field is not allowed if " +
742 if (secretType != jss::seed_hex.c_str())
753 rpcBAD_SEED,
"Specified seed is for an Ed25519 wallet.");
770 if (!params[jss::secret].isString())
792 LogicError(
"keypairForSignature: invalid key type");
819 auto const& p = params[jss::type];
828 auto const filter = p.asString();
830 types.begin(), types.end(), [&filter](decltype(types.front())& t) {
831 return t.first == filter;
833 if (iter == types.end())
840 result.second = iter->second;
859 requestedVersion = jv.
get(jss::api_version, requestedVersion);
861 if (!(requestedVersion.
isInt() || requestedVersion.
isUInt()) ||
862 requestedVersion < minVersion || requestedVersion > maxVersion)
864 requestedVersion = invalidVersion;
866 return requestedVersion.
asUInt();
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Status getLedger(std::shared_ptr< ReadView const > &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...
@ ledgerMaster
ledger master data for signing
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)
const SF_U64 sfIndexNext(access, STI_UINT64, 1, "IndexNext")
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")
unsigned int getAPIVersionNumber(Json::Value const &jv)
Retrieve the api version number from the json value.
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...
boost::optional< Seed > parseRippleLibSeed(Json::Value const &value)
boost::optional< AccountID > deprecatedParseBitcoinAccountID(std::string const &s)
LedgerMaster & ledgerMaster
bool getAccountObjects(ReadView const &ledger, AccountID const &account, boost::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.
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
uint128 getFieldH128(SField const &field) const
std::shared_ptr< Ledger const > getLedgerByHash(uint256 const &hash)
constexpr unsigned int APIVersionIfUnspecified
A Semantic Version number.
std::string to_string(ListDisposition disposition)
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()
uint256 getHashByIndex(std::uint32_t ledgerIndex, Application &app)
Json::Value missing_field_error(std::string const &name)
boost::optional< KeyType > keyTypeFromString(std::string const &s)
boost::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...
constexpr unsigned int ApiMinimumSupportedVersion
@ 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 Config & config()=0
Keylet page(uint256 const &key, std::uint64_t index) noexcept
A page in a directory.
AccountID calcAccountID(PublicKey const &pk)
std::shared_ptr< Ledger const > getValidatedLedger()
constexpr unsigned int ApiMaximumSupportedVersion
boost::optional< AccountID > accountFromStringStrict(std::string const &account)
Get an AccountID from an account ID or public key.
boost::optional< Seed > parseGenericSeed(std::string const &str)
Attempt to parse a string as a seed.
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_Vec256 sfIndexes(access, STI_VECTOR256, 1, "Indexes", SField::sMD_Never)
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
LedgerEntryType getType() const
Json::Value rpcError(int iError, Json::Value jvResult)
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.
constexpr unsigned int APIInvalidVersion
API version numbers used in later API versions.
bool SetHexExact(const char *psz)
Parse a hex string into a base_uint The string must contain exactly bytes * 2 hex characters and must...
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)
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)
Seeds are used to generate deterministic secret keys.
LedgerEntryType
Ledger entry types.
std::pair< RPC::Status, LedgerEntryType > chooseLedgerEntryType(Json::Value const ¶ms)
static std::string decodeBase58Token(std::string const &s, TokenType type, InverseArray const &inv)
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
bool isFieldPresent(SField const &field) const
static base_uint fromVoid(void const *data)
std::pair< PublicKey, SecretKey > keypairForSignature(Json::Value const ¶ms, Json::Value &error)
std::string strHex(FwdIt begin, FwdIt end)
@ ltDIR_NODE
Directory node.
hash_set< AccountID > parseAccountIds(Json::Value const &jvArray)
Represents RPC limit parameter values that have a min, default and max.
Json::Value make_param_error(std::string const &message)
Returns a new json object that indicates invalid parameters.
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)
The context of information needed to call an RPC.
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
const SF_U128 sfEmailHash(access, STI_HASH128, 1, "EmailHash")
boost::optional< Seed > getSeedFromRPC(Json::Value const ¶ms, Json::Value &error)
std::string asString() const
Returns the unquoted string value.
Status ledgerFromRequest(T &ledger, GRPCContext< org::xrpl::rpc::v1::GetAccountInfoRequest > &context)