rippled
RelationalDBInterface_nodes.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2020 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/app/ledger/AcceptedLedger.h>
21 #include <ripple/app/ledger/LedgerMaster.h>
22 #include <ripple/app/ledger/LedgerToJson.h>
23 #include <ripple/app/ledger/PendingSaves.h>
24 #include <ripple/app/ledger/TransactionMaster.h>
25 #include <ripple/app/misc/Manifest.h>
26 #include <ripple/app/rdb/RelationalDBInterface.h>
27 #include <ripple/app/rdb/RelationalDBInterface_nodes.h>
28 #include <ripple/basics/BasicConfig.h>
29 #include <ripple/basics/StringUtilities.h>
30 #include <ripple/core/DatabaseCon.h>
31 #include <ripple/core/SociDB.h>
32 #include <ripple/json/to_string.h>
33 #include <boost/algorithm/string.hpp>
34 #include <boost/range/adaptor/transformed.hpp>
35 #include <soci/sqlite3/soci-sqlite3.h>
36 
37 namespace ripple {
38 
44 static std::string
46 {
47  static_assert(
48  TableTypeCount == 3,
49  "Need to modify switch statement if enum is modified");
50  switch (type)
51  {
52  case TableType::Ledgers:
53  return "Ledgers";
55  return "Transactions";
57  return "AccountTransactions";
58  default:
59  assert(0);
60  return "Unknown";
61  }
62 }
63 
64 DatabasePairValid
66  Config const& config,
67  DatabaseCon::Setup const& setup,
68  DatabaseCon::CheckpointerSetup const& checkpointerSetup)
69 {
70  // ledger database
71  auto lgr{std::make_unique<DatabaseCon>(
72  setup, LgrDBName, LgrDBPragma, LgrDBInit, checkpointerSetup)};
73  lgr->getSession() << boost::str(
74  boost::format("PRAGMA cache_size=-%d;") %
76 
77  if (config.useTxTables())
78  {
79  // transaction database
80  auto tx{std::make_unique<DatabaseCon>(
81  setup, TxDBName, TxDBPragma, TxDBInit, checkpointerSetup)};
82  tx->getSession() << boost::str(
83  boost::format("PRAGMA cache_size=-%d;") %
85 
86  if (!setup.standAlone || setup.startUp == Config::LOAD ||
87  setup.startUp == Config::LOAD_FILE ||
88  setup.startUp == Config::REPLAY)
89  {
90  // Check if AccountTransactions has primary key
91  std::string cid, name, type;
92  std::size_t notnull, dflt_value, pk;
93  soci::indicator ind;
94  soci::statement st =
95  (tx->getSession().prepare
96  << ("PRAGMA table_info(AccountTransactions);"),
97  soci::into(cid),
98  soci::into(name),
99  soci::into(type),
100  soci::into(notnull),
101  soci::into(dflt_value, ind),
102  soci::into(pk));
103 
104  st.execute();
105  while (st.fetch())
106  {
107  if (pk == 1)
108  {
109  return {std::move(lgr), std::move(tx), false};
110  }
111  }
112  }
113 
114  return {std::move(lgr), std::move(tx), true};
115  }
116  else
117  return {std::move(lgr), {}, true};
118 }
119 
121 getMinLedgerSeq(soci::session& session, TableType type)
122 {
123  std::string query = "SELECT MIN(LedgerSeq) FROM " + to_string(type) + ";";
124  // SOCI requires boost::optional (not std::optional) as the parameter.
125  boost::optional<LedgerIndex> m;
126  session << query, soci::into(m);
127  return m ? *m : std::optional<LedgerIndex>();
128 }
129 
131 getMaxLedgerSeq(soci::session& session, TableType type)
132 {
133  std::string query = "SELECT MAX(LedgerSeq) FROM " + to_string(type) + ";";
134  // SOCI requires boost::optional (not std::optional) as the parameter.
135  boost::optional<LedgerIndex> m;
136  session << query, soci::into(m);
137  return m ? *m : std::optional<LedgerIndex>();
138 }
139 
140 void
141 deleteByLedgerSeq(soci::session& session, TableType type, LedgerIndex ledgerSeq)
142 {
143  session << "DELETE FROM " << to_string(type)
144  << " WHERE LedgerSeq == " << ledgerSeq << ";";
145 }
146 
147 void
149  soci::session& session,
150  TableType type,
151  LedgerIndex ledgerSeq)
152 {
153  session << "DELETE FROM " << to_string(type) << " WHERE LedgerSeq < "
154  << ledgerSeq << ";";
155 }
156 
158 getRows(soci::session& session, TableType type)
159 {
160  std::size_t rows;
161  session << "SELECT COUNT(*) AS rows "
162  "FROM "
163  << to_string(type) << ";",
164  soci::into(rows);
165 
166  return rows;
167 }
168 
169 RelationalDBInterface::CountMinMax
170 getRowsMinMax(soci::session& session, TableType type)
171 {
173  session << "SELECT COUNT(*) AS rows, "
174  "MIN(LedgerSeq) AS first, "
175  "MAX(LedgerSeq) AS last "
176  "FROM "
177  << to_string(type) << ";",
178  soci::into(res.numberOfRows), soci::into(res.minLedgerSequence),
179  soci::into(res.maxLedgerSequence);
180 
181  return res;
182 }
183 
184 bool
186  DatabaseCon& ldgDB,
187  DatabaseCon& txnDB,
188  Application& app,
189  std::shared_ptr<Ledger const> const& ledger,
190  bool current)
191 {
192  auto j = app.journal("Ledger");
193  auto seq = ledger->info().seq;
194 
195  // TODO(tom): Fix this hard-coded SQL!
196  JLOG(j.trace()) << "saveValidatedLedger " << (current ? "" : "fromAcquire ")
197  << seq;
198 
199  if (!ledger->info().accountHash.isNonZero())
200  {
201  JLOG(j.fatal()) << "AH is zero: " << getJson({*ledger, {}});
202  assert(false);
203  }
204 
205  if (ledger->info().accountHash != ledger->stateMap().getHash().as_uint256())
206  {
207  JLOG(j.fatal()) << "sAL: " << ledger->info().accountHash
208  << " != " << ledger->stateMap().getHash();
209  JLOG(j.fatal()) << "saveAcceptedLedger: seq=" << seq
210  << ", current=" << current;
211  assert(false);
212  }
213 
214  assert(ledger->info().txHash == ledger->txMap().getHash().as_uint256());
215 
216  // Save the ledger header in the hashed object store
217  {
218  Serializer s(128);
220  addRaw(ledger->info(), s);
221  app.getNodeStore().store(
222  hotLEDGER, std::move(s.modData()), ledger->info().hash, seq);
223  }
224 
225  AcceptedLedger::pointer aLedger;
226  try
227  {
228  aLedger = app.getAcceptedLedgerCache().fetch(ledger->info().hash);
229  if (!aLedger)
230  {
231  aLedger = std::make_shared<AcceptedLedger>(ledger, app);
232  app.getAcceptedLedgerCache().canonicalize_replace_client(
233  ledger->info().hash, aLedger);
234  }
235  }
236  catch (std::exception const&)
237  {
238  JLOG(j.warn()) << "An accepted ledger was missing nodes";
239  app.getLedgerMaster().failedSave(seq, ledger->info().hash);
240  // Clients can now trust the database for information about this
241  // ledger sequence.
242  app.pendingSaves().finishWork(seq);
243  return false;
244  }
245 
246  {
247  static boost::format deleteLedger(
248  "DELETE FROM Ledgers WHERE LedgerSeq = %u;");
249  static boost::format deleteTrans1(
250  "DELETE FROM Transactions WHERE LedgerSeq = %u;");
251  static boost::format deleteTrans2(
252  "DELETE FROM AccountTransactions WHERE LedgerSeq = %u;");
253  static boost::format deleteAcctTrans(
254  "DELETE FROM AccountTransactions WHERE TransID = '%s';");
255 
256  {
257  auto db = ldgDB.checkoutDb();
258  *db << boost::str(deleteLedger % seq);
259  }
260 
261  if (app.config().useTxTables())
262  {
263  auto db = txnDB.checkoutDb();
264 
265  soci::transaction tr(*db);
266 
267  *db << boost::str(deleteTrans1 % seq);
268  *db << boost::str(deleteTrans2 % seq);
269 
270  std::string const ledgerSeq(std::to_string(seq));
271 
272  for (auto const& [_, acceptedLedgerTx] : aLedger->getMap())
273  {
274  (void)_;
275  uint256 transactionID = acceptedLedgerTx->getTransactionID();
276 
277  std::string const txnId(to_string(transactionID));
278  std::string const txnSeq(
279  std::to_string(acceptedLedgerTx->getTxnSeq()));
280 
281  *db << boost::str(deleteAcctTrans % transactionID);
282 
283  auto const& accts = acceptedLedgerTx->getAffected();
284 
285  if (!accts.empty())
286  {
287  std::string sql(
288  "INSERT INTO AccountTransactions "
289  "(TransID, Account, LedgerSeq, TxnSeq) VALUES ");
290 
291  // Try to make an educated guess on how much space we'll
292  // need for our arguments. In argument order we have: 64
293  // + 34 + 10 + 10 = 118 + 10 extra = 128 bytes
294  sql.reserve(sql.length() + (accts.size() * 128));
295 
296  bool first = true;
297  for (auto const& account : accts)
298  {
299  if (!first)
300  sql += ", ('";
301  else
302  {
303  sql += "('";
304  first = false;
305  }
306 
307  sql += txnId;
308  sql += "','";
309  sql += app.accountIDCache().toBase58(account);
310  sql += "',";
311  sql += ledgerSeq;
312  sql += ",";
313  sql += txnSeq;
314  sql += ")";
315  }
316  sql += ";";
317  JLOG(j.trace()) << "ActTx: " << sql;
318  *db << sql;
319  }
320  else
321  {
322  JLOG(j.warn()) << "Transaction in ledger " << seq
323  << " affects no accounts";
324  JLOG(j.warn()) << acceptedLedgerTx->getTxn()->getJson(
326  }
327 
328  *db
330  acceptedLedgerTx->getTxn()->getMetaSQL(
331  seq, acceptedLedgerTx->getEscMeta()) +
332  ";");
333 
335  }
336 
337  tr.commit();
338  }
339 
340  {
341  static std::string addLedger(
342  R"sql(INSERT OR REPLACE INTO Ledgers
343  (LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,
344  CloseTimeRes,CloseFlags,AccountSetHash,TransSetHash)
345  VALUES
346  (:ledgerHash,:ledgerSeq,:prevHash,:totalCoins,:closingTime,:prevClosingTime,
347  :closeTimeRes,:closeFlags,:accountSetHash,:transSetHash);)sql");
348 
349  auto db(ldgDB.checkoutDb());
350 
351  soci::transaction tr(*db);
352 
353  auto const hash = to_string(ledger->info().hash);
354  auto const parentHash = to_string(ledger->info().parentHash);
355  auto const drops = to_string(ledger->info().drops);
356  auto const closeTime =
357  ledger->info().closeTime.time_since_epoch().count();
358  auto const parentCloseTime =
359  ledger->info().parentCloseTime.time_since_epoch().count();
360  auto const closeTimeResolution =
361  ledger->info().closeTimeResolution.count();
362  auto const closeFlags = ledger->info().closeFlags;
363  auto const accountHash = to_string(ledger->info().accountHash);
364  auto const txHash = to_string(ledger->info().txHash);
365 
366  *db << addLedger, soci::use(hash), soci::use(seq),
367  soci::use(parentHash), soci::use(drops), soci::use(closeTime),
368  soci::use(parentCloseTime), soci::use(closeTimeResolution),
369  soci::use(closeFlags), soci::use(accountHash),
370  soci::use(txHash);
371 
372  tr.commit();
373  }
374  }
375 
376  return true;
377 }
378 
389  soci::session& session,
390  std::string const& sqlSuffix,
391  beast::Journal j)
392 {
393  // SOCI requires boost::optional (not std::optional) as parameters.
394  boost::optional<std::string> hash, parentHash, accountHash, txHash;
395  boost::optional<std::uint64_t> seq, drops, closeTime, parentCloseTime,
396  closeTimeResolution, closeFlags;
397 
398  std::string const sql =
399  "SELECT "
400  "LedgerHash, PrevHash, AccountSetHash, TransSetHash, "
401  "TotalCoins,"
402  "ClosingTime, PrevClosingTime, CloseTimeRes, CloseFlags,"
403  "LedgerSeq FROM Ledgers " +
404  sqlSuffix + ";";
405 
406  session << sql, soci::into(hash), soci::into(parentHash),
407  soci::into(accountHash), soci::into(txHash), soci::into(drops),
408  soci::into(closeTime), soci::into(parentCloseTime),
409  soci::into(closeTimeResolution), soci::into(closeFlags),
410  soci::into(seq);
411 
412  if (!session.got_data())
413  {
414  JLOG(j.debug()) << "Ledger not found: " << sqlSuffix;
415  return {};
416  }
417 
418  using time_point = NetClock::time_point;
419  using duration = NetClock::duration;
420 
421  LedgerInfo info;
422 
423  if (hash && !info.hash.parseHex(*hash))
424  {
425  JLOG(j.debug()) << "Hash parse error for ledger: " << sqlSuffix;
426  return {};
427  }
428 
429  if (parentHash && !info.parentHash.parseHex(*parentHash))
430  {
431  JLOG(j.debug()) << "parentHash parse error for ledger: " << sqlSuffix;
432  return {};
433  }
434 
435  if (accountHash && !info.accountHash.parseHex(*accountHash))
436  {
437  JLOG(j.debug()) << "accountHash parse error for ledger: " << sqlSuffix;
438  return {};
439  }
440 
441  if (txHash && !info.txHash.parseHex(*txHash))
442  {
443  JLOG(j.debug()) << "txHash parse error for ledger: " << sqlSuffix;
444  return {};
445  }
446 
447  info.seq = rangeCheckedCast<std::uint32_t>(seq.value_or(0));
448  info.drops = drops.value_or(0);
449  info.closeTime = time_point{duration{closeTime.value_or(0)}};
450  info.parentCloseTime = time_point{duration{parentCloseTime.value_or(0)}};
451  info.closeFlags = closeFlags.value_or(0);
452  info.closeTimeResolution = duration{closeTimeResolution.value_or(0)};
453 
454  return info;
455 }
456 
459  soci::session& session,
460  LedgerIndex ledgerSeq,
461  beast::Journal j)
462 {
464  s << "WHERE LedgerSeq = " << ledgerSeq;
465  return getLedgerInfo(session, s.str(), j);
466 }
467 
469 getNewestLedgerInfo(soci::session& session, beast::Journal j)
470 {
472  s << "ORDER BY LedgerSeq DESC LIMIT 1";
473  return getLedgerInfo(session, s.str(), j);
474 }
475 
478  soci::session& session,
479  LedgerIndex ledgerFirstIndex,
480  beast::Journal j)
481 {
483  s << "WHERE LedgerSeq >= " + std::to_string(ledgerFirstIndex) +
484  " ORDER BY LedgerSeq ASC LIMIT 1";
485  return getLedgerInfo(session, s.str(), j);
486 }
487 
490  soci::session& session,
491  LedgerIndex ledgerFirstIndex,
492  beast::Journal j)
493 {
495  s << "WHERE LedgerSeq >= " + std::to_string(ledgerFirstIndex) +
496  " ORDER BY LedgerSeq DESC LIMIT 1";
497  return getLedgerInfo(session, s.str(), j);
498 }
499 
502  soci::session& session,
503  uint256 const& ledgerHash,
504  beast::Journal j)
505 {
507  s << "WHERE LedgerHash = '" << ledgerHash << "'";
508  return getLedgerInfo(session, s.str(), j);
509 }
510 
511 uint256
512 getHashByIndex(soci::session& session, LedgerIndex ledgerIndex)
513 {
514  uint256 ret;
515 
516  std::string sql =
517  "SELECT LedgerHash FROM Ledgers INDEXED BY SeqLedger WHERE LedgerSeq='";
518  sql.append(beast::lexicalCastThrow<std::string>(ledgerIndex));
519  sql.append("';");
520 
521  std::string hash;
522  {
523  // SOCI requires boost::optional (not std::optional) as the parameter.
524  boost::optional<std::string> lh;
525  session << sql, soci::into(lh);
526 
527  if (!session.got_data() || !lh)
528  return ret;
529 
530  hash = *lh;
531  if (hash.empty())
532  return ret;
533  }
534 
535  if (!ret.parseHex(hash))
536  return ret;
537 
538  return ret;
539 }
540 
543  soci::session& session,
544  LedgerIndex ledgerIndex,
545  beast::Journal j)
546 {
547  // SOCI requires boost::optional (not std::optional) as the parameter.
548  boost::optional<std::string> lhO, phO;
549 
550  session << "SELECT LedgerHash,PrevHash FROM Ledgers "
551  "INDEXED BY SeqLedger WHERE LedgerSeq = :ls;",
552  soci::into(lhO), soci::into(phO), soci::use(ledgerIndex);
553 
554  if (!lhO || !phO)
555  {
556  auto stream = j.trace();
557  JLOG(stream) << "Don't have ledger " << ledgerIndex;
558  return {};
559  }
560 
561  LedgerHashPair hashes;
562  if (!hashes.ledgerHash.parseHex(*lhO) || !hashes.parentHash.parseHex(*phO))
563  {
564  auto stream = j.trace();
565  JLOG(stream) << "Error parse hashes for ledger " << ledgerIndex;
566  return {};
567  }
568 
569  return hashes;
570 }
571 
574  soci::session& session,
575  LedgerIndex minSeq,
576  LedgerIndex maxSeq,
577  beast::Journal j)
578 {
579  std::string sql =
580  "SELECT LedgerSeq,LedgerHash,PrevHash FROM Ledgers WHERE LedgerSeq >= ";
581  sql.append(beast::lexicalCastThrow<std::string>(minSeq));
582  sql.append(" AND LedgerSeq <= ");
583  sql.append(beast::lexicalCastThrow<std::string>(maxSeq));
584  sql.append(";");
585 
586  std::uint64_t ls;
587  std::string lh;
588  // SOCI requires boost::optional (not std::optional) as the parameter.
589  boost::optional<std::string> ph;
590  soci::statement st =
591  (session.prepare << sql,
592  soci::into(ls),
593  soci::into(lh),
594  soci::into(ph));
595 
596  st.execute();
598  while (st.fetch())
599  {
600  LedgerHashPair& hashes = res[rangeCheckedCast<LedgerIndex>(ls)];
601  if (!hashes.ledgerHash.parseHex(lh))
602  {
603  JLOG(j.warn()) << "Error parsed hash for ledger seq: " << ls;
604  }
605  if (!ph)
606  {
607  JLOG(j.warn()) << "Null prev hash for ledger seq: " << ls;
608  }
609  else if (!hashes.parentHash.parseHex(*ph))
610  {
611  JLOG(j.warn()) << "Error parsed prev hash for ledger seq: " << ls;
612  }
613  }
614  return res;
615 }
616 
619  soci::session& session,
620  Application& app,
621  LedgerIndex startIndex,
622  int quantity,
623  bool count)
624 {
625  std::string sql = boost::str(
626  boost::format(
627  "SELECT LedgerSeq, Status, RawTxn "
628  "FROM Transactions ORDER BY LedgerSeq DESC LIMIT %u,%u;") %
629  startIndex % quantity);
630 
632  int total = 0;
633 
634  {
635  // SOCI requires boost::optional (not std::optional) as parameters.
636  boost::optional<std::uint64_t> ledgerSeq;
637  boost::optional<std::string> status;
638  soci::blob sociRawTxnBlob(session);
639  soci::indicator rti;
640  Blob rawTxn;
641 
642  soci::statement st =
643  (session.prepare << sql,
644  soci::into(ledgerSeq),
645  soci::into(status),
646  soci::into(sociRawTxnBlob, rti));
647 
648  st.execute();
649  while (st.fetch())
650  {
651  if (soci::i_ok == rti)
652  convert(sociRawTxnBlob, rawTxn);
653  else
654  rawTxn.clear();
655 
656  if (auto trans = Transaction::transactionFromSQL(
657  ledgerSeq, status, rawTxn, app))
658  {
659  total++;
660  txs.push_back(trans);
661  }
662  }
663 
664  if (!total && count)
665  {
666  session << "SELECT COUNT(*) FROM Transactions;", soci::into(total);
667 
668  total = -total;
669  }
670  }
671 
672  return {txs, total};
673 }
674 
694 static std::string
696  Application& app,
697  std::string selection,
698  RelationalDBInterface::AccountTxOptions const& options,
699  std::optional<int> const& limit_used,
700  bool descending,
701  bool binary,
702  bool count,
703  beast::Journal j)
704 {
705  constexpr std::uint32_t NONBINARY_PAGE_LENGTH = 200;
706  constexpr std::uint32_t BINARY_PAGE_LENGTH = 500;
707 
708  std::uint32_t numberOfResults;
709 
710  if (count)
711  {
712  numberOfResults = std::numeric_limits<std::uint32_t>::max();
713  }
714  else if (options.limit == UINT32_MAX)
715  {
716  numberOfResults = binary ? BINARY_PAGE_LENGTH : NONBINARY_PAGE_LENGTH;
717  }
718  else if (!options.bUnlimited)
719  {
720  numberOfResults = std::min(
721  binary ? BINARY_PAGE_LENGTH : NONBINARY_PAGE_LENGTH, options.limit);
722  }
723  else
724  {
725  numberOfResults = options.limit;
726  }
727 
728  if (limit_used)
729  {
730  if (numberOfResults <= *limit_used)
731  return "";
732  else
733  numberOfResults -= *limit_used;
734  }
735 
736  std::string maxClause = "";
737  std::string minClause = "";
738 
739  if (options.maxLedger)
740  {
741  maxClause = boost::str(
742  boost::format("AND AccountTransactions.LedgerSeq <= '%u'") %
743  options.maxLedger);
744  }
745 
746  if (options.minLedger)
747  {
748  minClause = boost::str(
749  boost::format("AND AccountTransactions.LedgerSeq >= '%u'") %
750  options.minLedger);
751  }
752 
753  std::string sql;
754 
755  if (count)
756  sql = boost::str(
757  boost::format("SELECT %s FROM AccountTransactions "
758  "WHERE Account = '%s' %s %s LIMIT %u, %u;") %
759  selection % app.accountIDCache().toBase58(options.account) %
760  maxClause % minClause %
761  beast::lexicalCastThrow<std::string>(options.offset) %
762  beast::lexicalCastThrow<std::string>(numberOfResults));
763  else
764  sql = boost::str(
765  boost::format(
766  "SELECT %s FROM "
767  "AccountTransactions INNER JOIN Transactions "
768  "ON Transactions.TransID = AccountTransactions.TransID "
769  "WHERE Account = '%s' %s %s "
770  "ORDER BY AccountTransactions.LedgerSeq %s, "
771  "AccountTransactions.TxnSeq %s, AccountTransactions.TransID %s "
772  "LIMIT %u, %u;") %
773  selection % app.accountIDCache().toBase58(options.account) %
774  maxClause % minClause % (descending ? "DESC" : "ASC") %
775  (descending ? "DESC" : "ASC") % (descending ? "DESC" : "ASC") %
776  beast::lexicalCastThrow<std::string>(options.offset) %
777  beast::lexicalCastThrow<std::string>(numberOfResults));
778  JLOG(j.trace()) << "txSQL query: " << sql;
779  return sql;
780 }
781 
803  soci::session& session,
804  Application& app,
805  LedgerMaster& ledgerMaster,
806  RelationalDBInterface::AccountTxOptions const& options,
807  std::optional<int> const& limit_used,
808  bool descending,
809  beast::Journal j)
810 {
812 
814  app,
815  "AccountTransactions.LedgerSeq,Status,RawTxn,TxnMeta",
816  options,
817  limit_used,
818  descending,
819  false,
820  false,
821  j);
822  if (sql == "")
823  return {ret, 0};
824 
825  int total = 0;
826  {
827  // SOCI requires boost::optional (not std::optional) as parameters.
828  boost::optional<std::uint64_t> ledgerSeq;
829  boost::optional<std::string> status;
830  soci::blob sociTxnBlob(session), sociTxnMetaBlob(session);
831  soci::indicator rti, tmi;
832  Blob rawTxn, txnMeta;
833 
834  soci::statement st =
835  (session.prepare << sql,
836  soci::into(ledgerSeq),
837  soci::into(status),
838  soci::into(sociTxnBlob, rti),
839  soci::into(sociTxnMetaBlob, tmi));
840 
841  st.execute();
842  while (st.fetch())
843  {
844  if (soci::i_ok == rti)
845  convert(sociTxnBlob, rawTxn);
846  else
847  rawTxn.clear();
848 
849  if (soci::i_ok == tmi)
850  convert(sociTxnMetaBlob, txnMeta);
851  else
852  txnMeta.clear();
853 
854  auto txn =
855  Transaction::transactionFromSQL(ledgerSeq, status, rawTxn, app);
856 
857  if (txnMeta.empty())
858  { // Work around a bug that could leave the metadata missing
859  auto const seq =
860  rangeCheckedCast<std::uint32_t>(ledgerSeq.value_or(0));
861 
862  JLOG(j.warn())
863  << "Recovering ledger " << seq << ", txn " << txn->getID();
864 
865  if (auto l = ledgerMaster.getLedgerBySeq(seq))
866  pendSaveValidated(app, l, false, false);
867  }
868 
869  if (txn)
870  {
871  ret.emplace_back(
872  txn,
873  std::make_shared<TxMeta>(
874  txn->getID(), txn->getLedger(), txnMeta));
875  total++;
876  }
877  }
878 
879  if (!total && limit_used)
880  {
881  RelationalDBInterface::AccountTxOptions opt = options;
882  opt.offset = 0;
884  app, "COUNT(*)", opt, limit_used, descending, false, false, j);
885 
886  session << sql1, soci::into(total);
887 
888  total = ~total;
889  }
890  }
891 
892  return {ret, total};
893 }
894 
897  soci::session& session,
898  Application& app,
899  LedgerMaster& ledgerMaster,
900  RelationalDBInterface::AccountTxOptions const& options,
901  std::optional<int> const& limit_used,
902  beast::Journal j)
903 {
905  session, app, ledgerMaster, options, limit_used, false, j);
906 }
907 
910  soci::session& session,
911  Application& app,
912  LedgerMaster& ledgerMaster,
913  RelationalDBInterface::AccountTxOptions const& options,
914  std::optional<int> const& limit_used,
915  beast::Journal j)
916 {
917  return getAccountTxs(
918  session, app, ledgerMaster, options, limit_used, true, j);
919 }
920 
942  soci::session& session,
943  Application& app,
944  RelationalDBInterface::AccountTxOptions const& options,
945  std::optional<int> const& limit_used,
946  bool descending,
947  beast::Journal j)
948 {
950 
952  app,
953  "AccountTransactions.LedgerSeq,Status,RawTxn,TxnMeta",
954  options,
955  limit_used,
956  descending,
957  true /*binary*/,
958  false,
959  j);
960  if (sql == "")
961  return {ret, 0};
962 
963  int total = 0;
964 
965  {
966  // SOCI requires boost::optional (not std::optional) as parameters.
967  boost::optional<std::uint64_t> ledgerSeq;
968  boost::optional<std::string> status;
969  soci::blob sociTxnBlob(session), sociTxnMetaBlob(session);
970  soci::indicator rti, tmi;
971 
972  soci::statement st =
973  (session.prepare << sql,
974  soci::into(ledgerSeq),
975  soci::into(status),
976  soci::into(sociTxnBlob, rti),
977  soci::into(sociTxnMetaBlob, tmi));
978 
979  st.execute();
980  while (st.fetch())
981  {
982  Blob rawTxn;
983  if (soci::i_ok == rti)
984  convert(sociTxnBlob, rawTxn);
985  Blob txnMeta;
986  if (soci::i_ok == tmi)
987  convert(sociTxnMetaBlob, txnMeta);
988 
989  auto const seq =
990  rangeCheckedCast<std::uint32_t>(ledgerSeq.value_or(0));
991 
992  ret.emplace_back(std::move(rawTxn), std::move(txnMeta), seq);
993  total++;
994  }
995 
996  if (!total && limit_used)
997  {
998  RelationalDBInterface::AccountTxOptions opt = options;
999  opt.offset = 0;
1001  app, "COUNT(*)", opt, limit_used, descending, true, false, j);
1002 
1003  session << sql1, soci::into(total);
1004 
1005  total = ~total;
1006  }
1007  }
1009  return {ret, total};
1010 }
1011 
1014  soci::session& session,
1015  Application& app,
1016  RelationalDBInterface::AccountTxOptions const& options,
1017  std::optional<int> const& limit_used,
1018  beast::Journal j)
1020  return getAccountTxsB(session, app, options, limit_used, false, j);
1021 }
1022 
1025  soci::session& session,
1026  Application& app,
1027  RelationalDBInterface::AccountTxOptions const& options,
1028  std::optional<int> const& limit_used,
1029  beast::Journal j)
1030 {
1031  return getAccountTxsB(session, app, options, limit_used, true, j);
1032 }
1033 
1058  soci::session& session,
1059  AccountIDCache const& idCache,
1060  std::function<void(std::uint32_t)> const& onUnsavedLedger,
1061  std::function<
1062  void(std::uint32_t, std::string const&, Blob&&, Blob&&)> const&
1063  onTransaction,
1064  RelationalDBInterface::AccountTxPageOptions const& options,
1065  int limit_used,
1066  std::uint32_t page_length,
1067  bool forward)
1068 {
1069  int total = 0;
1070 
1071  bool lookingForMarker = options.marker.has_value();
1072 
1073  std::uint32_t numberOfResults;
1074 
1075  if (options.limit == 0 || options.limit == UINT32_MAX ||
1076  (options.limit > page_length && !options.bAdmin))
1077  numberOfResults = page_length;
1078  else
1079  numberOfResults = options.limit;
1080 
1081  if (numberOfResults < limit_used)
1082  return {options.marker, -1};
1083  numberOfResults -= limit_used;
1084 
1085  // As an account can have many thousands of transactions, there is a limit
1086  // placed on the amount of transactions returned. If the limit is reached
1087  // before the result set has been exhausted (we always query for one more
1088  // than the limit), then we return an opaque marker that can be supplied in
1089  // a subsequent query.
1090  std::uint32_t queryLimit = numberOfResults + 1;
1091  std::uint32_t findLedger = 0, findSeq = 0;
1092 
1093  if (lookingForMarker)
1094  {
1095  findLedger = options.marker->ledgerSeq;
1096  findSeq = options.marker->txnSeq;
1097  }
1098 
1100  if (limit_used > 0)
1101  newmarker = options.marker;
1102 
1103  static std::string const prefix(
1104  R"(SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,
1105  Status,RawTxn,TxnMeta
1106  FROM AccountTransactions INNER JOIN Transactions
1107  ON Transactions.TransID = AccountTransactions.TransID
1108  AND AccountTransactions.Account = '%s' WHERE
1109  )");
1110 
1111  std::string sql;
1112 
1113  // SQL's BETWEEN uses a closed interval ([a,b])
1114 
1115  const char* const order = forward ? "ASC" : "DESC";
1116 
1117  if (findLedger == 0)
1118  {
1119  sql = boost::str(
1120  boost::format(
1121  prefix + (R"(AccountTransactions.LedgerSeq BETWEEN '%u' AND '%u'
1122  ORDER BY AccountTransactions.LedgerSeq %s,
1123  AccountTransactions.TxnSeq %s
1124  LIMIT %u;)")) %
1125  idCache.toBase58(options.account) % options.minLedger %
1126  options.maxLedger % order % order % queryLimit);
1127  }
1128  else
1129  {
1130  const char* const compare = forward ? ">=" : "<=";
1131  const std::uint32_t minLedger =
1132  forward ? findLedger + 1 : options.minLedger;
1133  const std::uint32_t maxLedger =
1134  forward ? options.maxLedger : findLedger - 1;
1135 
1136  auto b58acct = idCache.toBase58(options.account);
1137  sql = boost::str(
1138  boost::format((
1139  R"(SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,
1140  Status,RawTxn,TxnMeta
1141  FROM AccountTransactions, Transactions WHERE
1142  (AccountTransactions.TransID = Transactions.TransID AND
1143  AccountTransactions.Account = '%s' AND
1144  AccountTransactions.LedgerSeq BETWEEN '%u' AND '%u')
1145  OR
1146  (AccountTransactions.TransID = Transactions.TransID AND
1147  AccountTransactions.Account = '%s' AND
1148  AccountTransactions.LedgerSeq = '%u' AND
1149  AccountTransactions.TxnSeq %s '%u')
1150  ORDER BY AccountTransactions.LedgerSeq %s,
1151  AccountTransactions.TxnSeq %s
1152  LIMIT %u;
1153  )")) %
1154  b58acct % minLedger % maxLedger % b58acct % findLedger % compare %
1155  findSeq % order % order % queryLimit);
1156  }
1157 
1158  {
1159  Blob rawData;
1160  Blob rawMeta;
1161 
1162  // SOCI requires boost::optional (not std::optional) as parameters.
1163  boost::optional<std::uint64_t> ledgerSeq;
1164  boost::optional<std::uint32_t> txnSeq;
1165  boost::optional<std::string> status;
1166  soci::blob txnData(session);
1167  soci::blob txnMeta(session);
1168  soci::indicator dataPresent, metaPresent;
1169 
1170  soci::statement st =
1171  (session.prepare << sql,
1172  soci::into(ledgerSeq),
1173  soci::into(txnSeq),
1174  soci::into(status),
1175  soci::into(txnData, dataPresent),
1176  soci::into(txnMeta, metaPresent));
1177 
1178  st.execute();
1179 
1180  while (st.fetch())
1181  {
1182  if (lookingForMarker)
1183  {
1184  if (findLedger == ledgerSeq.value_or(0) &&
1185  findSeq == txnSeq.value_or(0))
1186  {
1187  lookingForMarker = false;
1188  }
1189  else
1190  continue;
1191  }
1192  else if (numberOfResults == 0)
1193  {
1194  newmarker = {
1195  rangeCheckedCast<std::uint32_t>(ledgerSeq.value_or(0)),
1196  txnSeq.value_or(0)};
1197  break;
1198  }
1199 
1200  if (dataPresent == soci::i_ok)
1201  convert(txnData, rawData);
1202  else
1203  rawData.clear();
1204 
1205  if (metaPresent == soci::i_ok)
1206  convert(txnMeta, rawMeta);
1207  else
1208  rawMeta.clear();
1209 
1210  // Work around a bug that could leave the metadata missing
1211  if (rawMeta.size() == 0)
1212  onUnsavedLedger(ledgerSeq.value_or(0));
1213 
1214  // `rawData` and `rawMeta` will be used after they are moved.
1215  // That's OK.
1216  onTransaction(
1217  rangeCheckedCast<std::uint32_t>(ledgerSeq.value_or(0)),
1218  *status,
1219  std::move(rawData),
1220  std::move(rawMeta));
1221  // Note some callbacks will move the data, some will not. Clear
1222  // them so code doesn't depend on if the data was actually moved
1223  // or not. The code will be more efficient if `rawData` and
1224  // `rawMeta` don't have to allocate in `convert`, so don't
1225  // refactor my moving these variables into loop scope.
1226  rawData.clear();
1227  rawMeta.clear();
1228 
1229  --numberOfResults;
1230  total++;
1231  }
1232  }
1233 
1234  return {newmarker, total};
1235 }
1236 
1239  soci::session& session,
1240  AccountIDCache const& idCache,
1241  std::function<void(std::uint32_t)> const& onUnsavedLedger,
1242  std::function<
1243  void(std::uint32_t, std::string const&, Blob&&, Blob&&)> const&
1244  onTransaction,
1246  int limit_used,
1247  std::uint32_t page_length)
1248 {
1249  return accountTxPage(
1250  session,
1251  idCache,
1252  onUnsavedLedger,
1253  onTransaction,
1254  options,
1255  limit_used,
1256  page_length,
1257  true);
1258 }
1259 
1262  soci::session& session,
1263  AccountIDCache const& idCache,
1264  std::function<void(std::uint32_t)> const& onUnsavedLedger,
1265  std::function<
1266  void(std::uint32_t, std::string const&, Blob&&, Blob&&)> const&
1267  onTransaction,
1269  int limit_used,
1270  std::uint32_t page_length)
1271 {
1272  return accountTxPage(
1273  session,
1274  idCache,
1275  onUnsavedLedger,
1276  onTransaction,
1277  options,
1278  limit_used,
1279  page_length,
1280  false);
1281 }
1282 
1285  soci::session& session,
1286  Application& app,
1287  uint256 const& id,
1288  std::optional<ClosedInterval<uint32_t>> const& range,
1289  error_code_i& ec)
1290 {
1291  std::string sql =
1292  "SELECT LedgerSeq,Status,RawTxn,TxnMeta "
1293  "FROM Transactions WHERE TransID='";
1294 
1295  sql.append(to_string(id));
1296  sql.append("';");
1297 
1298  // SOCI requires boost::optional (not std::optional) as parameters.
1299  boost::optional<std::uint64_t> ledgerSeq;
1300  boost::optional<std::string> status;
1301  Blob rawTxn, rawMeta;
1302  {
1303  soci::blob sociRawTxnBlob(session), sociRawMetaBlob(session);
1304  soci::indicator txn, meta;
1305 
1306  session << sql, soci::into(ledgerSeq), soci::into(status),
1307  soci::into(sociRawTxnBlob, txn), soci::into(sociRawMetaBlob, meta);
1308 
1309  auto const got_data = session.got_data();
1310 
1311  if ((!got_data || txn != soci::i_ok || meta != soci::i_ok) && !range)
1312  return TxSearched::unknown;
1313 
1314  if (!got_data)
1315  {
1316  uint64_t count = 0;
1317  soci::indicator rti;
1318 
1319  session
1320  << "SELECT COUNT(DISTINCT LedgerSeq) FROM Transactions WHERE "
1321  "LedgerSeq BETWEEN "
1322  << range->first() << " AND " << range->last() << ";",
1323  soci::into(count, rti);
1324 
1325  if (!session.got_data() || rti != soci::i_ok)
1326  return TxSearched::some;
1327 
1328  return count == (range->last() - range->first() + 1)
1329  ? TxSearched::all
1330  : TxSearched::some;
1331  }
1332 
1333  convert(sociRawTxnBlob, rawTxn);
1334  convert(sociRawMetaBlob, rawMeta);
1335  }
1336 
1337  try
1338  {
1339  auto txn =
1340  Transaction::transactionFromSQL(ledgerSeq, status, rawTxn, app);
1342  if (!ledgerSeq)
1343  return std::pair{std::move(txn), nullptr};
1344 
1345  std::uint32_t inLedger =
1346  rangeCheckedCast<std::uint32_t>(ledgerSeq.value());
1347 
1348  auto txMeta = std::make_shared<TxMeta>(id, inLedger, rawMeta);
1349 
1350  return std::pair{std::move(txn), std::move(txMeta)};
1351  }
1352  catch (std::exception& e)
1353  {
1354  JLOG(app.journal("Ledger").warn())
1355  << "Unable to deserialize transaction from raw SQL value. Error: "
1356  << e.what();
1357 
1358  ec = rpcDB_DESERIALIZATION;
1359  }
1360 
1361  return TxSearched::unknown;
1362 }
1363 
1364 bool
1365 dbHasSpace(soci::session& session, Config const& config, beast::Journal j)
1366 {
1367  boost::filesystem::space_info space =
1368  boost::filesystem::space(config.legacy("database_path"));
1369 
1370  if (space.available < megabytes(512))
1371  {
1372  JLOG(j.fatal()) << "Remaining free disk space is less than 512MB";
1373  return false;
1374  }
1375 
1376  if (config.useTxTables())
1377  {
1378  DatabaseCon::Setup dbSetup = setup_DatabaseCon(config);
1379  boost::filesystem::path dbPath = dbSetup.dataDir / TxDBName;
1380  boost::system::error_code ec;
1382  boost::filesystem::file_size(dbPath, ec);
1383  if (ec)
1384  {
1385  JLOG(j.error())
1386  << "Error checking transaction db file size: " << ec.message();
1387  dbSize.reset();
1388  }
1389 
1390  static auto const pageSize = [&] {
1391  std::uint32_t ps;
1392  session << "PRAGMA page_size;", soci::into(ps);
1393  return ps;
1394  }();
1395  static auto const maxPages = [&] {
1396  std::uint32_t mp;
1397  session << "PRAGMA max_page_count;", soci::into(mp);
1398  return mp;
1399  }();
1400  std::uint32_t pageCount;
1401  session << "PRAGMA page_count;", soci::into(pageCount);
1402  std::uint32_t freePages = maxPages - pageCount;
1403  std::uint64_t freeSpace =
1404  safe_cast<std::uint64_t>(freePages) * pageSize;
1405  JLOG(j.info())
1406  << "Transaction DB pathname: " << dbPath.string()
1407  << "; file size: " << dbSize.value_or(-1) << " bytes"
1408  << "; SQLite page size: " << pageSize << " bytes"
1409  << "; Free pages: " << freePages << "; Free space: " << freeSpace
1410  << " bytes; "
1411  << "Note that this does not take into account available disk "
1412  "space.";
1413 
1414  if (freeSpace < megabytes(512))
1415  {
1416  JLOG(j.fatal())
1417  << "Free SQLite space for transaction db is less than "
1418  "512MB. To fix this, rippled must be executed with the "
1419  "vacuum parameter before restarting. "
1420  "Note that this activity can take multiple days, "
1421  "depending on database size.";
1422  return false;
1423  }
1424  }
1425 
1426  return true;
1427 }
1428 
1429 } // namespace ripple
beast::Journal::fatal
Stream fatal() const
Definition: Journal.h:339
ripple::getLedgerInfoByIndex
std::optional< LedgerInfo > getLedgerInfoByIndex(soci::session &session, LedgerIndex ledgerSeq, beast::Journal j)
getLedgerInfoByIndex Returns ledger by its sequence.
Definition: RelationalDBInterface_nodes.cpp:453
ripple::Application
Definition: Application.h:102
ripple::deleteBeforeLedgerSeq
void deleteBeforeLedgerSeq(soci::session &session, TableType type, LedgerIndex ledgerSeq)
deleteBeforeLedgerSeq Deletes all entries in given table for the ledgers with given sequence and all ...
Definition: RelationalDBInterface_nodes.cpp:148
ripple::Transaction::transactionFromSQL
static Transaction::pointer transactionFromSQL(boost::optional< std::uint64_t > const &ledgerSeq, boost::optional< std::string > const &status, Blob const &rawTxn, Application &app)
Definition: Transaction.cpp:93
ripple::rpcDB_DESERIALIZATION
@ rpcDB_DESERIALIZATION
Definition: ErrorCodes.h:134
ripple::HashPrefix::ledgerMaster
@ ledgerMaster
ledger master data for signing
ripple::Blob
std::vector< unsigned char > Blob
Storage for linear binary data.
Definition: Blob.h:30
ripple::TxSearched::unknown
@ unknown
ripple::Application::getAcceptedLedgerCache
virtual TaggedCache< uint256, AcceptedLedger > & getAcceptedLedgerCache()=0
ripple::LedgerIndex
std::uint32_t LedgerIndex
A ledger index.
Definition: Protocol.h:57
std::string
STL class.
std::shared_ptr
STL class.
ripple::getTxHistory
std::pair< std::vector< std::shared_ptr< Transaction > >, int > getTxHistory(soci::session &session, Application &app, LedgerIndex startIndex, int quantity, bool count)
getTxHistory Returns given number of most recent transactions starting from given number of entry.
Definition: RelationalDBInterface_nodes.cpp:613
ripple::LedgerInfo::parentHash
uint256 parentHash
Definition: ReadView.h:103
ripple::getHashByIndex
uint256 getHashByIndex(soci::session &session, LedgerIndex ledgerIndex)
getHashByIndex Returns hash of ledger with given sequence.
Definition: RelationalDBInterface_nodes.cpp:507
ripple::SHAMap::getHash
SHAMapHash getHash() const
Definition: SHAMap.cpp:783
ripple::getOldestAccountTxs
std::pair< RelationalDBInterface::AccountTxs, int > getOldestAccountTxs(soci::session &session, Application &app, LedgerMaster &ledgerMaster, RelationalDBInterface::AccountTxOptions const &options, std::optional< int > const &limit_used, beast::Journal j)
getOldestAccountTxs Returns oldest transactions for given account which match given criteria starting...
Definition: RelationalDBInterface_nodes.cpp:891
std::exception
STL class.
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:513
ripple::test::jtx::drops
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Definition: amount.h:241
ripple::DatabaseCon::Setup
Definition: DatabaseCon.h:84
ripple::getAccountTxs
static std::pair< RelationalDBInterface::AccountTxs, int > getAccountTxs(soci::session &session, Application &app, LedgerMaster &ledgerMaster, RelationalDBInterface::AccountTxOptions const &options, std::optional< int > const &limit_used, bool descending, beast::Journal j)
getAccountTxs Returns oldest or newest transactions for given account which match given criteria star...
Definition: RelationalDBInterface_nodes.cpp:797
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
Json::stream
void stream(Json::Value const &jv, Write const &write)
Stream compact JSON to the specified function.
Definition: json_writer.h:300
ripple::getOldestAccountTxsB
std::pair< std::vector< RelationalDBInterface::txnMetaLedgerType >, int > getOldestAccountTxsB(soci::session &session, Application &app, RelationalDBInterface::AccountTxOptions const &options, std::optional< int > const &limit_used, beast::Journal j)
getOldestAccountTxsB Returns oldest transactions in binary form for given account which match given c...
Definition: RelationalDBInterface_nodes.cpp:1008
ripple::Serializer::modData
Blob & modData()
Definition: Serializer.h:178
std::pair
std::string::reserve
T reserve(T... args)
ripple::LedgerInfo::hash
uint256 hash
Definition: ReadView.h:100
ripple::TxSearched::all
@ all
ripple::convert
void convert(soci::blob &from, std::vector< std::uint8_t > &to)
Definition: SociDB.cpp:154
ripple::addRaw
void addRaw(LedgerInfo const &info, Serializer &s, bool includeHash)
Definition: View.cpp:44
ripple::setup_DatabaseCon
DatabaseCon::Setup setup_DatabaseCon(Config const &c, std::optional< beast::Journal > j=std::nullopt)
Definition: DatabaseCon.cpp:106
ripple::DatabaseCon::Setup::startUp
Config::StartUpType startUp
Definition: DatabaseCon.h:88
std::vector
STL class.
std::string::length
T length(T... args)
std::optional::value_or
T value_or(T... args)
ripple::getRowsMinMax
RelationalDBInterface::CountMinMax getRowsMinMax(soci::session &session, TableType type)
getRowsMinMax Returns minumum ledger sequence, maximum ledger sequence and total number of rows in gi...
Definition: RelationalDBInterface_nodes.cpp:170
ripple::DatabaseCon::CheckpointerSetup
Definition: DatabaseCon.h:107
ripple::newestAccountTxPage
std::pair< std::optional< RelationalDBInterface::AccountTxMarker >, int > newestAccountTxPage(soci::session &session, AccountIDCache const &idCache, std::function< void(std::uint32_t)> const &onUnsavedLedger, std::function< void(std::uint32_t, std::string const &, Blob &&, Blob &&)> const &onTransaction, RelationalDBInterface::AccountTxPageOptions const &options, int limit_used, std::uint32_t page_length)
newestAccountTxPage Searches newest transactions for given account which match given criteria startin...
Definition: RelationalDBInterface_nodes.cpp:1237
ripple::getLedgerInfoByHash
std::optional< LedgerInfo > getLedgerInfoByHash(soci::session &session, uint256 const &ledgerHash, beast::Journal j)
getLedgerInfoByHash Returns info of ledger with given hash.
Definition: RelationalDBInterface_nodes.cpp:496
ripple::Config::LOAD
@ LOAD
Definition: Config.h:128
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
ripple::kilobytes
constexpr auto kilobytes(T value) noexcept
Definition: ByteUtilities.h:27
ripple::STTx::getMetaSQLInsertReplaceHeader
static std::string const & getMetaSQLInsertReplaceHeader()
Definition: STTx.cpp:231
std::function
ripple::NodeStore::Database::store
virtual void store(NodeObjectType type, Blob &&data, uint256 const &hash, std::uint32_t ledgerSeq)=0
Store the object.
ripple::LedgerInfo::seq
LedgerIndex seq
Definition: ReadView.h:92
ripple::getLimitedNewestLedgerInfo
std::optional< LedgerInfo > getLimitedNewestLedgerInfo(soci::session &session, LedgerIndex ledgerFirstIndex, beast::Journal j)
getLimitedNewestLedgerInfo Returns info of newest ledger from ledgers with sequences greather or equa...
Definition: RelationalDBInterface_nodes.cpp:484
ripple::LedgerInfo::txHash
uint256 txHash
Definition: ReadView.h:101
std::optional::reset
T reset(T... args)
ripple::LgrDBInit
constexpr std::array< char const *, 5 > LgrDBInit
Definition: DBInit.h:48
ripple::AccountIDCache
Caches the base58 representations of AccountIDs.
Definition: AccountID.h:118
ripple::error_code_i
error_code_i
Definition: ErrorCodes.h:40
ripple::getLimitedOldestLedgerInfo
std::optional< LedgerInfo > getLimitedOldestLedgerInfo(soci::session &session, LedgerIndex ledgerFirstIndex, beast::Journal j)
getLimitedOldestLedgerInfo Returns info of oldest ledger from ledgers with sequences greather or equa...
Definition: RelationalDBInterface_nodes.cpp:472
ripple::Application::accountIDCache
virtual AccountIDCache const & accountIDCache() const =0
ripple::getLedgerInfo
static std::optional< LedgerInfo > getLedgerInfo(soci::session &session, std::string const &sqlSuffix, beast::Journal j)
getLedgerInfo Returns info of ledger with special condition given as SQL query.
Definition: RelationalDBInterface_nodes.cpp:383
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:526
std::vector::push_back
T push_back(T... args)
ripple::getNewestAccountTxs
std::pair< RelationalDBInterface::AccountTxs, int > getNewestAccountTxs(soci::session &session, Application &app, LedgerMaster &ledgerMaster, RelationalDBInterface::AccountTxOptions const &options, std::optional< int > const &limit_used, beast::Journal j)
getNewestAccountTxs Returns newest transactions for given account which match given criteria starting...
Definition: RelationalDBInterface_nodes.cpp:904
ripple::LedgerInfo::closeTime
NetClock::time_point closeTime
Definition: ReadView.h:123
ripple::RelationalDBInterface::CountMinMax
Definition: RelationalDBInterface.h:51
ripple::TxDBName
constexpr auto TxDBName
Definition: DBInit.h:73
ripple::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:74
ripple::Ledger::info
LedgerInfo const & info() const override
Returns information about the ledger.
Definition: Ledger.h:148
std::chrono::time_point::time_since_epoch
T time_since_epoch(T... args)
ripple::saveValidatedLedger
static bool saveValidatedLedger(Application &app, std::shared_ptr< Ledger const > const &ledger, bool current)
Definition: Ledger.cpp:916
ripple::DatabaseCon::Setup::standAlone
bool standAlone
Definition: DatabaseCon.h:89
ripple::Config::getValueFor
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.
Definition: Config.cpp:824
ripple::DatabaseCon::checkoutDb
LockedSociSession checkoutDb()
Definition: DatabaseCon.h:178
ripple::LgrDBPragma
constexpr std::array< char const *, 1 > LgrDBPragma
Definition: DBInit.h:45
ripple::LedgerMaster::failedSave
void failedSave(std::uint32_t seq, uint256 const &hash)
Definition: LedgerMaster.cpp:965
ripple::Application::getLedgerMaster
virtual LedgerMaster & getLedgerMaster()=0
ripple::Config
Definition: Config.h:67
ripple::Application::pendingSaves
virtual PendingSaves & pendingSaves()=0
std::forward
T forward(T... args)
ripple::compare
int compare(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:530
ripple::JsonOptions::none
@ none
ripple::Application::config
virtual Config & config()=0
ripple::megabytes
constexpr auto megabytes(T value) noexcept
Definition: ByteUtilities.h:34
ripple::Ledger::stateMap
SHAMap const & stateMap() const
Definition: Ledger.h:307
ripple::Config::useTxTables
bool useTxTables() const
Definition: Config.h:276
ripple::LedgerInfo::closeFlags
int closeFlags
Definition: ReadView.h:114
std::to_string
T to_string(T... args)
ripple::deleteByLedgerSeq
void deleteByLedgerSeq(soci::session &session, TableType type, LedgerIndex ledgerSeq)
deleteByLedgerSeq Deletes all entries in given table for the ledger with given sequence.
Definition: RelationalDBInterface_nodes.cpp:141
beast::Journal::error
Stream error() const
Definition: Journal.h:333
beast::Journal::info
Stream info() const
Definition: Journal.h:321
ripple::TableType::Transactions
@ Transactions
ripple::ValStatus::current
@ current
This was a new validation and was added.
ripple::SizedItem::lgrDBCache
@ lgrDBCache
ripple::PendingSaves::finishWork
void finishWork(LedgerIndex seq)
Finish working on a ledger.
Definition: PendingSaves.h:74
ripple::HashPrefix::transactionID
@ transactionID
transaction plus signature to give transaction ID
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint32_t
std::map
STL class.
ripple::range
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
Definition: RangeSet.h:53
ripple::getAccountTxsB
static std::pair< std::vector< RelationalDBInterface::txnMetaLedgerType >, int > getAccountTxsB(soci::session &session, Application &app, RelationalDBInterface::AccountTxOptions const &options, std::optional< int > const &limit_used, bool descending, beast::Journal j)
getAccountTxsB Returns oldest or newset transactions in binary form for given account which match giv...
Definition: RelationalDBInterface_nodes.cpp:936
ripple::SizedItem::txnDBCache
@ txnDBCache
ripple::RelationalDBInterface::CountMinMax::maxLedgerSequence
LedgerIndex maxLedgerSequence
Definition: RelationalDBInterface.h:55
std::string::append
T append(T... args)
ripple::TableType::Ledgers
@ Ledgers
ripple::LedgerInfo::drops
XRPAmount drops
Definition: ReadView.h:105
std::experimental::filesystem::status
T status(T... args)
ripple::TableType::AccountTransactions
@ AccountTransactions
std::experimental::filesystem::space
T space(T... args)
std::min
T min(T... args)
ripple::getNewestAccountTxsB
std::pair< std::vector< RelationalDBInterface::txnMetaLedgerType >, int > getNewestAccountTxsB(soci::session &session, Application &app, RelationalDBInterface::AccountTxOptions const &options, std::optional< int > const &limit_used, beast::Journal j)
getNewestAccountTxsB Returns newest transactions in binary form for given account which match given c...
Definition: RelationalDBInterface_nodes.cpp:1019
ripple::Serializer
Definition: Serializer.h:39
ripple::getJson
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
Definition: LedgerToJson.cpp:291
std::ostringstream
STL class.
ripple::Ledger::txMap
SHAMap const & txMap() const
Definition: Ledger.h:319
ripple::TransactionMaster::inLedger
bool inLedger(uint256 const &hash, std::uint32_t ledger)
Definition: TransactionMaster.cpp:40
ripple::TableTypeCount
constexpr int TableTypeCount
Definition: RelationalDBInterface_nodes.h:35
std::vector::emplace_back
T emplace_back(T... args)
ripple::getTransaction
std::variant< RelationalDBInterface::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.
Definition: RelationalDBInterface_nodes.cpp:1260
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::getRows
std::size_t getRows(soci::session &session, TableType type)
getRows Returns number of rows in given table.
Definition: RelationalDBInterface_nodes.cpp:158
ripple::Application::getNodeStore
virtual NodeStore::Database & getNodeStore()=0
ripple::Application::journal
virtual beast::Journal journal(std::string const &name)=0
ripple::getHashesByIndex
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...
Definition: RelationalDBInterface_nodes.cpp:537
ripple::RelationalDBInterface::CountMinMax::minLedgerSequence
LedgerIndex minLedgerSequence
Definition: RelationalDBInterface.h:54
ripple::LedgerInfo::closeTimeResolution
NetClock::duration closeTimeResolution
Definition: ReadView.h:117
ripple::Config::REPLAY
@ REPLAY
Definition: Config.h:128
ripple::DatabaseCon
Definition: DatabaseCon.h:81
ripple::TxDBPragma
constexpr std::array TxDBPragma
Definition: DBInit.h:76
std::chrono::duration::count
T count(T... args)
ripple::makeLedgerDBs
DatabasePairValid makeLedgerDBs(Config const &config, DatabaseCon::Setup const &setup, DatabaseCon::CheckpointerSetup const &checkpointerSetup)
makeLedgerDBs Opens ledger and transactions databases.
Definition: RelationalDBInterface_nodes.cpp:65
ripple::oldestAccountTxPage
std::pair< std::optional< RelationalDBInterface::AccountTxMarker >, int > oldestAccountTxPage(soci::session &session, AccountIDCache const &idCache, std::function< void(std::uint32_t)> const &onUnsavedLedger, std::function< void(std::uint32_t, std::string const &, Blob &&, Blob &&)> const &onTransaction, RelationalDBInterface::AccountTxPageOptions const &options, int limit_used, std::uint32_t page_length)
oldestAccountTxPage Searches oldest transactions for given account which match given criteria startin...
Definition: RelationalDBInterface_nodes.cpp:1214
std::string::empty
T empty(T... args)
std::optional
std::ostringstream::str
T str(T... args)
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
std::size_t
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:40
ripple::hotLEDGER
@ hotLEDGER
Definition: NodeObject.h:34
ripple::Serializer::add32
int add32(std::uint32_t i)
Definition: Serializer.cpp:38
ripple::RelationalDBInterface::AccountTxPageOptions
Definition: RelationalDBInterface.h:74
ripple::transactionsSQL
static std::string transactionsSQL(Application &app, std::string selection, RelationalDBInterface::AccountTxOptions const &options, std::optional< int > const &limit_used, bool descending, bool binary, bool count, beast::Journal j)
transactionsSQL Returns SQL query to select oldest or newest transactions in decoded or binary form f...
Definition: RelationalDBInterface_nodes.cpp:690
ripple::NetClock::duration
std::chrono::duration< rep, period > duration
Definition: chrono.h:55
ripple::RelationalDBInterface::CountMinMax::numberOfRows
std::size_t numberOfRows
Definition: RelationalDBInterface.h:53
ripple::SHAMapHash::as_uint256
uint256 const & as_uint256() const
Definition: SHAMapTreeNode.h:59
ripple::TxDBInit
constexpr std::array< char const *, 8 > TxDBInit
Definition: DBInit.h:84
std::numeric_limits::max
T max(T... args)
ripple::TableType
TableType
Definition: RelationalDBInterface_nodes.h:34
ripple::dbHasSpace
bool dbHasSpace(soci::session &session, Config const &config, beast::Journal j)
dbHasSpace Checks if given database has available space.
Definition: RelationalDBInterface_nodes.cpp:1341
ripple::getMinLedgerSeq
std::optional< LedgerIndex > getMinLedgerSeq(soci::session &session, TableType type)
getMinLedgerSeq Returns minimum ledger sequence in given table.
Definition: RelationalDBInterface_nodes.cpp:121
ripple::pendSaveValidated
bool pendSaveValidated(Application &app, std::shared_ptr< Ledger const > const &ledger, bool isSynchronous, bool isCurrent)
Save, or arrange to save, a fully-validated ledger Returns false on error.
Definition: Ledger.cpp:944
ripple::accountTxPage
static std::pair< std::optional< RelationalDBInterface::AccountTxMarker >, int > accountTxPage(soci::session &session, AccountIDCache const &idCache, std::function< void(std::uint32_t)> const &onUnsavedLedger, std::function< void(std::uint32_t, std::string const &, Blob &&, Blob &&)> const &onTransaction, RelationalDBInterface::AccountTxPageOptions const &options, int limit_used, std::uint32_t page_length, bool forward)
accountTxPage Searches oldest or newest transactions for given account which match given criteria sta...
Definition: RelationalDBInterface_nodes.cpp:1052
ripple::NetClock::time_point
std::chrono::time_point< NetClock > time_point
Definition: chrono.h:56
ripple::Config::LOAD_FILE
@ LOAD_FILE
Definition: Config.h:128
ripple::getNewestLedgerInfo
std::optional< LedgerInfo > getNewestLedgerInfo(soci::session &session, beast::Journal j)
getNewestLedgerInfo Returns info of newest saved ledger.
Definition: RelationalDBInterface_nodes.cpp:464
ripple::LedgerInfo::accountHash
uint256 accountHash
Definition: ReadView.h:102
ripple::getMaxLedgerSeq
std::optional< LedgerIndex > getMaxLedgerSeq(soci::session &session, TableType type)
getMaxLedgerSeq Returns maximum ledger sequence in given table.
Definition: RelationalDBInterface_nodes.cpp:131
std::exception::what
T what(T... args)
ripple::TxSearched::some
@ some
std::variant
ripple::AccountIDCache::toBase58
std::string toBase58(AccountID const &) const
Return ripple::toBase58 for the AccountID.
Definition: AccountID.cpp:134
ripple::RelationalDBInterface::AccountTxs
std::vector< AccountTx > AccountTxs
Definition: RelationalDBInterface.h:86
ripple::LedgerInfo::parentCloseTime
NetClock::time_point parentCloseTime
Definition: ReadView.h:93
ripple::LgrDBName
constexpr auto LgrDBName
Definition: DBInit.h:43
ripple::Application::getMasterTransaction
virtual TransactionMaster & getMasterTransaction()=0