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/Slice.h>
15#include <xrpl/basics/base_uint.h>
16#include <xrpl/basics/chrono.h>
17#include <xrpl/basics/contract.h>
18#include <xrpl/basics/safe_cast.h>
19#include <xrpl/beast/utility/Journal.h>
20#include <xrpl/beast/utility/instrumentation.h>
21#include <xrpl/config/Constants.h>
22#include <xrpl/core/NetworkIDService.h>
23#include <xrpl/core/StartUpType.h>
24#include <xrpl/json/to_string.h>
25#include <xrpl/ledger/PendingSaves.h>
26#include <xrpl/nodestore/NodeObject.h>
27#include <xrpl/protocol/AccountID.h>
28#include <xrpl/protocol/ErrorCodes.h>
29#include <xrpl/protocol/HashPrefix.h>
30#include <xrpl/protocol/LedgerHeader.h>
31#include <xrpl/protocol/Protocol.h>
32#include <xrpl/protocol/SField.h>
33#include <xrpl/protocol/STTx.h>
34#include <xrpl/protocol/Serializer.h>
35#include <xrpl/protocol/TxMeta.h>
36#include <xrpl/protocol/TxSearched.h>
37#include <xrpl/protocol/XRPAmount.h>
38#include <xrpl/rdb/DBInit.h>
39#include <xrpl/rdb/DatabaseCon.h>
40#include <xrpl/rdb/RelationalDatabase.h>
41#include <xrpl/rdb/SociDB.h>
43#include <boost/optional/optional.hpp>
44#include <boost/system/detail/error_code.hpp>
46#include <soci/blob-exchange.h>
48#include <soci/boost-optional.h>
50#include <soci/soci-backend.h>
51#include <soci/statement.h>
52#include <soci/transaction.h>
84 static_assert(
kTableTypeCount == 3,
"Need to modify switch statement if enum is modified");
91 return "Transactions";
93 return "AccountTransactions";
96 UNREACHABLE(
"xrpl::detail::toString : invalid TableType");
129 soci::indicator ind = soci::i_null;
131 (tx->getSession().prepare <<
"PRAGMA table_info(AccountTransactions);",
136 soci::into(dfltValue, ind),
145 .ledgerDb = std::move(lgr), .transactionDb = std::move(tx), .valid =
false};
150 return {.ledgerDb = std::move(lgr), .transactionDb = std::move(tx), .valid =
true};
153 return {.ledgerDb = std::move(lgr), .transactionDb = {}, .valid =
true};
161 boost::optional<LedgerIndex> m;
162 session << query, soci::into(m);
171 boost::optional<LedgerIndex> m;
172 session << query, soci::into(m);
179 session <<
"DELETE FROM " <<
toString(type) <<
" WHERE LedgerSeq == " << ledgerSeq <<
";";
185 session <<
"DELETE FROM " <<
toString(type) <<
" WHERE LedgerSeq < " << ledgerSeq <<
";";
192 session <<
"SELECT COUNT(*) AS rows "
204 session <<
"SELECT COUNT(*) AS rows, "
205 "MIN(LedgerSeq) AS first, "
206 "MAX(LedgerSeq) AS last "
224 auto seq = ledger->header().seq;
227 JLOG(j.trace()) <<
"saveValidatedLedger " << (current ?
"" :
"fromAcquire ") << seq;
229 if (!ledger->header().accountHash.isNonZero())
232 JLOG(j.fatal()) <<
"AH is zero: " <<
getJson({*ledger, {}});
233 UNREACHABLE(
"xrpl::detail::saveValidatedLedger : zero account hash");
237 if (ledger->header().accountHash != ledger->stateMap().getHash().asUInt256())
240 JLOG(j.fatal()) <<
"sAL: " << ledger->header().accountHash
241 <<
" != " << ledger->stateMap().getHash();
242 JLOG(j.fatal()) <<
"saveAcceptedLedger: seq=" << seq <<
", current=" << current;
243 UNREACHABLE(
"xrpl::detail::saveValidatedLedger : mismatched account hash");
248 ledger->header().txHash == ledger->txMap().getHash().asUInt256(),
249 "xrpl::detail::saveValidatedLedger : transaction hash match");
255 addRaw(ledger->header(), s);
272 JLOG(j.warn()) <<
"An accepted ledger was missing nodes";
281 static constexpr char const* kDeleteLedger =
"DELETE FROM Ledgers WHERE LedgerSeq = {};";
282 static constexpr char const* kDeleteTranS1 =
283 "DELETE FROM Transactions WHERE LedgerSeq = {};";
284 static constexpr char const* kDeleteTranS2 =
285 "DELETE FROM AccountTransactions WHERE LedgerSeq = {};";
286 static constexpr char const* kDeleteAcctTrans =
287 "DELETE FROM AccountTransactions WHERE TransID = '{}';";
299 JLOG(j.fatal()) <<
"TxTables db isn't available";
304 auto db = txnDB->checkoutDb();
306 soci::transaction tr(*db);
313 for (
auto const& acceptedLedgerTx : *aLedger)
315 uint256 const transactionID = acceptedLedgerTx->getTransactionID();
322 auto const& accts = acceptedLedgerTx->getAffected();
327 "INSERT INTO AccountTransactions "
328 "(TransID, Account, LedgerSeq, TxnSeq) VALUES ");
336 for (
auto const& account : accts)
358 JLOG(j.trace()) <<
"ActTx: " << sql;
361 else if (
auto const& sleTxn = acceptedLedgerTx->getTxn(); !
isPseudoTx(*sleTxn))
365 JLOG(j.warn()) <<
"Transaction in ledger " << seq <<
" affects no accounts";
371 acceptedLedgerTx->getTxn()->getMetaSQL(
372 seq, acceptedLedgerTx->getEscMeta()) +
378 acceptedLedgerTx->getTxnSeq(),
387 R
"sql(INSERT OR REPLACE INTO Ledgers
388 (LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,
389 CloseTimeRes,CloseFlags,AccountSetHash,TransSetHash)
391 (:ledgerHash,:ledgerSeq,:prevHash,:totalCoins,:closingTime,:prevClosingTime,
392 :closeTimeRes,:closeFlags,:accountSetHash,:transSetHash);)sql");
396 soci::transaction tr(*db);
398 auto const hash =
to_string(ledger->header().hash);
399 auto const parentHash =
to_string(ledger->header().parentHash);
400 auto const drops =
to_string(ledger->header().drops);
401 auto const closeTime = ledger->header().closeTime.time_since_epoch().count();
402 auto const parentCloseTime =
403 ledger->header().parentCloseTime.time_since_epoch().count();
404 auto const closeTimeResolution = ledger->header().closeTimeResolution.count();
405 auto const closeFlags = ledger->header().closeFlags;
406 auto const accountHash =
to_string(ledger->header().accountHash);
407 auto const txHash =
to_string(ledger->header().txHash);
409 *db << kAddLedger, soci::use(hash), soci::use(seq), soci::use(parentHash),
410 soci::use(drops), soci::use(closeTime), soci::use(parentCloseTime),
411 soci::use(closeTimeResolution), soci::use(closeFlags), soci::use(accountHash),
433 boost::optional<std::string> hash, parentHash, accountHash, txHash;
434 boost::optional<std::uint64_t> seq, drops, closeTime, parentCloseTime, closeTimeResolution,
439 "LedgerHash, PrevHash, AccountSetHash, TransSetHash, "
441 "ClosingTime, PrevClosingTime, CloseTimeRes, CloseFlags,"
442 "LedgerSeq FROM Ledgers " +
445 session << sql, soci::into(hash), soci::into(parentHash), soci::into(accountHash),
446 soci::into(txHash), soci::into(drops), soci::into(closeTime), soci::into(parentCloseTime),
447 soci::into(closeTimeResolution), soci::into(closeFlags), soci::into(seq);
449 if (!session.got_data())
451 JLOG(j.
debug()) <<
"Ledger not found: " << sqlSuffix;
462 JLOG(j.
debug()) <<
"Hash parse error for ledger: " << sqlSuffix;
468 JLOG(j.
debug()) <<
"parentHash parse error for ledger: " << sqlSuffix;
474 JLOG(j.
debug()) <<
"accountHash parse error for ledger: " << sqlSuffix;
480 JLOG(j.
debug()) <<
"txHash parse error for ledger: " << sqlSuffix;
485 info.
drops = drops.value_or(0);
486 info.
closeTime = time_point{duration{closeTime.value_or(0)}};
487 info.
parentCloseTime = time_point{duration{parentCloseTime.value_or(0)}};
498 s <<
"WHERE LedgerSeq = " << ledgerSeq;
506 s <<
"ORDER BY LedgerSeq DESC LIMIT 1";
515 " ORDER BY LedgerSeq ASC LIMIT 1";
524 " ORDER BY LedgerSeq DESC LIMIT 1";
532 s <<
"WHERE LedgerHash = '" << ledgerHash <<
"'";
541 std::string sql =
"SELECT LedgerHash FROM Ledgers INDEXED BY SeqLedger WHERE LedgerSeq='";
548 boost::optional<std::string> lh;
549 session << sql, soci::into(lh);
551 if (!session.got_data() || !lh)
569 boost::optional<std::string> lhO, phO;
571 session <<
"SELECT LedgerHash,PrevHash FROM Ledgers "
572 "INDEXED BY SeqLedger WHERE LedgerSeq = :ls;",
573 soci::into(lhO), soci::into(phO), soci::use(ledgerIndex);
577 auto stream = j.
trace();
578 JLOG(stream) <<
"Don't have ledger " << ledgerIndex;
582 LedgerHashPair hashes;
583 if (!hashes.ledgerHash.parseHex(*lhO) || !hashes.parentHash.parseHex(*phO))
585 auto stream = j.
trace();
586 JLOG(stream) <<
"Error parse hashes for ledger " << ledgerIndex;
596 std::string sql =
"SELECT LedgerSeq,LedgerHash,PrevHash FROM Ledgers WHERE LedgerSeq >= ";
598 sql.
append(
" AND LedgerSeq <= ");
605 boost::optional<std::string> ph;
606 soci::statement st = (session.prepare << sql, soci::into(ls), soci::into(lh), soci::into(ph));
615 JLOG(j.
warn()) <<
"Error parsed hash for ledger seq: " << ls;
619 JLOG(j.
warn()) <<
"Null prev hash for ledger seq: " << ls;
623 JLOG(j.
warn()) <<
"Error parsed prev hash for ledger seq: " << ls;
633 "SELECT LedgerSeq, Status, RawTxn "
634 "FROM Transactions ORDER BY LedgerSeq DESC LIMIT {},{};",
643 boost::optional<std::uint64_t> ledgerSeq;
644 boost::optional<std::string> status;
645 soci::blob sociRawTxnBlob(session);
646 soci::indicator rti = soci::i_null;
650 (session.prepare << sql,
651 soci::into(ledgerSeq),
653 soci::into(sociRawTxnBlob, rti));
658 if (soci::i_ok == rti)
660 convert(sociRawTxnBlob, rawTxn);
714 else if (options.
limit == UINT32_MAX)
716 numberOfResults = binary ? kBinaryPageLength : kNonbinaryPageLength;
721 std::min(binary ? kBinaryPageLength : kNonbinaryPageLength, options.
limit);
725 numberOfResults = options.
limit;
748 "SELECT {} FROM AccountTransactions "
749 "WHERE Account = '{}' {} {} LIMIT {}, {};",
759 char const*
const order = descending ?
"DESC" :
"ASC";
762 "AccountTransactions INNER JOIN Transactions "
763 "ON Transactions.TransID = AccountTransactions.TransID "
764 "WHERE Account = '{}' {} {} "
765 "ORDER BY AccountTransactions.LedgerSeq {}, "
766 "AccountTransactions.TxnSeq {}, AccountTransactions.TransID {} "
778 JLOG(j.
trace()) <<
"txSQL query: " << sql;
805 soci::session& session,
816 "AccountTransactions.LedgerSeq,Status,RawTxn,TxnMeta",
828 boost::optional<std::uint64_t> ledgerSeq;
829 boost::optional<std::string> status;
830 soci::blob sociTxnBlob(session), sociTxnMetaBlob(session);
831 soci::indicator rti = soci::i_null, tmi = soci::i_null;
832 Blob rawTxn, txnMeta;
835 (session.prepare << sql,
836 soci::into(ledgerSeq),
838 soci::into(sociTxnBlob, rti),
839 soci::into(sociTxnMetaBlob, tmi));
844 if (soci::i_ok == rti)
853 if (soci::i_ok == tmi)
855 convert(sociTxnMetaBlob, txnMeta);
868 JLOG(j.
warn()) <<
"Recovering ledger " << seq <<
", txn " << txn->getID();
888 soci::session& session,
891 RelationalDatabase::AccountTxOptions
const& options,
894 return getAccountTxs(session, app, ledgerMaster, options,
false, j);
899 soci::session& session,
905 return getAccountTxs(session, app, ledgerMaster, options,
true, j);
930 soci::session& session,
940 "AccountTransactions.LedgerSeq,Status,RawTxn,TxnMeta",
953 boost::optional<std::uint64_t> ledgerSeq;
954 boost::optional<std::string> status;
955 soci::blob sociTxnBlob(session), sociTxnMetaBlob(session);
956 soci::indicator rti = soci::i_null, tmi = soci::i_null;
959 (session.prepare << sql,
960 soci::into(ledgerSeq),
962 soci::into(sociTxnBlob, rti),
963 soci::into(sociTxnMetaBlob, tmi));
969 if (soci::i_ok == rti)
972 if (soci::i_ok == tmi)
973 convert(sociTxnMetaBlob, txnMeta);
977 ret.
emplace_back(std::move(rawTxn), std::move(txnMeta), seq);
987 soci::session& session,
989 RelationalDatabase::AccountTxOptions
const& options,
997 soci::session& session,
1017 Blob const& rawData,
1031 switch (filter.
type)
1036 bool const isDelegated = (txOwner == contextAccount) && (txSigner != contextAccount);
1045 bool const isActingAsDelegate =
1046 (txSigner == contextAccount) && (txOwner != contextAccount);
1047 if (!isActingAsDelegate)
1077 soci::session& session,
1086 bool const hasDelegateFilter = options.
delegate.has_value();
1087 bool lookingForMarker = options.
marker.has_value();
1091 if (options.
limit == 0 || options.
limit == UINT32_MAX ||
1094 numberOfResults = pageLength;
1098 numberOfResults = options.
limit;
1109 if (lookingForMarker)
1111 findLedger = options.
marker->ledgerSeq;
1112 findSeq = options.
marker->txnSeq;
1121 char const*
const order = forward ?
"ASC" :
"DESC";
1123 if (findLedger == 0)
1126 R
"(SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,
1127 Status,RawTxn,TxnMeta
1128 FROM AccountTransactions INNER JOIN Transactions
1129 ON Transactions.TransID = AccountTransactions.TransID
1130 AND AccountTransactions.Account = '{}' WHERE
1131 AccountTransactions.LedgerSeq BETWEEN {} AND {}
1132 ORDER BY AccountTransactions.LedgerSeq {},
1133 AccountTransactions.TxnSeq {}
1144 char const*
const compare = forward ?
">=" :
"<=";
1150 R
"(SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,
1151 Status,RawTxn,TxnMeta
1152 FROM AccountTransactions, Transactions WHERE
1153 (AccountTransactions.TransID = Transactions.TransID AND
1154 AccountTransactions.Account = '{}' AND
1155 AccountTransactions.LedgerSeq BETWEEN {} AND {})
1157 SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,Status,RawTxn,TxnMeta
1158 FROM AccountTransactions, Transactions WHERE
1159 (AccountTransactions.TransID = Transactions.TransID AND
1160 AccountTransactions.Account = '{}' AND
1161 AccountTransactions.LedgerSeq = {} AND
1162 AccountTransactions.TxnSeq {} {})
1163 ORDER BY AccountTransactions.LedgerSeq {},
1164 AccountTransactions.TxnSeq {}
1189 boost::optional<std::uint64_t> ledgerSeq;
1190 boost::optional<std::uint32_t> txnSeq;
1191 boost::optional<std::string> status;
1192 soci::blob txnData(session);
1193 soci::blob txnMeta(session);
1194 soci::indicator dataPresent = soci::i_null, metaPresent = soci::i_null;
1196 soci::statement st =
1197 (session.prepare << sql,
1198 soci::into(ledgerSeq),
1201 soci::into(txnData, dataPresent),
1202 soci::into(txnMeta, metaPresent));
1208 if (hasDelegateFilter)
1213 .txnSeq = txnSeq.value_or(0)};
1216 if (lookingForMarker)
1218 if (findLedger == ledgerSeq.value_or(0) && findSeq == txnSeq.value_or(0))
1220 lookingForMarker =
false;
1223 if (hasDelegateFilter)
1232 if (!hasDelegateFilter && numberOfResults == 0)
1236 .txnSeq = txnSeq.value_or(0)};
1240 if (dataPresent == soci::i_ok)
1249 if (metaPresent == soci::i_ok)
1258 if (hasDelegateFilter)
1260 if (rawData.
empty() ||
1268 if (numberOfResults == 0)
1270 newmarker = lastEmitted;
1276 if (rawMeta.
empty())
1277 onUnsavedLedger(ledgerSeq.value_or(0));
1285 std::move(rawMeta));
1296 if (hasDelegateFilter)
1300 .txnSeq = txnSeq.value_or(0)};
1306 if (hasDelegateFilter && !newmarker && !lookingForMarker && fetchedRows == queryLimit)
1307 newmarker = lastScanned;
1310 return {newmarker, total};
1313std::pair<std::optional<RelationalDatabase::AccountTxMarker>,
int>
1315 soci::session& session,
1316 std::function<
void(std::uint32_t)>
const& onUnsavedLedger,
1317 std::function<
void(std::uint32_t, std::string
const&,
Blob&&,
Blob&&)>
const& onTransaction,
1318 RelationalDatabase::AccountTxPageOptions
const& options,
1319 std::uint32_t pageLength)
1321 return accountTxPage(session, onUnsavedLedger, onTransaction, options, pageLength,
true);
1324std::pair<std::optional<RelationalDatabase::AccountTxMarker>,
int>
1326 soci::session& session,
1327 std::function<
void(std::uint32_t)>
const& onUnsavedLedger,
1328 std::function<
void(std::uint32_t, std::string
const&,
Blob&&,
Blob&&)>
const& onTransaction,
1329 RelationalDatabase::AccountTxPageOptions
const& options,
1330 std::uint32_t pageLength)
1332 return accountTxPage(session, onUnsavedLedger, onTransaction, options, pageLength,
false);
1335std::variant<RelationalDatabase::AccountTx, TxSearched>
1337 soci::session& session,
1344 "SELECT LedgerSeq,Status,RawTxn,TxnMeta "
1345 "FROM Transactions WHERE TransID='";
1351 boost::optional<std::uint64_t> ledgerSeq;
1352 boost::optional<std::string>
status;
1353 Blob rawTxn, rawMeta;
1355 soci::blob sociRawTxnBlob(session), sociRawMetaBlob(session);
1356 soci::indicator txn = soci::i_null, meta = soci::i_null;
1358 session << sql, soci::into(ledgerSeq), soci::into(status), soci::into(sociRawTxnBlob, txn),
1359 soci::into(sociRawMetaBlob, meta);
1361 auto const gotData = session.got_data();
1363 if ((!gotData || txn != soci::i_ok || meta != soci::i_ok) && !
range)
1369 soci::indicator rti = soci::i_null;
1371 session <<
"SELECT COUNT(DISTINCT LedgerSeq) FROM Transactions WHERE "
1372 "LedgerSeq BETWEEN "
1373 <<
range->first() <<
" AND " <<
range->last() <<
";",
1374 soci::into(count, rti);
1376 if (!session.got_data() || rti != soci::i_ok)
1384 convert(sociRawMetaBlob, rawMeta);
1392 return std::pair{std::move(txn),
nullptr};
1398 return std::pair{std::move(txn), std::move(txMeta)};
1400 catch (std::exception& e)
1402 JLOG(app.getJournal(
"Ledger").warn())
1403 <<
"Unable to deserialize transaction from raw SQL value. Error: " << e.
what();
1412dbHasSpace(soci::session& session, Config
const& config, beast::Journal j)
1414 std::filesystem::space_info
const space =
1419 JLOG(j.
fatal()) <<
"Remaining free disk space is less than 512MB";
1423 if (config.useTxTables())
1426 std::filesystem::path
const dbPath = dbSetup.dataDir /
kTxDbName;
1431 JLOG(j.
error()) <<
"Error checking transaction db file size: " << ec.
message();
1435 static auto const kPageSize = [&] {
1436 std::uint32_t ps = 0;
1437 session <<
"PRAGMA page_size;", soci::into(ps);
1440 static auto const kMaxPages = [&] {
1441 std::uint32_t mp = 0;
1442 session <<
"PRAGMA max_page_count;", soci::into(mp);
1445 std::uint32_t pageCount = 0;
1446 session <<
"PRAGMA page_count;", soci::into(pageCount);
1447 std::uint32_t
const freePages = kMaxPages - pageCount;
1449 JLOG(j.
info()) <<
"Transaction DB pathname: " << dbPath.
string()
1450 <<
"; file size: " << dbSize.
value_or(-1) <<
" bytes"
1451 <<
"; SQLite page size: " << kPageSize <<
" bytes"
1452 <<
"; Free pages: " << freePages <<
"; Free space: " << freeSpace
1454 <<
"Note that this does not take into account available disk "
1459 JLOG(j.
fatal()) <<
"Free SQLite space for transaction db is less than "
1460 "512MB. To fix this, xrpld must be executed with the "
1461 "vacuum parameter before restarting. "
1462 "Note that this activity can take multiple days, "
1463 "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.
void finishWork(LedgerIndex seq)
Finish working on a ledger.
std::vector< AccountTx > AccountTxs
bool isFieldPresent(SField const &field) const
AccountID getAccountID(SField const &field) const
static std::string const & getMetaSQLInsertReplaceHeader()
virtual PendingSaves & getPendingSaves()=0
virtual beast::Journal getJournal(std::string const &name)=0
virtual TransactionMaster & getMasterTransaction()=0
virtual NetworkIDService & getNetworkIDService()=0
virtual node_store::Database & getNodeStore()=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)
virtual void store(NodeObjectType type, Blob &&data, uint256 const &hash, std::uint32_t ledgerSeq)=0
Store the object.
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...
static bool passesDelegateFilter(Blob const &rawData, DelegateFilter const &filter, AccountID const &contextAccount)
Determines whether a transaction should be included in account_tx results based on a delegation filte...
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
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
constexpr Dest safeCast(Src s) noexcept
constexpr auto kLgrDbName
std::string to_string(BaseUInt< Bits, Tag > const &a)
@ Authorizer
This account signed and submitted transactions on behalf of another account (this account is the sign...
@ Actor
Another account signed and submitted transactions on behalf of this account (this account is the owne...
Slice makeSlice(std::array< T, N > 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
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
@ 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
std::optional< AccountID > counterparty
LedgerRange ledgerRange
Ledger sequence range to search.
AccountID const & account
AccountID const & account
std::optional< AccountTxMarker > marker
std::optional< DelegateFilter > delegate
LedgerIndex minLedgerSequence
LedgerIndex maxLedgerSequence
static constexpr auto kDatabasePath