rippled
Ledger.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 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/InboundLedgers.h>
22 #include <ripple/app/ledger/Ledger.h>
23 #include <ripple/app/ledger/LedgerMaster.h>
24 #include <ripple/app/ledger/LedgerToJson.h>
25 #include <ripple/app/ledger/OrderBookDB.h>
26 #include <ripple/app/ledger/PendingSaves.h>
27 #include <ripple/app/ledger/TransactionMaster.h>
28 #include <ripple/app/main/Application.h>
29 #include <ripple/app/misc/HashRouter.h>
30 #include <ripple/app/misc/LoadFeeTrack.h>
31 #include <ripple/app/misc/NetworkOPs.h>
32 #include <ripple/app/reporting/DBHelpers.h>
33 #include <ripple/basics/Log.h>
34 #include <ripple/basics/StringUtilities.h>
35 #include <ripple/basics/contract.h>
36 #include <ripple/beast/core/LexicalCast.h>
37 #include <ripple/consensus/LedgerTiming.h>
38 #include <ripple/core/Config.h>
39 #include <ripple/core/DatabaseCon.h>
40 #include <ripple/core/JobQueue.h>
41 #include <ripple/core/Pg.h>
42 #include <ripple/core/SociDB.h>
43 #include <ripple/json/to_string.h>
44 #include <ripple/nodestore/Database.h>
45 #include <ripple/protocol/Feature.h>
46 #include <ripple/protocol/HashPrefix.h>
47 #include <ripple/protocol/Indexes.h>
48 #include <ripple/protocol/PublicKey.h>
49 #include <ripple/protocol/SecretKey.h>
50 #include <ripple/protocol/UintTypes.h>
51 #include <ripple/protocol/digest.h>
52 #include <ripple/protocol/jss.h>
53 #include <boost/optional.hpp>
54 #include <cassert>
55 #include <utility>
56 #include <vector>
57 
58 #include <ripple/nodestore/impl/DatabaseNodeImp.h>
59 
60 namespace ripple {
61 
63 
64 uint256
66 {
67  // VFALCO This has to match addRaw in View.h.
68  return sha512Half(
70  std::uint32_t(info.seq),
71  std::uint64_t(info.drops.drops()),
72  info.parentHash,
73  info.txHash,
74  info.accountHash,
78  std::uint8_t(info.closeFlags));
79 }
80 
81 //------------------------------------------------------------------------------
82 
83 class Ledger::sles_iter_impl : public sles_type::iter_base
84 {
85 private:
87 
88 public:
89  sles_iter_impl() = delete;
91  operator=(sles_iter_impl const&) = delete;
92 
93  sles_iter_impl(sles_iter_impl const&) = default;
94 
96  {
97  }
98 
100  copy() const override
101  {
102  return std::make_unique<sles_iter_impl>(*this);
103  }
104 
105  bool
106  equal(base_type const& impl) const override
107  {
108  if (auto const p = dynamic_cast<sles_iter_impl const*>(&impl))
109  return iter_ == p->iter_;
110  return false;
111  }
112 
113  void
114  increment() override
115  {
116  ++iter_;
117  }
118 
120  dereference() const override
121  {
122  auto const item = *iter_;
123  SerialIter sit(item.slice());
124  return std::make_shared<SLE const>(sit, item.key());
125  }
126 };
127 
128 //------------------------------------------------------------------------------
129 
130 class Ledger::txs_iter_impl : public txs_type::iter_base
131 {
132 private:
133  bool metadata_;
135 
136 public:
137  txs_iter_impl() = delete;
139  operator=(txs_iter_impl const&) = delete;
140 
141  txs_iter_impl(txs_iter_impl const&) = default;
142 
144  : metadata_(metadata), iter_(iter)
145  {
146  }
147 
149  copy() const override
150  {
151  return std::make_unique<txs_iter_impl>(*this);
152  }
153 
154  bool
155  equal(base_type const& impl) const override
156  {
157  if (auto const p = dynamic_cast<txs_iter_impl const*>(&impl))
158  return iter_ == p->iter_;
159  return false;
160  }
161 
162  void
163  increment() override
164  {
165  ++iter_;
166  }
167 
169  dereference() const override
170  {
171  auto const item = *iter_;
172  if (metadata_)
173  return deserializeTxPlusMeta(item);
174  return {deserializeTx(item), nullptr};
175  }
176 };
177 
178 //------------------------------------------------------------------------------
179 
182  Config const& config,
183  std::vector<uint256> const& amendments,
184  Family& family)
185  : mImmutable(false)
186  , txMap_(std::make_shared<SHAMap>(SHAMapType::TRANSACTION, family))
187  , stateMap_(std::make_shared<SHAMap>(SHAMapType::STATE, family))
188  , rules_{config.features}
189 {
190  info_.seq = 1;
191  info_.drops = INITIAL_XRP;
192  info_.closeTimeResolution = ledgerGenesisTimeResolution;
193 
194  static auto const id = calcAccountID(
195  generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase"))
196  .first);
197  {
198  auto const sle = std::make_shared<SLE>(keylet::account(id));
199  sle->setFieldU32(sfSequence, 1);
200  sle->setAccountID(sfAccount, id);
201  sle->setFieldAmount(sfBalance, info_.drops);
202  rawInsert(sle);
203  }
204 
205  if (!amendments.empty())
206  {
207  auto const sle = std::make_shared<SLE>(keylet::amendments());
208  sle->setFieldV256(sfAmendments, STVector256{amendments});
209  rawInsert(sle);
210  }
211 
212  stateMap_->flushDirty(hotACCOUNT_NODE);
213  setImmutable(config);
214 }
215 
217  LedgerInfo const& info,
218  bool& loaded,
219  bool acquire,
220  Config const& config,
221  Family& family,
222  beast::Journal j)
223  : mImmutable(true)
224  , txMap_(std::make_shared<SHAMap>(
226  info.txHash,
227  family))
228  , stateMap_(
229  std::make_shared<SHAMap>(SHAMapType::STATE, info.accountHash, family))
230  , rules_(config.features)
231  , info_(info)
232 {
233  loaded = true;
234 
235  if (info_.txHash.isNonZero() &&
236  !txMap_->fetchRoot(SHAMapHash{info_.txHash}, nullptr))
237  {
238  if (config.reporting())
239  {
240  // Reporting should never have incomplete data
241  Throw<std::runtime_error>("Missing tx map root for ledger");
242  }
243  loaded = false;
244  JLOG(j.warn()) << "Don't have transaction root for ledger" << info_.seq;
245  }
246 
247  if (info_.accountHash.isNonZero() &&
248  !stateMap_->fetchRoot(SHAMapHash{info_.accountHash}, nullptr))
249  {
250  if (config.reporting())
251  {
252  // Reporting should never have incomplete data
253  Throw<std::runtime_error>("Missing state map root for ledger");
254  }
255  loaded = false;
256  JLOG(j.warn()) << "Don't have state data root for ledger" << info_.seq;
257  }
258 
259  txMap_->setImmutable();
260  stateMap_->setImmutable();
261 
262  if (!setup(config))
263  loaded = false;
264 
265  if (!loaded)
266  {
268  if (acquire && !config.reporting())
269  family.missingNode(info_.hash, info_.seq);
270  }
271 }
272 
273 // Create a new ledger that follows this one
274 Ledger::Ledger(Ledger const& prevLedger, NetClock::time_point closeTime)
275  : mImmutable(false)
276  , txMap_(std::make_shared<SHAMap>(
278  prevLedger.stateMap_->family()))
279  , stateMap_(prevLedger.stateMap_->snapShot(true))
280  , fees_(prevLedger.fees_)
281  , rules_(prevLedger.rules_)
282 {
283  info_.seq = prevLedger.info_.seq + 1;
284  info_.parentCloseTime = prevLedger.info_.closeTime;
285  info_.hash = prevLedger.info().hash + uint256(1);
286  info_.drops = prevLedger.info().drops;
288  info_.parentHash = prevLedger.info().hash;
290  prevLedger.info_.closeTimeResolution,
291  getCloseAgree(prevLedger.info()),
292  info_.seq);
293 
294  if (prevLedger.info_.closeTime == NetClock::time_point{})
295  {
297  }
298  else
299  {
300  info_.closeTime =
302  }
303 }
304 
305 Ledger::Ledger(LedgerInfo const& info, Config const& config, Family& family)
306  : mImmutable(true)
307  , txMap_(std::make_shared<SHAMap>(
309  info.txHash,
310  family))
311  , stateMap_(
312  std::make_shared<SHAMap>(SHAMapType::STATE, info.accountHash, family))
313  , rules_{config.features}
314  , info_(info)
315 {
316  info_.hash = calculateLedgerHash(info_);
317 }
318 
320  std::uint32_t ledgerSeq,
321  NetClock::time_point closeTime,
322  Config const& config,
323  Family& family)
324  : mImmutable(false)
325  , txMap_(std::make_shared<SHAMap>(SHAMapType::TRANSACTION, family))
326  , stateMap_(std::make_shared<SHAMap>(SHAMapType::STATE, family))
327  , rules_{config.features}
328 {
329  info_.seq = ledgerSeq;
330  info_.closeTime = closeTime;
331  info_.closeTimeResolution = ledgerDefaultTimeResolution;
332  setup(config);
333 }
334 
335 void
336 Ledger::setImmutable(Config const& config, bool rehash)
337 {
338  // Force update, since this is the only
339  // place the hash transitions to valid
340  if (!mImmutable && rehash)
341  {
342  info_.txHash = txMap_->getHash().as_uint256();
343  info_.accountHash = stateMap_->getHash().as_uint256();
344  }
345 
346  if (rehash)
348 
349  mImmutable = true;
350  txMap_->setImmutable();
351  stateMap_->setImmutable();
352  setup(config);
353 }
354 
355 void
357  NetClock::time_point closeTime,
358  NetClock::duration closeResolution,
359  bool correctCloseTime,
360  Config const& config)
361 {
362  // Used when we witnessed the consensus.
363  assert(!open());
364 
365  info_.closeTime = closeTime;
366  info_.closeTimeResolution = closeResolution;
367  info_.closeFlags = correctCloseTime ? 0 : sLCF_NoConsensusTime;
368  setImmutable(config);
369 }
370 
371 bool
372 Ledger::addSLE(SLE const& sle)
373 {
374  auto const s = sle.getSerializer();
375  SHAMapItem item(sle.key(), s.slice());
376  return stateMap_->addItem(SHAMapNodeType::tnACCOUNT_STATE, std::move(item));
377 }
378 
379 //------------------------------------------------------------------------------
380 
383 {
384  SerialIter sit(item.slice());
385  return std::make_shared<STTx const>(sit);
386 }
387 
390 {
392  result;
393  SerialIter sit(item.slice());
394  {
395  SerialIter s(sit.getSlice(sit.getVLDataLength()));
396  result.first = std::make_shared<STTx const>(s);
397  }
398  {
399  SerialIter s(sit.getSlice(sit.getVLDataLength()));
400  result.second = std::make_shared<STObject const>(s, sfMetadata);
401  }
402  return result;
403 }
404 
405 //------------------------------------------------------------------------------
406 
407 bool
408 Ledger::exists(Keylet const& k) const
409 {
410  // VFALCO NOTE Perhaps check the type for debug builds?
411  return stateMap_->hasItem(k.key);
412 }
413 
414 bool
415 Ledger::exists(uint256 const& key) const
416 {
417  return stateMap_->hasItem(key);
418 }
419 
421 Ledger::succ(uint256 const& key, std::optional<uint256> const& last) const
422 {
423  auto item = stateMap_->upper_bound(key);
424  if (item == stateMap_->end())
425  return std::nullopt;
426  if (last && item->key() >= last)
427  return std::nullopt;
428  return item->key();
429 }
430 
432 Ledger::read(Keylet const& k) const
433 {
434  if (k.key == beast::zero)
435  {
436  assert(false);
437  return nullptr;
438  }
439  auto const& item = stateMap_->peekItem(k.key);
440  if (!item)
441  return nullptr;
442  auto sle = std::make_shared<SLE>(SerialIter{item->slice()}, item->key());
443  if (!k.check(*sle))
444  return nullptr;
445  return sle;
446 }
447 
448 //------------------------------------------------------------------------------
449 
450 auto
451 Ledger::slesBegin() const -> std::unique_ptr<sles_type::iter_base>
452 {
453  return std::make_unique<sles_iter_impl>(stateMap_->begin());
454 }
455 
456 auto
457 Ledger::slesEnd() const -> std::unique_ptr<sles_type::iter_base>
458 {
459  return std::make_unique<sles_iter_impl>(stateMap_->end());
460 }
461 
462 auto
465 {
466  return std::make_unique<sles_iter_impl>(stateMap_->upper_bound(key));
467 }
468 
469 auto
470 Ledger::txsBegin() const -> std::unique_ptr<txs_type::iter_base>
471 {
472  return std::make_unique<txs_iter_impl>(!open(), txMap_->begin());
473 }
474 
475 auto
476 Ledger::txsEnd() const -> std::unique_ptr<txs_type::iter_base>
477 {
478  return std::make_unique<txs_iter_impl>(!open(), txMap_->end());
479 }
480 
481 bool
482 Ledger::txExists(uint256 const& key) const
483 {
484  return txMap_->hasItem(key);
485 }
486 
487 auto
488 Ledger::txRead(key_type const& key) const -> tx_type
489 {
490  assert(txMap_);
491  auto const& item = txMap_->peekItem(key);
492  if (!item)
493  return {};
494  if (!open())
495  {
496  auto result = deserializeTxPlusMeta(*item);
497  return {std::move(result.first), std::move(result.second)};
498  }
499  return {deserializeTx(*item), nullptr};
500 }
501 
502 auto
504 {
506  // VFALCO Unfortunately this loads the item
507  // from the NodeStore needlessly.
508  if (!stateMap_->peekItem(key, digest))
509  return std::nullopt;
510  return digest.as_uint256();
511 }
512 
513 //------------------------------------------------------------------------------
514 
515 void
517 {
518  if (!stateMap_->delItem(sle->key()))
519  LogicError("Ledger::rawErase: key not found");
520 }
521 
522 void
524 {
525  if (!stateMap_->delItem(key))
526  LogicError("Ledger::rawErase: key not found");
527 }
528 
529 void
531 {
532  Serializer ss;
533  sle->add(ss);
534  if (!stateMap_->addGiveItem(
536  std::make_shared<SHAMapItem const>(sle->key(), ss.slice())))
537  LogicError("Ledger::rawInsert: key already exists");
538 }
539 
540 void
542 {
543  Serializer ss;
544  sle->add(ss);
545  if (!stateMap_->updateGiveItem(
547  std::make_shared<SHAMapItem const>(sle->key(), ss.slice())))
548  LogicError("Ledger::rawReplace: key not found");
549 }
550 
551 void
553  uint256 const& key,
555  std::shared_ptr<Serializer const> const& metaData)
556 {
557  assert(metaData);
558 
559  // low-level - just add to table
560  Serializer s(txn->getDataLength() + metaData->getDataLength() + 16);
561  s.addVL(txn->peekData());
562  s.addVL(metaData->peekData());
563  if (!txMap().addGiveItem(
565  std::make_shared<SHAMapItem const>(key, s.slice())))
566  LogicError("duplicate_tx: " + to_string(key));
567 }
568 
569 uint256
571  uint256 const& key,
573  std::shared_ptr<Serializer const> const& metaData)
574 {
575  assert(metaData);
576 
577  // low-level - just add to table
578  Serializer s(txn->getDataLength() + metaData->getDataLength() + 16);
579  s.addVL(txn->peekData());
580  s.addVL(metaData->peekData());
581  auto item = std::make_shared<SHAMapItem const>(key, s.slice());
582  auto hash = sha512Half(HashPrefix::txNode, item->slice(), item->key());
583  if (!txMap().addGiveItem(SHAMapNodeType::tnTRANSACTION_MD, std::move(item)))
584  LogicError("duplicate_tx: " + to_string(key));
585 
586  return hash;
587 }
588 
589 bool
590 Ledger::setup(Config const& config)
591 {
592  bool ret = true;
593 
594  fees_.base = config.FEE_DEFAULT;
598 
599  try
600  {
601  if (auto const sle = read(keylet::fees()))
602  {
603  // VFALCO NOTE Why getFieldIndex and not isFieldPresent?
604 
605  if (sle->getFieldIndex(sfBaseFee) != -1)
606  fees_.base = sle->getFieldU64(sfBaseFee);
607 
608  if (sle->getFieldIndex(sfReferenceFeeUnits) != -1)
609  fees_.units = sle->getFieldU32(sfReferenceFeeUnits);
610 
611  if (sle->getFieldIndex(sfReserveBase) != -1)
612  fees_.reserve = sle->getFieldU32(sfReserveBase);
613 
614  if (sle->getFieldIndex(sfReserveIncrement) != -1)
615  fees_.increment = sle->getFieldU32(sfReserveIncrement);
616  }
617  }
618  catch (SHAMapMissingNode const&)
619  {
620  ret = false;
621  }
622  catch (std::exception const&)
623  {
624  Rethrow();
625  }
626 
627  try
628  {
629  rules_ = Rules(*this, config.features);
630  }
631  catch (SHAMapMissingNode const&)
632  {
633  ret = false;
634  }
635  catch (std::exception const&)
636  {
637  Rethrow();
638  }
639 
640  return ret;
641 }
642 
644 Ledger::peek(Keylet const& k) const
645 {
646  auto const& value = stateMap_->peekItem(k.key);
647  if (!value)
648  return nullptr;
649  auto sle = std::make_shared<SLE>(SerialIter{value->slice()}, value->key());
650  if (!k.check(*sle))
651  return nullptr;
652  return sle;
653 }
654 
657 {
658  hash_set<PublicKey> negUnl;
659  if (auto sle = read(keylet::negativeUNL());
660  sle && sle->isFieldPresent(sfDisabledValidators))
661  {
662  auto const& nUnlData = sle->getFieldArray(sfDisabledValidators);
663  for (auto const& n : nUnlData)
664  {
665  if (n.isFieldPresent(sfPublicKey))
666  {
667  auto d = n.getFieldVL(sfPublicKey);
668  auto s = makeSlice(d);
669  if (!publicKeyType(s))
670  {
671  continue;
672  }
673  negUnl.emplace(s);
674  }
675  }
676  }
677 
678  return negUnl;
679 }
680 
683 {
684  if (auto sle = read(keylet::negativeUNL());
685  sle && sle->isFieldPresent(sfValidatorToDisable))
686  {
687  auto d = sle->getFieldVL(sfValidatorToDisable);
688  auto s = makeSlice(d);
689  if (publicKeyType(s))
690  return PublicKey(s);
691  }
692 
693  return std::nullopt;
694 }
695 
698 {
699  if (auto sle = read(keylet::negativeUNL());
700  sle && sle->isFieldPresent(sfValidatorToReEnable))
701  {
702  auto d = sle->getFieldVL(sfValidatorToReEnable);
703  auto s = makeSlice(d);
704  if (publicKeyType(s))
705  return PublicKey(s);
706  }
707 
708  return std::nullopt;
709 }
710 
711 void
713 {
714  auto sle = peek(keylet::negativeUNL());
715  if (!sle)
716  return;
717 
718  bool const hasToDisable = sle->isFieldPresent(sfValidatorToDisable);
719  bool const hasToReEnable = sle->isFieldPresent(sfValidatorToReEnable);
720 
721  if (!hasToDisable && !hasToReEnable)
722  return;
723 
724  STArray newNUnl;
725  if (sle->isFieldPresent(sfDisabledValidators))
726  {
727  auto const& oldNUnl = sle->getFieldArray(sfDisabledValidators);
728  for (auto v : oldNUnl)
729  {
730  if (hasToReEnable && v.isFieldPresent(sfPublicKey) &&
731  v.getFieldVL(sfPublicKey) ==
732  sle->getFieldVL(sfValidatorToReEnable))
733  continue;
734  newNUnl.push_back(v);
735  }
736  }
737 
738  if (hasToDisable)
739  {
741  newNUnl.back().setFieldVL(
742  sfPublicKey, sle->getFieldVL(sfValidatorToDisable));
744  }
745 
746  if (!newNUnl.empty())
747  {
748  sle->setFieldArray(sfDisabledValidators, newNUnl);
749  if (hasToReEnable)
750  sle->makeFieldAbsent(sfValidatorToReEnable);
751  if (hasToDisable)
752  sle->makeFieldAbsent(sfValidatorToDisable);
753  rawReplace(sle);
754  }
755  else
756  {
757  rawErase(sle);
758  }
759 }
760 
761 //------------------------------------------------------------------------------
762 bool
764 {
765  std::vector<SHAMapMissingNode> missingNodes1;
766  std::vector<SHAMapMissingNode> missingNodes2;
767 
768  if (stateMap_->getHash().isZero() && !info_.accountHash.isZero() &&
769  !stateMap_->fetchRoot(SHAMapHash{info_.accountHash}, nullptr))
770  {
771  missingNodes1.emplace_back(
773  }
774  else
775  {
776  stateMap_->walkMap(missingNodes1, 32);
777  }
778 
779  if (!missingNodes1.empty())
780  {
781  if (auto stream = j.info())
782  {
783  stream << missingNodes1.size() << " missing account node(s)";
784  stream << "First: " << missingNodes1[0].what();
785  }
786  }
787 
788  if (txMap_->getHash().isZero() && info_.txHash.isNonZero() &&
789  !txMap_->fetchRoot(SHAMapHash{info_.txHash}, nullptr))
790  {
791  missingNodes2.emplace_back(
793  }
794  else
795  {
796  txMap_->walkMap(missingNodes2, 32);
797  }
798 
799  if (!missingNodes2.empty())
800  {
801  if (auto stream = j.info())
802  {
803  stream << missingNodes2.size() << " missing transaction node(s)";
804  stream << "First: " << missingNodes2[0].what();
805  }
806  }
807  return missingNodes1.empty() && missingNodes2.empty();
808 }
809 
810 bool
812 {
814  txMap_ && (info_.accountHash == stateMap_->getHash().as_uint256()) &&
815  (info_.txHash == txMap_->getHash().as_uint256()))
816  {
817  return true;
818  }
819 
820  Json::Value j = getJson({*this, {}});
821 
822  j[jss::accountTreeHash] = to_string(info_.accountHash);
823  j[jss::transTreeHash] = to_string(info_.txHash);
824 
825  JLOG(ledgerJ.fatal()) << "ledger is not sensible" << j;
826 
827  assert(false);
828 
829  return false;
830 }
831 
832 // update the skip list with the information from our previous ledger
833 // VFALCO TODO Document this skip list concept
834 void
836 {
837  if (info_.seq == 0) // genesis ledger has no previous ledger
838  return;
839 
840  std::uint32_t prevIndex = info_.seq - 1;
841 
842  // update record of every 256th ledger
843  if ((prevIndex & 0xff) == 0)
844  {
845  auto const k = keylet::skip(prevIndex);
846  auto sle = peek(k);
847  std::vector<uint256> hashes;
848 
849  bool created;
850  if (!sle)
851  {
852  sle = std::make_shared<SLE>(k);
853  created = true;
854  }
855  else
856  {
857  hashes = static_cast<decltype(hashes)>(sle->getFieldV256(sfHashes));
858  created = false;
859  }
860 
861  assert(hashes.size() <= 256);
862  hashes.push_back(info_.parentHash);
863  sle->setFieldV256(sfHashes, STVector256(hashes));
864  sle->setFieldU32(sfLastLedgerSequence, prevIndex);
865  if (created)
866  rawInsert(sle);
867  else
868  rawReplace(sle);
869  }
870 
871  // update record of past 256 ledger
872  auto const k = keylet::skip();
873  auto sle = peek(k);
874  std::vector<uint256> hashes;
875  bool created;
876  if (!sle)
877  {
878  sle = std::make_shared<SLE>(k);
879  created = true;
880  }
881  else
882  {
883  hashes = static_cast<decltype(hashes)>(sle->getFieldV256(sfHashes));
884  created = false;
885  }
886  assert(hashes.size() <= 256);
887  if (hashes.size() == 256)
888  hashes.erase(hashes.begin());
889  hashes.push_back(info_.parentHash);
890  sle->setFieldV256(sfHashes, STVector256(hashes));
891  sle->setFieldU32(sfLastLedgerSequence, prevIndex);
892  if (created)
893  rawInsert(sle);
894  else
895  rawReplace(sle);
896 }
897 
898 bool
900 {
901  return info_.seq % FLAG_LEDGER_INTERVAL == 0;
902 }
903 bool
905 {
906  return (info_.seq + 1) % FLAG_LEDGER_INTERVAL == 0;
907 }
908 
909 bool
911 {
912  return seq % FLAG_LEDGER_INTERVAL == 0;
913 }
914 
915 static bool
917  Application& app,
918  std::shared_ptr<Ledger const> const& ledger,
919  bool current)
920 {
921  auto j = app.journal("Ledger");
922  auto seq = ledger->info().seq;
923  if (!app.pendingSaves().startWork(seq))
924  {
925  // The save was completed synchronously
926  JLOG(j.debug()) << "Save aborted";
927  return true;
928  }
929 
930  // TODO(tom): Fix this hard-coded SQL!
931  JLOG(j.trace()) << "saveValidatedLedger " << (current ? "" : "fromAcquire ")
932  << seq;
933 
934  if (!ledger->info().accountHash.isNonZero())
935  {
936  JLOG(j.fatal()) << "AH is zero: " << getJson({*ledger, {}});
937  assert(false);
938  }
939 
940  if (ledger->info().accountHash != ledger->stateMap().getHash().as_uint256())
941  {
942  JLOG(j.fatal()) << "sAL: " << ledger->info().accountHash
943  << " != " << ledger->stateMap().getHash();
944  JLOG(j.fatal()) << "saveAcceptedLedger: seq=" << seq
945  << ", current=" << current;
946  assert(false);
947  }
948 
949  assert(ledger->info().txHash == ledger->txMap().getHash().as_uint256());
950 
951  // Save the ledger header in the hashed object store
952  {
953  Serializer s(128);
955  addRaw(ledger->info(), s);
956  app.getNodeStore().store(
957  hotLEDGER, std::move(s.modData()), ledger->info().hash, seq);
958  }
959 
960  AcceptedLedger::pointer aLedger;
961  try
962  {
963  aLedger = app.getAcceptedLedgerCache().fetch(ledger->info().hash);
964  if (!aLedger)
965  {
966  aLedger = std::make_shared<AcceptedLedger>(ledger, app);
967  app.getAcceptedLedgerCache().canonicalize_replace_client(
968  ledger->info().hash, aLedger);
969  }
970  }
971  catch (std::exception const&)
972  {
973  JLOG(j.warn()) << "An accepted ledger was missing nodes";
974  app.getLedgerMaster().failedSave(seq, ledger->info().hash);
975  // Clients can now trust the database for information about this
976  // ledger sequence.
977  app.pendingSaves().finishWork(seq);
978  return false;
979  }
980 
981  if (!app.config().reporting())
982  {
983  static boost::format deleteLedger(
984  "DELETE FROM Ledgers WHERE LedgerSeq = %u;");
985  static boost::format deleteTrans1(
986  "DELETE FROM Transactions WHERE LedgerSeq = %u;");
987  static boost::format deleteTrans2(
988  "DELETE FROM AccountTransactions WHERE LedgerSeq = %u;");
989  static boost::format deleteAcctTrans(
990  "DELETE FROM AccountTransactions WHERE TransID = '%s';");
991 
992  {
993  auto db = app.getLedgerDB().checkoutDb();
994  *db << boost::str(deleteLedger % seq);
995  }
996 
997  if (app.config().useTxTables())
998  {
999  auto db = app.getTxnDB().checkoutDb();
1000 
1001  soci::transaction tr(*db);
1002 
1003  *db << boost::str(deleteTrans1 % seq);
1004  *db << boost::str(deleteTrans2 % seq);
1005 
1006  std::string const ledgerSeq(std::to_string(seq));
1007 
1008  for (auto const& [_, acceptedLedgerTx] : aLedger->getMap())
1009  {
1010  (void)_;
1011  uint256 transactionID = acceptedLedgerTx->getTransactionID();
1012 
1013  std::string const txnId(to_string(transactionID));
1014  std::string const txnSeq(
1015  std::to_string(acceptedLedgerTx->getTxnSeq()));
1016 
1017  *db << boost::str(deleteAcctTrans % transactionID);
1018 
1019  auto const& accts = acceptedLedgerTx->getAffected();
1020 
1021  if (!accts.empty())
1022  {
1023  std::string sql(
1024  "INSERT INTO AccountTransactions "
1025  "(TransID, Account, LedgerSeq, TxnSeq) VALUES ");
1026 
1027  // Try to make an educated guess on how much space we'll
1028  // need for our arguments. In argument order we have: 64
1029  // + 34 + 10 + 10 = 118 + 10 extra = 128 bytes
1030  sql.reserve(sql.length() + (accts.size() * 128));
1031 
1032  bool first = true;
1033  for (auto const& account : accts)
1034  {
1035  if (!first)
1036  sql += ", ('";
1037  else
1038  {
1039  sql += "('";
1040  first = false;
1041  }
1042 
1043  sql += txnId;
1044  sql += "','";
1045  sql += app.accountIDCache().toBase58(account);
1046  sql += "',";
1047  sql += ledgerSeq;
1048  sql += ",";
1049  sql += txnSeq;
1050  sql += ")";
1051  }
1052  sql += ";";
1053  JLOG(j.trace()) << "ActTx: " << sql;
1054  *db << sql;
1055  }
1056  else
1057  {
1058  JLOG(j.warn()) << "Transaction in ledger " << seq
1059  << " affects no accounts";
1060  JLOG(j.warn()) << acceptedLedgerTx->getTxn()->getJson(
1062  }
1063 
1064  *db
1066  acceptedLedgerTx->getTxn()->getMetaSQL(
1067  seq, acceptedLedgerTx->getEscMeta()) +
1068  ";");
1069 
1071  }
1072 
1073  tr.commit();
1074  }
1075 
1076  {
1077  static std::string addLedger(
1078  R"sql(INSERT OR REPLACE INTO Ledgers
1079  (LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,
1080  CloseTimeRes,CloseFlags,AccountSetHash,TransSetHash)
1081  VALUES
1082  (:ledgerHash,:ledgerSeq,:prevHash,:totalCoins,:closingTime,:prevClosingTime,
1083  :closeTimeRes,:closeFlags,:accountSetHash,:transSetHash);)sql");
1084 
1085  auto db(app.getLedgerDB().checkoutDb());
1086 
1087  soci::transaction tr(*db);
1088 
1089  auto const hash = to_string(ledger->info().hash);
1090  auto const parentHash = to_string(ledger->info().parentHash);
1091  auto const drops = to_string(ledger->info().drops);
1092  auto const closeTime =
1093  ledger->info().closeTime.time_since_epoch().count();
1094  auto const parentCloseTime =
1095  ledger->info().parentCloseTime.time_since_epoch().count();
1096  auto const closeTimeResolution =
1097  ledger->info().closeTimeResolution.count();
1098  auto const closeFlags = ledger->info().closeFlags;
1099  auto const accountHash = to_string(ledger->info().accountHash);
1100  auto const txHash = to_string(ledger->info().txHash);
1101 
1102  *db << addLedger, soci::use(hash), soci::use(seq),
1103  soci::use(parentHash), soci::use(drops), soci::use(closeTime),
1104  soci::use(parentCloseTime), soci::use(closeTimeResolution),
1105  soci::use(closeFlags), soci::use(accountHash),
1106  soci::use(txHash);
1107 
1108  tr.commit();
1109  }
1110  }
1111  else
1112  {
1113  assert(false);
1114  }
1115 
1116  // Clients can now trust the database for
1117  // information about this ledger sequence.
1118  app.pendingSaves().finishWork(seq);
1119  return true;
1120 }
1125 bool
1127  Application& app,
1128  std::shared_ptr<Ledger const> const& ledger,
1129  bool isSynchronous,
1130  bool isCurrent)
1131 {
1132  if (!app.getHashRouter().setFlags(ledger->info().hash, SF_SAVED))
1133  {
1134  // We have tried to save this ledger recently
1135  auto stream = app.journal("Ledger").debug();
1136  JLOG(stream) << "Double pend save for " << ledger->info().seq;
1137 
1138  if (!isSynchronous || !app.pendingSaves().pending(ledger->info().seq))
1139  {
1140  // Either we don't need it to be finished
1141  // or it is finished
1142  return true;
1143  }
1144  }
1145 
1146  assert(ledger->isImmutable());
1147 
1148  if (!app.pendingSaves().shouldWork(ledger->info().seq, isSynchronous))
1149  {
1150  auto stream = app.journal("Ledger").debug();
1151  JLOG(stream) << "Pend save with seq in pending saves "
1152  << ledger->info().seq;
1153 
1154  return true;
1155  }
1156 
1157  JobType const jobType{isCurrent ? jtPUBLEDGER : jtPUBOLDLEDGER};
1158  char const* const jobName{
1159  isCurrent ? "Ledger::pendSave" : "Ledger::pendOldSave"};
1160 
1161  // See if we can use the JobQueue.
1162  if (!isSynchronous &&
1163  app.getJobQueue().addJob(
1164  jobType, jobName, [&app, ledger, isCurrent](Job&) {
1165  saveValidatedLedger(app, ledger, isCurrent);
1166  }))
1167  {
1168  return true;
1169  }
1170 
1171  // The JobQueue won't do the Job. Do the save synchronously.
1172  return saveValidatedLedger(app, ledger, isCurrent);
1173 }
1174 
1175 void
1176 Ledger::unshare() const
1177 {
1178  stateMap_->unshare();
1179  txMap_->unshare();
1180 }
1181 
1182 void
1183 Ledger::invariants() const
1184 {
1185  stateMap_->invariants();
1186  txMap_->invariants();
1187 }
1188 //------------------------------------------------------------------------------
1189 
1190 /*
1191  * Load a ledger from the database.
1192  *
1193  * @param sqlSuffix: Additional string to append to the sql query.
1194  * (typically a where clause).
1195  * @param acquire: Acquire the ledger if not found locally.
1196  * @return The ledger, ledger sequence, and ledger hash.
1197  */
1199 loadLedgerHelper(std::string const& sqlSuffix, Application& app, bool acquire)
1200 {
1201  uint256 ledgerHash{};
1202  std::uint32_t ledgerSeq{0};
1203 
1204  auto db = app.getLedgerDB().checkoutDb();
1205 
1206  // SOCI requires boost::optional (not std::optional) as parameters.
1207  boost::optional<std::string> sLedgerHash, sPrevHash, sAccountHash,
1208  sTransHash;
1209  boost::optional<std::uint64_t> totDrops, closingTime, prevClosingTime,
1210  closeResolution, closeFlags, ledgerSeq64;
1211 
1212  std::string const sql =
1213  "SELECT "
1214  "LedgerHash, PrevHash, AccountSetHash, TransSetHash, "
1215  "TotalCoins,"
1216  "ClosingTime, PrevClosingTime, CloseTimeRes, CloseFlags,"
1217  "LedgerSeq from Ledgers " +
1218  sqlSuffix + ";";
1219 
1220  *db << sql, soci::into(sLedgerHash), soci::into(sPrevHash),
1221  soci::into(sAccountHash), soci::into(sTransHash), soci::into(totDrops),
1222  soci::into(closingTime), soci::into(prevClosingTime),
1223  soci::into(closeResolution), soci::into(closeFlags),
1224  soci::into(ledgerSeq64);
1225 
1226  if (!db->got_data())
1227  {
1228  auto stream = app.journal("Ledger").debug();
1229  JLOG(stream) << "Ledger not found: " << sqlSuffix;
1230  return std::make_tuple(
1231  std::shared_ptr<Ledger>(), ledgerSeq, ledgerHash);
1232  }
1233 
1234  ledgerSeq = rangeCheckedCast<std::uint32_t>(ledgerSeq64.value_or(0));
1235 
1236  uint256 prevHash{}, accountHash{}, transHash{};
1237  if (sLedgerHash)
1238  (void)ledgerHash.parseHex(*sLedgerHash);
1239  if (sPrevHash)
1240  (void)prevHash.parseHex(*sPrevHash);
1241  if (sAccountHash)
1242  (void)accountHash.parseHex(*sAccountHash);
1243  if (sTransHash)
1244  (void)transHash.parseHex(*sTransHash);
1245 
1246  using time_point = NetClock::time_point;
1247  using duration = NetClock::duration;
1248 
1249  LedgerInfo info;
1250  info.parentHash = prevHash;
1251  info.txHash = transHash;
1252  info.accountHash = accountHash;
1253  info.drops = totDrops.value_or(0);
1254  info.closeTime = time_point{duration{closingTime.value_or(0)}};
1255  info.parentCloseTime = time_point{duration{prevClosingTime.value_or(0)}};
1256  info.closeFlags = closeFlags.value_or(0);
1257  info.closeTimeResolution = duration{closeResolution.value_or(0)};
1258  info.seq = ledgerSeq;
1259 
1260  bool loaded;
1261  auto ledger = std::make_shared<Ledger>(
1262  info,
1263  loaded,
1264  acquire,
1265  app.config(),
1266  app.getNodeFamily(),
1267  app.journal("Ledger"));
1268 
1269  if (!loaded)
1270  ledger.reset();
1272  return std::make_tuple(ledger, ledgerSeq, ledgerHash);
1273 }
1274 
1275 static void
1277  std::shared_ptr<Ledger> const& ledger,
1278  Config const& config,
1279  beast::Journal j)
1280 {
1281  if (!ledger)
1282  return;
1283 
1284  ledger->setImmutable(config);
1285 
1286  JLOG(j.trace()) << "Loaded ledger: " << to_string(ledger->info().hash);
1287 
1288  ledger->setFull();
1289 }
1290 
1291 // Load the ledger info for the specified ledger/s from the database
1292 // @param whichLedger specifies the ledger to load via ledger sequence, ledger
1293 // hash, a range of ledgers, or std::monostate (which loads the most recent)
1294 // @param app Application
1295 // @return vector of LedgerInfos
1298  std::variant<
1300  uint256,
1301  uint32_t,
1302  std::pair<uint32_t, uint32_t>> const& whichLedger,
1303  Application& app)
1304 {
1306 #ifdef RIPPLED_REPORTING
1307  auto log = app.journal("Ledger");
1308  assert(app.config().reporting());
1309  std::stringstream sql;
1310  sql << "SELECT ledger_hash, prev_hash, account_set_hash, trans_set_hash, "
1311  "total_coins, closing_time, prev_closing_time, close_time_res, "
1312  "close_flags, ledger_seq FROM ledgers ";
1313 
1314  uint32_t expNumResults = 1;
1315 
1316  if (auto ledgerSeq = std::get_if<uint32_t>(&whichLedger))
1317  {
1318  sql << "WHERE ledger_seq = " + std::to_string(*ledgerSeq);
1319  }
1320  else if (auto ledgerHash = std::get_if<uint256>(&whichLedger))
1321  {
1322  sql << ("WHERE ledger_hash = \'\\x" + strHex(*ledgerHash) + "\'");
1323  }
1324  else if (
1325  auto minAndMax =
1327  {
1328  expNumResults = minAndMax->second - minAndMax->first;
1329 
1330  sql
1331  << ("WHERE ledger_seq >= " + std::to_string(minAndMax->first) +
1332  " AND ledger_seq <= " + std::to_string(minAndMax->second));
1333  }
1334  else
1335  {
1336  sql << ("ORDER BY ledger_seq desc LIMIT 1");
1337  }
1338  sql << ";";
1339 
1340  JLOG(log.trace()) << __func__ << " : sql = " << sql.str();
1341 
1342  auto res = PgQuery(app.getPgPool())(sql.str().data());
1343  if (!res)
1344  {
1345  JLOG(log.error()) << __func__ << " : Postgres response is null - sql = "
1346  << sql.str();
1347  assert(false);
1348  return {};
1349  }
1350  else if (res.status() != PGRES_TUPLES_OK)
1351  {
1352  JLOG(log.error()) << __func__
1353  << " : Postgres response should have been "
1354  "PGRES_TUPLES_OK but instead was "
1355  << res.status() << " - msg = " << res.msg()
1356  << " - sql = " << sql.str();
1357  assert(false);
1358  return {};
1359  }
1360 
1361  JLOG(log.trace()) << __func__ << " Postgres result msg : " << res.msg();
1362 
1363  if (res.isNull() || res.ntuples() == 0)
1364  {
1365  JLOG(log.debug()) << __func__
1366  << " : Ledger not found. sql = " << sql.str();
1367  return {};
1368  }
1369  else if (res.ntuples() > 0)
1370  {
1371  if (res.nfields() != 10)
1372  {
1373  JLOG(log.error()) << __func__
1374  << " : Wrong number of fields in Postgres "
1375  "response. Expected 10, but got "
1376  << res.nfields() << " . sql = " << sql.str();
1377  assert(false);
1378  return {};
1379  }
1380  }
1381 
1382  for (size_t i = 0; i < res.ntuples(); ++i)
1383  {
1384  char const* hash = res.c_str(i, 0);
1385  char const* prevHash = res.c_str(i, 1);
1386  char const* accountHash = res.c_str(i, 2);
1387  char const* txHash = res.c_str(i, 3);
1388  std::int64_t totalCoins = res.asBigInt(i, 4);
1389  std::int64_t closeTime = res.asBigInt(i, 5);
1390  std::int64_t parentCloseTime = res.asBigInt(i, 6);
1391  std::int64_t closeTimeRes = res.asBigInt(i, 7);
1392  std::int64_t closeFlags = res.asBigInt(i, 8);
1393  std::int64_t ledgerSeq = res.asBigInt(i, 9);
1394 
1395  JLOG(log.trace()) << __func__ << " - Postgres response = " << hash
1396  << " , " << prevHash << " , " << accountHash << " , "
1397  << txHash << " , " << totalCoins << ", " << closeTime
1398  << ", " << parentCloseTime << ", " << closeTimeRes
1399  << ", " << closeFlags << ", " << ledgerSeq
1400  << " - sql = " << sql.str();
1401  JLOG(log.debug()) << __func__
1402  << " - Successfully fetched ledger with sequence = "
1403  << ledgerSeq << " from Postgres";
1404 
1405  using time_point = NetClock::time_point;
1406  using duration = NetClock::duration;
1407 
1408  LedgerInfo info;
1409  if (!info.parentHash.parseHex(prevHash + 2))
1410  assert(false);
1411  if (!info.txHash.parseHex(txHash + 2))
1412  assert(false);
1413  if (!info.accountHash.parseHex(accountHash + 2))
1414  assert(false);
1415  info.drops = totalCoins;
1416  info.closeTime = time_point{duration{closeTime}};
1417  info.parentCloseTime = time_point{duration{parentCloseTime}};
1418  info.closeFlags = closeFlags;
1419  info.closeTimeResolution = duration{closeTimeRes};
1420  info.seq = ledgerSeq;
1421  if (!info.hash.parseHex(hash + 2))
1422  assert(false);
1423  info.validated = true;
1424  infos.push_back(info);
1425  }
1426 
1427 #endif
1428  return infos;
1429 }
1430 
1431 // Load a ledger from Postgres
1432 // @param whichLedger specifies sequence or hash of ledger. Passing
1433 // std::monostate loads the most recent ledger
1434 // @param app the Application
1435 // @return tuple of (ledger, sequence, hash)
1439  Application& app)
1440 {
1442  std::visit(
1443  [&infos, &app](auto&& arg) {
1444  infos = loadLedgerInfosPostgres(arg, app);
1445  },
1446  whichLedger);
1447  assert(infos.size() <= 1);
1448  if (!infos.size())
1450  LedgerInfo info = infos[0];
1451  bool loaded;
1452  auto ledger = std::make_shared<Ledger>(
1453  info,
1454  loaded,
1455  false,
1456  app.config(),
1457  app.getNodeFamily(),
1458  app.journal("Ledger"));
1459 
1460  if (!loaded)
1461  ledger.reset();
1463  return std::make_tuple(ledger, info.seq, info.hash);
1464 }
1465 
1467 getLatestLedger(Application& app)
1468 {
1469  if (app.config().reporting())
1470  return loadLedgerHelperPostgres({}, app);
1471  else
1472  return loadLedgerHelper("order by LedgerSeq desc limit 1", app);
1473 }
1474 
1475 // Load a ledger by index (AKA sequence) from Postgres
1476 // @param ledgerIndex the ledger index (or sequence) to load
1477 // @param app reference to Application
1478 // @return the loaded ledger
1481 {
1482  std::shared_ptr<Ledger> ledger;
1483  std::tie(ledger, std::ignore, std::ignore) =
1484  loadLedgerHelperPostgres(uint32_t{ledgerIndex}, app);
1485  finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger"));
1486  return ledger;
1487 }
1488 
1489 // Load a ledger by hash from Postgres
1490 // @param hash hash of the ledger to load
1491 // @param app reference to Application
1492 // @return the loaded ledger
1494 loadByHashPostgres(uint256 const& ledgerHash, Application& app)
1495 {
1496  std::shared_ptr<Ledger> ledger;
1497  std::tie(ledger, std::ignore, std::ignore) =
1498  loadLedgerHelperPostgres(uint256{ledgerHash}, app);
1499 
1500  finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger"));
1501 
1502  assert(!ledger || ledger->info().hash == ledgerHash);
1503 
1504  return ledger;
1505 }
1506 
1507 // Given a ledger sequence, return the ledger hash
1508 // @param ledgerIndex ledger sequence
1509 // @param app Application
1510 // @return hash of ledger
1511 static uint256
1513 {
1514  auto infos = loadLedgerInfosPostgres(ledgerIndex, app);
1515  assert(infos.size() <= 1);
1516  if (infos.size())
1517  return infos[0].hash;
1518  return {};
1519 }
1520 
1521 // Given a ledger sequence, return the ledger hash and the parent hash
1522 // @param ledgerIndex ledger sequence
1523 // @param[out] ledgerHash hash of ledger
1524 // @param[out] parentHash hash of parent ledger
1525 // @param app Application
1526 // @return true if the data was found
1527 static bool
1529  std::uint32_t ledgerIndex,
1530  uint256& ledgerHash,
1531  uint256& parentHash,
1532  Application& app)
1533 {
1534  auto infos = loadLedgerInfosPostgres(ledgerIndex, app);
1535  assert(infos.size() <= 1);
1536  if (infos.size())
1537  {
1538  ledgerHash = infos[0].hash;
1539  parentHash = infos[0].parentHash;
1540  return true;
1541  }
1542  return false;
1543 }
1544 
1545 // Given a contiguous range of sequences, return a map of
1546 // sequence -> (hash, parent hash)
1547 // @param minSeq lower bound of range
1548 // @param maxSeq upper bound of range
1549 // @param app Application
1550 // @return mapping of all found ledger sequences to their hash and parent hash
1553  std::uint32_t minSeq,
1554  std::uint32_t maxSeq,
1555  Application& app)
1556 {
1558  auto infos = loadLedgerInfosPostgres(std::make_pair(minSeq, maxSeq), app);
1559  for (auto& info : infos)
1560  {
1561  ret[info.seq] = std::make_pair(info.hash, info.parentHash);
1562  }
1563  return ret;
1564 }
1565 
1567 loadByIndex(std::uint32_t ledgerIndex, Application& app, bool acquire)
1568 {
1569  if (app.config().reporting())
1570  return loadByIndexPostgres(ledgerIndex, app);
1571  std::shared_ptr<Ledger> ledger;
1572  {
1574  s << "WHERE LedgerSeq = " << ledgerIndex;
1575  std::tie(ledger, std::ignore, std::ignore) =
1576  loadLedgerHelper(s.str(), app, acquire);
1577  }
1578 
1579  finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger"));
1580  return ledger;
1581 }
1582 
1584 loadByHash(uint256 const& ledgerHash, Application& app, bool acquire)
1585 {
1586  if (app.config().reporting())
1587  return loadByHashPostgres(ledgerHash, app);
1588  std::shared_ptr<Ledger> ledger;
1589  {
1591  s << "WHERE LedgerHash = '" << ledgerHash << "'";
1592  std::tie(ledger, std::ignore, std::ignore) =
1593  loadLedgerHelper(s.str(), app, acquire);
1594  }
1595 
1596  finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger"));
1597 
1598  assert(!ledger || ledger->info().hash == ledgerHash);
1600  return ledger;
1601 }
1602 
1603 uint256
1604 getHashByIndex(std::uint32_t ledgerIndex, Application& app)
1605 {
1606  if (app.config().reporting())
1607  return getHashByIndexPostgres(ledgerIndex, app);
1608  uint256 ret;
1609 
1610  std::string sql =
1611  "SELECT LedgerHash FROM Ledgers INDEXED BY SeqLedger WHERE LedgerSeq='";
1612  sql.append(std::to_string(ledgerIndex));
1613  sql.append("';");
1614 
1615  std::string hash;
1616  {
1617  auto db = app.getLedgerDB().checkoutDb();
1618 
1619  // SOCI requires boost::optional (not std::optional) as the parameter.
1620  boost::optional<std::string> lh;
1621  *db << sql, soci::into(lh);
1622 
1623  if (!db->got_data() || !lh)
1624  return ret;
1625 
1626  hash = *lh;
1627  if (hash.empty())
1628  return ret;
1629  }
1630 
1631  (void)ret.parseHex(hash);
1632  return ret;
1633 }
1634 
1635 bool
1637  std::uint32_t ledgerIndex,
1638  uint256& ledgerHash,
1639  uint256& parentHash,
1640  Application& app)
1641 {
1642  if (app.config().reporting())
1643  return getHashesByIndexPostgres(
1644  ledgerIndex, ledgerHash, parentHash, app);
1645  auto db = app.getLedgerDB().checkoutDb();
1646 
1647  // SOCI requires boost::optional (not std::optional) as parameters.
1648  boost::optional<std::string> lhO, phO;
1649 
1650  *db << "SELECT LedgerHash,PrevHash FROM Ledgers "
1651  "INDEXED BY SeqLedger Where LedgerSeq = :ls;",
1652  soci::into(lhO), soci::into(phO), soci::use(ledgerIndex);
1653 
1654  if (!lhO || !phO)
1655  {
1656  auto stream = app.journal("Ledger").trace();
1657  JLOG(stream) << "Don't have ledger " << ledgerIndex;
1658  return false;
1659  }
1661  return ledgerHash.parseHex(*lhO) && parentHash.parseHex(*phO);
1662 }
1663 
1665 getHashesByIndex(std::uint32_t minSeq, std::uint32_t maxSeq, Application& app)
1666 {
1667  if (app.config().reporting())
1668  return getHashesByIndexPostgres(minSeq, maxSeq, app);
1670 
1671  std::string sql =
1672  "SELECT LedgerSeq,LedgerHash,PrevHash FROM Ledgers WHERE LedgerSeq >= ";
1673  sql.append(std::to_string(minSeq));
1674  sql.append(" AND LedgerSeq <= ");
1675  sql.append(std::to_string(maxSeq));
1676  sql.append(";");
1677 
1678  auto db = app.getLedgerDB().checkoutDb();
1679 
1680  std::uint64_t ls;
1681  std::string lh;
1682 
1683  // SOCI requires boost::optional (not std::optional) as the parameter.
1684  boost::optional<std::string> ph;
1685  soci::statement st =
1686  (db->prepare << sql, soci::into(ls), soci::into(lh), soci::into(ph));
1687 
1688  st.execute();
1689  while (st.fetch())
1690  {
1691  std::pair<uint256, uint256>& hashes =
1692  ret[rangeCheckedCast<std::uint32_t>(ls)];
1693  (void)hashes.first.parseHex(lh);
1694  if (ph)
1695  (void)hashes.second.parseHex(*ph);
1696  else
1697  hashes.second.zero();
1698  if (!ph)
1699  {
1700  auto stream = app.journal("Ledger").warn();
1701  JLOG(stream) << "Null prev hash for ledger seq: " << ls;
1702  }
1703  }
1704 
1705  return ret;
1706 }
1707 
1708 std::vector<
1710 flatFetchTransactions(Application& app, std::vector<uint256>& nodestoreHashes)
1711 {
1712  if (!app.config().reporting())
1713  {
1714  assert(false);
1715  Throw<std::runtime_error>(
1716  "flatFetchTransactions: not running in reporting mode");
1717  }
1718 
1719  std::vector<
1721  txns;
1722  auto start = std::chrono::system_clock::now();
1723  auto nodeDb =
1724  dynamic_cast<NodeStore::DatabaseNodeImp*>(&(app.getNodeStore()));
1725  if (!nodeDb)
1726  {
1727  assert(false);
1728  Throw<std::runtime_error>(
1729  "Called flatFetchTransactions but database is not DatabaseNodeImp");
1730  }
1731  auto objs = nodeDb->fetchBatch(nodestoreHashes);
1732 
1734  JLOG(app.journal("Ledger").debug())
1735  << " Flat fetch time : " << ((end - start).count() / 1000000000.0)
1736  << " number of transactions " << nodestoreHashes.size();
1737  assert(objs.size() == nodestoreHashes.size());
1738  for (size_t i = 0; i < objs.size(); ++i)
1739  {
1740  uint256& nodestoreHash = nodestoreHashes[i];
1741  auto& obj = objs[i];
1742  if (obj)
1743  {
1744  auto node = SHAMapTreeNode::makeFromPrefix(
1745  makeSlice(obj->getData()), SHAMapHash{nodestoreHash});
1746  if (!node)
1747  {
1748  assert(false);
1749  Throw<std::runtime_error>(
1750  "flatFetchTransactions : Error making SHAMap node");
1751  }
1752  auto item = (static_cast<SHAMapLeafNode*>(node.get()))->peekItem();
1753  if (!item)
1754  {
1755  assert(false);
1756  Throw<std::runtime_error>(
1757  "flatFetchTransactions : Error reading SHAMap node");
1758  }
1759  auto txnPlusMeta = deserializeTxPlusMeta(*item);
1760  if (!txnPlusMeta.first || !txnPlusMeta.second)
1761  {
1762  assert(false);
1763  Throw<std::runtime_error>(
1764  "flatFetchTransactions : Error deserializing SHAMap node");
1765  }
1766  txns.push_back(std::move(txnPlusMeta));
1767  }
1768  else
1769  {
1770  assert(false);
1771  Throw<std::runtime_error>(
1772  "flatFetchTransactions : Containing SHAMap node not found");
1773  }
1774  }
1775  return txns;
1776 }
1777 std::vector<
1779 flatFetchTransactions(ReadView const& ledger, Application& app)
1780 {
1781  if (!app.config().reporting())
1782  {
1783  assert(false);
1784  return {};
1785  }
1786  std::vector<uint256> nodestoreHashes;
1787 #ifdef RIPPLED_REPORTING
1788 
1789  auto log = app.journal("Ledger");
1790 
1791  std::string query =
1792  "SELECT nodestore_hash"
1793  " FROM transactions "
1794  " WHERE ledger_seq = " +
1795  std::to_string(ledger.info().seq);
1796  auto res = PgQuery(app.getPgPool())(query.c_str());
1797 
1798  if (!res)
1799  {
1800  JLOG(log.error()) << __func__
1801  << " : Postgres response is null - query = " << query;
1802  assert(false);
1803  return {};
1804  }
1805  else if (res.status() != PGRES_TUPLES_OK)
1806  {
1807  JLOG(log.error()) << __func__
1808  << " : Postgres response should have been "
1809  "PGRES_TUPLES_OK but instead was "
1810  << res.status() << " - msg = " << res.msg()
1811  << " - query = " << query;
1812  assert(false);
1813  return {};
1814  }
1815 
1816  JLOG(log.trace()) << __func__ << " Postgres result msg : " << res.msg();
1817 
1818  if (res.isNull() || res.ntuples() == 0)
1819  {
1820  JLOG(log.debug()) << __func__
1821  << " : Ledger not found. query = " << query;
1822  return {};
1823  }
1824  else if (res.ntuples() > 0)
1825  {
1826  if (res.nfields() != 1)
1827  {
1828  JLOG(log.error()) << __func__
1829  << " : Wrong number of fields in Postgres "
1830  "response. Expected 1, but got "
1831  << res.nfields() << " . query = " << query;
1832  assert(false);
1833  return {};
1834  }
1835  }
1836 
1837  JLOG(log.trace()) << __func__ << " : result = " << res.c_str()
1838  << " : query = " << query;
1839  for (size_t i = 0; i < res.ntuples(); ++i)
1840  {
1841  char const* nodestoreHash = res.c_str(i, 0);
1842  uint256 hash;
1843  if (!hash.parseHex(nodestoreHash + 2))
1844  assert(false);
1845 
1846  nodestoreHashes.push_back(hash);
1847  }
1848 #endif
1849 
1850  return flatFetchTransactions(app, nodestoreHashes);
1851 }
1852 } // namespace ripple
ripple::STArray::empty
bool empty() const
Definition: STArray.h:138
beast::Journal::fatal
Stream fatal() const
Definition: Journal.h:339
ripple::Ledger::slesUpperBound
std::unique_ptr< sles_type::iter_base > slesUpperBound(uint256 const &key) const override
Definition: Ledger.cpp:463
ripple::loadLedgerHelper
std::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > loadLedgerHelper(std::string const &sqlSuffix, Application &app, bool acquire)
Definition: Ledger.cpp:1194
ripple::Application
Definition: Application.h:102
ripple::Ledger::sles_iter_impl::sles_iter_impl
sles_iter_impl(SHAMap::const_iterator iter)
Definition: Ledger.cpp:95
ripple::Ledger::slesBegin
std::unique_ptr< sles_type::iter_base > slesBegin() const override
Definition: Ledger.cpp:451
ripple::Application::getNodeFamily
virtual Family & getNodeFamily()=0
ripple::Ledger::addSLE
bool addSLE(SLE const &sle)
Definition: Ledger.cpp:372
ripple::isFlagLedger
bool isFlagLedger(LedgerIndex seq)
Returns true if the given ledgerIndex is a flag ledgerIndex.
Definition: Ledger.cpp:910
ripple::Ledger::rawReplace
void rawReplace(std::shared_ptr< SLE > const &sle) override
Unconditionally replace a state item.
Definition: Ledger.cpp:541
ripple::HashPrefix::ledgerMaster
@ ledgerMaster
ledger master data for signing
std::make_tuple
T make_tuple(T... args)
ripple::Ledger::txMap_
std::shared_ptr< SHAMap > txMap_
Definition: Ledger.h:402
ripple::loadByHashPostgres
static std::shared_ptr< Ledger > loadByHashPostgres(uint256 const &ledgerHash, Application &app)
Definition: Ledger.cpp:1489
ripple::Ledger::setImmutable
void setImmutable(Config const &config, bool rehash=true)
Definition: Ledger.cpp:336
ripple::makeSlice
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:240
ripple::sfReserveBase
const SF_UINT32 sfReserveBase
ripple::Keylet
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:38
ripple::Application::getAcceptedLedgerCache
virtual TaggedCache< uint256, AcceptedLedger > & getAcceptedLedgerCache()=0
ripple::Ledger::mImmutable
bool mImmutable
Definition: Ledger.h:400
ripple::Ledger::sles_iter_impl
Definition: Ledger.cpp:83
ripple::STLedgerEntry
Definition: STLedgerEntry.h:30
ripple::sfMetadata
const SField sfMetadata
ripple::Ledger::isVotingLedger
bool isVotingLedger() const
Returns true if the ledger directly precedes a flag ledger.
Definition: Ledger.cpp:904
ripple::Ledger::succ
std::optional< uint256 > succ(uint256 const &key, std::optional< uint256 > const &last=std::nullopt) const override
Definition: Ledger.cpp:421
ripple::Ledger::txRead
tx_type txRead(key_type const &key) const override
Read a transaction from the tx map.
Definition: Ledger.cpp:488
std::string
STL class.
std::shared_ptr
STL class.
ripple::LedgerInfo::parentHash
uint256 parentHash
Definition: ReadView.h:103
ripple::keylet::amendments
Keylet const & amendments() noexcept
The index of the amendment table.
Definition: Indexes.cpp:160
ripple::SHAMap::getHash
SHAMapHash getHash() const
Definition: SHAMap.cpp:783
ripple::loadByIndex
std::shared_ptr< Ledger > loadByIndex(std::uint32_t ledgerIndex, Application &app, bool acquire)
Definition: Ledger.cpp:1562
ripple::HashPrefix::txNode
@ txNode
transaction plus metadata
utility
ripple::Ledger::fees_
Fees fees_
Definition: Ledger.h:408
std::exception
STL class.
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:513
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
ripple::Ledger::unshare
void unshare() const
Definition: Ledger.cpp:1171
ripple::Ledger::slesEnd
std::unique_ptr< sles_type::iter_base > slesEnd() const override
Definition: Ledger.cpp:457
ripple::Serializer::modData
Blob & modData()
Definition: Serializer.h:178
ripple::ReadView::txs_type
Definition: ReadView.h:213
ripple::sfFirstLedgerSequence
const SF_UINT32 sfFirstLedgerSequence
ripple::SHAMapNodeType::tnACCOUNT_STATE
@ tnACCOUNT_STATE
std::unordered_set
STL class.
ripple::PendingSaves::pending
bool pending(LedgerIndex seq)
Return true if a ledger is in the progress of being saved.
Definition: PendingSaves.h:84
std::pair
ripple::SHAMapType::TRANSACTION
@ TRANSACTION
std::string::reserve
T reserve(T... args)
ripple::LedgerInfo::hash
uint256 hash
Definition: ReadView.h:100
ripple::XRPAmount::drops
constexpr value_type drops() const
Returns the number of drops.
Definition: XRPAmount.h:172
ripple::sfSequence
const SF_UINT32 sfSequence
ripple::addRaw
void addRaw(LedgerInfo const &info, Serializer &s, bool includeHash)
Definition: View.cpp:44
ripple::hotACCOUNT_NODE
@ hotACCOUNT_NODE
Definition: NodeObject.h:35
vector
std::vector::size
T size(T... args)
ripple::Ledger::sles_iter_impl::dereference
sles_type::value_type dereference() const override
Definition: Ledger.cpp:120
std::chrono::duration
ripple::keylet::skip
Keylet const & skip() noexcept
The index of the "short" skip list.
Definition: Indexes.cpp:142
ripple::getLatestLedger
std::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > getLatestLedger(Application &app)
Definition: Ledger.cpp:1462
ripple::FLAG_LEDGER_INTERVAL
constexpr std::uint32_t FLAG_LEDGER_INTERVAL
Definition: Ledger.h:416
ripple::STObject::getSerializer
Serializer getSerializer() const
Definition: STObject.h:367
std::unordered_set::emplace
T emplace(T... args)
ripple::Ledger::exists
bool exists(Keylet const &k) const override
Determine if a state item exists.
Definition: Ledger.cpp:408
std::stringstream
STL class.
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
ripple::Ledger::txs_iter_impl::equal
bool equal(base_type const &impl) const override
Definition: Ledger.cpp:155
ripple::STArray::push_back
void push_back(STObject const &object)
Definition: STArray.h:96
ripple::Ledger::peek
std::shared_ptr< SLE > peek(Keylet const &k) const
Definition: Ledger.cpp:644
ripple::Ledger::invariants
void invariants() const
Definition: Ledger.cpp:1178
ripple::roundCloseTime
std::chrono::time_point< Clock, Duration > roundCloseTime(std::chrono::time_point< Clock, Duration > closeTime, std::chrono::duration< Rep, Period > closeResolution)
Calculates the close time for a ledger, given a close time resolution.
Definition: LedgerTiming.h:129
std::tuple
std::monostate
ripple::Ledger::txs_iter_impl::operator=
txs_iter_impl & operator=(txs_iter_impl const &)=delete
ripple::Ledger::walkLedger
bool walkLedger(beast::Journal j) const
Definition: Ledger.cpp:763
ripple::STTx::getMetaSQLInsertReplaceHeader
static std::string const & getMetaSQLInsertReplaceHeader()
Definition: STTx.cpp:231
ripple::JobQueue::addJob
bool addJob(JobType type, std::string const &name, JobHandler &&jobHandler)
Adds a job to the JobQueue.
Definition: JobQueue.h:166
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::Ledger::rawTxInsert
void rawTxInsert(uint256 const &key, std::shared_ptr< Serializer const > const &txn, std::shared_ptr< Serializer const > const &metaData) override
Definition: Ledger.cpp:552
ripple::STObject::setFieldVL
void setFieldVL(SField const &field, Blob const &)
Definition: STObject.cpp:668
ripple::PendingSaves::startWork
bool startWork(LedgerIndex seq)
Start working on a ledger.
Definition: PendingSaves.h:51
ripple::Ledger::txs_iter_impl::txs_iter_impl
txs_iter_impl(bool metadata, SHAMap::const_iterator iter)
Definition: Ledger.cpp:143
ripple::Fees::reserve
XRPAmount reserve
Definition: ReadView.h:52
ripple::Ledger::rawErase
void rawErase(std::shared_ptr< SLE > const &sle) override
Delete an existing state item.
Definition: Ledger.cpp:516
ripple::SHAMapType::STATE
@ STATE
ripple::Ledger::updateNegativeUNL
void updateNegativeUNL()
update the Negative UNL ledger component.
Definition: Ledger.cpp:712
ripple::Family::missingNode
virtual void missingNode(std::uint32_t refNum)=0
ripple::LedgerInfo::txHash
uint256 txHash
Definition: ReadView.h:101
ripple::Ledger::info_
LedgerInfo info_
Definition: Ledger.h:410
ripple::finishLoadByIndexOrHash
static void finishLoadByIndexOrHash(std::shared_ptr< Ledger > const &ledger, Config const &config, beast::Journal j)
Definition: Ledger.cpp:1271
ripple::loadLedgerHelperPostgres
static std::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > loadLedgerHelperPostgres(std::variant< std::monostate, uint256, uint32_t > const &whichLedger, Application &app)
Definition: Ledger.cpp:1432
std::shared_ptr::reset
T reset(T... args)
ripple::deserializeTx
std::shared_ptr< STTx const > deserializeTx(SHAMapItem const &item)
Deserialize a SHAMapItem containing a single STTx.
Definition: Ledger.cpp:382
ripple::SHAMapHash
Definition: SHAMapTreeNode.h:48
ripple::generateKeyPair
std::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
Definition: SecretKey.cpp:351
ripple::Application::accountIDCache
virtual AccountIDCache const & accountIDCache() const =0
ripple::INITIAL_XRP
constexpr XRPAmount INITIAL_XRP
Configure the native currency.
Definition: SystemParameters.h:43
ripple::getHashByIndex
uint256 getHashByIndex(std::uint32_t ledgerIndex, Application &app)
Definition: Ledger.cpp:1599
ripple::SHAMapMissingNode
Definition: SHAMapMissingNode.h:55
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:526
ripple::detail::ReadViewFwdRange< std::shared_ptr< SLE const > >::value_type
std::shared_ptr< SLE const > value_type
Definition: ReadViewFwdRange.h:137
ripple::Ledger::validatorToDisable
std::optional< PublicKey > validatorToDisable() const
get the to be disabled validator's master public key if any
Definition: Ledger.cpp:682
ripple::Ledger::txsEnd
std::unique_ptr< txs_type::iter_base > txsEnd() const override
Definition: Ledger.cpp:476
ripple::Fees::increment
XRPAmount increment
Definition: ReadView.h:53
std::tie
T tie(T... args)
std::vector::push_back
T push_back(T... args)
ripple::digest
static Hasher::result_type digest(void const *data, std::size_t size) noexcept
Definition: tokens.cpp:47
ripple::LedgerInfo::closeTime
NetClock::time_point closeTime
Definition: ReadView.h:123
ripple::publicKeyType
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Definition: PublicKey.cpp:203
ripple::STLedgerEntry::key
uint256 const & key() const
Returns the 'key' (or 'index') of this item.
Definition: STLedgerEntry.h:86
ripple::Keylet::key
uint256 key
Definition: Keylet.h:41
ripple::base_uint< 256 >
ripple::loadByIndexPostgres
static std::shared_ptr< Ledger > loadByIndexPostgres(std::uint32_t ledgerIndex, Application &app)
Definition: Ledger.cpp:1475
ripple::jtPUBOLDLEDGER
@ jtPUBOLDLEDGER
Definition: Job.h:42
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::Config::reporting
bool reporting() const
Definition: Config.h:270
ripple::Ledger::txExists
bool txExists(uint256 const &key) const override
Definition: Ledger.cpp:482
ripple::saveValidatedLedger
static bool saveValidatedLedger(Application &app, std::shared_ptr< Ledger const > const &ledger, bool current)
Definition: Ledger.cpp:916
ripple::loadByHash
std::shared_ptr< Ledger > loadByHash(uint256 const &ledgerHash, Application &app, bool acquire)
Definition: Ledger.cpp:1579
ripple::DatabaseCon::checkoutDb
LockedSociSession checkoutDb()
Definition: DatabaseCon.h:178
ripple::base_uint::isZero
bool isZero() const
Definition: base_uint.h:508
std::log
T log(T... args)
ripple::Ledger::setAccepted
void setAccepted(NetClock::time_point closeTime, NetClock::duration closeResolution, bool correctCloseTime, Config const &config)
Definition: Ledger.cpp:356
ripple::Ledger
Holds a ledger.
Definition: Ledger.h:76
ripple::LedgerMaster::failedSave
void failedSave(std::uint32_t seq, uint256 const &hash)
Definition: LedgerMaster.cpp:968
ripple::Application::getLedgerMaster
virtual LedgerMaster & getLedgerMaster()=0
ripple::Ledger::setFull
void setFull() const
Definition: Ledger.h:292
ripple::PublicKey
A public key.
Definition: PublicKey.h:59
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:130
ripple::SHAMapItem
Definition: SHAMapItem.h:31
ripple::Config
Definition: Config.h:67
ripple::Application::pendingSaves
virtual PendingSaves & pendingSaves()=0
ripple::deserializeTxPlusMeta
std::pair< std::shared_ptr< STTx const >, std::shared_ptr< STObject const > > deserializeTxPlusMeta(SHAMapItem const &item)
Deserialize a SHAMapItem containing STTx + STObject metadata.
Definition: Ledger.cpp:389
ripple::calculateLedgerHash
uint256 calculateLedgerHash(LedgerInfo const &info)
Definition: Ledger.cpp:65
ripple::Config::TRANSACTION_FEE_BASE
static constexpr FeeUnit32 TRANSACTION_FEE_BASE
Definition: Config.h:138
ripple::Ledger::txs_iter_impl::copy
std::unique_ptr< base_type > copy() const override
Definition: Ledger.cpp:149
ripple::Rethrow
void Rethrow()
Rethrow the exception currently being handled.
Definition: contract.h:48
ripple::sfReserveIncrement
const SF_UINT32 sfReserveIncrement
ripple::JsonOptions::none
@ none
ripple::Application::config
virtual Config & config()=0
ripple::isCurrent
bool isCurrent(ValidationParms const &p, NetClock::time_point now, NetClock::time_point signTime, NetClock::time_point seenTime)
Whether a validation is still current.
Definition: Validations.h:146
ripple::Ledger::txs_iter_impl::iter_
SHAMap::const_iterator iter_
Definition: Ledger.cpp:134
ripple::Ledger::stateMap
SHAMap const & stateMap() const
Definition: Ledger.h:307
ripple::Config::FEE_OWNER_RESERVE
XRPAmount FEE_OWNER_RESERVE
Definition: Config.h:173
std::string::c_str
T c_str(T... args)
ripple::SHAMap::const_iterator
Definition: SHAMap.h:593
ripple::calcAccountID
AccountID calcAccountID(PublicKey const &pk)
Definition: AccountID.cpp:80
ripple::SHAMap
A SHAMap is both a radix tree with a fan-out of 16 and a Merkle tree.
Definition: SHAMap.h:95
ripple::STArray
Definition: STArray.h:28
ripple::Ledger::sles_iter_impl::iter_
SHAMap::const_iterator iter_
Definition: Ledger.cpp:86
ripple::create_genesis_t
Definition: Ledger.h:44
ripple::SHAMapNodeType::tnTRANSACTION_MD
@ tnTRANSACTION_MD
ripple::Ledger::isFlagLedger
bool isFlagLedger() const
Returns true if the ledger is a flag ledger.
Definition: Ledger.cpp:899
ripple::Ledger::sles_iter_impl::equal
bool equal(base_type const &impl) const override
Definition: Ledger.cpp:106
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::Ledger::sles_iter_impl::operator=
sles_iter_impl & operator=(sles_iter_impl const &)=delete
ripple::Application::getJobQueue
virtual JobQueue & getJobQueue()=0
ripple::sfValidatorToDisable
const SF_VL sfValidatorToDisable
ripple::Config::FEE_ACCOUNT_RESERVE
XRPAmount FEE_ACCOUNT_RESERVE
Definition: Config.h:172
ripple::Serializer::slice
Slice slice() const noexcept
Definition: Serializer.h:63
ripple::Ledger::rawInsert
void rawInsert(std::shared_ptr< SLE > const &sle) override
Unconditionally insert a state item.
Definition: Ledger.cpp:530
beast::Journal::info
Stream info() const
Definition: Journal.h:321
std::chrono::time_point
std::vector::erase
T erase(T... args)
ripple::Ledger::assertSensible
bool assertSensible(beast::Journal ledgerJ) const
Definition: Ledger.cpp:811
ripple::Family
Definition: Family.h:32
ripple::ValStatus::current
@ current
This was a new validation and was added.
ripple::Job
Definition: Job.h:84
ripple::loadLedgerInfosPostgres
static std::vector< LedgerInfo > loadLedgerInfosPostgres(std::variant< std::monostate, uint256, uint32_t, std::pair< uint32_t, uint32_t >> const &whichLedger, Application &app)
Definition: Ledger.cpp:1292
ripple::SerialIter
Definition: Serializer.h:310
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
ripple::Application::getLedgerDB
virtual DatabaseCon & getLedgerDB()=0
ripple::getHashByIndexPostgres
static uint256 getHashByIndexPostgres(std::uint32_t ledgerIndex, Application &app)
Definition: Ledger.cpp:1507
std::uint32_t
ripple::Ledger::sles_iter_impl::sles_iter_impl
sles_iter_impl()=delete
ripple::Ledger::txs_iter_impl::txs_iter_impl
txs_iter_impl()=delete
ripple::Ledger::isImmutable
bool isImmutable() const
Definition: Ledger.h:276
std::map
STL class.
ripple::SHAMapItem::slice
Slice slice() const
Definition: SHAMapItem.h:51
ripple::jtPUBLEDGER
@ jtPUBLEDGER
Definition: Job.h:56
ripple::Ledger::validatorToReEnable
std::optional< PublicKey > validatorToReEnable() const
get the to be re-enabled validator's master public key if any
Definition: Ledger.cpp:697
ripple::PendingSaves::shouldWork
bool shouldWork(LedgerIndex seq, bool isSynchronous)
Check if a ledger should be dispatched.
Definition: PendingSaves.h:99
std::string::append
T append(T... args)
ripple::LedgerInfo::drops
XRPAmount drops
Definition: ReadView.h:105
ripple::STArray::back
STObject & back()
Definition: STArray.h:77
ripple::KeyType::secp256k1
@ secp256k1
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:293
std::ostringstream
STL class.
ripple::Ledger::read
std::shared_ptr< SLE const > read(Keylet const &k) const override
Return the state item associated with a key.
Definition: Ledger.cpp:432
ripple::SHAMapTreeNode::makeFromPrefix
static std::shared_ptr< SHAMapTreeNode > makeFromPrefix(Slice rawNode, SHAMapHash const &hash)
Definition: SHAMapTreeNode.cpp:148
ripple::Ledger::txMap
SHAMap const & txMap() const
Definition: Ledger.h:319
ripple::sfBaseFee
const SF_UINT64 sfBaseFee
ripple::getCloseAgree
bool getCloseAgree(LedgerInfo const &info)
Definition: ReadView.h:418
ripple::sfHashes
const SF_VECTOR256 sfHashes
ripple::Config::FEE_DEFAULT
XRPAmount FEE_DEFAULT
Definition: Config.h:171
ripple::generateSeed
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
Definition: Seed.cpp:69
ripple::Ledger::txsBegin
std::unique_ptr< txs_type::iter_base > txsBegin() const override
Definition: Ledger.cpp:470
ripple::TransactionMaster::inLedger
bool inLedger(uint256 const &hash, std::uint32_t ledger)
Definition: TransactionMaster.cpp:40
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::ReadView::sles_type
Definition: ReadView.h:202
ripple::Config::features
std::unordered_set< uint256, beast::uhash<> > features
Definition: Config.h:219
ripple::Application::getNodeStore
virtual NodeStore::Database & getNodeStore()=0
ripple::Application::journal
virtual beast::Journal journal(std::string const &name)=0
ripple::Ledger::setup
bool setup(Config const &config)
Definition: Ledger.cpp:590
ripple::STArray::emplace_back
void emplace_back(Args &&... args)
Definition: STArray.h:90
ripple::ReadView::seq
LedgerIndex seq() const
Returns the sequence number of the base ledger.
Definition: ReadView.h:260
std::vector::begin
T begin(T... args)
std
STL namespace.
ripple::LogicError
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
Definition: contract.cpp:48
ripple::Fees::units
FeeUnit32 units
Definition: ReadView.h:51
ripple::LedgerInfo::closeTimeResolution
NetClock::duration closeTimeResolution
Definition: ReadView.h:117
ripple::sha512Half
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition: digest.h:216
ripple::create_genesis
const create_genesis_t create_genesis
Definition: Ledger.cpp:62
cassert
ripple::Ledger::stateMap_
std::shared_ptr< SHAMap > stateMap_
Definition: Ledger.h:403
ripple::sfDisabledValidator
const SField sfDisabledValidator
ripple::Ledger::updateSkipList
void updateSkipList()
Definition: Ledger.cpp:835
ripple::SerialIter::getVLDataLength
int getVLDataLength()
Definition: Serializer.cpp:470
ripple::Ledger::open
bool open() const override
Returns true if this reflects an open ledger.
Definition: Ledger.h:142
std::get_if
T get_if(T... args)
ripple::sfBalance
const SF_AMOUNT sfBalance
std::chrono::duration::count
T count(T... args)
ripple::sfReferenceFeeUnits
const SF_UINT32 sfReferenceFeeUnits
ripple::Ledger::txs_iter_impl::metadata_
bool metadata_
Definition: Ledger.cpp:133
ripple::STVector256
Definition: STVector256.h:29
std::visit
T visit(T... args)
ripple::Serializer::addVL
int addVL(Blob const &vector)
Definition: Serializer.cpp:200
ripple::Ledger::negativeUNL
hash_set< PublicKey > negativeUNL() const
get Negative UNL validators' master public keys
Definition: Ledger.cpp:656
std::vector::empty
T empty(T... args)
ripple::Rules
Rules controlling protocol behavior.
Definition: ReadView.h:131
ripple::SHAMapType
SHAMapType
Definition: SHAMapMissingNode.h:32
ripple::Ledger::txs_iter_impl
Definition: Ledger.cpp:130
std::optional
std::stringstream::str
T str(T... args)
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
ripple::JobType
JobType
Definition: Job.h:33
ripple::keylet::fees
Keylet const & fees() noexcept
The (fixed) index of the object containing the ledger fees.
Definition: Indexes.cpp:168
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:38
ripple::getHashesByIndex
bool getHashesByIndex(std::uint32_t ledgerIndex, uint256 &ledgerHash, uint256 &parentHash, Application &app)
Definition: Ledger.cpp:1631
ripple::ledgerGenesisTimeResolution
constexpr auto ledgerGenesisTimeResolution
Close time resolution in genesis ledger.
Definition: LedgerTiming.h:47
ripple::hotLEDGER
@ hotLEDGER
Definition: NodeObject.h:34
ripple::Keylet::check
bool check(STLedgerEntry const &) const
Returns true if the SLE matches the type.
Definition: Keylet.cpp:26
std::make_pair
T make_pair(T... args)
ripple::sfAccount
const SF_ACCOUNT sfAccount
ripple::Serializer::add32
int add32(std::uint32_t i)
Definition: Serializer.cpp:38
ripple::LedgerInfo
Information about the notional ledger backing the view.
Definition: ReadView.h:84
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:45
std::end
T end(T... args)
ripple::NetClock::duration
std::chrono::duration< rep, period > duration
Definition: chrono.h:55
ripple::getHashesByIndexPostgres
static bool getHashesByIndexPostgres(std::uint32_t ledgerIndex, uint256 &ledgerHash, uint256 &parentHash, Application &app)
Definition: Ledger.cpp:1523
ripple::SHAMapHash::as_uint256
uint256 const & as_uint256() const
Definition: SHAMapTreeNode.h:59
ripple::base_uint::parseHex
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:472
ripple::getNextLedgerTimeResolution
std::chrono::duration< Rep, Period > getNextLedgerTimeResolution(std::chrono::duration< Rep, Period > previousResolution, bool previousAgree, Seq ledgerSeq)
Calculates the close time resolution for the specified ledger.
Definition: LedgerTiming.h:80
ripple::Ledger::rawTxInsertWithHash
uint256 rawTxInsertWithHash(uint256 const &key, std::shared_ptr< Serializer const > const &txn, std::shared_ptr< Serializer const > const &metaData)
Definition: Ledger.cpp:570
ripple::sfLastLedgerSequence
const SF_UINT32 sfLastLedgerSequence
ripple::ledgerDefaultTimeResolution
constexpr auto ledgerDefaultTimeResolution
Initial resolution of ledger close time.
Definition: LedgerTiming.h:44
ripple::keylet::negativeUNL
Keylet const & negativeUNL() noexcept
The (fixed) index of the object containing the ledger negativeUNL.
Definition: Indexes.cpp:176
ripple::Ledger::txs_iter_impl::dereference
txs_type::value_type dereference() const override
Definition: Ledger.cpp:169
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:1121
ripple::LedgerInfo::validated
bool validated
Definition: ReadView.h:110
ripple::Ledger::Ledger
Ledger(Ledger const &)=delete
std::unique_ptr
STL class.
ripple::Ledger::digest
std::optional< digest_type > digest(key_type const &key) const override
Return the digest associated with the key.
Definition: Ledger.cpp:503
ripple::Ledger::txs_iter_impl::increment
void increment() override
Definition: Ledger.cpp:163
ripple::NetClock::time_point
std::chrono::time_point< NetClock > time_point
Definition: chrono.h:56
ripple::STObject::setFieldU32
void setFieldU32(SField const &field, std::uint32_t)
Definition: STObject.cpp:632
ripple::Ledger::sles_iter_impl::copy
std::unique_ptr< base_type > copy() const override
Definition: Ledger.cpp:100
ripple::sfDisabledValidators
const SField sfDisabledValidators
ripple::sfPublicKey
const SF_VL sfPublicKey
ripple::Application::getHashRouter
virtual HashRouter & getHashRouter()=0
ripple::Ledger::sles_iter_impl::increment
void increment() override
Definition: Ledger.cpp:114
ripple::HashRouter::setFlags
bool setFlags(uint256 const &key, int flags)
Set the flags on a hash.
Definition: HashRouter.cpp:102
ripple::LedgerInfo::accountHash
uint256 accountHash
Definition: ReadView.h:102
ripple::Ledger::rules_
Rules rules_
Definition: Ledger.h:409
ripple::Fees::base
XRPAmount base
Definition: ReadView.h:50
ripple::SerialIter::getSlice
Slice getSlice(std::size_t bytes)
Definition: Serializer.cpp:495
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::sfAmendments
const SF_VECTOR256 sfAmendments
ripple::sLCF_NoConsensusTime
static const std::uint32_t sLCF_NoConsensusTime
Definition: ReadView.h:415
ripple::Application::getTxnDB
virtual DatabaseCon & getTxnDB()=0
ripple::open
void open(soci::session &s, BasicConfig const &config, std::string const &dbName)
Open a soci session.
Definition: SociDB.cpp:100
std::variant
ripple::sfValidatorToReEnable
const SF_VL sfValidatorToReEnable
ripple::AccountIDCache::toBase58
std::string toBase58(AccountID const &) const
Return ripple::toBase58 for the AccountID.
Definition: AccountID.cpp:134
ripple::LedgerInfo::parentCloseTime
NetClock::time_point parentCloseTime
Definition: ReadView.h:93
ripple::flatFetchTransactions
std::vector< std::pair< std::shared_ptr< STTx const >, std::shared_ptr< STObject const > > > flatFetchTransactions(Application &app, std::vector< uint256 > &nodestoreHashes)
Definition: Ledger.cpp:1705
ripple::Application::getMasterTransaction
virtual TransactionMaster & getMasterTransaction()=0
std::chrono::system_clock::now
T now(T... args)