rippled
AccountTx.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2014 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/app/ledger/LedgerMaster.h>
21 #include <ripple/app/main/Application.h>
22 #include <ripple/app/misc/DeliverMax.h>
23 #include <ripple/app/misc/NetworkOPs.h>
24 #include <ripple/app/misc/Transaction.h>
25 #include <ripple/app/rdb/backend/PostgresDatabase.h>
26 #include <ripple/app/rdb/backend/SQLiteDatabase.h>
27 #include <ripple/core/Pg.h>
28 #include <ripple/json/json_reader.h>
29 #include <ripple/json/json_value.h>
30 #include <ripple/ledger/ReadView.h>
31 #include <ripple/net/RPCErr.h>
32 #include <ripple/protocol/ErrorCodes.h>
33 #include <ripple/protocol/NFTSyntheticSerializer.h>
34 #include <ripple/protocol/UintTypes.h>
35 #include <ripple/protocol/jss.h>
36 #include <ripple/resource/Fees.h>
37 #include <ripple/rpc/Context.h>
38 #include <ripple/rpc/DeliveredAmount.h>
39 #include <ripple/rpc/Role.h>
40 
41 #include <grpcpp/grpcpp.h>
42 
43 namespace ripple {
44 
50 
53 
54 // parses args into a ledger specifier, or returns a Json object on error
56 parseLedgerArgs(RPC::Context& context, Json::Value const& params)
57 {
58  Json::Value response;
59  // if ledger_index_min or max is specified, then ledger_hash or ledger_index
60  // should not be specified. Error out if it is
61  if (context.apiVersion > 1u)
62  {
63  if ((params.isMember(jss::ledger_index_min) ||
64  params.isMember(jss::ledger_index_max)) &&
65  (params.isMember(jss::ledger_hash) ||
66  params.isMember(jss::ledger_index)))
67  {
68  RPC::Status status{rpcINVALID_PARAMS, "invalidParams"};
69  status.inject(response);
70  return response;
71  }
72  }
73  if (params.isMember(jss::ledger_index_min) ||
74  params.isMember(jss::ledger_index_max))
75  {
76  uint32_t min = params.isMember(jss::ledger_index_min) &&
77  params[jss::ledger_index_min].asInt() >= 0
78  ? params[jss::ledger_index_min].asUInt()
79  : 0;
80  uint32_t max = params.isMember(jss::ledger_index_max) &&
81  params[jss::ledger_index_max].asInt() >= 0
82  ? params[jss::ledger_index_max].asUInt()
83  : UINT32_MAX;
84 
85  return LedgerRange{min, max};
86  }
87  else if (params.isMember(jss::ledger_hash))
88  {
89  auto& hashValue = params[jss::ledger_hash];
90  if (!hashValue.isString())
91  {
92  RPC::Status status{rpcINVALID_PARAMS, "ledgerHashNotString"};
93  status.inject(response);
94  return response;
95  }
96 
97  LedgerHash hash;
98  if (!hash.parseHex(hashValue.asString()))
99  {
100  RPC::Status status{rpcINVALID_PARAMS, "ledgerHashMalformed"};
101  status.inject(response);
102  return response;
103  }
104  return hash;
105  }
106  else if (params.isMember(jss::ledger_index))
107  {
108  LedgerSpecifier ledger;
109  if (params[jss::ledger_index].isNumeric())
110  ledger = params[jss::ledger_index].asUInt();
111  else
112  {
113  std::string ledgerStr = params[jss::ledger_index].asString();
114 
115  if (ledgerStr == "current" || ledgerStr.empty())
116  ledger = LedgerShortcut::CURRENT;
117  else if (ledgerStr == "closed")
118  ledger = LedgerShortcut::CLOSED;
119  else if (ledgerStr == "validated")
120  ledger = LedgerShortcut::VALIDATED;
121  else
122  {
123  RPC::Status status{
124  rpcINVALID_PARAMS, "ledger_index string malformed"};
125  status.inject(response);
126  return response;
127  }
128  }
129  return ledger;
130  }
132 }
133 
136  RPC::Context& context,
137  std::optional<LedgerSpecifier> const& ledgerSpecifier)
138 {
139  std::uint32_t uValidatedMin;
140  std::uint32_t uValidatedMax;
141  bool bValidated =
142  context.ledgerMaster.getValidatedRange(uValidatedMin, uValidatedMax);
143 
144  if (!bValidated)
145  {
146  // Don't have a validated ledger range.
147  if (context.apiVersion == 1)
148  return rpcLGR_IDXS_INVALID;
149  return rpcNOT_SYNCED;
150  }
151 
152  std::uint32_t uLedgerMin = uValidatedMin;
153  std::uint32_t uLedgerMax = uValidatedMax;
154  // Does request specify a ledger or ledger range?
155  if (ledgerSpecifier)
156  {
157  auto const status = std::visit(
158  [&](auto const& ls) -> RPC::Status {
159  using T = std::decay_t<decltype(ls)>;
160  if constexpr (std::is_same_v<T, LedgerRange>)
161  {
162  // if ledger_index_min or ledger_index_max is out of
163  // valid ledger range, error out. exclude -1 as
164  // it is a valid input
165  if (context.apiVersion > 1u)
166  {
167  if ((ls.max > uValidatedMax && ls.max != -1) ||
168  (ls.min < uValidatedMin && ls.min != 0))
169  {
170  return rpcLGR_IDX_MALFORMED;
171  }
172  }
173  if (ls.min > uValidatedMin)
174  {
175  uLedgerMin = ls.min;
176  }
177  if (ls.max < uValidatedMax)
178  {
179  uLedgerMax = ls.max;
180  }
181  if (uLedgerMax < uLedgerMin)
182  {
183  if (context.apiVersion == 1)
184  return rpcLGR_IDXS_INVALID;
185  return rpcINVALID_LGR_RANGE;
186  }
187  }
188  else
189  {
191  auto const status = getLedger(ledgerView, ls, context);
192  if (!ledgerView)
193  {
194  return status;
195  }
196 
197  bool validated =
198  context.ledgerMaster.isValidated(*ledgerView);
199 
200  if (!validated || ledgerView->info().seq > uValidatedMax ||
201  ledgerView->info().seq < uValidatedMin)
202  {
203  return rpcLGR_NOT_VALIDATED;
204  }
205  uLedgerMin = uLedgerMax = ledgerView->info().seq;
206  }
207  return RPC::Status::OK;
208  },
209  *ledgerSpecifier);
210 
211  if (status)
212  return status;
213  }
214  return LedgerRange{uLedgerMin, uLedgerMax};
215 }
216 
219 {
221  if (context.app.config().reporting())
222  {
223  auto const db = dynamic_cast<PostgresDatabase*>(
224  &context.app.getRelationalDatabase());
225 
226  if (!db)
227  Throw<std::runtime_error>("Failed to get relational database");
228 
229  return db->getAccountTx(args);
230  }
231 
232  AccountTxResult result;
233 
234  auto lgrRange = getLedgerRange(context, args.ledger);
235  if (auto stat = std::get_if<RPC::Status>(&lgrRange))
236  {
237  // An error occurred getting the requested ledger range
238  return {result, *stat};
239  }
240 
241  result.ledgerRange = std::get<LedgerRange>(lgrRange);
242 
243  result.marker = args.marker;
244 
246  args.account,
247  result.ledgerRange.min,
248  result.ledgerRange.max,
249  result.marker,
250  args.limit,
251  isUnlimited(context.role)};
252 
253  auto const db =
254  dynamic_cast<SQLiteDatabase*>(&context.app.getRelationalDatabase());
255 
256  if (!db)
257  Throw<std::runtime_error>("Failed to get relational database");
258 
259  if (args.binary)
260  {
261  if (args.forward)
262  {
263  auto [tx, marker] = db->oldestAccountTxPageB(options);
264  result.transactions = tx;
265  result.marker = marker;
266  }
267  else
268  {
269  auto [tx, marker] = db->newestAccountTxPageB(options);
270  result.transactions = tx;
271  result.marker = marker;
272  }
273  }
274  else
275  {
276  if (args.forward)
277  {
278  auto [tx, marker] = db->oldestAccountTxPage(options);
279  result.transactions = tx;
280  result.marker = marker;
281  }
282  else
283  {
284  auto [tx, marker] = db->newestAccountTxPage(options);
285  result.transactions = tx;
286  result.marker = marker;
287  }
288  }
289 
290  result.limit = args.limit;
291  JLOG(context.j.debug()) << __func__ << " : finished";
292 
293  return {result, rpcSUCCESS};
294 }
295 
299  AccountTxArgs const& args,
300  RPC::JsonContext const& context)
301 {
302  Json::Value response;
303  RPC::Status const& error = res.second;
304  if (error.toErrorCode() != rpcSUCCESS)
305  {
306  error.inject(response);
307  }
308  else
309  {
310  AccountTxResult const& result = res.first;
311  response[jss::validated] = true;
312  response[jss::limit] = result.limit;
313  response[jss::account] = context.params[jss::account].asString();
314  response[jss::ledger_index_min] = result.ledgerRange.min;
315  response[jss::ledger_index_max] = result.ledgerRange.max;
316 
317  Json::Value& jvTxns = (response[jss::transactions] = Json::arrayValue);
318 
319  if (auto txnsData = std::get_if<TxnsData>(&result.transactions))
320  {
321  assert(!args.binary);
322 
323  for (auto const& [txn, txnMeta] : *txnsData)
324  {
325  if (txn)
326  {
327  Json::Value& jvObj = jvTxns.append(Json::objectValue);
328  jvObj[jss::validated] = true;
329 
330  auto const json_tx =
331  (context.apiVersion > 1 ? jss::tx_json : jss::tx);
332  if (context.apiVersion > 1)
333  {
334  jvObj[json_tx] = txn->getJson(
337  false);
338  jvObj[jss::hash] = to_string(txn->getID());
339  jvObj[jss::ledger_index] = txn->getLedger();
340  jvObj[jss::ledger_hash] =
342  txn->getLedger()));
343 
344  if (auto closeTime =
346  txn->getLedger()))
347  jvObj[jss::close_time_iso] =
348  to_string_iso(*closeTime);
349  }
350  else
351  jvObj[json_tx] =
352  txn->getJson(JsonOptions::include_date);
353 
354  auto const& sttx = txn->getSTransaction();
356  jvObj[json_tx], sttx->getTxnType(), context.apiVersion);
357  if (txnMeta)
358  {
359  jvObj[jss::meta] =
360  txnMeta->getJson(JsonOptions::include_date);
361  insertDeliveredAmount(
362  jvObj[jss::meta], context, txn, *txnMeta);
363  insertNFTSyntheticInJson(jvObj, sttx, *txnMeta);
364  }
365  else
366  assert(false && "Missing transaction medatata");
367  }
368  }
369  }
370  else
371  {
372  assert(args.binary);
373 
374  for (auto const& binaryData :
375  std::get<TxnsDataBinary>(result.transactions))
376  {
377  Json::Value& jvObj = jvTxns.append(Json::objectValue);
378 
379  jvObj[jss::tx_blob] = strHex(std::get<0>(binaryData));
380  auto const json_meta =
381  (context.apiVersion > 1 ? jss::meta_blob : jss::meta);
382  jvObj[json_meta] = strHex(std::get<1>(binaryData));
383  jvObj[jss::ledger_index] = std::get<2>(binaryData);
384  jvObj[jss::validated] = true;
385  }
386  }
387 
388  if (result.marker)
389  {
390  response[jss::marker] = Json::objectValue;
391  response[jss::marker][jss::ledger] = result.marker->ledgerSeq;
392  response[jss::marker][jss::seq] = result.marker->txnSeq;
393  }
394  if (context.app.config().reporting())
395  response["used_postgres"] = true;
396  }
397 
398  JLOG(context.j.debug()) << __func__ << " : finished";
399  return response;
400 }
401 
402 // {
403 // account: account,
404 // ledger_index_min: ledger_index // optional, defaults to earliest
405 // ledger_index_max: ledger_index, // optional, defaults to latest
406 // binary: boolean, // optional, defaults to false
407 // forward: boolean, // optional, defaults to false
408 // limit: integer, // optional
409 // marker: object {ledger: ledger_index, seq: txn_sequence} // optional,
410 // resume previous query
411 // }
414 {
415  if (!context.app.config().useTxTables())
416  return rpcError(rpcNOT_ENABLED);
417 
418  auto& params = context.params;
419  AccountTxArgs args;
420  Json::Value response;
421 
422  // The document[https://xrpl.org/account_tx.html#account_tx] states that
423  // binary and forward params are both boolean values, however, assigning any
424  // string value works. Do not allow this. This check is for api Version 2
425  // onwards only
426  if (context.apiVersion > 1u && params.isMember(jss::binary) &&
427  !params[jss::binary].isBool())
428  {
429  return rpcError(rpcINVALID_PARAMS);
430  }
431  if (context.apiVersion > 1u && params.isMember(jss::forward) &&
432  !params[jss::forward].isBool())
433  {
434  return rpcError(rpcINVALID_PARAMS);
435  }
436 
437  args.limit = params.isMember(jss::limit) ? params[jss::limit].asUInt() : 0;
438  args.binary = params.isMember(jss::binary) && params[jss::binary].asBool();
439  args.forward =
440  params.isMember(jss::forward) && params[jss::forward].asBool();
441 
442  if (!params.isMember(jss::account))
443  return rpcError(rpcINVALID_PARAMS);
444 
445  auto const account =
446  parseBase58<AccountID>(params[jss::account].asString());
447  if (!account)
448  return rpcError(rpcACT_MALFORMED);
449 
450  args.account = *account;
451 
452  auto parseRes = parseLedgerArgs(context, params);
453  if (auto jv = std::get_if<Json::Value>(&parseRes))
454  {
455  return *jv;
456  }
457  else
458  {
459  args.ledger = std::get<std::optional<LedgerSpecifier>>(parseRes);
460  }
461 
462  if (params.isMember(jss::marker))
463  {
464  auto& token = params[jss::marker];
465  if (!token.isMember(jss::ledger) || !token.isMember(jss::seq) ||
466  !token[jss::ledger].isConvertibleTo(Json::ValueType::uintValue) ||
467  !token[jss::seq].isConvertibleTo(Json::ValueType::uintValue))
468  {
469  RPC::Status status{
471  "invalid marker. Provide ledger index via ledger field, and "
472  "transaction sequence number via seq field"};
473  status.inject(response);
474  return response;
475  }
476  args.marker = {token[jss::ledger].asUInt(), token[jss::seq].asUInt()};
477  }
478 
479  auto res = doAccountTxHelp(context, args);
480  JLOG(context.j.debug()) << __func__ << " populating response";
481  return populateJsonResponse(res, args, context);
482 }
483 
484 } // namespace ripple
ripple::SQLiteDatabase
Definition: SQLiteDatabase.h:27
ripple::JsonOptions::disable_API_prior_V2
@ disable_API_prior_V2
Definition: STBase.h:44
ripple::JsonOptions::include_date
@ include_date
Definition: STBase.h:43
ripple::ReadView::info
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
ripple::LedgerMaster::getValidatedRange
bool getValidatedRange(std::uint32_t &minVal, std::uint32_t &maxVal)
Definition: LedgerMaster.cpp:678
ripple::RPC::JsonContext
Definition: Context.h:53
ripple::parseLedgerArgs
std::variant< std::optional< LedgerSpecifier >, Json::Value > parseLedgerArgs(RPC::Context &context, Json::Value const &params)
Definition: AccountTx.cpp:56
ripple::RelationalDatabase::txnMetaLedgerType
std::tuple< Blob, Blob, std::uint32_t > txnMetaLedgerType
Definition: RelationalDatabase.h:87
ripple::rpcLGR_IDXS_INVALID
@ rpcLGR_IDXS_INVALID
Definition: ErrorCodes.h:112
std::string
STL class.
std::shared_ptr
STL class.
ripple::rpcINVALID_PARAMS
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:84
ripple::rpcError
Json::Value rpcError(int iError)
Definition: RPCErr.cpp:29
ripple::RPC::insertDeliverMax
void insertDeliverMax(Json::Value &tx_json, TxType txnType, unsigned int apiVersion)
Copy Amount field to DeliverMax field in transaction output JSON.
Definition: DeliverMax.cpp:28
ripple::Resource::feeMediumBurdenRPC
const Charge feeMediumBurdenRPC
ripple::RelationalDatabase::AccountTxArgs
Definition: RelationalDatabase.h:96
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
std::pair
ripple::RPC::LedgerShortcut
LedgerShortcut
Definition: RPCHelpers.h:129
ripple::RelationalDatabase::AccountTxArgs::binary
bool binary
Definition: RelationalDatabase.h:100
ripple::RelationalDatabase::LedgerSpecifier
std::variant< LedgerRange, LedgerShortcut, LedgerSequence, LedgerHash > LedgerSpecifier
Definition: RelationalDatabase.h:94
ripple::RPC::Context::loadType
Resource::Charge & loadType
Definition: Context.h:43
ripple::RPC::Context::ledgerMaster
LedgerMaster & ledgerMaster
Definition: Context.h:45
ripple::RelationalDatabase::AccountTxs
std::vector< AccountTx > AccountTxs
Definition: RelationalDatabase.h:86
ripple::LedgerHeader::seq
LedgerIndex seq
Definition: LedgerHeader.h:41
ripple::RelationalDatabase::AccountTxResult::transactions
std::variant< AccountTxs, MetaTxsList > transactions
Definition: RelationalDatabase.h:108
ripple::to_string_iso
std::string to_string_iso(date::sys_time< Duration > tp)
Definition: chrono.h:93
std::tuple
ripple::RPC::Context::role
Role role
Definition: Context.h:47
ripple::RelationalDatabase::AccountTxArgs::account
AccountID account
Definition: RelationalDatabase.h:98
ripple::insertNFTSyntheticInJson
void insertNFTSyntheticInJson(Json::Value &response, std::shared_ptr< STTx const > const &transaction, TxMeta const &transactionMeta)
Adds common synthetic fields to transaction-related JSON responses.
Definition: NFTSyntheticSerializer.cpp:28
ripple::RelationalDatabase::AccountTxResult
Definition: RelationalDatabase.h:106
ripple::doAccountTxHelp
std::pair< AccountTxResult, RPC::Status > doAccountTxHelp(RPC::Context &context, AccountTxArgs const &args)
Definition: AccountTx.cpp:218
ripple::RPC::Context::j
const beast::Journal j
Definition: Context.h:41
ripple::getLedgerRange
std::variant< LedgerRange, RPC::Status > getLedgerRange(RPC::Context &context, std::optional< LedgerSpecifier > const &ledgerSpecifier)
Definition: AccountTx.cpp:135
ripple::RelationalDatabase::AccountTxResult::ledgerRange
LedgerRange ledgerRange
Definition: RelationalDatabase.h:109
ripple::base_uint< 256 >
ripple::RPC::Status::OK
static constexpr Code OK
Definition: Status.h:46
ripple::rpcSUCCESS
@ rpcSUCCESS
Definition: ErrorCodes.h:44
Json::Value::append
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:882
ripple::Config::reporting
bool reporting() const
Definition: Config.h:350
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
ripple::RelationalDatabase::MetaTxsList
std::vector< txnMetaLedgerType > MetaTxsList
Definition: RelationalDatabase.h:88
ripple::RelationalDatabase::LedgerShortcut
RPC::LedgerShortcut LedgerShortcut
Definition: RelationalDatabase.h:92
ripple::Application::config
virtual Config & config()=0
ripple::RelationalDatabase::AccountTxArgs::marker
std::optional< AccountTxMarker > marker
Definition: RelationalDatabase.h:103
ripple::RelationalDatabase::AccountTxArgs::limit
uint32_t limit
Definition: RelationalDatabase.h:102
ripple::Application::getRelationalDatabase
virtual RelationalDatabase & getRelationalDatabase()=0
ripple::Config::useTxTables
bool useTxTables() const
Definition: Config.h:356
ripple::RelationalDatabase::AccountTxResult::marker
std::optional< AccountTxMarker > marker
Definition: RelationalDatabase.h:111
ripple::RPC::Context::app
Application & app
Definition: Context.h:42
ripple::rpcNOT_ENABLED
@ rpcNOT_ENABLED
Definition: ErrorCodes.h:59
ripple::TxnsDataBinary
RelationalDatabase::MetaTxsList TxnsDataBinary
Definition: PostgresDatabase.cpp:47
Json::Value::isMember
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:932
std::uint32_t
ripple::RPC::Status
Status represents the results of an operation that might fail.
Definition: Status.h:39
std::decay_t
ripple::isUnlimited
bool isUnlimited(Role const &role)
ADMIN and IDENTIFIED roles shall have unlimited resources.
Definition: Role.cpp:124
ripple::RelationalDatabase::AccountTxArgs::forward
bool forward
Definition: RelationalDatabase.h:101
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::populateJsonResponse
Json::Value populateJsonResponse(std::pair< AccountTxResult, RPC::Status > const &res, AccountTxArgs const &args, RPC::JsonContext const &context)
Definition: AccountTx.cpp:297
ripple::rpcACT_MALFORMED
@ rpcACT_MALFORMED
Definition: ErrorCodes.h:90
ripple::LedgerMaster::getCloseTimeBySeq
std::optional< NetClock::time_point > getCloseTimeBySeq(LedgerIndex ledgerIndex)
Definition: LedgerMaster.cpp:1761
ripple::LedgerMaster::isValidated
bool isValidated(ReadView const &ledger)
Definition: LedgerMaster.cpp:602
ripple::rpcLGR_NOT_VALIDATED
@ rpcLGR_NOT_VALIDATED
Definition: ErrorCodes.h:73
ripple::doAccountTxJson
Json::Value doAccountTxJson(RPC::JsonContext &context)
Definition: AccountTx.cpp:413
ripple::LedgerRange::max
uint32_t max
Definition: RelationalDatabase.h:45
Json::Value::asUInt
UInt asUInt() const
Definition: json_value.cpp:545
ripple::PostgresDatabase
Definition: PostgresDatabase.h:27
ripple::RPC::Context::apiVersion
unsigned int apiVersion
Definition: Context.h:50
ripple::rpcLGR_IDX_MALFORMED
@ rpcLGR_IDX_MALFORMED
Definition: ErrorCodes.h:113
std::visit
T visit(T... args)
std::string::empty
T empty(T... args)
std::optional
beast::Journal::debug
Stream debug() const
Definition: Journal.h:314
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
Json::Value::asInt
Int asInt() const
Definition: json_value.cpp:503
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:30
ripple::rpcINVALID_LGR_RANGE
@ rpcINVALID_LGR_RANGE
Definition: ErrorCodes.h:136
ripple::TxnsData
RelationalDatabase::AccountTxs TxnsData
Definition: PostgresDatabase.cpp:46
ripple::RelationalDatabase::AccountTxArgs::ledger
std::optional< LedgerSpecifier > ledger
Definition: RelationalDatabase.h:99
ripple::LedgerRange
Definition: RelationalDatabase.h:42
ripple::base_uint::parseHex
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:496
ripple::LedgerMaster::getHashBySeq
uint256 getHashBySeq(std::uint32_t index)
Get a ledger's hash by sequence number using the cache.
Definition: LedgerMaster.cpp:1791
ripple::LedgerRange::min
uint32_t min
Definition: RelationalDatabase.h:44
ripple::RelationalDatabase::AccountTxResult::limit
uint32_t limit
Definition: RelationalDatabase.h:110
ripple::RPC::JsonContext::params
Json::Value params
Definition: Context.h:64
ripple::RPC::Context
The context of information needed to call an RPC.
Definition: Context.h:39
ripple::RelationalDatabase::AccountTxPageOptions
Definition: RelationalDatabase.h:74
ripple::rpcNOT_SYNCED
@ rpcNOT_SYNCED
Definition: ErrorCodes.h:67
Json::Value
Represents a JSON value.
Definition: json_value.h:145
std::variant
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469