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