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/basics/Log.h>
33 #include <ripple/basics/StringUtilities.h>
34 #include <ripple/basics/contract.h>
35 #include <ripple/beast/core/LexicalCast.h>
36 #include <ripple/consensus/LedgerTiming.h>
37 #include <ripple/core/Config.h>
38 #include <ripple/core/DatabaseCon.h>
39 #include <ripple/core/JobQueue.h>
40 #include <ripple/core/SociDB.h>
41 #include <ripple/json/to_string.h>
42 #include <ripple/nodestore/Database.h>
43 #include <ripple/protocol/Feature.h>
44 #include <ripple/protocol/HashPrefix.h>
45 #include <ripple/protocol/Indexes.h>
46 #include <ripple/protocol/PublicKey.h>
47 #include <ripple/protocol/SecretKey.h>
48 #include <ripple/protocol/UintTypes.h>
49 #include <ripple/protocol/digest.h>
50 #include <ripple/protocol/jss.h>
51 #include <boost/optional.hpp>
52 #include <cassert>
53 #include <utility>
54 
55 namespace ripple {
56 
58 
59 static uint256
61 {
62  // VFALCO This has to match addRaw in View.h.
63  return sha512Half(
65  std::uint32_t(info.seq),
66  std::uint64_t(info.drops.drops()),
67  info.parentHash,
68  info.txHash,
69  info.accountHash,
73  std::uint8_t(info.closeFlags));
74 }
75 
76 //------------------------------------------------------------------------------
77 
78 class Ledger::sles_iter_impl : public sles_type::iter_base
79 {
80 private:
82 
83 public:
84  sles_iter_impl() = delete;
86  operator=(sles_iter_impl const&) = delete;
87 
88  sles_iter_impl(sles_iter_impl const&) = default;
89 
91  {
92  }
93 
95  copy() const override
96  {
97  return std::make_unique<sles_iter_impl>(*this);
98  }
99 
100  bool
101  equal(base_type const& impl) const override
102  {
103  auto const& other = dynamic_cast<sles_iter_impl const&>(impl);
104  return iter_ == other.iter_;
105  }
106 
107  void
108  increment() override
109  {
110  ++iter_;
111  }
112 
114  dereference() const override
115  {
116  auto const item = *iter_;
117  SerialIter sit(item.slice());
118  return std::make_shared<SLE const>(sit, item.key());
119  }
120 };
121 
122 //------------------------------------------------------------------------------
123 
124 class Ledger::txs_iter_impl : public txs_type::iter_base
125 {
126 private:
127  bool metadata_;
129 
130 public:
131  txs_iter_impl() = delete;
133  operator=(txs_iter_impl const&) = delete;
134 
135  txs_iter_impl(txs_iter_impl const&) = default;
136 
138  : metadata_(metadata), iter_(iter)
139  {
140  }
141 
143  copy() const override
144  {
145  return std::make_unique<txs_iter_impl>(*this);
146  }
147 
148  bool
149  equal(base_type const& impl) const override
150  {
151  auto const& other = dynamic_cast<txs_iter_impl const&>(impl);
152  return iter_ == other.iter_;
153  }
154 
155  void
156  increment() override
157  {
158  ++iter_;
159  }
160 
162  dereference() const override
163  {
164  auto const item = *iter_;
165  if (metadata_)
166  return deserializeTxPlusMeta(item);
167  return {deserializeTx(item), nullptr};
168  }
169 };
170 
171 //------------------------------------------------------------------------------
172 
175  Config const& config,
176  std::vector<uint256> const& amendments,
177  Family& family)
178  : mImmutable(false)
179  , txMap_(std::make_shared<SHAMap>(SHAMapType::TRANSACTION, family))
180  , stateMap_(std::make_shared<SHAMap>(SHAMapType::STATE, family))
181  , rules_{config.features}
182 {
183  info_.seq = 1;
184  info_.drops = INITIAL_XRP;
185  info_.closeTimeResolution = ledgerDefaultTimeResolution;
186 
187  static auto const id = calcAccountID(
188  generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase"))
189  .first);
190  {
191  auto const sle = std::make_shared<SLE>(keylet::account(id));
192  sle->setFieldU32(sfSequence, 1);
193  sle->setAccountID(sfAccount, id);
194  sle->setFieldAmount(sfBalance, info_.drops);
195  rawInsert(sle);
196  }
197 
198  if (!amendments.empty())
199  {
200  auto const sle = std::make_shared<SLE>(keylet::amendments());
201  sle->setFieldV256(sfAmendments, STVector256{amendments});
202  rawInsert(sle);
203  }
204 
205  stateMap_->flushDirty(hotACCOUNT_NODE, info_.seq);
206  setImmutable(config);
207 }
208 
210  LedgerInfo const& info,
211  bool& loaded,
212  bool acquire,
213  Config const& config,
214  Family& family,
215  beast::Journal j)
216  : mImmutable(true)
217  , txMap_(std::make_shared<SHAMap>(
219  info.txHash,
220  family))
221  , stateMap_(
222  std::make_shared<SHAMap>(SHAMapType::STATE, info.accountHash, family))
223  , rules_(config.features)
224  , info_(info)
225 {
226  loaded = true;
227 
228  if (info_.txHash.isNonZero() &&
229  !txMap_->fetchRoot(SHAMapHash{info_.txHash}, nullptr))
230  {
231  loaded = false;
232  JLOG(j.warn()) << "Don't have transaction root for ledger" << info_.seq;
233  }
234 
235  if (info_.accountHash.isNonZero() &&
236  !stateMap_->fetchRoot(SHAMapHash{info_.accountHash}, nullptr))
237  {
238  loaded = false;
239  JLOG(j.warn()) << "Don't have state data root for ledger" << info_.seq;
240  }
241 
242  txMap_->setImmutable();
243  stateMap_->setImmutable();
244 
245  if (!setup(config))
246  loaded = false;
247 
248  if (!loaded)
249  {
251  if (acquire)
252  family.missingNode(info_.hash, info_.seq);
253  }
254 }
255 
256 // Create a new ledger that follows this one
257 Ledger::Ledger(Ledger const& prevLedger, NetClock::time_point closeTime)
258  : mImmutable(false)
259  , txMap_(std::make_shared<SHAMap>(
261  prevLedger.stateMap_->family()))
262  , stateMap_(prevLedger.stateMap_->snapShot(true))
263  , fees_(prevLedger.fees_)
264  , rules_(prevLedger.rules_)
265 {
266  info_.seq = prevLedger.info_.seq + 1;
267  info_.parentCloseTime = prevLedger.info_.closeTime;
268  info_.hash = prevLedger.info().hash + uint256(1);
269  info_.drops = prevLedger.info().drops;
271  info_.parentHash = prevLedger.info().hash;
273  prevLedger.info_.closeTimeResolution,
274  getCloseAgree(prevLedger.info()),
275  info_.seq);
276 
277  if (prevLedger.info_.closeTime == NetClock::time_point{})
278  {
280  }
281  else
282  {
283  info_.closeTime =
285  }
286 }
287 
288 Ledger::Ledger(LedgerInfo const& info, Config const& config, Family& family)
289  : mImmutable(true)
290  , txMap_(std::make_shared<SHAMap>(
292  info.txHash,
293  family))
294  , stateMap_(
295  std::make_shared<SHAMap>(SHAMapType::STATE, info.accountHash, family))
296  , rules_{config.features}
297  , info_(info)
298 {
299  info_.hash = calculateLedgerHash(info_);
300 }
301 
303  std::uint32_t ledgerSeq,
304  NetClock::time_point closeTime,
305  Config const& config,
306  Family& family)
307  : mImmutable(false)
308  , txMap_(std::make_shared<SHAMap>(SHAMapType::TRANSACTION, family))
309  , stateMap_(std::make_shared<SHAMap>(SHAMapType::STATE, family))
310  , rules_{config.features}
311 {
312  info_.seq = ledgerSeq;
313  info_.closeTime = closeTime;
314  info_.closeTimeResolution = ledgerDefaultTimeResolution;
315  setup(config);
316 }
317 
318 void
320 {
321  // Force update, since this is the only
322  // place the hash transitions to valid
323  if (!mImmutable)
324  {
325  info_.txHash = txMap_->getHash().as_uint256();
326  info_.accountHash = stateMap_->getHash().as_uint256();
327  }
328 
330 
331  mImmutable = true;
332  txMap_->setImmutable();
333  stateMap_->setImmutable();
334  setup(config);
335 }
336 
337 void
339  NetClock::time_point closeTime,
340  NetClock::duration closeResolution,
341  bool correctCloseTime,
342  Config const& config)
343 {
344  // Used when we witnessed the consensus.
345  assert(!open());
346 
347  info_.closeTime = closeTime;
348  info_.closeTimeResolution = closeResolution;
349  info_.closeFlags = correctCloseTime ? 0 : sLCF_NoConsensusTime;
350  setImmutable(config);
351 }
352 
353 bool
354 Ledger::addSLE(SLE const& sle)
355 {
356  SHAMapItem item(sle.key(), sle.getSerializer());
357  return stateMap_->addItem(std::move(item), false, false);
358 }
359 
360 //------------------------------------------------------------------------------
361 
364 {
365  SerialIter sit(item.slice());
366  return std::make_shared<STTx const>(sit);
367 }
368 
371 {
373  result;
374  SerialIter sit(item.slice());
375  {
376  SerialIter s(sit.getSlice(sit.getVLDataLength()));
377  result.first = std::make_shared<STTx const>(s);
378  }
379  {
380  SerialIter s(sit.getSlice(sit.getVLDataLength()));
381  result.second = std::make_shared<STObject const>(s, sfMetadata);
382  }
383  return result;
384 }
385 
386 //------------------------------------------------------------------------------
387 
388 bool
389 Ledger::exists(Keylet const& k) const
390 {
391  // VFALCO NOTE Perhaps check the type for debug builds?
392  return stateMap_->hasItem(k.key);
393 }
394 
395 boost::optional<uint256>
396 Ledger::succ(uint256 const& key, boost::optional<uint256> const& last) const
397 {
398  auto item = stateMap_->upper_bound(key);
399  if (item == stateMap_->end())
400  return boost::none;
401  if (last && item->key() >= last)
402  return boost::none;
403  return item->key();
404 }
405 
407 Ledger::read(Keylet const& k) const
408 {
409  if (k.key == beast::zero)
410  {
411  assert(false);
412  return nullptr;
413  }
414  auto const& item = stateMap_->peekItem(k.key);
415  if (!item)
416  return nullptr;
417  auto sle = std::make_shared<SLE>(
418  SerialIter{item->data(), item->size()}, item->key());
419  if (!k.check(*sle))
420  return nullptr;
421  return sle;
422 }
423 
424 //------------------------------------------------------------------------------
425 
426 auto
427 Ledger::slesBegin() const -> std::unique_ptr<sles_type::iter_base>
428 {
429  return std::make_unique<sles_iter_impl>(stateMap_->begin());
430 }
431 
432 auto
433 Ledger::slesEnd() const -> std::unique_ptr<sles_type::iter_base>
434 {
435  return std::make_unique<sles_iter_impl>(stateMap_->end());
436 }
437 
438 auto
441 {
442  return std::make_unique<sles_iter_impl>(stateMap_->upper_bound(key));
443 }
444 
445 auto
446 Ledger::txsBegin() const -> std::unique_ptr<txs_type::iter_base>
447 {
448  return std::make_unique<txs_iter_impl>(!open(), txMap_->begin());
449 }
450 
451 auto
452 Ledger::txsEnd() const -> std::unique_ptr<txs_type::iter_base>
453 {
454  return std::make_unique<txs_iter_impl>(!open(), txMap_->end());
455 }
456 
457 bool
458 Ledger::txExists(uint256 const& key) const
459 {
460  return txMap_->hasItem(key);
461 }
462 
463 auto
464 Ledger::txRead(key_type const& key) const -> tx_type
465 {
466  auto const& item = txMap_->peekItem(key);
467  if (!item)
468  return {};
469  if (!open())
470  {
471  auto result = deserializeTxPlusMeta(*item);
472  return {std::move(result.first), std::move(result.second)};
473  }
474  return {deserializeTx(*item), nullptr};
475 }
476 
477 auto
478 Ledger::digest(key_type const& key) const -> boost::optional<digest_type>
479 {
481  // VFALCO Unfortunately this loads the item
482  // from the NodeStore needlessly.
483  if (!stateMap_->peekItem(key, digest))
484  return boost::none;
485  return digest.as_uint256();
486 }
487 
488 //------------------------------------------------------------------------------
489 
490 void
492 {
493  if (!stateMap_->delItem(sle->key()))
494  LogicError("Ledger::rawErase: key not found");
495 }
496 
497 void
499 {
500  Serializer ss;
501  sle->add(ss);
502  auto item = std::make_shared<SHAMapItem const>(sle->key(), std::move(ss));
503  if (!stateMap_->addGiveItem(std::move(item), false, false))
504  LogicError("Ledger::rawInsert: key already exists");
505 }
506 
507 void
509 {
510  Serializer ss;
511  sle->add(ss);
512  auto item = std::make_shared<SHAMapItem const>(sle->key(), std::move(ss));
513 
514  if (!stateMap_->updateGiveItem(std::move(item), false, false))
515  LogicError("Ledger::rawReplace: key not found");
516 }
517 
518 void
520  uint256 const& key,
522  std::shared_ptr<Serializer const> const& metaData)
523 {
524  assert(metaData);
525 
526  // low-level - just add to table
527  Serializer s(txn->getDataLength() + metaData->getDataLength() + 16);
528  s.addVL(txn->peekData());
529  s.addVL(metaData->peekData());
530  auto item = std::make_shared<SHAMapItem const>(key, std::move(s));
531  if (!txMap().addGiveItem(std::move(item), true, true))
532  LogicError("duplicate_tx: " + to_string(key));
533 }
534 
535 bool
536 Ledger::setup(Config const& config)
537 {
538  bool ret = true;
539 
540  fees_.base = config.FEE_DEFAULT;
544 
545  try
546  {
547  if (auto const sle = read(keylet::fees()))
548  {
549  // VFALCO NOTE Why getFieldIndex and not isFieldPresent?
550 
551  if (sle->getFieldIndex(sfBaseFee) != -1)
552  fees_.base = sle->getFieldU64(sfBaseFee);
553 
554  if (sle->getFieldIndex(sfReferenceFeeUnits) != -1)
555  fees_.units = sle->getFieldU32(sfReferenceFeeUnits);
556 
557  if (sle->getFieldIndex(sfReserveBase) != -1)
558  fees_.reserve = sle->getFieldU32(sfReserveBase);
559 
560  if (sle->getFieldIndex(sfReserveIncrement) != -1)
561  fees_.increment = sle->getFieldU32(sfReserveIncrement);
562  }
563  }
564  catch (SHAMapMissingNode const&)
565  {
566  ret = false;
567  }
568  catch (std::exception const&)
569  {
570  Rethrow();
571  }
572 
573  try
574  {
575  rules_ = Rules(*this, config.features);
576  }
577  catch (SHAMapMissingNode const&)
578  {
579  ret = false;
580  }
581  catch (std::exception const&)
582  {
583  Rethrow();
584  }
585 
586  return ret;
587 }
588 
590 Ledger::peek(Keylet const& k) const
591 {
592  auto const& value = stateMap_->peekItem(k.key);
593  if (!value)
594  return nullptr;
595  auto sle = std::make_shared<SLE>(
596  SerialIter{value->data(), value->size()}, value->key());
597  if (!k.check(*sle))
598  return nullptr;
599  return sle;
600 }
601 
604 {
605  hash_set<PublicKey> negUnl;
606  if (auto sle = read(keylet::negativeUNL());
607  sle && sle->isFieldPresent(sfDisabledValidators))
608  {
609  auto const& nUnlData = sle->getFieldArray(sfDisabledValidators);
610  for (auto const& n : nUnlData)
611  {
612  if (n.isFieldPresent(sfPublicKey))
613  {
614  auto d = n.getFieldVL(sfPublicKey);
615  auto s = makeSlice(d);
616  if (!publicKeyType(s))
617  {
618  continue;
619  }
620  negUnl.emplace(s);
621  }
622  }
623  }
624 
625  return negUnl;
626 }
627 
628 boost::optional<PublicKey>
630 {
631  if (auto sle = read(keylet::negativeUNL());
632  sle && sle->isFieldPresent(sfValidatorToDisable))
633  {
634  auto d = sle->getFieldVL(sfValidatorToDisable);
635  auto s = makeSlice(d);
636  if (publicKeyType(s))
637  return PublicKey(s);
638  }
639 
640  return boost::none;
641 }
642 
643 boost::optional<PublicKey>
645 {
646  if (auto sle = read(keylet::negativeUNL());
647  sle && sle->isFieldPresent(sfValidatorToReEnable))
648  {
649  auto d = sle->getFieldVL(sfValidatorToReEnable);
650  auto s = makeSlice(d);
651  if (publicKeyType(s))
652  return PublicKey(s);
653  }
654 
655  return boost::none;
656 }
657 
658 void
660 {
661  auto sle = peek(keylet::negativeUNL());
662  if (!sle)
663  return;
664 
665  bool const hasToDisable = sle->isFieldPresent(sfValidatorToDisable);
666  bool const hasToReEnable = sle->isFieldPresent(sfValidatorToReEnable);
667 
668  if (!hasToDisable && !hasToReEnable)
669  return;
670 
671  STArray newNUnl;
672  if (sle->isFieldPresent(sfDisabledValidators))
673  {
674  auto const& oldNUnl = sle->getFieldArray(sfDisabledValidators);
675  for (auto v : oldNUnl)
676  {
677  if (hasToReEnable && v.isFieldPresent(sfPublicKey) &&
678  v.getFieldVL(sfPublicKey) ==
679  sle->getFieldVL(sfValidatorToReEnable))
680  continue;
681  newNUnl.push_back(v);
682  }
683  }
684 
685  if (hasToDisable)
686  {
688  newNUnl.back().setFieldVL(
689  sfPublicKey, sle->getFieldVL(sfValidatorToDisable));
691  }
692 
693  if (!newNUnl.empty())
694  {
695  sle->setFieldArray(sfDisabledValidators, newNUnl);
696  if (hasToReEnable)
697  sle->makeFieldAbsent(sfValidatorToReEnable);
698  if (hasToDisable)
699  sle->makeFieldAbsent(sfValidatorToDisable);
700  rawReplace(sle);
701  }
702  else
703  {
704  rawErase(sle);
705  }
706 }
707 
708 //------------------------------------------------------------------------------
709 bool
711 {
712  std::vector<SHAMapMissingNode> missingNodes1;
713  std::vector<SHAMapMissingNode> missingNodes2;
714 
715  if (stateMap_->getHash().isZero() && !info_.accountHash.isZero() &&
716  !stateMap_->fetchRoot(SHAMapHash{info_.accountHash}, nullptr))
717  {
718  missingNodes1.emplace_back(
720  }
721  else
722  {
723  stateMap_->walkMap(missingNodes1, 32);
724  }
725 
726  if (!missingNodes1.empty())
727  {
728  if (auto stream = j.info())
729  {
730  stream << missingNodes1.size() << " missing account node(s)";
731  stream << "First: " << missingNodes1[0].what();
732  }
733  }
734 
735  if (txMap_->getHash().isZero() && info_.txHash.isNonZero() &&
736  !txMap_->fetchRoot(SHAMapHash{info_.txHash}, nullptr))
737  {
738  missingNodes2.emplace_back(
740  }
741  else
742  {
743  txMap_->walkMap(missingNodes2, 32);
744  }
745 
746  if (!missingNodes2.empty())
747  {
748  if (auto stream = j.info())
749  {
750  stream << missingNodes2.size() << " missing transaction node(s)";
751  stream << "First: " << missingNodes2[0].what();
752  }
753  }
754  return missingNodes1.empty() && missingNodes2.empty();
755 }
756 
757 bool
759 {
761  txMap_ && (info_.accountHash == stateMap_->getHash().as_uint256()) &&
762  (info_.txHash == txMap_->getHash().as_uint256()))
763  {
764  return true;
765  }
766 
767  Json::Value j = getJson(*this);
768 
769  j[jss::accountTreeHash] = to_string(info_.accountHash);
770  j[jss::transTreeHash] = to_string(info_.txHash);
771 
772  JLOG(ledgerJ.fatal()) << "ledger is not sane" << j;
773 
774  assert(false);
775 
776  return false;
777 }
778 
779 // update the skip list with the information from our previous ledger
780 // VFALCO TODO Document this skip list concept
781 void
783 {
784  if (info_.seq == 0) // genesis ledger has no previous ledger
785  return;
786 
787  std::uint32_t prevIndex = info_.seq - 1;
788 
789  // update record of every 256th ledger
790  if ((prevIndex & 0xff) == 0)
791  {
792  auto const k = keylet::skip(prevIndex);
793  auto sle = peek(k);
794  std::vector<uint256> hashes;
795 
796  bool created;
797  if (!sle)
798  {
799  sle = std::make_shared<SLE>(k);
800  created = true;
801  }
802  else
803  {
804  hashes = static_cast<decltype(hashes)>(sle->getFieldV256(sfHashes));
805  created = false;
806  }
807 
808  assert(hashes.size() <= 256);
809  hashes.push_back(info_.parentHash);
810  sle->setFieldV256(sfHashes, STVector256(hashes));
811  sle->setFieldU32(sfLastLedgerSequence, prevIndex);
812  if (created)
813  rawInsert(sle);
814  else
815  rawReplace(sle);
816  }
817 
818  // update record of past 256 ledger
819  auto const k = keylet::skip();
820  auto sle = peek(k);
821  std::vector<uint256> hashes;
822  bool created;
823  if (!sle)
824  {
825  sle = std::make_shared<SLE>(k);
826  created = true;
827  }
828  else
829  {
830  hashes = static_cast<decltype(hashes)>(sle->getFieldV256(sfHashes));
831  created = false;
832  }
833  assert(hashes.size() <= 256);
834  if (hashes.size() == 256)
835  hashes.erase(hashes.begin());
836  hashes.push_back(info_.parentHash);
837  sle->setFieldV256(sfHashes, STVector256(hashes));
838  sle->setFieldU32(sfLastLedgerSequence, prevIndex);
839  if (created)
840  rawInsert(sle);
841  else
842  rawReplace(sle);
843 }
844 
845 bool
847 {
848  return info_.seq % FLAG_LEDGER_INTERVAL == 0;
849 }
850 bool
852 {
853  return (info_.seq + 1) % FLAG_LEDGER_INTERVAL == 0;
854 }
855 
856 bool
858 {
859  return seq % FLAG_LEDGER_INTERVAL == 0;
860 }
861 
862 static bool
864  Application& app,
865  std::shared_ptr<Ledger const> const& ledger,
866  bool current)
867 {
868  auto j = app.journal("Ledger");
869  auto seq = ledger->info().seq;
870  if (!app.pendingSaves().startWork(seq))
871  {
872  // The save was completed synchronously
873  JLOG(j.debug()) << "Save aborted";
874  return true;
875  }
876 
877  // TODO(tom): Fix this hard-coded SQL!
878  JLOG(j.trace()) << "saveValidatedLedger " << (current ? "" : "fromAcquire ")
879  << seq;
880  static boost::format deleteLedger(
881  "DELETE FROM Ledgers WHERE LedgerSeq = %u;");
882  static boost::format deleteTrans1(
883  "DELETE FROM Transactions WHERE LedgerSeq = %u;");
884  static boost::format deleteTrans2(
885  "DELETE FROM AccountTransactions WHERE LedgerSeq = %u;");
886  static boost::format deleteAcctTrans(
887  "DELETE FROM AccountTransactions WHERE TransID = '%s';");
888 
889  if (!ledger->info().accountHash.isNonZero())
890  {
891  JLOG(j.fatal()) << "AH is zero: " << getJson(*ledger);
892  assert(false);
893  }
894 
895  if (ledger->info().accountHash != ledger->stateMap().getHash().as_uint256())
896  {
897  JLOG(j.fatal()) << "sAL: " << ledger->info().accountHash
898  << " != " << ledger->stateMap().getHash();
899  JLOG(j.fatal()) << "saveAcceptedLedger: seq=" << seq
900  << ", current=" << current;
901  assert(false);
902  }
903 
904  assert(ledger->info().txHash == ledger->txMap().getHash().as_uint256());
905 
906  // Save the ledger header in the hashed object store
907  {
908  Serializer s(128);
910  addRaw(ledger->info(), s);
911  app.getNodeStore().store(
912  hotLEDGER, std::move(s.modData()), ledger->info().hash, seq);
913  }
914 
915  AcceptedLedger::pointer aLedger;
916  try
917  {
918  aLedger = app.getAcceptedLedgerCache().fetch(ledger->info().hash);
919  if (!aLedger)
920  {
921  aLedger = std::make_shared<AcceptedLedger>(
922  ledger, app.accountIDCache(), app.logs());
923  app.getAcceptedLedgerCache().canonicalize_replace_client(
924  ledger->info().hash, aLedger);
925  }
926  }
927  catch (std::exception const&)
928  {
929  JLOG(j.warn()) << "An accepted ledger was missing nodes";
930  app.getLedgerMaster().failedSave(seq, ledger->info().hash);
931  // Clients can now trust the database for information about this
932  // ledger sequence.
933  app.pendingSaves().finishWork(seq);
934  return false;
935  }
936 
937  {
938  auto db = app.getLedgerDB().checkoutDb();
939  *db << boost::str(deleteLedger % seq);
940  }
941 
942  {
943  auto db = app.getTxnDB().checkoutDb();
944 
945  soci::transaction tr(*db);
946 
947  *db << boost::str(deleteTrans1 % seq);
948  *db << boost::str(deleteTrans2 % seq);
949 
950  std::string const ledgerSeq(std::to_string(seq));
951 
952  for (auto const& [_, acceptedLedgerTx] : aLedger->getMap())
953  {
954  (void)_;
955  uint256 transactionID = acceptedLedgerTx->getTransactionID();
956 
958 
959  std::string const txnId(to_string(transactionID));
960  std::string const txnSeq(
961  std::to_string(acceptedLedgerTx->getTxnSeq()));
962 
963  *db << boost::str(deleteAcctTrans % transactionID);
964 
965  auto const& accts = acceptedLedgerTx->getAffected();
966 
967  if (!accts.empty())
968  {
969  std::string sql(
970  "INSERT INTO AccountTransactions "
971  "(TransID, Account, LedgerSeq, TxnSeq) VALUES ");
972 
973  // Try to make an educated guess on how much space we'll need
974  // for our arguments. In argument order we have:
975  // 64 + 34 + 10 + 10 = 118 + 10 extra = 128 bytes
976  sql.reserve(sql.length() + (accts.size() * 128));
977 
978  bool first = true;
979  for (auto const& account : accts)
980  {
981  if (!first)
982  sql += ", ('";
983  else
984  {
985  sql += "('";
986  first = false;
987  }
988 
989  sql += txnId;
990  sql += "','";
991  sql += app.accountIDCache().toBase58(account);
992  sql += "',";
993  sql += ledgerSeq;
994  sql += ",";
995  sql += txnSeq;
996  sql += ")";
997  }
998  sql += ";";
999  JLOG(j.trace()) << "ActTx: " << sql;
1000  *db << sql;
1001  }
1002  else
1003  {
1004  JLOG(j.warn()) << "Transaction in ledger " << seq
1005  << " affects no accounts";
1006  JLOG(j.warn())
1007  << acceptedLedgerTx->getTxn()->getJson(JsonOptions::none);
1008  }
1009 
1010  *db
1012  acceptedLedgerTx->getTxn()->getMetaSQL(
1013  seq, acceptedLedgerTx->getEscMeta()) +
1014  ";");
1015  }
1016 
1017  tr.commit();
1018  }
1019 
1020  {
1021  static std::string addLedger(
1022  R"sql(INSERT OR REPLACE INTO Ledgers
1023  (LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,
1024  CloseTimeRes,CloseFlags,AccountSetHash,TransSetHash)
1025  VALUES
1026  (:ledgerHash,:ledgerSeq,:prevHash,:totalCoins,:closingTime,:prevClosingTime,
1027  :closeTimeRes,:closeFlags,:accountSetHash,:transSetHash);)sql");
1028 
1029  auto db(app.getLedgerDB().checkoutDb());
1030 
1031  soci::transaction tr(*db);
1032 
1033  auto const hash = to_string(ledger->info().hash);
1034  auto const parentHash = to_string(ledger->info().parentHash);
1035  auto const drops = to_string(ledger->info().drops);
1036  auto const closeTime =
1037  ledger->info().closeTime.time_since_epoch().count();
1038  auto const parentCloseTime =
1039  ledger->info().parentCloseTime.time_since_epoch().count();
1040  auto const closeTimeResolution =
1041  ledger->info().closeTimeResolution.count();
1042  auto const closeFlags = ledger->info().closeFlags;
1043  auto const accountHash = to_string(ledger->info().accountHash);
1044  auto const txHash = to_string(ledger->info().txHash);
1045 
1046  *db << addLedger, soci::use(hash), soci::use(seq),
1047  soci::use(parentHash), soci::use(drops), soci::use(closeTime),
1048  soci::use(parentCloseTime), soci::use(closeTimeResolution),
1049  soci::use(closeFlags), soci::use(accountHash), soci::use(txHash);
1050 
1051  tr.commit();
1052  }
1053 
1054  // Clients can now trust the database for
1055  // information about this ledger sequence.
1056  app.pendingSaves().finishWork(seq);
1057  return true;
1058 }
1063 bool
1065  Application& app,
1066  std::shared_ptr<Ledger const> const& ledger,
1067  bool isSynchronous,
1068  bool isCurrent)
1069 {
1070  if (!app.getHashRouter().setFlags(ledger->info().hash, SF_SAVED))
1071  {
1072  // We have tried to save this ledger recently
1073  auto stream = app.journal("Ledger").debug();
1074  JLOG(stream) << "Double pend save for " << ledger->info().seq;
1075 
1076  if (!isSynchronous || !app.pendingSaves().pending(ledger->info().seq))
1077  {
1078  // Either we don't need it to be finished
1079  // or it is finished
1080  return true;
1081  }
1082  }
1083 
1084  assert(ledger->isImmutable());
1085 
1086  if (!app.pendingSaves().shouldWork(ledger->info().seq, isSynchronous))
1087  {
1088  auto stream = app.journal("Ledger").debug();
1089  JLOG(stream) << "Pend save with seq in pending saves "
1090  << ledger->info().seq;
1091 
1092  return true;
1093  }
1094 
1095  JobType const jobType{isCurrent ? jtPUBLEDGER : jtPUBOLDLEDGER};
1096  char const* const jobName{
1097  isCurrent ? "Ledger::pendSave" : "Ledger::pendOldSave"};
1098 
1099  // See if we can use the JobQueue.
1100  if (!isSynchronous &&
1101  app.getJobQueue().addJob(
1102  jobType, jobName, [&app, ledger, isCurrent](Job&) {
1103  saveValidatedLedger(app, ledger, isCurrent);
1104  }))
1105  {
1106  return true;
1107  }
1108 
1109  // The JobQueue won't do the Job. Do the save synchronously.
1110  return saveValidatedLedger(app, ledger, isCurrent);
1111 }
1112 
1113 void
1114 Ledger::unshare() const
1115 {
1116  stateMap_->unshare();
1117  txMap_->unshare();
1118 }
1119 
1120 void
1121 Ledger::invariants() const
1122 {
1123  stateMap_->invariants();
1124  txMap_->invariants();
1125 }
1126 
1127 //------------------------------------------------------------------------------
1128 
1129 /*
1130  * Load a ledger from the database.
1131  *
1132  * @param sqlSuffix: Additional string to append to the sql query.
1133  * (typically a where clause).
1134  * @param acquire: Acquire the ledger if not found locally.
1135  * @return The ledger, ledger sequence, and ledger hash.
1136  */
1138 loadLedgerHelper(std::string const& sqlSuffix, Application& app, bool acquire)
1139 {
1140  uint256 ledgerHash{};
1141  std::uint32_t ledgerSeq{0};
1142 
1143  auto db = app.getLedgerDB().checkoutDb();
1144 
1145  boost::optional<std::string> sLedgerHash, sPrevHash, sAccountHash,
1146  sTransHash;
1147  boost::optional<std::uint64_t> totDrops, closingTime, prevClosingTime,
1148  closeResolution, closeFlags, ledgerSeq64;
1149 
1150  std::string const sql =
1151  "SELECT "
1152  "LedgerHash, PrevHash, AccountSetHash, TransSetHash, "
1153  "TotalCoins,"
1154  "ClosingTime, PrevClosingTime, CloseTimeRes, CloseFlags,"
1155  "LedgerSeq from Ledgers " +
1156  sqlSuffix + ";";
1157 
1158  *db << sql, soci::into(sLedgerHash), soci::into(sPrevHash),
1159  soci::into(sAccountHash), soci::into(sTransHash), soci::into(totDrops),
1160  soci::into(closingTime), soci::into(prevClosingTime),
1161  soci::into(closeResolution), soci::into(closeFlags),
1162  soci::into(ledgerSeq64);
1163 
1164  if (!db->got_data())
1165  {
1166  auto stream = app.journal("Ledger").debug();
1167  JLOG(stream) << "Ledger not found: " << sqlSuffix;
1168  return std::make_tuple(
1169  std::shared_ptr<Ledger>(), ledgerSeq, ledgerHash);
1170  }
1171 
1172  ledgerSeq = rangeCheckedCast<std::uint32_t>(ledgerSeq64.value_or(0));
1173 
1174  uint256 prevHash{}, accountHash{}, transHash{};
1175  if (sLedgerHash)
1176  ledgerHash.SetHexExact(*sLedgerHash);
1177  if (sPrevHash)
1178  prevHash.SetHexExact(*sPrevHash);
1179  if (sAccountHash)
1180  accountHash.SetHexExact(*sAccountHash);
1181  if (sTransHash)
1182  transHash.SetHexExact(*sTransHash);
1183 
1184  using time_point = NetClock::time_point;
1185  using duration = NetClock::duration;
1186 
1187  LedgerInfo info;
1188  info.parentHash = prevHash;
1189  info.txHash = transHash;
1190  info.accountHash = accountHash;
1191  info.drops = totDrops.value_or(0);
1192  info.closeTime = time_point{duration{closingTime.value_or(0)}};
1193  info.parentCloseTime = time_point{duration{prevClosingTime.value_or(0)}};
1194  info.closeFlags = closeFlags.value_or(0);
1195  info.closeTimeResolution = duration{closeResolution.value_or(0)};
1196  info.seq = ledgerSeq;
1197 
1198  bool loaded;
1199  auto ledger = std::make_shared<Ledger>(
1200  info,
1201  loaded,
1202  acquire,
1203  app.config(),
1204  app.getNodeFamily(),
1205  app.journal("Ledger"));
1206 
1207  if (!loaded)
1208  ledger.reset();
1210  return std::make_tuple(ledger, ledgerSeq, ledgerHash);
1211 }
1212 
1213 static void
1215  std::shared_ptr<Ledger> const& ledger,
1216  Config const& config,
1217  beast::Journal j)
1218 {
1219  if (!ledger)
1220  return;
1221 
1222  ledger->setImmutable(config);
1223 
1224  JLOG(j.trace()) << "Loaded ledger: " << to_string(ledger->info().hash);
1226  ledger->setFull();
1227 }
1228 
1230 loadByIndex(std::uint32_t ledgerIndex, Application& app, bool acquire)
1231 {
1232  std::shared_ptr<Ledger> ledger;
1233  {
1235  s << "WHERE LedgerSeq = " << ledgerIndex;
1236  std::tie(ledger, std::ignore, std::ignore) =
1237  loadLedgerHelper(s.str(), app, acquire);
1238  }
1239 
1240  finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger"));
1241  return ledger;
1242 }
1243 
1245 loadByHash(uint256 const& ledgerHash, Application& app, bool acquire)
1246 {
1247  std::shared_ptr<Ledger> ledger;
1248  {
1250  s << "WHERE LedgerHash = '" << ledgerHash << "'";
1251  std::tie(ledger, std::ignore, std::ignore) =
1252  loadLedgerHelper(s.str(), app, acquire);
1253  }
1254 
1255  finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger"));
1256 
1257  assert(!ledger || ledger->info().hash == ledgerHash);
1259  return ledger;
1260 }
1261 
1262 uint256
1263 getHashByIndex(std::uint32_t ledgerIndex, Application& app)
1264 {
1265  uint256 ret;
1266 
1267  std::string sql =
1268  "SELECT LedgerHash FROM Ledgers INDEXED BY SeqLedger WHERE LedgerSeq='";
1269  sql.append(beast::lexicalCastThrow<std::string>(ledgerIndex));
1270  sql.append("';");
1271 
1272  std::string hash;
1273  {
1274  auto db = app.getLedgerDB().checkoutDb();
1275 
1276  boost::optional<std::string> lh;
1277  *db << sql, soci::into(lh);
1278 
1279  if (!db->got_data() || !lh)
1280  return ret;
1281 
1282  hash = *lh;
1283  if (hash.empty())
1284  return ret;
1285  }
1286 
1287  ret.SetHexExact(hash);
1288  return ret;
1289 }
1290 
1291 bool
1293  std::uint32_t ledgerIndex,
1294  uint256& ledgerHash,
1295  uint256& parentHash,
1296  Application& app)
1297 {
1298  auto db = app.getLedgerDB().checkoutDb();
1299 
1300  boost::optional<std::string> lhO, phO;
1301 
1302  *db << "SELECT LedgerHash,PrevHash FROM Ledgers "
1303  "INDEXED BY SeqLedger Where LedgerSeq = :ls;",
1304  soci::into(lhO), soci::into(phO), soci::use(ledgerIndex);
1305 
1306  if (!lhO || !phO)
1307  {
1308  auto stream = app.journal("Ledger").trace();
1309  JLOG(stream) << "Don't have ledger " << ledgerIndex;
1310  return false;
1311  }
1312 
1313  ledgerHash.SetHexExact(*lhO);
1314  parentHash.SetHexExact(*phO);
1316  return true;
1317 }
1318 
1320 getHashesByIndex(std::uint32_t minSeq, std::uint32_t maxSeq, Application& app)
1321 {
1323 
1324  std::string sql =
1325  "SELECT LedgerSeq,LedgerHash,PrevHash FROM Ledgers WHERE LedgerSeq >= ";
1326  sql.append(beast::lexicalCastThrow<std::string>(minSeq));
1327  sql.append(" AND LedgerSeq <= ");
1328  sql.append(beast::lexicalCastThrow<std::string>(maxSeq));
1329  sql.append(";");
1330 
1331  auto db = app.getLedgerDB().checkoutDb();
1332 
1333  std::uint64_t ls;
1334  std::string lh;
1335  boost::optional<std::string> ph;
1336  soci::statement st =
1337  (db->prepare << sql, soci::into(ls), soci::into(lh), soci::into(ph));
1338 
1339  st.execute();
1340  while (st.fetch())
1341  {
1342  std::pair<uint256, uint256>& hashes =
1343  ret[rangeCheckedCast<std::uint32_t>(ls)];
1344  hashes.first.SetHexExact(lh);
1345  if (ph)
1346  hashes.second.SetHexExact(*ph);
1347  else
1348  hashes.second.zero();
1349  if (!ph)
1350  {
1351  auto stream = app.journal("Ledger").warn();
1352  JLOG(stream) << "Null prev hash for ledger seq: " << ls;
1353  }
1354  }
1355 
1356  return ret;
1357 }
1358 
1359 } // namespace ripple
ripple::STArray::empty
bool empty() const
Definition: STArray.h:144
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:439
ripple::loadLedgerHelper
std::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > loadLedgerHelper(std::string const &sqlSuffix, Application &app, bool acquire)
Definition: Ledger.cpp:1133
ripple::Application
Definition: Application.h:97
ripple::Ledger::sles_iter_impl::sles_iter_impl
sles_iter_impl(SHAMap::const_iterator iter)
Definition: Ledger.cpp:90
ripple::Ledger::slesBegin
std::unique_ptr< sles_type::iter_base > slesBegin() const override
Definition: Ledger.cpp:427
ripple::Application::getNodeFamily
virtual Family & getNodeFamily()=0
ripple::Ledger::addSLE
bool addSLE(SLE const &sle)
Definition: Ledger.cpp:354
ripple::isFlagLedger
bool isFlagLedger(LedgerIndex seq)
Returns true if the given ledgerIndex is a flag ledgerIndex.
Definition: Ledger.cpp:857
ripple::Ledger::rawReplace
void rawReplace(std::shared_ptr< SLE > const &sle) override
Unconditionally replace a state item.
Definition: Ledger.cpp:508
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:384
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::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:382
ripple::Ledger::sles_iter_impl
Definition: Ledger.cpp:78
ripple::STLedgerEntry
Definition: STLedgerEntry.h:30
ripple::Ledger::isVotingLedger
bool isVotingLedger() const
Returns true if the ledger directly precedes a flag ledger.
Definition: Ledger.cpp:851
ripple::Ledger::txRead
tx_type txRead(key_type const &key) const override
Read a transaction from the tx map.
Definition: Ledger.cpp:464
std::string
STL class.
std::shared_ptr
STL class.
ripple::LedgerInfo::parentHash
uint256 parentHash
Definition: ReadView.h:99
ripple::keylet::amendments
Keylet const & amendments() noexcept
The index of the amendment table.
Definition: Indexes.cpp:151
ripple::SHAMap::getHash
SHAMapHash getHash() const
Definition: SHAMap.cpp:793
ripple::loadByIndex
std::shared_ptr< Ledger > loadByIndex(std::uint32_t ledgerIndex, Application &app, bool acquire)
Definition: Ledger.cpp:1225
utility
ripple::Ledger::fees_
Fees fees_
Definition: Ledger.h:390
std::exception
STL class.
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:480
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
ripple::Ledger::unshare
void unshare() const
Definition: Ledger.cpp:1109
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:433
ripple::Serializer::modData
Blob & modData()
Definition: Serializer.h:176
ripple::ReadView::txs_type
Definition: ReadView.h:209
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:96
ripple::XRPAmount::drops
constexpr value_type drops() const
Returns the number of drops.
Definition: XRPAmount.h:172
ripple::sfMetadata
const SField sfMetadata(access, STI_METADATA, 257, "Metadata")
Definition: SField.h:336
ripple::hotACCOUNT_NODE
@ hotACCOUNT_NODE
Definition: NodeObject.h:35
std::vector
STL class.
std::vector::size
T size(T... args)
ripple::sfSequence
const SF_U32 sfSequence(access, STI_UINT32, 4, "Sequence")
Definition: SField.h:356
ripple::Ledger::sles_iter_impl::dereference
sles_type::value_type dereference() const override
Definition: Ledger.cpp:114
ripple::sfAccount
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
Definition: SField.h:480
std::chrono::duration
ripple::keylet::skip
Keylet const & skip() noexcept
The index of the "short" skip list.
Definition: Indexes.cpp:133
ripple::FLAG_LEDGER_INTERVAL
constexpr std::uint32_t FLAG_LEDGER_INTERVAL
Definition: Ledger.h:398
ripple::STObject::getSerializer
Serializer getSerializer() const
Definition: STObject.h:366
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:389
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:149
ripple::STArray::push_back
void push_back(STObject const &object)
Definition: STArray.h:102
ripple::Ledger::peek
std::shared_ptr< SLE > peek(Keylet const &k) const
Definition: Ledger.cpp:590
ripple::Ledger::invariants
void invariants() const
Definition: Ledger.cpp:1116
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:126
std::tuple
ripple::addRaw
void addRaw(LedgerInfo const &info, Serializer &s)
Definition: View.cpp:43
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:710
ripple::STTx::getMetaSQLInsertReplaceHeader
static std::string const & getMetaSQLInsertReplaceHeader()
Definition: STTx.cpp:216
ripple::JobQueue::addJob
bool addJob(JobType type, std::string const &name, JobHandler &&jobHandler)
Adds a job to the JobQueue.
Definition: JobQueue.h:166
ripple::LedgerInfo::seq
LedgerIndex seq
Definition: ReadView.h:88
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:42
ripple::Ledger::rawTxInsert
void rawTxInsert(uint256 const &key, std::shared_ptr< Serializer const > const &txn, std::shared_ptr< Serializer const > const &metaData) override
Add a transaction to the tx map.
Definition: Ledger.cpp:519
ripple::STObject::setFieldVL
void setFieldVL(SField const &field, Blob const &)
Definition: STObject.cpp:668
ripple::sfDisabledValidators
const SField sfDisabledValidators(access, STI_ARRAY, 17, "DisabledValidators")
Definition: SField.h:524
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:137
ripple::Fees::reserve
XRPAmount reserve
Definition: ReadView.h:51
ripple::Ledger::rawErase
void rawErase(std::shared_ptr< SLE > const &sle) override
Delete an existing state item.
Definition: Ledger.cpp:491
ripple::SHAMapType::STATE
@ STATE
ripple::Ledger::updateNegativeUNL
void updateNegativeUNL()
update the Negative UNL ledger component.
Definition: Ledger.cpp:659
ripple::sfReserveBase
const SF_U32 sfReserveBase(access, STI_UINT32, 31, "ReserveBase")
Definition: SField.h:384
ripple::Family::missingNode
virtual void missingNode(std::uint32_t refNum)=0
ripple::LedgerInfo::txHash
uint256 txHash
Definition: ReadView.h:97
ripple::Ledger::info_
LedgerInfo info_
Definition: Ledger.h:392
ripple::finishLoadByIndexOrHash
static void finishLoadByIndexOrHash(std::shared_ptr< Ledger > const &ledger, Config const &config, beast::Journal j)
Definition: Ledger.cpp:1209
ripple::deserializeTx
std::shared_ptr< STTx const > deserializeTx(SHAMapItem const &item)
Deserialize a SHAMapItem containing a single STTx.
Definition: Ledger.cpp:363
ripple::SHAMapHash
Definition: SHAMapTreeNode.h:43
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::Ledger::setImmutable
void setImmutable(Config const &config)
Definition: Ledger.cpp:319
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:1258
ripple::SHAMapMissingNode
Definition: SHAMapMissingNode.h:55
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:493
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:452
ripple::Fees::increment
XRPAmount increment
Definition: ReadView.h:52
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:43
ripple::LedgerInfo::closeTime
NetClock::time_point closeTime
Definition: ReadView.h:119
ripple::STLedgerEntry::key
uint256 const & key() const
Returns the 'key' (or 'index') of this item.
Definition: STLedgerEntry.h:92
ripple::Keylet::key
uint256 key
Definition: Keylet.h:41
ripple::base_uint< 256 >
ripple::sfLastLedgerSequence
const SF_U32 sfLastLedgerSequence(access, STI_UINT32, 27, "LastLedgerSequence")
Definition: SField.h:380
ripple::jtPUBOLDLEDGER
@ jtPUBOLDLEDGER
Definition: Job.h:42
ripple::Ledger::info
LedgerInfo const & info() const override
Returns information about the ledger.
Definition: Ledger.h:155
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:644
ripple::NodeStore::Database::store
virtual void store(NodeObjectType type, Blob &&data, uint256 const &hash, std::uint32_t seq)=0
Store the object.
ripple::Ledger::txExists
bool txExists(uint256 const &key) const override
Returns true if a tx exists in the tx map.
Definition: Ledger.cpp:458
ripple::Ledger::assertSane
bool assertSane(beast::Journal ledgerJ) const
Definition: Ledger.cpp:758
ripple::saveValidatedLedger
static bool saveValidatedLedger(Application &app, std::shared_ptr< Ledger const > const &ledger, bool current)
Definition: Ledger.cpp:863
ripple::loadByHash
std::shared_ptr< Ledger > loadByHash(uint256 const &ledgerHash, Application &app, bool acquire)
Definition: Ledger.cpp:1240
ripple::DatabaseCon::checkoutDb
LockedSociSession checkoutDb()
Definition: DatabaseCon.h:176
ripple::base_uint::isZero
bool isZero() const
Definition: base_uint.h:475
ripple::Ledger::setAccepted
void setAccepted(NetClock::time_point closeTime, NetClock::duration closeResolution, bool correctCloseTime, Config const &config)
Definition: Ledger.cpp:338
ripple::Ledger
Holds a ledger.
Definition: Ledger.h:77
ripple::LedgerMaster::failedSave
void failedSave(std::uint32_t seq, uint256 const &hash)
Definition: LedgerMaster.cpp:926
ripple::Application::getLedgerMaster
virtual LedgerMaster & getLedgerMaster()=0
ripple::Ledger::setFull
void setFull() const
Definition: Ledger.h:274
ripple::PublicKey
A public key.
Definition: PublicKey.h:59
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:121
ripple::SHAMapItem
Definition: SHAMapItem.h:34
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:370
ripple::Config::TRANSACTION_FEE_BASE
static constexpr FeeUnit32 TRANSACTION_FEE_BASE
Definition: Config.h:133
ripple::Ledger::txs_iter_impl::copy
std::unique_ptr< base_type > copy() const override
Definition: Ledger.cpp:143
ripple::Rethrow
void Rethrow()
Rethrow the exception currently being handled.
Definition: contract.h:48
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:629
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:128
ripple::Ledger::stateMap
SHAMap const & stateMap() const
Definition: Ledger.h:289
ripple::Config::FEE_OWNER_RESERVE
XRPAmount FEE_OWNER_RESERVE
Definition: Config.h:161
ripple::SHAMap::const_iterator
Definition: SHAMap.h:535
ripple::calcAccountID
AccountID calcAccountID(PublicKey const &pk)
Definition: AccountID.cpp:131
ripple::SHAMap
A SHAMap is both a radix tree with a fan-out of 16 and a Merkle tree.
Definition: SHAMap.h:81
ripple::STArray
Definition: STArray.h:28
ripple::Ledger::sles_iter_impl::iter_
SHAMap::const_iterator iter_
Definition: Ledger.cpp:81
ripple::create_genesis_t
Definition: Ledger.h:45
ripple::Ledger::isFlagLedger
bool isFlagLedger() const
Returns true if the ledger is a flag ledger.
Definition: Ledger.cpp:846
ripple::Ledger::sles_iter_impl::equal
bool equal(base_type const &impl) const override
Definition: Ledger.cpp:101
ripple::LedgerInfo::closeFlags
int closeFlags
Definition: ReadView.h:110
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::Config::FEE_ACCOUNT_RESERVE
XRPAmount FEE_ACCOUNT_RESERVE
Definition: Config.h:160
ripple::Ledger::rawInsert
void rawInsert(std::shared_ptr< SLE > const &sle) override
Unconditionally insert a state item.
Definition: Ledger.cpp:498
beast::Journal::info
Stream info() const
Definition: Journal.h:321
std::chrono::time_point
ripple::sfReferenceFeeUnits
const SF_U32 sfReferenceFeeUnits(access, STI_UINT32, 30, "ReferenceFeeUnits")
Definition: SField.h:383
std::vector::erase
T erase(T... args)
ripple::Application::logs
virtual Logs & logs()=0
ripple::Family
Definition: Family.h:32
ripple::ValStatus::current
@ current
This was a new validation and was added.
ripple::Job
Definition: Job.h:82
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
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:258
std::map
STL class.
ripple::SHAMapItem::slice
Slice slice() const
Definition: SHAMapItem.h:63
ripple::jtPUBLEDGER
@ jtPUBLEDGER
Definition: Job.h:54
ripple::sfFirstLedgerSequence
const SF_U32 sfFirstLedgerSequence(access, STI_UINT32, 26, "FirstLedgerSequence")
Definition: SField.h:379
ripple::PendingSaves::shouldWork
bool shouldWork(LedgerIndex seq, bool isSynchronous)
Check if a ledger should be dispatched.
Definition: PendingSaves.h:99
ripple::base_uint::SetHexExact
bool SetHexExact(const char *psz)
Parse a hex string into a base_uint The string must contain exactly bytes * 2 hex characters and must...
Definition: base_uint.h:370
std::string::append
T append(T... args)
ripple::LedgerInfo::drops
XRPAmount drops
Definition: ReadView.h:101
ripple::STArray::back
STObject & back()
Definition: STArray.h:83
ripple::KeyType::secp256k1
@ secp256k1
ripple::Serializer
Definition: Serializer.h:39
ripple::sfValidatorToReEnable
const SF_Blob sfValidatorToReEnable(access, STI_VL, 21, "ValidatorToReEnable")
Definition: SField.h:477
ripple::getJson
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
Definition: LedgerToJson.cpp:283
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:407
ripple::Ledger::txMap
SHAMap const & txMap() const
Definition: Ledger.h:301
ripple::getCloseAgree
bool getCloseAgree(LedgerInfo const &info)
Definition: ReadView.h:414
ripple::Config::FEE_DEFAULT
XRPAmount FEE_DEFAULT
Definition: Config.h:159
ripple::generateSeed
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
Definition: Seed.cpp:69
ripple::sfHashes
const SF_Vec256 sfHashes(access, STI_VECTOR256, 2, "Hashes")
Definition: SField.h:494
ripple::Ledger::txsBegin
std::unique_ptr< txs_type::iter_base > txsBegin() const override
Definition: Ledger.cpp:446
ripple::TransactionMaster::inLedger
bool inLedger(uint256 const &hash, std::uint32_t ledger)
Definition: TransactionMaster.cpp:40
ripple::sfPublicKey
const SF_Blob sfPublicKey(access, STI_VL, 1, "PublicKey")
Definition: SField.h:457
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:198
ripple::Config::features
std::unordered_set< uint256, beast::uhash<> > features
Definition: Config.h:185
ripple::Application::getNodeStore
virtual NodeStore::Database & getNodeStore()=0
ripple::Application::journal
virtual beast::Journal journal(std::string const &name)=0
ripple::sfBalance
const SF_Amount sfBalance(access, STI_AMOUNT, 2, "Balance")
Definition: SField.h:441
ripple::calculateLedgerHash
static uint256 calculateLedgerHash(LedgerInfo const &info)
Definition: Ledger.cpp:60
ripple::Ledger::setup
bool setup(Config const &config)
Definition: Ledger.cpp:536
ripple::STArray::emplace_back
void emplace_back(Args &&... args)
Definition: STArray.h:96
ripple::ReadView::seq
LedgerIndex seq() const
Returns the sequence number of the base ledger.
Definition: ReadView.h:256
std::vector::begin
T begin(T... args)
ripple::sfReserveIncrement
const SF_U32 sfReserveIncrement(access, STI_UINT32, 32, "ReserveIncrement")
Definition: SField.h:385
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:50
ripple::LedgerInfo::closeTimeResolution
NetClock::duration closeTimeResolution
Definition: ReadView.h:113
ripple::sha512Half
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition: digest.h:227
ripple::create_genesis
const create_genesis_t create_genesis
Definition: Ledger.cpp:57
cassert
ripple::Ledger::stateMap_
std::shared_ptr< SHAMap > stateMap_
Definition: Ledger.h:385
ripple::Ledger::updateSkipList
void updateSkipList()
Definition: Ledger.cpp:782
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:149
ripple::Ledger::succ
boost::optional< uint256 > succ(uint256 const &key, boost::optional< uint256 > const &last=boost::none) const override
Return the key of the next state item.
Definition: Ledger.cpp:396
std::chrono::duration::count
T count(T... args)
ripple::Ledger::txs_iter_impl::metadata_
bool metadata_
Definition: Ledger.cpp:127
ripple::STVector256
Definition: STVector256.h:29
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:603
std::vector::empty
T empty(T... args)
ripple::Rules
Rules controlling protocol behavior.
Definition: ReadView.h:127
ripple::SHAMapType
SHAMapType
Definition: SHAMapMissingNode.h:32
ripple::Ledger::txs_iter_impl
Definition: Ledger.cpp:124
std::ostringstream::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:159
ripple::getHashesByIndex
bool getHashesByIndex(std::uint32_t ledgerIndex, uint256 &ledgerHash, uint256 &parentHash, Application &app)
Definition: Ledger.cpp:1287
ripple::sfValidatorToDisable
const SF_Blob sfValidatorToDisable(access, STI_VL, 20, "ValidatorToDisable")
Definition: SField.h:476
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
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:80
ripple::NetClock::duration
std::chrono::duration< rep, period > duration
Definition: chrono.h:53
ripple::SHAMapHash::as_uint256
uint256 const & as_uint256() const
Definition: SHAMapTreeNode.h:54
ripple::sfAmendments
const SF_Vec256 sfAmendments(access, STI_VECTOR256, 3, "Amendments")
Definition: SField.h:495
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:77
ripple::sfBaseFee
const SF_U64 sfBaseFee(access, STI_UINT64, 5, "BaseFee")
Definition: SField.h:399
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:167
ripple::Ledger::txs_iter_impl::dereference
txs_type::value_type dereference() const override
Definition: Ledger.cpp:162
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:1059
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:478
ripple::Ledger::txs_iter_impl::increment
void increment() override
Definition: Ledger.cpp:156
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:95
ripple::Application::getHashRouter
virtual HashRouter & getHashRouter()=0
ripple::Ledger::sles_iter_impl::increment
void increment() override
Definition: Ledger.cpp:108
ripple::HashRouter::setFlags
bool setFlags(uint256 const &key, int flags)
Set the flags on a hash.
Definition: HashRouter.cpp:96
ripple::LedgerInfo::accountHash
uint256 accountHash
Definition: ReadView.h:98
ripple::Ledger::rules_
Rules rules_
Definition: Ledger.h:391
ripple::Fees::base
XRPAmount base
Definition: ReadView.h:49
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::sLCF_NoConsensusTime
static const std::uint32_t sLCF_NoConsensusTime
Definition: ReadView.h:411
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
ripple::AccountIDCache::toBase58
std::string toBase58(AccountID const &) const
Return ripple::toBase58 for the AccountID.
Definition: AccountID.cpp:190
ripple::LedgerInfo::parentCloseTime
NetClock::time_point parentCloseTime
Definition: ReadView.h:89
ripple::sfDisabledValidator
const SField sfDisabledValidator(access, STI_OBJECT, 19, "DisabledValidator")
Definition: SField.h:511
ripple::Application::getMasterTransaction
virtual TransactionMaster & getMasterTransaction()=0