1#include <xrpld/app/ledger/LedgerMaster.h>
2#include <xrpld/app/ledger/LedgerToJson.h>
3#include <xrpld/app/ledger/OpenLedger.h>
4#include <xrpld/app/main/Application.h>
5#include <xrpld/rpc/detail/RPCLedgerHelpers.h>
7#include <xrpl/protocol/RPCErr.h>
9#include <boost/algorithm/string/case_conv.hpp>
17isValidatedOld(LedgerMaster&
ledgerMaster,
bool standalone)
30 Context
const& context,
34 if (!ledgerHash.parseHex(hash.
asString()))
37 return getLedger(ledger, ledgerHash, context);
45 Context
const& context,
48 auto const index = indexValue.
asString();
50 if (index ==
"current" || index.empty())
51 return getLedger(ledger, LedgerShortcut::Current, context);
53 if (index ==
"validated")
54 return getLedger(ledger, LedgerShortcut::Validated, context);
56 if (index ==
"closed")
57 return getLedger(ledger, LedgerShortcut::Closed, context);
74 auto& params = context.params;
75 auto const hasLedger = context.params.isMember(jss::ledger);
76 auto const hasHash = context.params.isMember(jss::ledger_hash);
77 auto const hasIndex = context.params.isMember(jss::ledger_index);
79 if ((hasLedger + hasHash + hasIndex) > 1)
86 "Exactly one of 'ledger', 'ledger_hash', or "
87 "'ledger_index' can be specified."};
90 "Exactly one of 'ledger_hash' or "
91 "'ledger_index' can be specified."};
97 auto& legacyLedger = params[jss::ledger];
98 if (!legacyLedger.isString() && !legacyLedger.isUInt() &&
99 !legacyLedger.isInt())
105 if (legacyLedger.isString() && legacyLedger.asString().size() == 64)
106 return ledgerFromHash(ledger, legacyLedger, context, jss::ledger);
108 return ledgerFromIndex(ledger, legacyLedger, context, jss::ledger);
113 auto const& ledgerHash = params[jss::ledger_hash];
114 if (!ledgerHash.isString())
118 return ledgerFromHash(ledger, ledgerHash, context, jss::ledger_hash);
123 auto const& ledgerIndex = params[jss::ledger_index];
124 if (!ledgerIndex.isString() && !ledgerIndex.isUInt() &&
125 !ledgerIndex.isInt())
131 return ledgerFromIndex(ledger, ledgerIndex, context, jss::ledger_index);
135 return getLedger(ledger, LedgerShortcut::Current, context);
139template <
class T,
class R>
143 R
const& request = context.
params;
169 org::xrpl::rpc::v1::LedgerSpecifier
const& specifier,
174 using LedgerCase = org::xrpl::rpc::v1::LedgerSpecifier::LedgerCase;
175 LedgerCase ledgerCase = specifier.ledger_case();
178 case LedgerCase::kHash: {
181 return getLedger(ledger, *hash, context);
185 case LedgerCase::kSequence:
186 return getLedger(ledger, specifier.sequence(), context);
187 case LedgerCase::kShortcut:
189 case LedgerCase::LEDGER_NOT_SET: {
190 auto const shortcut = specifier.shortcut();
192 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED)
194 return getLedger(ledger, LedgerShortcut::Validated, context);
199 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT ||
201 org::xrpl::rpc::v1::LedgerSpecifier::
202 SHORTCUT_UNSPECIFIED)
204 return getLedger(ledger, LedgerShortcut::Current, context);
208 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED)
210 return getLedger(ledger, LedgerShortcut::Closed, context);
224 if (ledger ==
nullptr)
234 if (ledger ==
nullptr)
237 if (cur->header().seq == ledgerIndex)
243 if (ledger ==
nullptr)
269 if (shortcut == LedgerShortcut::Validated)
272 if (ledger ==
nullptr)
280 !ledger->open(),
"xrpl::RPC::getLedger : validated is not open");
284 if (shortcut == LedgerShortcut::Current)
288 ledger->open(),
"xrpl::RPC::getLedger : current is open");
290 else if (shortcut == LedgerShortcut::Closed)
294 !ledger->open(),
"xrpl::RPC::getLedger : closed is not open");
301 if (ledger ==
nullptr)
308 static auto const minSequenceGap = 10;
310 if (ledger->header().seq + minSequenceGap <
363 auto& info = ledger->header();
367 result[jss::ledger_hash] =
to_string(info.hash);
368 result[jss::ledger_index] = info.seq;
372 result[jss::ledger_current_index] = info.seq;
385 if (
auto status =
lookupLedger(ledger, context, result))
386 status.inject(result);
401 if ((hasHash + hasIndex) != 1)
405 "'ledger_index' can be specified."));
410 auto const& jsonHash =
412 if (!jsonHash.isString() || !ledgerHash.
parseHex(jsonHash.asString()))
418 auto const& jsonIndex =
420 if (!jsonIndex.isInt() && !jsonIndex.isUInt())
433 ledgerIndex = jsonIndex.asInt();
436 if (ledgerIndex >= ledger->header().seq)
438 if (ledgerIndex <= 0)
441 auto const j = context.
app.
journal(
"RPCHandler");
444 auto neededHash =
hashOfSeq(*ledger, ledgerIndex, j);
450 auto refHash =
hashOfSeq(*ledger, refIndex, j);
452 refHash,
"xrpl::RPC::getOrAcquireLedger : nonzero ledger hash");
465 "acquiring ledger containing requested index");
466 jvResult[jss::acquiring] =
475 "acquiring ledger containing requested index");
476 jvResult[jss::acquiring] = il->getJson(0);
484 neededHash =
hashOfSeq(*ledger, ledgerIndex, j);
487 neededHash,
"xrpl::RPC::getOrAcquireLedger : nonzero needed hash");
488 ledgerHash = neededHash ? *neededHash : beast::zero;
507 rpcNOT_READY,
"findCreate failed to return an inbound ledger"));
Lightweight wrapper to tag static string.
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...
virtual Config & config()=0
virtual InboundLedgers & getInboundLedgers()=0
virtual LedgerMaster & getLedgerMaster()=0
virtual beast::Journal journal(std::string const &name)=0
virtual std::shared_ptr< Ledger const > acquire(uint256 const &hash, std::uint32_t seq, InboundLedger::Reason)=0
virtual std::shared_ptr< InboundLedger > find(LedgerHash const &hash)=0
std::shared_ptr< Ledger const > getLedgerBySeq(std::uint32_t index)
std::shared_ptr< Ledger const > getClosedLedger()
std::shared_ptr< Ledger const > getValidatedLedger()
bool isValidated(ReadView const &ledger)
LedgerIndex getValidLedgerIndex()
std::shared_ptr< ReadView const > getCurrentLedger()
std::shared_ptr< Ledger const > getLedgerByHash(uint256 const &hash)
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
static std::optional< base_uint > fromVoidChecked(T const &from)
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
Status
Return codes from Backend operations.
auto constexpr maxValidatedLedgerAge
std::string expected_field_message(std::string const &name, std::string const &type)
Status ledgerFromSpecifier(T &ledger, org::xrpl::rpc::v1::LedgerSpecifier const &specifier, Context const &context)
Retrieves a ledger based on a LedgerSpecifier.
Expected< std::shared_ptr< Ledger const >, Json::Value > getOrAcquireLedger(RPC::JsonContext const &context)
Retrieves or acquires a ledger based on the parameters provided in the given JsonContext.
Json::Value expected_field_error(std::string const &name, 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.
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.
Status getLedger(T &ledger, uint256 const &ledgerHash, Context const &context)
Retrieves a ledger by its hash.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
std::string to_string(base_uint< Bits, Tag > const &a)
LedgerIndex getCandidateLedger(LedgerIndex requested)
Find a ledger index from which we could easily get the requested ledger.
std::optional< uint256 > hashOfSeq(ReadView const &ledger, LedgerIndex seq, beast::Journal journal)
Return the hash of a ledger by sequence.
Json::Value rpcError(error_code_i iError)
@ ledgerMaster
ledger master data for signing
The context of information needed to call an RPC.
LedgerMaster & ledgerMaster
Status represents the results of an operation that might fail.