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