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/misc/Transaction.h>
5#include <xrpld/app/paths/TrustLine.h>
6#include <xrpld/app/rdb/RelationalDatabase.h>
7#include <xrpld/app/tx/detail/NFTokenUtils.h>
8#include <xrpld/rpc/Context.h>
9#include <xrpld/rpc/DeliveredAmount.h>
10#include <xrpld/rpc/detail/RPCHelpers.h>
12#include <xrpl/ledger/View.h>
13#include <xrpl/protocol/AccountID.h>
14#include <xrpl/protocol/RPCErr.h>
15#include <xrpl/protocol/nftPageMask.h>
16#include <xrpl/resource/Fees.h>
18#include <boost/algorithm/string/case_conv.hpp>
19#include <boost/algorithm/string/predicate.hpp>
27isValidatedOld(LedgerMaster&
ledgerMaster,
bool standalone)
41 auto& params = context.params;
43 auto indexValue = params[jss::ledger_index];
44 auto hashValue = params[jss::ledger_hash];
47 auto& legacyLedger = params[jss::ledger];
50 if (legacyLedger.asString().size() > 12)
51 hashValue = legacyLedger;
53 indexValue = legacyLedger;
56 if (!hashValue.isNull())
58 if (!hashValue.isString())
62 if (!ledgerHash.parseHex(hashValue.asString()))
64 return getLedger(ledger, ledgerHash, context);
70 auto const index = indexValue.asString();
72 if (index ==
"current" || index.empty())
73 return getLedger(ledger, LedgerShortcut::CURRENT, context);
75 if (index ==
"validated")
76 return getLedger(ledger, LedgerShortcut::VALIDATED, context);
78 if (index ==
"closed")
79 return getLedger(ledger, LedgerShortcut::CLOSED, context);
89template <
class T,
class R>
93 R& request = context.
params;
119 org::xrpl::rpc::v1::LedgerSpecifier
const& specifier,
124 using LedgerCase = org::xrpl::rpc::v1::LedgerSpecifier::LedgerCase;
125 LedgerCase ledgerCase = specifier.ledger_case();
128 case LedgerCase::kHash: {
131 return getLedger(ledger, *hash, context);
135 case LedgerCase::kSequence:
136 return getLedger(ledger, specifier.sequence(), context);
137 case LedgerCase::kShortcut:
139 case LedgerCase::LEDGER_NOT_SET: {
140 auto const shortcut = specifier.shortcut();
142 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED)
144 return getLedger(ledger, LedgerShortcut::VALIDATED, context);
149 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT ||
151 org::xrpl::rpc::v1::LedgerSpecifier::
152 SHORTCUT_UNSPECIFIED)
154 return getLedger(ledger, LedgerShortcut::CURRENT, context);
158 org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED)
160 return getLedger(ledger, LedgerShortcut::CLOSED, context);
174 if (ledger ==
nullptr)
184 if (ledger ==
nullptr)
187 if (cur->info().seq == ledgerIndex)
193 if (ledger ==
nullptr)
219 if (shortcut == LedgerShortcut::VALIDATED)
222 if (ledger ==
nullptr)
230 !ledger->open(),
"ripple::RPC::getLedger : validated is not open");
234 if (shortcut == LedgerShortcut::CURRENT)
238 ledger->open(),
"ripple::RPC::getLedger : current is open");
240 else if (shortcut == LedgerShortcut::CLOSED)
244 !ledger->open(),
"ripple::RPC::getLedger : closed is not open");
251 if (ledger ==
nullptr)
258 static auto const minSequenceGap = 10;
260 if (ledger->info().seq + minSequenceGap <
313 auto& info = ledger->info();
317 result[jss::ledger_hash] =
to_string(info.hash);
318 result[jss::ledger_index] = info.seq;
322 result[jss::ledger_current_index] = info.seq;
333 if (
auto status =
lookupLedger(ledger, context, result))
334 status.inject(result);
349 if ((hasHash && hasIndex) || !(hasHash || hasIndex))
352 "Exactly one of ledger_hash and ledger_index can be set.");
359 auto const& jsonHash = context.
params[jss::ledger_hash];
360 if (!jsonHash.isString() || !ledgerHash.
parseHex(jsonHash.asString()))
365 auto const& jsonIndex = context.
params[jss::ledger_index];
366 if (!jsonIndex.isInt())
378 ledgerIndex = jsonIndex.asInt();
381 if (ledgerIndex >= ledger->info().seq)
383 if (ledgerIndex <= 0)
386 auto const j = context.
app.
journal(
"RPCHandler");
389 auto neededHash =
hashOfSeq(*ledger, ledgerIndex, j);
395 auto refHash =
hashOfSeq(*ledger, refIndex, j);
398 "ripple::RPC::getLedgerByContext : nonzero ledger hash");
411 "acquiring ledger containing requested index");
412 jvResult[jss::acquiring] =
421 "acquiring ledger containing requested index");
422 jvResult[jss::acquiring] = il->getJson(0);
430 neededHash =
hashOfSeq(*ledger, ledgerIndex, j);
434 "ripple::RPC::getLedgerByContext : nonzero needed hash");
435 ledgerHash = neededHash ? *neededHash : beast::zero;
451 return il->getJson(0);
454 rpcNOT_READY,
"findCreate failed to return an inbound ledger");
bool isMember(char const *key) const
Return true if the object has a member named key.
virtual Config & config()=0
virtual beast::Journal journal(std::string const &name)=0
virtual InboundLedgers & getInboundLedgers()=0
virtual LedgerMaster & getLedgerMaster()=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 > getValidatedLedger()
std::shared_ptr< ReadView const > getCurrentLedger()
bool isValidated(ReadView const &ledger)
std::shared_ptr< Ledger const > getClosedLedger()
std::shared_ptr< Ledger const > getLedgerBySeq(std::uint32_t index)
std::shared_ptr< Ledger const > getLedgerByHash(uint256 const &hash)
LedgerIndex getValidLedgerIndex()
static std::optional< base_uint > fromVoidChecked(T const &from)
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
@ stringValue
UTF-8 string value.
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
Status
Return codes from Backend operations.
auto constexpr maxValidatedLedgerAge
Status ledgerFromRequest(T &ledger, GRPCContext< R > &context)
Json::Value make_error(error_code_i code)
Returns a new json object that reflects the error code.
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.
Json::Value invalid_field_error(std::string const &name)
Json::Value make_param_error(std::string const &message)
Returns a new json object that indicates invalid parameters.
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...
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.
Status ledgerFromSpecifier(T &ledger, org::xrpl::rpc::v1::LedgerSpecifier const &specifier, Context &context)
Charge const feeHeavyBurdenRPC
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
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(int iError)
std::string to_string(base_uint< Bits, Tag > const &a)
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.
Resource::Charge & loadType
LedgerMaster & ledgerMaster
Status represents the results of an operation that might fail.