rippled
RelationalDBInterface_global.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/TransactionMaster.h>
24 #include <ripple/app/misc/Manifest.h>
25 #include <ripple/app/rdb/RelationalDBInterface_global.h>
26 #include <ripple/basics/BasicConfig.h>
27 #include <ripple/basics/StringUtilities.h>
28 #include <ripple/core/DatabaseCon.h>
29 #include <ripple/core/SociDB.h>
30 #include <ripple/json/to_string.h>
31 #include <boost/algorithm/string.hpp>
32 #include <boost/range/adaptor/transformed.hpp>
33 #include <soci/sqlite3/soci-sqlite3.h>
34 
35 namespace ripple {
36 
37 /* Wallet DB */
38 
41 {
42  // wallet database
43  return std::make_unique<DatabaseCon>(
45 }
46 
48 makeTestWalletDB(DatabaseCon::Setup const& setup, std::string const& dbname)
49 {
50  // wallet database
51  return std::make_unique<DatabaseCon>(
52  setup, dbname.data(), std::array<char const*, 0>(), WalletDBInit);
53 }
54 
55 void
57  soci::session& session,
58  std::string const& dbTable,
59  ManifestCache& mCache,
61 {
62  // Load manifests stored in database
63  std::string const sql = "SELECT RawData FROM " + dbTable + ";";
64  soci::blob sociRawData(session);
65  soci::statement st = (session.prepare << sql, soci::into(sociRawData));
66  st.execute();
67  while (st.fetch())
68  {
69  std::string serialized;
70  convert(sociRawData, serialized);
71  if (auto mo = deserializeManifest(serialized))
72  {
73  if (!mo->verify())
74  {
75  JLOG(j.warn()) << "Unverifiable manifest in db";
76  continue;
77  }
78 
79  mCache.applyManifest(std::move(*mo));
80  }
81  else
82  {
83  JLOG(j.warn()) << "Malformed manifest in database";
84  }
85  }
86 }
87 
88 static void
90  soci::session& session,
91  std::string const& dbTable,
92  std::string const& serialized)
93 {
94  // soci does not support bulk insertion of blob data
95  // Do not reuse blob because manifest ecdsa signatures vary in length
96  // but blob write length is expected to be >= the last write
97  soci::blob rawData(session);
98  convert(serialized, rawData);
99  session << "INSERT INTO " << dbTable << " (RawData) VALUES (:rawData);",
100  soci::use(rawData);
101 }
102 
103 void
105  soci::session& session,
106  std::string const& dbTable,
107  std::function<bool(PublicKey const&)> isTrusted,
109  beast::Journal j)
110 {
111  soci::transaction tr(session);
112  session << "DELETE FROM " << dbTable;
113  for (auto const& v : map)
114  {
115  // Save all revocation manifests,
116  // but only save trusted non-revocation manifests.
117  if (!v.second.revoked() && !isTrusted(v.second.masterKey))
118  {
119  JLOG(j.info()) << "Untrusted manifest in cache not saved to db";
120  continue;
121  }
122 
123  saveManifest(session, dbTable, v.second.serialized);
124  }
125  tr.commit();
126 }
127 
128 void
129 addValidatorManifest(soci::session& session, std::string const& serialized)
130 {
131  soci::transaction tr(session);
132  saveManifest(session, "ValidatorManifests", serialized);
133  tr.commit();
134 }
135 
137 getNodeIdentity(soci::session& session)
138 {
139  {
140  // SOCI requires boost::optional (not std::optional) as the parameter.
141  boost::optional<std::string> pubKO, priKO;
142  soci::statement st =
143  (session.prepare
144  << "SELECT PublicKey, PrivateKey FROM NodeIdentity;",
145  soci::into(pubKO),
146  soci::into(priKO));
147  st.execute();
148  while (st.fetch())
149  {
150  auto const sk = parseBase58<SecretKey>(
151  TokenType::NodePrivate, priKO.value_or(""));
152  auto const pk = parseBase58<PublicKey>(
153  TokenType::NodePublic, pubKO.value_or(""));
154 
155  // Only use if the public and secret keys are a pair
156  if (sk && pk && (*pk == derivePublicKey(KeyType::secp256k1, *sk)))
157  return {*pk, *sk};
158  }
159  }
160 
161  // If a valid identity wasn't found, we randomly generate a new one:
162  auto [newpublicKey, newsecretKey] = randomKeyPair(KeyType::secp256k1);
163 
164  session << str(
165  boost::format("INSERT INTO NodeIdentity (PublicKey,PrivateKey) "
166  "VALUES ('%s','%s');") %
167  toBase58(TokenType::NodePublic, newpublicKey) %
168  toBase58(TokenType::NodePrivate, newsecretKey));
169 
170  return {newpublicKey, newsecretKey};
171 }
172 
174 getPeerReservationTable(soci::session& session, beast::Journal j)
175 {
177  // These values must be boost::optionals (not std) because SOCI expects
178  // boost::optionals.
179  boost::optional<std::string> valPubKey, valDesc;
180  // We should really abstract the table and column names into constants,
181  // but no one else does. Because it is too tedious? It would be easy if we
182  // had a jOOQ for C++.
183  soci::statement st =
184  (session.prepare
185  << "SELECT PublicKey, Description FROM PeerReservations;",
186  soci::into(valPubKey),
187  soci::into(valDesc));
188  st.execute();
189  while (st.fetch())
190  {
191  if (!valPubKey || !valDesc)
192  {
193  // This represents a `NULL` in a `NOT NULL` column. It should be
194  // unreachable.
195  continue;
196  }
197  auto const optNodeId =
198  parseBase58<PublicKey>(TokenType::NodePublic, *valPubKey);
199  if (!optNodeId)
200  {
201  JLOG(j.warn()) << "load: not a public key: " << valPubKey;
202  continue;
203  }
204  table.insert(PeerReservation{*optNodeId, *valDesc});
205  }
206 
207  return table;
208 }
209 
210 void
212  soci::session& session,
213  PublicKey const& nodeId,
214  std::string const& description)
215 {
216  session << "INSERT INTO PeerReservations (PublicKey, Description) "
217  "VALUES (:nodeId, :desc) "
218  "ON CONFLICT (PublicKey) DO UPDATE SET "
219  "Description=excluded.Description",
220  soci::use(toBase58(TokenType::NodePublic, nodeId)),
221  soci::use(description);
222 }
223 
224 void
225 deletePeerReservation(soci::session& session, PublicKey const& nodeId)
226 {
227  session << "DELETE FROM PeerReservations WHERE PublicKey = :nodeId",
228  soci::use(toBase58(TokenType::NodePublic, nodeId));
229 }
230 
231 bool
232 createFeatureVotes(soci::session& session)
233 {
234  soci::transaction tr(session);
235  std::string sql =
236  "SELECT count(*) FROM sqlite_master "
237  "WHERE type='table' AND name='FeatureVotes'";
238  // SOCI requires boost::optional (not std::optional) as the parameter.
239  boost::optional<int> featureVotesCount;
240  session << sql, soci::into(featureVotesCount);
241  bool exists = static_cast<bool>(*featureVotesCount);
242 
243  // Create FeatureVotes table in WalletDB if it doesn't exist
244  if (!exists)
245  {
246  session << "CREATE TABLE FeatureVotes ( "
247  "AmendmentHash CHARACTER(64) NOT NULL, "
248  "AmendmentName TEXT, "
249  "Veto INTEGER NOT NULL );";
250  tr.commit();
251  }
252  return exists;
253 }
254 
255 void
257  soci::session& session,
258  std::function<void(
259  boost::optional<std::string> amendment_hash,
260  boost::optional<std::string> amendment_name,
261  boost::optional<int> vote_to_veto)> const& callback)
262 {
263  soci::transaction tr(session);
264  std::string sql =
265  "SELECT AmendmentHash, AmendmentName, Veto FROM FeatureVotes";
266  // SOCI requires boost::optional (not std::optional) as parameters.
267  boost::optional<std::string> amendment_hash;
268  boost::optional<std::string> amendment_name;
269  boost::optional<int> vote_to_veto;
270  soci::statement st =
271  (session.prepare << sql,
272  soci::into(amendment_hash),
273  soci::into(amendment_name),
274  soci::into(vote_to_veto));
275  st.execute();
276  while (st.fetch())
277  {
278  callback(amendment_hash, amendment_name, vote_to_veto);
279  }
280 }
281 
282 void
284  soci::session& session,
285  uint256 const& amendment,
286  std::string const& name,
287  bool vote_to_veto)
288 {
289  soci::transaction tr(session);
290  std::string sql =
291  "INSERT INTO FeatureVotes (AmendmentHash, AmendmentName, Veto) VALUES "
292  "('";
293  sql += to_string(amendment);
294  sql += "', '" + name;
295  sql += "', '" + std::to_string(int{vote_to_veto}) + "');";
296  session << sql;
297  tr.commit();
298 }
299 
300 /* State DB */
301 
302 void
304  soci::session& session,
305  BasicConfig const& config,
306  std::string const& dbName)
307 {
308  open(session, config, dbName);
309 
310  session << "PRAGMA synchronous=FULL;";
311 
312  session << "CREATE TABLE IF NOT EXISTS DbState ("
313  " Key INTEGER PRIMARY KEY,"
314  " WritableDb TEXT,"
315  " ArchiveDb TEXT,"
316  " LastRotatedLedger INTEGER"
317  ");";
318 
319  session << "CREATE TABLE IF NOT EXISTS CanDelete ("
320  " Key INTEGER PRIMARY KEY,"
321  " CanDeleteSeq INTEGER"
322  ");";
323 
324  std::int64_t count = 0;
325  {
326  // SOCI requires boost::optional (not std::optional) as the parameter.
327  boost::optional<std::int64_t> countO;
328  session << "SELECT COUNT(Key) FROM DbState WHERE Key = 1;",
329  soci::into(countO);
330  if (!countO)
331  Throw<std::runtime_error>(
332  "Failed to fetch Key Count from DbState.");
333  count = *countO;
334  }
335 
336  if (!count)
337  {
338  session << "INSERT INTO DbState VALUES (1, '', '', 0);";
339  }
340 
341  {
342  // SOCI requires boost::optional (not std::optional) as the parameter.
343  boost::optional<std::int64_t> countO;
344  session << "SELECT COUNT(Key) FROM CanDelete WHERE Key = 1;",
345  soci::into(countO);
346  if (!countO)
347  Throw<std::runtime_error>(
348  "Failed to fetch Key Count from CanDelete.");
349  count = *countO;
350  }
351 
352  if (!count)
353  {
354  session << "INSERT INTO CanDelete VALUES (1, 0);";
355  }
356 }
357 
359 getCanDelete(soci::session& session)
360 {
361  LedgerIndex seq;
362  session << "SELECT CanDeleteSeq FROM CanDelete WHERE Key = 1;",
363  soci::into(seq);
364  ;
365  return seq;
366 }
367 
369 setCanDelete(soci::session& session, LedgerIndex canDelete)
370 {
371  session << "UPDATE CanDelete SET CanDeleteSeq = :canDelete WHERE Key = 1;",
372  soci::use(canDelete);
373  return canDelete;
374 }
375 
376 SavedState
377 getSavedState(soci::session& session)
378 {
379  SavedState state;
380  session << "SELECT WritableDb, ArchiveDb, LastRotatedLedger"
381  " FROM DbState WHERE Key = 1;",
382  soci::into(state.writableDb), soci::into(state.archiveDb),
383  soci::into(state.lastRotated);
384 
385  return state;
386 }
387 
388 void
389 setSavedState(soci::session& session, SavedState const& state)
390 {
391  session << "UPDATE DbState"
392  " SET WritableDb = :writableDb,"
393  " ArchiveDb = :archiveDb,"
394  " LastRotatedLedger = :lastRotated"
395  " WHERE Key = 1;",
396  soci::use(state.writableDb), soci::use(state.archiveDb),
397  soci::use(state.lastRotated);
398 }
399 
400 void
401 setLastRotated(soci::session& session, LedgerIndex seq)
402 {
403  session << "UPDATE DbState SET LastRotatedLedger = :seq"
404  " WHERE Key = 1;",
405  soci::use(seq);
406 }
407 
408 /* DatabaseBody DB */
409 
412  DatabaseCon::Setup const& setup,
413  boost::filesystem::path path)
414 {
415  // SOCI requires boost::optional (not std::optional) as the parameter.
416  boost::optional<std::string> pathFromDb;
417  boost::optional<std::uint64_t> size;
418 
419  auto conn = std::make_unique<DatabaseCon>(
420  setup, "Download", DownloaderDBPragma, DatabaseBodyDBInit);
421 
422  auto& session = *conn->checkoutDb();
423 
424  session << "SELECT Path FROM Download WHERE Part=0;",
425  soci::into(pathFromDb);
426 
427  // Try to reuse preexisting
428  // database.
429  if (pathFromDb)
430  {
431  // Can't resuse - database was
432  // from a different file download.
433  if (pathFromDb != path.string())
434  {
435  session << "DROP TABLE Download;";
436  }
437 
438  // Continuing a file download.
439  else
440  {
441  session << "SELECT SUM(LENGTH(Data)) FROM Download;",
442  soci::into(size);
443  }
444  }
445 
446  return {std::move(conn), (size ? *size : std::optional<std::uint64_t>())};
447 }
448 
451  soci::session& session,
452  std::string const& data,
453  std::string const& path,
454  std::uint64_t fileSize,
455  std::uint64_t part,
456  std::uint16_t maxRowSizePad)
457 {
458  std::uint64_t rowSize = 0;
459  soci::indicator rti;
460 
461  std::uint64_t remainingInRow = 0;
462 
463  auto be =
464  dynamic_cast<soci::sqlite3_session_backend*>(session.get_backend());
465  BOOST_ASSERT(be);
466 
467  // This limits how large we can make the blob
468  // in each row. Also subtract a pad value to
469  // account for the other values in the row.
470  auto const blobMaxSize =
471  sqlite_api::sqlite3_limit(be->conn_, SQLITE_LIMIT_LENGTH, -1) -
472  maxRowSizePad;
473 
474  std::string newpath;
475 
476  auto rowInit = [&] {
477  session << "INSERT INTO Download VALUES (:path, zeroblob(0), 0, :part)",
478  soci::use(newpath), soci::use(part);
479 
480  remainingInRow = blobMaxSize;
481  rowSize = 0;
482  };
483 
484  session << "SELECT Path,Size,Part FROM Download ORDER BY Part DESC "
485  "LIMIT 1",
486  soci::into(newpath), soci::into(rowSize), soci::into(part, rti);
487 
488  if (!session.got_data())
489  {
490  newpath = path;
491  rowInit();
492  }
493  else
494  remainingInRow = blobMaxSize - rowSize;
495 
496  auto insert = [&session, &rowSize, &part, &fs = fileSize](
497  auto const& data) {
498  std::uint64_t updatedSize = rowSize + data.size();
499 
500  session << "UPDATE Download SET Data = CAST(Data || :data AS blob), "
501  "Size = :size WHERE Part = :part;",
502  soci::use(data), soci::use(updatedSize), soci::use(part);
503 
504  fs += data.size();
505  };
506 
507  size_t currentBase = 0;
508 
509  while (currentBase + remainingInRow < data.size())
510  {
511  if (remainingInRow)
512  {
513  insert(data.substr(currentBase, remainingInRow));
514  currentBase += remainingInRow;
515  }
516 
517  ++part;
518  rowInit();
519  }
520 
521  insert(data.substr(currentBase));
522 
523  return part;
524 }
525 
526 void
527 databaseBodyFinish(soci::session& session, std::ofstream& fout)
528 {
529  soci::rowset<std::string> rs =
530  (session.prepare << "SELECT Data FROM Download ORDER BY PART ASC;");
531 
532  // iteration through the resultset:
533  for (auto it = rs.begin(); it != rs.end(); ++it)
534  fout.write(it->data(), it->size());
535 }
536 
537 /* Vacuum DB */
538 
539 bool
541 {
542  boost::filesystem::path dbPath = setup.dataDir / TxDBName;
543 
544  uintmax_t const dbSize = file_size(dbPath);
545  assert(dbSize != static_cast<uintmax_t>(-1));
546 
547  if (auto available = space(dbPath.parent_path()).available;
548  available < dbSize)
549  {
550  std::cerr << "The database filesystem must have at least as "
551  "much free space as the size of "
552  << dbPath.string() << ", which is " << dbSize
553  << " bytes. Only " << available << " bytes are available.\n";
554  return false;
555  }
556 
557  auto txnDB =
558  std::make_unique<DatabaseCon>(setup, TxDBName, TxDBPragma, TxDBInit);
559  auto& session = txnDB->getSession();
560  std::uint32_t pageSize;
561 
562  // Only the most trivial databases will fit in memory on typical
563  // (recommended) software. Force temp files to be written to disk
564  // regardless of the config settings.
565  session << boost::format(CommonDBPragmaTemp) % "file";
566  session << "PRAGMA page_size;", soci::into(pageSize);
567 
568  std::cout << "VACUUM beginning. page_size: " << pageSize << std::endl;
569 
570  session << "VACUUM;";
571  assert(setup.globalPragma);
572  for (auto const& p : *setup.globalPragma)
573  session << p;
574  session << "PRAGMA page_size;", soci::into(pageSize);
575 
576  std::cout << "VACUUM finished. page_size: " << pageSize << std::endl;
577 
578  return true;
579 }
580 
581 /* PeerFinder DB */
582 
583 void
585  soci::session& session,
586  BasicConfig const& config,
587  beast::Journal j)
588 {
589  DBConfig m_sociConfig(config, "peerfinder");
590  m_sociConfig.open(session);
591 
592  JLOG(j.info()) << "Opening database at '" << m_sociConfig.connectionString()
593  << "'";
594 
595  soci::transaction tr(session);
596  session << "PRAGMA encoding=\"UTF-8\";";
597 
598  session << "CREATE TABLE IF NOT EXISTS SchemaVersion ( "
599  " name TEXT PRIMARY KEY, "
600  " version INTEGER"
601  ");";
602 
603  session << "CREATE TABLE IF NOT EXISTS PeerFinder_BootstrapCache ( "
604  " id INTEGER PRIMARY KEY AUTOINCREMENT, "
605  " address TEXT UNIQUE NOT NULL, "
606  " valence INTEGER"
607  ");";
608 
609  session << "CREATE INDEX IF NOT EXISTS "
610  " PeerFinder_BootstrapCache_Index ON "
611  "PeerFinder_BootstrapCache "
612  " ( "
613  " address "
614  " ); ";
615 
616  tr.commit();
617 }
618 
619 void
621  soci::session& session,
622  int currentSchemaVersion,
623  beast::Journal j)
624 {
625  soci::transaction tr(session);
626  // get version
627  int version(0);
628  {
629  // SOCI requires a boost::optional (not std::optional) parameter.
630  boost::optional<int> vO;
631  session << "SELECT "
632  " version "
633  "FROM SchemaVersion WHERE "
634  " name = 'PeerFinder';",
635  soci::into(vO);
636 
637  version = vO.value_or(0);
638 
639  JLOG(j.info()) << "Opened version " << version << " database";
640  }
641 
642  {
643  if (version < currentSchemaVersion)
644  {
645  JLOG(j.info()) << "Updating database to version "
646  << currentSchemaVersion;
647  }
648  else if (version > currentSchemaVersion)
649  {
650  Throw<std::runtime_error>(
651  "The PeerFinder database version is higher than expected");
652  }
653  }
654 
655  if (version < 4)
656  {
657  //
658  // Remove the "uptime" column from the bootstrap table
659  //
660 
661  session << "CREATE TABLE IF NOT EXISTS "
662  "PeerFinder_BootstrapCache_Next ( "
663  " id INTEGER PRIMARY KEY AUTOINCREMENT, "
664  " address TEXT UNIQUE NOT NULL, "
665  " valence INTEGER"
666  ");";
667 
668  session << "CREATE INDEX IF NOT EXISTS "
669  " PeerFinder_BootstrapCache_Next_Index ON "
670  " PeerFinder_BootstrapCache_Next "
671  " ( address ); ";
672 
673  std::size_t count;
674  session << "SELECT COUNT(*) FROM PeerFinder_BootstrapCache;",
675  soci::into(count);
676 
678 
679  {
680  list.reserve(count);
681  std::string s;
682  int valence;
683  soci::statement st =
684  (session.prepare << "SELECT "
685  " address, "
686  " valence "
687  "FROM PeerFinder_BootstrapCache;",
688  soci::into(s),
689  soci::into(valence));
690 
691  st.execute();
692  while (st.fetch())
693  {
696  if (!is_unspecified(entry.endpoint))
697  {
698  entry.valence = valence;
699  list.push_back(entry);
700  }
701  else
702  {
703  JLOG(j.error()) << "Bad address string '" << s
704  << "' in Bootcache table";
705  }
706  }
707  }
708 
709  if (!list.empty())
710  {
712  std::vector<int> valence;
713  s.reserve(list.size());
714  valence.reserve(list.size());
715 
716  for (auto iter(list.cbegin()); iter != list.cend(); ++iter)
717  {
718  s.emplace_back(to_string(iter->endpoint));
719  valence.emplace_back(iter->valence);
720  }
721 
722  session << "INSERT INTO PeerFinder_BootstrapCache_Next ( "
723  " address, "
724  " valence "
725  ") VALUES ( "
726  " :s, :valence"
727  ");",
728  soci::use(s), soci::use(valence);
729  }
730 
731  session << "DROP TABLE IF EXISTS PeerFinder_BootstrapCache;";
732 
733  session << "DROP INDEX IF EXISTS PeerFinder_BootstrapCache_Index;";
734 
735  session << "ALTER TABLE PeerFinder_BootstrapCache_Next "
736  " RENAME TO PeerFinder_BootstrapCache;";
737 
738  session << "CREATE INDEX IF NOT EXISTS "
739  " PeerFinder_BootstrapCache_Index ON "
740  "PeerFinder_BootstrapCache "
741  " ( "
742  " address "
743  " ); ";
744  }
745 
746  if (version < 3)
747  {
748  //
749  // Remove legacy endpoints from the schema
750  //
751 
752  session << "DROP TABLE IF EXISTS LegacyEndpoints;";
753 
754  session << "DROP TABLE IF EXISTS PeerFinderLegacyEndpoints;";
755 
756  session << "DROP TABLE IF EXISTS PeerFinder_LegacyEndpoints;";
757 
758  session << "DROP TABLE IF EXISTS PeerFinder_LegacyEndpoints_Index;";
759  }
760 
761  {
762  int const v(currentSchemaVersion);
763  session << "INSERT OR REPLACE INTO SchemaVersion ("
764  " name "
765  " ,version "
766  ") VALUES ( "
767  " 'PeerFinder', :version "
768  ");",
769  soci::use(v);
770  }
771 
772  tr.commit();
773 }
774 
775 void
777  soci::session& session,
778  std::function<void(std::string const&, int)> const& func)
779 {
780  std::string s;
781  int valence;
782  soci::statement st =
783  (session.prepare << "SELECT "
784  " address, "
785  " valence "
786  "FROM PeerFinder_BootstrapCache;",
787  soci::into(s),
788  soci::into(valence));
789 
790  st.execute();
791  while (st.fetch())
792  {
793  func(s, valence);
794  }
795 }
796 
797 void
799  soci::session& session,
801 {
802  soci::transaction tr(session);
803  session << "DELETE FROM PeerFinder_BootstrapCache;";
804 
805  if (!v.empty())
806  {
808  std::vector<int> valence;
809  s.reserve(v.size());
810  valence.reserve(v.size());
811 
812  for (auto const& e : v)
813  {
814  s.emplace_back(to_string(e.endpoint));
815  valence.emplace_back(e.valence);
816  }
817 
818  session << "INSERT INTO PeerFinder_BootstrapCache ( "
819  " address, "
820  " valence "
821  ") VALUES ( "
822  " :s, :valence "
823  ");",
824  soci::use(s), soci::use(valence);
825  }
826 
827  tr.commit();
828 }
829 
830 } // namespace ripple
ripple::getNodeIdentity
std::pair< PublicKey, SecretKey > getNodeIdentity(Application &app)
The cryptographic credentials identifying this server instance.
Definition: NodeIdentity.cpp:32
ripple::setCanDelete
LedgerIndex setCanDelete(soci::session &session, LedgerIndex canDelete)
setCanDelete Updates ledger sequence which can be deleted.
Definition: RelationalDBInterface_global.cpp:369
ripple::WalletDBName
constexpr auto WalletDBName
Definition: DBInit.h:187
ripple::DatabaseCon::Setup::globalPragma
static std::unique_ptr< std::vector< std::string > const > globalPragma
Definition: DatabaseCon.h:104
ripple::LedgerIndex
std::uint32_t LedgerIndex
A ledger index.
Definition: Protocol.h:57
std::string
STL class.
ripple::DatabaseCon::Setup
Definition: DatabaseCon.h:84
ripple::DBConfig::connectionString
std::string connectionString() const
Definition: SociDB.cpp:86
ripple::initPeerFinderDB
void initPeerFinderDB(soci::session &session, BasicConfig const &config, beast::Journal j)
initPeerFinderDB Opens session with peer finder database.
Definition: RelationalDBInterface_global.cpp:584
std::unordered_set
STL class.
ripple::readAmendments
void readAmendments(soci::session &session, std::function< void(boost::optional< std::string > amendment_hash, boost::optional< std::string > amendment_name, boost::optional< int > vote_to_veto)> const &callback)
readAmendments Read all amendments from FeatureVotes table.
Definition: RelationalDBInterface_global.cpp:256
std::pair
std::vector::reserve
T reserve(T... args)
ripple::convert
void convert(soci::blob &from, std::vector< std::uint8_t > &to)
Definition: SociDB.cpp:154
ripple::setSavedState
void setSavedState(soci::session &session, SavedState const &state)
setSavedState Saves given state.
Definition: RelationalDBInterface_global.cpp:389
ripple::createFeatureVotes
bool createFeatureVotes(soci::session &session)
createFeatureVotes Creates FeatureVote table if it is not exists.
Definition: RelationalDBInterface_global.cpp:232
ripple::DBConfig::open
void open(soci::session &s) const
Definition: SociDB.cpp:92
std::vector
STL class.
std::vector::size
T size(T... args)
ripple::updatePeerFinderDB
void updatePeerFinderDB(soci::session &session, int currentSchemaVersion, beast::Journal j)
updatePeerFinderDB Update peer finder DB to new version.
Definition: RelationalDBInterface_global.cpp:620
ripple::SavedState::writableDb
std::string writableDb
Definition: RelationalDBInterface_global.h:167
ripple::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:29
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
ripple::addValidatorManifest
void addValidatorManifest(soci::session &session, std::string const &serialized)
addValidatorManifest Saves manifest of validator to database.
Definition: RelationalDBInterface_global.cpp:129
ripple::DBConfig
DBConfig is used when a client wants to delay opening a soci::session after parsing the config parame...
Definition: SociDB.h:57
std::cerr
ripple::DatabaseCon::Setup::dataDir
boost::filesystem::path dataDir
Definition: DatabaseCon.h:91
std::function
ripple::makeTestWalletDB
std::unique_ptr< DatabaseCon > makeTestWalletDB(DatabaseCon::Setup const &setup, std::string const &dbname)
makeTestWalletDB Opens test wallet DB with arbitrary name.
Definition: RelationalDBInterface_global.cpp:48
std::ofstream::write
T write(T... args)
std::vector::push_back
T push_back(T... args)
std::cout
ripple::DownloaderDBPragma
static constexpr std::array< char const *, 2 > DownloaderDBPragma
Definition: DBInit.h:225
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::voteAmendment
void voteAmendment(soci::session &session, uint256 const &amendment, std::string const &name, bool vote_to_veto)
voteAmendment Set veto value for particular amendment.
Definition: RelationalDBInterface_global.cpp:283
ripple::PublicKey
A public key.
Definition: PublicKey.h:59
ripple::derivePublicKey
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
Definition: SecretKey.cpp:313
std::ofstream
STL class.
ripple::readPeerFinderDB
void readPeerFinderDB(soci::session &session, std::function< void(std::string const &, int)> const &func)
readPeerFinderDB Read all entries from peer finder DB and call given callback for each entry.
Definition: RelationalDBInterface_global.cpp:776
ripple::getManifests
void getManifests(soci::session &session, std::string const &dbTable, ManifestCache &mCache, beast::Journal j)
getManifests Loads manifest from wallet DB and stores it in the cache.
Definition: RelationalDBInterface_global.cpp:56
ripple::insertPeerReservation
void insertPeerReservation(soci::session &session, PublicKey const &nodeId, std::string const &description)
insertPeerReservation Adds entry to peer reservation table.
Definition: RelationalDBInterface_global.cpp:211
ripple::deletePeerReservation
void deletePeerReservation(soci::session &session, PublicKey const &nodeId)
deletePeerReservation Deletes entry from peer reservation table.
Definition: RelationalDBInterface_global.cpp:225
std::to_string
T to_string(T... args)
std::array
STL class.
ripple::PeerFinder::Store::Entry::valence
int valence
Definition: Store.h:45
beast::Journal::error
Stream error() const
Definition: Journal.h:333
beast::Journal::info
Stream info() const
Definition: Journal.h:321
ripple::initStateDB
void initStateDB(soci::session &session, BasicConfig const &config, std::string const &dbName)
initStateDB Opens DB session with State DB.
Definition: RelationalDBInterface_global.cpp:303
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::int64_t
ripple::CommonDBPragmaTemp
constexpr char const * CommonDBPragmaTemp
Definition: DBInit.h:34
ripple::PeerReservation
Definition: PeerReservationTable.h:43
ripple::getSavedState
SavedState getSavedState(soci::session &session)
getSavedState Returns saved state.
Definition: RelationalDBInterface_global.cpp:377
ripple::databaseBodyDoPut
std::uint64_t databaseBodyDoPut(soci::session &session, std::string const &data, std::string const &path, std::uint64_t fileSize, std::uint64_t part, std::uint16_t maxRowSizePad)
databaseBodyDoPut Saves new fragment of downloaded file.
Definition: RelationalDBInterface_global.cpp:450
ripple::KeyType::secp256k1
@ secp256k1
ripple::randomKeyPair
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
Definition: SecretKey.cpp:368
ripple::getPeerReservationTable
std::unordered_set< PeerReservation, beast::uhash<>, KeyEqual > getPeerReservationTable(soci::session &session, beast::Journal j)
getPeerReservationTable Returns peer reservation table.
Definition: RelationalDBInterface_global.cpp:174
ripple::ManifestCache
Remembers manifests with the highest sequence number.
Definition: Manifest.h:223
ripple::setLastRotated
void setLastRotated(soci::session &session, LedgerIndex seq)
setLastRotated Updates last rotated ledger sequence.
Definition: RelationalDBInterface_global.cpp:401
std::vector::emplace_back
T emplace_back(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::saveManifests
void saveManifests(soci::session &session, std::string const &dbTable, std::function< bool(PublicKey const &)> isTrusted, hash_map< PublicKey, Manifest > const &map, beast::Journal j)
saveManifests Saves all given manifests to database.
Definition: RelationalDBInterface_global.cpp:104
std::endl
T endl(T... args)
std::vector::cbegin
T cbegin(T... args)
std::unordered_set::insert
T insert(T... args)
ripple::SavedState::archiveDb
std::string archiveDb
Definition: RelationalDBInterface_global.h:168
beast::IP::Endpoint::from_string
static Endpoint from_string(std::string const &s)
Definition: IPEndpoint.cpp:46
ripple::getCanDelete
LedgerIndex getCanDelete(soci::session &session)
getCanDelete Returns ledger sequence which can be deleted.
Definition: RelationalDBInterface_global.cpp:359
ripple::makeWalletDB
std::unique_ptr< DatabaseCon > makeWalletDB(DatabaseCon::Setup const &setup)
makeWalletDB Opens wallet DB and returns it.
Definition: RelationalDBInterface_global.cpp:40
ripple::saveManifest
static void saveManifest(soci::session &session, std::string const &dbTable, std::string const &serialized)
Definition: RelationalDBInterface_global.cpp:89
ripple::SavedState::lastRotated
LedgerIndex lastRotated
Definition: RelationalDBInterface_global.h:169
ripple::openDatabaseBodyDb
std::pair< std::unique_ptr< DatabaseCon >, std::optional< std::uint64_t > > openDatabaseBodyDb(DatabaseCon::Setup const &setup, boost::filesystem::path path)
openDatabaseBodyDb Opens file download DB and returns its descriptor.
Definition: RelationalDBInterface_global.cpp:411
ripple::savePeerFinderDB
void savePeerFinderDB(soci::session &session, std::vector< PeerFinder::Store::Entry > const &v)
savePeerFinderDB Save new entry to peer finder DB.
Definition: RelationalDBInterface_global.cpp:798
ripple::TxDBPragma
constexpr std::array TxDBPragma
Definition: DBInit.h:76
std::vector::empty
T empty(T... args)
ripple::TokenType::NodePublic
@ NodePublic
std::optional
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:39
ripple::databaseBodyFinish
void databaseBodyFinish(soci::session &session, std::ofstream &fout)
databaseBodyFinish Finishes download process and writes file to disk.
Definition: RelationalDBInterface_global.cpp:527
std::vector::cend
T cend(T... args)
ripple::DatabaseBodyDBInit
static constexpr std::array< char const *, 3 > DatabaseBodyDBInit
Definition: DBInit.h:238
ripple::doVacuumDB
bool doVacuumDB(DatabaseCon::Setup const &setup)
doVacuumDB Creates, initialises DB, and performs its cleanup.
Definition: RelationalDBInterface_global.cpp:540
ripple::KeyEqual
Definition: PeerReservationTable.h:70
ripple::TxDBInit
constexpr std::array< char const *, 8 > TxDBInit
Definition: DBInit.h:84
ripple::PeerFinder::Store::Entry
Definition: Store.h:40
ripple::WalletDBInit
constexpr std::array< char const *, 6 > WalletDBInit
Definition: DBInit.h:189
std::unique_ptr
STL class.
ripple::ManifestCache::applyManifest
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
Definition: app/misc/impl/Manifest.cpp:357
std::unordered_map
STL class.
ripple::deserializeManifest
std::optional< Manifest > deserializeManifest(Slice s)
Constructs Manifest from serialized string.
Definition: app/misc/impl/Manifest.cpp:51
ripple::SavedState
Definition: RelationalDBInterface_global.h:165
std::string::data
T data(T... args)
ripple::PeerFinder::Store::Entry::endpoint
beast::IP::Endpoint endpoint
Definition: Store.h:44
ripple::BasicConfig
Holds unparsed configuration information.
Definition: BasicConfig.h:178
ripple::TokenType::NodePrivate
@ NodePrivate
ripple::PublisherStatus::available
@ available
ripple::open
void open(soci::session &s, BasicConfig const &config, std::string const &dbName)
Open a soci session.
Definition: SociDB.cpp:98