20 #include <ripple/app/ledger/LedgerMaster.h>
21 #include <ripple/app/main/Application.h>
22 #include <ripple/app/misc/NetworkOPs.h>
23 #include <ripple/app/misc/Transaction.h>
24 #include <ripple/app/rdb/backend/PostgresDatabase.h>
25 #include <ripple/app/rdb/backend/SQLiteDatabase.h>
26 #include <ripple/core/Pg.h>
27 #include <ripple/json/json_reader.h>
28 #include <ripple/json/json_value.h>
29 #include <ripple/ledger/ReadView.h>
30 #include <ripple/net/RPCErr.h>
31 #include <ripple/protocol/ErrorCodes.h>
32 #include <ripple/protocol/UintTypes.h>
33 #include <ripple/protocol/jss.h>
34 #include <ripple/resource/Fees.h>
35 #include <ripple/rpc/Context.h>
36 #include <ripple/rpc/DeliveredAmount.h>
37 #include <ripple/rpc/NFTSyntheticSerializer.h>
38 #include <ripple/rpc/Role.h>
39 #include <ripple/rpc/impl/RPCHelpers.h>
41 #include <grpcpp/grpcpp.h>
63 if ((params.
isMember(jss::ledger_index_min) ||
64 params.
isMember(jss::ledger_index_max)) &&
65 (params.
isMember(jss::ledger_hash) ||
69 status.inject(response);
73 if (params.
isMember(jss::ledger_index_min) ||
74 params.
isMember(jss::ledger_index_max))
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()
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()
87 else if (params.
isMember(jss::ledger_hash))
89 auto& hashValue = params[jss::ledger_hash];
90 if (!hashValue.isString())
93 status.inject(response);
98 if (!hash.
parseHex(hashValue.asString()))
101 status.inject(response);
106 else if (params.
isMember(jss::ledger_index))
109 if (params[jss::ledger_index].isNumeric())
110 ledger = params[jss::ledger_index].
asUInt();
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;
125 status.inject(response);
160 if constexpr (std::is_same_v<T, LedgerRange>)
167 if ((ls.max > uValidatedMax && ls.max != -1) ||
168 (ls.min < uValidatedMin && ls.min != 0))
173 if (ls.min > uValidatedMin)
177 if (ls.max < uValidatedMax)
181 if (uLedgerMax < uLedgerMin)
191 auto const status = getLedger(ledgerView, ls, context);
200 if (!validated || ledgerView->
info().
seq > uValidatedMax ||
201 ledgerView->
info().
seq < uValidatedMin)
205 uLedgerMin = uLedgerMax = ledgerView->
info().
seq;
227 Throw<std::runtime_error>(
"Failed to get relational database");
229 return db->getAccountTx(args);
235 if (
auto stat = std::get_if<RPC::Status>(&lgrRange))
238 return {result, *stat};
241 result.
ledgerRange = std::get<LedgerRange>(lgrRange);
257 Throw<std::runtime_error>(
"Failed to get relational database");
263 auto [tx, marker] = db->oldestAccountTxPageB(options);
269 auto [tx, marker] = db->newestAccountTxPageB(options);
278 auto [tx, marker] = db->oldestAccountTxPage(options);
284 auto [tx, marker] = db->newestAccountTxPage(options);
291 JLOG(context.
j.
debug()) << __func__ <<
" : finished";
306 error.inject(response);
311 response[jss::validated] =
true;
312 response[jss::limit] = result.
limit;
319 if (
auto txnsData = std::get_if<TxnsData>(&result.
transactions))
322 for (
auto const& [txn, txnMeta] : *txnsData)
333 jvObj[jss::validated] =
true;
334 insertDeliveredAmount(
335 jvObj[jss::meta], context, txn, *txnMeta);
336 insertNFTSyntheticInJson(
337 jvObj, context, txn->getSTransaction(), *txnMeta);
346 for (
auto const& binaryData :
351 jvObj[jss::tx_blob] =
strHex(std::get<0>(binaryData));
352 jvObj[jss::meta] =
strHex(std::get<1>(binaryData));
353 jvObj[jss::ledger_index] = std::get<2>(binaryData);
354 jvObj[jss::validated] =
true;
361 response[jss::marker][jss::ledger] = result.
marker->ledgerSeq;
362 response[jss::marker][jss::seq] = result.
marker->txnSeq;
365 response[
"used_postgres"] =
true;
368 JLOG(context.
j.
debug()) << __func__ <<
" : finished";
388 auto& params = context.
params;
392 args.
limit = params.isMember(jss::limit) ? params[jss::limit].asUInt() : 0;
393 args.
binary = params.isMember(jss::binary) && params[jss::binary].asBool();
395 params.isMember(jss::forward) && params[jss::forward].asBool();
397 if (!params.isMember(jss::account))
401 parseBase58<AccountID>(params[jss::account].asString());
408 if (
auto jv = std::get_if<Json::Value>(&parseRes))
414 args.
ledger = std::get<std::optional<LedgerSpecifier>>(parseRes);
417 if (params.isMember(jss::marker))
419 auto& token = params[jss::marker];
420 if (!token.isMember(jss::ledger) || !token.isMember(jss::seq) ||
421 !token[jss::ledger].isConvertibleTo(Json::ValueType::uintValue) ||
422 !token[jss::seq].isConvertibleTo(Json::ValueType::uintValue))
426 "invalid marker. Provide ledger index via ledger field, and "
427 "transaction sequence number via seq field"};
428 status.inject(response);
431 args.
marker = {token[jss::ledger].asUInt(), token[jss::seq].asUInt()};
435 JLOG(context.
j.
debug()) << __func__ <<
" populating response";