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/Role.h>
38 #include <ripple/rpc/impl/RPCHelpers.h>
40 #include <grpcpp/grpcpp.h>
58 if (params.
isMember(jss::ledger_index_min) ||
59 params.
isMember(jss::ledger_index_max))
61 uint32_t min = params.
isMember(jss::ledger_index_min) &&
62 params[jss::ledger_index_min].
asInt() >= 0
63 ? params[jss::ledger_index_min].
asUInt()
65 uint32_t max = params.
isMember(jss::ledger_index_max) &&
66 params[jss::ledger_index_max].
asInt() >= 0
67 ? params[jss::ledger_index_max].
asUInt()
72 else if (params.
isMember(jss::ledger_hash))
74 auto& hashValue = params[jss::ledger_hash];
75 if (!hashValue.isString())
78 status.inject(response);
83 if (!hash.
parseHex(hashValue.asString()))
86 status.inject(response);
91 else if (params.
isMember(jss::ledger_index))
94 if (params[jss::ledger_index].isNumeric())
95 ledger = params[jss::ledger_index].
asUInt();
100 if (ledgerStr ==
"current" || ledgerStr.
empty())
101 ledger = LedgerShortcut::CURRENT;
102 else if (ledgerStr ==
"closed")
103 ledger = LedgerShortcut::CLOSED;
104 else if (ledgerStr ==
"validated")
105 ledger = LedgerShortcut::VALIDATED;
110 status.inject(response);
145 if constexpr (std::is_same_v<T, LedgerRange>)
147 if (ls.min > uValidatedMin)
151 if (ls.max < uValidatedMax)
155 if (uLedgerMax < uLedgerMin)
165 auto const status = getLedger(ledgerView, ls, context);
174 if (!validated || ledgerView->
info().
seq > uValidatedMax ||
175 ledgerView->
info().
seq < uValidatedMin)
179 uLedgerMin = uLedgerMax = ledgerView->
info().
seq;
201 Throw<std::runtime_error>(
"Failed to get relational database");
203 return db->getAccountTx(args);
209 if (
auto stat = std::get_if<RPC::Status>(&lgrRange))
212 return {result, *stat};
215 result.
ledgerRange = std::get<LedgerRange>(lgrRange);
231 Throw<std::runtime_error>(
"Failed to get relational database");
237 auto [tx, marker] = db->oldestAccountTxPageB(options);
243 auto [tx, marker] = db->newestAccountTxPageB(options);
252 auto [tx, marker] = db->oldestAccountTxPage(options);
258 auto [tx, marker] = db->newestAccountTxPage(options);
265 JLOG(context.
j.
debug()) << __func__ <<
" : finished";
280 error.inject(response);
285 response[jss::validated] =
true;
286 response[jss::limit] = result.
limit;
293 if (
auto txnsData = std::get_if<TxnsData>(&result.
transactions))
296 for (
auto const& [txn, txnMeta] : *txnsData)
307 jvObj[jss::validated] =
true;
308 insertDeliveredAmount(
309 jvObj[jss::meta], context, txn, *txnMeta);
318 for (
auto const& binaryData :
323 jvObj[jss::tx_blob] =
strHex(std::get<0>(binaryData));
324 jvObj[jss::meta] =
strHex(std::get<1>(binaryData));
325 jvObj[jss::ledger_index] = std::get<2>(binaryData);
326 jvObj[jss::validated] =
true;
333 response[jss::marker][jss::ledger] = result.
marker->ledgerSeq;
334 response[jss::marker][jss::seq] = result.
marker->txnSeq;
337 response[
"used_postgres"] =
true;
340 JLOG(context.
j.
debug()) << __func__ <<
" : finished";
360 auto& params = context.
params;
364 args.
limit = params.isMember(jss::limit) ? params[jss::limit].asUInt() : 0;
365 args.
binary = params.isMember(jss::binary) && params[jss::binary].asBool();
367 params.isMember(jss::forward) && params[jss::forward].asBool();
369 if (!params.isMember(jss::account))
373 parseBase58<AccountID>(params[jss::account].asString());
380 if (
auto jv = std::get_if<Json::Value>(&parseRes))
386 args.
ledger = std::get<std::optional<LedgerSpecifier>>(parseRes);
389 if (params.isMember(jss::marker))
391 auto& token = params[jss::marker];
392 if (!token.isMember(jss::ledger) || !token.isMember(jss::seq) ||
393 !token[jss::ledger].isConvertibleTo(Json::ValueType::uintValue) ||
394 !token[jss::seq].isConvertibleTo(Json::ValueType::uintValue))
398 "invalid marker. Provide ledger index via ledger field, and "
399 "transaction sequence number via seq field"};
400 status.inject(response);
403 args.
marker = {token[jss::ledger].asUInt(), token[jss::seq].asUInt()};
407 JLOG(context.
j.
debug()) << __func__ <<
" populating response";