1#include <xrpld/rpc/detail/RPCLedgerHelpers.h>
3#include <xrpld/app/ledger/InboundLedger.h>
4#include <xrpld/app/ledger/InboundLedgers.h>
5#include <xrpld/app/ledger/LedgerMaster.h>
6#include <xrpld/app/ledger/LedgerToJson.h>
7#include <xrpld/app/main/Application.h>
8#include <xrpld/rpc/Context.h>
9#include <xrpld/rpc/Status.h>
10#include <xrpld/rpc/detail/Tuning.h>
12#include <xrpl/basics/base_uint.h>
13#include <xrpl/beast/core/LexicalCast.h>
14#include <xrpl/beast/utility/Zero.h>
15#include <xrpl/beast/utility/instrumentation.h>
16#include <xrpl/json/json_value.h>
17#include <xrpl/ledger/View.h>
18#include <xrpl/protocol/ErrorCodes.h>
19#include <xrpl/protocol/RPCErr.h>
20#include <xrpl/protocol/RippleLedgerHash.h>
21#include <xrpl/protocol/jss.h>
23#include <org/xrpl/rpc/v1/get_ledger.pb.h>
24#include <org/xrpl/rpc/v1/get_ledger_data.pb.h>
25#include <org/xrpl/rpc/v1/get_ledger_entry.pb.h>
26#include <org/xrpl/rpc/v1/ledger.pb.h>
27#include <rpcspec/Ledger.hpp>
39template <
typename... Ts>
40struct Overload : Ts...
42 using Ts::operator()...;
44 constexpr Overload(Ts&&... ts) : Ts(std::
forward<Ts>(ts))...
50isValidatedOld(
LedgerMaster& ledgerMaster,
bool standalone)
64 json::StaticString
const fieldName)
67 if (!ledgerHash.parseHex(hash.
asString()))
69 return getLedger(ledger, ledgerHash, context);
76 json::Value indexValue,
78 json::StaticString
const fieldName)
80 auto const index = indexValue.
asString();
82 if (index ==
"current" || index.empty())
83 return getLedger(ledger, ::rpc::spec::LedgerShortcut::Current, context);
85 if (index ==
"validated")
86 return getLedger(ledger, ::rpc::spec::LedgerShortcut::Validated, context);
88 if (index ==
"closed")
89 return getLedger(ledger, ::rpc::spec::LedgerShortcut::Closed, context);
91 std::uint32_t iVal = 0;
104 auto& params = context.params;
105 auto const hasLedger = context.params.isMember(jss::ledger);
106 auto const hasHash = context.params.isMember(jss::ledger_hash);
107 auto const hasIndex = context.params.isMember(jss::ledger_index);
109 if ((hasLedger + hasHash + hasIndex) > 1)
117 "Exactly one of 'ledger', 'ledger_hash', or "
118 "'ledger_index' can be specified."};
122 "Exactly one of 'ledger_hash' or "
123 "'ledger_index' can be specified."};
129 auto& legacyLedger = params[jss::ledger];
130 if (!legacyLedger.isString() && !legacyLedger.isUInt() && !legacyLedger.isInt())
134 if (legacyLedger.isString() && legacyLedger.asString().size() == 64)
136 return ledgerFromHash(ledger, legacyLedger, context, jss::ledger);
139 return ledgerFromIndex(ledger, legacyLedger, context, jss::ledger);
144 auto const& ledgerHash = params[jss::ledger_hash];
145 if (!ledgerHash.isString())
147 return ledgerFromHash(ledger, ledgerHash, context, jss::ledger_hash);
152 auto const& ledgerIndex = params[jss::ledger_index];
153 if (!ledgerIndex.isString() && !ledgerIndex.isUInt() && !ledgerIndex.isInt())
157 return ledgerFromIndex(ledger, ledgerIndex, context, jss::ledger_index);
161 return getLedger(ledger, ::rpc::spec::LedgerShortcut::Current, context);
165template <
class T,
class R>
169 R
const& request = context.
params;
195 org::xrpl::rpc::v1::LedgerSpecifier
const& specifier,
200 using LedgerCase = org::xrpl::rpc::v1::LedgerSpecifier::LedgerCase;
201 LedgerCase
const ledgerCase = specifier.ledger_case();
204 case LedgerCase::kHash: {
207 return getLedger(ledger, *hash, context);
211 case LedgerCase::kSequence:
212 return getLedger(ledger, specifier.sequence(), context);
213 case LedgerCase::kShortcut:
215 case LedgerCase::LEDGER_NOT_SET: {
216 auto const shortcut = specifier.shortcut();
217 if (shortcut == org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED)
219 return getLedger(ledger, ::rpc::spec::LedgerShortcut::Validated, context);
222 if (shortcut == org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT ||
223 shortcut == org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_UNSPECIFIED)
225 return getLedger(ledger, ::rpc::spec::LedgerShortcut::Current, context);
227 if (shortcut == org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED)
229 return getLedger(ledger, ::rpc::spec::LedgerShortcut::Closed, context);
242 if (ledger ==
nullptr)
252 if (ledger ==
nullptr)
255 if (cur->header().seq == ledgerIndex)
261 if (ledger ==
nullptr)
287 if (shortcut == ::rpc::spec::LedgerShortcut::Validated)
290 if (ledger ==
nullptr)
297 XRPL_ASSERT(!ledger->open(),
"xrpl::rpc::getLedger : validated is not open");
301 if (shortcut == ::rpc::spec::LedgerShortcut::Current)
304 XRPL_ASSERT(ledger->open(),
"xrpl::rpc::getLedger : current is open");
306 else if (shortcut == ::rpc::spec::LedgerShortcut::Closed)
309 XRPL_ASSERT(!ledger->open(),
"xrpl::rpc::getLedger : closed is not open");
316 if (ledger ==
nullptr)
323 static auto const kMinSequenceGap = 10;
343 return getLedger(ledger, ::rpc::spec::kDefaultLedgerShortcut, context);
345 [&](
auto const& value) {
return getLedger(ledger, value, context); },
367 org::xrpl::rpc::v1::LedgerSpecifier
const&,
398 auto& info = ledger->header();
402 result[jss::ledger_hash] =
to_string(info.hash);
403 result[jss::ledger_index] = info.seq;
407 result[jss::ledger_current_index] = info.seq;
418 if (
auto status =
lookupLedger(ledger, context, result))
419 status.inject(result);
424std::expected<std::shared_ptr<Ledger const>,
json::Value>
434 if ((
static_cast<int>(hasHash) +
static_cast<int>(hasIndex)) != 1)
438 "Exactly one of 'ledger_hash' or "
439 "'ledger_index' can be specified."));
445 if (!jsonHash.isString() || !ledgerHash.
parseHex(jsonHash.asString()))
451 if (!jsonIndex.isInt() && !jsonIndex.isUInt())
462 ledgerIndex = jsonIndex.asInt();
463 auto ledger = ledgerMaster.getValidatedLedger();
465 if (ledgerIndex >= ledger->header().seq)
467 if (ledgerIndex <= 0)
473 auto neededHash =
hashOfSeq(*ledger, ledgerIndex, j);
479 auto refHash =
hashOfSeq(*ledger, refIndex, j);
480 XRPL_ASSERT(refHash,
"xrpl::rpc::getOrAcquireLedger : nonzero ledger hash");
483 ledger = ledgerMaster.getLedgerByHash(*refHash);
503 jvResult[jss::acquiring] = il->getJson(0);
511 neededHash =
hashOfSeq(*ledger, ledgerIndex, j);
513 XRPL_ASSERT(neededHash,
"xrpl::rpc::getOrAcquireLedger : nonzero needed hash");
524 ledger = ledgerMaster.getLedgerByHash(ledgerHash);
Value get(UInt index, Value const &defaultValue) const
If the array contains at least index+1 elements, returns the element value, otherwise returns default...
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.
virtual Config & config()=0
static std::optional< BaseUInt > fromVoidChecked(T const &from)
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
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)
Finds a ledger by sequence, preferring the validated chain.
std::shared_ptr< Ledger const > getClosedLedger()
The finalized ledger is the last closed/accepted ledger.
std::shared_ptr< Ledger const > getLedgerByHash(UInt256 const &hash)
std::shared_ptr< Ledger const > getValidatedLedger()
The validated ledger is the last fully validated ledger.
bool isValidated(ReadView const &ledger)
Tests whether a ledger is on the validated chain, using the skip list when the ledger does not alread...
LedgerIndex getValidLedgerIndex()
std::shared_ptr< ReadView const > getCurrentLedger()
The current ledger is the ledger we believe new transactions should go in.
virtual beast::Journal getJournal(std::string const &name)=0
virtual InboundLedgers & getInboundLedgers()=0
virtual LedgerMaster & getLedgerMaster()=0
constexpr bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
constexpr auto kMaxValidatedLedgerAge
API version numbers used in later API versions.
json::Value expectedFieldError(std::string const &name, std::string const &type)
std::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.
Status getLedger(T &ledger, UInt256 const &ledgerHash, Context const &context)
Retrieves a ledger by its hash.
Status ledgerFromRequest(T &ledger, GRPCContext< R > const &context)
Retrieves a ledger from a gRPC request context.
json::Value makeParamError(std::string const &message)
Returns a new json object that indicates invalid parameters.
Status ledgerFromSpecifier(T &ledger, org::xrpl::rpc::v1::LedgerSpecifier const &specifier, Context const &context)
Retrieves a ledger based on a LedgerSpecifier.
std::string expectedFieldMessage(std::string const &name, std::string const &type)
json::Value makeError(ErrorCodeI code)
Returns a new json object that reflects the error code.
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.
std::optional< UInt256 > hashOfSeq(ReadView const &ledger, LedgerIndex seq, beast::Journal journal)
Return the hash of a ledger by sequence.
std::string to_string(BaseUInt< Bits, Tag > const &a)
LedgerIndex getCandidateLedger(LedgerIndex requested)
Find a ledger index from which we could easily get the requested ledger.
json::Value rpcError(ErrorCodeI iError)
json::Value getJson(LedgerFill const &fill)
Return a new json::Value representing the ledger with given options.
@ 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.
static constexpr Code kOK