xrpld
Loading...
Searching...
No Matches
RawStateTable.cpp
1#include <xrpl/ledger/detail/RawStateTable.h>
2
3#include <xrpl/basics/base_uint.h>
4#include <xrpl/basics/contract.h>
5#include <xrpl/beast/utility/instrumentation.h>
6#include <xrpl/ledger/RawView.h>
7#include <xrpl/ledger/ReadView.h>
8#include <xrpl/protocol/Keylet.h>
9#include <xrpl/protocol/STLedgerEntry.h>
10#include <xrpl/protocol/XRPAmount.h>
11
12#include <memory>
13#include <optional>
14#include <stdexcept>
15#include <tuple>
16#include <utility>
17
18namespace xrpl::detail {
19
21{
22private:
24 ReadView::SlesType::Iterator iter0_;
25 ReadView::SlesType::Iterator end0_;
27 items_t::const_iterator iter1_;
28 items_t::const_iterator end1_;
29
30public:
31 SlesIterImpl(SlesIterImpl const&) = default;
32
34 items_t::const_iterator iter1,
35 items_t::const_iterator end1,
36 ReadView::SlesType::Iterator iter0,
37 ReadView::SlesType::Iterator end0)
38 : iter0_(std::move(iter0)), end0_(std::move(end0)), iter1_(iter1), end1_(end1)
39 {
40 if (iter0_ != end0_)
41 sle0_ = *iter0_;
42 if (iter1_ != end1)
43 {
44 sle1_ = iter1_->second.sle;
45 skip();
46 }
47 }
48
50 copy() const override
51 {
53 }
54
55 bool
56 equal(base_type const& impl) const override
57 {
58 if (auto const p = dynamic_cast<SlesIterImpl const*>(&impl))
59 {
60 XRPL_ASSERT(
61 end1_ == p->end1_ && end0_ == p->end0_,
62 "xrpl::detail::RawStateTable::equal : matching end "
63 "iterators");
64 return iter1_ == p->iter1_ && iter0_ == p->iter0_;
65 }
66
67 return false;
68 }
69
70 void
71 increment() override
72 {
73 XRPL_ASSERT(
74 sle1_ || sle0_,
75 "xrpl::detail::RawStateTable::increment : either SLE is "
76 "non-null");
77
78 if (sle1_ && !sle0_)
79 {
80 inc1();
81 return;
82 }
83
84 if (sle0_ && !sle1_)
85 {
86 inc0();
87 return;
88 }
89
90 if (sle1_->key() == sle0_->key())
91 {
92 inc1();
93 inc0();
94 }
95 else if (sle1_->key() < sle0_->key())
96 {
97 inc1();
98 }
99 else
100 {
101 inc0();
102 }
103 skip();
104 }
105
106 value_type
107 dereference() const override
108 {
109 if (!sle1_)
110 {
111 return sle0_;
112 }
113 if (!sle0_)
114 {
115 return sle1_;
116 }
117 if (sle1_->key() <= sle0_->key())
118 return sle1_;
119 return sle0_;
120 }
121
122private:
123 void
125 {
126 ++iter0_;
127 if (iter0_ == end0_)
128 {
129 sle0_ = nullptr;
130 }
131 else
132 {
133 sle0_ = *iter0_;
134 }
135 }
136
137 void
139 {
140 ++iter1_;
141 if (iter1_ == end1_)
142 {
143 sle1_ = nullptr;
144 }
145 else
146 {
147 sle1_ = iter1_->second.sle;
148 }
149 }
150
151 void
153 {
154 while (iter1_ != end1_ && iter1_->second.action == Action::Erase &&
155 sle0_->key() == sle1_->key())
156 {
157 inc1();
158 inc0();
159 if (!sle0_)
160 return;
161 }
162 }
163};
164
165//------------------------------------------------------------------------------
166
167// Base invariants are checked by the base during apply()
168
169void
171{
173 for (auto const& elem : items_)
174 {
175 auto const& item = elem.second;
176 switch (item.action)
177 {
178 case Action::Erase:
179 to.rawErase(item.sle);
180 break;
181 case Action::Insert:
182 to.rawInsert(item.sle);
183 break;
184 case Action::Replace:
185 to.rawReplace(item.sle);
186 break;
187 }
188 }
189}
190
191bool
192RawStateTable::exists(ReadView const& base, Keylet const& k) const
193{
194 XRPL_ASSERT(k.key.isNonZero(), "xrpl::detail::RawStateTable::exists : nonzero key");
195 auto const iter = items_.find(k.key);
196 if (iter == items_.end())
197 return base.exists(k);
198 auto const& item = iter->second;
199 if (item.action == Action::Erase)
200 return false;
201 if (!k.check(*item.sle))
202 return false;
203 return true;
204}
205
206/* This works by first calculating succ() on the parent,
207 then calculating succ() our internal list, and taking
208 the lower of the two.
209*/
210auto
213{
214 std::optional<key_type> next = key;
215 items_t::const_iterator iter;
216 // Find base successor that is
217 // not also deleted in our list
218 do
219 {
220 next = base.succ(*next, last);
221 if (!next)
222 break;
223 iter = items_.find(*next);
224 } while (iter != items_.end() && iter->second.action == Action::Erase);
225 // Find non-deleted successor in our list
226 for (iter = items_.upper_bound(key); iter != items_.end(); ++iter)
227 {
228 if (iter->second.action != Action::Erase)
229 {
230 // Found both, return the lower key
231 if (!next || next > iter->first)
232 next = iter->first;
233 break;
234 }
235 }
236 // Nothing in our list, return
237 // what we got from the parent.
238 if (last && next >= last)
239 return std::nullopt;
240 return next;
241}
242
243void
245{
246 // The base invariant is checked during apply
247 auto const result = items_.emplace(
249 std::forward_as_tuple(sle->key()),
251 if (result.second)
252 return;
253 auto& item = result.first->second;
254 switch (item.action)
255 {
256 case Action::Erase:
257 Throw<std::logic_error>("RawStateTable::erase: already erased");
258 break;
259 case Action::Insert:
260 items_.erase(result.first);
261 break;
262 case Action::Replace:
263 item.action = Action::Erase;
264 item.sle = sle;
265 break;
266 }
267}
268
269void
271{
272 auto const result = items_.emplace(
274 std::forward_as_tuple(sle->key()),
276 if (result.second)
277 return;
278 auto& item = result.first->second;
279 switch (item.action)
280 {
281 case Action::Erase:
282 item.action = Action::Replace;
283 item.sle = sle;
284 break;
285 case Action::Insert:
286 Throw<std::logic_error>("RawStateTable::insert: already inserted");
287 break;
288 case Action::Replace:
289 Throw<std::logic_error>("RawStateTable::insert: already exists");
290 break;
291 }
292}
293
294void
296{
297 auto const result = items_.emplace(
299 std::forward_as_tuple(sle->key()),
301 if (result.second)
302 return;
303 auto& item = result.first->second;
304 switch (item.action)
305 {
306 case Action::Erase:
307 Throw<std::logic_error>("RawStateTable::replace: was erased");
308 break;
309 case Action::Insert:
310 case Action::Replace:
311 item.sle = sle;
312 break;
313 }
314}
315
317RawStateTable::read(ReadView const& base, Keylet const& k) const
318{
319 auto const iter = items_.find(k.key);
320 if (iter == items_.end())
321 return base.read(k);
322 auto const& item = iter->second;
323 if (item.action == Action::Erase)
324 return nullptr;
325 // Convert to SLE const
326 SLE::const_pointer sle = item.sle;
327 if (!k.check(*sle))
328 return nullptr;
329 return sle;
330}
331
332void
334{
335 dropsDestroyed_ += fee;
336}
337
340{
342 items_.begin(), items_.end(), base.sles.begin(), base.sles.end());
343}
344
347{
349 items_.end(), items_.end(), base.sles.end(), base.sles.end());
350}
351
353RawStateTable::slesUpperBound(ReadView const& base, uint256 const& key) const
354{
356 items_.upper_bound(key), items_.end(), base.sles.upperBound(key), base.sles.end());
357}
358
359} // namespace xrpl::detail
bool isNonZero() const
Definition base_uint.h:549
Interface for ledger entry changes.
Definition RawView.h:14
virtual void rawInsert(SLE::ref sle)=0
Unconditionally insert a state item.
virtual void rawReplace(SLE::ref sle)=0
Unconditionally replace a state item.
virtual void rawErase(SLE::ref sle)=0
Delete an existing state item.
virtual void rawDestroyXRP(XRPAmount const &fee)=0
Destroy XRP.
A view into a ledger.
Definition ReadView.h:31
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
SlesType sles
Iterable range of ledger state items.
Definition ReadView.h:239
std::shared_ptr< STLedgerEntry > const & ref
std::shared_ptr< STLedgerEntry const > const_pointer
SlesIterImpl(SlesIterImpl const &)=default
SlesIterImpl(items_t::const_iterator iter1, items_t::const_iterator end1, ReadView::SlesType::Iterator iter0, ReadView::SlesType::Iterator end0)
ReadView::SlesType::Iterator iter0_
value_type dereference() const override
bool equal(base_type const &impl) const override
std::unique_ptr< base_type > copy() const override
std::optional< key_type > succ(ReadView const &base, key_type const &key, std::optional< key_type > const &last) const
bool exists(ReadView const &base, Keylet const &k) const
SLE::const_pointer read(ReadView const &base, Keylet const &k) const
std::unique_ptr< ReadView::SlesType::iter_base > slesEnd(ReadView const &base) const
void apply(RawView &to) const
std::unique_ptr< ReadView::SlesType::iter_base > slesBegin(ReadView const &base) const
ReadView::key_type key_type
std::unique_ptr< ReadView::SlesType::iter_base > slesUpperBound(ReadView const &base, uint256 const &key) const
void destroyXRP(XRPAmount const &fee)
ReadViewFwdIter< SLE::const_pointer > iter_base
T forward_as_tuple(T... args)
T make_unique(T... args)
STL namespace.
BaseUInt< 256 > uint256
Definition base_uint.h:562
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:49
T piecewise_construct
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:19
uint256 key
Definition Keylet.h:20
bool check(STLedgerEntry const &) const
Returns true if the SLE matches the type.
Definition Keylet.cpp:10
Iterator begin() const
Definition ReadView.cpp:21
Iterator upperBound(key_type const &key) const
Definition ReadView.cpp:33
Iterator end() const
Definition ReadView.cpp:27