1#include <xrpld/app/ledger/AcceptedLedger.h>
2#include <xrpld/app/ledger/LedgerMaster.h>
3#include <xrpld/app/ledger/LedgerPersistence.h>
4#include <xrpld/app/ledger/LedgerToJson.h>
5#include <xrpld/app/ledger/TransactionMaster.h>
6#include <xrpld/app/rdb/backend/detail/Node.h>
8#include <xrpl/basics/BasicConfig.h>
9#include <xrpl/basics/StringUtilities.h>
10#include <xrpl/core/NetworkIDService.h>
11#include <xrpl/json/to_string.h>
12#include <xrpl/ledger/PendingSaves.h>
13#include <xrpl/rdb/DatabaseCon.h>
14#include <xrpl/rdb/RelationalDatabase.h>
15#include <xrpl/rdb/SociDB.h>
17#include <boost/range/adaptor/transformed.hpp>
19#include <soci/sqlite3/soci-sqlite3.h>
32 static_assert(
TableTypeCount == 3,
"Need to modify switch statement if enum is modified");
39 return "Transactions";
41 return "AccountTransactions";
44 UNREACHABLE(
"xrpl::detail::to_string : invalid TableType");
60 lgr->getSession() << boost::str(
61 boost::format(
"PRAGMA cache_size=-%d;") %
69 tx->getSession() << boost::str(
70 boost::format(
"PRAGMA cache_size=-%d;") %
79 soci::indicator ind = soci::i_null;
81 (tx->getSession().prepare << (
"PRAGMA table_info(AccountTransactions);"),
86 soci::into(dflt_value, ind),
94 return {std::move(lgr), std::move(tx),
false};
99 return {std::move(lgr), std::move(tx),
true};
102 return {std::move(lgr), {},
true};
110 boost::optional<LedgerIndex> m;
111 session << query, soci::into(m);
120 boost::optional<LedgerIndex> m;
121 session << query, soci::into(m);
128 session <<
"DELETE FROM " <<
to_string(type) <<
" WHERE LedgerSeq == " << ledgerSeq <<
";";
134 session <<
"DELETE FROM " <<
to_string(type) <<
" WHERE LedgerSeq < " << ledgerSeq <<
";";
141 session <<
"SELECT COUNT(*) AS rows "
153 session <<
"SELECT COUNT(*) AS rows, "
154 "MIN(LedgerSeq) AS first, "
155 "MAX(LedgerSeq) AS last "
158 soci::into(res.numberOfRows), soci::into(res.minLedgerSequence),
159 soci::into(res.maxLedgerSequence);
173 auto seq = ledger->header().seq;
176 JLOG(j.trace()) <<
"saveValidatedLedger " << (
current ?
"" :
"fromAcquire ") << seq;
178 if (!ledger->header().accountHash.isNonZero())
181 JLOG(j.fatal()) <<
"AH is zero: " <<
getJson({*ledger, {}});
182 UNREACHABLE(
"xrpl::detail::saveValidatedLedger : zero account hash");
186 if (ledger->header().accountHash != ledger->stateMap().getHash().as_uint256())
189 JLOG(j.fatal()) <<
"sAL: " << ledger->header().accountHash
190 <<
" != " << ledger->stateMap().getHash();
191 JLOG(j.fatal()) <<
"saveAcceptedLedger: seq=" << seq <<
", current=" <<
current;
192 UNREACHABLE(
"xrpl::detail::saveValidatedLedger : mismatched account hash");
197 ledger->header().txHash == ledger->txMap().getHash().as_uint256(),
198 "xrpl::detail::saveValidatedLedger : transaction hash match");
204 addRaw(ledger->header(), s);
216 ledger->header().hash, aLedger);
221 JLOG(j.warn()) <<
"An accepted ledger was missing nodes";
230 static boost::format deleteLedger(
"DELETE FROM Ledgers WHERE LedgerSeq = %u;");
231 static boost::format deleteTrans1(
"DELETE FROM Transactions WHERE LedgerSeq = %u;");
232 static boost::format deleteTrans2(
"DELETE FROM AccountTransactions WHERE LedgerSeq = %u;");
233 static boost::format deleteAcctTrans(
234 "DELETE FROM AccountTransactions WHERE TransID = '%s';");
238 *db << boost::str(deleteLedger % seq);
246 JLOG(j.fatal()) <<
"TxTables db isn't available";
247 Throw<std::runtime_error>(
"TxTables db isn't available");
251 auto db = txnDB->checkoutDb();
253 soci::transaction tr(*db);
255 *db << boost::str(deleteTrans1 % seq);
256 *db << boost::str(deleteTrans2 % seq);
260 for (
auto const& acceptedLedgerTx : *aLedger)
269 auto const& accts = acceptedLedgerTx->getAffected();
274 "INSERT INTO AccountTransactions "
275 "(TransID, Account, LedgerSeq, TxnSeq) VALUES ");
283 for (
auto const& account : accts)
305 JLOG(j.trace()) <<
"ActTx: " << sql;
308 else if (
auto const& sleTxn = acceptedLedgerTx->getTxn(); !
isPseudoTx(*sleTxn))
312 JLOG(j.warn()) <<
"Transaction in ledger " << seq <<
" affects no accounts";
318 acceptedLedgerTx->getTxn()->getMetaSQL(
319 seq, acceptedLedgerTx->getEscMeta()) +
325 acceptedLedgerTx->getTxnSeq(),
334 R
"sql(INSERT OR REPLACE INTO Ledgers
335 (LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,
336 CloseTimeRes,CloseFlags,AccountSetHash,TransSetHash)
338 (:ledgerHash,:ledgerSeq,:prevHash,:totalCoins,:closingTime,:prevClosingTime,
339 :closeTimeRes,:closeFlags,:accountSetHash,:transSetHash);)sql");
343 soci::transaction tr(*db);
345 auto const hash =
to_string(ledger->header().hash);
346 auto const parentHash =
to_string(ledger->header().parentHash);
347 auto const drops =
to_string(ledger->header().drops);
348 auto const closeTime = ledger->header().closeTime.time_since_epoch().count();
349 auto const parentCloseTime =
350 ledger->header().parentCloseTime.time_since_epoch().count();
351 auto const closeTimeResolution = ledger->header().closeTimeResolution.count();
352 auto const closeFlags = ledger->header().closeFlags;
353 auto const accountHash =
to_string(ledger->header().accountHash);
354 auto const txHash =
to_string(ledger->header().txHash);
356 *db << addLedger, soci::use(hash), soci::use(seq), soci::use(parentHash),
357 soci::use(drops), soci::use(closeTime), soci::use(parentCloseTime),
358 soci::use(closeTimeResolution), soci::use(closeFlags), soci::use(accountHash),
380 boost::optional<std::string> hash, parentHash, accountHash, txHash;
381 boost::optional<std::uint64_t> seq, drops, closeTime, parentCloseTime, closeTimeResolution,
386 "LedgerHash, PrevHash, AccountSetHash, TransSetHash, "
388 "ClosingTime, PrevClosingTime, CloseTimeRes, CloseFlags,"
389 "LedgerSeq FROM Ledgers " +
392 session << sql, soci::into(hash), soci::into(parentHash), soci::into(accountHash),
393 soci::into(txHash), soci::into(drops), soci::into(closeTime), soci::into(parentCloseTime),
394 soci::into(closeTimeResolution), soci::into(closeFlags), soci::into(seq);
396 if (!session.got_data())
398 JLOG(j.
debug()) <<
"Ledger not found: " << sqlSuffix;
407 if (hash && !info.hash.parseHex(*hash))
409 JLOG(j.
debug()) <<
"Hash parse error for ledger: " << sqlSuffix;
413 if (parentHash && !info.parentHash.parseHex(*parentHash))
415 JLOG(j.
debug()) <<
"parentHash parse error for ledger: " << sqlSuffix;
419 if (accountHash && !info.accountHash.parseHex(*accountHash))
421 JLOG(j.
debug()) <<
"accountHash parse error for ledger: " << sqlSuffix;
425 if (txHash && !info.txHash.parseHex(*txHash))
427 JLOG(j.
debug()) <<
"txHash parse error for ledger: " << sqlSuffix;
431 info.seq = rangeCheckedCast<std::uint32_t>(seq.value_or(0));
432 info.drops =
drops.value_or(0);
433 info.closeTime = time_point{duration{closeTime.value_or(0)}};
434 info.parentCloseTime = time_point{duration{parentCloseTime.value_or(0)}};
435 info.closeFlags = closeFlags.value_or(0);
436 info.closeTimeResolution = duration{closeTimeResolution.value_or(0)};
445 s <<
"WHERE LedgerSeq = " << ledgerSeq;
453 s <<
"ORDER BY LedgerSeq DESC LIMIT 1";
462 " ORDER BY LedgerSeq ASC LIMIT 1";
471 " ORDER BY LedgerSeq DESC LIMIT 1";
479 s <<
"WHERE LedgerHash = '" << ledgerHash <<
"'";
488 std::string sql =
"SELECT LedgerHash FROM Ledgers INDEXED BY SeqLedger WHERE LedgerSeq='";
495 boost::optional<std::string> lh;
496 session << sql, soci::into(lh);
498 if (!session.got_data() || !lh)
516 boost::optional<std::string> lhO, phO;
518 session <<
"SELECT LedgerHash,PrevHash FROM Ledgers "
519 "INDEXED BY SeqLedger WHERE LedgerSeq = :ls;",
520 soci::into(lhO), soci::into(phO), soci::use(ledgerIndex);
524 auto stream = j.
trace();
525 JLOG(stream) <<
"Don't have ledger " << ledgerIndex;
529 LedgerHashPair hashes;
530 if (!hashes.ledgerHash.parseHex(*lhO) || !hashes.parentHash.parseHex(*phO))
532 auto stream = j.
trace();
533 JLOG(stream) <<
"Error parse hashes for ledger " << ledgerIndex;
543 std::string sql =
"SELECT LedgerSeq,LedgerHash,PrevHash FROM Ledgers WHERE LedgerSeq >= ";
545 sql.
append(
" AND LedgerSeq <= ");
552 boost::optional<std::string> ph;
553 soci::statement st = (session.prepare << sql, soci::into(ls), soci::into(lh), soci::into(ph));
562 JLOG(j.
warn()) <<
"Error parsed hash for ledger seq: " << ls;
566 JLOG(j.
warn()) <<
"Null prev hash for ledger seq: " << ls;
570 JLOG(j.
warn()) <<
"Error parsed prev hash for ledger seq: " << ls;
581 "SELECT LedgerSeq, Status, RawTxn "
582 "FROM Transactions ORDER BY LedgerSeq DESC LIMIT %u,%u;") %
583 startIndex % quantity);
590 boost::optional<std::uint64_t> ledgerSeq;
591 boost::optional<std::string> status;
592 soci::blob sociRawTxnBlob(session);
593 soci::indicator rti = soci::i_null;
597 (session.prepare << sql,
598 soci::into(ledgerSeq),
600 soci::into(sociRawTxnBlob, rti));
605 if (soci::i_ok == rti)
607 convert(sociRawTxnBlob, rawTxn);
646 RelationalDatabase::AccountTxOptions
const& options,
661 else if (options.limit == UINT32_MAX)
663 numberOfResults = binary ? BINARY_PAGE_LENGTH : NONBINARY_PAGE_LENGTH;
665 else if (!options.bUnlimited)
668 std::min(binary ? BINARY_PAGE_LENGTH : NONBINARY_PAGE_LENGTH, options.limit);
672 numberOfResults = options.limit;
678 if (options.ledgerRange.max != 0u)
680 maxClause = boost::str(
681 boost::format(
"AND AccountTransactions.LedgerSeq <= '%u'") % options.ledgerRange.max);
684 if (options.ledgerRange.min != 0u)
686 minClause = boost::str(
687 boost::format(
"AND AccountTransactions.LedgerSeq >= '%u'") % options.ledgerRange.min);
696 "SELECT %s FROM AccountTransactions "
697 "WHERE Account = '%s' %s %s LIMIT %u, %u;") %
698 selection %
toBase58(options.account) % maxClause % minClause % options.offset %
706 "AccountTransactions INNER JOIN Transactions "
707 "ON Transactions.TransID = AccountTransactions.TransID "
708 "WHERE Account = '%s' %s %s "
709 "ORDER BY AccountTransactions.LedgerSeq %s, "
710 "AccountTransactions.TxnSeq %s, AccountTransactions.TransID %s "
712 selection %
toBase58(options.account) % maxClause % minClause %
713 (descending ?
"DESC" :
"ASC") % (descending ?
"DESC" :
"ASC") %
714 (descending ?
"DESC" :
"ASC") % options.offset % numberOfResults);
716 JLOG(j.
trace()) <<
"txSQL query: " << sql;
743 soci::session& session,
746 RelationalDatabase::AccountTxOptions
const& options,
754 "AccountTransactions.LedgerSeq,Status,RawTxn,TxnMeta",
766 boost::optional<std::uint64_t> ledgerSeq;
767 boost::optional<std::string>
status;
768 soci::blob sociTxnBlob(session), sociTxnMetaBlob(session);
769 soci::indicator rti = soci::i_null, tmi = soci::i_null;
770 Blob rawTxn, txnMeta;
773 (session.prepare << sql,
774 soci::into(ledgerSeq),
776 soci::into(sociTxnBlob, rti),
777 soci::into(sociTxnMetaBlob, tmi));
782 if (soci::i_ok == rti)
791 if (soci::i_ok == tmi)
793 convert(sociTxnMetaBlob, txnMeta);
804 auto const seq = rangeCheckedCast<std::uint32_t>(ledgerSeq.value_or(0));
806 JLOG(j.
warn()) <<
"Recovering ledger " << seq <<
", txn " << txn->getID();
826 soci::session& session,
829 RelationalDatabase::AccountTxOptions
const& options,
837 soci::session& session,
868 soci::session& session,
870 RelationalDatabase::AccountTxOptions
const& options,
878 "AccountTransactions.LedgerSeq,Status,RawTxn,TxnMeta",
891 boost::optional<std::uint64_t> ledgerSeq;
892 boost::optional<std::string>
status;
893 soci::blob sociTxnBlob(session), sociTxnMetaBlob(session);
894 soci::indicator rti = soci::i_null, tmi = soci::i_null;
897 (session.prepare << sql,
898 soci::into(ledgerSeq),
900 soci::into(sociTxnBlob, rti),
901 soci::into(sociTxnMetaBlob, tmi));
907 if (soci::i_ok == rti)
910 if (soci::i_ok == tmi)
911 convert(sociTxnMetaBlob, txnMeta);
913 auto const seq = rangeCheckedCast<std::uint32_t>(ledgerSeq.value_or(0));
915 ret.
emplace_back(std::move(rawTxn), std::move(txnMeta), seq);
925 soci::session& session,
927 RelationalDatabase::AccountTxOptions
const& options,
935 soci::session& session,
964 soci::session& session,
967 RelationalDatabase::AccountTxPageOptions
const& options,
973 bool lookingForMarker = options.marker.has_value();
977 if (options.limit == 0 || options.limit == UINT32_MAX ||
978 (options.limit > page_length && !options.bAdmin))
980 numberOfResults = page_length;
984 numberOfResults = options.limit;
995 if (lookingForMarker)
997 findLedger = options.marker->ledgerSeq;
998 findSeq = options.marker->txnSeq;
1004 R
"(SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,
1005 Status,RawTxn,TxnMeta
1006 FROM AccountTransactions INNER JOIN Transactions
1007 ON Transactions.TransID = AccountTransactions.TransID
1008 AND AccountTransactions.Account = '%s' WHERE
1015 char const*
const order =
forward ?
"ASC" :
"DESC";
1017 if (findLedger == 0)
1020 boost::format(prefix + (R
"(AccountTransactions.LedgerSeq BETWEEN %u AND %u
1021 ORDER BY AccountTransactions.LedgerSeq %s,
1022 AccountTransactions.TxnSeq %s
1024 toBase58(options.account) % options.ledgerRange.min % options.ledgerRange.max % order %
1025 order % queryLimit);
1033 auto b58acct =
toBase58(options.account);
1036 R
"(SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,
1037 Status,RawTxn,TxnMeta
1038 FROM AccountTransactions, Transactions WHERE
1039 (AccountTransactions.TransID = Transactions.TransID AND
1040 AccountTransactions.Account = '%s' AND
1041 AccountTransactions.LedgerSeq BETWEEN %u AND %u)
1043 SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,Status,RawTxn,TxnMeta
1044 FROM AccountTransactions, Transactions WHERE
1045 (AccountTransactions.TransID = Transactions.TransID AND
1046 AccountTransactions.Account = '%s' AND
1047 AccountTransactions.LedgerSeq = %u AND
1048 AccountTransactions.TxnSeq %s %u)
1049 ORDER BY AccountTransactions.LedgerSeq %s,
1050 AccountTransactions.TxnSeq %s
1053 b58acct % minLedger % maxLedger % b58acct % findLedger % compare % findSeq % order %
1054 order % queryLimit);
1062 boost::optional<std::uint64_t> ledgerSeq;
1063 boost::optional<std::uint32_t> txnSeq;
1064 boost::optional<std::string>
status;
1065 soci::blob txnData(session);
1066 soci::blob txnMeta(session);
1067 soci::indicator dataPresent = soci::i_null, metaPresent = soci::i_null;
1069 soci::statement st =
1070 (session.prepare << sql,
1071 soci::into(ledgerSeq),
1074 soci::into(txnData, dataPresent),
1075 soci::into(txnMeta, metaPresent));
1081 if (lookingForMarker)
1083 if (findLedger == ledgerSeq.value_or(0) && findSeq == txnSeq.value_or(0))
1085 lookingForMarker =
false;
1092 else if (numberOfResults == 0)
1095 rangeCheckedCast<std::uint32_t>(ledgerSeq.value_or(0)), txnSeq.
value_or(0)};
1099 if (dataPresent == soci::i_ok)
1108 if (metaPresent == soci::i_ok)
1118 if (rawMeta.empty())
1119 onUnsavedLedger(ledgerSeq.value_or(0));
1124 rangeCheckedCast<std::uint32_t>(ledgerSeq.value_or(0)),
1127 std::move(rawMeta));
1141 return {newmarker, total};
1146 soci::session& session,
1149 RelationalDatabase::AccountTxPageOptions
const& options,
1152 return accountTxPage(session, onUnsavedLedger, onTransaction, options, page_length,
true);
1157 soci::session& session,
1160 RelationalDatabase::AccountTxPageOptions
const& options,
1163 return accountTxPage(session, onUnsavedLedger, onTransaction, options, page_length,
false);
1168 soci::session& session,
1175 "SELECT LedgerSeq,Status,RawTxn,TxnMeta "
1176 "FROM Transactions WHERE TransID='";
1182 boost::optional<std::uint64_t> ledgerSeq;
1183 boost::optional<std::string>
status;
1184 Blob rawTxn, rawMeta;
1186 soci::blob sociRawTxnBlob(session), sociRawMetaBlob(session);
1187 soci::indicator txn = soci::i_null, meta = soci::i_null;
1189 session << sql, soci::into(ledgerSeq), soci::into(status), soci::into(sociRawTxnBlob, txn),
1190 soci::into(sociRawMetaBlob, meta);
1192 auto const got_data = session.got_data();
1194 if ((!got_data || txn != soci::i_ok || meta != soci::i_ok) && !
range)
1200 soci::indicator rti = soci::i_null;
1202 session <<
"SELECT COUNT(DISTINCT LedgerSeq) FROM Transactions WHERE "
1203 "LedgerSeq BETWEEN "
1204 <<
range->first() <<
" AND " <<
range->last() <<
";",
1205 soci::into(count, rti);
1207 if (!session.got_data() || rti != soci::i_ok)
1214 convert(sociRawTxnBlob, rawTxn);
1215 convert(sociRawMetaBlob, rawMeta);
1223 return std::pair{std::move(txn),
nullptr};
1225 std::uint32_t const inLedger = rangeCheckedCast<std::uint32_t>(ledgerSeq.value());
1229 return std::pair{std::move(txn), std::move(txMeta)};
1233 JLOG(app.getJournal(
"Ledger").warn())
1234 <<
"Unable to deserialize transaction from raw SQL value. Error: " << e.
what();
1245 boost::filesystem::space_info
const space =
1246 boost::filesystem::space(config.legacy(
"database_path"));
1250 JLOG(j.
fatal()) <<
"Remaining free disk space is less than 512MB";
1254 if (config.useTxTables())
1257 boost::filesystem::path
const dbPath = dbSetup.dataDir /
TxDBName;
1258 boost::system::error_code ec;
1262 JLOG(j.
error()) <<
"Error checking transaction db file size: " << ec.message();
1266 static auto const pageSize = [&] {
1268 session <<
"PRAGMA page_size;", soci::into(ps);
1271 static auto const maxPages = [&] {
1273 session <<
"PRAGMA max_page_count;", soci::into(mp);
1277 session <<
"PRAGMA page_count;", soci::into(pageCount);
1279 std::uint64_t const freeSpace = safe_cast<std::uint64_t>(freePages) * pageSize;
1280 JLOG(j.
info()) <<
"Transaction DB pathname: " << dbPath.string()
1281 <<
"; file size: " << dbSize.
value_or(-1) <<
" bytes"
1282 <<
"; SQLite page size: " << pageSize <<
" bytes"
1283 <<
"; Free pages: " << freePages <<
"; Free space: " << freeSpace
1285 <<
"Note that this does not take into account available disk "
1290 JLOG(j.
fatal()) <<
"Free SQLite space for transaction db is less than "
1291 "512MB. To fix this, rippled must be executed with the "
1292 "vacuum parameter before restarting. "
1293 "Note that this activity can take multiple days, "
1294 "depending on database size.";
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
virtual Config & config()=0
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()
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)
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
T emplace_back(T... args)
int compare(SemanticVersion const &lhs, SemanticVersion const &rhs)
Compare two SemanticVersions against each other.
std::optional< LedgerHeader > getLedgerInfoByHash(soci::session &session, uint256 const &ledgerHash, beast::Journal j)
getLedgerInfoByHash Returns info of ledger with given hash.
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.
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...
std::variant< RelationalDatabase::AccountTx, TxSearched > getTransaction(soci::session &session, Application &app, uint256 const &id, std::optional< ClosedInterval< uint32_t > > const &range, error_code_i &ec)
getTransaction Returns transaction with given hash.
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...
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 page_length, bool forward)
accountTxPage Searches for the oldest or newest transactions for the account that matches the given c...
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::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 page_length)
oldestAccountTxPage Searches oldest transactions for given account which match given criteria startin...
static std::string to_string(TableType type)
to_string Returns the name of a table according to its TableType.
constexpr int TableTypeCount
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 page_length)
newestAccountTxPage Searches newest transactions for given account which match given criteria startin...
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...
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool pendSaveValidated(ServiceRegistry ®istry, std::shared_ptr< Ledger const > const &ledger, bool isSynchronous, bool isCurrent)
Save, or arrange to save, a fully-validated ledger.
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
constexpr std::array< char const *, 8 > TxDBInit
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
@ current
This was a new validation and was added.
constexpr auto megabytes(T value) noexcept
DatabaseCon::Setup setup_DatabaseCon(Config const &c, std::optional< beast::Journal > j=std::nullopt)
std::uint32_t LedgerIndex
A ledger index.
void addRaw(LedgerHeader const &, Serializer &, bool includeHash=false)
std::vector< unsigned char > Blob
Storage for linear binary data.
constexpr auto kilobytes(T value) noexcept
@ ledgerMaster
ledger master data for signing
@ transactionID
transaction plus signature to give transaction ID
constexpr std::array< char const *, 5 > LgrDBInit
bool isPseudoTx(STObject const &tx)
Check whether a transaction is a pseudo-transaction.
void convert(soci::blob &from, std::vector< std::uint8_t > &to)
std::array< std::string, 4 > txPragma
std::array< std::string, 1 > lgrPragma