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  SHAMapItem item(sle.key(), sle.getSerializer());
375  return stateMap_->addItem(SHAMapNodeType::tnACCOUNT_STATE, std::move(item));
376 }
377 
378 //------------------------------------------------------------------------------
379 
382 {
383  SerialIter sit(item.slice());
384  return std::make_shared<STTx const>(sit);
385 }
386 
389 {
391  result;
392  SerialIter sit(item.slice());
393  {
394  SerialIter s(sit.getSlice(sit.getVLDataLength()));
395  result.first = std::make_shared<STTx const>(s);
396  }
397  {
398  SerialIter s(sit.getSlice(sit.getVLDataLength()));
399  result.second = std::make_shared<STObject const>(s, sfMetadata);
400  }
401  return result;
402 }
403 
404 //------------------------------------------------------------------------------
405 
406 bool
407 Ledger::exists(Keylet const& k) const
408 {
409  // VFALCO NOTE Perhaps check the type for debug builds?
410  return stateMap_->hasItem(k.key);
411 }
412 
413 bool
414 Ledger::exists(uint256 const& key) const
415 {
416  return stateMap_->hasItem(key);
417 }
418 
419 boost::optional<uint256>
420 Ledger::succ(uint256 const& key, boost::optional<uint256> const& last) const
421 {
422  auto item = stateMap_->upper_bound(key);
423  if (item == stateMap_->end())
424  return boost::none;
425  if (last && item->key() >= last)
426  return boost::none;
427  return item->key();
428 }
429 
431 Ledger::read(Keylet const& k) const
432 {
433  if (k.key == beast::zero)
434  {
435  assert(false);
436  return nullptr;
437  }
438  auto const& item = stateMap_->peekItem(k.key);
439  if (!item)
440  return nullptr;
441  auto sle = std::make_shared<SLE>(
442  SerialIter{item->data(), item->size()}, 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
503 Ledger::digest(key_type const& key) const -> boost::optional<digest_type>
504 {
506  // VFALCO Unfortunately this loads the item
507  // from the NodeStore needlessly.
508  if (!stateMap_->peekItem(key, digest))
509  return boost::none;
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(), std::move(ss))))
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(), std::move(ss))))
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, std::move(s))))
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, std::move(s));
582  auto hash = sha512Half(
583  HashPrefix::txNode, makeSlice(item->peekData()), item->key());
584  if (!txMap().addGiveItem(SHAMapNodeType::tnTRANSACTION_MD, std::move(item)))
585  LogicError("duplicate_tx: " + to_string(key));
586 
587  return hash;
588 }
589 
590 bool
591 Ledger::setup(Config const& config)
592 {
593  bool ret = true;
594 
595  fees_.base = config.FEE_DEFAULT;
599 
600  try
601  {
602  if (auto const sle = read(keylet::fees()))
603  {
604  // VFALCO NOTE Why getFieldIndex and not isFieldPresent?
605 
606  if (sle->getFieldIndex(sfBaseFee) != -1)
607  fees_.base = sle->getFieldU64(sfBaseFee);
608 
609  if (sle->getFieldIndex(sfReferenceFeeUnits) != -1)
610  fees_.units = sle->getFieldU32(sfReferenceFeeUnits);
611 
612  if (sle->getFieldIndex(sfReserveBase) != -1)
613  fees_.reserve = sle->getFieldU32(sfReserveBase);
614 
615  if (sle->getFieldIndex(sfReserveIncrement) != -1)
616  fees_.increment = sle->getFieldU32(sfReserveIncrement);
617  }
618  }
619  catch (SHAMapMissingNode const&)
620  {
621  ret = false;
622  }
623  catch (std::exception const&)
624  {
625  Rethrow();
626  }
627 
628  try
629  {
630  rules_ = Rules(*this, config.features);
631  }
632  catch (SHAMapMissingNode const&)
633  {
634  ret = false;
635  }
636  catch (std::exception const&)
637  {
638  Rethrow();
639  }
640 
641  return ret;
642 }
643 
645 Ledger::peek(Keylet const& k) const
646 {
647  auto const& value = stateMap_->peekItem(k.key);
648  if (!value)
649  return nullptr;
650  auto sle = std::make_shared<SLE>(
651  SerialIter{value->data(), value->size()}, value->key());
652  if (!k.check(*sle))
653  return nullptr;
654  return sle;
655 }
656 
659 {
660  hash_set<PublicKey> negUnl;
661  if (auto sle = read(keylet::negativeUNL());
662  sle && sle->isFieldPresent(sfDisabledValidators))
663  {
664  auto const& nUnlData = sle->getFieldArray(sfDisabledValidators);
665  for (auto const& n : nUnlData)
666  {
667  if (n.isFieldPresent(sfPublicKey))
668  {
669  auto d = n.getFieldVL(sfPublicKey);
670  auto s = makeSlice(d);
671  if (!publicKeyType(s))
672  {
673  continue;
674  }
675  negUnl.emplace(s);
676  }
677  }
678  }
679 
680  return negUnl;
681 }
682 
683 boost::optional<PublicKey>
685 {
686  if (auto sle = read(keylet::negativeUNL());
687  sle && sle->isFieldPresent(sfValidatorToDisable))
688  {
689  auto d = sle->getFieldVL(sfValidatorToDisable);
690  auto s = makeSlice(d);
691  if (publicKeyType(s))
692  return PublicKey(s);
693  }
694 
695  return boost::none;
696 }
697 
698 boost::optional<PublicKey>
700 {
701  if (auto sle = read(keylet::negativeUNL());
702  sle && sle->isFieldPresent(sfValidatorToReEnable))
703  {
704  auto d = sle->getFieldVL(sfValidatorToReEnable);
705  auto s = makeSlice(d);
706  if (publicKeyType(s))
707  return PublicKey(s);
708  }
709 
710  return boost::none;
711 }
712 
713 void
715 {
716  auto sle = peek(keylet::negativeUNL());
717  if (!sle)
718  return;
719 
720  bool const hasToDisable = sle->isFieldPresent(sfValidatorToDisable);
721  bool const hasToReEnable = sle->isFieldPresent(sfValidatorToReEnable);
722 
723  if (!hasToDisable && !hasToReEnable)
724  return;
725 
726  STArray newNUnl;
727  if (sle->isFieldPresent(sfDisabledValidators))
728  {
729  auto const& oldNUnl = sle->getFieldArray(sfDisabledValidators);
730  for (auto v : oldNUnl)
731  {
732  if (hasToReEnable && v.isFieldPresent(sfPublicKey) &&
733  v.getFieldVL(sfPublicKey) ==
734  sle->getFieldVL(sfValidatorToReEnable))
735  continue;
736  newNUnl.push_back(v);
737  }
738  }
739 
740  if (hasToDisable)
741  {
743  newNUnl.back().setFieldVL(
744  sfPublicKey, sle->getFieldVL(sfValidatorToDisable));
746  }
747 
748  if (!newNUnl.empty())
749  {
750  sle->setFieldArray(sfDisabledValidators, newNUnl);
751  if (hasToReEnable)
752  sle->makeFieldAbsent(sfValidatorToReEnable);
753  if (hasToDisable)
754  sle->makeFieldAbsent(sfValidatorToDisable);
755  rawReplace(sle);
756  }
757  else
758  {
759  rawErase(sle);
760  }
761 }
762 
763 //------------------------------------------------------------------------------
764 bool
766 {
767  std::vector<SHAMapMissingNode> missingNodes1;
768  std::vector<SHAMapMissingNode> missingNodes2;
769 
770  if (stateMap_->getHash().isZero() && !info_.accountHash.isZero() &&
771  !stateMap_->fetchRoot(SHAMapHash{info_.accountHash}, nullptr))
772  {
773  missingNodes1.emplace_back(
775  }
776  else
777  {
778  stateMap_->walkMap(missingNodes1, 32);
779  }
780 
781  if (!missingNodes1.empty())
782  {
783  if (auto stream = j.info())
784  {
785  stream << missingNodes1.size() << " missing account node(s)";
786  stream << "First: " << missingNodes1[0].what();
787  }
788  }
789 
790  if (txMap_->getHash().isZero() && info_.txHash.isNonZero() &&
791  !txMap_->fetchRoot(SHAMapHash{info_.txHash}, nullptr))
792  {
793  missingNodes2.emplace_back(
795  }
796  else
797  {
798  txMap_->walkMap(missingNodes2, 32);
799  }
800 
801  if (!missingNodes2.empty())
802  {
803  if (auto stream = j.info())
804  {
805  stream << missingNodes2.size() << " missing transaction node(s)";
806  stream << "First: " << missingNodes2[0].what();
807  }
808  }
809  return missingNodes1.empty() && missingNodes2.empty();
810 }
811 
812 bool
814 {
816  txMap_ && (info_.accountHash == stateMap_->getHash().as_uint256()) &&
817  (info_.txHash == txMap_->getHash().as_uint256()))
818  {
819  return true;
820  }
821 
822  Json::Value j = getJson({*this, {}});
823 
824  j[jss::accountTreeHash] = to_string(info_.accountHash);
825  j[jss::transTreeHash] = to_string(info_.txHash);
826 
827  JLOG(ledgerJ.fatal()) << "ledger is not sensible" << j;
828 
829  assert(false);
830 
831  return false;
832 }
833 
834 // update the skip list with the information from our previous ledger
835 // VFALCO TODO Document this skip list concept
836 void
838 {
839  if (info_.seq == 0) // genesis ledger has no previous ledger
840  return;
841 
842  std::uint32_t prevIndex = info_.seq - 1;
843 
844  // update record of every 256th ledger
845  if ((prevIndex & 0xff) == 0)
846  {
847  auto const k = keylet::skip(prevIndex);
848  auto sle = peek(k);
849  std::vector<uint256> hashes;
850 
851  bool created;
852  if (!sle)
853  {
854  sle = std::make_shared<SLE>(k);
855  created = true;
856  }
857  else
858  {
859  hashes = static_cast<decltype(hashes)>(sle->getFieldV256(sfHashes));
860  created = false;
861  }
862 
863  assert(hashes.size() <= 256);
864  hashes.push_back(info_.parentHash);
865  sle->setFieldV256(sfHashes, STVector256(hashes));
866  sle->setFieldU32(sfLastLedgerSequence, prevIndex);
867  if (created)
868  rawInsert(sle);
869  else
870  rawReplace(sle);
871  }
872 
873  // update record of past 256 ledger
874  auto const k = keylet::skip();
875  auto sle = peek(k);
876  std::vector<uint256> hashes;
877  bool created;
878  if (!sle)
879  {
880  sle = std::make_shared<SLE>(k);
881  created = true;
882  }
883  else
884  {
885  hashes = static_cast<decltype(hashes)>(sle->getFieldV256(sfHashes));
886  created = false;
887  }
888  assert(hashes.size() <= 256);
889  if (hashes.size() == 256)
890  hashes.erase(hashes.begin());
891  hashes.push_back(info_.parentHash);
892  sle->setFieldV256(sfHashes, STVector256(hashes));
893  sle->setFieldU32(sfLastLedgerSequence, prevIndex);
894  if (created)
895  rawInsert(sle);
896  else
897  rawReplace(sle);
898 }
899 
900 bool
902 {
903  return info_.seq % FLAG_LEDGER_INTERVAL == 0;
904 }
905 bool
907 {
908  return (info_.seq + 1) % FLAG_LEDGER_INTERVAL == 0;
909 }
910 
911 bool
913 {
914  return seq % FLAG_LEDGER_INTERVAL == 0;
915 }
916 
917 static bool
919  Application& app,
920  std::shared_ptr<Ledger const> const& ledger,
921  bool current)
922 {
923  auto j = app.journal("Ledger");
924  auto seq = ledger->info().seq;
925  if (!app.pendingSaves().startWork(seq))
926  {
927  // The save was completed synchronously
928  JLOG(j.debug()) << "Save aborted";
929  return true;
930  }
931 
932  // TODO(tom): Fix this hard-coded SQL!
933  JLOG(j.trace()) << "saveValidatedLedger " << (current ? "" : "fromAcquire ")
934  << seq;
935 
936  if (!ledger->info().accountHash.isNonZero())
937  {
938  JLOG(j.fatal()) << "AH is zero: " << getJson({*ledger, {}});
939  assert(false);
940  }
941 
942  if (ledger->info().accountHash != ledger->stateMap().getHash().as_uint256())
943  {
944  JLOG(j.fatal()) << "sAL: " << ledger->info().accountHash
945  << " != " << ledger->stateMap().getHash();
946  JLOG(j.fatal()) << "saveAcceptedLedger: seq=" << seq
947  << ", current=" << current;
948  assert(false);
949  }
950 
951  assert(ledger->info().txHash == ledger->txMap().getHash().as_uint256());
952 
953  // Save the ledger header in the hashed object store
954  {
955  Serializer s(128);
957  addRaw(ledger->info(), s);
958  app.getNodeStore().store(
959  hotLEDGER, std::move(s.modData()), ledger->info().hash, seq);
960  }
961 
962  AcceptedLedger::pointer aLedger;
963  try
964  {
965  aLedger = app.getAcceptedLedgerCache().fetch(ledger->info().hash);
966  if (!aLedger)
967  {
968  aLedger = std::make_shared<AcceptedLedger>(ledger, app);
969  app.getAcceptedLedgerCache().canonicalize_replace_client(
970  ledger->info().hash, aLedger);
971  }
972  }
973  catch (std::exception const&)
974  {
975  JLOG(j.warn()) << "An accepted ledger was missing nodes";
976  app.getLedgerMaster().failedSave(seq, ledger->info().hash);
977  // Clients can now trust the database for information about this
978  // ledger sequence.
979  app.pendingSaves().finishWork(seq);
980  return false;
981  }
982 
983  if (!app.config().reporting())
984  {
985  static boost::format deleteLedger(
986  "DELETE FROM Ledgers WHERE LedgerSeq = %u;");
987  static boost::format deleteTrans1(
988  "DELETE FROM Transactions WHERE LedgerSeq = %u;");
989  static boost::format deleteTrans2(
990  "DELETE FROM AccountTransactions WHERE LedgerSeq = %u;");
991  static boost::format deleteAcctTrans(
992  "DELETE FROM AccountTransactions WHERE TransID = '%s';");
993 
994  {
995  auto db = app.getLedgerDB().checkoutDb();
996  *db << boost::str(deleteLedger % seq);
997  }
998 
999  if (app.config().useTxTables())
1000  {
1001  auto db = app.getTxnDB().checkoutDb();
1002 
1003  soci::transaction tr(*db);
1004 
1005  *db << boost::str(deleteTrans1 % seq);
1006  *db << boost::str(deleteTrans2 % seq);
1007 
1008  std::string const ledgerSeq(std::to_string(seq));
1009 
1010  for (auto const& [_, acceptedLedgerTx] : aLedger->getMap())
1011  {
1012  (void)_;
1013  uint256 transactionID = acceptedLedgerTx->getTransactionID();
1014 
1015  std::string const txnId(to_string(transactionID));
1016  std::string const txnSeq(
1017  std::to_string(acceptedLedgerTx->getTxnSeq()));
1018 
1019  *db << boost::str(deleteAcctTrans % transactionID);
1020 
1021  auto const& accts = acceptedLedgerTx->getAffected();
1022 
1023  if (!accts.empty())
1024  {
1025  std::string sql(
1026  "INSERT INTO AccountTransactions "
1027  "(TransID, Account, LedgerSeq, TxnSeq) VALUES ");
1028 
1029  // Try to make an educated guess on how much space we'll
1030  // need for our arguments. In argument order we have: 64
1031  // + 34 + 10 + 10 = 118 + 10 extra = 128 bytes
1032  sql.reserve(sql.length() + (accts.size() * 128));
1033 
1034  bool first = true;
1035  for (auto const& account : accts)
1036  {
1037  if (!first)
1038  sql += ", ('";
1039  else
1040  {
1041  sql += "('";
1042  first = false;
1043  }
1044 
1045  sql += txnId;
1046  sql += "','";
1047  sql += app.accountIDCache().toBase58(account);
1048  sql += "',";
1049  sql += ledgerSeq;
1050  sql += ",";
1051  sql += txnSeq;
1052  sql += ")";
1053  }
1054  sql += ";";
1055  JLOG(j.trace()) << "ActTx: " << sql;
1056  *db << sql;
1057  }
1058  else
1059  {
1060  JLOG(j.warn()) << "Transaction in ledger " << seq
1061  << " affects no accounts";
1062  JLOG(j.warn()) << acceptedLedgerTx->getTxn()->getJson(
1064  }
1065 
1066  *db
1068  acceptedLedgerTx->getTxn()->getMetaSQL(
1069  seq, acceptedLedgerTx->getEscMeta()) +
1070  ";");
1071 
1073  }
1074 
1075  tr.commit();
1076  }
1077 
1078  {
1079  static std::string addLedger(
1080  R"sql(INSERT OR REPLACE INTO Ledgers
1081  (LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,
1082  CloseTimeRes,CloseFlags,AccountSetHash,TransSetHash)
1083  VALUES
1084  (:ledgerHash,:ledgerSeq,:prevHash,:totalCoins,:closingTime,:prevClosingTime,
1085  :closeTimeRes,:closeFlags,:accountSetHash,:transSetHash);)sql");
1086 
1087  auto db(app.getLedgerDB().checkoutDb());
1088 
1089  soci::transaction tr(*db);
1090 
1091  auto const hash = to_string(ledger->info().hash);
1092  auto const parentHash = to_string(ledger->info().parentHash);
1093  auto const drops = to_string(ledger->info().drops);
1094  auto const closeTime =
1095  ledger->info().closeTime.time_since_epoch().count();
1096  auto const parentCloseTime =
1097  ledger->info().parentCloseTime.time_since_epoch().count();
1098  auto const closeTimeResolution =
1099  ledger->info().closeTimeResolution.count();
1100  auto const closeFlags = ledger->info().closeFlags;
1101  auto const accountHash = to_string(ledger->info().accountHash);
1102  auto const txHash = to_string(ledger->info().txHash);
1103 
1104  *db << addLedger, soci::use(hash), soci::use(seq),
1105  soci::use(parentHash), soci::use(drops), soci::use(closeTime),
1106  soci::use(parentCloseTime), soci::use(closeTimeResolution),
1107  soci::use(closeFlags), soci::use(accountHash),
1108  soci::use(txHash);
1109 
1110  tr.commit();
1111  }
1112  }
1113  else
1114  {
1115  assert(false);
1116  }
1117 
1118  // Clients can now trust the database for
1119  // information about this ledger sequence.
1120  app.pendingSaves().finishWork(seq);
1121  return true;
1122 }
1127 bool
1129  Application& app,
1130  std::shared_ptr<Ledger const> const& ledger,
1131  bool isSynchronous,
1132  bool isCurrent)
1133 {
1134  if (!app.getHashRouter().setFlags(ledger->info().hash, SF_SAVED))
1135  {
1136  // We have tried to save this ledger recently
1137  auto stream = app.journal("Ledger").debug();
1138  JLOG(stream) << "Double pend save for " << ledger->info().seq;
1139 
1140  if (!isSynchronous || !app.pendingSaves().pending(ledger->info().seq))
1141  {
1142  // Either we don't need it to be finished
1143  // or it is finished
1144  return true;
1145  }
1146  }
1147 
1148  assert(ledger->isImmutable());
1149 
1150  if (!app.pendingSaves().shouldWork(ledger->info().seq, isSynchronous))
1151  {
1152  auto stream = app.journal("Ledger").debug();
1153  JLOG(stream) << "Pend save with seq in pending saves "
1154  << ledger->info().seq;
1155 
1156  return true;
1157  }
1158 
1159  JobType const jobType{isCurrent ? jtPUBLEDGER : jtPUBOLDLEDGER};
1160  char const* const jobName{
1161  isCurrent ? "Ledger::pendSave" : "Ledger::pendOldSave"};
1162 
1163  // See if we can use the JobQueue.
1164  if (!isSynchronous &&
1165  app.getJobQueue().addJob(
1166  jobType, jobName, [&app, ledger, isCurrent](Job&) {
1167  saveValidatedLedger(app, ledger, isCurrent);
1168  }))
1169  {
1170  return true;
1171  }
1172 
1173  // The JobQueue won't do the Job. Do the save synchronously.
1174  return saveValidatedLedger(app, ledger, isCurrent);
1175 }
1176 
1177 void
1178 Ledger::unshare() const
1179 {
1180  stateMap_->unshare();
1181  txMap_->unshare();
1182 }
1183 
1184 void
1185 Ledger::invariants() const
1186 {
1187  stateMap_->invariants();
1188  txMap_->invariants();
1189 }
1190 //------------------------------------------------------------------------------
1191 
1192 /*
1193  * Load a ledger from the database.
1194  *
1195  * @param sqlSuffix: Additional string to append to the sql query.
1196  * (typically a where clause).
1197  * @param acquire: Acquire the ledger if not found locally.
1198  * @return The ledger, ledger sequence, and ledger hash.
1199  */
1201 loadLedgerHelper(std::string const& sqlSuffix, Application& app, bool acquire)
1202 {
1203  uint256 ledgerHash{};
1204  std::uint32_t ledgerSeq{0};
1205 
1206  auto db = app.getLedgerDB().checkoutDb();
1207 
1208  boost::optional<std::string> sLedgerHash, sPrevHash, sAccountHash,
1209  sTransHash;
1210  boost::optional<std::uint64_t> totDrops, closingTime, prevClosingTime,
1211  closeResolution, closeFlags, ledgerSeq64;
1212 
1213  std::string const sql =
1214  "SELECT "
1215  "LedgerHash, PrevHash, AccountSetHash, TransSetHash, "
1216  "TotalCoins,"
1217  "ClosingTime, PrevClosingTime, CloseTimeRes, CloseFlags,"
1218  "LedgerSeq from Ledgers " +
1219  sqlSuffix + ";";
1220 
1221  *db << sql, soci::into(sLedgerHash), soci::into(sPrevHash),
1222  soci::into(sAccountHash), soci::into(sTransHash), soci::into(totDrops),
1223  soci::into(closingTime), soci::into(prevClosingTime),
1224  soci::into(closeResolution), soci::into(closeFlags),
1225  soci::into(ledgerSeq64);
1226 
1227  if (!db->got_data())
1228  {
1229  auto stream = app.journal("Ledger").debug();
1230  JLOG(stream) << "Ledger not found: " << sqlSuffix;
1231  return std::make_tuple(
1232  std::shared_ptr<Ledger>(), ledgerSeq, ledgerHash);
1233  }
1234 
1235  ledgerSeq = rangeCheckedCast<std::uint32_t>(ledgerSeq64.value_or(0));
1236 
1237  uint256 prevHash{}, accountHash{}, transHash{};
1238  if (sLedgerHash)
1239  (void)ledgerHash.parseHex(*sLedgerHash);
1240  if (sPrevHash)
1241  (void)prevHash.parseHex(*sPrevHash);
1242  if (sAccountHash)
1243  (void)accountHash.parseHex(*sAccountHash);
1244  if (sTransHash)
1245  (void)transHash.parseHex(*sTransHash);
1246 
1247  using time_point = NetClock::time_point;
1248  using duration = NetClock::duration;
1249 
1250  LedgerInfo info;
1251  info.parentHash = prevHash;
1252  info.txHash = transHash;
1253  info.accountHash = accountHash;
1254  info.drops = totDrops.value_or(0);
1255  info.closeTime = time_point{duration{closingTime.value_or(0)}};
1256  info.parentCloseTime = time_point{duration{prevClosingTime.value_or(0)}};
1257  info.closeFlags = closeFlags.value_or(0);
1258  info.closeTimeResolution = duration{closeResolution.value_or(0)};
1259  info.seq = ledgerSeq;
1260 
1261  bool loaded;
1262  auto ledger = std::make_shared<Ledger>(
1263  info,
1264  loaded,
1265  acquire,
1266  app.config(),
1267  app.getNodeFamily(),
1268  app.journal("Ledger"));
1269 
1270  if (!loaded)
1271  ledger.reset();
1273  return std::make_tuple(ledger, ledgerSeq, ledgerHash);
1274 }
1275 
1276 static void
1278  std::shared_ptr<Ledger> const& ledger,
1279  Config const& config,
1280  beast::Journal j)
1281 {
1282  if (!ledger)
1283  return;
1284 
1285  ledger->setImmutable(config);
1286 
1287  JLOG(j.trace()) << "Loaded ledger: " << to_string(ledger->info().hash);
1288 
1289  ledger->setFull();
1290 }
1291 
1292 // Load the ledger info for the specified ledger/s from the database
1293 // @param whichLedger specifies the ledger to load via ledger sequence, ledger
1294 // hash, a range of ledgers, or std::monostate (which loads the most recent)
1295 // @param app Application
1296 // @return vector of LedgerInfos
1299  std::variant<
1301  uint256,
1302  uint32_t,
1303  std::pair<uint32_t, uint32_t>> const& whichLedger,
1304  Application& app)
1305 {
1307 #ifdef RIPPLED_REPORTING
1308  auto log = app.journal("Ledger");
1309  assert(app.config().reporting());
1310  std::stringstream sql;
1311  sql << "SELECT ledger_hash, prev_hash, account_set_hash, trans_set_hash, "
1312  "total_coins, closing_time, prev_closing_time, close_time_res, "
1313  "close_flags, ledger_seq FROM ledgers ";
1314 
1315  uint32_t expNumResults = 1;
1316 
1317  if (auto ledgerSeq = std::get_if<uint32_t>(&whichLedger))
1318  {
1319  sql << "WHERE ledger_seq = " + std::to_string(*ledgerSeq);
1320  }
1321  else if (auto ledgerHash = std::get_if<uint256>(&whichLedger))
1322  {
1323  sql << ("WHERE ledger_hash = \'\\x" + strHex(*ledgerHash) + "\'");
1324  }
1325  else if (
1326  auto minAndMax =
1328  {
1329  expNumResults = minAndMax->second - minAndMax->first;
1330 
1331  sql
1332  << ("WHERE ledger_seq >= " + std::to_string(minAndMax->first) +
1333  " AND ledger_seq <= " + std::to_string(minAndMax->second));
1334  }
1335  else
1336  {
1337  sql << ("ORDER BY ledger_seq desc LIMIT 1");
1338  }
1339  sql << ";";
1340 
1341  JLOG(log.trace()) << __func__ << " : sql = " << sql.str();
1342 
1343  auto res = PgQuery(app.getPgPool())(sql.str().data());
1344  if (!res)
1345  {
1346  JLOG(log.error()) << __func__ << " : Postgres response is null - sql = "
1347  << sql.str();
1348  assert(false);
1349  return {};
1350  }
1351  else if (res.status() != PGRES_TUPLES_OK)
1352  {
1353  JLOG(log.error()) << __func__
1354  << " : Postgres response should have been "
1355  "PGRES_TUPLES_OK but instead was "
1356  << res.status() << " - msg = " << res.msg()
1357  << " - sql = " << sql.str();
1358  assert(false);
1359  return {};
1360  }
1361 
1362  JLOG(log.trace()) << __func__ << " Postgres result msg : " << res.msg();
1363 
1364  if (res.isNull() || res.ntuples() == 0)
1365  {
1366  JLOG(log.debug()) << __func__
1367  << " : Ledger not found. sql = " << sql.str();
1368  return {};
1369  }
1370  else if (res.ntuples() > 0)
1371  {
1372  if (res.nfields() != 10)
1373  {
1374  JLOG(log.error()) << __func__
1375  << " : Wrong number of fields in Postgres "
1376  "response. Expected 10, but got "
1377  << res.nfields() << " . sql = " << sql.str();
1378  assert(false);
1379  return {};
1380  }
1381  }
1382 
1383  for (size_t i = 0; i < res.ntuples(); ++i)
1384  {
1385  char const* hash = res.c_str(i, 0);
1386  char const* prevHash = res.c_str(i, 1);
1387  char const* accountHash = res.c_str(i, 2);
1388  char const* txHash = res.c_str(i, 3);
1389  std::int64_t totalCoins = res.asBigInt(i, 4);
1390  std::int64_t closeTime = res.asBigInt(i, 5);
1391  std::int64_t parentCloseTime = res.asBigInt(i, 6);
1392  std::int64_t closeTimeRes = res.asBigInt(i, 7);
1393  std::int64_t closeFlags = res.asBigInt(i, 8);
1394  std::int64_t ledgerSeq = res.asBigInt(i, 9);
1395 
1396  JLOG(log.trace()) << __func__ << " - Postgres response = " << hash
1397  << " , " << prevHash << " , " << accountHash << " , "
1398  << txHash << " , " << totalCoins << ", " << closeTime
1399  << ", " << parentCloseTime << ", " << closeTimeRes
1400  << ", " << closeFlags << ", " << ledgerSeq
1401  << " - sql = " << sql.str();
1402  JLOG(log.debug()) << __func__
1403  << " - Successfully fetched ledger with sequence = "
1404  << ledgerSeq << " from Postgres";
1405 
1406  using time_point = NetClock::time_point;
1407  using duration = NetClock::duration;
1408 
1409  LedgerInfo info;
1410  if (!info.parentHash.parseHex(prevHash + 2))
1411  assert(false);
1412  if (!info.txHash.parseHex(txHash + 2))
1413  assert(false);
1414  if (!info.accountHash.parseHex(accountHash + 2))
1415  assert(false);
1416  info.drops = totalCoins;
1417  info.closeTime = time_point{duration{closeTime}};
1418  info.parentCloseTime = time_point{duration{parentCloseTime}};
1419  info.closeFlags = closeFlags;
1420  info.closeTimeResolution = duration{closeTimeRes};
1421  info.seq = ledgerSeq;
1422  if (!info.hash.parseHex(hash + 2))
1423  assert(false);
1424  info.validated = true;
1425  infos.push_back(info);
1426  }
1427 
1428 #endif
1429  return infos;
1430 }
1431 
1432 // Load a ledger from Postgres
1433 // @param whichLedger specifies sequence or hash of ledger. Passing
1434 // std::monostate loads the most recent ledger
1435 // @param app the Application
1436 // @return tuple of (ledger, sequence, hash)
1440  Application& app)
1441 {
1443  std::visit(
1444  [&infos, &app](auto&& arg) {
1445  infos = loadLedgerInfosPostgres(arg, app);
1446  },
1447  whichLedger);
1448  assert(infos.size() <= 1);
1449  if (!infos.size())
1451  LedgerInfo info = infos[0];
1452  bool loaded;
1453  auto ledger = std::make_shared<Ledger>(
1454  info,
1455  loaded,
1456  false,
1457  app.config(),
1458  app.getNodeFamily(),
1459  app.journal("Ledger"));
1460 
1461  if (!loaded)
1462  ledger.reset();
1464  return std::make_tuple(ledger, info.seq, info.hash);
1465 }
1466 
1468 getLatestLedger(Application& app)
1469 {
1470  if (app.config().reporting())
1471  return loadLedgerHelperPostgres({}, app);
1472  else
1473  return loadLedgerHelper("order by LedgerSeq desc limit 1", app);
1474 }
1475 
1476 // Load a ledger by index (AKA sequence) from Postgres
1477 // @param ledgerIndex the ledger index (or sequence) to load
1478 // @param app reference to Application
1479 // @return the loaded ledger
1482 {
1483  std::shared_ptr<Ledger> ledger;
1484  std::tie(ledger, std::ignore, std::ignore) =
1485  loadLedgerHelperPostgres(uint32_t{ledgerIndex}, app);
1486  finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger"));
1487  return ledger;
1488 }
1489 
1490 // Load a ledger by hash from Postgres
1491 // @param hash hash of the ledger to load
1492 // @param app reference to Application
1493 // @return the loaded ledger
1495 loadByHashPostgres(uint256 const& ledgerHash, Application& app)
1496 {
1497  std::shared_ptr<Ledger> ledger;
1498  std::tie(ledger, std::ignore, std::ignore) =
1499  loadLedgerHelperPostgres(uint256{ledgerHash}, app);
1500 
1501  finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger"));
1502 
1503  assert(!ledger || ledger->info().hash == ledgerHash);
1504 
1505  return ledger;
1506 }
1507 
1508 // Given a ledger sequence, return the ledger hash
1509 // @param ledgerIndex ledger sequence
1510 // @param app Application
1511 // @return hash of ledger
1512 static uint256
1514 {
1515  uint256 ret;
1516 
1517  auto infos = loadLedgerInfosPostgres(ledgerIndex, app);
1518  assert(infos.size() <= 1);
1519  if (infos.size())
1520  return infos[0].hash;
1521  return {};
1522 }
1523 
1524 // Given a ledger sequence, return the ledger hash and the parent hash
1525 // @param ledgerIndex ledger sequence
1526 // @param[out] ledgerHash hash of ledger
1527 // @param[out] parentHash hash of parent ledger
1528 // @param app Application
1529 // @return true if the data was found
1530 static bool
1532  std::uint32_t ledgerIndex,
1533  uint256& ledgerHash,
1534  uint256& parentHash,
1535  Application& app)
1536 {
1537  auto infos = loadLedgerInfosPostgres(ledgerIndex, app);
1538  assert(infos.size() <= 1);
1539  if (infos.size())
1540  {
1541  ledgerHash = infos[0].hash;
1542  parentHash = infos[0].parentHash;
1543  return true;
1544  }
1545  return false;
1546 }
1547 
1548 // Given a contiguous range of sequences, return a map of
1549 // sequence -> (hash, parent hash)
1550 // @param minSeq lower bound of range
1551 // @param maxSeq upper bound of range
1552 // @param app Application
1553 // @return mapping of all found ledger sequences to their hash and parent hash
1556  std::uint32_t minSeq,
1557  std::uint32_t maxSeq,
1558  Application& app)
1559 {
1561  auto infos = loadLedgerInfosPostgres(std::make_pair(minSeq, maxSeq), app);
1562  for (auto& info : infos)
1563  {
1564  ret[info.seq] = std::make_pair(info.hash, info.parentHash);
1565  }
1566  return ret;
1567 }
1568 
1570 loadByIndex(std::uint32_t ledgerIndex, Application& app, bool acquire)
1571 {
1572  if (app.config().reporting())
1573  return loadByIndexPostgres(ledgerIndex, app);
1574  std::shared_ptr<Ledger> ledger;
1575  {
1577  s << "WHERE LedgerSeq = " << ledgerIndex;
1578  std::tie(ledger, std::ignore, std::ignore) =
1579  loadLedgerHelper(s.str(), app, acquire);
1580  }
1581 
1582  finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger"));
1583  return ledger;
1584 }
1585 
1587 loadByHash(uint256 const& ledgerHash, Application& app, bool acquire)
1588 {
1589  if (app.config().reporting())
1590  return loadByHashPostgres(ledgerHash, app);
1591  std::shared_ptr<Ledger> ledger;
1592  {
1594  s << "WHERE LedgerHash = '" << ledgerHash << "'";
1595  std::tie(ledger, std::ignore, std::ignore) =
1596  loadLedgerHelper(s.str(), app, acquire);
1597  }
1598 
1599  finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger"));
1600 
1601  assert(!ledger || ledger->info().hash == ledgerHash);
1603  return ledger;
1604 }
1605 
1606 uint256
1607 getHashByIndex(std::uint32_t ledgerIndex, Application& app)
1608 {
1609  if (app.config().reporting())
1610  return getHashByIndexPostgres(ledgerIndex, app);
1611  uint256 ret;
1612 
1613  std::string sql =
1614  "SELECT LedgerHash FROM Ledgers INDEXED BY SeqLedger WHERE LedgerSeq='";
1615  sql.append(std::to_string(ledgerIndex));
1616  sql.append("';");
1617 
1618  std::string hash;
1619  {
1620  auto db = app.getLedgerDB().checkoutDb();
1621 
1622  boost::optional<std::string> lh;
1623  *db << sql, soci::into(lh);
1624 
1625  if (!db->got_data() || !lh)
1626  return ret;
1627 
1628  hash = *lh;
1629  if (hash.empty())
1630  return ret;
1631  }
1632 
1633  (void)ret.parseHex(hash);
1634  return ret;
1635 }
1636 
1637 bool
1639  std::uint32_t ledgerIndex,
1640  uint256& ledgerHash,
1641  uint256& parentHash,
1642  Application& app)
1643 {
1644  if (app.config().reporting())
1645  return getHashesByIndexPostgres(
1646  ledgerIndex, ledgerHash, parentHash, app);
1647  auto db = app.getLedgerDB().checkoutDb();
1648 
1649  boost::optional<std::string> lhO, phO;
1650 
1651  *db << "SELECT LedgerHash,PrevHash FROM Ledgers "
1652  "INDEXED BY SeqLedger Where LedgerSeq = :ls;",
1653  soci::into(lhO), soci::into(phO), soci::use(ledgerIndex);
1654 
1655  if (!lhO || !phO)
1656  {
1657  auto stream = app.journal("Ledger").trace();
1658  JLOG(stream) << "Don't have ledger " << ledgerIndex;
1659  return false;
1660  }
1662  return ledgerHash.parseHex(*lhO) && parentHash.parseHex(*phO);
1663 }
1664 
1666 getHashesByIndex(std::uint32_t minSeq, std::uint32_t maxSeq, Application& app)
1667 {
1668  if (app.config().reporting())
1669  return getHashesByIndexPostgres(minSeq, maxSeq, app);
1671 
1672  std::string sql =
1673  "SELECT LedgerSeq,LedgerHash,PrevHash FROM Ledgers WHERE LedgerSeq >= ";
1674  sql.append(std::to_string(minSeq));
1675  sql.append(" AND LedgerSeq <= ");
1676  sql.append(std::to_string(maxSeq));
1677  sql.append(";");
1678 
1679  auto db = app.getLedgerDB().checkoutDb();
1680 
1681  std::uint64_t ls;
1682  std::string lh;
1683  boost::optional<std::string> ph;
1684  soci::statement st =
1685  (db->prepare << sql, soci::into(ls), soci::into(lh), soci::into(ph));
1686 
1687  st.execute();
1688  while (st.fetch())
1689  {
1690  std::pair<uint256, uint256>& hashes =
1691  ret[rangeCheckedCast<std::uint32_t>(ls)];
1692  (void)hashes.first.parseHex(lh);
1693  if (ph)
1694  (void)hashes.second.parseHex(*ph);
1695  else
1696  hashes.second.zero();
1697  if (!ph)
1698  {
1699  auto stream = app.journal("Ledger").warn();
1700  JLOG(stream) << "Null prev hash for ledger seq: " << ls;
1701  }
1702  }
1703 
1704  return ret;
1705 }
1706 
1707 std::vector<
1709 flatFetchTransactions(Application& app, std::vector<uint256>& nodestoreHashes)
1710 {
1711  if (!app.config().reporting())
1712  {
1713  assert(false);
1714  Throw<std::runtime_error>(
1715  "flatFetchTransactions: not running in reporting mode");
1716  }
1717 
1718  std::vector<
1720  txns;
1721  auto start = std::chrono::system_clock::now();
1722  auto nodeDb =
1723  dynamic_cast<NodeStore::DatabaseNodeImp*>(&(app.getNodeStore()));
1724  if (!nodeDb)
1725  {
1726  assert(false);
1727  Throw<std::runtime_error>(
1728  "Called flatFetchTransactions but database is not DatabaseNodeImp");
1729  }
1730  auto objs = nodeDb->fetchBatch(nodestoreHashes);
1731 
1733  JLOG(app.journal("Ledger").debug())
1734  << " Flat fetch time : " << ((end - start).count() / 1000000000.0)
1735  << " number of transactions " << nodestoreHashes.size();
1736  assert(objs.size() == nodestoreHashes.size());
1737  for (size_t i = 0; i < objs.size(); ++i)
1738  {
1739  uint256& nodestoreHash = nodestoreHashes[i];
1740  auto& obj = objs[i];
1741  if (obj)
1742  {
1743  auto node = SHAMapTreeNode::makeFromPrefix(
1744  makeSlice(obj->getData()), SHAMapHash{nodestoreHash});
1745  if (!node)
1746  {
1747  assert(false);
1748  Throw<std::runtime_error>(
1749  "flatFetchTransactions : Error making SHAMap node");
1750  }
1751  auto item = (static_cast<SHAMapLeafNode*>(node.get()))->peekItem();
1752  if (!item)
1753  {
1754  assert(false);
1755  Throw<std::runtime_error>(
1756  "flatFetchTransactions : Error reading SHAMap node");
1757  }
1758  auto txnPlusMeta = deserializeTxPlusMeta(*item);
1759  if (!txnPlusMeta.first || !txnPlusMeta.second)
1760  {
1761  assert(false);
1762  Throw<std::runtime_error>(
1763  "flatFetchTransactions : Error deserializing SHAMap node");
1764  }
1765  txns.push_back(std::move(txnPlusMeta));
1766  }
1767  else
1768  {
1769  assert(false);
1770  Throw<std::runtime_error>(
1771  "flatFetchTransactions : Containing SHAMap node not found");
1772  }
1773  }
1774  return txns;
1775 }
1776 std::vector<
1778 flatFetchTransactions(ReadView const& ledger, Application& app)
1779 {
1780  if (!app.config().reporting())
1781  {
1782  assert(false);
1783  return {};
1784  }
1785  std::vector<uint256> nodestoreHashes;
1786 #ifdef RIPPLED_REPORTING
1787 
1788  auto log = app.journal("Ledger");
1789 
1790  std::string query =
1791  "SELECT nodestore_hash"
1792  " FROM transactions "
1793  " WHERE ledger_seq = " +
1794  std::to_string(ledger.info().seq);
1795  auto res = PgQuery(app.getPgPool())(query.c_str());
1796 
1797  if (!res)
1798  {
1799  JLOG(log.error()) << __func__
1800  << " : Postgres response is null - query = " << query;
1801  assert(false);
1802  return {};
1803  }
1804  else if (res.status() != PGRES_TUPLES_OK)
1805  {
1806  JLOG(log.error()) << __func__
1807  << " : Postgres response should have been "
1808  "PGRES_TUPLES_OK but instead was "
1809  << res.status() << " - msg = " << res.msg()
1810  << " - query = " << query;
1811  assert(false);
1812  return {};
1813  }
1814 
1815  JLOG(log.trace()) << __func__ << " Postgres result msg : " << res.msg();
1816 
1817  if (res.isNull() || res.ntuples() == 0)
1818  {
1819  JLOG(log.debug()) << __func__
1820  << " : Ledger not found. query = " << query;
1821  return {};
1822  }
1823  else if (res.ntuples() > 0)
1824  {
1825  if (res.nfields() != 1)
1826  {
1827  JLOG(log.error()) << __func__
1828  << " : Wrong number of fields in Postgres "
1829  "response. Expected 1, but got "
1830  << res.nfields() << " . query = " << query;
1831  assert(false);
1832  return {};
1833  }
1834  }
1835 
1836  JLOG(log.trace()) << __func__ << " : result = " << res.c_str()
1837  << " : query = " << query;
1838  for (size_t i = 0; i < res.ntuples(); ++i)
1839  {
1840  char const* nodestoreHash = res.c_str(i, 0);
1841  uint256 hash;
1842  if (!hash.parseHex(nodestoreHash + 2))
1843  assert(false);
1844 
1845  nodestoreHashes.push_back(hash);
1846  }
1847 #endif
1848 
1849  return flatFetchTransactions(app, nodestoreHashes);
1850 }
1851 } // 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:1196
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:912
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:403
ripple::loadByHashPostgres
static std::shared_ptr< Ledger > loadByHashPostgres(uint256 const &ledgerHash, Application &app)
Definition: Ledger.cpp:1490
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:401
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:906
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:164
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:1565
ripple::HashPrefix::txNode
@ txNode
transaction plus metadata
utility
ripple::Ledger::fees_
Fees fees_
Definition: Ledger.h:409
std::exception
STL class.
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:444
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
ripple::Ledger::unshare
void unshare() const
Definition: Ledger.cpp:1173
ripple::publicKeyType
boost::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Definition: PublicKey.cpp:203
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:176
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:43
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:146
ripple::getLatestLedger
std::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > getLatestLedger(Application &app)
Definition: Ledger.cpp:1463
ripple::FLAG_LEDGER_INTERVAL
constexpr std::uint32_t FLAG_LEDGER_INTERVAL
Definition: Ledger.h:417
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:407
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:645
ripple::Ledger::invariants
void invariants() const
Definition: Ledger.cpp:1180
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:765
ripple::STTx::getMetaSQLInsertReplaceHeader
static std::string const & getMetaSQLInsertReplaceHeader()
Definition: STTx.cpp:232
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::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:45
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:714
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:411
ripple::finishLoadByIndexOrHash
static void finishLoadByIndexOrHash(std::shared_ptr< Ledger > const &ledger, Config const &config, beast::Journal j)
Definition: Ledger.cpp:1272
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:1433
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:381
ripple::SHAMapHash
Definition: SHAMapTreeNode.h:47
ripple::generateKeyPair
std::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
Definition: SecretKey.cpp:243
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:1602
ripple::SHAMapMissingNode
Definition: SHAMapMissingNode.h:55
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:457
ripple::detail::ReadViewFwdRange< std::shared_ptr< SLE const > >::value_type
std::shared_ptr< SLE const > value_type
Definition: ReadViewFwdRange.h:137
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::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:1476
ripple::jtPUBOLDLEDGER
@ jtPUBOLDLEDGER
Definition: Job.h:42
ripple::Ledger::info
LedgerInfo const & info() const override
Returns information about the ledger.
Definition: Ledger.h:149
std::chrono::time_point::time_since_epoch
T time_since_epoch(T... args)
ripple::Ledger::validatorToReEnable
boost::optional< PublicKey > validatorToReEnable() const
get the to be re-enabled validator's master public key if any
Definition: Ledger.cpp:699
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:918
ripple::loadByHash
std::shared_ptr< Ledger > loadByHash(uint256 const &ledgerHash, Application &app, bool acquire)
Definition: Ledger.cpp:1582
ripple::DatabaseCon::checkoutDb
LockedSociSession checkoutDb()
Definition: DatabaseCon.h:178
ripple::base_uint::isZero
bool isZero() const
Definition: base_uint.h:439
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:77
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:293
ripple::PublicKey
A public key.
Definition: PublicKey.h:59
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:134
ripple::SHAMapItem
Definition: SHAMapItem.h:35
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:388
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::Ledger::validatorToDisable
boost::optional< PublicKey > validatorToDisable() const
get the to be disabled validator's master public key if any
Definition: Ledger.cpp:684
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:145
ripple::Ledger::txs_iter_impl::iter_
SHAMap::const_iterator iter_
Definition: Ledger.cpp:134
ripple::Ledger::stateMap
SHAMap const & stateMap() const
Definition: Ledger.h:308
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:45
ripple::SHAMapNodeType::tnTRANSACTION_MD
@ tnTRANSACTION_MD
ripple::Ledger::isFlagLedger
bool isFlagLedger() const
Returns true if the ledger is a flag ledger.
Definition: Ledger.cpp:901
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::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:813
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:1293
ripple::SerialIter
Definition: Serializer.h:308
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:1508
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:277
std::map
STL class.
ripple::SHAMapItem::slice
Slice slice() const
Definition: SHAMapItem.h:64
ripple::jtPUBLEDGER
@ jtPUBLEDGER
Definition: Job.h:56
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:431
ripple::SHAMapTreeNode::makeFromPrefix
static std::shared_ptr< SHAMapTreeNode > makeFromPrefix(Slice rawNode, SHAMapHash const &hash)
Definition: SHAMapTreeNode.cpp:151
ripple::Ledger::txMap
SHAMap const & txMap() const
Definition: Ledger.h:320
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::base_uint::parseHex
bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:384
ripple::Ledger::setup
bool setup(Config const &config)
Definition: Ledger.cpp:591
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:404
ripple::sfDisabledValidator
const SField sfDisabledValidator
ripple::Ledger::updateSkipList
void updateSkipList()
Definition: Ledger.cpp:837
ripple::SerialIter::getVLDataLength
int getVLDataLength()
Definition: Serializer.cpp:462
ripple::Ledger::open
bool open() const override
Returns true if this reflects an open ledger.
Definition: Ledger.h:143
ripple::Ledger::succ
boost::optional< uint256 > succ(uint256 const &key, boost::optional< uint256 > const &last=boost::none) const override
Definition: Ledger.cpp:420
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:192
ripple::Ledger::negativeUNL
hash_set< PublicKey > negativeUNL() const
get Negative UNL validators' master public keys
Definition: Ledger.cpp:658
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::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:172
ripple::getHashesByIndex
bool getHashesByIndex(std::uint32_t ledgerIndex, uint256 &ledgerHash, uint256 &parentHash, Application &app)
Definition: Ledger.cpp:1633
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:53
ripple::getHashesByIndexPostgres
static bool getHashesByIndexPostgres(std::uint32_t ledgerIndex, uint256 &ledgerHash, uint256 &parentHash, Application &app)
Definition: Ledger.cpp:1526
ripple::SHAMapHash::as_uint256
uint256 const & as_uint256() const
Definition: SHAMapTreeNode.h:58
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:180
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:1123
ripple::LedgerInfo::validated
bool validated
Definition: ReadView.h:110
ripple::Ledger::Ledger
Ledger(Ledger const &)=delete
std::unique_ptr
STL class.
ripple::Ledger::digest
boost::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:54
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:410
ripple::Fees::base
XRPAmount base
Definition: ReadView.h:50
ripple::SerialIter::getSlice
Slice getSlice(std::size_t bytes)
Definition: Serializer.cpp:487
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:1704
ripple::Application::getMasterTransaction
virtual TransactionMaster & getMasterTransaction()=0
std::chrono::system_clock::now
T now(T... args)