1#include <xrpld/app/rdb/backend/detail/Node.h>
3#include <xrpld/app/ledger/AcceptedLedger.h>
4#include <xrpld/app/ledger/LedgerMaster.h>
5#include <xrpld/app/ledger/LedgerPersistence.h>
6#include <xrpld/app/ledger/LedgerToJson.h>
7#include <xrpld/app/ledger/TransactionMaster.h>
8#include <xrpld/core/Config.h>
10#include <xrpl/basics/Blob.h>
11#include <xrpl/basics/ByteUtilities.h>
12#include <xrpl/basics/Log.h>
13#include <xrpl/basics/RangeSet.h>
14#include <xrpl/basics/base_uint.h>
15#include <xrpl/basics/chrono.h>
16#include <xrpl/basics/contract.h>
17#include <xrpl/basics/safe_cast.h>
18#include <xrpl/beast/utility/Journal.h>
19#include <xrpl/beast/utility/instrumentation.h>
20#include <xrpl/config/Constants.h>
21#include <xrpl/core/NetworkIDService.h>
22#include <xrpl/core/StartUpType.h>
23#include <xrpl/json/to_string.h>
24#include <xrpl/ledger/PendingSaves.h>
25#include <xrpl/nodestore/NodeObject.h>
26#include <xrpl/protocol/AccountID.h>
27#include <xrpl/protocol/ErrorCodes.h>
28#include <xrpl/protocol/HashPrefix.h>
29#include <xrpl/protocol/LedgerHeader.h>
30#include <xrpl/protocol/Protocol.h>
31#include <xrpl/protocol/STTx.h>
32#include <xrpl/protocol/Serializer.h>
33#include <xrpl/protocol/TxMeta.h>
34#include <xrpl/protocol/TxSearched.h>
35#include <xrpl/protocol/XRPAmount.h>
36#include <xrpl/rdb/DBInit.h>
37#include <xrpl/rdb/DatabaseCon.h>
38#include <xrpl/rdb/RelationalDatabase.h>
39#include <xrpl/rdb/SociDB.h>
41#include <boost/filesystem/operations.hpp>
42#include <boost/format/free_funcs.hpp>
43#include <boost/optional/optional.hpp>
44#include <boost/system/detail/error_code.hpp>
48#include <soci/soci-backend.h>
49#include <soci/statement.h>
50#include <soci/transaction.h>
79 static_assert(
kTableTypeCount == 3,
"Need to modify switch statement if enum is modified");
86 return "Transactions";
88 return "AccountTransactions";
91 UNREACHABLE(
"xrpl::detail::toString : invalid TableType");
107 lgr->getSession() << boost::str(
108 boost::format(
"PRAGMA cache_size=-%d;") %
116 tx->getSession() << boost::str(
117 boost::format(
"PRAGMA cache_size=-%d;") %
126 soci::indicator ind = soci::i_null;
128 (tx->getSession().prepare <<
"PRAGMA table_info(AccountTransactions);",
133 soci::into(dfltValue, ind),
142 .ledgerDb = std::move(lgr), .transactionDb = std::move(tx), .valid =
false};
147 return {.ledgerDb = std::move(lgr), .transactionDb = std::move(tx), .valid =
true};
150 return {.ledgerDb = std::move(lgr), .transactionDb = {}, .valid =
true};
158 boost::optional<LedgerIndex> m;
159 session << query, soci::into(m);
168 boost::optional<LedgerIndex> m;
169 session << query, soci::into(m);
176 session <<
"DELETE FROM " <<
toString(type) <<
" WHERE LedgerSeq == " << ledgerSeq <<
";";
182 session <<
"DELETE FROM " <<
toString(type) <<
" WHERE LedgerSeq < " << ledgerSeq <<
";";
189 session <<
"SELECT COUNT(*) AS rows "
201 session <<
"SELECT COUNT(*) AS rows, "
202 "MIN(LedgerSeq) AS first, "
203 "MAX(LedgerSeq) AS last "
221 auto seq = ledger->header().seq;
224 JLOG(j.trace()) <<
"saveValidatedLedger " << (current ?
"" :
"fromAcquire ") << seq;
226 if (!ledger->header().accountHash.isNonZero())
229 JLOG(j.fatal()) <<
"AH is zero: " <<
getJson({*ledger, {}});
230 UNREACHABLE(
"xrpl::detail::saveValidatedLedger : zero account hash");
234 if (ledger->header().accountHash != ledger->stateMap().getHash().asUInt256())
237 JLOG(j.fatal()) <<
"sAL: " << ledger->header().accountHash
238 <<
" != " << ledger->stateMap().getHash();
239 JLOG(j.fatal()) <<
"saveAcceptedLedger: seq=" << seq <<
", current=" << current;
240 UNREACHABLE(
"xrpl::detail::saveValidatedLedger : mismatched account hash");
245 ledger->header().txHash == ledger->txMap().getHash().asUInt256(),
246 "xrpl::detail::saveValidatedLedger : transaction hash match");
252 addRaw(ledger->header(), s);
269 JLOG(j.warn()) <<
"An accepted ledger was missing nodes";
278 static boost::format kDeleteLedger(
"DELETE FROM Ledgers WHERE LedgerSeq = %u;");
279 static boost::format kDeleteTranS1(
"DELETE FROM Transactions WHERE LedgerSeq = %u;");
280 static boost::format kDeleteTranS2(
"DELETE FROM AccountTransactions WHERE LedgerSeq = %u;");
281 static boost::format kDeleteAcctTrans(
282 "DELETE FROM AccountTransactions WHERE TransID = '%s';");
286 *db << boost::str(kDeleteLedger % seq);
294 JLOG(j.fatal()) <<
"TxTables db isn't available";
299 auto db = txnDB->checkoutDb();
301 soci::transaction tr(*db);
303 *db << boost::str(kDeleteTranS1 % seq);
304 *db << boost::str(kDeleteTranS2 % seq);
308 for (
auto const& acceptedLedgerTx : *aLedger)
310 uint256 transactionID = acceptedLedgerTx->getTransactionID();
315 *db << boost::str(kDeleteAcctTrans % transactionID);
317 auto const& accts = acceptedLedgerTx->getAffected();
322 "INSERT INTO AccountTransactions "
323 "(TransID, Account, LedgerSeq, TxnSeq) VALUES ");
331 for (
auto const& account : accts)
353 JLOG(j.trace()) <<
"ActTx: " << sql;
356 else if (
auto const& sleTxn = acceptedLedgerTx->getTxn(); !
isPseudoTx(*sleTxn))
360 JLOG(j.warn()) <<
"Transaction in ledger " << seq <<
" affects no accounts";
366 acceptedLedgerTx->getTxn()->getMetaSQL(
367 seq, acceptedLedgerTx->getEscMeta()) +
373 acceptedLedgerTx->getTxnSeq(),
382 R
"sql(INSERT OR REPLACE INTO Ledgers
383 (LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,
384 CloseTimeRes,CloseFlags,AccountSetHash,TransSetHash)
386 (:ledgerHash,:ledgerSeq,:prevHash,:totalCoins,:closingTime,:prevClosingTime,
387 :closeTimeRes,:closeFlags,:accountSetHash,:transSetHash);)sql");
391 soci::transaction tr(*db);
393 auto const hash =
to_string(ledger->header().hash);
394 auto const parentHash =
to_string(ledger->header().parentHash);
395 auto const drops =
to_string(ledger->header().drops);
396 auto const closeTime = ledger->header().closeTime.time_since_epoch().count();
397 auto const parentCloseTime =
398 ledger->header().parentCloseTime.time_since_epoch().count();
399 auto const closeTimeResolution = ledger->header().closeTimeResolution.count();
400 auto const closeFlags = ledger->header().closeFlags;
401 auto const accountHash =
to_string(ledger->header().accountHash);
402 auto const txHash =
to_string(ledger->header().txHash);
404 *db << kAddLedger, soci::use(hash), soci::use(seq), soci::use(parentHash),
405 soci::use(drops), soci::use(closeTime), soci::use(parentCloseTime),
406 soci::use(closeTimeResolution), soci::use(closeFlags), soci::use(accountHash),
428 boost::optional<std::string> hash, parentHash, accountHash, txHash;
429 boost::optional<std::uint64_t> seq, drops, closeTime, parentCloseTime, closeTimeResolution,
434 "LedgerHash, PrevHash, AccountSetHash, TransSetHash, "
436 "ClosingTime, PrevClosingTime, CloseTimeRes, CloseFlags,"
437 "LedgerSeq FROM Ledgers " +
440 session << sql, soci::into(hash), soci::into(parentHash), soci::into(accountHash),
441 soci::into(txHash), soci::into(drops), soci::into(closeTime), soci::into(parentCloseTime),
442 soci::into(closeTimeResolution), soci::into(closeFlags), soci::into(seq);
444 if (!session.got_data())
446 JLOG(j.
debug()) <<
"Ledger not found: " << sqlSuffix;
457 JLOG(j.
debug()) <<
"Hash parse error for ledger: " << sqlSuffix;
463 JLOG(j.
debug()) <<
"parentHash parse error for ledger: " << sqlSuffix;
469 JLOG(j.
debug()) <<
"accountHash parse error for ledger: " << sqlSuffix;
475 JLOG(j.
debug()) <<
"txHash parse error for ledger: " << sqlSuffix;
480 info.
drops = drops.value_or(0);
481 info.
closeTime = time_point{duration{closeTime.value_or(0)}};
482 info.
parentCloseTime = time_point{duration{parentCloseTime.value_or(0)}};
493 s <<
"WHERE LedgerSeq = " << ledgerSeq;
501 s <<
"ORDER BY LedgerSeq DESC LIMIT 1";
510 " ORDER BY LedgerSeq ASC LIMIT 1";
519 " ORDER BY LedgerSeq DESC LIMIT 1";
527 s <<
"WHERE LedgerHash = '" << ledgerHash <<
"'";
536 std::string sql =
"SELECT LedgerHash FROM Ledgers INDEXED BY SeqLedger WHERE LedgerSeq='";
543 boost::optional<std::string> lh;
544 session << sql, soci::into(lh);
546 if (!session.got_data() || !lh)
564 boost::optional<std::string> lhO, phO;
566 session <<
"SELECT LedgerHash,PrevHash FROM Ledgers "
567 "INDEXED BY SeqLedger WHERE LedgerSeq = :ls;",
568 soci::into(lhO), soci::into(phO), soci::use(ledgerIndex);
572 auto stream = j.
trace();
573 JLOG(stream) <<
"Don't have ledger " << ledgerIndex;
577 LedgerHashPair hashes;
578 if (!hashes.ledgerHash.parseHex(*lhO) || !hashes.parentHash.parseHex(*phO))
580 auto stream = j.
trace();
581 JLOG(stream) <<
"Error parse hashes for ledger " << ledgerIndex;
591 std::string sql =
"SELECT LedgerSeq,LedgerHash,PrevHash FROM Ledgers WHERE LedgerSeq >= ";
593 sql.
append(
" AND LedgerSeq <= ");
600 boost::optional<std::string> ph;
601 soci::statement st = (session.prepare << sql, soci::into(ls), soci::into(lh), soci::into(ph));
610 JLOG(j.
warn()) <<
"Error parsed hash for ledger seq: " << ls;
614 JLOG(j.
warn()) <<
"Null prev hash for ledger seq: " << ls;
618 JLOG(j.
warn()) <<
"Error parsed prev hash for ledger seq: " << ls;
629 "SELECT LedgerSeq, Status, RawTxn "
630 "FROM Transactions ORDER BY LedgerSeq DESC LIMIT %u,%u;") %
631 startIndex % quantity);
638 boost::optional<std::uint64_t> ledgerSeq;
639 boost::optional<std::string> status;
640 soci::blob sociRawTxnBlob(session);
641 soci::indicator rti = soci::i_null;
645 (session.prepare << sql,
646 soci::into(ledgerSeq),
648 soci::into(sociRawTxnBlob, rti));
653 if (soci::i_ok == rti)
655 convert(sociRawTxnBlob, rawTxn);
709 else if (options.
limit == UINT32_MAX)
711 numberOfResults = binary ? kBinaryPageLength : kNonbinaryPageLength;
716 std::min(binary ? kBinaryPageLength : kNonbinaryPageLength, options.
limit);
720 numberOfResults = options.
limit;
728 maxClause = boost::str(
729 boost::format(
"AND AccountTransactions.LedgerSeq <= '%u'") % options.
ledgerRange.
max);
734 minClause = boost::str(
735 boost::format(
"AND AccountTransactions.LedgerSeq >= '%u'") % options.
ledgerRange.
min);
744 "SELECT %s FROM AccountTransactions "
745 "WHERE Account = '%s' %s %s LIMIT %u, %u;") %
754 "AccountTransactions INNER JOIN Transactions "
755 "ON Transactions.TransID = AccountTransactions.TransID "
756 "WHERE Account = '%s' %s %s "
757 "ORDER BY AccountTransactions.LedgerSeq %s, "
758 "AccountTransactions.TxnSeq %s, AccountTransactions.TransID %s "
761 (descending ?
"DESC" :
"ASC") % (descending ?
"DESC" :
"ASC") %
762 (descending ?
"DESC" :
"ASC") % options.
offset % numberOfResults);
764 JLOG(j.
trace()) <<
"txSQL query: " << sql;
791 soci::session& session,
802 "AccountTransactions.LedgerSeq,Status,RawTxn,TxnMeta",
814 boost::optional<std::uint64_t> ledgerSeq;
815 boost::optional<std::string> status;
816 soci::blob sociTxnBlob(session), sociTxnMetaBlob(session);
817 soci::indicator rti = soci::i_null, tmi = soci::i_null;
818 Blob rawTxn, txnMeta;
821 (session.prepare << sql,
822 soci::into(ledgerSeq),
824 soci::into(sociTxnBlob, rti),
825 soci::into(sociTxnMetaBlob, tmi));
830 if (soci::i_ok == rti)
839 if (soci::i_ok == tmi)
841 convert(sociTxnMetaBlob, txnMeta);
854 JLOG(j.
warn()) <<
"Recovering ledger " << seq <<
", txn " << txn->getID();
874 soci::session& session,
877 RelationalDatabase::AccountTxOptions
const& options,
880 return getAccountTxs(session, app, ledgerMaster, options,
false, j);
885 soci::session& session,
891 return getAccountTxs(session, app, ledgerMaster, options,
true, j);
916 soci::session& session,
926 "AccountTransactions.LedgerSeq,Status,RawTxn,TxnMeta",
939 boost::optional<std::uint64_t> ledgerSeq;
940 boost::optional<std::string> status;
941 soci::blob sociTxnBlob(session), sociTxnMetaBlob(session);
942 soci::indicator rti = soci::i_null, tmi = soci::i_null;
945 (session.prepare << sql,
946 soci::into(ledgerSeq),
948 soci::into(sociTxnBlob, rti),
949 soci::into(sociTxnMetaBlob, tmi));
955 if (soci::i_ok == rti)
958 if (soci::i_ok == tmi)
959 convert(sociTxnMetaBlob, txnMeta);
963 ret.
emplace_back(std::move(rawTxn), std::move(txnMeta), seq);
973 soci::session& session,
975 RelationalDatabase::AccountTxOptions
const& options,
983 soci::session& session,
1012 soci::session& session,
1021 bool lookingForMarker = options.
marker.has_value();
1025 if (options.
limit == 0 || options.
limit == UINT32_MAX ||
1028 numberOfResults = pageLength;
1032 numberOfResults = options.
limit;
1043 if (lookingForMarker)
1045 findLedger = options.
marker->ledgerSeq;
1046 findSeq = options.
marker->txnSeq;
1052 R
"(SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,
1053 Status,RawTxn,TxnMeta
1054 FROM AccountTransactions INNER JOIN Transactions
1055 ON Transactions.TransID = AccountTransactions.TransID
1056 AND AccountTransactions.Account = '%s' WHERE
1063 char const*
const order = forward ?
"ASC" :
"DESC";
1065 if (findLedger == 0)
1068 boost::format(kPrefix + R
"(AccountTransactions.LedgerSeq BETWEEN %u AND %u
1069 ORDER BY AccountTransactions.LedgerSeq %s,
1070 AccountTransactions.TxnSeq %s
1073 order % queryLimit);
1077 char const*
const compare = forward ?
">=" :
"<=";
1084 R
"(SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,
1085 Status,RawTxn,TxnMeta
1086 FROM AccountTransactions, Transactions WHERE
1087 (AccountTransactions.TransID = Transactions.TransID AND
1088 AccountTransactions.Account = '%s' AND
1089 AccountTransactions.LedgerSeq BETWEEN %u AND %u)
1091 SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,Status,RawTxn,TxnMeta
1092 FROM AccountTransactions, Transactions WHERE
1093 (AccountTransactions.TransID = Transactions.TransID AND
1094 AccountTransactions.Account = '%s' AND
1095 AccountTransactions.LedgerSeq = %u AND
1096 AccountTransactions.TxnSeq %s %u)
1097 ORDER BY AccountTransactions.LedgerSeq %s,
1098 AccountTransactions.TxnSeq %s
1101 b58acct % minLedger % maxLedger % b58acct % findLedger % compare % findSeq % order %
1102 order % queryLimit);
1110 boost::optional<std::uint64_t> ledgerSeq;
1111 boost::optional<std::uint32_t> txnSeq;
1112 boost::optional<std::string> status;
1113 soci::blob txnData(session);
1114 soci::blob txnMeta(session);
1115 soci::indicator dataPresent = soci::i_null, metaPresent = soci::i_null;
1117 soci::statement st =
1118 (session.prepare << sql,
1119 soci::into(ledgerSeq),
1122 soci::into(txnData, dataPresent),
1123 soci::into(txnMeta, metaPresent));
1129 if (lookingForMarker)
1131 if (findLedger == ledgerSeq.value_or(0) && findSeq == txnSeq.value_or(0))
1133 lookingForMarker =
false;
1140 else if (numberOfResults == 0)
1144 .txnSeq = txnSeq.value_or(0)};
1148 if (dataPresent == soci::i_ok)
1157 if (metaPresent == soci::i_ok)
1167 if (rawMeta.
empty())
1168 onUnsavedLedger(ledgerSeq.value_or(0));
1176 std::move(rawMeta));
1190 return {newmarker, total};
1193std::pair<std::optional<RelationalDatabase::AccountTxMarker>,
int>
1195 soci::session& session,
1196 std::function<
void(std::uint32_t)>
const& onUnsavedLedger,
1197 std::function<
void(std::uint32_t, std::string
const&,
Blob&&,
Blob&&)>
const& onTransaction,
1198 RelationalDatabase::AccountTxPageOptions
const& options,
1199 std::uint32_t pageLength)
1201 return accountTxPage(session, onUnsavedLedger, onTransaction, options, pageLength,
true);
1204std::pair<std::optional<RelationalDatabase::AccountTxMarker>,
int>
1206 soci::session& session,
1207 std::function<
void(std::uint32_t)>
const& onUnsavedLedger,
1208 std::function<
void(std::uint32_t, std::string
const&,
Blob&&,
Blob&&)>
const& onTransaction,
1209 RelationalDatabase::AccountTxPageOptions
const& options,
1210 std::uint32_t pageLength)
1212 return accountTxPage(session, onUnsavedLedger, onTransaction, options, pageLength,
false);
1215std::variant<RelationalDatabase::AccountTx, TxSearched>
1217 soci::session& session,
1224 "SELECT LedgerSeq,Status,RawTxn,TxnMeta "
1225 "FROM Transactions WHERE TransID='";
1231 boost::optional<std::uint64_t> ledgerSeq;
1232 boost::optional<std::string>
status;
1233 Blob rawTxn, rawMeta;
1235 soci::blob sociRawTxnBlob(session), sociRawMetaBlob(session);
1236 soci::indicator txn = soci::i_null, meta = soci::i_null;
1238 session << sql, soci::into(ledgerSeq), soci::into(status), soci::into(sociRawTxnBlob, txn),
1239 soci::into(sociRawMetaBlob, meta);
1241 auto const gotData = session.got_data();
1243 if ((!gotData || txn != soci::i_ok || meta != soci::i_ok) && !
range)
1249 soci::indicator rti = soci::i_null;
1251 session <<
"SELECT COUNT(DISTINCT LedgerSeq) FROM Transactions WHERE "
1252 "LedgerSeq BETWEEN "
1253 <<
range->first() <<
" AND " <<
range->last() <<
";",
1254 soci::into(count, rti);
1256 if (!session.got_data() || rti != soci::i_ok)
1264 convert(sociRawMetaBlob, rawMeta);
1272 return std::pair{std::move(txn),
nullptr};
1278 return std::pair{std::move(txn), std::move(txMeta)};
1280 catch (std::exception& e)
1282 JLOG(app.getJournal(
"Ledger").warn())
1283 <<
"Unable to deserialize transaction from raw SQL value. Error: " << e.
what();
1292dbHasSpace(soci::session& session, Config
const& config, beast::Journal j)
1294 boost::filesystem::space_info
const space =
1299 JLOG(j.
fatal()) <<
"Remaining free disk space is less than 512MB";
1303 if (config.useTxTables())
1306 boost::filesystem::path
const dbPath = dbSetup.dataDir /
kTxDbName;
1307 boost::system::error_code ec;
1308 std::optional<std::uint64_t> dbSize = boost::filesystem::file_size(dbPath, ec);
1311 JLOG(j.
error()) <<
"Error checking transaction db file size: " << ec.message();
1315 static auto const kPageSize = [&] {
1316 std::uint32_t ps = 0;
1317 session <<
"PRAGMA page_size;", soci::into(ps);
1320 static auto const kMaxPages = [&] {
1321 std::uint32_t mp = 0;
1322 session <<
"PRAGMA max_page_count;", soci::into(mp);
1325 std::uint32_t pageCount = 0;
1326 session <<
"PRAGMA page_count;", soci::into(pageCount);
1327 std::uint32_t
const freePages = kMaxPages - pageCount;
1329 JLOG(j.
info()) <<
"Transaction DB pathname: " << dbPath.string()
1330 <<
"; file size: " << dbSize.
value_or(-1) <<
" bytes"
1331 <<
"; SQLite page size: " << kPageSize <<
" bytes"
1332 <<
"; Free pages: " << freePages <<
"; Free space: " << freeSpace
1334 <<
"Note that this does not take into account available disk "
1339 JLOG(j.
fatal()) <<
"Free SQLite space for transaction db is less than "
1340 "512MB. To fix this, xrpld must be executed with the "
1341 "vacuum parameter before restarting. "
1342 "Note that this activity can take multiple days, "
1343 "depending on database size.";
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
virtual Config & config()=0
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
int getValueFor(SizedItem item, std::optional< std::size_t > node=std::nullopt) const
Retrieve the default value for the item at the specified node size.
LockedSociSession checkoutDb()
std::shared_ptr< Ledger const > getLedgerBySeq(std::uint32_t index)
void failedSave(std::uint32_t seq, uint256 const &hash)
std::chrono::time_point< NetClock > time_point
std::chrono::duration< rep, period > duration
virtual std::uint32_t getNetworkID() const noexcept=0
Get the configured network ID.
virtual void store(NodeObjectType type, Blob &&data, uint256 const &hash, std::uint32_t ledgerSeq)=0
Store the object.
void finishWork(LedgerIndex seq)
Finish working on a ledger.
std::vector< AccountTx > AccountTxs
static std::string const & getMetaSQLInsertReplaceHeader()
virtual PendingSaves & getPendingSaves()=0
virtual beast::Journal getJournal(std::string const &name)=0
virtual TransactionMaster & getMasterTransaction()=0
virtual NodeStore::Database & getNodeStore()=0
virtual NetworkIDService & getNetworkIDService()=0
virtual LedgerMaster & getLedgerMaster()=0
virtual TaggedCache< uint256, AcceptedLedger > & getAcceptedLedgerCache()=0
bool inLedger(uint256 const &hash, std::uint32_t ledger, std::optional< uint32_t > tseq, std::optional< uint32_t > netID)
static Transaction::pointer transactionFromSQL(boost::optional< std::uint64_t > const &ledgerSeq, boost::optional< std::string > const &status, Blob const &rawTxn, Application &app)
T emplace_back(T... args)
std::optional< LedgerHeader > getLedgerInfoByHash(soci::session &session, uint256 const &ledgerHash, beast::Journal j)
getLedgerInfoByHash Returns info of ledger with given hash.
static std::pair< std::optional< RelationalDatabase::AccountTxMarker >, int > accountTxPage(soci::session &session, std::function< void(std::uint32_t)> const &onUnsavedLedger, std::function< void(std::uint32_t, std::string const &, Blob &&, Blob &&)> const &onTransaction, RelationalDatabase::AccountTxPageOptions const &options, std::uint32_t pageLength, bool forward)
accountTxPage Searches for the oldest or newest transactions for the account that matches the given c...
std::pair< std::optional< RelationalDatabase::AccountTxMarker >, int > newestAccountTxPage(soci::session &session, std::function< void(std::uint32_t)> const &onUnsavedLedger, std::function< void(std::uint32_t, std::string const &, Blob &&, Blob &&)> const &onTransaction, RelationalDatabase::AccountTxPageOptions const &options, std::uint32_t pageLength)
newestAccountTxPage Searches newest transactions for given account which match given criteria startin...
constexpr int kTableTypeCount
bool saveValidatedLedger(DatabaseCon &ldgDB, std::unique_ptr< DatabaseCon > const &txnDB, Application &app, std::shared_ptr< Ledger const > const &ledger, bool current)
saveValidatedLedger Saves ledger into database.
std::pair< std::optional< RelationalDatabase::AccountTxMarker >, int > oldestAccountTxPage(soci::session &session, std::function< void(std::uint32_t)> const &onUnsavedLedger, std::function< void(std::uint32_t, std::string const &, Blob &&, Blob &&)> const &onTransaction, RelationalDatabase::AccountTxPageOptions const &options, std::uint32_t pageLength)
oldestAccountTxPage Searches oldest transactions for given account which match given criteria startin...
void deleteBeforeLedgerSeq(soci::session &session, TableType type, LedgerIndex ledgerSeq)
deleteBeforeLedgerSeq Deletes all entries in given table for the ledgers with given sequence and all ...
std::optional< LedgerIndex > getMinLedgerSeq(soci::session &session, TableType type)
getMinLedgerSeq Returns minimum ledger sequence in given table.
std::optional< LedgerIndex > getMaxLedgerSeq(soci::session &session, TableType type)
getMaxLedgerSeq Returns maximum ledger sequence in given table.
std::pair< RelationalDatabase::AccountTxs, int > getNewestAccountTxs(soci::session &session, Application &app, LedgerMaster &ledgerMaster, RelationalDatabase::AccountTxOptions const &options, beast::Journal j)
getNewestAccountTxs Returns newest transactions for given account which match given criteria starting...
std::pair< std::vector< std::shared_ptr< Transaction > >, int > getTxHistory(soci::session &session, Application &app, LedgerIndex startIndex, int quantity)
getTxHistory Returns given number of most recent transactions starting from given number of entry.
std::pair< std::vector< RelationalDatabase::txnMetaLedgerType >, int > getOldestAccountTxsB(soci::session &session, Application &app, RelationalDatabase::AccountTxOptions const &options, beast::Journal j)
getOldestAccountTxsB Returns oldest transactions in binary form for given account which match given c...
std::optional< LedgerHeader > getNewestLedgerInfo(soci::session &session, beast::Journal j)
getNewestLedgerInfo Returns info of newest saved ledger.
std::optional< LedgerHeader > getLimitedOldestLedgerInfo(soci::session &session, LedgerIndex ledgerFirstIndex, beast::Journal j)
getLimitedOldestLedgerInfo Returns info of oldest ledger from ledgers with sequences greater or equal...
DatabasePairValid makeLedgerDBs(Config const &config, DatabaseCon::Setup const &setup, DatabaseCon::CheckpointerSetup const &checkpointerSetup, beast::Journal j)
makeLedgerDBs Opens ledger and transactions databases.
RelationalDatabase::CountMinMax getRowsMinMax(soci::session &session, TableType type)
getRowsMinMax Returns minimum ledger sequence, maximum ledger sequence and total number of rows in gi...
static std::pair< RelationalDatabase::AccountTxs, int > getAccountTxs(soci::session &session, Application &app, LedgerMaster &ledgerMaster, RelationalDatabase::AccountTxOptions const &options, bool descending, beast::Journal j)
getAccountTxs Returns the oldest or newest transactions for the account that matches the given criter...
static std::optional< LedgerHeader > getLedgerInfo(soci::session &session, std::string const &sqlSuffix, beast::Journal j)
getLedgerInfo Returns the info of the ledger retrieved from the database by using the provided SQL qu...
std::size_t getRows(soci::session &session, TableType type)
getRows Returns number of rows in given table.
std::optional< LedgerHeader > getLedgerInfoByIndex(soci::session &session, LedgerIndex ledgerSeq, beast::Journal j)
getLedgerInfoByIndex Returns ledger by its sequence.
std::pair< std::vector< RelationalDatabase::txnMetaLedgerType >, int > getNewestAccountTxsB(soci::session &session, Application &app, RelationalDatabase::AccountTxOptions const &options, beast::Journal j)
getNewestAccountTxsB Returns newest transactions in binary form for given account which match given c...
uint256 getHashByIndex(soci::session &session, LedgerIndex ledgerIndex)
getHashByIndex Returns hash of ledger with given sequence.
void deleteByLedgerSeq(soci::session &session, TableType type, LedgerIndex ledgerSeq)
deleteByLedgerSeq Deletes all entries in given table for the ledger with given sequence.
std::pair< RelationalDatabase::AccountTxs, int > getOldestAccountTxs(soci::session &session, Application &app, LedgerMaster &ledgerMaster, RelationalDatabase::AccountTxOptions const &options, beast::Journal j)
getOldestAccountTxs Returns oldest transactions for given account which match given criteria starting...
bool dbHasSpace(soci::session &session, Config const &config, beast::Journal j)
dbHasSpace Checks if given database has available space.
std::optional< LedgerHeader > getLimitedNewestLedgerInfo(soci::session &session, LedgerIndex ledgerFirstIndex, beast::Journal j)
getLimitedNewestLedgerInfo Returns info of newest ledger from ledgers with sequences greater or equal...
static std::pair< std::vector< RelationalDatabase::txnMetaLedgerType >, int > getAccountTxsB(soci::session &session, Application &app, RelationalDatabase::AccountTxOptions const &options, bool descending, beast::Journal j)
getAccountTxsB Returns the oldest or newest transactions in binary form for the account that matches ...
std::variant< RelationalDatabase::AccountTx, TxSearched > getTransaction(soci::session &session, Application &app, uint256 const &id, std::optional< ClosedInterval< uint32_t > > const &range, ErrorCodeI &ec)
getTransaction Returns transaction with given hash.
static std::string toString(TableType type)
to_string Returns the name of a table according to its TableType.
static std::string transactionsSQL(Application &app, std::string selection, RelationalDatabase::AccountTxOptions const &options, bool descending, bool binary, bool count, beast::Journal j)
transactionsSQL Returns a SQL query for selecting the oldest or newest transactions in decoded or bin...
std::optional< LedgerHashPair > getHashesByIndex(soci::session &session, LedgerIndex ledgerIndex, beast::Journal j)
getHashesByIndex Returns hash of the ledger and hash of parent ledger for the ledger of given sequenc...
constexpr std::array< char const *, 5 > kLgrDbInit
bool pendSaveValidated(ServiceRegistry ®istry, std::shared_ptr< Ledger const > const &ledger, bool isSynchronous, bool isCurrent)
Save, or arrange to save, a fully-validated ledger.
std::uint32_t LedgerIndex
A ledger index.
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
constexpr std::array< char const *, 8 > kTxDbInit
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > safeCast(Src s) noexcept
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
constexpr auto kLgrDbName
std::string to_string(BaseUInt< Bits, Tag > const &a)
constexpr auto megabytes(T value) noexcept
void addRaw(LedgerHeader const &, Serializer &, bool includeHash=false)
json::Value getJson(LedgerFill const &fill)
Return a new json::Value representing the ledger with given options.
boost::icl::closed_interval< T > ClosedInterval
A closed interval over the domain T.
constexpr auto kilobytes(T value) noexcept
@ LedgerMaster
ledger master data for signing
DatabaseCon::Setup setupDatabaseCon(Config const &c, std::optional< beast::Journal > j=std::nullopt)
std::vector< unsigned char > Blob
Storage for linear binary data.
bool isPseudoTx(STObject const &tx)
Check whether a transaction is a pseudo-transaction.
void convert(soci::blob &from, std::vector< std::uint8_t > &to)
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
std::array< std::string, 4 > txPragma
std::array< std::string, 1 > lgrPragma
LedgerRange ledgerRange
Ledger sequence range to search.
AccountID const & account
AccountID const & account
std::optional< AccountTxMarker > marker
LedgerIndex minLedgerSequence
LedgerIndex maxLedgerSequence
static constexpr auto kDatabasePath