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 #include <ripple/rpc/impl/RPCHelpers.h>
42 #include <grpcpp/grpcpp.h>
64 if ((params.
isMember(jss::ledger_index_min) ||
65 params.
isMember(jss::ledger_index_max)) &&
66 (params.
isMember(jss::ledger_hash) ||
70 status.inject(response);
74 if (params.
isMember(jss::ledger_index_min) ||
75 params.
isMember(jss::ledger_index_max))
77 uint32_t min = params.
isMember(jss::ledger_index_min) &&
78 params[jss::ledger_index_min].
asInt() >= 0
79 ? params[jss::ledger_index_min].
asUInt()
81 uint32_t max = params.
isMember(jss::ledger_index_max) &&
82 params[jss::ledger_index_max].
asInt() >= 0
83 ? params[jss::ledger_index_max].
asUInt()
88 else if (params.
isMember(jss::ledger_hash))
90 auto& hashValue = params[jss::ledger_hash];
91 if (!hashValue.isString())
94 status.inject(response);
99 if (!hash.
parseHex(hashValue.asString()))
102 status.inject(response);
107 else if (params.
isMember(jss::ledger_index))
110 if (params[jss::ledger_index].isNumeric())
111 ledger = params[jss::ledger_index].
asUInt();
116 if (ledgerStr ==
"current" || ledgerStr.
empty())
117 ledger = LedgerShortcut::CURRENT;
118 else if (ledgerStr ==
"closed")
119 ledger = LedgerShortcut::CLOSED;
120 else if (ledgerStr ==
"validated")
121 ledger = LedgerShortcut::VALIDATED;
126 status.inject(response);
161 if constexpr (std::is_same_v<T, LedgerRange>)
168 if ((ls.max > uValidatedMax && ls.max != -1) ||
169 (ls.min < uValidatedMin && ls.min != 0))
174 if (ls.min > uValidatedMin)
178 if (ls.max < uValidatedMax)
182 if (uLedgerMax < uLedgerMin)
192 auto const status = getLedger(ledgerView, ls, context);
201 if (!validated || ledgerView->
info().
seq > uValidatedMax ||
202 ledgerView->
info().
seq < uValidatedMin)
206 uLedgerMin = uLedgerMax = ledgerView->
info().
seq;
228 Throw<std::runtime_error>(
"Failed to get relational database");
230 return db->getAccountTx(args);
236 if (
auto stat = std::get_if<RPC::Status>(&lgrRange))
239 return {result, *stat};
242 result.
ledgerRange = std::get<LedgerRange>(lgrRange);
258 Throw<std::runtime_error>(
"Failed to get relational database");
264 auto [tx, marker] = db->oldestAccountTxPageB(options);
270 auto [tx, marker] = db->newestAccountTxPageB(options);
279 auto [tx, marker] = db->oldestAccountTxPage(options);
285 auto [tx, marker] = db->newestAccountTxPage(options);
292 JLOG(context.
j.
debug()) << __func__ <<
" : finished";
307 error.inject(response);
312 response[jss::validated] =
true;
313 response[jss::limit] = result.
limit;
320 if (
auto txnsData = std::get_if<TxnsData>(&result.
transactions))
323 for (
auto const& [txn, txnMeta] : *txnsData)
330 auto const& sttx = txn->getSTransaction();
332 jvObj[jss::tx], sttx->getTxnType(), context.
apiVersion);
337 jvObj[jss::validated] =
true;
338 insertDeliveredAmount(
339 jvObj[jss::meta], context, txn, *txnMeta);
349 for (
auto const& binaryData :
354 jvObj[jss::tx_blob] =
strHex(std::get<0>(binaryData));
355 jvObj[jss::meta] =
strHex(std::get<1>(binaryData));
356 jvObj[jss::ledger_index] = std::get<2>(binaryData);
357 jvObj[jss::validated] =
true;
364 response[jss::marker][jss::ledger] = result.
marker->ledgerSeq;
365 response[jss::marker][jss::seq] = result.
marker->txnSeq;
368 response[
"used_postgres"] =
true;
371 JLOG(context.
j.
debug()) << __func__ <<
" : finished";
391 auto& params = context.
params;
399 if (context.
apiVersion > 1u && params.isMember(jss::binary) &&
400 !params[jss::binary].isBool())
404 if (context.
apiVersion > 1u && params.isMember(jss::forward) &&
405 !params[jss::forward].isBool())
410 args.
limit = params.isMember(jss::limit) ? params[jss::limit].asUInt() : 0;
411 args.
binary = params.isMember(jss::binary) && params[jss::binary].asBool();
413 params.isMember(jss::forward) && params[jss::forward].asBool();
415 if (!params.isMember(jss::account))
419 parseBase58<AccountID>(params[jss::account].asString());
426 if (
auto jv = std::get_if<Json::Value>(&parseRes))
432 args.
ledger = std::get<std::optional<LedgerSpecifier>>(parseRes);
435 if (params.isMember(jss::marker))
437 auto& token = params[jss::marker];
438 if (!token.isMember(jss::ledger) || !token.isMember(jss::seq) ||
439 !token[jss::ledger].isConvertibleTo(Json::ValueType::uintValue) ||
440 !token[jss::seq].isConvertibleTo(Json::ValueType::uintValue))
444 "invalid marker. Provide ledger index via ledger field, and "
445 "transaction sequence number via seq field"};
446 status.inject(response);
449 args.
marker = {token[jss::ledger].asUInt(), token[jss::seq].asUInt()};
453 JLOG(context.
j.
debug()) << __func__ <<
" populating response";