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