rippled
RawStateTable.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 <ripple/basics/contract.h>
21 #include <ripple/ledger/detail/RawStateTable.h>
22 
23 namespace ripple {
24 namespace detail {
25 
27 {
28 private:
30  ReadView::sles_type::iterator iter0_;
31  ReadView::sles_type::iterator end0_;
33  items_t::const_iterator iter1_;
34  items_t::const_iterator end1_;
35 
36 public:
37  sles_iter_impl(sles_iter_impl const&) = default;
38 
40  items_t::const_iterator iter1,
41  items_t::const_iterator end1,
42  ReadView::sles_type::iterator iter0,
43  ReadView::sles_type::iterator end0)
44  : iter0_(iter0), end0_(end0), iter1_(iter1), end1_(end1)
45  {
46  if (iter0_ != end0_)
47  sle0_ = *iter0_;
48  if (iter1_ != end1)
49  {
50  sle1_ = iter1_->second.sle;
51  skip();
52  }
53  }
54 
56  copy() const override
57  {
58  return std::make_unique<sles_iter_impl>(*this);
59  }
60 
61  bool
62  equal(base_type const& impl) const override
63  {
64  if (auto const p = dynamic_cast<sles_iter_impl const*>(&impl))
65  {
66  assert(end1_ == p->end1_ && end0_ == p->end0_);
67  return iter1_ == p->iter1_ && iter0_ == p->iter0_;
68  }
69 
70  return false;
71  }
72 
73  void
74  increment() override
75  {
76  assert(sle1_ || sle0_);
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  return sle0_;
111  else if (!sle0_)
112  return sle1_;
113  if (sle1_->key() <= sle0_->key())
114  return sle1_;
115  return sle0_;
116  }
117 
118 private:
119  void
121  {
122  ++iter0_;
123  if (iter0_ == end0_)
124  sle0_ = nullptr;
125  else
126  sle0_ = *iter0_;
127  }
128 
129  void
131  {
132  ++iter1_;
133  if (iter1_ == end1_)
134  sle1_ = nullptr;
135  else
136  sle1_ = iter1_->second.sle;
137  }
138 
139  void
141  {
142  while (iter1_ != end1_ && iter1_->second.action == Action::erase &&
143  sle0_->key() == sle1_->key())
144  {
145  inc1();
146  inc0();
147  if (!sle0_)
148  return;
149  }
150  }
151 };
152 
153 //------------------------------------------------------------------------------
154 
155 // Base invariants are checked by the base during apply()
156 
157 void
159 {
161  for (auto const& elem : items_)
162  {
163  auto const& item = elem.second;
164  switch (item.action)
165  {
166  case Action::erase:
167  to.rawErase(item.sle);
168  break;
169  case Action::insert:
170  to.rawInsert(item.sle);
171  break;
172  case Action::replace:
173  to.rawReplace(item.sle);
174  break;
175  }
176  }
177 }
178 
179 bool
180 RawStateTable::exists(ReadView const& base, Keylet const& k) const
181 {
182  assert(k.key.isNonZero());
183  auto const iter = items_.find(k.key);
184  if (iter == items_.end())
185  return base.exists(k);
186  auto const& item = iter->second;
187  if (item.action == Action::erase)
188  return false;
189  if (!k.check(*item.sle))
190  return false;
191  return true;
192 }
193 
194 /* This works by first calculating succ() on the parent,
195  then calculating succ() our internal list, and taking
196  the lower of the two.
197 */
198 auto
200  ReadView const& base,
201  key_type const& key,
203 {
204  std::optional<key_type> next = key;
205  items_t::const_iterator iter;
206  // Find base successor that is
207  // not also deleted in our list
208  do
209  {
210  next = base.succ(*next, last);
211  if (!next)
212  break;
213  iter = items_.find(*next);
214  } while (iter != items_.end() && iter->second.action == Action::erase);
215  // Find non-deleted successor in our list
216  for (iter = items_.upper_bound(key); iter != items_.end(); ++iter)
217  {
218  if (iter->second.action != Action::erase)
219  {
220  // Found both, return the lower key
221  if (!next || next > iter->first)
222  next = iter->first;
223  break;
224  }
225  }
226  // Nothing in our list, return
227  // what we got from the parent.
228  if (last && next >= last)
229  return std::nullopt;
230  return next;
231 }
232 
233 void
235 {
236  // The base invariant is checked during apply
237  auto const result = items_.emplace(
238  std::piecewise_construct,
239  std::forward_as_tuple(sle->key()),
241  if (result.second)
242  return;
243  auto& item = result.first->second;
244  switch (item.action)
245  {
246  case Action::erase:
247  LogicError("RawStateTable::erase: already erased");
248  break;
249  case Action::insert:
250  items_.erase(result.first);
251  break;
252  case Action::replace:
253  item.action = Action::erase;
254  item.sle = sle;
255  break;
256  }
257 }
258 
259 void
261 {
262  auto const result = items_.emplace(
263  std::piecewise_construct,
264  std::forward_as_tuple(sle->key()),
266  if (result.second)
267  return;
268  auto& item = result.first->second;
269  switch (item.action)
270  {
271  case Action::erase:
272  item.action = Action::replace;
273  item.sle = sle;
274  break;
275  case Action::insert:
276  LogicError("RawStateTable::insert: already inserted");
277  break;
278  case Action::replace:
279  LogicError("RawStateTable::insert: already exists");
280  break;
281  }
282 }
283 
284 void
286 {
287  auto const result = items_.emplace(
288  std::piecewise_construct,
289  std::forward_as_tuple(sle->key()),
291  if (result.second)
292  return;
293  auto& item = result.first->second;
294  switch (item.action)
295  {
296  case Action::erase:
297  LogicError("RawStateTable::replace: was erased");
298  break;
299  case Action::insert:
300  case Action::replace:
301  item.sle = sle;
302  break;
303  }
304 }
305 
307 RawStateTable::read(ReadView const& base, Keylet const& k) const
308 {
309  auto const iter = items_.find(k.key);
310  if (iter == items_.end())
311  return base.read(k);
312  auto const& item = iter->second;
313  if (item.action == Action::erase)
314  return nullptr;
315  // Convert to SLE const
316  std::shared_ptr<SLE const> sle = item.sle;
317  if (!k.check(*sle))
318  return nullptr;
319  return sle;
320 }
321 
322 void
324 {
325  dropsDestroyed_ += fee;
326 }
327 
330 {
331  return std::make_unique<sles_iter_impl>(
332  items_.begin(), items_.end(), base.sles.begin(), base.sles.end());
333 }
334 
337 {
338  return std::make_unique<sles_iter_impl>(
339  items_.end(), items_.end(), base.sles.end(), base.sles.end());
340 }
341 
343 RawStateTable::slesUpperBound(ReadView const& base, uint256 const& key) const
344 {
345  return std::make_unique<sles_iter_impl>(
346  items_.upper_bound(key),
347  items_.end(),
348  base.sles.upper_bound(key),
349  base.sles.end());
350 }
351 
352 } // namespace detail
353 } // namespace ripple
ripple::detail::RawStateTable::dropsDestroyed_
XRPAmount dropsDestroyed_
Definition: RawStateTable.h:136
ripple::Keylet
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:38
ripple::detail::RawStateTable::sles_iter_impl::sles_iter_impl
sles_iter_impl(sles_iter_impl const &)=default
std::shared_ptr
STL class.
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:537
ripple::detail::RawStateTable::succ
std::optional< key_type > succ(ReadView const &base, key_type const &key, std::optional< key_type > const &last) const
Definition: RawStateTable.cpp:199
std::map::find
T find(T... args)
ripple::detail::RawStateTable::sles_iter_impl::iter0_
ReadView::sles_type::iterator iter0_
Definition: RawStateTable.cpp:30
ripple::RawView::rawDestroyXRP
virtual void rawDestroyXRP(XRPAmount const &fee)=0
Destroy XRP.
ripple::detail::RawStateTable::Action::erase
@ erase
std::map::emplace
T emplace(T... args)
ripple::detail::RawStateTable::read
std::shared_ptr< SLE const > read(ReadView const &base, Keylet const &k) const
Definition: RawStateTable.cpp:307
ripple::detail::RawStateTable::sles_iter_impl::inc0
void inc0()
Definition: RawStateTable.cpp:120
ripple::ReadView::sles_type::upper_bound
iterator upper_bound(key_type const &key) const
Definition: ReadView.cpp:41
ripple::detail::RawStateTable::Action::replace
@ replace
ripple::RawView::rawReplace
virtual void rawReplace(std::shared_ptr< SLE > const &sle)=0
Unconditionally replace a state item.
ripple::ReadView::sles_type::begin
iterator begin() const
Definition: ReadView.cpp:29
ripple::detail::RawStateTable::sles_iter_impl::sles_iter_impl
sles_iter_impl(items_t::const_iterator iter1, items_t::const_iterator end1, ReadView::sles_type::iterator iter0, ReadView::sles_type::iterator end0)
Definition: RawStateTable.cpp:39
ripple::RawView::rawErase
virtual void rawErase(std::shared_ptr< SLE > const &sle)=0
Delete an existing state item.
ripple::Keylet::key
uint256 key
Definition: Keylet.h:40
ripple::base_uint< 256 >
ripple::RawView
Interface for ledger entry changes.
Definition: RawView.h:36
ripple::detail::RawStateTable::sles_iter_impl
Definition: RawStateTable.cpp:26
ripple::detail::RawStateTable::sles_iter_impl::dereference
value_type dereference() const override
Definition: RawStateTable.cpp:107
ripple::detail::RawStateTable::slesUpperBound
std::unique_ptr< ReadView::sles_type::iter_base > slesUpperBound(ReadView const &base, uint256 const &key) const
Definition: RawStateTable.cpp:343
ripple::RawView::rawInsert
virtual void rawInsert(std::shared_ptr< SLE > const &sle)=0
Unconditionally insert a state item.
ripple::ReadView::sles_type::end
iterator end() const
Definition: ReadView.cpp:35
ripple::ReadView::exists
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
std::map::erase
T erase(T... args)
ripple::ReadView::sles
sles_type sles
Iterable range of ledger state items.
Definition: ReadView.h:320
ripple::detail::RawStateTable::Action::insert
@ insert
ripple::detail::RawStateTable::slesBegin
std::unique_ptr< ReadView::sles_type::iter_base > slesBegin(ReadView const &base) const
Definition: RawStateTable.cpp:329
ripple::detail::RawStateTable::sles_iter_impl::equal
bool equal(base_type const &impl) const override
Definition: RawStateTable.cpp:62
std::forward_as_tuple
T forward_as_tuple(T... args)
ripple::detail::RawStateTable::erase
void erase(std::shared_ptr< SLE > const &sle)
Definition: RawStateTable.cpp:234
ripple::detail::RawStateTable::exists
bool exists(ReadView const &base, Keylet const &k) const
Definition: RawStateTable.cpp:180
std::map::upper_bound
T upper_bound(T... args)
ripple::detail::RawStateTable::sles_iter_impl::end1_
items_t::const_iterator end1_
Definition: RawStateTable.cpp:34
ripple::ReadView::read
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
ripple::detail::RawStateTable::sles_iter_impl::copy
std::unique_ptr< base_type > copy() const override
Definition: RawStateTable.cpp:56
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:125
ripple::detail::RawStateTable::sles_iter_impl::increment
void increment() override
Definition: RawStateTable.cpp:74
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::detail::RawStateTable::apply
void apply(RawView &to) const
Definition: RawStateTable.cpp:158
ripple::detail::RawStateTable::items_
items_t items_
Definition: RawStateTable.h:134
ripple::detail::RawStateTable::destroyXRP
void destroyXRP(XRPAmount const &fee)
Definition: RawStateTable.cpp:323
ripple::detail::RawStateTable::sles_iter_impl::sle0_
std::shared_ptr< SLE const > sle0_
Definition: RawStateTable.cpp:29
std::map::begin
T begin(T... args)
ripple::LogicError
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
Definition: contract.cpp:48
ripple::detail::RawStateTable::sles_iter_impl::skip
void skip()
Definition: RawStateTable.cpp:140
ripple::detail::RawStateTable::insert
void insert(std::shared_ptr< SLE > const &sle)
Definition: RawStateTable.cpp:260
ripple::detail::ReadViewFwdRange< std::shared_ptr< SLE const > >::iter_base
ReadViewFwdIter< std::shared_ptr< SLE const > > iter_base
Definition: ReadViewFwdRange.h:70
ripple::detail::RawStateTable::sles_iter_impl::iter1_
items_t::const_iterator iter1_
Definition: RawStateTable.cpp:33
std::optional
ripple::detail::RawStateTable::replace
void replace(std::shared_ptr< SLE > const &sle)
Definition: RawStateTable.cpp:285
ripple::Keylet::check
bool check(STLedgerEntry const &) const
Returns true if the SLE matches the type.
Definition: Keylet.cpp:26
ripple::detail::RawStateTable::sles_iter_impl::sle1_
std::shared_ptr< SLE const > sle1_
Definition: RawStateTable.cpp:32
std::map::end
T end(T... args)
ripple::detail::RawStateTable::sles_iter_impl::inc1
void inc1()
Definition: RawStateTable.cpp:130
ripple::detail::RawStateTable::slesEnd
std::unique_ptr< ReadView::sles_type::iter_base > slesEnd(ReadView const &base) const
Definition: RawStateTable.cpp:336
std::unique_ptr
STL class.
ripple::detail::RawStateTable::sles_iter_impl::end0_
ReadView::sles_type::iterator end0_
Definition: RawStateTable.cpp:31
ripple::XRPAmount
Definition: XRPAmount.h:46