xrpld
Loading...
Searching...
No Matches
SLEBase.h
1#pragma once
2
3#include <xrpl/basics/base_uint.h>
4#include <xrpl/basics/contract.h>
5#include <xrpl/beast/utility/Journal.h>
6#include <xrpl/beast/utility/instrumentation.h>
7#include <xrpl/ledger/ApplyView.h>
8#include <xrpl/ledger/ReadView.h>
9#include <xrpl/protocol/Keylet.h>
10#include <xrpl/protocol/LedgerFormats.h>
11#include <xrpl/protocol/STLedgerEntry.h>
12
13#include <concepts>
14#include <memory>
15#include <stdexcept>
16#include <type_traits>
17#include <utility>
18
19namespace xrpl {
20
21// Concept to distinguish read-only vs writable view types
22template <typename V>
23concept IsWritableView = std::derived_from<V, ApplyView>;
24
25namespace detail {
26
57resolveEntry(ReadView const& view, Keylet const& key)
58{
59 // Safe only for a view that is not itself a const object -- see the
60 // note above. The entry holds a const reference because it does not
61 // modify the view, not because the view is const.
62 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
63 if (auto const applyView = dynamic_cast<ApplyView*>(const_cast<ReadView*>(&view)))
64 return applyView->peek(key);
65 return view.read(key);
66}
67
68} // namespace detail
69
90template <typename ViewT, LedgerEntryType EntryType = ltANY>
92{
93public:
94 static constexpr bool kIsWritable = IsWritableView<ViewT>;
95
96 // The ledger entry type this entry is bound to, and whether that binding
97 // is meaningful (ltANY means "any type", i.e. no static check).
98 static constexpr LedgerEntryType kEntryType = EntryType;
99 static constexpr bool kIsTyped = (EntryType != ltANY);
100
101 // SLE pointer type: mutable for writable views, const for read-only
103
104 // View reference type: ApplyView& for writable, ReadView const& for
105 // read-only
107
108 // Non-virtual by design: these entries are parameterized on the view and
109 // entry type, never used polymorphically through a base pointer. A vptr
110 // would be 8 bytes of pure overhead on a type meant to be as cheap as the
111 // shared_ptr it wraps. See the static_assert below the class.
112 //
113 // The destructor is public because the ReadOnlySLE / WritableSLE aliases
114 // name this class directly and are used as value types. Since it is not
115 // virtual, never delete a derived entry through an SLEBase*.
116 ~SLEBase() = default;
117
119 requires(!kIsWritable)
120 = default;
121 SLEBase(SLEBase&&) = default;
122 SLEBase&
123 operator=(SLEBase const&) = delete;
124 SLEBase&
125 operator=(SLEBase&&) = delete;
126 SLEBase() = delete;
127
128 // --- Constructors that adopt/resolve an SLE (public so the ReadOnlySLE /
129 // WritableSLE aliases and the per-type entries can be built directly
130 // from a keylet, or -- read-only only -- from an already-fetched
131 // SLE). ---
132
140 explicit SLEBase(
142 ViewRefType view,
144 requires(!kIsWritable)
145 : view_(view), sle_(std::move(sle)), j_(j)
146 {
147 XRPL_ASSERT(
148 !kIsTyped || !sle_ || sle_->getType() == kEntryType,
149 "xrpl::SLEBase::SLEBase : adopted SLE matches bound entry type");
150 }
151
155 explicit SLEBase(
156 Keylet const& key,
157 ViewRefType view,
159 requires(!kIsWritable)
160 : view_(view), sle_(detail::resolveEntry(view, key)), j_(j)
161 {
162 XRPL_ASSERT(
163 !kIsTyped || key.type == kEntryType,
164 "xrpl::SLEBase::SLEBase : keylet matches bound entry type");
165 }
166
180 template <typename OtherViewT, LedgerEntryType OtherType>
183 (OtherType == EntryType || EntryType == ltANY))
184 : view_(other.readView()), sle_(other.rawSle()), j_(other.journal())
185 {
186 }
187
191 explicit SLEBase(
192 Keylet const& key,
193 ApplyView& view,
195 requires kIsWritable
196 : view_(view), key_(key), sle_(view_.peek(key)), j_(j)
197 {
198 XRPL_ASSERT(
199 !kIsTyped || key.type == kEntryType,
200 "xrpl::SLEBase::SLEBase : keylet matches bound entry type");
201 }
202
212 explicit SLEBase(
213 Keylet const& key,
214 ApplyViewContext const& ctx,
216 requires kIsWritable
217 : SLEBase(key, ctx.view, j)
218 {
219 }
220
221 // --- Common interface (always available) ---
222
226 [[nodiscard]] bool
227 exists() const
228 {
229 return sle_ != nullptr;
230 }
231
235 explicit
236 operator bool() const
237 {
238 return exists();
239 }
240
247 [[nodiscard]] SLE::const_pointer
248 rawSle() const
249 {
250 return sle_;
251 }
252
263 [[nodiscard]] LedgerEntryType
264 type() const
265 {
266 if constexpr (kIsTyped)
267 {
268 return kEntryType;
269 }
270 else
271 {
272 if (!exists())
273 Throw<std::logic_error>("xrpl::SLEBase::type : entry does not exist");
274 return sle_->getType();
275 }
276 }
277
287 [[nodiscard]] Keylet
288 keylet() const
289 {
290 if constexpr (kIsWritable)
291 {
292 return key_;
293 }
294 else
295 {
296 if (!exists())
297 Throw<std::logic_error>("xrpl::SLEBase::keylet : entry does not exist");
298 // Take the type from the SLE, not from kEntryType: the adopt-SLE
299 // constructor's type check is assert-only, so a Release build can
300 // be holding an SLE whose type disagrees with the binding, and the
301 // SLE is the one telling the truth.
302 return Keylet(sle_->getType(), sle_->key());
303 }
304 }
305
312 [[nodiscard]] UInt256
313 key() const
314 {
315 return keylet().key;
316 }
317
321 [[nodiscard]] ReadView const&
322 readView() const
323 {
324 return view_;
325 }
326
332 STLedgerEntry const*
334 {
335 if (!exists())
336 Throw<std::logic_error>("xrpl::SLEBase::operator-> : entry does not exist");
337 return sle_.get();
338 }
339
340 STLedgerEntry const&
341 operator*() const
342 {
343 if (!exists())
344 Throw<std::logic_error>("xrpl::SLEBase::operator* : entry does not exist");
345 return *sle_;
346 }
347
348 // --- Writable interface (compile-time gated) ---
349 //
350 // Everything that hands out mutable access (or mutates) is non-const, so
351 // that a `FooEntryW const&` is as inert as a `FooEntryR`. Use readView()
352 // when a const entry only needs to inspect the view.
353
360 [[nodiscard]] SlePtrType const&
362 requires kIsWritable
363 {
364 return sle_;
365 }
366
370 [[nodiscard]] ApplyView&
372 requires kIsWritable
373 {
374 return view_;
375 }
376
384 requires kIsWritable
385 {
386 if (!exists())
387 Throw<std::logic_error>("xrpl::SLEBase::operator-> : entry does not exist");
388 return sle_.get();
389 }
390
393 requires kIsWritable
394 {
395 if (!exists())
396 Throw<std::logic_error>("xrpl::SLEBase::operator* : entry does not exist");
397 return *sle_;
398 }
399
405 void
407 requires kIsWritable
408 {
409 if (!exists())
410 Throw<std::logic_error>("xrpl::SLEBase::insert : entry does not exist");
411 view_.insert(sle_);
412 }
413
427 void
429 requires kIsWritable
430 {
431 if (!exists())
432 Throw<std::logic_error>("xrpl::SLEBase::erase : entry does not exist");
433 view_.erase(sle_);
434 sle_ = nullptr;
435 }
436
440 void
442 requires kIsWritable
443 {
444 if (!exists())
445 Throw<std::logic_error>("xrpl::SLEBase::update : entry does not exist");
446 view_.update(sle_);
447 }
448
453 void
455 requires kIsWritable
456 {
457 if (exists())
458 Throw<std::logic_error>("xrpl::SLEBase::newSLE : entry already exists");
460 }
461
462 [[nodiscard]] beast::Journal
463 journal() const
464 {
465 return j_;
466 }
467
468protected:
470
471 // Keylet is only meaningful for writable views, which need it to build an
472 // SLE that does not exist yet; read-only entries derive it from the SLE.
473 struct Empty
474 {
475 };
476
477 // No default member initializer: Keylet is not default-constructible, so
478 // every writable constructor must initialize key_ explicitly.
479 [[no_unique_address]]
481
484};
485
498
499static_assert(
501 "SLEBase must stay a thin value type; it must not acquire a vtable");
502
503} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:44
static Sink & getNullSink()
Returns a Sink which does nothing.
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:141
A view into a ledger.
Definition ReadView.h:41
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
View-parameterized base class for all ledger entries.
Definition SLEBase.h:92
void erase()
Erases the entry from the view.
Definition SLEBase.h:428
SLEBase()=delete
SLEBase(SLEBase< OtherViewT, OtherType > const &other)
Converting constructor: writable → read-only.
Definition SLEBase.h:181
bool exists() const
Returns true if the ledger entry exists.
Definition SLEBase.h:227
beast::Journal journal() const
Definition SLEBase.h:463
SLEBase & operator=(SLEBase &&)=delete
STLedgerEntry const * operator->() const
Const dereference operators (always available).
Definition SLEBase.h:333
void insert()
Inserts the entry into the view.
Definition SLEBase.h:406
SLEBase(SLE::const_pointer sle, ViewRefType view, beast::Journal j=beast::Journal{beast::Journal::getNullSink()})
Constructor for read-only context (adopt an already-fetched SLE).
Definition SLEBase.h:140
Keylet keylet() const
Returns the keylet identifying this entry.
Definition SLEBase.h:288
~SLEBase()=default
std::conditional_t< kIsWritable, SLE::pointer, SLE::const_pointer > SlePtrType
Definition SLEBase.h:102
LedgerEntryType type() const
Returns the ledger entry type of this entry.
Definition SLEBase.h:264
SlePtrType const & mutableRawSle()
Returns the underlying SLE for write access.
Definition SLEBase.h:361
std::conditional_t< kIsWritable, Keylet, Empty > key_
Definition SLEBase.h:480
void newSLE()
Definition SLEBase.h:454
beast::Journal j_
Definition SLEBase.h:483
void update()
Definition SLEBase.h:441
ApplyView & applyView()
Returns the apply view for write operations.
Definition SLEBase.h:371
STLedgerEntry * operator->()
Mutable dereference operators.
Definition SLEBase.h:383
ReadView const & readView() const
Definition SLEBase.h:322
static constexpr bool kIsWritable
Definition SLEBase.h:94
static constexpr LedgerEntryType kEntryType
Definition SLEBase.h:98
SLE::const_pointer rawSle() const
Definition SLEBase.h:248
SLEBase(Keylet const &key, ApplyViewContext const &ctx, beast::Journal j=beast::Journal{beast::Journal::getNullSink()})
Constructor for writable context, for call sites that hold an ApplyViewContext (peek from ctx....
Definition SLEBase.h:212
static constexpr bool kIsTyped
Definition SLEBase.h:99
std::conditional_t< kIsWritable, ApplyView &, ReadView const & > ViewRefType
Definition SLEBase.h:106
STLedgerEntry & operator*()
Definition SLEBase.h:392
SLEBase(SLEBase &&)=default
SLEBase(SLEBase const &)=default
SLEBase & operator=(SLEBase const &)=delete
ViewRefType view_
Definition SLEBase.h:469
STLedgerEntry const & operator*() const
Definition SLEBase.h:341
SLEBase(Keylet const &key, ApplyView &view, beast::Journal j=beast::Journal{beast::Journal::getNullSink()})
Constructor for writable context (peek from view by keylet).
Definition SLEBase.h:191
SlePtrType sle_
Definition SLEBase.h:482
SLEBase(Keylet const &key, ViewRefType view, beast::Journal j=beast::Journal{beast::Journal::getNullSink()})
Constructor for read-only context (read from view by keylet).
Definition SLEBase.h:155
A serialized ledger entry, commonly abbreviated "SLE".
std::shared_ptr< STLedgerEntry const > const_pointer
T is_polymorphic_v
T make_shared(T... args)
STL namespace.
SLE::const_pointer resolveEntry(ReadView const &view, Keylet const &key)
Resolves a keylet for a read-only entry.
Definition SLEBase.h:57
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
SLEBase< ApplyView > WritableSLE
Definition SLEBase.h:497
BaseUInt< 256 > UInt256
Definition base_uint.h:580
LedgerEntryType
Identifiers for on-ledger objects.
@ ltANY
A special type, matching any ledger entry type.
SLEBase< ReadView > ReadOnlySLE
Generic (any-entry-type) SLE entries.
Definition SLEBase.h:496
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:52
Bundles the mutable ledger view and the transaction being applied.
Definition ApplyView.h:451
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:20
UInt256 key
Definition Keylet.h:21