rippled
Loading...
Searching...
No Matches
PermissionedDomainInvariant.cpp
1#include <xrpl/tx/invariants/PermissionedDomainInvariant.h>
2//
3#include <xrpl/beast/utility/instrumentation.h>
4#include <xrpl/ledger/helpers/CredentialHelpers.h>
5#include <xrpl/protocol/Feature.h>
6#include <xrpl/protocol/STArray.h>
7#include <xrpl/protocol/TxFormats.h>
8
9namespace xrpl {
10
11void
13 bool isDel,
14 std::shared_ptr<SLE const> const& before,
16{
17 if (before && before->getType() != ltPERMISSIONED_DOMAIN)
18 return;
19 if (after && after->getType() != ltPERMISSIONED_DOMAIN)
20 return;
21
22 auto check = [isDel](std::vector<SleStatus>& sleStatus, std::shared_ptr<SLE const> const& sle) {
23 auto const& credentials = sle->getFieldArray(sfAcceptedCredentials);
24 auto const sorted = credentials::makeSorted(credentials);
25
26 SleStatus ss{credentials.size(), false, !sorted.empty(), isDel};
27
28 // If array have duplicates then all the other checks are invalid
29 if (ss.isUnique_)
30 {
31 unsigned i = 0;
32 for (auto const& cred : sorted)
33 {
34 auto const& credTx = credentials[i++];
35 ss.isSorted_ =
36 (cred.first == credTx[sfIssuer]) && (cred.second == credTx[sfCredentialType]);
37 if (!ss.isSorted_)
38 break;
39 }
40 }
41 sleStatus.emplace_back(ss);
42 };
43
44 if (after)
45 check(sleStatus_, after);
46}
47
48bool
50 STTx const& tx,
51 TER const result,
52 XRPAmount const,
53 ReadView const& view,
54 beast::Journal const& j)
55{
56 auto check = [](SleStatus const& sleStatus, beast::Journal const& j) {
57 if (!sleStatus.credentialsSize_)
58 {
59 JLOG(j.fatal()) << "Invariant failed: permissioned domain with "
60 "no rules.";
61 return false;
62 }
63
65 {
66 JLOG(j.fatal()) << "Invariant failed: permissioned domain bad "
67 "credentials size "
68 << sleStatus.credentialsSize_;
69 return false;
70 }
71
72 if (!sleStatus.isUnique_)
73 {
74 JLOG(j.fatal()) << "Invariant failed: permissioned domain credentials "
75 "aren't unique";
76 return false;
77 }
78
79 if (!sleStatus.isSorted_)
80 {
81 JLOG(j.fatal()) << "Invariant failed: permissioned domain credentials "
82 "aren't sorted";
83 return false;
84 }
85
86 return true;
87 };
88
89 if (view.rules().enabled(fixPermissionedDomainInvariant))
90 {
91 // No permissioned domains should be affected if the transaction failed
92 if (!isTesSuccess(result))
93 {
94 // If nothing changed, all is good. If there were changes, that's bad.
95 return sleStatus_.empty();
96 }
97
98 if (sleStatus_.size() > 1)
99 {
100 JLOG(j.fatal()) << "Invariant failed: transaction affected more "
101 "than 1 permissioned domain entry.";
102 return false;
103 }
104
105 switch (tx.getTxnType())
106 {
107 case ttPERMISSIONED_DOMAIN_SET: {
108 if (sleStatus_.empty())
109 {
110 JLOG(j.fatal()) << "Invariant failed: no domain objects affected by "
111 "PermissionedDomainSet";
112 return false;
113 }
114
115 auto const& sleStatus = sleStatus_[0];
116 if (sleStatus.isDelete_)
117 {
118 JLOG(j.fatal()) << "Invariant failed: domain object "
119 "deleted by PermissionedDomainSet";
120 return false;
121 }
122 return check(sleStatus, j);
123 }
124 case ttPERMISSIONED_DOMAIN_DELETE: {
125 if (sleStatus_.empty())
126 {
127 JLOG(j.fatal()) << "Invariant failed: no domain objects affected by "
128 "PermissionedDomainDelete";
129 return false;
130 }
131
132 if (!sleStatus_[0].isDelete_)
133 {
134 JLOG(j.fatal()) << "Invariant failed: domain object "
135 "modified, but not deleted by "
136 "PermissionedDomainDelete";
137 return false;
138 }
139 return true;
140 }
141 default: {
142 if (!sleStatus_.empty())
143 {
144 JLOG(j.fatal()) << "Invariant failed: " << sleStatus_.size()
145 << " domain object(s) affected by an "
146 "unauthorized transaction. "
147 << tx.getTxnType();
148 return false;
149 }
150 return true;
151 }
152 }
153 }
154 else
155 {
156 if (tx.getTxnType() != ttPERMISSIONED_DOMAIN_SET || !isTesSuccess(result) ||
157 sleStatus_.empty())
158 return true;
159 return check(sleStatus_[0], j);
160 }
161}
162
163} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:40
Stream fatal() const
Definition Journal.h:325
A view into a ledger.
Definition ReadView.h:31
virtual Rules const & rules() const =0
Returns the tx processing rules.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:120
TxType getTxnType() const
Definition STTx.h:188
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
T emplace_back(T... args)
std::set< std::pair< AccountID, Slice > > makeSorted(STArray const &credentials)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:523
std::size_t constexpr maxPermissionedDomainCredentialsArraySize
The maximum number of credentials can be passed in array for permissioned domain.
Definition Protocol.h:228
bool isTesSuccess(TER x) noexcept
Definition TER.h:651