xrpld
Loading...
Searching...
No Matches
DirectoryInvariant.cpp
1#include <xrpl/tx/invariants/DirectoryInvariant.h>
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/beast/utility/Journal.h>
5#include <xrpl/ledger/ReadView.h>
6#include <xrpl/protocol/Feature.h>
7#include <xrpl/protocol/Indexes.h>
8#include <xrpl/protocol/LedgerFormats.h>
9#include <xrpl/protocol/SField.h>
10#include <xrpl/protocol/STLedgerEntry.h>
11#include <xrpl/protocol/STTx.h>
12#include <xrpl/protocol/TER.h>
13#include <xrpl/protocol/XRPAmount.h>
14
15#include <memory>
16
17namespace xrpl {
18
19namespace {
20
21[[nodiscard]] bool
22isRootBookDirectory(SLE const& dir)
23{
24 // Child page keys do not encode book quality.
25 return dir.isFieldPresent(sfExchangeRate) || dir.isFieldPresent(sfTakerPaysCurrency) ||
26 dir.isFieldPresent(sfTakerPaysIssuer) || dir.isFieldPresent(sfTakerPaysMPT) ||
27 dir.isFieldPresent(sfTakerGetsCurrency) || dir.isFieldPresent(sfTakerGetsIssuer) ||
28 dir.isFieldPresent(sfTakerGetsMPT) || dir.isFieldPresent(sfDomainID);
29}
30
31[[nodiscard]] bool
32badExchangeRate(SLE const& dir)
33{
34 return isRootBookDirectory(dir) &&
35 (!dir.isFieldPresent(sfExchangeRate) ||
36 dir.getFieldU64(sfExchangeRate) != getQuality(dir.key()));
37}
38
39} // namespace
40
41void
43 bool isDelete,
44 std::shared_ptr<SLE const> const& before,
46{
47 // New root directories must have matching exchange-rate metadata. New
48 // child directories, and modified directories that change sfRootIndex, must
49 // point to an existing root.
50
51 // Only validate newly-created directories and sfRootIndex changes;
52 // LedgerStateFix handles legacy bad exchange-rate metadata. Skip deletions
53 // because `after` is not guaranteed to be null.
54 if (badBookDirectory_ || isDelete || !after || after->getType() != ltDIR_NODE)
55 return;
56
57 auto const rootIndex = after->getFieldH256(sfRootIndex);
58 // Ignore ordinary modifications that do not change which root this
59 // directory belongs to. That tolerates legacy bad exchange-rate metadata
60 // during normal operation while still checking sfRootIndex changes.
61 if (before && before->getFieldH256(sfRootIndex) == rootIndex)
62 return;
63
64 if (after->key() == rootIndex && !badBookDirectory_)
65 {
66 badBookDirectory_ = badBookDirectory_ || badExchangeRate(*after);
67 return;
68 }
69
70 rootIndexes_.insert(rootIndex);
71}
72
73bool
75 STTx const&,
76 TER const,
77 XRPAmount const,
78 ReadView const& view,
79 beast::Journal const& j)
80{
81 if (!view.rules().enabled(fixCleanup3_2_0))
82 return true;
83
85 {
86 JLOG(j.fatal()) << "Invariant failed: book directory exchange rate "
87 "does not match directory quality";
88 return false;
89 }
90
91 for (auto const& rootIndex : rootIndexes_)
92 {
93 auto const root = view.read(Keylet(ltDIR_NODE, rootIndex));
94 if (!root)
95 {
96 JLOG(j.fatal()) << "Invariant failed: book directory root missing";
97 return false;
98 }
99 }
100
101 return true;
102}
103
104} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:38
Stream fatal() const
Definition Journal.h:321
A view into a ledger.
Definition ReadView.h:31
virtual Rules const & rules() const =0
Returns the tx processing rules.
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:171
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
hash_set< uint256 > rootIndexes_
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::uint64_t getQuality(uint256 const &uBase)
Definition Indexes.cpp:152
Number root(Number f, unsigned d)
Definition Number.cpp:1201
STLedgerEntry SLE
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:554
TERSubset< CanCvtToTER > TER
Definition TER.h:634
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:19