rippled
Loading...
Searching...
No Matches
Ledger.cpp
1#include <xrpld/app/ledger/InboundLedgers.h>
2#include <xrpld/app/ledger/Ledger.h>
3#include <xrpld/app/ledger/LedgerToJson.h>
4#include <xrpld/app/ledger/PendingSaves.h>
5#include <xrpld/app/main/Application.h>
6#include <xrpld/app/misc/HashRouter.h>
7#include <xrpld/app/rdb/backend/SQLiteDatabase.h>
8#include <xrpld/consensus/LedgerTiming.h>
9#include <xrpld/core/Config.h>
10#include <xrpld/core/SociDB.h>
11
12#include <xrpl/basics/Log.h>
13#include <xrpl/basics/contract.h>
14#include <xrpl/beast/utility/instrumentation.h>
15#include <xrpl/core/JobQueue.h>
16#include <xrpl/json/to_string.h>
17#include <xrpl/nodestore/Database.h>
18#include <xrpl/nodestore/detail/DatabaseNodeImp.h>
19#include <xrpl/protocol/Feature.h>
20#include <xrpl/protocol/HashPrefix.h>
21#include <xrpl/protocol/Indexes.h>
22#include <xrpl/protocol/PublicKey.h>
23#include <xrpl/protocol/SecretKey.h>
24#include <xrpl/protocol/digest.h>
25#include <xrpl/protocol/jss.h>
26
27#include <utility>
28#include <vector>
29
30namespace xrpl {
31
33
36{
37 // VFALCO This has to match addRaw in View.h.
38 return sha512Half(
40 std::uint32_t(info.seq),
42 info.parentHash,
43 info.txHash,
44 info.accountHash,
49}
50
51//------------------------------------------------------------------------------
52
53class Ledger::sles_iter_impl : public sles_type::iter_base
54{
55private:
57
58public:
59 sles_iter_impl() = delete;
61 operator=(sles_iter_impl const&) = delete;
62
63 sles_iter_impl(sles_iter_impl const&) = default;
64
68
70 copy() const override
71 {
73 }
74
75 bool
76 equal(base_type const& impl) const override
77 {
78 if (auto const p = dynamic_cast<sles_iter_impl const*>(&impl))
79 return iter_ == p->iter_;
80 return false;
81 }
82
83 void
84 increment() override
85 {
86 ++iter_;
87 }
88
89 sles_type::value_type
90 dereference() const override
91 {
92 SerialIter sit(iter_->slice());
93 return std::make_shared<SLE const>(sit, iter_->key());
94 }
95};
96
97//------------------------------------------------------------------------------
98
99class Ledger::txs_iter_impl : public txs_type::iter_base
100{
101private:
104
105public:
106 txs_iter_impl() = delete;
108 operator=(txs_iter_impl const&) = delete;
109
110 txs_iter_impl(txs_iter_impl const&) = default;
111
112 txs_iter_impl(bool metadata, SHAMap::const_iterator iter) : metadata_(metadata), iter_(std::move(iter))
113 {
114 }
115
117 copy() const override
118 {
120 }
121
122 bool
123 equal(base_type const& impl) const override
124 {
125 if (auto const p = dynamic_cast<txs_iter_impl const*>(&impl))
126 return iter_ == p->iter_;
127 return false;
128 }
129
130 void
131 increment() override
132 {
133 ++iter_;
134 }
135
136 txs_type::value_type
137 dereference() const override
138 {
139 auto const& item = *iter_;
140 if (metadata_)
141 return deserializeTxPlusMeta(item);
142 return {deserializeTx(item), nullptr};
143 }
144};
145
146//------------------------------------------------------------------------------
147
148Ledger::Ledger(create_genesis_t, Config const& config, std::vector<uint256> const& amendments, Family& family)
149 : mImmutable(false)
150 , txMap_(SHAMapType::TRANSACTION, family)
151 , stateMap_(SHAMapType::STATE, family)
152 , rules_{config.features}
153 , j_(beast::Journal(beast::Journal::getNullSink()))
154{
155 header_.seq = 1;
158
159 static auto const id = calcAccountID(generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase")).first);
160 {
161 auto const sle = std::make_shared<SLE>(keylet::account(id));
162 sle->setFieldU32(sfSequence, 1);
163 sle->setAccountID(sfAccount, id);
164 sle->setFieldAmount(sfBalance, header_.drops);
165 rawInsert(sle);
166 }
167
168 if (!amendments.empty())
169 {
170 auto const sle = std::make_shared<SLE>(keylet::amendments());
171 sle->setFieldV256(sfAmendments, STVector256{amendments});
172 rawInsert(sle);
173 }
174
175 {
177 // Whether featureXRPFees is supported will depend on startup options.
178 if (std::find(amendments.begin(), amendments.end(), featureXRPFees) != amendments.end())
179 {
180 sle->at(sfBaseFeeDrops) = config.FEES.reference_fee;
181 sle->at(sfReserveBaseDrops) = config.FEES.account_reserve;
182 sle->at(sfReserveIncrementDrops) = config.FEES.owner_reserve;
183 }
184 else
185 {
186 if (auto const f = config.FEES.reference_fee.dropsAs<std::uint64_t>())
187 sle->at(sfBaseFee) = *f;
188 if (auto const f = config.FEES.account_reserve.dropsAs<std::uint32_t>())
189 sle->at(sfReserveBase) = *f;
190 if (auto const f = config.FEES.owner_reserve.dropsAs<std::uint32_t>())
191 sle->at(sfReserveIncrement) = *f;
192 sle->at(sfReferenceFeeUnits) = Config::FEE_UNITS_DEPRECATED;
193 }
194 rawInsert(sle);
195 }
196
198 setImmutable();
199}
200
202 LedgerHeader const& info,
203 bool& loaded,
204 bool acquire,
205 Config const& config,
206 Family& family,
208 : mImmutable(true)
209 , txMap_(SHAMapType::TRANSACTION, info.txHash, family)
210 , stateMap_(SHAMapType::STATE, info.accountHash, family)
211 , rules_(config.features)
212 , header_(info)
213 , j_(j)
214{
215 loaded = true;
216
217 if (header_.txHash.isNonZero() && !txMap_.fetchRoot(SHAMapHash{header_.txHash}, nullptr))
218 {
219 loaded = false;
220 JLOG(j.warn()) << "Don't have transaction root for ledger" << header_.seq;
221 }
222
223 if (header_.accountHash.isNonZero() && !stateMap_.fetchRoot(SHAMapHash{header_.accountHash}, nullptr))
224 {
225 loaded = false;
226 JLOG(j.warn()) << "Don't have state data root for ledger" << header_.seq;
227 }
228
231
232 defaultFees(config);
233 if (!setup())
234 loaded = false;
235
236 if (!loaded)
237 {
239 if (acquire)
241 }
242}
243
244// Create a new ledger that follows this one
245Ledger::Ledger(Ledger const& prevLedger, NetClock::time_point closeTime)
246 : mImmutable(false)
247 , txMap_(SHAMapType::TRANSACTION, prevLedger.txMap_.family())
248 , stateMap_(prevLedger.stateMap_, true)
249 , fees_(prevLedger.fees_)
250 , rules_(prevLedger.rules_)
251 , j_(beast::Journal(beast::Journal::getNullSink()))
252{
253 header_.seq = prevLedger.header_.seq + 1;
255 header_.hash = prevLedger.header().hash + uint256(1);
256 header_.drops = prevLedger.header().drops;
258 header_.parentHash = prevLedger.header().hash;
260 prevLedger.header_.closeTimeResolution, getCloseAgree(prevLedger.header()), header_.seq);
261
262 if (prevLedger.header_.closeTime == NetClock::time_point{})
263 {
265 }
266 else
267 {
269 }
270}
271
272Ledger::Ledger(LedgerHeader const& info, Config const& config, Family& family)
273 : mImmutable(true)
274 , txMap_(SHAMapType::TRANSACTION, info.txHash, family)
275 , stateMap_(SHAMapType::STATE, info.accountHash, family)
276 , rules_{config.features}
277 , header_(info)
278 , j_(beast::Journal(beast::Journal::getNullSink()))
279{
281}
282
283Ledger::Ledger(std::uint32_t ledgerSeq, NetClock::time_point closeTime, Config const& config, Family& family)
284 : mImmutable(false)
285 , txMap_(SHAMapType::TRANSACTION, family)
286 , stateMap_(SHAMapType::STATE, family)
287 , rules_{config.features}
288 , j_(beast::Journal(beast::Journal::getNullSink()))
289{
290 header_.seq = ledgerSeq;
291 header_.closeTime = closeTime;
293 defaultFees(config);
294 setup();
295}
296
297void
299{
300 // Force update, since this is the only
301 // place the hash transitions to valid
302 if (!mImmutable && rehash)
303 {
306 }
307
308 if (rehash)
310
311 mImmutable = true;
314 setup();
315}
316
317void
318Ledger::setAccepted(NetClock::time_point closeTime, NetClock::duration closeResolution, bool correctCloseTime)
319{
320 // Used when we witnessed the consensus.
321 XRPL_ASSERT(!open(), "xrpl::Ledger::setAccepted : valid ledger state");
322
323 header_.closeTime = closeTime;
324 header_.closeTimeResolution = closeResolution;
325 header_.closeFlags = correctCloseTime ? 0 : sLCF_NoConsensusTime;
326 setImmutable();
327}
328
329bool
331{
332 auto const s = sle.getSerializer();
334}
335
336//------------------------------------------------------------------------------
337
340{
341 SerialIter sit(item.slice());
343}
344
347{
349 SerialIter sit(item.slice());
350 {
351 SerialIter s(sit.getSlice(sit.getVLDataLength()));
353 }
354 {
355 SerialIter s(sit.getSlice(sit.getVLDataLength()));
356 result.second = std::make_shared<STObject const>(s, sfMetadata);
357 }
358 return result;
359}
360
361//------------------------------------------------------------------------------
362
363bool
364Ledger::exists(Keylet const& k) const
365{
366 // VFALCO NOTE Perhaps check the type for debug builds?
367 return stateMap_.hasItem(k.key);
368}
369
370bool
371Ledger::exists(uint256 const& key) const
372{
373 return stateMap_.hasItem(key);
374}
375
377Ledger::succ(uint256 const& key, std::optional<uint256> const& last) const
378{
379 auto item = stateMap_.upper_bound(key);
380 if (item == stateMap_.end())
381 return std::nullopt;
382 if (last && item->key() >= last)
383 return std::nullopt;
384 return item->key();
385}
386
388Ledger::read(Keylet const& k) const
389{
390 if (k.key == beast::zero)
391 {
392 // LCOV_EXCL_START
393 UNREACHABLE("xrpl::Ledger::read : zero key");
394 return nullptr;
395 // LCOV_EXCL_STOP
396 }
397 auto const& item = stateMap_.peekItem(k.key);
398 if (!item)
399 return nullptr;
400 auto sle = std::make_shared<SLE>(SerialIter{item->slice()}, item->key());
401 if (!k.check(*sle))
402 return nullptr;
403 return sle;
404}
405
406//------------------------------------------------------------------------------
407
408auto
409Ledger::slesBegin() const -> std::unique_ptr<sles_type::iter_base>
410{
412}
413
414auto
415Ledger::slesEnd() const -> std::unique_ptr<sles_type::iter_base>
416{
418}
419
420auto
422{
423 return std::make_unique<sles_iter_impl>(stateMap_.upper_bound(key));
424}
425
426auto
427Ledger::txsBegin() const -> std::unique_ptr<txs_type::iter_base>
428{
430}
431
432auto
433Ledger::txsEnd() const -> std::unique_ptr<txs_type::iter_base>
434{
436}
437
438bool
439Ledger::txExists(uint256 const& key) const
440{
441 return txMap_.hasItem(key);
442}
443
444auto
445Ledger::txRead(key_type const& key) const -> tx_type
446{
447 auto const& item = txMap_.peekItem(key);
448 if (!item)
449 return {};
450 if (!open())
451 {
452 auto result = deserializeTxPlusMeta(*item);
453 return {std::move(result.first), std::move(result.second)};
454 }
455 return {deserializeTx(*item), nullptr};
456}
457
458auto
460{
462 // VFALCO Unfortunately this loads the item
463 // from the NodeStore needlessly.
464 if (!stateMap_.peekItem(key, digest))
465 return std::nullopt;
466 return digest.as_uint256();
467}
468
469//------------------------------------------------------------------------------
470
471void
473{
474 if (!stateMap_.delItem(sle->key()))
475 LogicError("Ledger::rawErase: key not found");
476}
477
478void
480{
481 if (!stateMap_.delItem(key))
482 LogicError("Ledger::rawErase: key not found");
483}
484
485void
487{
488 Serializer ss;
489 sle->add(ss);
491 LogicError("Ledger::rawInsert: key already exists");
492}
493
494void
496{
497 Serializer ss;
498 sle->add(ss);
500 LogicError("Ledger::rawReplace: key not found");
501}
502
503void
505 uint256 const& key,
507 std::shared_ptr<Serializer const> const& metaData)
508{
509 XRPL_ASSERT(metaData, "xrpl::Ledger::rawTxInsert : non-null metadata input");
510
511 // low-level - just add to table
512 Serializer s(txn->getDataLength() + metaData->getDataLength() + 16);
513 s.addVL(txn->peekData());
514 s.addVL(metaData->peekData());
516 LogicError("duplicate_tx: " + to_string(key));
517}
518
521 uint256 const& key,
523 std::shared_ptr<Serializer const> const& metaData)
524{
525 XRPL_ASSERT(metaData, "xrpl::Ledger::rawTxInsertWithHash : non-null metadata input");
526
527 // low-level - just add to table
528 Serializer s(txn->getDataLength() + metaData->getDataLength() + 16);
529 s.addVL(txn->peekData());
530 s.addVL(metaData->peekData());
531 auto item = make_shamapitem(key, s.slice());
532 auto hash = sha512Half(HashPrefix::txNode, item->slice(), item->key());
534 LogicError("duplicate_tx: " + to_string(key));
535
536 return hash;
537}
538
539bool
541{
542 bool ret = true;
543
544 try
545 {
547 }
548 catch (SHAMapMissingNode const&)
549 {
550 ret = false;
551 }
552 catch (std::exception const& ex)
553 {
554 JLOG(j_.error()) << "Exception in " << __func__ << ": " << ex.what();
555 Rethrow();
556 }
557
558 try
559 {
560 if (auto const sle = read(keylet::fees()))
561 {
562 bool oldFees = false;
563 bool newFees = false;
564 {
565 auto const baseFee = sle->at(~sfBaseFee);
566 auto const reserveBase = sle->at(~sfReserveBase);
567 auto const reserveIncrement = sle->at(~sfReserveIncrement);
568 if (baseFee)
569 fees_.base = *baseFee;
570 if (reserveBase)
571 fees_.reserve = *reserveBase;
572 if (reserveIncrement)
573 fees_.increment = *reserveIncrement;
574 oldFees = baseFee || reserveBase || reserveIncrement;
575 }
576 {
577 auto const baseFeeXRP = sle->at(~sfBaseFeeDrops);
578 auto const reserveBaseXRP = sle->at(~sfReserveBaseDrops);
579 auto const reserveIncrementXRP = sle->at(~sfReserveIncrementDrops);
580 auto assign = [&ret](XRPAmount& dest, std::optional<STAmount> const& src) {
581 if (src)
582 {
583 if (src->native())
584 dest = src->xrp();
585 else
586 ret = false;
587 }
588 };
589 assign(fees_.base, baseFeeXRP);
590 assign(fees_.reserve, reserveBaseXRP);
591 assign(fees_.increment, reserveIncrementXRP);
592 newFees = baseFeeXRP || reserveBaseXRP || reserveIncrementXRP;
593 }
594 if (oldFees && newFees)
595 // Should be all of one or the other, but not both
596 ret = false;
597 if (!rules_.enabled(featureXRPFees) && newFees)
598 // Can't populate the new fees before the amendment is enabled
599 ret = false;
600 }
601 }
602 catch (SHAMapMissingNode const&)
603 {
604 ret = false;
605 }
606 catch (std::exception const& ex)
607 {
608 JLOG(j_.error()) << "Exception in " << __func__ << ": " << ex.what();
609 Rethrow();
610 }
611
612 return ret;
613}
614
615void
617{
618 XRPL_ASSERT(fees_.base == 0 && fees_.reserve == 0 && fees_.increment == 0, "xrpl::Ledger::defaultFees : zero fees");
619 if (fees_.base == 0)
620 fees_.base = config.FEES.reference_fee;
621 if (fees_.reserve == 0)
623 if (fees_.increment == 0)
625}
626
628Ledger::peek(Keylet const& k) const
629{
630 auto const& value = stateMap_.peekItem(k.key);
631 if (!value)
632 return nullptr;
633 auto sle = std::make_shared<SLE>(SerialIter{value->slice()}, value->key());
634 if (!k.check(*sle))
635 return nullptr;
636 return sle;
637}
638
641{
642 hash_set<PublicKey> negUnl;
643 if (auto sle = read(keylet::negativeUNL()); sle && sle->isFieldPresent(sfDisabledValidators))
644 {
645 auto const& nUnlData = sle->getFieldArray(sfDisabledValidators);
646 for (auto const& n : nUnlData)
647 {
648 if (n.isFieldPresent(sfPublicKey))
649 {
650 auto d = n.getFieldVL(sfPublicKey);
651 auto s = makeSlice(d);
652 if (!publicKeyType(s))
653 {
654 continue;
655 }
656 negUnl.emplace(s);
657 }
658 }
659 }
660
661 return negUnl;
662}
663
666{
667 if (auto sle = read(keylet::negativeUNL()); sle && sle->isFieldPresent(sfValidatorToDisable))
668 {
669 auto d = sle->getFieldVL(sfValidatorToDisable);
670 auto s = makeSlice(d);
671 if (publicKeyType(s))
672 return PublicKey(s);
673 }
674
675 return std::nullopt;
676}
677
680{
681 if (auto sle = read(keylet::negativeUNL()); sle && sle->isFieldPresent(sfValidatorToReEnable))
682 {
683 auto d = sle->getFieldVL(sfValidatorToReEnable);
684 auto s = makeSlice(d);
685 if (publicKeyType(s))
686 return PublicKey(s);
687 }
688
689 return std::nullopt;
690}
691
692void
694{
695 auto sle = peek(keylet::negativeUNL());
696 if (!sle)
697 return;
698
699 bool const hasToDisable = sle->isFieldPresent(sfValidatorToDisable);
700 bool const hasToReEnable = sle->isFieldPresent(sfValidatorToReEnable);
701
702 if (!hasToDisable && !hasToReEnable)
703 return;
704
705 STArray newNUnl;
706 if (sle->isFieldPresent(sfDisabledValidators))
707 {
708 auto const& oldNUnl = sle->getFieldArray(sfDisabledValidators);
709 for (auto v : oldNUnl)
710 {
711 if (hasToReEnable && v.isFieldPresent(sfPublicKey) &&
712 v.getFieldVL(sfPublicKey) == sle->getFieldVL(sfValidatorToReEnable))
713 continue;
714 newNUnl.push_back(v);
715 }
716 }
717
718 if (hasToDisable)
719 {
720 newNUnl.push_back(STObject::makeInnerObject(sfDisabledValidator));
721 newNUnl.back().setFieldVL(sfPublicKey, sle->getFieldVL(sfValidatorToDisable));
722 newNUnl.back().setFieldU32(sfFirstLedgerSequence, seq());
723 }
724
725 if (!newNUnl.empty())
726 {
727 sle->setFieldArray(sfDisabledValidators, newNUnl);
728 if (hasToReEnable)
729 sle->makeFieldAbsent(sfValidatorToReEnable);
730 if (hasToDisable)
731 sle->makeFieldAbsent(sfValidatorToDisable);
732 rawReplace(sle);
733 }
734 else
735 {
736 rawErase(sle);
737 }
738}
739
740//------------------------------------------------------------------------------
741bool
742Ledger::walkLedger(beast::Journal j, bool parallel) const
743{
744 std::vector<SHAMapMissingNode> missingNodes1;
745 std::vector<SHAMapMissingNode> missingNodes2;
746
748 !stateMap_.fetchRoot(SHAMapHash{header_.accountHash}, nullptr))
749 {
751 }
752 else
753 {
754 if (parallel)
755 return stateMap_.walkMapParallel(missingNodes1, 32);
756 else
757 stateMap_.walkMap(missingNodes1, 32);
758 }
759
760 if (!missingNodes1.empty())
761 {
762 if (auto stream = j.info())
763 {
764 stream << missingNodes1.size() << " missing account node(s)";
765 stream << "First: " << missingNodes1[0].what();
766 }
767 }
768
770 !txMap_.fetchRoot(SHAMapHash{header_.txHash}, nullptr))
771 {
773 }
774 else
775 {
776 txMap_.walkMap(missingNodes2, 32);
777 }
778
779 if (!missingNodes2.empty())
780 {
781 if (auto stream = j.info())
782 {
783 stream << missingNodes2.size() << " missing transaction node(s)";
784 stream << "First: " << missingNodes2[0].what();
785 }
786 }
787 return missingNodes1.empty() && missingNodes2.empty();
788}
789
790bool
792{
795 {
796 return true;
797 }
798
799 // LCOV_EXCL_START
800 Json::Value j = getJson({*this, {}});
801
802 j[jss::accountTreeHash] = to_string(header_.accountHash);
803 j[jss::transTreeHash] = to_string(header_.txHash);
804
805 JLOG(ledgerJ.fatal()) << "ledger is not sensible" << j;
806
807 UNREACHABLE("xrpl::Ledger::assertSensible : ledger is not sensible");
808
809 return false;
810 // LCOV_EXCL_STOP
811}
812
813// update the skip list with the information from our previous ledger
814// VFALCO TODO Document this skip list concept
815void
817{
818 if (header_.seq == 0) // genesis ledger has no previous ledger
819 return;
820
821 std::uint32_t prevIndex = header_.seq - 1;
822
823 // update record of every 256th ledger
824 if ((prevIndex & 0xff) == 0)
825 {
826 auto const k = keylet::skip(prevIndex);
827 auto sle = peek(k);
829
830 bool created;
831 if (!sle)
832 {
833 sle = std::make_shared<SLE>(k);
834 created = true;
835 }
836 else
837 {
838 hashes = static_cast<decltype(hashes)>(sle->getFieldV256(sfHashes));
839 created = false;
840 }
841
842 XRPL_ASSERT(hashes.size() <= 256, "xrpl::Ledger::updateSkipList : first maximum hashes size");
844 sle->setFieldV256(sfHashes, STVector256(hashes));
845 sle->setFieldU32(sfLastLedgerSequence, prevIndex);
846 if (created)
847 rawInsert(sle);
848 else
849 rawReplace(sle);
850 }
851
852 // update record of past 256 ledger
853 auto const k = keylet::skip();
854 auto sle = peek(k);
856 bool created;
857 if (!sle)
858 {
859 sle = std::make_shared<SLE>(k);
860 created = true;
861 }
862 else
863 {
864 hashes = static_cast<decltype(hashes)>(sle->getFieldV256(sfHashes));
865 created = false;
866 }
867 XRPL_ASSERT(hashes.size() <= 256, "xrpl::Ledger::updateSkipList : second maximum hashes size");
868 if (hashes.size() == 256)
869 hashes.erase(hashes.begin());
871 sle->setFieldV256(sfHashes, STVector256(hashes));
872 sle->setFieldU32(sfLastLedgerSequence, prevIndex);
873 if (created)
874 rawInsert(sle);
875 else
876 rawReplace(sle);
877}
878
879bool
881{
882 return header_.seq % FLAG_LEDGER_INTERVAL == 0;
883}
884bool
886{
887 return (header_.seq + 1) % FLAG_LEDGER_INTERVAL == 0;
888}
889
890bool
892{
893 return seq % FLAG_LEDGER_INTERVAL == 0;
894}
895
896static bool
898{
899 auto j = app.journal("Ledger");
900 auto seq = ledger->header().seq;
901 if (!app.pendingSaves().startWork(seq))
902 {
903 // The save was completed synchronously
904 JLOG(j.debug()) << "Save aborted";
905 return true;
906 }
907
908 auto const db = dynamic_cast<SQLiteDatabase*>(&app.getRelationalDatabase());
909 if (!db)
910 Throw<std::runtime_error>("Failed to get relational database");
911
912 auto const res = db->saveValidatedLedger(ledger, current);
913
914 // Clients can now trust the database for
915 // information about this ledger sequence.
916 app.pendingSaves().finishWork(seq);
917 return res;
918}
919
923bool
924pendSaveValidated(Application& app, std::shared_ptr<Ledger const> const& ledger, bool isSynchronous, bool isCurrent)
925{
926 if (!app.getHashRouter().setFlags(ledger->header().hash, HashRouterFlags::SAVED))
927 {
928 // We have tried to save this ledger recently
929 auto stream = app.journal("Ledger").debug();
930 JLOG(stream) << "Double pend save for " << ledger->header().seq;
931
932 if (!isSynchronous || !app.pendingSaves().pending(ledger->header().seq))
933 {
934 // Either we don't need it to be finished
935 // or it is finished
936 return true;
937 }
938 }
939
940 XRPL_ASSERT(ledger->isImmutable(), "xrpl::pendSaveValidated : immutable ledger");
941
942 if (!app.pendingSaves().shouldWork(ledger->header().seq, isSynchronous))
943 {
944 auto stream = app.journal("Ledger").debug();
945 JLOG(stream) << "Pend save with seq in pending saves " << ledger->header().seq;
946
947 return true;
948 }
949
950 // See if we can use the JobQueue.
951 if (!isSynchronous &&
952 app.getJobQueue().addJob(
953 isCurrent ? jtPUBLEDGER : jtPUBOLDLEDGER, std::to_string(ledger->seq()), [&app, ledger, isCurrent]() {
954 saveValidatedLedger(app, ledger, isCurrent);
955 }))
956 {
957 return true;
958 }
959
960 // The JobQueue won't do the Job. Do the save synchronously.
961 return saveValidatedLedger(app, ledger, isCurrent);
962}
963
964void
966{
968 txMap_.unshare();
969}
970
971void
977//------------------------------------------------------------------------------
978
979/*
980 * Make ledger using info loaded from database.
981 *
982 * @param LedgerHeader: Ledger information.
983 * @param app: Link to the Application.
984 * @param acquire: Acquire the ledger if not found locally.
985 * @return Shared pointer to the ledger.
986 */
988loadLedgerHelper(LedgerHeader const& info, Application& app, bool acquire)
989{
990 bool loaded;
991 auto ledger =
992 std::make_shared<Ledger>(info, loaded, acquire, app.config(), app.getNodeFamily(), app.journal("Ledger"));
993
994 if (!loaded)
995 ledger.reset();
996
997 return ledger;
998}
999
1000static void
1002{
1003 if (!ledger)
1004 return;
1005
1006 XRPL_ASSERT(
1007 ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || ledger->read(keylet::fees()),
1008 "xrpl::finishLoadByIndexOrHash : valid ledger fees");
1009 ledger->setImmutable();
1010
1011 JLOG(j.trace()) << "Loaded ledger: " << to_string(ledger->header().hash);
1012
1013 ledger->setFull();
1014}
1015
1018{
1020 if (!info)
1021 return {std::shared_ptr<Ledger>(), {}, {}};
1022 return {loadLedgerHelper(*info, app, true), info->seq, info->hash};
1023}
1024
1026loadByIndex(std::uint32_t ledgerIndex, Application& app, bool acquire)
1027{
1029 {
1030 std::shared_ptr<Ledger> ledger = loadLedgerHelper(*info, app, acquire);
1031 finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger"));
1032 return ledger;
1033 }
1034 return {};
1035}
1036
1038loadByHash(uint256 const& ledgerHash, Application& app, bool acquire)
1039{
1041 {
1042 std::shared_ptr<Ledger> ledger = loadLedgerHelper(*info, app, acquire);
1043 finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger"));
1044 XRPL_ASSERT(!ledger || ledger->header().hash == ledgerHash, "xrpl::loadByHash : ledger hash match if loaded");
1045 return ledger;
1046 }
1047 return {};
1048}
1049
1050} // namespace xrpl
T begin(T... args)
Represents a JSON value.
Definition json_value.h:131
A generic endpoint for log messages.
Definition Journal.h:41
Stream fatal() const
Definition Journal.h:325
Stream error() const
Definition Journal.h:319
Stream debug() const
Definition Journal.h:301
Stream info() const
Definition Journal.h:307
Stream trace() const
Severity stream access functions.
Definition Journal.h:295
Stream warn() const
Definition Journal.h:313
virtual HashRouter & getHashRouter()=0
virtual Config & config()=0
virtual PendingSaves & pendingSaves()=0
virtual beast::Journal journal(std::string const &name)=0
virtual Family & getNodeFamily()=0
virtual JobQueue & getJobQueue()=0
virtual RelationalDatabase & getRelationalDatabase()=0
static constexpr std::uint32_t FEE_UNITS_DEPRECATED
Definition Config.h:142
FeeSetup FEES
Definition Config.h:185
virtual void missingNodeAcquireByHash(uint256 const &refHash, std::uint32_t refNum)=0
Acquire ledger that has a missing node by ledger hash.
bool setFlags(uint256 const &key, HashRouterFlags flags)
Set the flags on a hash.
bool addJob(JobType type, std::string const &name, JobHandler &&jobHandler)
Adds a job to the JobQueue.
Definition JobQueue.h:146
sles_iter_impl(sles_iter_impl const &)=default
void increment() override
Definition Ledger.cpp:84
SHAMap::const_iterator iter_
Definition Ledger.cpp:56
bool equal(base_type const &impl) const override
Definition Ledger.cpp:76
std::unique_ptr< base_type > copy() const override
Definition Ledger.cpp:70
sles_iter_impl & operator=(sles_iter_impl const &)=delete
sles_type::value_type dereference() const override
Definition Ledger.cpp:90
sles_iter_impl(SHAMap::const_iterator iter)
Definition Ledger.cpp:65
bool equal(base_type const &impl) const override
Definition Ledger.cpp:123
SHAMap::const_iterator iter_
Definition Ledger.cpp:103
txs_iter_impl(txs_iter_impl const &)=default
std::unique_ptr< base_type > copy() const override
Definition Ledger.cpp:117
txs_iter_impl(bool metadata, SHAMap::const_iterator iter)
Definition Ledger.cpp:112
void increment() override
Definition Ledger.cpp:131
txs_type::value_type dereference() const override
Definition Ledger.cpp:137
txs_iter_impl & operator=(txs_iter_impl const &)=delete
Holds a ledger.
Definition Ledger.h:61
bool txExists(uint256 const &key) const override
Definition Ledger.cpp:439
std::unique_ptr< txs_type::iter_base > txsEnd() const override
Definition Ledger.cpp:433
Fees fees_
Definition Ledger.h:386
bool isFlagLedger() const
Returns true if the ledger is a flag ledger.
Definition Ledger.cpp:880
std::optional< digest_type > digest(key_type const &key) const override
Return the digest associated with the key.
Definition Ledger.cpp:459
void rawTxInsert(uint256 const &key, std::shared_ptr< Serializer const > const &txn, std::shared_ptr< Serializer const > const &metaData) override
Definition Ledger.cpp:504
std::optional< PublicKey > validatorToDisable() const
get the to be disabled validator's master public key if any
Definition Ledger.cpp:665
uint256 rawTxInsertWithHash(uint256 const &key, std::shared_ptr< Serializer const > const &txn, std::shared_ptr< Serializer const > const &metaData)
Definition Ledger.cpp:520
std::shared_ptr< SLE const > read(Keylet const &k) const override
Return the state item associated with a key.
Definition Ledger.cpp:388
void updateNegativeUNL()
update the Negative UNL ledger component.
Definition Ledger.cpp:693
bool assertSensible(beast::Journal ledgerJ) const
Definition Ledger.cpp:791
bool isVotingLedger() const
Returns true if the ledger directly precedes a flag ledger.
Definition Ledger.cpp:885
std::unique_ptr< sles_type::iter_base > slesBegin() const override
Definition Ledger.cpp:409
Rules rules_
Definition Ledger.h:387
void invariants() const
Definition Ledger.cpp:972
hash_set< PublicKey > negativeUNL() const
get Negative UNL validators' master public keys
Definition Ledger.cpp:640
void rawInsert(std::shared_ptr< SLE > const &sle) override
Unconditionally insert a state item.
Definition Ledger.cpp:486
void rawReplace(std::shared_ptr< SLE > const &sle) override
Unconditionally replace a state item.
Definition Ledger.cpp:495
void setImmutable(bool rehash=true)
Definition Ledger.cpp:298
void updateSkipList()
Definition Ledger.cpp:816
void defaultFees(Config const &config)
Definition Ledger.cpp:616
bool open() const override
Returns true if this reflects an open ledger.
Definition Ledger.h:119
void rawErase(std::shared_ptr< SLE > const &sle) override
Delete an existing state item.
Definition Ledger.cpp:472
LedgerHeader const & header() const override
Returns information about the ledger.
Definition Ledger.h:125
void setAccepted(NetClock::time_point closeTime, NetClock::duration closeResolution, bool correctCloseTime)
Definition Ledger.cpp:318
bool mImmutable
Definition Ledger.h:375
Ledger(Ledger const &)=delete
std::shared_ptr< SLE > peek(Keylet const &k) const
Definition Ledger.cpp:628
LedgerHeader header_
Definition Ledger.h:388
bool addSLE(SLE const &sle)
Definition Ledger.cpp:330
std::unique_ptr< txs_type::iter_base > txsBegin() const override
Definition Ledger.cpp:427
std::unique_ptr< sles_type::iter_base > slesEnd() const override
Definition Ledger.cpp:415
SHAMap stateMap_
Definition Ledger.h:381
std::optional< uint256 > succ(uint256 const &key, std::optional< uint256 > const &last=std::nullopt) const override
Definition Ledger.cpp:377
SHAMap txMap_
Definition Ledger.h:378
beast::Journal j_
Definition Ledger.h:389
bool walkLedger(beast::Journal j, bool parallel=false) const
Definition Ledger.cpp:742
void unshare() const
Definition Ledger.cpp:965
std::unique_ptr< sles_type::iter_base > slesUpperBound(uint256 const &key) const override
Definition Ledger.cpp:421
std::optional< PublicKey > validatorToReEnable() const
get the to be re-enabled validator's master public key if any
Definition Ledger.cpp:679
tx_type txRead(key_type const &key) const override
Read a transaction from the tx map.
Definition Ledger.cpp:445
bool setup()
Definition Ledger.cpp:540
bool exists(Keylet const &k) const override
Determine if a state item exists.
Definition Ledger.cpp:364
void finishWork(LedgerIndex seq)
Finish working on a ledger.
bool shouldWork(LedgerIndex seq, bool isSynchronous)
Check if a ledger should be dispatched.
bool startWork(LedgerIndex seq)
Start working on a ledger.
bool pending(LedgerIndex seq)
Return true if a ledger is in the progress of being saved.
A public key.
Definition PublicKey.h:43
LedgerIndex seq() const
Returns the sequence number of the base ledger.
Definition ReadView.h:98
virtual std::optional< LedgerHeader > getNewestLedgerInfo()=0
getNewestLedgerInfo Returns the info of the newest saved ledger.
virtual std::optional< LedgerHeader > getLedgerInfoByHash(uint256 const &ledgerHash)=0
getLedgerInfoByHash Returns the info of the ledger with given hash.
virtual std::optional< LedgerHeader > getLedgerInfoByIndex(LedgerIndex ledgerSeq)=0
getLedgerInfoByIndex Returns a ledger by its sequence.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:118
uint256 const & as_uint256() const
Definition SHAMapHash.h:25
bool isZero() const
Definition SHAMapHash.h:35
Slice slice() const
Definition SHAMapItem.h:83
bool addItem(SHAMapNodeType type, boost::intrusive_ptr< SHAMapItem const > item)
Definition SHAMap.cpp:775
const_iterator upper_bound(uint256 const &id) const
Find the first item after the given item.
Definition SHAMap.cpp:557
const_iterator end() const
Definition SHAMap.h:675
const_iterator begin() const
Definition SHAMap.h:669
boost::intrusive_ptr< SHAMapItem const > const & peekItem(uint256 const &id) const
Definition SHAMap.cpp:534
int flushDirty(NodeObjectType t)
Flush modified nodes to the nodestore and convert them to shared.
Definition SHAMap.cpp:920
bool walkMapParallel(std::vector< SHAMapMissingNode > &missingNodes, int maxMissing) const
void walkMap(std::vector< SHAMapMissingNode > &missingNodes, int maxMissing) const
bool hasItem(uint256 const &id) const
Does the tree have an item with the given ID?
Definition SHAMap.cpp:625
int unshare()
Convert any modified nodes to shared.
Definition SHAMap.cpp:913
bool updateGiveItem(SHAMapNodeType type, boost::intrusive_ptr< SHAMapItem const > item)
Definition SHAMap.cpp:793
void setImmutable()
Definition SHAMap.h:524
void invariants() const
Definition SHAMap.cpp:1115
bool addGiveItem(SHAMapNodeType type, boost::intrusive_ptr< SHAMapItem const > item)
Definition SHAMap.cpp:708
bool fetchRoot(SHAMapHash const &hash, SHAMapSyncFilter *filter)
Definition SHAMap.cpp:833
SHAMapHash getHash() const
Definition SHAMap.cpp:781
bool delItem(uint256 const &id)
Definition SHAMap.cpp:631
void push_back(STObject const &object)
Definition STArray.h:188
bool empty() const
Definition STArray.h:230
STObject & back()
Definition STArray.h:169
uint256 const & key() const
Returns the 'key' (or 'index') of this item.
void setFieldVL(SField const &field, Blob const &)
Definition STObject.cpp:760
void setFieldU32(SField const &field, std::uint32_t)
Definition STObject.cpp:718
Serializer getSerializer() const
Definition STObject.h:967
static STObject makeInnerObject(SField const &name)
Definition STObject.cpp:72
Slice getSlice(std::size_t bytes)
int addVL(Blob const &vector)
Slice slice() const noexcept
Definition Serializer.h:45
constexpr value_type drops() const
Returns the number of drops.
Definition XRPAmount.h:158
std::optional< Dest > dropsAs() const
Definition XRPAmount.h:168
bool isZero() const
Definition base_uint.h:509
bool isNonZero() const
Definition base_uint.h:514
T emplace_back(T... args)
T emplace(T... args)
T empty(T... args)
T erase(T... args)
T find(T... args)
T is_same_v
STL namespace.
Keylet const & skip() noexcept
The index of the "short" skip list.
Definition Indexes.cpp:172
Keylet const & negativeUNL() noexcept
The (fixed) index of the object containing the ledger negativeUNL.
Definition Indexes.cpp:201
Keylet const & amendments() noexcept
The index of the amendment table.
Definition Indexes.cpp:187
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:160
Keylet const & fees() noexcept
The (fixed) index of the object containing the ledger fees.
Definition Indexes.cpp:194
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
static constexpr std::uint32_t XRP_LEDGER_EARLIEST_FEES
The XRP Ledger mainnet's earliest ledger with a FeeSettings object.
std::shared_ptr< Ledger > loadByHash(uint256 const &ledgerHash, Application &app, bool acquire)
Definition Ledger.cpp:1038
std::shared_ptr< Ledger > loadLedgerHelper(LedgerHeader const &info, Application &app, bool acquire)
Definition Ledger.cpp:988
bool isCurrent(ValidationParms const &p, NetClock::time_point now, NetClock::time_point signTime, NetClock::time_point seenTime)
Whether a validation is still current.
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
static void finishLoadByIndexOrHash(std::shared_ptr< Ledger > const &ledger, Config const &config, beast::Journal j)
Definition Ledger.cpp:1001
bool isFlagLedger(LedgerIndex seq)
Returns true if the given ledgerIndex is a flag ledgerIndex.
Definition Ledger.cpp:891
static Hasher::result_type digest(void const *data, std::size_t size) noexcept
Definition tokens.cpp:137
boost::intrusive_ptr< SHAMapItem > make_shamapitem(uint256 const &tag, Slice data)
Definition SHAMapItem.h:138
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition digest.h:205
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:598
Rules makeRulesGivenLedger(DigestAwareReadView const &ledger, Rules const &current)
Definition ReadView.cpp:50
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:346
std::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > getLatestLedger(Application &app)
Definition Ledger.cpp:1017
std::shared_ptr< STTx const > deserializeTx(SHAMapItem const &item)
Deserialize a SHAMapItem containing a single STTx.
Definition Ledger.cpp:339
create_genesis_t const create_genesis
Definition Ledger.cpp:32
static bool saveValidatedLedger(Application &app, std::shared_ptr< Ledger const > const &ledger, bool current)
Definition Ledger.cpp:897
auto constexpr ledgerDefaultTimeResolution
Initial resolution of ledger close time.
@ hotACCOUNT_NODE
Definition NodeObject.h:16
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
Definition Seed.cpp:57
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.
std::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
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:924
bool getCloseAgree(LedgerHeader const &info)
uint256 calculateLedgerHash(LedgerHeader const &info)
Definition Ledger.cpp:35
@ current
This was a new validation and was added.
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
base_uint< 256 > uint256
Definition base_uint.h:527
std::shared_ptr< Ledger > loadByIndex(std::uint32_t ledgerIndex, Application &app, bool acquire)
Definition Ledger.cpp:1026
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.
@ jtPUBLEDGER
Definition Job.h:48
@ jtPUBOLDLEDGER
Definition Job.h:24
@ open
We haven't closed our ledger yet, but others might have.
static std::uint32_t const sLCF_NoConsensusTime
AccountID calcAccountID(PublicKey const &pk)
auto constexpr ledgerGenesisTimeResolution
Close time resolution in genesis ledger.
@ txNode
transaction plus metadata
@ ledgerMaster
ledger master data for signing
constexpr XRPAmount INITIAL_XRP
Configure the native currency.
void Rethrow()
Rethrow the exception currently being handled.
Definition contract.h:29
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:214
std::uint32_t constexpr FLAG_LEDGER_INTERVAL
Definition Ledger.h:395
T push_back(T... args)
T size(T... args)
XRPAmount reference_fee
The cost of a reference transaction in drops.
Definition Config.h:49
XRPAmount account_reserve
The account reserve requirement in drops.
Definition Config.h:52
XRPAmount owner_reserve
The per-owned item reserve requirement in drops.
Definition Config.h:55
XRPAmount reserve
XRPAmount increment
XRPAmount base
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:20
uint256 key
Definition Keylet.h:21
bool check(STLedgerEntry const &) const
Returns true if the SLE matches the type.
Definition Keylet.cpp:9
Information about the notional ledger backing the view.
NetClock::time_point parentCloseTime
NetClock::duration closeTimeResolution
NetClock::time_point closeTime
T time_since_epoch(T... args)
T to_string(T... args)
T what(T... args)