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  auto const& other = dynamic_cast<sles_iter_impl const&>(impl);
65  assert(end1_ == other.end1_ && end0_ == other.end0_);
66  return iter1_ == other.iter1_ && iter0_ == other.iter0_;
67  }
68 
69  void
70  increment() override
71  {
72  assert(sle1_ || sle0_);
73 
74  if (sle1_ && !sle0_)
75  {
76  inc1();
77  return;
78  }
79 
80  if (sle0_ && !sle1_)
81  {
82  inc0();
83  return;
84  }
85 
86  if (sle1_->key() == sle0_->key())
87  {
88  inc1();
89  inc0();
90  }
91  else if (sle1_->key() < sle0_->key())
92  {
93  inc1();
94  }
95  else
96  {
97  inc0();
98  }
99  skip();
100  }
101 
102  value_type
103  dereference() const override
104  {
105  if (!sle1_)
106  return sle0_;
107  else if (!sle0_)
108  return sle1_;
109  if (sle1_->key() <= sle0_->key())
110  return sle1_;
111  return sle0_;
112  }
113 
114 private:
115  void
117  {
118  ++iter0_;
119  if (iter0_ == end0_)
120  sle0_ = nullptr;
121  else
122  sle0_ = *iter0_;
123  }
124 
125  void
127  {
128  ++iter1_;
129  if (iter1_ == end1_)
130  sle1_ = nullptr;
131  else
132  sle1_ = iter1_->second.sle;
133  }
134 
135  void
137  {
138  while (iter1_ != end1_ && iter1_->second.action == Action::erase &&
139  sle0_->key() == sle1_->key())
140  {
141  inc1();
142  inc0();
143  if (!sle0_)
144  return;
145  }
146  }
147 };
148 
149 //------------------------------------------------------------------------------
150 
151 // Base invariants are checked by the base during apply()
152 
153 void
155 {
157  for (auto const& elem : items_)
158  {
159  auto const& item = elem.second;
160  switch (item.action)
161  {
162  case Action::erase:
163  to.rawErase(item.sle);
164  break;
165  case Action::insert:
166  to.rawInsert(item.sle);
167  break;
168  case Action::replace:
169  to.rawReplace(item.sle);
170  break;
171  }
172  }
173 }
174 
175 bool
176 RawStateTable::exists(ReadView const& base, Keylet const& k) const
177 {
178  assert(k.key.isNonZero());
179  auto const iter = items_.find(k.key);
180  if (iter == items_.end())
181  return base.exists(k);
182  auto const& item = iter->second;
183  if (item.action == Action::erase)
184  return false;
185  if (!k.check(*item.sle))
186  return false;
187  return true;
188 }
189 
190 /* This works by first calculating succ() on the parent,
191  then calculating succ() our internal list, and taking
192  the lower of the two.
193 */
194 auto
196  ReadView const& base,
197  key_type const& key,
198  boost::optional<key_type> const& last) const -> boost::optional<key_type>
199 {
200  boost::optional<key_type> next = key;
201  items_t::const_iterator iter;
202  // Find base successor that is
203  // not also deleted in our list
204  do
205  {
206  next = base.succ(*next, last);
207  if (!next)
208  break;
209  iter = items_.find(*next);
210  } while (iter != items_.end() && iter->second.action == Action::erase);
211  // Find non-deleted successor in our list
212  for (iter = items_.upper_bound(key); iter != items_.end(); ++iter)
213  {
214  if (iter->second.action != Action::erase)
215  {
216  // Found both, return the lower key
217  if (!next || next > iter->first)
218  next = iter->first;
219  break;
220  }
221  }
222  // Nothing in our list, return
223  // what we got from the parent.
224  if (last && next >= last)
225  return boost::none;
226  return next;
227 }
228 
229 void
231 {
232  // The base invariant is checked during apply
233  auto const result = items_.emplace(
234  std::piecewise_construct,
235  std::forward_as_tuple(sle->key()),
237  if (result.second)
238  return;
239  auto& item = result.first->second;
240  switch (item.action)
241  {
242  case Action::erase:
243  LogicError("RawStateTable::erase: already erased");
244  break;
245  case Action::insert:
246  items_.erase(result.first);
247  break;
248  case Action::replace:
249  item.action = Action::erase;
250  item.sle = sle;
251  break;
252  }
253 }
254 
255 void
257 {
258  auto const result = items_.emplace(
259  std::piecewise_construct,
260  std::forward_as_tuple(sle->key()),
262  if (result.second)
263  return;
264  auto& item = result.first->second;
265  switch (item.action)
266  {
267  case Action::erase:
268  item.action = Action::replace;
269  item.sle = sle;
270  break;
271  case Action::insert:
272  LogicError("RawStateTable::insert: already inserted");
273  break;
274  case Action::replace:
275  LogicError("RawStateTable::insert: already exists");
276  break;
277  }
278 }
279 
280 void
282 {
283  auto const result = items_.emplace(
284  std::piecewise_construct,
285  std::forward_as_tuple(sle->key()),
287  if (result.second)
288  return;
289  auto& item = result.first->second;
290  switch (item.action)
291  {
292  case Action::erase:
293  LogicError("RawStateTable::replace: was erased");
294  break;
295  case Action::insert:
296  case Action::replace:
297  item.sle = sle;
298  break;
299  }
300 }
301 
303 RawStateTable::read(ReadView const& base, Keylet const& k) const
304 {
305  auto const iter = items_.find(k.key);
306  if (iter == items_.end())
307  return base.read(k);
308  auto const& item = iter->second;
309  if (item.action == Action::erase)
310  return nullptr;
311  // Convert to SLE const
312  std::shared_ptr<SLE const> sle = item.sle;
313  if (!k.check(*sle))
314  return nullptr;
315  return sle;
316 }
317 
318 void
320 {
321  dropsDestroyed_ += fee;
322 }
323 
326 {
327  return std::make_unique<sles_iter_impl>(
328  items_.begin(), items_.end(), base.sles.begin(), base.sles.end());
329 }
330 
333 {
334  return std::make_unique<sles_iter_impl>(
335  items_.end(), items_.end(), base.sles.end(), base.sles.end());
336 }
337 
339 RawStateTable::slesUpperBound(ReadView const& base, uint256 const& key) const
340 {
341  return std::make_unique<sles_iter_impl>(
342  items_.upper_bound(key),
343  items_.end(),
344  base.sles.upper_bound(key),
345  base.sles.end());
346 }
347 
348 } // namespace detail
349 } // 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:444
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:303
ripple::detail::RawStateTable::sles_iter_impl::inc0
void inc0()
Definition: RawStateTable.cpp:116
ripple::ReadView::sles_type::upper_bound
iterator upper_bound(key_type const &key) const
Definition: ReadView.cpp:146
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:132
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:41
ripple::base_uint< 256 >
ripple::RawView
Interface for ledger entry changes.
Definition: RawView.h:37
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:103
ripple::detail::RawStateTable::slesUpperBound
std::unique_ptr< ReadView::sles_type::iter_base > slesUpperBound(ReadView const &base, uint256 const &key) const
Definition: RawStateTable.cpp:339
ripple::RawView::rawInsert
virtual void rawInsert(std::shared_ptr< SLE > const &sle)=0
Unconditionally insert a state item.
ripple::ReadView::sles_type::end
iterator const & end() const
Definition: ReadView.cpp:138
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:387
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:325
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:230
ripple::detail::RawStateTable::exists
bool exists(ReadView const &base, Keylet const &k) const
Definition: RawStateTable.cpp:176
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::detail::RawStateTable::succ
boost::optional< key_type > succ(ReadView const &base, key_type const &key, boost::optional< key_type > const &last) const
Definition: RawStateTable.cpp:195
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:192
ripple::detail::RawStateTable::sles_iter_impl::increment
void increment() override
Definition: RawStateTable.cpp:70
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:154
ripple::detail::RawStateTable::items_
items_t items_
Definition: RawStateTable.h:134
ripple::detail::RawStateTable::destroyXRP
void destroyXRP(XRPAmount const &fee)
Definition: RawStateTable.cpp:319
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:136
ripple::detail::RawStateTable::insert
void insert(std::shared_ptr< SLE > const &sle)
Definition: RawStateTable.cpp:256
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
ripple::detail::RawStateTable::replace
void replace(std::shared_ptr< SLE > const &sle)
Definition: RawStateTable.cpp:281
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:126
ripple::detail::RawStateTable::slesEnd
std::unique_ptr< ReadView::sles_type::iter_base > slesEnd(ReadView const &base) const
Definition: RawStateTable.cpp:332
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