xrpld
Loading...
Searching...
No Matches
PermissionedDEXInvariant.cpp
1#include <xrpl/tx/invariants/PermissionedDEXInvariant.h>
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/base_uint.h>
5#include <xrpl/beast/utility/Journal.h>
6#include <xrpl/ledger/ReadView.h>
7#include <xrpl/protocol/Feature.h>
8#include <xrpl/protocol/Indexes.h>
9#include <xrpl/protocol/LedgerFormats.h>
10#include <xrpl/protocol/Rules.h>
11#include <xrpl/protocol/SField.h>
12#include <xrpl/protocol/STArray.h>
13#include <xrpl/protocol/STLedgerEntry.h>
14#include <xrpl/protocol/STTx.h>
15#include <xrpl/protocol/TER.h>
16#include <xrpl/protocol/TxFormats.h>
17#include <xrpl/protocol/XRPAmount.h>
18
19namespace xrpl {
20
21void
23{
24 // Post-fixCleanup3_4_0: skip when after is null (defensive).
25 // Pre-amendment: original after-only path via the `if (after && ...)` checks below.
26 if (isFeatureEnabled(fixCleanup3_4_0) && !after)
27 return;
28
29 auto trackDomain = [this, isDelete](UInt256 const& domain) {
30 domainsOld_.insert(domain);
31 if (!isDelete)
32 domains_.insert(domain);
33 };
34
35 if (after && after->getType() == ltDIR_NODE)
36 {
37 if (after->isFieldPresent(sfDomainID))
38 trackDomain(after->getFieldH256(sfDomainID));
39 }
40
41 if (after && after->getType() == ltOFFER)
42 {
43 if (after->isFieldPresent(sfDomainID))
44 {
45 trackDomain(after->getFieldH256(sfDomainID));
46 }
47 else
48 {
49 regularOffersOld_ = true;
50 if (!isDelete)
51 regularOffers_ = true;
52 }
53
54 // pre-fixCleanup3_1_3: hybrid offer missing domain, missing
55 // sfAdditionalBooks, or sfAdditionalBooks has more than one entry
56 if (after->isFlag(lsfHybrid) &&
57 (!after->isFieldPresent(sfDomainID) || !after->isFieldPresent(sfAdditionalBooks) ||
58 after->getFieldArray(sfAdditionalBooks).size() > 1))
59 badHybridsOld_ = true;
60
61 // post-fixCleanup3_1_3: same as above but also catches size == 0
62 if (after->isFlag(lsfHybrid) &&
63 (!after->isFieldPresent(sfDomainID) || !after->isFieldPresent(sfAdditionalBooks) ||
64 after->getFieldArray(sfAdditionalBooks).size() != 1))
65 badHybrids_ = true;
66 }
67}
68
69bool
71 STTx const& tx,
72 TER const result,
73 XRPAmount const,
74 ReadView const& view,
75 beast::Journal const& j)
76{
77 auto const txType = tx.getTxnType();
78 if ((txType != ttPAYMENT && txType != ttOFFER_CREATE) || !isTesSuccess(result))
79 return true;
80
81 // For each offercreate transaction, check if
82 // permissioned offers are valid
83 bool const isMalformed = view.rules().enabled(fixCleanup3_1_3) ? badHybrids_ : badHybridsOld_;
84 if (txType == ttOFFER_CREATE && isMalformed)
85 {
86 JLOG(j.fatal()) << "Invariant failed: hybrid offer is malformed";
87 return false;
88 }
89
90 if (!tx.isFieldPresent(sfDomainID))
91 return true;
92
93 auto const domain = tx.getFieldH256(sfDomainID);
94
95 if (!view.exists(keylet::permissionedDomain(domain)))
96 {
97 JLOG(j.fatal()) << "Invariant failed: domain doesn't exist";
98 return false;
99 }
100
101 // for both payment and offercreate, there shouldn't be another domain
102 // that's different from the domain specified
103 auto const& domains = view.rules().enabled(fixCleanup3_4_0) ? domains_ : domainsOld_;
104 for (auto const& d : domains)
105 {
106 if (d != domain)
107 {
108 JLOG(j.fatal()) << "Invariant failed: transaction"
109 " consumed wrong domains";
110 return false;
111 }
112 }
113
114 bool const hasRegularOffers =
115 view.rules().enabled(fixCleanup3_2_0) ? regularOffers_ : regularOffersOld_;
116 if (hasRegularOffers)
117 {
118 JLOG(j.fatal()) << "Invariant failed: domain transaction"
119 " affected regular offers";
120 return false;
121 }
122
123 return true;
124}
125
126} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:44
Stream fatal() const
Definition Journal.h:368
A view into a ledger.
Definition ReadView.h:41
virtual Rules const & rules() const =0
Returns the tx processing rules.
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
bool enabled(UInt256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:182
std::shared_ptr< STLedgerEntry const > const & ConstRef
UInt256 getFieldH256(SField const &field) const
Definition STObject.cpp:631
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:464
TxType getTxnType() const
Definition STTx.h:250
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
void visitEntry(bool, SLE::ConstRef, SLE::ConstRef)
Keylet permissionedDomain(AccountID const &account, SeqProxy const &seq) noexcept
Definition Indexes.cpp:609
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
bool isFeatureEnabled(UInt256 const &feature, bool resultIfNoRules)
Check whether a feature is enabled in the current ledger rules.
Definition Rules.cpp:199
BaseUInt< 256 > UInt256
Definition base_uint.h:580
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:644
bool isTesSuccess(TER x) noexcept
Definition TER.h:683
TERSubset< CanCvtToTER > TER
Definition TER.h:654